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-reservation-price-offset #681

Merged
merged 28 commits into from
Dec 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
280cc4d
bigz/amm-reservation-price-offset
0xbigz Nov 7, 2023
abaa09c
start spread shrinkage based on calculate_reservation_price_offset
0xbigz Nov 7, 2023
9c6d86f
add reservation_price_offset to calculate_spread
0xbigz Nov 7, 2023
bb21a89
add fields
crispheaney Nov 7, 2023
16704a7
Merge branch 'crispheaney/amm-new-fields' into bigz/amm-reservation-p…
0xbigz Nov 7, 2023
e936d93
incorp into calculate_spread_reserves
0xbigz Nov 7, 2023
9f48b7e
add typescript
0xbigz Nov 8, 2023
c876b87
add rust / typescript test, make max 1/5th of max_spread
0xbigz Nov 8, 2023
9375d20
Merge branch 'master' into bigz/amm-reservation-price-offset
0xbigz Nov 10, 2023
78ceb8f
update anchor types for 24h funding
0xbigz Nov 10, 2023
7067e67
fix calculateSpreadReserves return type
0xbigz Nov 20, 2023
f00f2cf
merge master + address comments/rename
0xbigz Nov 27, 2023
956775d
incorp feedback
0xbigz Nov 27, 2023
7df18ad
support sdk and tests, remove shrinakge of spread
0xbigz Nov 28, 2023
d9405cf
cleanup commented out code
0xbigz Nov 28, 2023
e8f00fd
amm.ts: add calculateInventoryLiquidityRatio
0xbigz Nov 28, 2023
6dd1b78
fix param in sdk/tests/amm/test.ts
0xbigz Nov 28, 2023
768f8a7
Merge branch 'master' into bigz/amm-reservation-price-offset
0xbigz Nov 28, 2023
320d305
fix some ts tests
0xbigz Nov 28, 2023
c9e4499
fix fmt/prettier
0xbigz Nov 28, 2023
76eedcb
add spread reserve logic to typescript
0xbigz Nov 28, 2023
e973135
fix idl
0xbigz Nov 28, 2023
4977f38
wip test
0xbigz Nov 29, 2023
f49bd28
wip sdk test
0xbigz Dec 6, 2023
2f2c3fd
merge master
0xbigz Dec 11, 2023
c93f93a
working spread offset test
0xbigz Dec 11, 2023
f1da8ee
calculate_reference_price_offset: ensure sign is consistent with two …
0xbigz Dec 11, 2023
eb25a25
update CHANGELOG.md
0xbigz Dec 11, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Features

- program: amm can use reference price offset from oracle price based on clamped inventory and persist market premiums ([#681](https://github.com/drift-labs/protocol-v2/pull/681))

### Fixes

### Breaking
Expand Down Expand Up @@ -55,6 +57,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- program: account for step size when canceling reduce only orders

### Breaking

- sdk: UserStatsMap use bulkAccountLoader (`UserStatsMap.subscribe` and `UserStatsMap.sync` now requires list of authorities) ([#716](https://github.com/drift-labs/protocol-v2/pull/716))

## [2.47.0] - 2023-11-26
Expand Down Expand Up @@ -134,6 +137,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- program: add positive perp funding rate offset ([#576](https://github.com/drift-labs/protocol-v2/pull/576/files))

### Fixes

- program: add validation check in update max imbalances ([#667](https://github.com/drift-labs/protocol-v2/pull/667))

### Breaking
Expand Down
11 changes: 11 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions programs/drift/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ serum_dex = { git = "https://github.com/project-serum/serum-dex", rev = "85b4f14
enumflags2 = "0.6.4"
phoenix-v1 = { git = "https://github.com/drift-labs/phoenix-v1", rev = "4c65c9", version = "0.2.4", features = ["no-entrypoint"] }
solana-security-txt = "1.1.0"
static_assertions = "1.1.0"
drift-macros = { git = "https://github.com/drift-labs/drift-macros.git", rev = "c57d87" }

[dev-dependencies]
bytes = "1.2.0"
Expand Down
26 changes: 26 additions & 0 deletions programs/drift/src/controller/amm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,31 @@ pub fn update_spread_reserves(amm: &mut AMM) -> DriftResult {
}

pub fn update_spreads(amm: &mut AMM, reserve_price: u64) -> DriftResult<(u32, u32)> {
let max_offset = amm.get_max_reference_price_offset()?;

let reference_price_offset = if amm.curve_update_intensity > 0 {
let liquidity_ratio = amm_spread::calculate_inventory_liquidity_ratio(
amm.base_asset_amount_with_amm,
amm.base_asset_reserve,
amm.max_base_asset_reserve,
amm.min_base_asset_reserve,
)?;

amm_spread::calculate_reference_price_offset(
reserve_price,
amm.last_24h_avg_funding_rate,
liquidity_ratio,
amm.min_order_size,
amm.historical_oracle_data.last_oracle_price_twap_5min,
amm.last_mark_price_twap_5min,
amm.historical_oracle_data.last_oracle_price_twap,
amm.last_mark_price_twap,
max_offset,
)?
} else {
0
};

let (long_spread, short_spread) = if amm.curve_update_intensity > 0 {
amm_spread::calculate_spread(
amm.base_spread,
Expand Down Expand Up @@ -196,6 +221,7 @@ pub fn update_spreads(amm: &mut AMM, reserve_price: u64) -> DriftResult<(u32, u3

amm.long_spread = long_spread;
amm.short_spread = short_spread;
amm.reference_price_offset = reference_price_offset;

update_spread_reserves(amm)?;

Expand Down
4 changes: 2 additions & 2 deletions programs/drift/src/controller/insurance/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1534,7 +1534,7 @@ fn test_transfer_protocol_owned_stake() {
.unwrap();
if_balance -= amount_returned;

assert_eq!(amount_returned, 99500000000);
assert_eq!(amount_returned, 99500000000_u64);
assert_eq!(spot_market.insurance_fund.user_shares, 0);
assert_eq!(spot_market.insurance_fund.total_shares, 21105203599);

Expand Down Expand Up @@ -1597,7 +1597,7 @@ fn test_transfer_protocol_owned_stake() {

let mut expected_if_stake_2 = InsuranceFundStake::new(Pubkey::default(), 0, 0);
expected_if_stake_2
.increase_if_shares(21105203599, &spot_market)
.increase_if_shares(21105203599_u128, &spot_market)
.unwrap();

assert_eq!(user_stats_2.if_staked_quote_asset_amount, 99500000000);
Expand Down
5 changes: 4 additions & 1 deletion programs/drift/src/instructions/admin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -727,7 +727,10 @@
padding1: 0,
padding2: 0,
total_fee_earned_per_lp: 0,
padding: [0; 32],
net_unsettled_funding_pnl: 0,
quote_asset_amount_with_unsettled_lp: 0,
reference_price_offset: 0,
padding: [0; 12],

Check warning on line 733 in programs/drift/src/instructions/admin.rs

View check run for this annotation

Codecov / codecov/patch

programs/drift/src/instructions/admin.rs#L733

Added line #L733 was not covered by tests
},
};

Expand Down
104 changes: 90 additions & 14 deletions programs/drift/src/math/amm_spread.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,15 @@
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,
PERCENTAGE_PRECISION_U64, PRICE_PRECISION, PRICE_PRECISION_I128,
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,
};
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 @@ -328,8 +327,10 @@
volume_24h,
)?;

let mut long_spread = max((base_spread / 2) as u64, long_vol_spread);
let mut short_spread = max((base_spread / 2) as u64, short_vol_spread);
let half_base_spread_u64 = (base_spread / 2) as u64;

let mut long_spread = max(half_base_spread_u64, long_vol_spread);
let mut short_spread = max(half_base_spread_u64, short_vol_spread);

let max_target_spread = max_spread
.cast::<u64>()?
Expand Down Expand Up @@ -448,20 +449,23 @@
PositionDirection::Short => amm.short_spread,
};

let spread_with_offset: i32 = spread.cast::<i32>()?.safe_add(amm.reference_price_offset)?;

let quote_asset_reserve_delta = if spread > 0 {
amm.quote_asset_reserve
.safe_div(BID_ASK_SPREAD_PRECISION_U128 / (spread.cast::<u128>()? / 2))?
.safe_div(BID_ASK_SPREAD_PRECISION_U128 / (spread_with_offset.cast::<u128>()? / 2))?
} else {
0
};

let quote_asset_reserve = match direction {
PositionDirection::Long => amm
.quote_asset_reserve
.safe_add(quote_asset_reserve_delta)?,
PositionDirection::Short => amm
.quote_asset_reserve
.safe_sub(quote_asset_reserve_delta)?,
let quote_asset_reserve = if spread_with_offset >= 0 && direction == PositionDirection::Long
|| spread_with_offset <= 0 && direction == PositionDirection::Short
{
amm.quote_asset_reserve
.safe_add(quote_asset_reserve_delta)?
} else {
amm.quote_asset_reserve
.safe_sub(quote_asset_reserve_delta)?
};

let invariant_sqrt_u192 = U192::from(amm.sqrt_k);
Expand All @@ -473,3 +477,75 @@

Ok((base_asset_reserve, quote_asset_reserve))
}

#[allow(clippy::comparison_chain)]
pub fn calculate_reference_price_offset(
reserve_price: u64,
last_24h_avg_funding_rate: i64,
liquidity_fraction: i128,
_min_order_size: u64,
oracle_twap_fast: i64,
mark_twap_fast: u64,
oracle_twap_slow: i64,
mark_twap_slow: u64,
max_offset_pct: i64,
) -> DriftResult<i32> {
if last_24h_avg_funding_rate == 0 {
return Ok(0);
}

let max_offset_in_price = max_offset_pct
.safe_mul(reserve_price.cast()?)?
.safe_div(PERCENTAGE_PRECISION.cast()?)?;

// calculate quote denominated market premium
let mark_premium_minute: i64 = mark_twap_fast
.cast::<i64>()?
.safe_sub(oracle_twap_fast)?

Check warning on line 504 in programs/drift/src/math/amm_spread.rs

View check run for this annotation

Codecov / codecov/patch

programs/drift/src/math/amm_spread.rs#L504

Added line #L504 was not covered by tests
Copy link
Member

Choose a reason for hiding this comment

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

would be good to figure out why code cov thinks this has no coverage? maybe you need to merge master?

.clamp(-max_offset_in_price, max_offset_in_price);
let mark_premium_hour: i64 = mark_twap_slow
.cast::<i64>()?
.safe_sub(oracle_twap_slow)?

Check warning on line 508 in programs/drift/src/math/amm_spread.rs

View check run for this annotation

Codecov / codecov/patch

programs/drift/src/math/amm_spread.rs#L508

Added line #L508 was not covered by tests
.clamp(-max_offset_in_price, max_offset_in_price);
// convert last_24h_avg_funding_rate to quote denominated premium
let mark_premium_day: i64 = last_24h_avg_funding_rate
.safe_div(FUNDING_RATE_BUFFER.cast()?)?
.safe_mul(24)?
.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
let mark_premium_avg = mark_premium_minute
.safe_add(mark_premium_hour)?
.safe_add(mark_premium_day)?

Check warning on line 519 in programs/drift/src/math/amm_spread.rs

View check run for this annotation

Codecov / codecov/patch

programs/drift/src/math/amm_spread.rs#L518-L519

Added lines #L518 - L519 were not covered by tests
.safe_div(3_i64)?;

let mark_premium_avg_pct: i64 = mark_premium_avg
.safe_mul(PRICE_PRECISION_I64)?

Check warning on line 523 in programs/drift/src/math/amm_spread.rs

View check run for this annotation

Codecov / codecov/patch

programs/drift/src/math/amm_spread.rs#L523

Added line #L523 was not covered by tests
.safe_div(reserve_price.cast()?)?;

let inventory_pct = liquidity_fraction
.cast::<i64>()?
.safe_mul(max_offset_pct)?

Check warning on line 528 in programs/drift/src/math/amm_spread.rs

View check run for this annotation

Codecov / codecov/patch

programs/drift/src/math/amm_spread.rs#L528

Added line #L528 was not covered by tests
.safe_div(PERCENTAGE_PRECISION.cast::<i64>()?)?
.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)
{
mark_premium_avg_pct.safe_add(inventory_pct)?
} else {
0
};

let clamped_offset_pct = offset_pct.clamp(-max_offset_pct, max_offset_pct);

validate!(

Check warning on line 543 in programs/drift/src/math/amm_spread.rs

View check run for this annotation

Codecov / codecov/patch

programs/drift/src/math/amm_spread.rs#L543

Added line #L543 was not covered by tests
clamped_offset_pct.abs() <= max_offset_pct,
ErrorCode::InvalidAmmDetected,

Check warning on line 545 in programs/drift/src/math/amm_spread.rs

View check run for this annotation

Codecov / codecov/patch

programs/drift/src/math/amm_spread.rs#L545

Added line #L545 was not covered by tests
"clamp offset pct failed {}",
clamped_offset_pct
)?;

clamped_offset_pct.cast()
}
Loading
Loading