mango-explorer/docs/MarketmakingOrderChain.md

11 KiB
Raw Blame History

🥭 Mango Explorer

🏃 Marketmaking Order Chain

The Marketmaking Introduction talks a bit about marketmaking generally but here we're going to focus specifically on building orders.

A marketmaker wants to ensure the orderbook contains orders with the values it wants. It does this with two phases:

  1. Build a set of 'desired orders' - the orders it wants to see on the orderbook
  2. Reconcile those desired orders with the existing orders on the orderbook, placing and cancelling orders as appropriate

The 'order chain' deals solely with the first part - building a set of desired orders.

What Is An Order Chain?

An order chain is a sequence of Element objects, each of which, in turn, gets a chance to see and modify the desired order list before the marketmaker processes them.

The first Element is usually the one responsible for creating the orders for subsequent Elements to modify, but that's just a convention. Any Element can add desired orders.

Elements are called with a Context, the current ModelState, and the list of desired Orders. It performs its duties, and then returns the updated list of desired Orders.

When there are no more Elements in the Chain, the desired orders are passed to the MarketMaker itself for reconciliation with existing orders.

The Default Chain

Usually the head of the marketmaker chain creates some desired orders, and they may be modified by subsequent elements in the chain.

The default chain is (in order):

  • confidenceinterval
  • biasquoteonposition
  • minimumcharge
  • preventpostonlycrossingbook
  • roundtolotsize

It's possible to specify a different Chain on the command line.

Note: it's not possbile to modify the default chain on the command line. The default chain is what is used if no chain is specified. If you specify any part of a chain, what you specify will replace the use of the default chain entirely: if you want to change any part of the default chain, you must specify the entire chain you want.

Specifying A Different Chain

The default chain is equivalent to specifying:

--chain confidenceinterval --chain biasquoteonposition --chain minimumcharge --chain preventpostonlycrossingbook --chain roundtolotsize

To specify a different chain, you must specify on the command-line each chain element you want to use, in order.

For example, to specify a chain similar to the default chain but without the BiasQuoteOnPosition element, you would add the following parameters to the marketmaker command-line:

--chain confidenceinterval --chain minimumcharge --chain preventpostonlycrossingbook --chain roundtolotsize

Don't forget - if you want to change any part of the default chain, you must specify the full chain you want to use.

Chain Heads

Currently only two elements - ratios and confidenceinterval - create orders. The remaining elements modify orders that are passed to them. Since each 'pulse' starts with no desired orders, that means the first element of the chain (or 'head of the chain') must be either ratios or confidenceinterval. Subsequent elements in the chain can modify the orders.

Example Chain

Here's a completely different chain. This chain will specify orders with a spread of 0.5% and a position size of 2:

--chain ratios --ratios-spread 0.005 --chain fixedpositionsize --fixedpositionsize-value 2

The lack of a roundtolotsize element means positions won't be rounded to lot sizes when being sent to the marketmaker (so reconciling orders won't work as well as it might) but they'll be properly rounded when placed.

The lack of a preventpostonlycrossingbook element means there's no specific handling of a POST_ONLY order that would cross the orderbook. That means those orders (since they're POST_ONLY) will be implicitly cancelled - this default behaviour may be exactly what you want.

Alternatively, both those elements can be added to the end to give the following chain parameters:

--chain ratios --ratios-spread 0.005 --chain fixedpositionsize --fixedpositionsize-value 2 --chain preventpostonlycrossingbook --chain roundtolotsize

Element Reference

Here's a list of all available Elements and the additional configuration parameters they can take.

Note: In general, any parameters for a specific element have the name --elementname-parametername to help distinguish them and the element they operate upon.

AfterAccumulatedDepthElement

Specified using: --chain afteraccumulateddepth

Tries to place an order on the orderbook with sufficient quantity on orders between it and the mid-price.

Basically, if an order is for quantity X then this element will start at the top of the book and move down orders until the accumulated quantity from orders is greater than the quantity of the desired order.

E.g. if an order is for 1 BTC, the order will be priced so that there is at least 1 BTC's worth of orders between its price and the mid-price.

BiasQuoteOnPositionElement

Specified using: --chain biasquoteonposition

Accepts parameter: --biasquoteonposition-bias

This can shift the price of orders based on how much inventory is held. Too much inventory: bias prices down (so it tends to buy less and sell more). Too little inventory: bias prices up (so it tends to buy more and sell less).

The default bias is 0, meaning no changes will be made to orders. You can change this using the -biasquoteonposition-bias parameter. This should be a small, positive number - for example 0.00003 can shift the order price significantly.

ConfidenceIntervalElement

Specified using: --chain confidenceinterval

Accepts parameter: --confidenceinterval-level

Accepts parameter: --confidenceinterval-position-size-ratio

The ConfidenceIntervalElement uses the confidence interval in the oracle price to determine the spread. How aggressively this is used can be tuned by the --confidenceinterval-level parameter.

This 'level' is weighting to apply to the confidence interval from the oracle: e.g. 1 - use the oracle confidence interval as the spread, 2 (risk averse, default) - multiply the oracle confidence interval by 2 to get the spread, 0.5 (aggressive) halve the oracle confidence interval to get the spread.

The confidence interval is Pyths expectation of how far from the current mid-price the next trade will occur. If you use a confidence weighting parameter of 2, this confidence interval is doubled and then added to the mid-price to get the sell price for the order and subtracted from the mid-price to get the buy price for the order.

  • Using a confidence weighting of 1 just uses the confidence interval to create the spread
  • Using a confidence weighting of 2 (the default) doubles the width of the spread
  • Using a confidence weighting of 0.5 halves the width of the spread (and so is more aggressive)

Important note: this can be specified multiple times on the command line, so you can have orders placed at, say, 1x, 2x and 5x the confidence interval, placing/checking 6 orders in total each pulse (3 BUYs, 3 SELLs).

FixedPositionSizeElement

Specified using: --chain fixedpositionsize

Accepts parameter: --fixedpositionsize-value

The FixedPositionSizeElement overrides the position size of all orders it sees, setting them to the fixed value (in the base currency) specified in the parameter.

For example, adding:

--chain fixedpositionsize --fixedpositionsize-value 3

to a chain on ETH/USDC will force all BUY and SELL orders to have a position size of 3 ETH.

FixedSpreadElement

Specified using: --chain fixedspread

Accepts parameter: --fixedspread-value

The FixedSpreadElement overrides the spread of all orders it sees, setting them to the fixed value (in the quote currency) specified in the parameter.

For example, adding:

--chain fixedspread --fixedspread-value 0.5

to a chain on ETH/USDC will force the spread on BUY and SELL orders to be 0.5 USDC, meaning the BUY price will be the mid-price minus half the --fixedspread-value, and the SELL price will be the mid-price plus half the --fixedspread-value.

MinimumChargeElement

Specified using: --chain minimumcharge

Accepts parameter: --minimumcharge-ratio

Accepts parameter: --minimumcharge-from-bid-ask

This ensures that theres a minimum value of spread to be paid by the taker.

Its possible that the configuration may lead to too small a spread to be profitable. You can use the --minimumcharge-ratio parameter to enforce a minimum spread. The default of 0.0005 is 0.05%.

The default is to perform calculations based on the mid price. The --minimumcharge-from-bid-ask parameter specifies calculations are to be performed using the bid price (for BUYs) or ask price (for SELLs), not the mid price.

PreventPostOnlyCrossingBookElement

Specified using --chain preventpostonlycrossingbook

This ensures that POST_ONLY orders that would corss the orderbook (and so be cancelled instead of put on the book) are placed just inside the spread by 1 tick.

QuoteSingleSideElement

Specified using: --chain quotesingleside

Accepts parameter: --quotesingleside-side

Sometimes you may only want your marketmaker to place SELL orders. Or only place BUY orders. The QuoteSingleSideElement allows you to specify a single side, and will filter out all desired orders that are not for that side.

For example, you can set the 'order chain' to have a RatiosElement asking for orders with spreads at 0.5%, 0.7%, and 0.9% (which would produce 6 orders - 3 BUYs and 3 SELLs), and then use a QuoteSingleSideElement with a side of SELL which would remove the 3 BUYs from the desired orders leaving only the 3 SELLs.

RatiosElement

Specified using: --chain ratios

Accepts parameter: --ratios-spread

Accepts parameter: --ratios-position-size

Accepts parameter: --ratios-from-bid-ask

The RatiosElement builds orders using the specified ratio of available collateral for the position size and the specified ratio of the price for the spread. The position size is specified using the --ratios-position-size parameter, and the spread is specified using the --ratios-spread parameter.

It is possible to 'layer' orders by specifying the --ratios-position-size and --ratios-spread parameters multiple times. Note: both parameters must be specified the same number of times - for example, it is an error to specify 3 position size ratios and only 2 spread ratios.

The default is to perform calculations based on the mid price. The --ratios-from-bid-ask parameter specifies spread calculations are to be performed using the bid price (for BUYs) or ask price (for SELLs), not the mid price.

RoundToLotSizeElement

Specified using --chain roundtolotsize

This ensures prices and quantities are properly rounded to lot sizes. This can make the order reconciliation process more reliable since exact matches can be found for rounded orders while non-rounded orders may need more tolerance.