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

Bigz/amm spread inventory pct #374

Merged
merged 14 commits into from
Feb 28, 2023
22 changes: 14 additions & 8 deletions programs/drift/src/controller/repeg/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,10 @@ pub fn update_amm_test() {
assert_eq!(reserve_price, 12743902015);
assert_eq!(ask, 12762712014);
assert!(ask >= (oracle_price_data.price as u64));
assert!((ask - bid) * 1000000 / reserve_price == market.amm.max_spread as u64);
assert_eq!(
(ask - bid) * 1000000 / reserve_price,
(market.amm.max_spread) as u64
);
}

#[test]
Expand Down Expand Up @@ -264,8 +267,8 @@ pub fn update_amm_larg_conf_test() {
let cost_of_update = _update_amm(&mut market, &oracle_price_data, &state, now, slot).unwrap();
assert_eq!(cost_of_update, -42992787); // amm wins when price increases

assert_eq!(market.amm.short_spread, 975 - market.amm.long_spread);
assert_eq!(market.amm.long_spread, 76);
assert_eq!(market.amm.short_spread, 975 - 76);

let reserve_price_after = market.amm.reserve_price().unwrap();
assert_eq!(reserve_price_after, 18849999999);
Expand All @@ -291,7 +294,7 @@ pub fn update_amm_larg_conf_test() {

assert_eq!(market.amm.long_spread, 76);
assert_eq!(market.amm.peg_multiplier, 19443664550);
assert_eq!(market.amm.short_spread, 975 - 76);
assert_eq!(market.amm.short_spread, 975 - market.amm.long_spread);

// add move lower
let oracle_price_data = OraclePriceData {
Expand Down Expand Up @@ -320,7 +323,7 @@ pub fn update_amm_larg_conf_test() {
let cost_of_update = _update_amm(&mut market, &oracle_price_data, &state, now, slot).unwrap();
assert_eq!(cost_of_update, 30468749);
assert_eq!(market.amm.long_spread, 60);
assert_eq!(market.amm.short_spread, 975 - 60);
assert_eq!(market.amm.short_spread, 975 - market.amm.long_spread);

let mrk = market.amm.reserve_price().unwrap();
let (bid, ask) = market.amm.bid_ask_price(mrk).unwrap();
Expand All @@ -342,7 +345,7 @@ pub fn update_amm_larg_conf_test() {
let cost_of_update = _update_amm(&mut market, &oracle_price_data, &state, now, slot).unwrap();
assert_eq!(cost_of_update, -3046875);
assert_eq!(market.amm.long_spread, 60);
assert_eq!(market.amm.short_spread, 975 - 60);
assert_eq!(market.amm.short_spread, 975 - market.amm.long_spread);

let mrk = market.amm.reserve_price().unwrap();
let (bid, ask) = market.amm.bid_ask_price(mrk).unwrap();
Expand Down Expand Up @@ -416,7 +419,10 @@ pub fn update_amm_larg_conf_w_neg_tfmd_test() {
assert_eq!(market.amm.last_update_slot, slot);

assert_eq!(market.amm.long_spread, 389);
assert_eq!(market.amm.short_spread, 975 - 389);
assert_eq!(
market.amm.short_spread,
market.amm.max_spread - market.amm.long_spread
);

let reserve_price_after = market.amm.reserve_price().unwrap();
assert_eq!(reserve_price_after, 18849999999);
Expand Down Expand Up @@ -490,7 +496,7 @@ pub fn update_amm_larg_conf_w_neg_tfmd_test() {
assert_eq!(market.amm.last_update_slot, slot);

assert_eq!(market.amm.long_spread, 369);
assert_eq!(market.amm.short_spread, 975 - 369);
assert_eq!(market.amm.short_spread, 975 - market.amm.long_spread);

let mrk = market.amm.reserve_price().unwrap();
let (bid, ask) = market.amm.bid_ask_price(mrk).unwrap();
Expand All @@ -514,7 +520,7 @@ pub fn update_amm_larg_conf_w_neg_tfmd_test() {
let cost_of_update = _update_amm(&mut market, &oracle_price_data, &state, now, slot).unwrap();
assert_eq!(cost_of_update, 299367);
assert_eq!(market.amm.long_spread, 378);
assert_eq!(market.amm.short_spread, 975 - 378);
assert_eq!(market.amm.short_spread, 975 - market.amm.long_spread);

let mrk = market.amm.reserve_price().unwrap();
let (bid, ask) = market.amm.bid_ask_price(mrk).unwrap();
Expand Down
77 changes: 56 additions & 21 deletions programs/drift/src/math/amm_spread.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,19 @@ use crate::math::amm::_calculate_market_open_bids_asks;
use crate::math::bn::U192;
use crate::math::casting::Cast;
use crate::math::constants::{
AMM_RESERVE_PRECISION_I128, AMM_TIMES_PEG_TO_QUOTE_PRECISION_RATIO_I128,
AMM_TO_QUOTE_PRECISION_RATIO_I128, BID_ASK_SPREAD_PRECISION, BID_ASK_SPREAD_PRECISION_I128,
BID_ASK_SPREAD_PRECISION_U128, DEFAULT_LARGE_BID_ASK_FACTOR,
DEFAULT_REVENUE_SINCE_LAST_FUNDING_SPREAD_RETREAT, MAX_BID_ASK_INVENTORY_SKEW_FACTOR,
PEG_PRECISION, PERCENTAGE_PRECISION, PRICE_PRECISION, PRICE_PRECISION_I128,
AMM_TIMES_PEG_TO_QUOTE_PRECISION_RATIO_I128, AMM_TO_QUOTE_PRECISION_RATIO_I128,
BID_ASK_SPREAD_PRECISION, BID_ASK_SPREAD_PRECISION_I128, BID_ASK_SPREAD_PRECISION_U128,
DEFAULT_LARGE_BID_ASK_FACTOR, DEFAULT_REVENUE_SINCE_LAST_FUNDING_SPREAD_RETREAT,
MAX_BID_ASK_INVENTORY_SKEW_FACTOR, PEG_PRECISION, PERCENTAGE_PRECISION, PRICE_PRECISION,
PRICE_PRECISION_I128,
};
use crate::math::safe_math::SafeMath;

use crate::state::perp_market::AMM;
use crate::validate;

use super::constants::PERCENTAGE_PRECISION_I128;

#[cfg(test)]
mod tests;

Expand Down Expand Up @@ -153,6 +155,37 @@ pub fn calculate_long_short_vol_spread(
))
}

pub fn calculate_inventory_liquidity_ratio(
base_asset_amount_with_amm: i128,
base_asset_reserve: u128,
min_base_asset_reserve: u128,
max_base_asset_reserve: u128,
) -> DriftResult<i128> {
// computes min(1, x/(1-x)) for 0 < x < 1

// inventory scale
let (max_bids, max_asks) = _calculate_market_open_bids_asks(
base_asset_reserve,
min_base_asset_reserve,
max_base_asset_reserve,
)?;

let min_side_liquidity = max_bids.min(max_asks.abs());
msg!("max_bids={:?} / max_asks={:?}", max_bids, max_asks);
0xbigz marked this conversation as resolved.
Show resolved Hide resolved

// cap so (6e9 * AMM_RESERVE_PRECISION)^2 < 2^127
let amm_inventory_pct = if base_asset_amount_with_amm < 6000000000000000000 {
base_asset_amount_with_amm
.abs()
.safe_mul(PERCENTAGE_PRECISION_I128)?
.safe_div(min_side_liquidity.max(1))?
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could maybe just max this with PERCENTAGE_PRECISION_I128 and get rid of the min before, might make it easier to replicate in ts sdk?

} else {
PERCENTAGE_PRECISION_I128 // 100%
};

Ok(amm_inventory_pct.min(PERCENTAGE_PRECISION_I128))
}

pub fn calculate_spread_inventory_scale(
base_asset_amount_with_amm: i128,
base_asset_reserve: u128,
Expand All @@ -165,38 +198,40 @@ pub fn calculate_spread_inventory_scale(
return Ok(BID_ASK_SPREAD_PRECISION);
}

// inventory scale
let (max_bids, max_asks) = _calculate_market_open_bids_asks(
let amm_inventory_pct = calculate_inventory_liquidity_ratio(
base_asset_amount_with_amm,
base_asset_reserve,
min_base_asset_reserve,
max_base_asset_reserve,
)?;

let min_side_liquidity = max_bids.min(max_asks.abs());

// cap so (6e9 * AMM_RESERVE_PRECISION)^2 < 2^127
let amm_inventory_size = base_asset_amount_with_amm.abs().min(6000000000000000000);
msg!(
"{:?} => amm_inventory_pct={:?}",
base_asset_amount_with_amm,
amm_inventory_pct
);

// inventory scale
let inventory_scale = amm_inventory_size
.safe_mul(amm_inventory_size.max(AMM_RESERVE_PRECISION_I128))?
.safe_div(AMM_RESERVE_PRECISION_I128)?
.safe_mul(DEFAULT_LARGE_BID_ASK_FACTOR.cast::<i128>()?)?
.safe_div(min_side_liquidity.max(1))?
.unsigned_abs();

// only allow up to scale up of larger of MAX_BID_ASK_INVENTORY_SKEW_FACTOR or half of max spread
let inventory_scale = amm_inventory_pct.unsigned_abs();
msg!("inventory_scale={:?}", inventory_scale);

// only allow up to scale up of larger of MAX_BID_ASK_INVENTORY_SKEW_FACTOR or max spread
let inventory_scale_max = MAX_BID_ASK_INVENTORY_SKEW_FACTOR.max(
max_spread
.safe_div(2)?
.safe_mul(BID_ASK_SPREAD_PRECISION)?
.safe_div(max(directional_spread, 1))?,
);
msg!("inventory_scale_max={:?}", inventory_scale_max);

let inventory_scale_capped = min(
inventory_scale_max,
BID_ASK_SPREAD_PRECISION
.safe_add(inventory_scale.cast()?)
.safe_add(
inventory_scale_max
.safe_mul(inventory_scale.cast()?)
.unwrap_or(u64::MAX)
.safe_div(PERCENTAGE_PRECISION_I128.cast()?)?,
)
.unwrap_or(u64::MAX),
);

Expand Down
Loading