diff --git a/programs/drift/src/controller/position/tests.rs b/programs/drift/src/controller/position/tests.rs index ab6cf1034c..b25efb70a8 100644 --- a/programs/drift/src/controller/position/tests.rs +++ b/programs/drift/src/controller/position/tests.rs @@ -599,7 +599,7 @@ fn amm_ref_price_decay_tail_test() { perp_market.amm.curve_update_intensity = 200; let max_ref_offset = perp_market.amm.get_max_reference_price_offset().unwrap(); - assert_eq!(max_ref_offset, 10000); + assert_eq!(max_ref_offset, 5000); let liquidity_ratio = crate::math::amm_spread::calculate_inventory_liquidity_ratio( perp_market.amm.base_asset_amount_with_amm, @@ -814,7 +814,7 @@ fn amm_ref_price_offset_decay_logic() { max_ref_offset, ) .unwrap(); - assert_eq!(res, 10000); + assert_eq!(res, 750); let mut now = perp_market.amm.last_mark_price_twap_ts + 10; let mut clock_slot = 353317544 + 20; // todo @@ -988,7 +988,7 @@ fn amm_negative_ref_price_offset_decay_logic() { max_ref_offset, ) .unwrap(); - assert_eq!(res, 10000); + assert_eq!(res, 750); let mut now = perp_market.amm.last_mark_price_twap_ts + 10; let mut clock_slot = 353317544 + 20; // todo @@ -1210,7 +1210,7 @@ fn amm_perp_ref_offset() { let r = perp_market.amm.reserve_price().unwrap(); let (b, a) = perp_market.amm.bid_ask_price(r).unwrap(); - assert_eq!(b, 7098999); + assert_eq!(b, 7102635); assert_eq!(a, 7106129); assert_eq!( perp_market.amm.historical_oracle_data.last_oracle_price, diff --git a/programs/drift/src/math/amm_spread.rs b/programs/drift/src/math/amm_spread.rs index 80915b83b9..384831d198 100644 --- a/programs/drift/src/math/amm_spread.rs +++ b/programs/drift/src/math/amm_spread.rs @@ -11,9 +11,9 @@ use crate::math::constants::{ AMM_TIMES_PEG_TO_QUOTE_PRECISION_RATIO_I128, AMM_TO_QUOTE_PRECISION_RATIO_I128, BID_ASK_SPREAD_PRECISION, BID_ASK_SPREAD_PRECISION_I128, DEFAULT_LARGE_BID_ASK_FACTOR, DEFAULT_REVENUE_SINCE_LAST_FUNDING_SPREAD_RETREAT, FUNDING_RATE_BUFFER, - MAX_BID_ASK_INVENTORY_SKEW_FACTOR, PEG_PRECISION, PERCENTAGE_PRECISION, - PERCENTAGE_PRECISION_I128, PERCENTAGE_PRECISION_U64, PRICE_PRECISION, PRICE_PRECISION_I128, - PRICE_PRECISION_I64, + FUNDING_RATE_OFFSET_DENOMINATOR, MAX_BID_ASK_INVENTORY_SKEW_FACTOR, PEG_PRECISION, + PERCENTAGE_PRECISION, PERCENTAGE_PRECISION_I128, PERCENTAGE_PRECISION_U64, PRICE_PRECISION, + PRICE_PRECISION_I128, PRICE_PRECISION_I64, }; use crate::math::safe_math::SafeMath; use crate::state::perp_market::{ContractType, PerpMarket, AMM}; @@ -591,9 +591,13 @@ pub fn calculate_reference_price_offset( let mark_premium_day: i64 = last_24h_avg_funding_rate .safe_div(FUNDING_RATE_BUFFER.cast()?)? .safe_mul(24)? + .safe_sub( + oracle_twap_slow + .abs() + .safe_div(FUNDING_RATE_OFFSET_DENOMINATOR)?, + )? .clamp(-max_offset_in_price, max_offset_in_price); // todo: look at how 24h funding is calc w.r.t. the funding_period - - // take average clamped premium as the price-based offset + // take average clamped premium as the price-based offset let mark_premium_avg = mark_premium_minute .safe_add(mark_premium_hour)? .safe_add(mark_premium_day)? @@ -603,17 +607,13 @@ pub fn calculate_reference_price_offset( .safe_mul(PRICE_PRECISION_I64)? .safe_div(reserve_price.cast()?)?; - let inventory_pct = liquidity_fraction - .cast::()? - .safe_mul(max_offset_pct)? - .safe_div(PERCENTAGE_PRECISION.cast::()?)? - .clamp(-max_offset_pct, max_offset_pct); - // only apply when inventory is consistent with recent and 24h market premium - let offset_pct = if (mark_premium_avg_pct >= 0 && inventory_pct >= 0) - || (mark_premium_avg_pct <= 0 && inventory_pct <= 0) + let offset_pct = if (mark_premium_avg_pct >= 0 && liquidity_fraction >= 0) + || (mark_premium_avg_pct <= 0 && liquidity_fraction <= 0) { - mark_premium_avg_pct.safe_add(inventory_pct)? + mark_premium_avg_pct + .safe_mul(liquidity_fraction.cast::()?)? + .safe_div(5)? } else { 0 }; diff --git a/programs/drift/src/math/amm_spread/tests.rs b/programs/drift/src/math/amm_spread/tests.rs index 5953db1e04..74f6bd4d52 100644 --- a/programs/drift/src/math/amm_spread/tests.rs +++ b/programs/drift/src/math/amm_spread/tests.rs @@ -59,7 +59,7 @@ mod test { max_offset, ) .unwrap(); - assert_eq!(res, 158); // 237*2/3); // 1 penny divergence + assert_eq!(res, 182); // 237*2/3); // 1 penny divergence let res = calculate_reference_price_offset( rev_price, 1, @@ -393,7 +393,7 @@ mod test { market.amm.curve_update_intensity = 110; let max_ref_offset = market.amm.get_max_reference_price_offset().unwrap(); - assert_eq!(max_ref_offset, 1000); // 10 bps + assert_eq!(max_ref_offset, 500); // 5 bps market.amm.curve_update_intensity = 200; let max_ref_offset = market.amm.get_max_reference_price_offset().unwrap(); diff --git a/programs/drift/src/state/perp_market.rs b/programs/drift/src/state/perp_market.rs index 815fa83fc2..a84f764a94 100644 --- a/programs/drift/src/state/perp_market.rs +++ b/programs/drift/src/state/perp_market.rs @@ -1331,15 +1331,17 @@ impl AMM { pub fn get_max_reference_price_offset(self) -> DriftResult { if self.curve_update_intensity <= 100 { return Ok(0); + } else if self.curve_update_intensity >= 200 { + return Ok(self.max_spread.cast::()? / 2); } let lower_bound_multiplier: i64 = self.curve_update_intensity.safe_sub(100)?.cast::()?; - // always higher of 1-100 bps of price offset and half of the market's max_spread + // always the lesser of 1-100 bps of price offset and half of the market's max_spread let lb_bps = (PERCENTAGE_PRECISION.cast::()? / 10000).safe_mul(lower_bound_multiplier)?; - let max_offset = (self.max_spread.cast::()? / 2).max(lb_bps); + let max_offset = (self.max_spread.cast::()? / 2).min(lb_bps); Ok(max_offset) } diff --git a/sdk/VERSION b/sdk/VERSION index efa9a6c58f..6460b55cd8 100644 --- a/sdk/VERSION +++ b/sdk/VERSION @@ -1 +1 @@ -2.139.0-beta.2 \ No newline at end of file +2.139.0-beta.2