Skip to content

Commit

Permalink
program: revert-bid-ask-estimate-update (#986)
Browse files Browse the repository at this point in the history
  • Loading branch information
0xbigz committed Apr 1, 2024
1 parent e1a64d0 commit 695b210
Show file tree
Hide file tree
Showing 3 changed files with 21 additions and 149 deletions.
114 changes: 1 addition & 113 deletions programs/drift/src/controller/position/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,8 @@ use crate::controller::amm::{
};
use crate::controller::lp::{apply_lp_rebase_to_perp_market, settle_lp_position};
use crate::controller::position::{
update_lp_market_position, update_position_and_market, PositionDelta, PositionDirection,
update_lp_market_position, update_position_and_market, PositionDelta,
};
use crate::math::amm::estimate_best_bid_ask_price;

use crate::controller::repeg::_update_amm;
use crate::math::constants::{
Expand Down Expand Up @@ -183,117 +182,6 @@ fn amm_split_large_k() {
// assert_eq!(243360075047/9977763076 < 23, true); // ensure rounding in favor
}

#[test]
fn est_bid_ask_amm() {
let perp_market_str = String::from("Ct8MLGv1N/dvAH3EF67yBqaUQerctpm4yqpK+QNSrXCQz76p+B+ka+8Ni2/aLOukHaFdQJXR2jkqDS+O0MbHvA9M+sjCgLVt+ZlACwAAAAAAAAAAAAAAAAsAAAAAAAAA7qpCCwAAAAC4pEILAAAAAM80A2YAAAAAw3D+Q3v//////////////140wCb9///////////////BxseW97wLAAAAAAAAAAAAAAAAAAAAAAAkJxFcfNoMAAAAAAAAAAAA1zaaHQfsLQAAAAAAAAAAAJxiDwAAAAAAAAAAAAAAAABA3MVuOsEMAAAAAAAAAAAAgQcQ9oz3DAAAAAAAAAAAAI2Es72RSxgAAAAAAAAAAAClRSYDAAAAAAAAAAAAAAAA04ZcWqHlLQAAAAAAAAAAAACCXOjX+gEAAAAAAAAAAAAAM8+xVAj+////////////rRDbp8oBAAAAAAAAAAAAAFOkUPJhAQAAAAAAAAAAAAAAwFdzpXwCAAAAAAAAAAAA7ChoURUDAAAAAAAAAAAAADgppSk1q/////////////8AvdVXzFEAAAAAAAAAAAAAm4q7HPmp/////////////1OqNxBzUwAAAAAAAAAAAABZaPEEvrgKAAAAAAAAAAAAmP0CAQAAAACY/QIBAAAAAJj9AgEAAAAADvGuAAAAAADk8/rI/wUAAAAAAAAAAAAAq3UYzAACAAAAAAAAAAAAAK6UWaIPBAAAAAAAAAAAAADE5UUQtAQAAAAAAAAAAAAAqk4rAFkBAAAAAAAAAAAAAIttLk+yAAAAAAAAAAAAAADSM6t1BQAAAAAAAAAAAAAAV9hgaQUAAAAAAAAAAAAAAMG4+QwBAAAAAAAAAAAAAAB1buJiZdEMAAAAAAAAAAAAp6DXzJcMLgAAAAAAAAAAAPWPB6Ka3gwAAAAAAAAAAAB0Ls4vVd0tAAAAAAAAAAAA+ZlACwAAAAAAAAAAAAAAAPVQRgsAAAAA37ZKCwAAAADqg0gLAAAAAPDpSAsAAAAAXcVLDwAAAAD3AQAAAAAAAAmH4Zv/////TikDZgAAAAAQDgAAAAAAAADh9QUAAAAAZAAAAAAAAAAA4fUFAAAAAAAAAAAAAAAAfbNpS6dGAAC/w9I8tgAAAORXqHOmAAAAzzQDZgAAAACIHQ8AAAAAAPUQAgAAAAAAzzQDZgAAAADECQAAqGEAAJcVAADECQAAAAAAADIMAADECTIAZMgAAMDIUt4DAAAAnfyXDgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJPHxf64g0AAAAAAAAAAAAAAAAAAAAAAFNPTC1QRVJQICAgICAgICAgICAgICAgICAgICAgICAgAAAAAAAAAAAAwusLAAAAAABcsuwiAAAAa6PKbQQAAABWDQNmAAAAAADh9QUAAAAAAAAAAAAAAAAAAAAAAAAAAC8jSgAAAAAAVi8AAAAAAAAZBQAAAAAAAMgAAAAAAAAATB0AANQwAADoAwAA9AEAAAAAAAAQJwAA1S8AABxVAAAAAAEAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==");
let mut decoded_bytes = base64::decode(perp_market_str).unwrap();
let perp_market_bytes = decoded_bytes.as_mut_slice();

let key = Pubkey::default();
let owner = Pubkey::from_str("dRiftyHA39MWEi3m9aunc5MzRF1JYuBsbn6VPcn33UH").unwrap();
let mut lamports = 0;
let perp_market_account_info =
create_account_info(&key, true, &mut lamports, perp_market_bytes, &owner);

let perp_market_loader: AccountLoader<PerpMarket> =
AccountLoader::try_from(&perp_market_account_info).unwrap();
let mut perp_market = perp_market_loader.load_mut().unwrap();

assert_eq!(
perp_market.amm.historical_oracle_data.last_oracle_price,
188783097
);
assert_eq!(
perp_market
.amm
.historical_oracle_data
.last_oracle_price_twap_5min,
188916920
);
assert_eq!(perp_market.amm.last_bid_price_twap, 189157621);
assert_eq!(perp_market.amm.last_mark_price_twap, 189301738);
assert_eq!(perp_market.amm.last_mark_price_twap_5min, 189327856);
assert_eq!(perp_market.amm.last_ask_price_twap, 189445855);

assert_eq!(
perp_market
.amm
.historical_oracle_data
.last_oracle_price_twap_ts,
1711486159
);
assert_eq!(perp_market.amm.last_mark_price_twap_ts, 1711486159);
assert_eq!(
perp_market.amm.last_mark_price_twap_ts,
perp_market
.amm
.historical_oracle_data
.last_oracle_price_twap_ts
);

let (bid_og, ask_og) = estimate_best_bid_ask_price(&mut perp_market.amm, None, None).unwrap();

assert_eq!(bid_og, 188783097);
assert_eq!(ask_og, 188783097);

let (bid, ask) = estimate_best_bid_ask_price(
&mut perp_market.amm,
Some(ask_og),
Some(PositionDirection::Long),
)
.unwrap();

assert_eq!(bid, 188311140);
assert_eq!(ask, 188783097);

let (bid, ask) = estimate_best_bid_ask_price(
&mut perp_market.amm,
Some(bid_og),
Some(PositionDirection::Short),
)
.unwrap();

assert_eq!(bid, 188783097);
assert_eq!(ask, 189255054);

let (bid, ask) = estimate_best_bid_ask_price(
&mut perp_market.amm,
Some(188783097 + PRICE_PRECISION_U64 / 2),
Some(PositionDirection::Short),
)
.unwrap();

assert_eq!(bid, 189283097);
assert_eq!(ask, 189755054);

let amm_reserve_price = perp_market.amm.reserve_price().unwrap();
let (amm_bid_price, amm_ask_price) = perp_market.amm.bid_ask_price(amm_reserve_price).unwrap();

// wick order (short at $4 above oracle)
let (bid, ask) = estimate_best_bid_ask_price(
&mut perp_market.amm,
Some(188783097 + PRICE_PRECISION_U64 * 4),
Some(PositionDirection::Short),
)
.unwrap();

assert_eq!(bid, 189826069);
assert_eq!(ask, 189826069);

assert_eq!(bid, amm_ask_price);

// wick order (long at $4 below oracle)
let (bid, ask) = estimate_best_bid_ask_price(
&mut perp_market.amm,
Some(188783097 - PRICE_PRECISION_U64 * 4),
Some(PositionDirection::Long),
)
.unwrap();

assert_eq!(bid, amm_bid_price);
assert_eq!(ask, amm_bid_price);
}

#[test]
fn amm_split_large_k_with_rebase() {
let perp_market_str = String::from("Ct8MLGv1N/dvAH3EF67yBqaUQerctpm4yqpK+QNSrXCQz76p+B+ka+8Ni2/aLOukHaFdQJXR2jkqDS+O0MbHvA9M+sjCgLVtQwhkAQAAAAAAAAAAAAAAAAIAAAAAAAAAkI1kAQAAAAB6XWQBAAAAAO8yzWQAAAAAnJ7I3f///////////////2dHvwAAAAAAAAAAAAAAAABGiVjX6roAAAAAAAAAAAAAAAAAAAAAAAB1tO47J+xiAAAAAAAAAAAAGD03Fis3mgAAAAAAAAAAAJxiDwAAAAAAAAAAAAAAAABxqRCIGRxiAAAAAAAAAAAAEy8wZfK9YwAAAAAAAAAAAGZeZCE+g3sAAAAAAAAAAAAKYeQAAAAAAAAAAAAAAAAAlIvoyyc3mgAAAAAAAAAAAADQdQKjbgAAAAAAAAAAAAAAwu8g05H/////////////E6tNHAIAAAAAAAAAAAAAAO3mFwd0AAAAAAAAAAAAAAAAgPQg5rUAAAAAAAAAAAAAGkDtXR4AAAAAAAAAAAAAAEv0WeZW/f////////////9kUidaqAIAAAAAAAAAAAAA0ZMEr1H9/////////////w5/U3uqAgAAAAAAAAAAAAAANfbqfCd3AAAAAAAAAAAAIhABAAAAAAAiEAEAAAAAACIQAQAAAAAAY1QBAAAAAAA5f3WMVAAAAAAAAAAAAAAAFhkiihsAAAAAAAAAAAAAAO2EfWc5AAAAAAAAAAAAAACM/5CAQgAAAAAAAAAAAAAAvenX0SsAAAAAAAAAAAAAALgPUogZAAAAAAAAAAAAAAC01x97AAAAAAAAAAAAAAAAOXzVbgAAAAAAAAAAAAAAAMG4+QwBAAAAAAAAAAAAAABwHI3fLeJiAAAAAAAAAAAABvigOblGmgAAAAAAAAAAALeRnZsi9mIAAAAAAAAAAAAqgs3ynCeaAAAAAAAAAAAAQwhkAQAAAAAAAAAAAAAAAJOMZAEAAAAAFKJkAQAAAABTl2QBAAAAALFuZAEAAAAAgrx7DAAAAAAUAwAAAAAAAAN1TAYAAAAAuC7NZAAAAAAQDgAAAAAAAADh9QUAAAAAZAAAAAAAAAAA4fUFAAAAAAAAAAAAAAAAn2HvyMABAADGV6rZFwAAAE5Qg2oPAAAA8zHNZAAAAAAdYAAAAAAAAE2FAAAAAAAA6zLNZAAAAAD6AAAAaEIAABQDAAAUAwAAAAAAANcBAABkADIAZGQAAcDIUt4AAAAA0QQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAI9qQbynsAAAAAAAAAAAAAAAAAAAAAAAAFNPTC1QRVJQICAgICAgICAgICAgICAgICAgICAgICAghuS1//////8A4fUFAAAAAAB0O6QLAAAAR7PdeQMAAAD+Mc1kAAAAAADKmjsAAAAAAAAAAAAAAAAAAAAAAAAAAOULDwAAAAAAUBkAAAAAAADtAQAAAAAAAMgAAAAAAAAAECcAAKhhAADoAwAA9AEAAAAAAAAQJwAAZAIAAGQCAAAAAAEAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==");
Expand Down
42 changes: 13 additions & 29 deletions programs/drift/src/math/amm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -149,28 +149,17 @@ pub fn estimate_best_bid_ask_price(
precomputed_trade_price: Option<u64>,
direction: Option<PositionDirection>,
) -> DriftResult<(u64, u64)> {
let base_spread_u64 = amm.base_spread.cast::<u64>()?;
let last_oracle_price_u64 = amm.historical_oracle_data.last_oracle_price.cast::<u64>()?;

// in price units
let base_spread_price_u64 = last_oracle_price_u64
.safe_mul(amm.base_spread.cast::<u64>()?)?
.safe_div(PERCENTAGE_PRECISION_U64)?;
let max_spread_price_u64 = last_oracle_price_u64
.safe_mul(amm.base_spread.max(amm.max_spread).cast::<u64>()?)?
.safe_div(PERCENTAGE_PRECISION_U64)?;

let trade_price: u64 = match precomputed_trade_price {
Some(trade_price) => trade_price,
None => last_oracle_price_u64,
};
let est_market_spread = amm
.last_ask_price_twap
.cast::<i64>()?
.safe_sub(amm.last_bid_price_twap.cast::<i64>()?)?
.max(0)
.unsigned_abs()
.clamp(base_spread_price_u64, max_spread_price_u64);

let trade_premium: i64 = trade_price
.cast::<i64>()?
.safe_sub(amm.historical_oracle_data.last_oracle_price)?;
validate!(
amm.historical_oracle_data.last_oracle_price > 0,
ErrorCode::InvalidOracle,
Expand All @@ -179,26 +168,21 @@ pub fn estimate_best_bid_ask_price(

let amm_reserve_price = amm.reserve_price()?;
let (amm_bid_price, amm_ask_price) = amm.bid_ask_price(amm_reserve_price)?;
// estimation of bid/ask by looking at execution premium

let best_bid_estimate = if let Some(direction) = direction {
// taker is a long, hitting ask, assuming best bid is est_market_spread below
if direction == PositionDirection::Long {
trade_price.saturating_sub(est_market_spread)
} else {
trade_price
}
// trade is a long
let best_bid_estimate = if trade_premium > 0 {
let discount = min(base_spread_u64, amm.short_spread.cast::<u64>()? / 2);
last_oracle_price_u64.safe_sub(discount.min(trade_premium.unsigned_abs()))?
} else {
trade_price
}
.max(amm_bid_price);

let best_ask_estimate = if let Some(direction) = direction {
// taker is a short, hitting bid, assuming best ask is est_market_spread above
if direction == PositionDirection::Short {
trade_price.saturating_add(est_market_spread)
} else {
trade_price
}
// trade is a short
let best_ask_estimate = if trade_premium < 0 {
let premium = min(base_spread_u64, amm.long_spread.cast::<u64>()? / 2);
last_oracle_price_u64.safe_add(premium.min(trade_premium.unsigned_abs()))?
} else {
trade_price
}
Expand Down
14 changes: 7 additions & 7 deletions programs/drift/src/math/amm/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -676,10 +676,10 @@ fn update_mark_twap_tests() {
assert_eq!((new_bid_twap + new_ask_twap) / 2, new_mark_twap);
assert!((new_oracle_twap as u64) < new_mark_twap); // funding in favor of maker?
assert_eq!(new_oracle_twap, 40008161);
assert_eq!(new_bid_twap, 40013203);
assert_eq!(new_mark_twap, 40023382); // ~ 2 cents above oracle twap
assert_eq!(new_bid_twap, 40014547);
assert_eq!(new_mark_twap, 40024054); // ~ 2 cents above oracle twap
assert_eq!(new_ask_twap, 40033561);
assert_eq!(amm.mark_std, 27902);
assert_eq!(amm.mark_std, 27230);
assert_eq!(amm.oracle_std, 3119);

let trade_price_2 = 39_971_280 * PRICE_PRECISION_U64 / 1_000_000;
Expand Down Expand Up @@ -712,16 +712,16 @@ fn update_mark_twap_tests() {
let new_bid_twap = amm.last_bid_price_twap;
let new_ask_twap = amm.last_ask_price_twap;

assert_eq!(new_bid_twap, 39_989_217);
assert_eq!(new_ask_twap, 40_004_701);
assert_eq!(new_bid_twap, 39_989_389);
assert_eq!(new_ask_twap, 40_000_790);
assert!(new_bid_twap < new_ask_twap);
assert_eq!((new_bid_twap + new_ask_twap) / 2, new_mark_twap);

assert_eq!(new_oracle_twap, 39_998_518);
assert_eq!(new_mark_twap, 39996959);
assert_eq!(new_mark_twap, 39995089);

assert!((new_oracle_twap as u64) >= new_mark_twap); // funding in favor of maker
assert_eq!(amm.mark_std, 26291);
assert_eq!(amm.mark_std, 24467);
assert_eq!(amm.oracle_std, 7238);
}

Expand Down

0 comments on commit 695b210

Please sign in to comment.