Perp: Allow setting pnl asset weights (#391)

This replaces the previous distinction between trusted and untrusted
markets, they are equivalent to setting the asset weights to 1 or 0
instead.

This way, we can weigh positive pnl in the trusted case at less than 1
which is more correct from a risk point of view and allows for more
flexibility when it comes to liquidation.

Co-authored-by: microwavedcola1 <microwavedcola@gmail.com>
This commit is contained in:
Christian Kamm 2023-01-16 16:49:09 +01:00 committed by GitHub
parent da1dfb2c3c
commit ec99376a8f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
26 changed files with 593 additions and 456 deletions

View File

@ -436,8 +436,22 @@ mod tests {
let oo1key = oo1.pubkey; let oo1key = oo1.pubkey;
oo1.data().native_pc_total = 20; oo1.data().native_pc_total = 20;
let mut perp1 = mock_perp_market(group, oracle2.pubkey, oracle2_price, 9, 0.2, 0.1); let mut perp1 = mock_perp_market(
let mut perp2 = mock_perp_market(group, oracle1.pubkey, oracle1_price, 8, 0.2, 0.1); group,
oracle2.pubkey,
oracle2_price,
9,
(0.2, 0.1),
(0.05, 0.02),
);
let mut perp2 = mock_perp_market(
group,
oracle1.pubkey,
oracle1_price,
8,
(0.2, 0.1),
(0.05, 0.02),
);
let oracle1_account_info = oracle1.as_account_info(); let oracle1_account_info = oracle1.as_account_info();
let oracle2_account_info = oracle2.as_account_info(); let oracle2_account_info = oracle2.as_account_info();

View File

@ -209,10 +209,12 @@ pub(crate) struct Serum3Reserved {
#[derive(Clone, AnchorDeserialize, AnchorSerialize, Debug)] #[derive(Clone, AnchorDeserialize, AnchorSerialize, Debug)]
pub struct PerpInfo { pub struct PerpInfo {
pub perp_market_index: PerpMarketIndex, pub perp_market_index: PerpMarketIndex,
pub maint_asset_weight: I80F48, pub maint_base_asset_weight: I80F48,
pub init_asset_weight: I80F48, pub init_base_asset_weight: I80F48,
pub maint_liab_weight: I80F48, pub maint_base_liab_weight: I80F48,
pub init_liab_weight: I80F48, pub init_base_liab_weight: I80F48,
pub maint_pnl_asset_weight: I80F48,
pub init_pnl_asset_weight: I80F48,
pub base_lot_size: i64, pub base_lot_size: i64,
pub base_lots: i64, pub base_lots: i64,
pub bids_base_lots: i64, pub bids_base_lots: i64,
@ -221,7 +223,6 @@ pub struct PerpInfo {
pub quote: I80F48, pub quote: I80F48,
pub prices: Prices, pub prices: Prices,
pub has_open_orders: bool, pub has_open_orders: bool,
pub trusted_market: bool,
} }
impl PerpInfo { impl PerpInfo {
@ -237,10 +238,12 @@ impl PerpInfo {
Ok(Self { Ok(Self {
perp_market_index: perp_market.perp_market_index, perp_market_index: perp_market.perp_market_index,
init_asset_weight: perp_market.init_asset_weight, init_base_asset_weight: perp_market.init_base_asset_weight,
init_liab_weight: perp_market.init_liab_weight, init_base_liab_weight: perp_market.init_base_liab_weight,
maint_asset_weight: perp_market.maint_asset_weight, maint_base_asset_weight: perp_market.maint_base_asset_weight,
maint_liab_weight: perp_market.maint_liab_weight, maint_base_liab_weight: perp_market.maint_base_liab_weight,
init_pnl_asset_weight: perp_market.init_pnl_asset_weight,
maint_pnl_asset_weight: perp_market.maint_pnl_asset_weight,
base_lot_size: perp_market.base_lot_size, base_lot_size: perp_market.base_lot_size,
base_lots, base_lots,
bids_base_lots: perp_position.bids_base_lots, bids_base_lots: perp_position.bids_base_lots,
@ -248,14 +251,15 @@ impl PerpInfo {
quote: quote_current, quote: quote_current,
prices, prices,
has_open_orders: perp_position.has_open_orders(), has_open_orders: perp_position.has_open_orders(),
trusted_market: perp_market.trusted_market(),
}) })
} }
/// Total health contribution from perp balances /// Total health contribution from perp balances
/// ///
/// Due to isolation of perp markets, users may never borrow against perp /// For fully isolated perp markets, users may never borrow against unsettled
/// positions in untrusted without settling first: perp health is capped at zero. /// positive perp pnl, there pnl_asset_weight == 0 and there can't be positive
/// health contributions from these perp market. We sometimes call these markets
/// "untrusted markets".
/// ///
/// Users need to settle their perp pnl with other perp market participants /// Users need to settle their perp pnl with other perp market participants
/// in order to realize their gains if they want to use them as collateral. /// in order to realize their gains if they want to use them as collateral.
@ -264,32 +268,43 @@ impl PerpInfo {
/// zero (if users could borrow against their perp balances they might now /// zero (if users could borrow against their perp balances they might now
/// be bankrupt) or suddenly increase a lot (if users could borrow against perp /// be bankrupt) or suddenly increase a lot (if users could borrow against perp
/// balances they could now borrow other assets). /// balances they could now borrow other assets).
///
/// Other markets may be liquid enough that we have enough confidence to allow
/// users to borrow against unsettled positive pnl to some extend. In these cases,
/// the pnl asset weights would be >0.
#[inline(always)] #[inline(always)]
pub fn health_contribution(&self, health_type: HealthType) -> I80F48 { pub fn health_contribution(&self, health_type: HealthType) -> I80F48 {
let c = self.uncapped_health_contribution(health_type); let contribution = self.unweighted_health_contribution(health_type);
if self.trusted_market { if contribution > 0 {
c let asset_weight = match health_type {
HealthType::Init => self.init_pnl_asset_weight,
HealthType::Maint => self.maint_pnl_asset_weight,
};
cm!(asset_weight * contribution)
} else { } else {
c.min(I80F48::ZERO) contribution
} }
} }
#[inline(always)] #[inline(always)]
pub fn uncapped_health_contribution(&self, health_type: HealthType) -> I80F48 { pub fn unweighted_health_contribution(&self, health_type: HealthType) -> I80F48 {
let order_execution_case = |orders_base_lots: i64, order_price: I80F48| { let order_execution_case = |orders_base_lots: i64, order_price: I80F48| {
let net_base_native = let net_base_native =
I80F48::from(cm!((self.base_lots + orders_base_lots) * self.base_lot_size)); I80F48::from(cm!((self.base_lots + orders_base_lots) * self.base_lot_size));
let (weight, base_price) = match (health_type, net_base_native.is_negative()) { let (weight, base_price) = match (health_type, net_base_native.is_negative()) {
(HealthType::Init, true) => (self.init_liab_weight, self.prices.liab(health_type)), (HealthType::Init, true) => {
(self.init_base_liab_weight, self.prices.liab(health_type))
}
(HealthType::Init, false) => { (HealthType::Init, false) => {
(self.init_asset_weight, self.prices.asset(health_type)) (self.init_base_asset_weight, self.prices.asset(health_type))
} }
(HealthType::Maint, true) => { (HealthType::Maint, true) => {
(self.maint_liab_weight, self.prices.liab(health_type)) (self.maint_base_liab_weight, self.prices.liab(health_type))
} }
(HealthType::Maint, false) => { (HealthType::Maint, false) => {
(self.maint_asset_weight, self.prices.asset(health_type)) (self.maint_base_asset_weight, self.prices.asset(health_type))
} }
}; };
// Total value of the order-execution adjusted base position // Total value of the order-execution adjusted base position
@ -437,10 +452,10 @@ impl HealthCache {
self.perp_infos.iter().any(|p| p.base_lots != 0) self.perp_infos.iter().any(|p| p.base_lots != 0)
} }
pub fn has_perp_positive_trusted_pnl_without_base_position(&self) -> bool { pub fn has_perp_positive_maint_pnl_without_base_position(&self) -> bool {
self.perp_infos self.perp_infos
.iter() .iter()
.any(|p| p.trusted_market && p.base_lots == 0 && p.quote > 0) .any(|p| p.maint_pnl_asset_weight > 0 && p.base_lots == 0 && p.quote > 0)
} }
pub fn has_perp_negative_pnl(&self) -> bool { pub fn has_perp_negative_pnl(&self) -> bool {
@ -473,7 +488,7 @@ impl HealthCache {
pub fn has_phase2_liquidatable(&self) -> bool { pub fn has_phase2_liquidatable(&self) -> bool {
self.has_spot_assets() && self.has_spot_borrows() self.has_spot_assets() && self.has_spot_borrows()
|| self.has_perp_base_positions() || self.has_perp_base_positions()
|| self.has_perp_positive_trusted_pnl_without_base_position() || self.has_perp_positive_maint_pnl_without_base_position()
} }
pub fn require_after_phase2_liquidation(&self) -> Result<()> { pub fn require_after_phase2_liquidation(&self) -> Result<()> {
@ -487,7 +502,7 @@ impl HealthCache {
MangoError::HasLiquidatablePerpBasePosition MangoError::HasLiquidatablePerpBasePosition
); );
require!( require!(
!self.has_perp_positive_trusted_pnl_without_base_position(), !self.has_perp_positive_maint_pnl_without_base_position(),
MangoError::HasLiquidatableTrustedPerpPnl MangoError::HasLiquidatableTrustedPerpPnl
); );
Ok(()) Ok(())
@ -636,12 +651,8 @@ impl HealthCache {
} }
for perp_info in self.perp_infos.iter() { for perp_info in self.perp_infos.iter() {
if perp_info.trusted_market { let positive_contrib = perp_info.health_contribution(health_type).max(I80F48::ZERO);
let positive_contrib = perp_info cm!(health += positive_contrib);
.uncapped_health_contribution(health_type)
.max(I80F48::ZERO);
cm!(health += positive_contrib);
}
} }
health health
} }
@ -842,7 +853,7 @@ mod tests {
oo1.data().native_coin_free = 3; oo1.data().native_coin_free = 3;
oo1.data().referrer_rebates_accrued = 2; oo1.data().referrer_rebates_accrued = 2;
let mut perp1 = mock_perp_market(group, oracle2.pubkey, 5.0, 9, 0.2, 0.1); let mut perp1 = mock_perp_market(group, oracle2.pubkey, 5.0, 9, (0.2, 0.1), (0.05, 0.02));
let perpaccount = account.ensure_perp_position(9, 1).unwrap().0; let perpaccount = account.ensure_perp_position(9, 1).unwrap().0;
perpaccount.record_trade(perp1.data(), 3, -I80F48::from(310u16)); perpaccount.record_trade(perp1.data(), 3, -I80F48::from(310u16));
perpaccount.bids_base_lots = 7; perpaccount.bids_base_lots = 7;
@ -966,7 +977,7 @@ mod tests {
oo2.data().native_pc_total = testcase.oo_1_3.0; oo2.data().native_pc_total = testcase.oo_1_3.0;
oo2.data().native_coin_total = testcase.oo_1_3.1; oo2.data().native_coin_total = testcase.oo_1_3.1;
let mut perp1 = mock_perp_market(group, oracle2.pubkey, 5.0, 9, 0.2, 0.1); let mut perp1 = mock_perp_market(group, oracle2.pubkey, 5.0, 9, (0.2, 0.1), (0.05, 0.02));
let perpaccount = account.ensure_perp_position(9, 1).unwrap().0; let perpaccount = account.ensure_perp_position(9, 1).unwrap().0;
perpaccount.record_trade( perpaccount.record_trade(
perp1.data(), perp1.data(),
@ -1033,27 +1044,27 @@ mod tests {
..Default::default() ..Default::default()
}, },
TestHealth1Case { TestHealth1Case {
// 2 // 2: weighted positive perp pnl
perp1: (-1, 100, 0, 0), perp1: (-1, 100, 0, 0),
expected_health: 0.0, expected_health: 0.95 * (100.0 - 1.2 * 1.0 * base_lots_to_quote),
..Default::default() ..Default::default()
}, },
TestHealth1Case { TestHealth1Case {
// 3 // 3: negative perp pnl is not weighted
perp1: (1, -100, 0, 0), perp1: (1, -100, 0, 0),
expected_health: -100.0 + 0.8 * 1.0 * base_lots_to_quote, expected_health: -100.0 + 0.8 * 1.0 * base_lots_to_quote,
..Default::default() ..Default::default()
}, },
TestHealth1Case { TestHealth1Case {
// 4 // 4: perp health
perp1: (10, 100, 0, 0), perp1: (10, 100, 0, 0),
expected_health: 0.0, expected_health: 0.95 * (100.0 + 0.8 * 10.0 * base_lots_to_quote),
..Default::default() ..Default::default()
}, },
TestHealth1Case { TestHealth1Case {
// 5 // 5: perp health
perp1: (30, -100, 0, 0), perp1: (30, -100, 0, 0),
expected_health: 0.0, expected_health: 0.95 * (-100.0 + 0.8 * 30.0 * base_lots_to_quote),
..Default::default() ..Default::default()
}, },
TestHealth1Case { // 6, reserved oo funds TestHealth1Case { // 6, reserved oo funds

View File

@ -310,12 +310,13 @@ impl HealthCache {
let prices = &perp_info.prices; let prices = &perp_info.prices;
let base_lot_size = I80F48::from(perp_info.base_lot_size); let base_lot_size = I80F48::from(perp_info.base_lot_size);
// If the price is sufficiently good then health will just increase from trading // If the price is sufficiently good then health will just increase from trading.
// TODO: This is not actually correct, since perp health for untrusted markets can't go above 0 // It's ok to ignore the pnl_asset_weight here because we'll jump out early if this
// slope is >=0, and the extra asset weight would just decrease it.
let final_health_slope = if direction == 1 { let final_health_slope = if direction == 1 {
perp_info.init_asset_weight * prices.asset(health_type) - price perp_info.init_base_asset_weight * prices.asset(health_type) - price
} else { } else {
price - perp_info.init_liab_weight * prices.liab(health_type) price - perp_info.init_base_liab_weight * prices.liab(health_type)
}; };
if final_health_slope >= 0 { if final_health_slope >= 0 {
return Ok(i64::MAX); return Ok(i64::MAX);
@ -374,8 +375,7 @@ impl HealthCache {
let perp_info = &start_cache.perp_infos[perp_info_index]; let perp_info = &start_cache.perp_infos[perp_info_index];
let start_health_uncapped = start_health let start_health_uncapped = start_health
- perp_info.health_contribution(HealthType::Init) - perp_info.health_contribution(HealthType::Init)
+ perp_info.uncapped_health_contribution(HealthType::Init); + perp_info.unweighted_health_contribution(HealthType::Init);
// We add 1 here because health is computed for truncated base_lots and we want to guarantee // We add 1 here because health is computed for truncated base_lots and we want to guarantee
// zero_health_ratio <= 0. // zero_health_ratio <= 0.
let zero_health_amount = case1_start_i80f48 let zero_health_amount = case1_start_i80f48
@ -938,10 +938,12 @@ mod tests {
let base_lot_size = 100; let base_lot_size = 100;
let default_perp_info = |x| PerpInfo { let default_perp_info = |x| PerpInfo {
perp_market_index: 0, perp_market_index: 0,
maint_asset_weight: I80F48::from_num(1.0 - x), maint_base_asset_weight: I80F48::from_num(1.0 - x),
init_asset_weight: I80F48::from_num(1.0 - x), init_base_asset_weight: I80F48::from_num(1.0 - x),
maint_liab_weight: I80F48::from_num(1.0 + x), maint_base_liab_weight: I80F48::from_num(1.0 + x),
init_liab_weight: I80F48::from_num(1.0 + x), init_base_liab_weight: I80F48::from_num(1.0 + x),
maint_pnl_asset_weight: I80F48::from_num(0.6),
init_pnl_asset_weight: I80F48::from_num(0.6),
base_lot_size, base_lot_size,
base_lots: 0, base_lots: 0,
bids_base_lots: 0, bids_base_lots: 0,
@ -949,7 +951,6 @@ mod tests {
quote: I80F48::ZERO, quote: I80F48::ZERO,
prices: Prices::new_single_price(I80F48::from_num(2.0)), prices: Prices::new_single_price(I80F48::from_num(2.0)),
has_open_orders: false, has_open_orders: false,
trusted_market: false,
}; };
let health_cache = HealthCache { let health_cache = HealthCache {
@ -1088,7 +1089,7 @@ mod tests {
) )
.unwrap(); .unwrap();
let mut perp1 = mock_perp_market(group, oracle1.pubkey, 1.0, 9, 0.2, 0.1); let mut perp1 = mock_perp_market(group, oracle1.pubkey, 1.0, 9, (0.2, 0.1), (0.05, 0.02));
perp1.data().long_funding = I80F48::from_num(10.1); perp1.data().long_funding = I80F48::from_num(10.1);
let perpaccount = account.ensure_perp_position(9, 1).unwrap().0; let perpaccount = account.ensure_perp_position(9, 1).unwrap().0;
perpaccount.record_trade(perp1.data(), 10, I80F48::from(-110)); perpaccount.record_trade(perp1.data(), 10, I80F48::from(-110));
@ -1126,8 +1127,8 @@ mod tests {
let mut oo1 = TestAccount::<OpenOrders>::new_zeroed(); let mut oo1 = TestAccount::<OpenOrders>::new_zeroed();
let mut perp1 = mock_perp_market(group, oracle1.pubkey, 1.0, 9, 0.2, 0.1); let mut perp1 = mock_perp_market(group, oracle1.pubkey, 1.0, 9, (0.2, 0.1), (0.05, 0.02));
let mut perp2 = mock_perp_market(group, oracle2.pubkey, 5.0, 8, 0.2, 0.1); let mut perp2 = mock_perp_market(group, oracle2.pubkey, 5.0, 8, (0.2, 0.1), (0.05, 0.02));
let oracle1_account_info = oracle1.as_account_info(); let oracle1_account_info = oracle1.as_account_info();
let oracle2_account_info = oracle2.as_account_info(); let oracle2_account_info = oracle2.as_account_info();
@ -1180,7 +1181,7 @@ mod tests {
) )
.unwrap(); .unwrap();
let mut perp1 = mock_perp_market(group, oracle1.pubkey, 1.0, 9, 0.2, 0.1); let mut perp1 = mock_perp_market(group, oracle1.pubkey, 1.0, 9, (0.2, 0.1), (0.05, 0.02));
perp1.data().stable_price_model.stable_price = 0.5; perp1.data().stable_price_model.stable_price = 0.5;
let perpaccount = account3.ensure_perp_position(9, 1).unwrap().0; let perpaccount = account3.ensure_perp_position(9, 1).unwrap().0;
perpaccount.record_trade(perp1.data(), 10, I80F48::from(-100)); perpaccount.record_trade(perp1.data(), 10, I80F48::from(-100));

View File

@ -108,17 +108,19 @@ pub fn mock_perp_market(
oracle: Pubkey, oracle: Pubkey,
price: f64, price: f64,
market_index: PerpMarketIndex, market_index: PerpMarketIndex,
init_weights: f64, base_weights: (f64, f64),
maint_weights: f64, pnl_weights: (f64, f64),
) -> TestAccount<PerpMarket> { ) -> TestAccount<PerpMarket> {
let mut pm = TestAccount::<PerpMarket>::new_zeroed(); let mut pm = TestAccount::<PerpMarket>::new_zeroed();
pm.data().group = group; pm.data().group = group;
pm.data().oracle = oracle; pm.data().oracle = oracle;
pm.data().perp_market_index = market_index; pm.data().perp_market_index = market_index;
pm.data().init_asset_weight = I80F48::from_num(1.0 - init_weights); pm.data().init_base_asset_weight = I80F48::from_num(1.0 - base_weights.0);
pm.data().init_liab_weight = I80F48::from_num(1.0 + init_weights); pm.data().init_base_liab_weight = I80F48::from_num(1.0 + base_weights.0);
pm.data().maint_asset_weight = I80F48::from_num(1.0 - maint_weights); pm.data().maint_base_asset_weight = I80F48::from_num(1.0 - base_weights.1);
pm.data().maint_liab_weight = I80F48::from_num(1.0 + maint_weights); pm.data().maint_base_liab_weight = I80F48::from_num(1.0 + base_weights.1);
pm.data().init_pnl_asset_weight = I80F48::from_num(1.0 - pnl_weights.0);
pm.data().maint_pnl_asset_weight = I80F48::from_num(1.0 - pnl_weights.1);
pm.data().quote_lot_size = 100; pm.data().quote_lot_size = 100;
pm.data().base_lot_size = 10; pm.data().base_lot_size = 10;
pm.data().stable_price_model.reset_to_price(price, 0); pm.data().stable_price_model.reset_to_price(price, 0);

View File

@ -56,10 +56,12 @@ pub fn perp_create_market(
base_decimals: u8, base_decimals: u8,
quote_lot_size: i64, quote_lot_size: i64,
base_lot_size: i64, base_lot_size: i64,
maint_asset_weight: f32, maint_base_asset_weight: f32,
init_asset_weight: f32, init_base_asset_weight: f32,
maint_liab_weight: f32, maint_base_liab_weight: f32,
init_liab_weight: f32, init_base_liab_weight: f32,
maint_pnl_asset_weight: f32,
init_pnl_asset_weight: f32,
liquidation_fee: f32, liquidation_fee: f32,
maker_fee: f32, maker_fee: f32,
taker_fee: f32, taker_fee: f32,
@ -67,7 +69,6 @@ pub fn perp_create_market(
max_funding: f32, max_funding: f32,
impact_quantity: i64, impact_quantity: i64,
group_insurance_fund: bool, group_insurance_fund: bool,
trusted_market: bool,
fee_penalty: f32, fee_penalty: f32,
settle_fee_flat: f32, settle_fee_flat: f32,
settle_fee_amount_threshold: f32, settle_fee_amount_threshold: f32,
@ -93,7 +94,7 @@ pub fn perp_create_market(
group: ctx.accounts.group.key(), group: ctx.accounts.group.key(),
settle_token_index, settle_token_index,
perp_market_index, perp_market_index,
trusted_market: u8::from(trusted_market), blocked1: 0,
group_insurance_fund: u8::from(group_insurance_fund), group_insurance_fund: u8::from(group_insurance_fund),
bump: *ctx.bumps.get("perp_market").ok_or(MangoError::SomeError)?, bump: *ctx.bumps.get("perp_market").ok_or(MangoError::SomeError)?,
base_decimals, base_decimals,
@ -106,10 +107,10 @@ pub fn perp_create_market(
stable_price_model: StablePriceModel::default(), stable_price_model: StablePriceModel::default(),
quote_lot_size, quote_lot_size,
base_lot_size, base_lot_size,
maint_asset_weight: I80F48::from_num(maint_asset_weight), maint_base_asset_weight: I80F48::from_num(maint_base_asset_weight),
init_asset_weight: I80F48::from_num(init_asset_weight), init_base_asset_weight: I80F48::from_num(init_base_asset_weight),
maint_liab_weight: I80F48::from_num(maint_liab_weight), maint_base_liab_weight: I80F48::from_num(maint_base_liab_weight),
init_liab_weight: I80F48::from_num(init_liab_weight), init_base_liab_weight: I80F48::from_num(init_base_liab_weight),
open_interest: 0, open_interest: 0,
seq_num: 0, seq_num: 0,
registration_time: now_ts, registration_time: now_ts,
@ -132,7 +133,10 @@ pub fn perp_create_market(
padding3: Default::default(), padding3: Default::default(),
settle_pnl_limit_window_size_ts, settle_pnl_limit_window_size_ts,
reduce_only: 0, reduce_only: 0,
reserved: [0; 1943], padding4: Default::default(),
maint_pnl_asset_weight: I80F48::from_num(maint_pnl_asset_weight),
init_pnl_asset_weight: I80F48::from_num(init_pnl_asset_weight),
reserved: [0; 1904],
}; };
let oracle_price = let oracle_price =

View File

@ -28,10 +28,12 @@ pub fn perp_edit_market(
oracle_opt: Option<Pubkey>, oracle_opt: Option<Pubkey>,
oracle_config_opt: Option<OracleConfigParams>, oracle_config_opt: Option<OracleConfigParams>,
base_decimals_opt: Option<u8>, base_decimals_opt: Option<u8>,
maint_asset_weight_opt: Option<f32>, maint_base_asset_weight_opt: Option<f32>,
init_asset_weight_opt: Option<f32>, init_base_asset_weight_opt: Option<f32>,
maint_liab_weight_opt: Option<f32>, maint_base_liab_weight_opt: Option<f32>,
init_liab_weight_opt: Option<f32>, init_base_liab_weight_opt: Option<f32>,
maint_pnl_asset_weight_opt: Option<f32>,
init_pnl_asset_weight_opt: Option<f32>,
liquidation_fee_opt: Option<f32>, liquidation_fee_opt: Option<f32>,
maker_fee_opt: Option<f32>, maker_fee_opt: Option<f32>,
taker_fee_opt: Option<f32>, taker_fee_opt: Option<f32>,
@ -39,7 +41,6 @@ pub fn perp_edit_market(
max_funding_opt: Option<f32>, max_funding_opt: Option<f32>,
impact_quantity_opt: Option<i64>, impact_quantity_opt: Option<i64>,
group_insurance_fund_opt: Option<bool>, group_insurance_fund_opt: Option<bool>,
trusted_market_opt: Option<bool>,
fee_penalty_opt: Option<f32>, fee_penalty_opt: Option<f32>,
settle_fee_flat_opt: Option<f32>, settle_fee_flat_opt: Option<f32>,
settle_fee_amount_threshold_opt: Option<f32>, settle_fee_amount_threshold_opt: Option<f32>,
@ -82,17 +83,23 @@ pub fn perp_edit_market(
// quote_lot_size // quote_lot_size
// base_lot_size // base_lot_size
if let Some(maint_asset_weight) = maint_asset_weight_opt { if let Some(maint_base_asset_weight) = maint_base_asset_weight_opt {
perp_market.maint_asset_weight = I80F48::from_num(maint_asset_weight); perp_market.maint_base_asset_weight = I80F48::from_num(maint_base_asset_weight);
} }
if let Some(init_asset_weight) = init_asset_weight_opt { if let Some(init_base_asset_weight) = init_base_asset_weight_opt {
perp_market.init_asset_weight = I80F48::from_num(init_asset_weight); perp_market.init_base_asset_weight = I80F48::from_num(init_base_asset_weight);
} }
if let Some(maint_liab_weight) = maint_liab_weight_opt { if let Some(maint_base_liab_weight) = maint_base_liab_weight_opt {
perp_market.maint_liab_weight = I80F48::from_num(maint_liab_weight); perp_market.maint_base_liab_weight = I80F48::from_num(maint_base_liab_weight);
} }
if let Some(init_liab_weight) = init_liab_weight_opt { if let Some(init_base_liab_weight) = init_base_liab_weight_opt {
perp_market.init_liab_weight = I80F48::from_num(init_liab_weight); perp_market.init_base_liab_weight = I80F48::from_num(init_base_liab_weight);
}
if let Some(maint_pnl_asset_weight) = maint_pnl_asset_weight_opt {
perp_market.maint_pnl_asset_weight = I80F48::from_num(maint_pnl_asset_weight);
}
if let Some(init_pnl_asset_weight) = init_pnl_asset_weight_opt {
perp_market.init_pnl_asset_weight = I80F48::from_num(init_pnl_asset_weight);
} }
if let Some(liquidation_fee) = liquidation_fee_opt { if let Some(liquidation_fee) = liquidation_fee_opt {
perp_market.liquidation_fee = I80F48::from_num(liquidation_fee); perp_market.liquidation_fee = I80F48::from_num(liquidation_fee);
@ -140,9 +147,6 @@ pub fn perp_edit_market(
if let Some(group_insurance_fund) = group_insurance_fund_opt { if let Some(group_insurance_fund) = group_insurance_fund_opt {
perp_market.set_elligible_for_group_insurance_fund(group_insurance_fund); perp_market.set_elligible_for_group_insurance_fund(group_insurance_fund);
} }
if let Some(trusted_market) = trusted_market_opt {
perp_market.trusted_market = u8::from(trusted_market);
}
if let Some(settle_fee_flat) = settle_fee_flat_opt { if let Some(settle_fee_flat) = settle_fee_flat_opt {
perp_market.settle_fee_flat = settle_fee_flat; perp_market.settle_fee_flat = settle_fee_flat;

View File

@ -99,63 +99,62 @@ pub fn perp_liq_base_position(
// Take over the liqee's base in exchange for quote // Take over the liqee's base in exchange for quote
require_msg!(liqee_base_lots != 0, "liqee base position is zero"); require_msg!(liqee_base_lots != 0, "liqee base position is zero");
let (base_transfer, quote_transfer) = let (base_transfer, quote_transfer) = if liqee_base_lots > 0 {
if liqee_base_lots > 0 { require_msg!(
require_msg!( max_base_transfer > 0,
max_base_transfer > 0, "max_base_transfer must be positive when liqee's base_position is positive"
"max_base_transfer must be positive when liqee's base_position is positive" );
);
// health gets reduced by `base * price * perp_init_asset_weight` // health gets reduced by `base * price * perp_init_asset_weight`
// and increased by `base * price * (1 - liq_fee) * quote_init_asset_weight` // and increased by `base * price * (1 - liq_fee) * quote_init_asset_weight`
let quote_init_asset_weight = I80F48::ONE; let quote_init_asset_weight = I80F48::ONE;
let fee_factor = cm!(I80F48::ONE - perp_market.liquidation_fee); let fee_factor = cm!(I80F48::ONE - perp_market.liquidation_fee);
let health_per_lot = cm!(price_per_lot let health_per_lot = cm!(price_per_lot
* (-perp_market.init_asset_weight + quote_init_asset_weight * fee_factor)); * (-perp_market.init_base_asset_weight + quote_init_asset_weight * fee_factor));
// number of lots to transfer to bring health to zero, rounded up // number of lots to transfer to bring health to zero, rounded up
let base_transfer_for_zero: i64 = cm!(-liqee_init_health / health_per_lot) let base_transfer_for_zero: i64 = cm!(-liqee_init_health / health_per_lot)
.checked_ceil() .checked_ceil()
.unwrap() .unwrap()
.checked_to_num() .checked_to_num()
.unwrap(); .unwrap();
let base_transfer = base_transfer_for_zero let base_transfer = base_transfer_for_zero
.min(liqee_base_lots) .min(liqee_base_lots)
.min(max_base_transfer) .min(max_base_transfer)
.max(0); .max(0);
let quote_transfer = cm!(-I80F48::from(base_transfer) * price_per_lot * fee_factor); let quote_transfer = cm!(-I80F48::from(base_transfer) * price_per_lot * fee_factor);
(base_transfer, quote_transfer) // base > 0, quote < 0 (base_transfer, quote_transfer) // base > 0, quote < 0
} else { } else {
// liqee_base_lots < 0 // liqee_base_lots < 0
require_msg!( require_msg!(
max_base_transfer < 0, max_base_transfer < 0,
"max_base_transfer must be negative when liqee's base_position is positive" "max_base_transfer must be negative when liqee's base_position is positive"
); );
// health gets increased by `base * price * perp_init_liab_weight` // health gets increased by `base * price * perp_init_liab_weight`
// and reduced by `base * price * (1 + liq_fee) * quote_init_liab_weight` // and reduced by `base * price * (1 + liq_fee) * quote_init_liab_weight`
let quote_init_liab_weight = I80F48::ONE; let quote_init_liab_weight = I80F48::ONE;
let fee_factor = cm!(I80F48::ONE + perp_market.liquidation_fee); let fee_factor = cm!(I80F48::ONE + perp_market.liquidation_fee);
let health_per_lot = cm!(price_per_lot let health_per_lot = cm!(price_per_lot
* (perp_market.init_liab_weight - quote_init_liab_weight * fee_factor)); * (perp_market.init_base_liab_weight - quote_init_liab_weight * fee_factor));
// (negative) number of lots to transfer to bring health to zero, rounded away from zero // (negative) number of lots to transfer to bring health to zero, rounded away from zero
let base_transfer_for_zero: i64 = cm!(liqee_init_health / health_per_lot) let base_transfer_for_zero: i64 = cm!(liqee_init_health / health_per_lot)
.checked_floor() .checked_floor()
.unwrap() .unwrap()
.checked_to_num() .checked_to_num()
.unwrap(); .unwrap();
let base_transfer = base_transfer_for_zero let base_transfer = base_transfer_for_zero
.max(liqee_base_lots) .max(liqee_base_lots)
.max(max_base_transfer) .max(max_base_transfer)
.min(0); .min(0);
let quote_transfer = cm!(-I80F48::from(base_transfer) * price_per_lot * fee_factor); let quote_transfer = cm!(-I80F48::from(base_transfer) * price_per_lot * fee_factor);
(base_transfer, quote_transfer) // base < 0, quote > 0 (base_transfer, quote_transfer) // base < 0, quote > 0
}; };
// Execute the transfer. This is essentially a forced trade and updates the // Execute the transfer. This is essentially a forced trade and updates the
// liqee and liqors entry and break even prices. // liqee and liqors entry and break even prices.

View File

@ -434,10 +434,12 @@ pub mod mango_v4 {
base_decimals: u8, base_decimals: u8,
quote_lot_size: i64, quote_lot_size: i64,
base_lot_size: i64, base_lot_size: i64,
maint_asset_weight: f32, maint_base_asset_weight: f32,
init_asset_weight: f32, init_base_asset_weight: f32,
maint_liab_weight: f32, maint_base_liab_weight: f32,
init_liab_weight: f32, init_base_liab_weight: f32,
maint_pnl_asset_weight: f32,
init_pnl_asset_weight: f32,
liquidation_fee: f32, liquidation_fee: f32,
maker_fee: f32, maker_fee: f32,
taker_fee: f32, taker_fee: f32,
@ -445,7 +447,6 @@ pub mod mango_v4 {
max_funding: f32, max_funding: f32,
impact_quantity: i64, impact_quantity: i64,
group_insurance_fund: bool, group_insurance_fund: bool,
trusted_market: bool,
fee_penalty: f32, fee_penalty: f32,
settle_fee_flat: f32, settle_fee_flat: f32,
settle_fee_amount_threshold: f32, settle_fee_amount_threshold: f32,
@ -463,10 +464,12 @@ pub mod mango_v4 {
base_decimals, base_decimals,
quote_lot_size, quote_lot_size,
base_lot_size, base_lot_size,
maint_asset_weight, maint_base_asset_weight,
init_asset_weight, init_base_asset_weight,
maint_liab_weight, maint_base_liab_weight,
init_liab_weight, init_base_liab_weight,
maint_pnl_asset_weight,
init_pnl_asset_weight,
liquidation_fee, liquidation_fee,
maker_fee, maker_fee,
taker_fee, taker_fee,
@ -474,7 +477,6 @@ pub mod mango_v4 {
max_funding, max_funding,
impact_quantity, impact_quantity,
group_insurance_fund, group_insurance_fund,
trusted_market,
fee_penalty, fee_penalty,
settle_fee_flat, settle_fee_flat,
settle_fee_amount_threshold, settle_fee_amount_threshold,
@ -490,10 +492,12 @@ pub mod mango_v4 {
oracle_opt: Option<Pubkey>, oracle_opt: Option<Pubkey>,
oracle_config_opt: Option<OracleConfigParams>, oracle_config_opt: Option<OracleConfigParams>,
base_decimals_opt: Option<u8>, base_decimals_opt: Option<u8>,
maint_asset_weight_opt: Option<f32>, maint_base_asset_weight_opt: Option<f32>,
init_asset_weight_opt: Option<f32>, init_base_asset_weight_opt: Option<f32>,
maint_liab_weight_opt: Option<f32>, maint_base_liab_weight_opt: Option<f32>,
init_liab_weight_opt: Option<f32>, init_base_liab_weight_opt: Option<f32>,
maint_pnl_asset_weight_opt: Option<f32>,
init_pnl_asset_weight_opt: Option<f32>,
liquidation_fee_opt: Option<f32>, liquidation_fee_opt: Option<f32>,
maker_fee_opt: Option<f32>, maker_fee_opt: Option<f32>,
taker_fee_opt: Option<f32>, taker_fee_opt: Option<f32>,
@ -501,7 +505,6 @@ pub mod mango_v4 {
max_funding_opt: Option<f32>, max_funding_opt: Option<f32>,
impact_quantity_opt: Option<i64>, impact_quantity_opt: Option<i64>,
group_insurance_fund_opt: Option<bool>, group_insurance_fund_opt: Option<bool>,
trusted_market_opt: Option<bool>,
fee_penalty_opt: Option<f32>, fee_penalty_opt: Option<f32>,
settle_fee_flat_opt: Option<f32>, settle_fee_flat_opt: Option<f32>,
settle_fee_amount_threshold_opt: Option<f32>, settle_fee_amount_threshold_opt: Option<f32>,
@ -518,10 +521,12 @@ pub mod mango_v4 {
oracle_opt, oracle_opt,
oracle_config_opt, oracle_config_opt,
base_decimals_opt, base_decimals_opt,
maint_asset_weight_opt, maint_base_asset_weight_opt,
init_asset_weight_opt, init_base_asset_weight_opt,
maint_liab_weight_opt, maint_base_liab_weight_opt,
init_liab_weight_opt, init_base_liab_weight_opt,
maint_pnl_asset_weight_opt,
init_pnl_asset_weight_opt,
liquidation_fee_opt, liquidation_fee_opt,
maker_fee_opt, maker_fee_opt,
taker_fee_opt, taker_fee_opt,
@ -529,7 +534,6 @@ pub mod mango_v4 {
max_funding_opt, max_funding_opt,
impact_quantity_opt, impact_quantity_opt,
group_insurance_fund_opt, group_insurance_fund_opt,
trusted_market_opt,
fee_penalty_opt, fee_penalty_opt,
settle_fee_flat_opt, settle_fee_flat_opt,
settle_fee_amount_threshold_opt, settle_fee_amount_threshold_opt,

View File

@ -88,10 +88,10 @@ mod tests {
let mut perp_market = PerpMarket::zeroed(); let mut perp_market = PerpMarket::zeroed();
perp_market.quote_lot_size = 1; perp_market.quote_lot_size = 1;
perp_market.base_lot_size = 1; perp_market.base_lot_size = 1;
perp_market.maint_asset_weight = I80F48::ONE; perp_market.maint_base_asset_weight = I80F48::ONE;
perp_market.maint_liab_weight = I80F48::ONE; perp_market.maint_base_liab_weight = I80F48::ONE;
perp_market.init_asset_weight = I80F48::ONE; perp_market.init_base_asset_weight = I80F48::ONE;
perp_market.init_liab_weight = I80F48::ONE; perp_market.init_base_liab_weight = I80F48::ONE;
(perp_market, oracle_price, event_queue, book) (perp_market, oracle_price, event_queue, book)
} }

View File

@ -26,8 +26,8 @@ pub struct PerpMarket {
/// Lookup indices /// Lookup indices
pub perp_market_index: PerpMarketIndex, pub perp_market_index: PerpMarketIndex,
/// May this market contribute positive values to health? // Used to store trusted_market here
pub trusted_market: u8, pub blocked1: u8,
/// Is this market covered by the group insurance fund? /// Is this market covered by the group insurance fund?
pub group_insurance_fund: u8, pub group_insurance_fund: u8,
@ -56,10 +56,10 @@ pub struct PerpMarket {
// These weights apply to the base asset, the quote token is always assumed to be // These weights apply to the base asset, the quote token is always assumed to be
// the health-reference token and have 1 for price and weights // the health-reference token and have 1 for price and weights
pub maint_asset_weight: I80F48, pub maint_base_asset_weight: I80F48,
pub init_asset_weight: I80F48, pub init_base_asset_weight: I80F48,
pub maint_liab_weight: I80F48, pub maint_base_liab_weight: I80F48,
pub init_liab_weight: I80F48, pub init_base_liab_weight: I80F48,
pub open_interest: i64, pub open_interest: i64,
@ -114,8 +114,12 @@ pub struct PerpMarket {
pub settle_pnl_limit_window_size_ts: u64, pub settle_pnl_limit_window_size_ts: u64,
pub reduce_only: u8, pub reduce_only: u8,
pub padding4: [u8; 7],
pub reserved: [u8; 1943], pub maint_pnl_asset_weight: I80F48,
pub init_pnl_asset_weight: I80F48,
pub reserved: [u8; 1904],
} }
const_assert_eq!( const_assert_eq!(
@ -149,7 +153,9 @@ const_assert_eq!(
+ 8 + 8
+ 8 + 8
+ 1 + 1
+ 1943 + 7
+ 2 * 16
+ 1904
); );
const_assert_eq!(size_of::<PerpMarket>(), 2808); const_assert_eq!(size_of::<PerpMarket>(), 2808);
const_assert_eq!(size_of::<PerpMarket>() % 8, 0); const_assert_eq!(size_of::<PerpMarket>() % 8, 0);
@ -173,10 +179,6 @@ impl PerpMarket {
self.group_insurance_fund = u8::from(v); self.group_insurance_fund = u8::from(v);
} }
pub fn trusted_market(&self) -> bool {
self.trusted_market == 1
}
pub fn settle_pnl_limit_factor(&self) -> I80F48 { pub fn settle_pnl_limit_factor(&self) -> I80F48 {
I80F48::from_num(self.settle_pnl_limit_factor) I80F48::from_num(self.settle_pnl_limit_factor)
} }
@ -288,8 +290,8 @@ impl PerpMarket {
oracle_price: I80F48, oracle_price: I80F48,
) -> bool { ) -> bool {
match side { match side {
Side::Bid => native_price <= cm!(self.maint_liab_weight * oracle_price), Side::Bid => native_price <= cm!(self.maint_base_liab_weight * oracle_price),
Side::Ask => native_price >= cm!(self.maint_asset_weight * oracle_price), Side::Ask => native_price >= cm!(self.maint_base_asset_weight * oracle_price),
} }
} }
@ -319,7 +321,7 @@ impl PerpMarket {
group: Pubkey::new_unique(), group: Pubkey::new_unique(),
settle_token_index: 0, settle_token_index: 0,
perp_market_index: 0, perp_market_index: 0,
trusted_market: 0, blocked1: 0,
group_insurance_fund: 0, group_insurance_fund: 0,
bump: 0, bump: 0,
base_decimals: 0, base_decimals: 0,
@ -336,10 +338,10 @@ impl PerpMarket {
stable_price_model: StablePriceModel::default(), stable_price_model: StablePriceModel::default(),
quote_lot_size: 1, quote_lot_size: 1,
base_lot_size: 1, base_lot_size: 1,
maint_asset_weight: I80F48::from(1), maint_base_asset_weight: I80F48::from(1),
init_asset_weight: I80F48::from(1), init_base_asset_weight: I80F48::from(1),
maint_liab_weight: I80F48::from(1), maint_base_liab_weight: I80F48::from(1),
init_liab_weight: I80F48::from(1), init_base_liab_weight: I80F48::from(1),
open_interest: 0, open_interest: 0,
seq_num: 0, seq_num: 0,
registration_time: 0, registration_time: 0,
@ -362,7 +364,10 @@ impl PerpMarket {
padding3: Default::default(), padding3: Default::default(),
settle_pnl_limit_window_size_ts: 24 * 60 * 60, settle_pnl_limit_window_size_ts: 24 * 60 * 60,
reduce_only: 0, reduce_only: 0,
reserved: [0; 1943], padding4: Default::default(),
maint_pnl_asset_weight: I80F48::ONE,
init_pnl_asset_weight: I80F48::ONE,
reserved: [0; 1904],
} }
} }
} }

View File

@ -2543,15 +2543,16 @@ pub struct PerpCreateMarketInstruction {
pub base_decimals: u8, pub base_decimals: u8,
pub quote_lot_size: i64, pub quote_lot_size: i64,
pub base_lot_size: i64, pub base_lot_size: i64,
pub maint_asset_weight: f32, pub maint_base_asset_weight: f32,
pub init_asset_weight: f32, pub init_base_asset_weight: f32,
pub maint_liab_weight: f32, pub maint_base_liab_weight: f32,
pub init_liab_weight: f32, pub init_base_liab_weight: f32,
pub maint_pnl_asset_weight: f32,
pub init_pnl_asset_weight: f32,
pub liquidation_fee: f32, pub liquidation_fee: f32,
pub maker_fee: f32, pub maker_fee: f32,
pub taker_fee: f32, pub taker_fee: f32,
pub group_insurance_fund: bool, pub group_insurance_fund: bool,
pub trusted_market: bool,
pub fee_penalty: f32, pub fee_penalty: f32,
pub settle_fee_flat: f32, pub settle_fee_flat: f32,
pub settle_fee_amount_threshold: f32, pub settle_fee_amount_threshold: f32,
@ -2599,10 +2600,12 @@ impl ClientInstruction for PerpCreateMarketInstruction {
perp_market_index: self.perp_market_index, perp_market_index: self.perp_market_index,
quote_lot_size: self.quote_lot_size, quote_lot_size: self.quote_lot_size,
base_lot_size: self.base_lot_size, base_lot_size: self.base_lot_size,
maint_asset_weight: self.maint_asset_weight, maint_base_asset_weight: self.maint_base_asset_weight,
init_asset_weight: self.init_asset_weight, init_base_asset_weight: self.init_base_asset_weight,
maint_liab_weight: self.maint_liab_weight, maint_base_liab_weight: self.maint_base_liab_weight,
init_liab_weight: self.init_liab_weight, init_base_liab_weight: self.init_base_liab_weight,
maint_pnl_asset_weight: self.maint_pnl_asset_weight,
init_pnl_asset_weight: self.init_pnl_asset_weight,
liquidation_fee: self.liquidation_fee, liquidation_fee: self.liquidation_fee,
maker_fee: self.maker_fee, maker_fee: self.maker_fee,
taker_fee: self.taker_fee, taker_fee: self.taker_fee,
@ -2611,7 +2614,6 @@ impl ClientInstruction for PerpCreateMarketInstruction {
impact_quantity: 100, impact_quantity: 100,
base_decimals: self.base_decimals, base_decimals: self.base_decimals,
group_insurance_fund: self.group_insurance_fund, group_insurance_fund: self.group_insurance_fund,
trusted_market: self.trusted_market,
fee_penalty: self.fee_penalty, fee_penalty: self.fee_penalty,
settle_fee_flat: self.settle_fee_flat, settle_fee_flat: self.settle_fee_flat,
settle_fee_amount_threshold: self.settle_fee_amount_threshold, settle_fee_amount_threshold: self.settle_fee_amount_threshold,
@ -2656,10 +2658,12 @@ fn perp_edit_instruction_default() -> mango_v4::instruction::PerpEditMarket {
oracle_opt: None, oracle_opt: None,
oracle_config_opt: None, oracle_config_opt: None,
base_decimals_opt: None, base_decimals_opt: None,
maint_asset_weight_opt: None, maint_base_asset_weight_opt: None,
init_asset_weight_opt: None, init_base_asset_weight_opt: None,
maint_liab_weight_opt: None, maint_base_liab_weight_opt: None,
init_liab_weight_opt: None, init_base_liab_weight_opt: None,
maint_pnl_asset_weight_opt: None,
init_pnl_asset_weight_opt: None,
liquidation_fee_opt: None, liquidation_fee_opt: None,
maker_fee_opt: None, maker_fee_opt: None,
taker_fee_opt: None, taker_fee_opt: None,
@ -2667,7 +2671,6 @@ fn perp_edit_instruction_default() -> mango_v4::instruction::PerpEditMarket {
max_funding_opt: None, max_funding_opt: None,
impact_quantity_opt: None, impact_quantity_opt: None,
group_insurance_fund_opt: None, group_insurance_fund_opt: None,
trusted_market_opt: None,
fee_penalty_opt: None, fee_penalty_opt: None,
settle_fee_flat_opt: None, settle_fee_flat_opt: None,
settle_fee_amount_threshold_opt: None, settle_fee_amount_threshold_opt: None,

View File

@ -215,10 +215,10 @@ async fn test_health_compute_perp() -> Result<(), TransportError> {
perp_market_index: perp_market_index as PerpMarketIndex, perp_market_index: perp_market_index as PerpMarketIndex,
quote_lot_size: 10, quote_lot_size: 10,
base_lot_size: 100, base_lot_size: 100,
maint_asset_weight: 0.975, maint_base_asset_weight: 0.975,
init_asset_weight: 0.95, init_base_asset_weight: 0.95,
maint_liab_weight: 1.025, maint_base_liab_weight: 1.025,
init_liab_weight: 1.05, init_base_liab_weight: 1.05,
liquidation_fee: 0.012, liquidation_fee: 0.012,
maker_fee: 0.0002, maker_fee: 0.0002,
taker_fee: 0.000, taker_fee: 0.000,

View File

@ -56,10 +56,10 @@ async fn test_liq_perps_force_cancel() -> Result<(), TransportError> {
perp_market_index: 0, perp_market_index: 0,
quote_lot_size: 10, quote_lot_size: 10,
base_lot_size: 100, base_lot_size: 100,
maint_asset_weight: 0.8, maint_base_asset_weight: 0.8,
init_asset_weight: 0.6, init_base_asset_weight: 0.6,
maint_liab_weight: 1.2, maint_base_liab_weight: 1.2,
init_liab_weight: 1.4, init_base_liab_weight: 1.4,
liquidation_fee: 0.05, liquidation_fee: 0.05,
maker_fee: 0.0, maker_fee: 0.0,
taker_fee: 0.0, taker_fee: 0.0,
@ -261,10 +261,10 @@ async fn test_liq_perps_base_position_and_bankruptcy() -> Result<(), TransportEr
perp_market_index: 0, perp_market_index: 0,
quote_lot_size: 10, quote_lot_size: 10,
base_lot_size: 100, base_lot_size: 100,
maint_asset_weight: 0.8, maint_base_asset_weight: 0.8,
init_asset_weight: 0.6, init_base_asset_weight: 0.6,
maint_liab_weight: 1.2, maint_base_liab_weight: 1.2,
init_liab_weight: 1.4, init_base_liab_weight: 1.4,
liquidation_fee: 0.05, liquidation_fee: 0.05,
maker_fee: 0.0, maker_fee: 0.0,
taker_fee: 0.0, taker_fee: 0.0,
@ -843,10 +843,10 @@ async fn test_liq_perps_bankruptcy() -> Result<(), TransportError> {
perp_market_index, perp_market_index,
quote_lot_size: 1, quote_lot_size: 1,
base_lot_size: 100, base_lot_size: 100,
maint_asset_weight: 0.8, maint_base_asset_weight: 0.8,
init_asset_weight: 0.6, init_base_asset_weight: 0.6,
maint_liab_weight: 1.2, maint_base_liab_weight: 1.2,
init_liab_weight: 1.4, init_base_liab_weight: 1.4,
liquidation_fee: 0.05, liquidation_fee: 0.05,
maker_fee: 0.0, maker_fee: 0.0,
taker_fee: 0.0, taker_fee: 0.0,

View File

@ -76,10 +76,10 @@ async fn test_perp_fixed() -> Result<(), TransportError> {
perp_market_index: 0, perp_market_index: 0,
quote_lot_size: 10, quote_lot_size: 10,
base_lot_size: 100, base_lot_size: 100,
maint_asset_weight: 0.975, maint_base_asset_weight: 0.975,
init_asset_weight: 0.95, init_base_asset_weight: 0.95,
maint_liab_weight: 1.025, maint_base_liab_weight: 1.025,
init_liab_weight: 1.05, init_base_liab_weight: 1.05,
liquidation_fee: 0.012, liquidation_fee: 0.012,
maker_fee: -0.0001, maker_fee: -0.0001,
taker_fee: 0.0002, taker_fee: 0.0002,
@ -520,10 +520,10 @@ async fn test_perp_oracle_peg() -> Result<(), TransportError> {
perp_market_index: 0, perp_market_index: 0,
quote_lot_size: 10, quote_lot_size: 10,
base_lot_size: 10000, base_lot_size: 10000,
maint_asset_weight: 0.975, maint_base_asset_weight: 0.975,
init_asset_weight: 0.95, init_base_asset_weight: 0.95,
maint_liab_weight: 1.025, maint_base_liab_weight: 1.025,
init_liab_weight: 1.05, init_base_liab_weight: 1.05,
liquidation_fee: 0.012, liquidation_fee: 0.012,
maker_fee: -0.0001, maker_fee: -0.0001,
taker_fee: 0.0002, taker_fee: 0.0002,

View File

@ -73,10 +73,10 @@ async fn test_perp_settle_pnl() -> Result<(), TransportError> {
perp_market_index: 0, perp_market_index: 0,
quote_lot_size: 10, quote_lot_size: 10,
base_lot_size: 100, base_lot_size: 100,
maint_asset_weight: 0.975, maint_base_asset_weight: 0.975,
init_asset_weight: 0.95, init_base_asset_weight: 0.95,
maint_liab_weight: 1.025, maint_base_liab_weight: 1.025,
init_liab_weight: 1.05, init_base_liab_weight: 1.05,
liquidation_fee: 0.012, liquidation_fee: 0.012,
maker_fee: 0.0002, maker_fee: 0.0002,
taker_fee: 0.000, taker_fee: 0.000,
@ -103,10 +103,10 @@ async fn test_perp_settle_pnl() -> Result<(), TransportError> {
perp_market_index: 1, perp_market_index: 1,
quote_lot_size: 10, quote_lot_size: 10,
base_lot_size: 100, base_lot_size: 100,
maint_asset_weight: 0.975, maint_base_asset_weight: 0.975,
init_asset_weight: 0.95, init_base_asset_weight: 0.95,
maint_liab_weight: 1.025, maint_base_liab_weight: 1.025,
init_liab_weight: 1.05, init_base_liab_weight: 1.05,
liquidation_fee: 0.012, liquidation_fee: 0.012,
maker_fee: 0.0002, maker_fee: 0.0002,
taker_fee: 0.000, taker_fee: 0.000,
@ -576,10 +576,10 @@ async fn test_perp_settle_pnl_fees() -> Result<(), TransportError> {
perp_market_index: 0, perp_market_index: 0,
quote_lot_size: 10, quote_lot_size: 10,
base_lot_size: 100, base_lot_size: 100,
maint_asset_weight: 1.0, maint_base_asset_weight: 1.0,
init_asset_weight: 1.0, init_base_asset_weight: 1.0,
maint_liab_weight: 1.0, maint_base_liab_weight: 1.0,
init_liab_weight: 1.0, init_base_liab_weight: 1.0,
liquidation_fee: 0.0, liquidation_fee: 0.0,
maker_fee: 0.0, maker_fee: 0.0,
taker_fee: 0.0, taker_fee: 0.0,
@ -848,10 +848,10 @@ async fn test_perp_pnl_settle_limit() -> Result<(), TransportError> {
perp_market_index: 0, perp_market_index: 0,
quote_lot_size: 10, quote_lot_size: 10,
base_lot_size: 100, base_lot_size: 100,
maint_asset_weight: 0.975, maint_base_asset_weight: 0.975,
init_asset_weight: 0.95, init_base_asset_weight: 0.95,
maint_liab_weight: 1.025, maint_base_liab_weight: 1.025,
init_liab_weight: 1.05, init_base_liab_weight: 1.05,
liquidation_fee: 0.012, liquidation_fee: 0.012,
maker_fee: 0.0, maker_fee: 0.0,
taker_fee: 0.0, taker_fee: 0.0,

View File

@ -152,10 +152,10 @@ async fn test_perp_settle_fees() -> Result<(), TransportError> {
perp_market_index: 0, perp_market_index: 0,
quote_lot_size: 10, quote_lot_size: 10,
base_lot_size: 100, base_lot_size: 100,
maint_asset_weight: 0.975, maint_base_asset_weight: 0.975,
init_asset_weight: 0.95, init_base_asset_weight: 0.95,
maint_liab_weight: 1.025, maint_base_liab_weight: 1.025,
init_liab_weight: 1.05, init_base_liab_weight: 1.05,
liquidation_fee: 0.012, liquidation_fee: 0.012,
maker_fee: 0.0002, maker_fee: 0.0002,
taker_fee: 0.000, taker_fee: 0.000,
@ -182,10 +182,10 @@ async fn test_perp_settle_fees() -> Result<(), TransportError> {
perp_market_index: 1, perp_market_index: 1,
quote_lot_size: 10, quote_lot_size: 10,
base_lot_size: 100, base_lot_size: 100,
maint_asset_weight: 0.975, maint_base_asset_weight: 0.975,
init_asset_weight: 0.95, init_base_asset_weight: 0.95,
maint_liab_weight: 1.025, maint_base_liab_weight: 1.025,
init_liab_weight: 1.05, init_base_liab_weight: 1.05,
liquidation_fee: 0.012, liquidation_fee: 0.012,
maker_fee: 0.0002, maker_fee: 0.0002,
taker_fee: 0.000, taker_fee: 0.000,

View File

@ -251,10 +251,10 @@ async fn test_perp_reduce_only() -> Result<(), TransportError> {
perp_market_index: 0, perp_market_index: 0,
quote_lot_size: 10, quote_lot_size: 10,
base_lot_size: 100, base_lot_size: 100,
maint_asset_weight: 0.975, maint_base_asset_weight: 0.975,
init_asset_weight: 0.95, init_base_asset_weight: 0.95,
maint_liab_weight: 1.025, maint_base_liab_weight: 1.025,
init_liab_weight: 1.05, init_base_liab_weight: 1.05,
liquidation_fee: 0.012, liquidation_fee: 0.012,
maker_fee: 0.0002, maker_fee: 0.0002,
taker_fee: 0.000, taker_fee: 0.000,

View File

@ -31,17 +31,19 @@ function mockBankAndOracle(
function mockPerpMarket( function mockPerpMarket(
perpMarketIndex: number, perpMarketIndex: number,
maintWeight: number, maintBaseWeight: number,
initWeight: number, initBaseWeight: number,
baseLotSize: number, baseLotSize: number,
price: number, price: number,
): PerpMarket { ): PerpMarket {
return { return {
perpMarketIndex, perpMarketIndex,
maintAssetWeight: I80F48.fromNumber(1 - maintWeight), maintBaseAssetWeight: I80F48.fromNumber(1 - maintBaseWeight),
initAssetWeight: I80F48.fromNumber(1 - initWeight), initBaseAssetWeight: I80F48.fromNumber(1 - initBaseWeight),
maintLiabWeight: I80F48.fromNumber(1 + maintWeight), maintBaseLiabWeight: I80F48.fromNumber(1 + maintBaseWeight),
initLiabWeight: I80F48.fromNumber(1 + initWeight), initBaseLiabWeight: I80F48.fromNumber(1 + initBaseWeight),
maintPnlAssetWeight: I80F48.fromNumber(1 - 0.02),
initPnlAssetWeight: I80F48.fromNumber(1 - 0.05),
price: I80F48.fromNumber(price), price: I80F48.fromNumber(price),
stablePriceModel: { stablePrice: price } as StablePriceModel, stablePriceModel: { stablePrice: price } as StablePriceModel,
quoteLotSize: new BN(100), quoteLotSize: new BN(100),
@ -231,7 +233,9 @@ describe('Health Cache', () => {
const hc = new HealthCache([ti1, ti2, ti3], [si1, si2], [pi1]); const hc = new HealthCache([ti1, ti2, ti3], [si1, si2], [pi1]);
const health = hc.health(HealthType.init).toNumber(); const health = hc.health(HealthType.init).toNumber();
console.log( console.log(
` - case "${fixture.name}" health ${health.toFixed(3).padStart(10)}`, ` - case "${fixture.name}" health ${health
.toFixed(3)
.padStart(10)}, expected ${fixture.expectedHealth}`,
); );
expect(health - fixture.expectedHealth).lessThan(0.0000001); expect(health - fixture.expectedHealth).lessThan(0.0000001);
} }
@ -276,18 +280,18 @@ describe('Health Cache', () => {
}); });
testFixture({ testFixture({
name: '2', name: '2: weighted positive perp pnl',
token1: 0, token1: 0,
token2: 0, token2: 0,
token3: 0, token3: 0,
oo12: [0, 0], oo12: [0, 0],
oo13: [0, 0], oo13: [0, 0],
perp1: [-10, 100, 0, 0], perp1: [-1, 100, 0, 0],
expectedHealth: 0, expectedHealth: 0.95 * (100.0 - 1.2 * 1.0 * baseLotsToQuote),
}); });
testFixture({ testFixture({
name: '3', name: '3: negative perp pnl is not weighted',
token1: 0, token1: 0,
token2: 0, token2: 0,
token3: 0, token3: 0,
@ -298,25 +302,25 @@ describe('Health Cache', () => {
}); });
testFixture({ testFixture({
name: '4', name: '4: perp health',
token1: 0, token1: 0,
token2: 0, token2: 0,
token3: 0, token3: 0,
oo12: [0, 0], oo12: [0, 0],
oo13: [0, 0], oo13: [0, 0],
perp1: [10, 100, 0, 0], perp1: [10, 100, 0, 0],
expectedHealth: 0, expectedHealth: 0.95 * (100.0 + 0.8 * 10.0 * baseLotsToQuote),
}); });
testFixture({ testFixture({
name: '5', name: '5: perp health',
token1: 0, token1: 0,
token2: 0, token2: 0,
token3: 0, token3: 0,
oo12: [0, 0], oo12: [0, 0],
oo13: [0, 0], oo13: [0, 0],
perp1: [30, -100, 0, 0], perp1: [30, -100, 0, 0],
expectedHealth: 0, expectedHealth: 0.95 * (-100.0 + 0.8 * 30.0 * baseLotsToQuote),
}); });
testFixture({ testFixture({
@ -326,7 +330,7 @@ describe('Health Cache', () => {
token3: -10, token3: -10,
oo12: [1, 1], oo12: [1, 1],
oo13: [1, 1], oo13: [1, 1],
perp1: [30, -100, 0, 0], perp1: [0, 0, 0, 0],
expectedHealth: expectedHealth:
// tokens // tokens
-100.0 * 1.2 - -100.0 * 1.2 -

View File

@ -206,13 +206,11 @@ export class HealthCache {
health.iadd(contrib); health.iadd(contrib);
} }
for (const perpInfo of this.perpInfos) { for (const perpInfo of this.perpInfos) {
if (perpInfo.trustedMarket) { const positiveContrib = perpInfo
const positiveContrib = perpInfo .healthContribution(HealthType.maint)
.uncappedHealthContribution(HealthType.maint) .max(ZERO_I80F48());
.max(ZERO_I80F48()); // console.log(` - pi ${positiveContrib}`);
// console.log(` - pi ${positiveContrib}`); health.iadd(positiveContrib);
health.iadd(positiveContrib);
}
} }
return health; return health;
} }
@ -1052,8 +1050,12 @@ export class HealthCache {
// If the price is sufficiently good then health will just increase from trading // If the price is sufficiently good then health will just increase from trading
const finalHealthSlope = const finalHealthSlope =
direction == 1 direction == 1
? perpInfo.initAssetWeight.mul(prices.asset(HealthType.init)).sub(price) ? perpInfo.initBaseAssetWeight
: price.sub(perpInfo.initLiabWeight.mul(prices.liab(HealthType.init))); .mul(prices.asset(HealthType.init))
.sub(price)
: price.sub(
perpInfo.initBaseLiabWeight.mul(prices.liab(HealthType.init)),
);
if (finalHealthSlope.gte(ZERO_I80F48())) { if (finalHealthSlope.gte(ZERO_I80F48())) {
return MAX_I80F48(); return MAX_I80F48();
} }
@ -1123,7 +1125,7 @@ export class HealthCache {
const perpInfo = startCache.perpInfos[perpInfoIndex]; const perpInfo = startCache.perpInfos[perpInfoIndex];
const startHealthUncapped = startHealth const startHealthUncapped = startHealth
.sub(perpInfo.healthContribution(HealthType.init)) .sub(perpInfo.healthContribution(HealthType.init))
.add(perpInfo.uncappedHealthContribution(HealthType.init)); .add(perpInfo.unweightedHealthContribution(HealthType.init));
const zeroHealthAmount = case1Start const zeroHealthAmount = case1Start
.sub(startHealthUncapped.div(finalHealthSlope).div(baseLotSize)) .sub(startHealthUncapped.div(finalHealthSlope).div(baseLotSize))
@ -1420,10 +1422,12 @@ export class Serum3Info {
export class PerpInfo { export class PerpInfo {
constructor( constructor(
public perpMarketIndex: number, public perpMarketIndex: number,
public maintAssetWeight: I80F48, public maintBaseAssetWeight: I80F48,
public initAssetWeight: I80F48, public initBaseAssetWeight: I80F48,
public maintLiabWeight: I80F48, public maintBaseLiabWeight: I80F48,
public initLiabWeight: I80F48, public initBaseLiabWeight: I80F48,
public maintPnlAssetWeight: I80F48,
public initPnlAssetWeight: I80F48,
public baseLotSize: BN, public baseLotSize: BN,
public baseLots: BN, public baseLots: BN,
public bidsBaseLots: BN, public bidsBaseLots: BN,
@ -1431,16 +1435,17 @@ export class PerpInfo {
public quote: I80F48, public quote: I80F48,
public prices: Prices, public prices: Prices,
public hasOpenOrders: boolean, public hasOpenOrders: boolean,
public trustedMarket: boolean,
) {} ) {}
static fromDto(dto: PerpInfoDto): PerpInfo { static fromDto(dto: PerpInfoDto): PerpInfo {
return new PerpInfo( return new PerpInfo(
dto.perpMarketIndex, dto.perpMarketIndex,
I80F48.from(dto.maintAssetWeight), I80F48.from(dto.maintBaseAssetWeight),
I80F48.from(dto.initAssetWeight), I80F48.from(dto.initBaseAssetWeight),
I80F48.from(dto.maintLiabWeight), I80F48.from(dto.maintBaseLiabWeight),
I80F48.from(dto.initLiabWeight), I80F48.from(dto.initBaseLiabWeight),
I80F48.from(dto.maintPnlAssetWeight),
I80F48.from(dto.initPnlAssetWeight),
dto.baseLotSize, dto.baseLotSize,
dto.baseLots, dto.baseLots,
dto.bidsBaseLots, dto.bidsBaseLots,
@ -1451,7 +1456,6 @@ export class PerpInfo {
I80F48.from(dto.prices.stable), I80F48.from(dto.prices.stable),
), ),
dto.hasOpenOrders, dto.hasOpenOrders,
dto.trustedMarket,
); );
} }
@ -1473,10 +1477,12 @@ export class PerpInfo {
return new PerpInfo( return new PerpInfo(
perpMarket.perpMarketIndex, perpMarket.perpMarketIndex,
perpMarket.maintAssetWeight, perpMarket.maintBaseAssetWeight,
perpMarket.initAssetWeight, perpMarket.initBaseAssetWeight,
perpMarket.maintLiabWeight, perpMarket.maintBaseLiabWeight,
perpMarket.initLiabWeight, perpMarket.initBaseLiabWeight,
perpMarket.maintPnlAssetWeight,
perpMarket.initPnlAssetWeight,
perpMarket.baseLotSize, perpMarket.baseLotSize,
baseLots, baseLots,
perpPosition.bidsBaseLots, perpPosition.bidsBaseLots,
@ -1487,17 +1493,22 @@ export class PerpInfo {
I80F48.fromNumber(perpMarket.stablePriceModel.stablePrice), I80F48.fromNumber(perpMarket.stablePriceModel.stablePrice),
), ),
perpPosition.hasOpenOrders(), perpPosition.hasOpenOrders(),
perpMarket.trustedMarket,
); );
} }
healthContribution(healthType: HealthType | undefined): I80F48 { healthContribution(healthType: HealthType | undefined): I80F48 {
return this.trustedMarket const contrib = this.unweightedHealthContribution(healthType);
? this.uncappedHealthContribution(healthType) if (contrib.gt(ZERO_I80F48())) {
: this.uncappedHealthContribution(healthType).min(ZERO_I80F48()); const assetWeight =
healthType == HealthType.init
? this.initPnlAssetWeight
: this.maintPnlAssetWeight;
return assetWeight.mul(contrib);
}
return contrib;
} }
uncappedHealthContribution(healthType: HealthType | undefined): I80F48 { unweightedHealthContribution(healthType: HealthType | undefined): I80F48 {
function orderExecutionCase( function orderExecutionCase(
pi: PerpInfo, pi: PerpInfo,
ordersBaseLots: BN, ordersBaseLots: BN,
@ -1510,18 +1521,18 @@ export class PerpInfo {
let weight, basePrice; let weight, basePrice;
if (healthType == HealthType.init) { if (healthType == HealthType.init) {
if (netBaseNative.isNeg()) { if (netBaseNative.isNeg()) {
weight = pi.initLiabWeight; weight = pi.initBaseLiabWeight;
basePrice = pi.prices.liab(healthType); basePrice = pi.prices.liab(healthType);
} else { } else {
weight = pi.initAssetWeight; weight = pi.initBaseAssetWeight;
basePrice = pi.prices.asset(healthType); basePrice = pi.prices.asset(healthType);
} }
} else { } else {
if (netBaseNative.isNeg()) { if (netBaseNative.isNeg()) {
weight = pi.maintLiabWeight; weight = pi.maintBaseLiabWeight;
basePrice = pi.prices.liab(healthType); basePrice = pi.prices.liab(healthType);
} else { } else {
weight = pi.maintAssetWeight; weight = pi.maintBaseAssetWeight;
basePrice = pi.prices.asset(healthType); basePrice = pi.prices.asset(healthType);
} }
} }
@ -1557,10 +1568,12 @@ export class PerpInfo {
static emptyFromPerpMarket(perpMarket: PerpMarket): PerpInfo { static emptyFromPerpMarket(perpMarket: PerpMarket): PerpInfo {
return new PerpInfo( return new PerpInfo(
perpMarket.perpMarketIndex, perpMarket.perpMarketIndex,
perpMarket.maintAssetWeight, perpMarket.maintBaseAssetWeight,
perpMarket.initAssetWeight, perpMarket.initBaseAssetWeight,
perpMarket.maintLiabWeight, perpMarket.maintBaseLiabWeight,
perpMarket.initLiabWeight, perpMarket.initBaseLiabWeight,
perpMarket.maintPnlAssetWeight,
perpMarket.initPnlAssetWeight,
perpMarket.baseLotSize, perpMarket.baseLotSize,
new BN(0), new BN(0),
new BN(0), new BN(0),
@ -1571,7 +1584,6 @@ export class PerpInfo {
I80F48.fromNumber(perpMarket.stablePriceModel.stablePrice), I80F48.fromNumber(perpMarket.stablePriceModel.stablePrice),
), ),
false, false,
perpMarket.trustedMarket,
); );
} }
@ -1580,7 +1592,7 @@ export class PerpInfo {
this.baseLots this.baseLots
}, quote: ${this.quote}, oraclePrice: ${ }, quote: ${this.quote}, oraclePrice: ${
this.prices.oracle this.prices.oracle
}, uncapped health contribution ${this.uncappedHealthContribution( }, uncapped health contribution ${this.unweightedHealthContribution(
HealthType.init, HealthType.init,
)}`; )}`;
} }
@ -1641,10 +1653,12 @@ export class Serum3InfoDto {
export class PerpInfoDto { export class PerpInfoDto {
perpMarketIndex: number; perpMarketIndex: number;
maintAssetWeight: I80F48Dto; maintBaseAssetWeight: I80F48Dto;
initAssetWeight: I80F48Dto; initBaseAssetWeight: I80F48Dto;
maintLiabWeight: I80F48Dto; maintBaseLiabWeight: I80F48Dto;
initLiabWeight: I80F48Dto; initBaseLiabWeight: I80F48Dto;
maintPnlAssetWeight: I80F48Dto;
initPnlAssetWeight: I80F48Dto;
public baseLotSize: BN; public baseLotSize: BN;
public baseLots: BN; public baseLots: BN;
public bidsBaseLots: BN; public bidsBaseLots: BN;
@ -1652,5 +1666,4 @@ export class PerpInfoDto {
quote: I80F48Dto; quote: I80F48Dto;
prices: { oracle: I80F48Dto; stable: I80F48Dto }; prices: { oracle: I80F48Dto; stable: I80F48Dto };
hasOpenOrders: boolean; hasOpenOrders: boolean;
trustedMarket: boolean;
} }

View File

@ -30,10 +30,10 @@ export type ParsedFillEvent = Modify<
export class PerpMarket { export class PerpMarket {
public name: string; public name: string;
public oracleConfig: OracleConfig; public oracleConfig: OracleConfig;
public maintAssetWeight: I80F48; public maintBaseAssetWeight: I80F48;
public initAssetWeight: I80F48; public initBaseAssetWeight: I80F48;
public maintLiabWeight: I80F48; public maintBaseLiabWeight: I80F48;
public initLiabWeight: I80F48; public initBaseLiabWeight: I80F48;
public liquidationFee: I80F48; public liquidationFee: I80F48;
public makerFee: I80F48; public makerFee: I80F48;
public takerFee: I80F48; public takerFee: I80F48;
@ -43,6 +43,9 @@ export class PerpMarket {
public shortFunding: I80F48; public shortFunding: I80F48;
public feesAccrued: I80F48; public feesAccrued: I80F48;
public feesSettled: I80F48; public feesSettled: I80F48;
public maintPnlAssetWeight: I80F48;
public initPnlAssetWeight: I80F48;
public _price: I80F48; public _price: I80F48;
public _uiPrice: number; public _uiPrice: number;
@ -59,7 +62,6 @@ export class PerpMarket {
group: PublicKey; group: PublicKey;
settleTokenIndex: number; settleTokenIndex: number;
perpMarketIndex: number; perpMarketIndex: number;
trustedMarket: number;
groupInsuranceFund: number; groupInsuranceFund: number;
baseDecimals: number; baseDecimals: number;
name: number[]; name: number[];
@ -71,10 +73,10 @@ export class PerpMarket {
stablePriceModel: StablePriceModel; stablePriceModel: StablePriceModel;
quoteLotSize: BN; quoteLotSize: BN;
baseLotSize: BN; baseLotSize: BN;
maintAssetWeight: I80F48Dto; maintBaseAssetWeight: I80F48Dto;
initAssetWeight: I80F48Dto; initBaseAssetWeight: I80F48Dto;
maintLiabWeight: I80F48Dto; maintBaseLiabWeight: I80F48Dto;
initLiabWeight: I80F48Dto; initBaseLiabWeight: I80F48Dto;
openInterest: BN; openInterest: BN;
seqNum: BN; seqNum: BN;
registrationTime: BN; registrationTime: BN;
@ -96,6 +98,8 @@ export class PerpMarket {
settlePnlLimitFactor: number; settlePnlLimitFactor: number;
settlePnlLimitWindowSizeTs: BN; settlePnlLimitWindowSizeTs: BN;
reduceOnly: number; reduceOnly: number;
maintPnlAssetWeight: I80F48Dto;
initPnlAssetWeight: I80F48Dto;
}, },
): PerpMarket { ): PerpMarket {
return new PerpMarket( return new PerpMarket(
@ -103,7 +107,6 @@ export class PerpMarket {
obj.group, obj.group,
obj.settleTokenIndex as TokenIndex, obj.settleTokenIndex as TokenIndex,
obj.perpMarketIndex as PerpMarketIndex, obj.perpMarketIndex as PerpMarketIndex,
obj.trustedMarket == 1,
obj.groupInsuranceFund == 1, obj.groupInsuranceFund == 1,
obj.baseDecimals, obj.baseDecimals,
obj.name, obj.name,
@ -115,10 +118,10 @@ export class PerpMarket {
obj.stablePriceModel, obj.stablePriceModel,
obj.quoteLotSize, obj.quoteLotSize,
obj.baseLotSize, obj.baseLotSize,
obj.maintAssetWeight, obj.maintBaseAssetWeight,
obj.initAssetWeight, obj.initBaseAssetWeight,
obj.maintLiabWeight, obj.maintBaseLiabWeight,
obj.initLiabWeight, obj.initBaseLiabWeight,
obj.openInterest, obj.openInterest,
obj.seqNum, obj.seqNum,
obj.registrationTime, obj.registrationTime,
@ -140,6 +143,8 @@ export class PerpMarket {
obj.settlePnlLimitFactor, obj.settlePnlLimitFactor,
obj.settlePnlLimitWindowSizeTs, obj.settlePnlLimitWindowSizeTs,
obj.reduceOnly == 1, obj.reduceOnly == 1,
obj.maintPnlAssetWeight,
obj.initPnlAssetWeight,
); );
} }
@ -148,7 +153,6 @@ export class PerpMarket {
public group: PublicKey, public group: PublicKey,
public settleTokenIndex: TokenIndex, public settleTokenIndex: TokenIndex,
public perpMarketIndex: PerpMarketIndex, // TODO rename to marketIndex? public perpMarketIndex: PerpMarketIndex, // TODO rename to marketIndex?
public trustedMarket: boolean,
public groupInsuranceFund: boolean, public groupInsuranceFund: boolean,
public baseDecimals: number, public baseDecimals: number,
name: number[], name: number[],
@ -160,10 +164,10 @@ export class PerpMarket {
public stablePriceModel: StablePriceModel, public stablePriceModel: StablePriceModel,
public quoteLotSize: BN, public quoteLotSize: BN,
public baseLotSize: BN, public baseLotSize: BN,
maintAssetWeight: I80F48Dto, maintBaseAssetWeight: I80F48Dto,
initAssetWeight: I80F48Dto, initBaseAssetWeight: I80F48Dto,
maintLiabWeight: I80F48Dto, maintBaseLiabWeight: I80F48Dto,
initLiabWeight: I80F48Dto, initBaseLiabWeight: I80F48Dto,
public openInterest: BN, public openInterest: BN,
public seqNum: BN, public seqNum: BN,
public registrationTime: BN, public registrationTime: BN,
@ -185,16 +189,18 @@ export class PerpMarket {
public settlePnlLimitFactor: number, public settlePnlLimitFactor: number,
public settlePnlLimitWindowSizeTs: BN, public settlePnlLimitWindowSizeTs: BN,
public reduceOnly: boolean, public reduceOnly: boolean,
maintPnlAssetWeight: I80F48Dto,
initPnlAssetWeight: I80F48Dto,
) { ) {
this.name = utf8.decode(new Uint8Array(name)).split('\x00')[0]; this.name = utf8.decode(new Uint8Array(name)).split('\x00')[0];
this.oracleConfig = { this.oracleConfig = {
confFilter: I80F48.from(oracleConfig.confFilter), confFilter: I80F48.from(oracleConfig.confFilter),
maxStalenessSlots: oracleConfig.maxStalenessSlots, maxStalenessSlots: oracleConfig.maxStalenessSlots,
} as OracleConfig; } as OracleConfig;
this.maintAssetWeight = I80F48.from(maintAssetWeight); this.maintBaseAssetWeight = I80F48.from(maintBaseAssetWeight);
this.initAssetWeight = I80F48.from(initAssetWeight); this.initBaseAssetWeight = I80F48.from(initBaseAssetWeight);
this.maintLiabWeight = I80F48.from(maintLiabWeight); this.maintBaseLiabWeight = I80F48.from(maintBaseLiabWeight);
this.initLiabWeight = I80F48.from(initLiabWeight); this.initBaseLiabWeight = I80F48.from(initBaseLiabWeight);
this.liquidationFee = I80F48.from(liquidationFee); this.liquidationFee = I80F48.from(liquidationFee);
this.makerFee = I80F48.from(makerFee); this.makerFee = I80F48.from(makerFee);
this.takerFee = I80F48.from(takerFee); this.takerFee = I80F48.from(takerFee);
@ -204,6 +210,8 @@ export class PerpMarket {
this.shortFunding = I80F48.from(shortFunding); this.shortFunding = I80F48.from(shortFunding);
this.feesAccrued = I80F48.from(feesAccrued); this.feesAccrued = I80F48.from(feesAccrued);
this.feesSettled = I80F48.from(feesSettled); this.feesSettled = I80F48.from(feesSettled);
this.maintPnlAssetWeight = I80F48.from(maintPnlAssetWeight);
this.initPnlAssetWeight = I80F48.from(initPnlAssetWeight);
this.priceLotsToUiConverter = new Big(10) this.priceLotsToUiConverter = new Big(10)
.pow(baseDecimals - QUOTE_DECIMALS) .pow(baseDecimals - QUOTE_DECIMALS)
@ -249,9 +257,9 @@ export class PerpMarket {
insidePriceLimit(side: PerpOrderSide, orderPrice: number): boolean { insidePriceLimit(side: PerpOrderSide, orderPrice: number): boolean {
return ( return (
(side === PerpOrderSide.bid && (side === PerpOrderSide.bid &&
orderPrice <= this.maintLiabWeight.toNumber() * this.uiPrice) || orderPrice <= this.maintBaseLiabWeight.toNumber() * this.uiPrice) ||
(side === PerpOrderSide.ask && (side === PerpOrderSide.ask &&
orderPrice >= this.maintAssetWeight.toNumber() * this.uiPrice) orderPrice >= this.maintBaseAssetWeight.toNumber() * this.uiPrice)
); );
} }
@ -486,13 +494,13 @@ export class PerpMarket {
'\n perpMarketIndex -' + '\n perpMarketIndex -' +
this.perpMarketIndex + this.perpMarketIndex +
'\n maintAssetWeight -' + '\n maintAssetWeight -' +
this.maintAssetWeight.toString() + this.maintBaseAssetWeight.toString() +
'\n initAssetWeight -' + '\n initAssetWeight -' +
this.initAssetWeight.toString() + this.initBaseAssetWeight.toString() +
'\n maintLiabWeight -' + '\n maintLiabWeight -' +
this.maintLiabWeight.toString() + this.maintBaseLiabWeight.toString() +
'\n initLiabWeight -' + '\n initLiabWeight -' +
this.initLiabWeight.toString() + this.initBaseLiabWeight.toString() +
'\n liquidationFee -' + '\n liquidationFee -' +
this.liquidationFee.toString() + this.liquidationFee.toString() +
'\n makerFee -' + '\n makerFee -' +

View File

@ -1521,10 +1521,12 @@ export class MangoClient {
baseDecimals: number, baseDecimals: number,
quoteLotSize: number, quoteLotSize: number,
baseLotSize: number, baseLotSize: number,
maintAssetWeight: number, maintBaseAssetWeight: number,
initAssetWeight: number, initBaseAssetWeight: number,
maintLiabWeight: number, maintBaseLiabWeight: number,
initLiabWeight: number, initBaseLiabWeight: number,
maintPnlAssetWeight: number,
initPnlAssetWeight: number,
liquidationFee: number, liquidationFee: number,
makerFee: number, makerFee: number,
takerFee: number, takerFee: number,
@ -1533,7 +1535,6 @@ export class MangoClient {
maxFunding: number, maxFunding: number,
impactQuantity: number, impactQuantity: number,
groupInsuranceFund: boolean, groupInsuranceFund: boolean,
trustedMarket: boolean,
settleFeeFlat: number, settleFeeFlat: number,
settleFeeAmountThreshold: number, settleFeeAmountThreshold: number,
settleFeeFractionLowHealth: number, settleFeeFractionLowHealth: number,
@ -1560,10 +1561,12 @@ export class MangoClient {
baseDecimals, baseDecimals,
new BN(quoteLotSize), new BN(quoteLotSize),
new BN(baseLotSize), new BN(baseLotSize),
maintAssetWeight, maintBaseAssetWeight,
initAssetWeight, initBaseAssetWeight,
maintLiabWeight, maintBaseLiabWeight,
initLiabWeight, initBaseLiabWeight,
maintPnlAssetWeight,
initPnlAssetWeight,
liquidationFee, liquidationFee,
makerFee, makerFee,
takerFee, takerFee,
@ -1571,7 +1574,6 @@ export class MangoClient {
maxFunding, maxFunding,
new BN(impactQuantity), new BN(impactQuantity),
groupInsuranceFund, groupInsuranceFund,
trustedMarket,
feePenalty, feePenalty,
settleFeeFlat, settleFeeFlat,
settleFeeAmountThreshold, settleFeeAmountThreshold,
@ -1642,10 +1644,12 @@ export class MangoClient {
params.oracle, params.oracle,
params.oracleConfig, params.oracleConfig,
params.baseDecimals, params.baseDecimals,
params.maintAssetWeight, params.maintBaseAssetWeight,
params.initAssetWeight, params.initBaseAssetWeight,
params.maintLiabWeight, params.maintBaseLiabWeight,
params.initLiabWeight, params.initBaseLiabWeight,
params.maintPnlAssetWeight,
params.initPnlAssetWeight,
params.liquidationFee, params.liquidationFee,
params.makerFee, params.makerFee,
params.takerFee, params.takerFee,
@ -1653,7 +1657,6 @@ export class MangoClient {
params.maxFunding, params.maxFunding,
params.impactQuantity !== null ? new BN(params.impactQuantity) : null, params.impactQuantity !== null ? new BN(params.impactQuantity) : null,
params.groupInsuranceFund, params.groupInsuranceFund,
params.trustedMarket,
params.feePenalty, params.feePenalty,
params.settleFeeFlat, params.settleFeeFlat,
params.settleFeeAmountThreshold, params.settleFeeAmountThreshold,

View File

@ -55,10 +55,12 @@ export interface PerpEditParams {
oracle: PublicKey | null; oracle: PublicKey | null;
oracleConfig: OracleConfigParams | null; oracleConfig: OracleConfigParams | null;
baseDecimals: number | null; baseDecimals: number | null;
maintAssetWeight: number | null; maintBaseAssetWeight: number | null;
initAssetWeight: number | null; initBaseAssetWeight: number | null;
maintLiabWeight: number | null; maintBaseLiabWeight: number | null;
initLiabWeight: number | null; initBaseLiabWeight: number | null;
maintPnlAssetWeight: number | null;
initPnlAssetWeight: number | null;
liquidationFee: number | null; liquidationFee: number | null;
makerFee: number | null; makerFee: number | null;
takerFee: number | null; takerFee: number | null;
@ -67,7 +69,6 @@ export interface PerpEditParams {
maxFunding: number | null; maxFunding: number | null;
impactQuantity: number | null; impactQuantity: number | null;
groupInsuranceFund: boolean | null; groupInsuranceFund: boolean | null;
trustedMarket: boolean | null;
settleFeeFlat: number | null; settleFeeFlat: number | null;
settleFeeAmountThreshold: number | null; settleFeeAmountThreshold: number | null;
settleFeeFractionLowHealth: number | null; settleFeeFractionLowHealth: number | null;
@ -83,10 +84,12 @@ export const NullPerpEditParams: PerpEditParams = {
oracle: null, oracle: null,
oracleConfig: null, oracleConfig: null,
baseDecimals: null, baseDecimals: null,
maintAssetWeight: null, maintBaseAssetWeight: null,
initAssetWeight: null, initBaseAssetWeight: null,
maintLiabWeight: null, maintBaseLiabWeight: null,
initLiabWeight: null, initBaseLiabWeight: null,
maintPnlAssetWeight: null,
initPnlAssetWeight: null,
liquidationFee: null, liquidationFee: null,
makerFee: null, makerFee: null,
takerFee: null, takerFee: null,
@ -95,7 +98,6 @@ export const NullPerpEditParams: PerpEditParams = {
maxFunding: null, maxFunding: null,
impactQuantity: null, impactQuantity: null,
groupInsuranceFund: null, groupInsuranceFund: null,
trustedMarket: null,
settleFeeFlat: null, settleFeeFlat: null,
settleFeeAmountThreshold: null, settleFeeAmountThreshold: null,
settleFeeFractionLowHealth: null, settleFeeFractionLowHealth: null,

View File

@ -1,5 +1,5 @@
export type MangoV4 = { export type MangoV4 = {
"version": "0.2.0", "version": "0.3.0",
"name": "mango_v4", "name": "mango_v4",
"instructions": [ "instructions": [
{ {
@ -2508,19 +2508,27 @@ export type MangoV4 = {
"type": "i64" "type": "i64"
}, },
{ {
"name": "maintAssetWeight", "name": "maintBaseAssetWeight",
"type": "f32" "type": "f32"
}, },
{ {
"name": "initAssetWeight", "name": "initBaseAssetWeight",
"type": "f32" "type": "f32"
}, },
{ {
"name": "maintLiabWeight", "name": "maintBaseLiabWeight",
"type": "f32" "type": "f32"
}, },
{ {
"name": "initLiabWeight", "name": "initBaseLiabWeight",
"type": "f32"
},
{
"name": "maintPnlAssetWeight",
"type": "f32"
},
{
"name": "initPnlAssetWeight",
"type": "f32" "type": "f32"
}, },
{ {
@ -2551,10 +2559,6 @@ export type MangoV4 = {
"name": "groupInsuranceFund", "name": "groupInsuranceFund",
"type": "bool" "type": "bool"
}, },
{
"name": "trustedMarket",
"type": "bool"
},
{ {
"name": "feePenalty", "name": "feePenalty",
"type": "f32" "type": "f32"
@ -2631,25 +2635,37 @@ export type MangoV4 = {
} }
}, },
{ {
"name": "maintAssetWeightOpt", "name": "maintBaseAssetWeightOpt",
"type": { "type": {
"option": "f32" "option": "f32"
} }
}, },
{ {
"name": "initAssetWeightOpt", "name": "initBaseAssetWeightOpt",
"type": { "type": {
"option": "f32" "option": "f32"
} }
}, },
{ {
"name": "maintLiabWeightOpt", "name": "maintBaseLiabWeightOpt",
"type": { "type": {
"option": "f32" "option": "f32"
} }
}, },
{ {
"name": "initLiabWeightOpt", "name": "initBaseLiabWeightOpt",
"type": {
"option": "f32"
}
},
{
"name": "maintPnlAssetWeightOpt",
"type": {
"option": "f32"
}
},
{
"name": "initPnlAssetWeightOpt",
"type": { "type": {
"option": "f32" "option": "f32"
} }
@ -2696,12 +2712,6 @@ export type MangoV4 = {
"option": "bool" "option": "bool"
} }
}, },
{
"name": "trustedMarketOpt",
"type": {
"option": "bool"
}
},
{ {
"name": "feePenaltyOpt", "name": "feePenaltyOpt",
"type": { "type": {
@ -4308,10 +4318,7 @@ export type MangoV4 = {
"type": "u16" "type": "u16"
}, },
{ {
"name": "trustedMarket", "name": "blocked1",
"docs": [
"May this market contribute positive values to health?"
],
"type": "u8" "type": "u8"
}, },
{ {
@ -4386,25 +4393,25 @@ export type MangoV4 = {
"type": "i64" "type": "i64"
}, },
{ {
"name": "maintAssetWeight", "name": "maintBaseAssetWeight",
"type": { "type": {
"defined": "I80F48" "defined": "I80F48"
} }
}, },
{ {
"name": "initAssetWeight", "name": "initBaseAssetWeight",
"type": { "type": {
"defined": "I80F48" "defined": "I80F48"
} }
}, },
{ {
"name": "maintLiabWeight", "name": "maintBaseLiabWeight",
"type": { "type": {
"defined": "I80F48" "defined": "I80F48"
} }
}, },
{ {
"name": "initLiabWeight", "name": "initBaseLiabWeight",
"type": { "type": {
"defined": "I80F48" "defined": "I80F48"
} }
@ -4564,12 +4571,33 @@ export type MangoV4 = {
"name": "reduceOnly", "name": "reduceOnly",
"type": "u8" "type": "u8"
}, },
{
"name": "padding4",
"type": {
"array": [
"u8",
7
]
}
},
{
"name": "maintPnlAssetWeight",
"type": {
"defined": "I80F48"
}
},
{
"name": "initPnlAssetWeight",
"type": {
"defined": "I80F48"
}
},
{ {
"name": "reserved", "name": "reserved",
"type": { "type": {
"array": [ "array": [
"u8", "u8",
1943 1904
] ]
} }
} }
@ -4869,25 +4897,37 @@ export type MangoV4 = {
"type": "u16" "type": "u16"
}, },
{ {
"name": "maintAssetWeight", "name": "maintBaseAssetWeight",
"type": { "type": {
"defined": "I80F48" "defined": "I80F48"
} }
}, },
{ {
"name": "initAssetWeight", "name": "initBaseAssetWeight",
"type": { "type": {
"defined": "I80F48" "defined": "I80F48"
} }
}, },
{ {
"name": "maintLiabWeight", "name": "maintBaseLiabWeight",
"type": { "type": {
"defined": "I80F48" "defined": "I80F48"
} }
}, },
{ {
"name": "initLiabWeight", "name": "initBaseLiabWeight",
"type": {
"defined": "I80F48"
}
},
{
"name": "maintPnlAssetWeight",
"type": {
"defined": "I80F48"
}
},
{
"name": "initPnlAssetWeight",
"type": { "type": {
"defined": "I80F48" "defined": "I80F48"
} }
@ -4923,10 +4963,6 @@ export type MangoV4 = {
{ {
"name": "hasOpenOrders", "name": "hasOpenOrders",
"type": "bool" "type": "bool"
},
{
"name": "trustedMarket",
"type": "bool"
} }
] ]
} }
@ -7717,7 +7753,7 @@ export type MangoV4 = {
}; };
export const IDL: MangoV4 = { export const IDL: MangoV4 = {
"version": "0.2.0", "version": "0.3.0",
"name": "mango_v4", "name": "mango_v4",
"instructions": [ "instructions": [
{ {
@ -10226,19 +10262,27 @@ export const IDL: MangoV4 = {
"type": "i64" "type": "i64"
}, },
{ {
"name": "maintAssetWeight", "name": "maintBaseAssetWeight",
"type": "f32" "type": "f32"
}, },
{ {
"name": "initAssetWeight", "name": "initBaseAssetWeight",
"type": "f32" "type": "f32"
}, },
{ {
"name": "maintLiabWeight", "name": "maintBaseLiabWeight",
"type": "f32" "type": "f32"
}, },
{ {
"name": "initLiabWeight", "name": "initBaseLiabWeight",
"type": "f32"
},
{
"name": "maintPnlAssetWeight",
"type": "f32"
},
{
"name": "initPnlAssetWeight",
"type": "f32" "type": "f32"
}, },
{ {
@ -10269,10 +10313,6 @@ export const IDL: MangoV4 = {
"name": "groupInsuranceFund", "name": "groupInsuranceFund",
"type": "bool" "type": "bool"
}, },
{
"name": "trustedMarket",
"type": "bool"
},
{ {
"name": "feePenalty", "name": "feePenalty",
"type": "f32" "type": "f32"
@ -10349,25 +10389,37 @@ export const IDL: MangoV4 = {
} }
}, },
{ {
"name": "maintAssetWeightOpt", "name": "maintBaseAssetWeightOpt",
"type": { "type": {
"option": "f32" "option": "f32"
} }
}, },
{ {
"name": "initAssetWeightOpt", "name": "initBaseAssetWeightOpt",
"type": { "type": {
"option": "f32" "option": "f32"
} }
}, },
{ {
"name": "maintLiabWeightOpt", "name": "maintBaseLiabWeightOpt",
"type": { "type": {
"option": "f32" "option": "f32"
} }
}, },
{ {
"name": "initLiabWeightOpt", "name": "initBaseLiabWeightOpt",
"type": {
"option": "f32"
}
},
{
"name": "maintPnlAssetWeightOpt",
"type": {
"option": "f32"
}
},
{
"name": "initPnlAssetWeightOpt",
"type": { "type": {
"option": "f32" "option": "f32"
} }
@ -10414,12 +10466,6 @@ export const IDL: MangoV4 = {
"option": "bool" "option": "bool"
} }
}, },
{
"name": "trustedMarketOpt",
"type": {
"option": "bool"
}
},
{ {
"name": "feePenaltyOpt", "name": "feePenaltyOpt",
"type": { "type": {
@ -12026,10 +12072,7 @@ export const IDL: MangoV4 = {
"type": "u16" "type": "u16"
}, },
{ {
"name": "trustedMarket", "name": "blocked1",
"docs": [
"May this market contribute positive values to health?"
],
"type": "u8" "type": "u8"
}, },
{ {
@ -12104,25 +12147,25 @@ export const IDL: MangoV4 = {
"type": "i64" "type": "i64"
}, },
{ {
"name": "maintAssetWeight", "name": "maintBaseAssetWeight",
"type": { "type": {
"defined": "I80F48" "defined": "I80F48"
} }
}, },
{ {
"name": "initAssetWeight", "name": "initBaseAssetWeight",
"type": { "type": {
"defined": "I80F48" "defined": "I80F48"
} }
}, },
{ {
"name": "maintLiabWeight", "name": "maintBaseLiabWeight",
"type": { "type": {
"defined": "I80F48" "defined": "I80F48"
} }
}, },
{ {
"name": "initLiabWeight", "name": "initBaseLiabWeight",
"type": { "type": {
"defined": "I80F48" "defined": "I80F48"
} }
@ -12282,12 +12325,33 @@ export const IDL: MangoV4 = {
"name": "reduceOnly", "name": "reduceOnly",
"type": "u8" "type": "u8"
}, },
{
"name": "padding4",
"type": {
"array": [
"u8",
7
]
}
},
{
"name": "maintPnlAssetWeight",
"type": {
"defined": "I80F48"
}
},
{
"name": "initPnlAssetWeight",
"type": {
"defined": "I80F48"
}
},
{ {
"name": "reserved", "name": "reserved",
"type": { "type": {
"array": [ "array": [
"u8", "u8",
1943 1904
] ]
} }
} }
@ -12587,25 +12651,37 @@ export const IDL: MangoV4 = {
"type": "u16" "type": "u16"
}, },
{ {
"name": "maintAssetWeight", "name": "maintBaseAssetWeight",
"type": { "type": {
"defined": "I80F48" "defined": "I80F48"
} }
}, },
{ {
"name": "initAssetWeight", "name": "initBaseAssetWeight",
"type": { "type": {
"defined": "I80F48" "defined": "I80F48"
} }
}, },
{ {
"name": "maintLiabWeight", "name": "maintBaseLiabWeight",
"type": { "type": {
"defined": "I80F48" "defined": "I80F48"
} }
}, },
{ {
"name": "initLiabWeight", "name": "initBaseLiabWeight",
"type": {
"defined": "I80F48"
}
},
{
"name": "maintPnlAssetWeight",
"type": {
"defined": "I80F48"
}
},
{
"name": "initPnlAssetWeight",
"type": { "type": {
"defined": "I80F48" "defined": "I80F48"
} }
@ -12641,10 +12717,6 @@ export const IDL: MangoV4 = {
{ {
"name": "hasOpenOrders", "name": "hasOpenOrders",
"type": "bool" "type": "bool"
},
{
"name": "trustedMarket",
"type": "bool"
} }
] ]
} }

View File

@ -245,13 +245,14 @@ async function main() {
1.05, 1.05,
0.012, 0.012,
0.0002, 0.0002,
1,
1,
0.0, 0.0,
0, 0,
0.05, 0.05,
0.05, 0.05,
100, 100,
true, true,
true,
1000, 1000,
1000000, 1000000,
0.05, 0.05,

View File

@ -424,6 +424,8 @@ async function registerPerpMarkets() {
0.95, 0.95,
1.025, 1.025,
1.05, 1.05,
1,
1,
0.0125, 0.0125,
-0.0001, -0.0001,
0.0004, 0.0004,
@ -432,7 +434,6 @@ async function registerPerpMarkets() {
0.05, 0.05,
100, // if btc is at 20k, this is 200$ 100, // if btc is at 20k, this is 200$
true, true,
true,
1000, // solana tx fee is currently 50 native quote at a sol price of 10$ 1000, // solana tx fee is currently 50 native quote at a sol price of 10$
1000000, 1000000,
0.01, // less than liquidationFee 0.01, // less than liquidationFee
@ -454,6 +455,8 @@ async function registerPerpMarkets() {
0.99, // 100x leverage 0.99, // 100x leverage
1.005, 1.005,
1.01, 1.01,
0,
0,
0.0025, 0.0025,
-0.0001, -0.0001,
0.0004, 0.0004,
@ -462,7 +465,6 @@ async function registerPerpMarkets() {
0.05, 0.05,
1000, // if mngo price 1 cent, this is 10$ 1000, // if mngo price 1 cent, this is 10$
false, false,
false,
1000, 1000,
1000000, 1000000,
0.001, // less than liquidationFee 0.001, // less than liquidationFee
@ -487,21 +489,6 @@ async function makePerpMarketReduceOnly() {
); );
} }
async function makePerpMarketUntrusted() {
const result = await buildAdminClient();
const client = result[0];
const admin = result[1];
const creator = result[2];
const group = await client.getGroupForCreator(creator.publicKey, GROUP_NUM);
const perpMarket = group.getPerpMarketByName('BTC-PERP');
await client.perpEditMarket(
group,
perpMarket.perpMarketIndex,
Builder(NullPerpEditParams).trustedMarket(false).build(),
);
}
async function createAndPopulateAlt() { async function createAndPopulateAlt() {
const result = await buildAdminClient(); const result = await buildAdminClient();
const client = result[0]; const client = result[0];
@ -662,7 +649,6 @@ async function main() {
try { try {
// await registerPerpMarkets(); // await registerPerpMarkets();
// await makePerpMarketReduceOnly(); // await makePerpMarketReduceOnly();
// await makePerpMarketUntrusted();
} catch (error) { } catch (error) {
console.log(error); console.log(error);
} }

View File

@ -228,6 +228,8 @@ async function main() {
0.8, 0.8,
1.1, 1.1,
1.2, 1.2,
1,
1,
0.05, 0.05,
-0.001, -0.001,
0.002, 0.002,
@ -236,7 +238,6 @@ async function main() {
0.1, 0.1,
10, 10,
false, false,
false,
0, 0,
0, 0,
0, 0,