diff --git a/programs/drift/src/math/amm_spread.rs b/programs/drift/src/math/amm_spread.rs index 744d253fb..5953b04d0 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/state/perp_market.rs b/programs/drift/src/state/perp_market.rs index 2135183f2..6fbad9209 100644 --- a/programs/drift/src/state/perp_market.rs +++ b/programs/drift/src/state/perp_market.rs @@ -1225,15 +1225,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) }