@0x/asset-swapper
: Add exponential sampling, exposed by sampleDistributionBase
.
`@0x/asset-swapper`: Disable ethgasstation polling in tests. `@0x/asset-swapper`: Tweak default hyper parameters to be friendlier to big fills.
This commit is contained in:
committed by
Jacob Evans
parent
391f9b31f6
commit
7f56091fbd
@@ -13,6 +13,10 @@
|
||||
{
|
||||
"note": "Added `getBatchMarketBuySwapQuoteForAssetDataAsync` on `SwapQuoter`",
|
||||
"pr": 2427
|
||||
},
|
||||
{
|
||||
"note": "Add exponential sampling distribution and `sampleDistributionBase` option to `SwapQuoter`",
|
||||
"pr": 2427
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@@ -24,12 +24,14 @@ export const SELL_SOURCES = [ERC20BridgeSource.Uniswap, ERC20BridgeSource.Eth2Da
|
||||
export const BUY_SOURCES = [ERC20BridgeSource.Uniswap, ERC20BridgeSource.Eth2Dai];
|
||||
|
||||
export const DEFAULT_GET_MARKET_ORDERS_OPTS: GetMarketOrdersOpts = {
|
||||
runLimit: 4096,
|
||||
// tslint:disable-next-line: custom-no-magic-numbers
|
||||
runLimit: 2 ** 15,
|
||||
excludedSources: [],
|
||||
bridgeSlippage: 0.0005,
|
||||
dustFractionThreshold: 0.01,
|
||||
numSamples: 10,
|
||||
dustFractionThreshold: 0.0025,
|
||||
numSamples: 12,
|
||||
noConflicts: true,
|
||||
sampleDistributionBase: 1.25,
|
||||
};
|
||||
|
||||
export const constants = {
|
||||
@@ -40,5 +42,5 @@ export const constants = {
|
||||
DEFAULT_GET_MARKET_ORDERS_OPTS,
|
||||
ERC20_PROXY_ID: '0xf47261b0',
|
||||
WALLET_SIGNATURE: '0x04',
|
||||
SAMPLER_CONTRACT_GAS_LIMIT: 10e6,
|
||||
SAMPLER_CONTRACT_GAS_LIMIT: 16e6,
|
||||
};
|
||||
|
@@ -63,7 +63,7 @@ export class MarketOperationUtils {
|
||||
};
|
||||
const [fillableAmounts, dexQuotes] = await this._dexSampler.getFillableAmountsAndSampleMarketSellAsync(
|
||||
nativeOrders,
|
||||
DexOrderSampler.getSampleAmounts(takerAmount, _opts.numSamples),
|
||||
DexOrderSampler.getSampleAmounts(takerAmount, _opts.numSamples, _opts.sampleDistributionBase),
|
||||
difference(SELL_SOURCES, _opts.excludedSources),
|
||||
);
|
||||
const nativeOrdersWithFillableAmounts = createSignedOrdersWithFillableAmounts(
|
||||
@@ -78,7 +78,6 @@ export class MarketOperationUtils {
|
||||
_opts.dustFractionThreshold,
|
||||
);
|
||||
const clippedNativePath = clipPathToInput(prunedNativePath, takerAmount);
|
||||
|
||||
const dexPaths = createPathsFromDexQuotes(dexQuotes, _opts.noConflicts);
|
||||
const allPaths = [...dexPaths];
|
||||
const allFills = flattenDexPaths(dexPaths);
|
||||
@@ -134,7 +133,7 @@ export class MarketOperationUtils {
|
||||
|
||||
const [fillableAmounts, dexQuotes] = await this._dexSampler.getFillableAmountsAndSampleMarketBuyAsync(
|
||||
nativeOrders,
|
||||
DexOrderSampler.getSampleAmounts(makerAmount, _opts.numSamples),
|
||||
DexOrderSampler.getSampleAmounts(makerAmount, _opts.numSamples, _opts.sampleDistributionBase),
|
||||
difference(BUY_SOURCES, _opts.excludedSources),
|
||||
);
|
||||
const signedOrderWithFillableAmounts = this._createBuyOrdersPathFromSamplerResultIfExists(
|
||||
|
@@ -13,16 +13,14 @@ export class DexOrderSampler {
|
||||
/**
|
||||
* Generate sample amounts up to `maxFillAmount`.
|
||||
*/
|
||||
public static getSampleAmounts(maxFillAmount: BigNumber, numSamples: number): BigNumber[] {
|
||||
const amounts = [];
|
||||
for (let i = 0; i < numSamples; i++) {
|
||||
amounts.push(
|
||||
maxFillAmount
|
||||
.times(i + 1)
|
||||
.div(numSamples)
|
||||
.integerValue(BigNumber.ROUND_UP),
|
||||
);
|
||||
}
|
||||
public static getSampleAmounts(maxFillAmount: BigNumber, numSamples: number, expBase: number = 1): BigNumber[] {
|
||||
const distribution = [...Array<BigNumber>(numSamples)].map((v, i) => new BigNumber(expBase).pow(i));
|
||||
const stepSizes = distribution.map(d => d.div(BigNumber.sum(...distribution)));
|
||||
const amounts = stepSizes.map((s, i) => {
|
||||
return maxFillAmount
|
||||
.times(BigNumber.sum(...[0, ...stepSizes.slice(0, i + 1)]))
|
||||
.integerValue(BigNumber.ROUND_UP);
|
||||
});
|
||||
return amounts;
|
||||
}
|
||||
|
||||
|
@@ -114,4 +114,12 @@ export interface GetMarketOrdersOpts {
|
||||
* Default is 0.01 (100 basis points).
|
||||
*/
|
||||
dustFractionThreshold: number;
|
||||
/**
|
||||
* The exponential sampling distribution base.
|
||||
* A value of 1 will result in evenly spaced samples.
|
||||
* > 1 will result in more samples at lower sizes.
|
||||
* < 1 will result in more samples at higher sizes.
|
||||
* Default: 1.25.
|
||||
*/
|
||||
sampleDistributionBase: number;
|
||||
}
|
||||
|
@@ -9,9 +9,9 @@ export class ProtocolFeeUtils {
|
||||
public gasPriceEstimation: BigNumber;
|
||||
private readonly _gasPriceHeart: any;
|
||||
|
||||
constructor(gasPricePollingIntervalInMs: number) {
|
||||
constructor(gasPricePollingIntervalInMs: number, initialGasPrice: BigNumber = constants.ZERO_AMOUNT) {
|
||||
this._gasPriceHeart = heartbeats.createHeart(gasPricePollingIntervalInMs);
|
||||
this.gasPriceEstimation = constants.ZERO_AMOUNT;
|
||||
this.gasPriceEstimation = initialGasPrice;
|
||||
this._initializeHeartBeat();
|
||||
}
|
||||
|
||||
|
@@ -123,7 +123,7 @@ describe('ExchangeSwapQuoteConsumer', () => {
|
||||
};
|
||||
const privateKey = devConstants.TESTRPC_PRIVATE_KEYS[userAddresses.indexOf(makerAddress)];
|
||||
orderFactory = new OrderFactory(privateKey, defaultOrderParams);
|
||||
protocolFeeUtils = new ProtocolFeeUtils(constants.PROTOCOL_FEE_UTILS_POLLING_INTERVAL_IN_MS);
|
||||
protocolFeeUtils = new ProtocolFeeUtils(constants.PROTOCOL_FEE_UTILS_POLLING_INTERVAL_IN_MS, new BigNumber(1));
|
||||
expectMakerAndTakerBalancesForTakerAssetAsync = expectMakerAndTakerBalancesAsyncFactory(
|
||||
erc20TakerTokenContract,
|
||||
makerAddress,
|
||||
|
@@ -126,7 +126,7 @@ describe('ForwarderSwapQuoteConsumer', () => {
|
||||
};
|
||||
const privateKey = devConstants.TESTRPC_PRIVATE_KEYS[userAddresses.indexOf(makerAddress)];
|
||||
orderFactory = new OrderFactory(privateKey, defaultOrderParams);
|
||||
protocolFeeUtils = new ProtocolFeeUtils(constants.PROTOCOL_FEE_UTILS_POLLING_INTERVAL_IN_MS);
|
||||
protocolFeeUtils = new ProtocolFeeUtils(constants.PROTOCOL_FEE_UTILS_POLLING_INTERVAL_IN_MS, new BigNumber(1));
|
||||
expectMakerAndTakerBalancesAsync = expectMakerAndTakerBalancesAsyncFactory(
|
||||
erc20TokenContract,
|
||||
makerAddress,
|
||||
|
@@ -306,7 +306,7 @@ describe('MarketOperationUtils tests', () => {
|
||||
_.times(3, () => SOURCE_RATES[ERC20BridgeSource.Native][0]),
|
||||
);
|
||||
const DEFAULT_SAMPLER = createSamplerFromSellRates(SOURCE_RATES);
|
||||
const DEFAULT_OPTS = { numSamples: 3, runLimit: 0 };
|
||||
const DEFAULT_OPTS = { numSamples: 3, runLimit: 0, sampleDistributionBase: 1 };
|
||||
const defaultMarketOperationUtils = new MarketOperationUtils(
|
||||
DEFAULT_SAMPLER,
|
||||
contractAddresses,
|
||||
@@ -552,7 +552,7 @@ describe('MarketOperationUtils tests', () => {
|
||||
_.times(3, () => SOURCE_RATES[ERC20BridgeSource.Native][0]),
|
||||
);
|
||||
const DEFAULT_SAMPLER = createSamplerFromBuyRates(SOURCE_RATES);
|
||||
const DEFAULT_OPTS = { numSamples: 3, runLimit: 0 };
|
||||
const DEFAULT_OPTS = { numSamples: 3, runLimit: 0, sampleDistributionBase: 1 };
|
||||
const defaultMarketOperationUtils = new MarketOperationUtils(
|
||||
DEFAULT_SAMPLER,
|
||||
contractAddresses,
|
||||
|
@@ -119,7 +119,7 @@ describe('swapQuoteConsumerUtils', () => {
|
||||
};
|
||||
const privateKey = devConstants.TESTRPC_PRIVATE_KEYS[userAddresses.indexOf(makerAddress)];
|
||||
orderFactory = new OrderFactory(privateKey, defaultOrderParams);
|
||||
protocolFeeUtils = new ProtocolFeeUtils(constants.PROTOCOL_FEE_UTILS_POLLING_INTERVAL_IN_MS);
|
||||
protocolFeeUtils = new ProtocolFeeUtils(constants.PROTOCOL_FEE_UTILS_POLLING_INTERVAL_IN_MS, new BigNumber(1));
|
||||
forwarderOrderFactory = new OrderFactory(privateKey, defaultForwarderOrderParams);
|
||||
|
||||
swapQuoteConsumer = new SwapQuoteConsumer(provider, {
|
||||
|
Reference in New Issue
Block a user