Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

A simple constant product market making method #118

Open
0xSSoul opened this issue Jun 10, 2020 · 6 comments
Open

A simple constant product market making method #118

0xSSoul opened this issue Jun 10, 2020 · 6 comments

Comments

@0xSSoul
Copy link
Member

0xSSoul commented Jun 10, 2020

Although the collateral of this Market Protocol contract is imBTC, the market maker’s funds are all USDT.

Define some symbols as follows:

PRICE: The price of the contract denominated in USD
LONG TOKEN PRICE : The price of the long position token in USD. It should also be equal to the USD value of the IMBTC got by the long position token holder when the contract is settled. Besides, because the Market Protocol contract's price floor is set to 0, PRICE = LONG TOKEN PRICE

The market maker's goal is to place bid/ask orders around some market PRICE.

First, we calculate the INIT PRICE using some model, for example, a model based on FTX hash rate contract. How to calculate the INIT PRICE is beyond this issue.

Second, we calculate the initial X (long position reserve) and Y (collateral token reserve) in the constant product formula.

Let INIT FUND be the initial funds of the market marker, eg $20k-50k.

X = INIT FUND / ( 2 * INIT PRICE)
Y = INIT FUND / 2

Third, we apply the constant product formula: X Y= k, to get the bid/ask order price.

  1. Let Δx be the ask order size, then (X-Δx)(Y+Δy)=X Y,
    ASK PRICE = Δy/Δx = Y/(x-Δx)
    Thus the market maker should put an ask order in the order book with order size is Δx and the order price is ASK PRICE

  2. Let Δx be the bid order size, then (X+Δx)(Y-Δy)=X Y,
    BID PRICE = Δy/Δx = Y/(x+Δx)
    Thus the market maker should put a bid order in the order book with order size is Δx and order price is BID PRICE

Third, update the X and Y:

  1. When the ask order gets filled, update X' = X - Δx,Y'=Y+Δy
  2. When the bid order gets filled, update X' = X +Δx,Y'=Y-Δy

Whenever the market maker has both long position tokens and short position tokens, he should redeem the tokens by Market Protocol.

Hedge

When the market maker is the seller, the buyer pays USDT to the market maker and the market maker uses IMBTC to mint Long and Short token. Thus, the market maker needs to convert some USDT to imBTC before minting and the imBTC locked in the Market Protocol is a risk exposure. We could hedge the imBTC risk exposure in a Perpetual or Futures market if needed.

Optimization

  1. We could artificially enlarge the initial X and initial Y to reduce the slippage. The disadvantage is that the market making depth will become limited. Thus, Let X = p X and Y = p Y. p is a parameter. For example, let p = 10.

  2. We could add an additional fixed discount/premium rate to the bid/ask order to increase the make maker's profit and reduce risk:
    ASK PRICE = Δy/Δx = Y/(x-Δx) * (1 + rate)
    BID PRICE = Δy/Δx = Y/(x+Δx) * (1 - rate)

Roll to new contract

We can continue to use the X and Y values ​​of the old contract in the new contract. This is because the value of the contract has not changed much in two consecutive days.
We can also use the Y/X of the previous day to get the INIT PRICE of the new day. And recalculate the initial X and Y based on the remaining available funds of market maker.

@longyunlyd
Copy link

As the collateral of this Market Protocol contract is in imBTC, let‘s assume that the market maker’s funding pool is also in imBTC. If the initial capital of the market maker is in US dollars, conversion and hedging can be done so that the problem is equivalently reduced to the same market-making problem in imBTC.

Define some symbols as follows:

PRICE: The price of the contract denominated in imBTC
LONG TOKEN PRICE = PRICE - Floor = PRICE - 0 = PRICE : The price of the long position token
SHORT TOKEN PRICE = Cap - PRICE = 1.25Index - PRICE: The price of the short position token

The above definition shows that buyers holding long tokens can receive imBTC at the index price when the contract is settled. So, if the buyer had purchased the tokens at some price lower than the settlement index price, his profit would be: Settlement Index - PRICE.

The market maker's goal is to place bid/ask orders around some "market" PRICE, thus providing liquidity while minimizing its risk and exposure to the underlying asset, i.e. the index.
In order to do so, we borrow the idea and formula from uniswap in our pricing as follows

  1. Calculate the INIT PRICE using some model, for example, a model based on FTX hash rate contract. How to calculate the INIT PRICE is beyond this iss

  2. Calculate the initial X (long position reserve) and Y (collateral token reserve) in the constant product formula.

Let INIT FUND be the initial funds of the market marker, e.g 2-5imBTC( about $20k-50k).

X = INIT FUND / ( 2 * LONG TOKEN PRICE) = INIT FUND / ( 2 * INIT PRICE)
Y = INIT FUND / 2

  1. we apply the constant product formula: X Y= k, to get the bid/ask order price.

Let Δx be the ask order size, then (X-Δx)(Y+Δx)=X Y,
ASK PRICE = Δy/Δx = Y/(x-Δx)
Thus the market maker should put an ask order in the order book with order size is Δx and the order price is ASK PRICE

Let Δx be the bid order size, then (X+Δx)(Y-Δx)=X Y,
BID PRICE = Δy/Δx = Y/(x+Δx)
Thus the market maker should put a bid order in the order book with order size is Δx and order price is BID PRICE

  1. update X and Y:

When the ask order gets filled, update X' = X - Δx,Y'=Y+Δy
When the bid order gets filled, update X' = X +Δx,Y'=Y-Δy
Whenever the market maker has both long position tokens and short position tokens, he should redeem the tokens by Market Protocol.

Optimization

We could artificially enlarge the initial X and initial Y to reduce the slippage. The disadvantage is that the market making depth will become limited. Thus, Let X = p X and Y = p Y. p is a parameter. For example, let p = 10.

We could add an additional fixed discount/premium rate to the bid/ask order to increase the make maker's profit and reduce risk:
ASK PRICE = Δy/Δx = Y/(x-Δx) * (1 + rate)
BID PRICE = Δy/Δx = Y/(x+Δx) * (1 - rate)

Roll to new contract

We can continue to use the X and Y values ​​of the old contract in the new contract. This is because the value of the contract has not changed much in two consecutive days.
We can also use the Y/X of the previous day to get the INIT PRICE of the new day. And recalculate the initial X and Y based on the remaining available funds of market maker.

@andr11111
Copy link
Contributor

andr11111 commented Jun 13, 2020

@Jie85 thanks for the write up! I think it makes sense on the high-level, need to clarify some details:

  1. How is BTC collateral that's required to be locked/redeemed accounted for? Is it managed as a separate pool and doesn't influence the price? Or is it managed as a part of the main BTC pool and therefore influences the price when it is locked/redeemed? At a minimum, the collateral requirement put a constraint on the market making on the short side.

  2. Initially the pool is seeded with Long Position tokens. I'm assuming this initial "seed" will be represented as 0x orders in the orderbook, not actual long position tokens. Correct?

  3. What constraints does the USD<>BTC conversion put on the system? For example, is there a liquid USDC<>imBTC market. (possible out of scope)

  4. Regarding X and Y continuity. Perhaps at end of day we can redeem, net-out contracts, recalculate the new X and Y based on the last price as initial price and new reserves. This is related to question 1.

@0xSSoul
Copy link
Member Author

0xSSoul commented Jun 15, 2020

I see. Because we use USDT for trading and IMBTC for contract settlement. I have edited the post to change to USDT. I think it has answered questions 1 and 3.

My answer to question 2:
We do not need to really mint long position token at the beginning of market-making. We just use the X as the "virtual size" of the long position. And it is used for pricing only. As the "PRICE" is equal to the "LONG TOKEN PRICE", the PRICE can used in order book directly.

My answer to question 4:
Yes, I agree with you. I think when we calculate the new initial price we could take the old XY into account.

@andr11111
Copy link
Contributor

(work-in-progress)

Choice of bonding curve reserves
I believe that the bonding curve should have the following reserves: LPT (X) and BTC (Y). Why not USDT? We can reasonably expect the USD-denominated price to be heavily influenced by BTC/USD price rather than contracts supply/demand. Using BTC reserve will allow us to isolate the bonding curve from this influence. The bonding curve price will be denominated in BTC, however the MM will quote the external price in USD based on the current BTC/USD price. That way the BTC/USD price changes will be reflected in the quotes even when reserves stay constant.

Real reserves
Real reserves represent actual tokens on MM balance sheet

  • BTC payment reserve (PAY) - used to enter positions, instantly converted to/from USDT when doing trades (in theory)
  • BTC collateral reserve (COL) - used for collateral when entering short positions
  • Long Position token (LPT) - pays BTC at settlement
  • Short Position token (SPT) - requires BTC collateral at initiation, returns remainder at settlement.

Operations and their effect on real reserves:

  • Enter long position => LPT+, PAY-
  • Enter short position => SPT+, PAY+, COL-
  • Redeem LPT => LPT-, COL+
  • Redeem SPT => SPT-, COL+
  • Net-out LPT and SPT => LTP-, SPT-, COL+

MM daily goals wrt to real reserves:

  1. To have equal LPT and SPT reserve (in order to net them out and free up BTC collateral)
  2. To reduce exposure to BTC price movements - likely via derivative hedging

Virtual Reserves
Virtual reserves are used for the purpose of bonding curve price calculation. Virtual reserves might not represent actual tokens on the balance sheet.

  • Virtual LPT reserve (X) = initial COL reserve / collateral requirement per contract(!this depends on the MRI!) + LPT balance - SPT balance
  • Virtual BTC payment reserve (PAY) = combination of BTC, USDT and hedges. Important goal is to make total virtual BTC reserve independent of BTC/USD price. This can be achieved in theory by instantaneously converting from/to USDT when doing trades. How to achieve it in reality - TBD.

Daily operations
At beginning of each day MM:

  1. Allocates BTC fund between PAY and COL reserves 44/56 - given 1.25 collateral ratio
  2. Picks initial price in BTC (how - TBD)
  3. Calculates K based on X (virtual LPT reserve) and Y(payment BTC reserve)

Throughout the day:

  • Quotes USD price per TH for infinitesimally small TH amount = Y / X * USDBTC price (bid/ask as discussed in the first comment)
  • Should be able to either quickly convert between BTC<>USDT or hold some USDT reserve in order to be able to enter long positions. Alternatively, it can be in a form of a liquid perpetual contract that can be quickly sold for USDT. In any case, it is important for Y to not be influenced by the price of Bitcoin.

BTC price hedging
Can be achieved via perpetuals/futures etc. Needs to be continuously managed in order to reflect total BTC reserve (incl locked collateral)

@longyunlyd
Copy link

longyunlyd commented Jun 26, 2020

Current Strategy

Input sample input value variable name Explanation/Notes
BTC/USDT price 9234 btcUsdtPrice  
current MRI (in BTC) 0.00000835 currentMRI  
Current Long Positions held by the MM (TH) 500 longPositionHoldings  
Current Short Positions held by the MM (TH) 400 shortPositionHoldings  
Current total USDT Reserve (USDT) 20000 currentUSDTReserve USDT reserve at the time of order
Long Order Size (TH) 1000 buyOrderSize number of contracts(TH) to buy
Short Order Size (TH) 2500 sellOrderSize number of contracts(TH) to offer
Est. total transaction cost for offers (USDT) 3 estFeeSell estimated gas cost when an offer is executed
Est. total transaction cost for buying (USDT) 7 estFeeBuy estimated gas cost when a buy order is executed

Note that all the inputs are the latest values at the time of order creation.

Intermediate results Sample value from sample inputs variable name
Init Contract Price 0.0771039 initialContractPrice
Init X 129695.1257 initialX
Init Y 10000 initialY
net position 100 netPosition
delta X for ask 2400 deltaXAsk
delta X for bid 1100 DeltaXBid
Output sample results from sample inputs
Ask Price (USDT/TH) 0.07975760342
Bid Price 0.06945544854

Recalculate initX and initY each time when an order is about to be placed with the latest inputs (using uniswap formula only for price shifts from the theoretical price).

Formulae
initContractPrice = currrentMRI * btcUsdtPrice (we use the spot for now but will optimize later with live market data)
initialX = currentUSDTReserve / 2 / btcUsdtPrice
initialY = currentUSDTReserve/ 2
netPosition = longPositionHoldings - shortPositionHoldings
deltaXAsk = sellOrderSize - netPosition
deltXBid = buyOrderSize + netPosition

Final Outputs
askPrice = initialY/(initialX - deltaXAsk) * (1 + r1) + estFeeSell/buyOrderSize
bidPrice = initialY/(initialX + deltaXBid) * (1 - r2) - estFeeBuy/sellOrderSize

where r1 and r2 are preset params for even more offset, r1 and r2 are real numbers.
Need to give MM admin (ZT perhaps) a place to override r1 and r2

@longyunlyd
Copy link

longyunlyd commented Jun 27, 2020

Data entries worth keep track of if possible

Data worth keep track on HoneyLemon Data worth keep track of on our side as MM Notes
-- USDT reserve MM daily should be fine or every hour if possible
-- BTC + imBTC reserve MM daily should be fine or every hour if possible
-- total long position holdings MM daily time series for each existing contract
-- total short position holdings MM daily time series for each existing contract
Daily Long order filled Daily Long order filled MM time series of daily data entry
Daily Short order filled Daily Short order filled MM time series of daily data entry
Filled price spread on each filled Long order Filled price spread on each filled Long order as MM = spot at the time of fill - weighted avg fill price, plotted as time series per filled order
Filled price spread on each filled Short order Filled price spread on each filled Short order as MM = weighted avg fill price -spot at the time of fill plotted as time series per filled order
daily overall spread long daily overall spread long MM = daily weighted avg of long spread weighted by filled volume
daily overall spread short daily overall spread short MM = daily weighted avg of long spread weighted by filled volume
-- avg BTC slippage each transaction as MM =number_of_BTC_supposed_to_get_using_BTCUSDT_index/number_of_BTC_actually_got - 1, a positive value means we lost money and a negative slippage means we actually made money
-- avg USDT slippage each transaction as MM =number_of_USDT_supposed_to_get_using_BTCUSDT_index/number_of_USDT_actually_got - 1
gas cost per transaction gas cost per transaction MM
Data worth streaming from 3rd party source Notes
FTX weighted avg price weighted by order book delpth** frequency decided by tech (balance between feasibility and frequency)
FTX filled price and volume frequency decided by tech (balance between feasibility and frequency)
The above two from other similar mining products  

** a.k.a volume weighted avg price calculation procedure.

  1. assign config parameter: depth for FTX let it be 1000 USDT for now
  2. compute avg ask price up to depth weighted by order size(1k usdt)
  3. compute avg bid price up to depth weighted by order size
  4. compute the avg of 2. and 3.
    (the results of 2, 3, and 4 are all needed as outputs)

Operation Details

  1. set aside 20% USDT reserve and convert them to BTC as reserve (now usdt : btc = 4:1 in value)
  2. rebalance the above mentioned dual reserve
    a. when BTC reserve falls belew 5% of USDT reserve (i.e. usdt :btc >= 20 : 1 in value)
    b. at the end of the day
  3. when placing an sell order, mint imBTC with BTC
  4. Early redemption (net out long and shorts) 1. at the end of day 2. or when min(num LPT, num SPT) > 20000
  5. size of each order min(0.5% of current total reserve value, 1000TH)
    current total reserve value include USDT + BTC
  6. need to give MM admin (ZT perhaps) a place to override r1 and r2.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants