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:
parent
da1dfb2c3c
commit
ec99376a8f
|
@ -436,8 +436,22 @@ mod tests {
|
|||
let oo1key = oo1.pubkey;
|
||||
oo1.data().native_pc_total = 20;
|
||||
|
||||
let mut perp1 = mock_perp_market(group, oracle2.pubkey, oracle2_price, 9, 0.2, 0.1);
|
||||
let mut perp2 = mock_perp_market(group, oracle1.pubkey, oracle1_price, 8, 0.2, 0.1);
|
||||
let mut perp1 = mock_perp_market(
|
||||
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 oracle2_account_info = oracle2.as_account_info();
|
||||
|
|
|
@ -209,10 +209,12 @@ pub(crate) struct Serum3Reserved {
|
|||
#[derive(Clone, AnchorDeserialize, AnchorSerialize, Debug)]
|
||||
pub struct PerpInfo {
|
||||
pub perp_market_index: PerpMarketIndex,
|
||||
pub maint_asset_weight: I80F48,
|
||||
pub init_asset_weight: I80F48,
|
||||
pub maint_liab_weight: I80F48,
|
||||
pub init_liab_weight: I80F48,
|
||||
pub maint_base_asset_weight: I80F48,
|
||||
pub init_base_asset_weight: I80F48,
|
||||
pub maint_base_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_lots: i64,
|
||||
pub bids_base_lots: i64,
|
||||
|
@ -221,7 +223,6 @@ pub struct PerpInfo {
|
|||
pub quote: I80F48,
|
||||
pub prices: Prices,
|
||||
pub has_open_orders: bool,
|
||||
pub trusted_market: bool,
|
||||
}
|
||||
|
||||
impl PerpInfo {
|
||||
|
@ -237,10 +238,12 @@ impl PerpInfo {
|
|||
|
||||
Ok(Self {
|
||||
perp_market_index: perp_market.perp_market_index,
|
||||
init_asset_weight: perp_market.init_asset_weight,
|
||||
init_liab_weight: perp_market.init_liab_weight,
|
||||
maint_asset_weight: perp_market.maint_asset_weight,
|
||||
maint_liab_weight: perp_market.maint_liab_weight,
|
||||
init_base_asset_weight: perp_market.init_base_asset_weight,
|
||||
init_base_liab_weight: perp_market.init_base_liab_weight,
|
||||
maint_base_asset_weight: perp_market.maint_base_asset_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_lots,
|
||||
bids_base_lots: perp_position.bids_base_lots,
|
||||
|
@ -248,14 +251,15 @@ impl PerpInfo {
|
|||
quote: quote_current,
|
||||
prices,
|
||||
has_open_orders: perp_position.has_open_orders(),
|
||||
trusted_market: perp_market.trusted_market(),
|
||||
})
|
||||
}
|
||||
|
||||
/// Total health contribution from perp balances
|
||||
///
|
||||
/// Due to isolation of perp markets, users may never borrow against perp
|
||||
/// positions in untrusted without settling first: perp health is capped at zero.
|
||||
/// For fully isolated perp markets, users may never borrow against unsettled
|
||||
/// 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
|
||||
/// 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
|
||||
/// be bankrupt) or suddenly increase a lot (if users could borrow against perp
|
||||
/// 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)]
|
||||
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 {
|
||||
c
|
||||
if contribution > 0 {
|
||||
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 {
|
||||
c.min(I80F48::ZERO)
|
||||
contribution
|
||||
}
|
||||
}
|
||||
|
||||
#[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 net_base_native =
|
||||
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()) {
|
||||
(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) => {
|
||||
(self.init_asset_weight, self.prices.asset(health_type))
|
||||
(self.init_base_asset_weight, self.prices.asset(health_type))
|
||||
}
|
||||
(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) => {
|
||||
(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
|
||||
|
@ -437,10 +452,10 @@ impl HealthCache {
|
|||
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
|
||||
.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 {
|
||||
|
@ -473,7 +488,7 @@ impl HealthCache {
|
|||
pub fn has_phase2_liquidatable(&self) -> bool {
|
||||
self.has_spot_assets() && self.has_spot_borrows()
|
||||
|| 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<()> {
|
||||
|
@ -487,7 +502,7 @@ impl HealthCache {
|
|||
MangoError::HasLiquidatablePerpBasePosition
|
||||
);
|
||||
require!(
|
||||
!self.has_perp_positive_trusted_pnl_without_base_position(),
|
||||
!self.has_perp_positive_maint_pnl_without_base_position(),
|
||||
MangoError::HasLiquidatableTrustedPerpPnl
|
||||
);
|
||||
Ok(())
|
||||
|
@ -636,12 +651,8 @@ impl HealthCache {
|
|||
}
|
||||
|
||||
for perp_info in self.perp_infos.iter() {
|
||||
if perp_info.trusted_market {
|
||||
let positive_contrib = perp_info
|
||||
.uncapped_health_contribution(health_type)
|
||||
.max(I80F48::ZERO);
|
||||
cm!(health += positive_contrib);
|
||||
}
|
||||
let positive_contrib = perp_info.health_contribution(health_type).max(I80F48::ZERO);
|
||||
cm!(health += positive_contrib);
|
||||
}
|
||||
health
|
||||
}
|
||||
|
@ -842,7 +853,7 @@ mod tests {
|
|||
oo1.data().native_coin_free = 3;
|
||||
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;
|
||||
perpaccount.record_trade(perp1.data(), 3, -I80F48::from(310u16));
|
||||
perpaccount.bids_base_lots = 7;
|
||||
|
@ -966,7 +977,7 @@ mod tests {
|
|||
oo2.data().native_pc_total = testcase.oo_1_3.0;
|
||||
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;
|
||||
perpaccount.record_trade(
|
||||
perp1.data(),
|
||||
|
@ -1033,27 +1044,27 @@ mod tests {
|
|||
..Default::default()
|
||||
},
|
||||
TestHealth1Case {
|
||||
// 2
|
||||
// 2: weighted positive perp pnl
|
||||
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()
|
||||
},
|
||||
TestHealth1Case {
|
||||
// 3
|
||||
// 3: negative perp pnl is not weighted
|
||||
perp1: (1, -100, 0, 0),
|
||||
expected_health: -100.0 + 0.8 * 1.0 * base_lots_to_quote,
|
||||
..Default::default()
|
||||
},
|
||||
TestHealth1Case {
|
||||
// 4
|
||||
// 4: perp health
|
||||
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()
|
||||
},
|
||||
TestHealth1Case {
|
||||
// 5
|
||||
// 5: perp health
|
||||
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()
|
||||
},
|
||||
TestHealth1Case { // 6, reserved oo funds
|
||||
|
|
|
@ -310,12 +310,13 @@ impl HealthCache {
|
|||
let prices = &perp_info.prices;
|
||||
let base_lot_size = I80F48::from(perp_info.base_lot_size);
|
||||
|
||||
// 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
|
||||
// If the price is sufficiently good then health will just increase from trading.
|
||||
// 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 {
|
||||
perp_info.init_asset_weight * prices.asset(health_type) - price
|
||||
perp_info.init_base_asset_weight * prices.asset(health_type) - price
|
||||
} 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 {
|
||||
return Ok(i64::MAX);
|
||||
|
@ -374,8 +375,7 @@ impl HealthCache {
|
|||
let perp_info = &start_cache.perp_infos[perp_info_index];
|
||||
let start_health_uncapped = start_health
|
||||
- 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
|
||||
// zero_health_ratio <= 0.
|
||||
let zero_health_amount = case1_start_i80f48
|
||||
|
@ -938,10 +938,12 @@ mod tests {
|
|||
let base_lot_size = 100;
|
||||
let default_perp_info = |x| PerpInfo {
|
||||
perp_market_index: 0,
|
||||
maint_asset_weight: I80F48::from_num(1.0 - x),
|
||||
init_asset_weight: I80F48::from_num(1.0 - x),
|
||||
maint_liab_weight: I80F48::from_num(1.0 + x),
|
||||
init_liab_weight: I80F48::from_num(1.0 + x),
|
||||
maint_base_asset_weight: I80F48::from_num(1.0 - x),
|
||||
init_base_asset_weight: I80F48::from_num(1.0 - x),
|
||||
maint_base_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_lots: 0,
|
||||
bids_base_lots: 0,
|
||||
|
@ -949,7 +951,6 @@ mod tests {
|
|||
quote: I80F48::ZERO,
|
||||
prices: Prices::new_single_price(I80F48::from_num(2.0)),
|
||||
has_open_orders: false,
|
||||
trusted_market: false,
|
||||
};
|
||||
|
||||
let health_cache = HealthCache {
|
||||
|
@ -1088,7 +1089,7 @@ mod tests {
|
|||
)
|
||||
.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);
|
||||
let perpaccount = account.ensure_perp_position(9, 1).unwrap().0;
|
||||
perpaccount.record_trade(perp1.data(), 10, I80F48::from(-110));
|
||||
|
@ -1126,8 +1127,8 @@ mod tests {
|
|||
|
||||
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 perp2 = mock_perp_market(group, oracle2.pubkey, 5.0, 8, 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), (0.05, 0.02));
|
||||
|
||||
let oracle1_account_info = oracle1.as_account_info();
|
||||
let oracle2_account_info = oracle2.as_account_info();
|
||||
|
@ -1180,7 +1181,7 @@ mod tests {
|
|||
)
|
||||
.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;
|
||||
let perpaccount = account3.ensure_perp_position(9, 1).unwrap().0;
|
||||
perpaccount.record_trade(perp1.data(), 10, I80F48::from(-100));
|
||||
|
|
|
@ -108,17 +108,19 @@ pub fn mock_perp_market(
|
|||
oracle: Pubkey,
|
||||
price: f64,
|
||||
market_index: PerpMarketIndex,
|
||||
init_weights: f64,
|
||||
maint_weights: f64,
|
||||
base_weights: (f64, f64),
|
||||
pnl_weights: (f64, f64),
|
||||
) -> TestAccount<PerpMarket> {
|
||||
let mut pm = TestAccount::<PerpMarket>::new_zeroed();
|
||||
pm.data().group = group;
|
||||
pm.data().oracle = oracle;
|
||||
pm.data().perp_market_index = market_index;
|
||||
pm.data().init_asset_weight = I80F48::from_num(1.0 - init_weights);
|
||||
pm.data().init_liab_weight = I80F48::from_num(1.0 + init_weights);
|
||||
pm.data().maint_asset_weight = I80F48::from_num(1.0 - maint_weights);
|
||||
pm.data().maint_liab_weight = I80F48::from_num(1.0 + maint_weights);
|
||||
pm.data().init_base_asset_weight = I80F48::from_num(1.0 - base_weights.0);
|
||||
pm.data().init_base_liab_weight = I80F48::from_num(1.0 + base_weights.0);
|
||||
pm.data().maint_base_asset_weight = I80F48::from_num(1.0 - base_weights.1);
|
||||
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().base_lot_size = 10;
|
||||
pm.data().stable_price_model.reset_to_price(price, 0);
|
||||
|
|
|
@ -56,10 +56,12 @@ pub fn perp_create_market(
|
|||
base_decimals: u8,
|
||||
quote_lot_size: i64,
|
||||
base_lot_size: i64,
|
||||
maint_asset_weight: f32,
|
||||
init_asset_weight: f32,
|
||||
maint_liab_weight: f32,
|
||||
init_liab_weight: f32,
|
||||
maint_base_asset_weight: f32,
|
||||
init_base_asset_weight: f32,
|
||||
maint_base_liab_weight: f32,
|
||||
init_base_liab_weight: f32,
|
||||
maint_pnl_asset_weight: f32,
|
||||
init_pnl_asset_weight: f32,
|
||||
liquidation_fee: f32,
|
||||
maker_fee: f32,
|
||||
taker_fee: f32,
|
||||
|
@ -67,7 +69,6 @@ pub fn perp_create_market(
|
|||
max_funding: f32,
|
||||
impact_quantity: i64,
|
||||
group_insurance_fund: bool,
|
||||
trusted_market: bool,
|
||||
fee_penalty: f32,
|
||||
settle_fee_flat: f32,
|
||||
settle_fee_amount_threshold: f32,
|
||||
|
@ -93,7 +94,7 @@ pub fn perp_create_market(
|
|||
group: ctx.accounts.group.key(),
|
||||
settle_token_index,
|
||||
perp_market_index,
|
||||
trusted_market: u8::from(trusted_market),
|
||||
blocked1: 0,
|
||||
group_insurance_fund: u8::from(group_insurance_fund),
|
||||
bump: *ctx.bumps.get("perp_market").ok_or(MangoError::SomeError)?,
|
||||
base_decimals,
|
||||
|
@ -106,10 +107,10 @@ pub fn perp_create_market(
|
|||
stable_price_model: StablePriceModel::default(),
|
||||
quote_lot_size,
|
||||
base_lot_size,
|
||||
maint_asset_weight: I80F48::from_num(maint_asset_weight),
|
||||
init_asset_weight: I80F48::from_num(init_asset_weight),
|
||||
maint_liab_weight: I80F48::from_num(maint_liab_weight),
|
||||
init_liab_weight: I80F48::from_num(init_liab_weight),
|
||||
maint_base_asset_weight: I80F48::from_num(maint_base_asset_weight),
|
||||
init_base_asset_weight: I80F48::from_num(init_base_asset_weight),
|
||||
maint_base_liab_weight: I80F48::from_num(maint_base_liab_weight),
|
||||
init_base_liab_weight: I80F48::from_num(init_base_liab_weight),
|
||||
open_interest: 0,
|
||||
seq_num: 0,
|
||||
registration_time: now_ts,
|
||||
|
@ -132,7 +133,10 @@ pub fn perp_create_market(
|
|||
padding3: Default::default(),
|
||||
settle_pnl_limit_window_size_ts,
|
||||
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 =
|
||||
|
|
|
@ -28,10 +28,12 @@ pub fn perp_edit_market(
|
|||
oracle_opt: Option<Pubkey>,
|
||||
oracle_config_opt: Option<OracleConfigParams>,
|
||||
base_decimals_opt: Option<u8>,
|
||||
maint_asset_weight_opt: Option<f32>,
|
||||
init_asset_weight_opt: Option<f32>,
|
||||
maint_liab_weight_opt: Option<f32>,
|
||||
init_liab_weight_opt: Option<f32>,
|
||||
maint_base_asset_weight_opt: Option<f32>,
|
||||
init_base_asset_weight_opt: Option<f32>,
|
||||
maint_base_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>,
|
||||
maker_fee_opt: Option<f32>,
|
||||
taker_fee_opt: Option<f32>,
|
||||
|
@ -39,7 +41,6 @@ pub fn perp_edit_market(
|
|||
max_funding_opt: Option<f32>,
|
||||
impact_quantity_opt: Option<i64>,
|
||||
group_insurance_fund_opt: Option<bool>,
|
||||
trusted_market_opt: Option<bool>,
|
||||
fee_penalty_opt: Option<f32>,
|
||||
settle_fee_flat_opt: Option<f32>,
|
||||
settle_fee_amount_threshold_opt: Option<f32>,
|
||||
|
@ -82,17 +83,23 @@ pub fn perp_edit_market(
|
|||
// quote_lot_size
|
||||
// base_lot_size
|
||||
|
||||
if let Some(maint_asset_weight) = maint_asset_weight_opt {
|
||||
perp_market.maint_asset_weight = I80F48::from_num(maint_asset_weight);
|
||||
if let Some(maint_base_asset_weight) = maint_base_asset_weight_opt {
|
||||
perp_market.maint_base_asset_weight = I80F48::from_num(maint_base_asset_weight);
|
||||
}
|
||||
if let Some(init_asset_weight) = init_asset_weight_opt {
|
||||
perp_market.init_asset_weight = I80F48::from_num(init_asset_weight);
|
||||
if let Some(init_base_asset_weight) = init_base_asset_weight_opt {
|
||||
perp_market.init_base_asset_weight = I80F48::from_num(init_base_asset_weight);
|
||||
}
|
||||
if let Some(maint_liab_weight) = maint_liab_weight_opt {
|
||||
perp_market.maint_liab_weight = I80F48::from_num(maint_liab_weight);
|
||||
if let Some(maint_base_liab_weight) = maint_base_liab_weight_opt {
|
||||
perp_market.maint_base_liab_weight = I80F48::from_num(maint_base_liab_weight);
|
||||
}
|
||||
if let Some(init_liab_weight) = init_liab_weight_opt {
|
||||
perp_market.init_liab_weight = I80F48::from_num(init_liab_weight);
|
||||
if let Some(init_base_liab_weight) = init_base_liab_weight_opt {
|
||||
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 {
|
||||
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 {
|
||||
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 {
|
||||
perp_market.settle_fee_flat = settle_fee_flat;
|
||||
|
|
|
@ -99,63 +99,62 @@ pub fn perp_liq_base_position(
|
|||
|
||||
// Take over the liqee's base in exchange for quote
|
||||
require_msg!(liqee_base_lots != 0, "liqee base position is zero");
|
||||
let (base_transfer, quote_transfer) =
|
||||
if liqee_base_lots > 0 {
|
||||
require_msg!(
|
||||
max_base_transfer > 0,
|
||||
"max_base_transfer must be positive when liqee's base_position is positive"
|
||||
);
|
||||
let (base_transfer, quote_transfer) = if liqee_base_lots > 0 {
|
||||
require_msg!(
|
||||
max_base_transfer > 0,
|
||||
"max_base_transfer must be positive when liqee's base_position is positive"
|
||||
);
|
||||
|
||||
// health gets reduced by `base * price * perp_init_asset_weight`
|
||||
// and increased by `base * price * (1 - liq_fee) * quote_init_asset_weight`
|
||||
let quote_init_asset_weight = I80F48::ONE;
|
||||
let fee_factor = cm!(I80F48::ONE - perp_market.liquidation_fee);
|
||||
let health_per_lot = cm!(price_per_lot
|
||||
* (-perp_market.init_asset_weight + quote_init_asset_weight * fee_factor));
|
||||
// health gets reduced by `base * price * perp_init_asset_weight`
|
||||
// and increased by `base * price * (1 - liq_fee) * quote_init_asset_weight`
|
||||
let quote_init_asset_weight = I80F48::ONE;
|
||||
let fee_factor = cm!(I80F48::ONE - perp_market.liquidation_fee);
|
||||
let health_per_lot = cm!(price_per_lot
|
||||
* (-perp_market.init_base_asset_weight + quote_init_asset_weight * fee_factor));
|
||||
|
||||
// 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)
|
||||
.checked_ceil()
|
||||
.unwrap()
|
||||
.checked_to_num()
|
||||
.unwrap();
|
||||
// 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)
|
||||
.checked_ceil()
|
||||
.unwrap()
|
||||
.checked_to_num()
|
||||
.unwrap();
|
||||
|
||||
let base_transfer = base_transfer_for_zero
|
||||
.min(liqee_base_lots)
|
||||
.min(max_base_transfer)
|
||||
.max(0);
|
||||
let quote_transfer = cm!(-I80F48::from(base_transfer) * price_per_lot * fee_factor);
|
||||
let base_transfer = base_transfer_for_zero
|
||||
.min(liqee_base_lots)
|
||||
.min(max_base_transfer)
|
||||
.max(0);
|
||||
let quote_transfer = cm!(-I80F48::from(base_transfer) * price_per_lot * fee_factor);
|
||||
|
||||
(base_transfer, quote_transfer) // base > 0, quote < 0
|
||||
} else {
|
||||
// liqee_base_lots < 0
|
||||
require_msg!(
|
||||
max_base_transfer < 0,
|
||||
"max_base_transfer must be negative when liqee's base_position is positive"
|
||||
);
|
||||
(base_transfer, quote_transfer) // base > 0, quote < 0
|
||||
} else {
|
||||
// liqee_base_lots < 0
|
||||
require_msg!(
|
||||
max_base_transfer < 0,
|
||||
"max_base_transfer must be negative when liqee's base_position is positive"
|
||||
);
|
||||
|
||||
// health gets increased by `base * price * perp_init_liab_weight`
|
||||
// and reduced by `base * price * (1 + liq_fee) * quote_init_liab_weight`
|
||||
let quote_init_liab_weight = I80F48::ONE;
|
||||
let fee_factor = cm!(I80F48::ONE + perp_market.liquidation_fee);
|
||||
let health_per_lot = cm!(price_per_lot
|
||||
* (perp_market.init_liab_weight - quote_init_liab_weight * fee_factor));
|
||||
// health gets increased by `base * price * perp_init_liab_weight`
|
||||
// and reduced by `base * price * (1 + liq_fee) * quote_init_liab_weight`
|
||||
let quote_init_liab_weight = I80F48::ONE;
|
||||
let fee_factor = cm!(I80F48::ONE + perp_market.liquidation_fee);
|
||||
let health_per_lot = cm!(price_per_lot
|
||||
* (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
|
||||
let base_transfer_for_zero: i64 = cm!(liqee_init_health / health_per_lot)
|
||||
.checked_floor()
|
||||
.unwrap()
|
||||
.checked_to_num()
|
||||
.unwrap();
|
||||
// (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)
|
||||
.checked_floor()
|
||||
.unwrap()
|
||||
.checked_to_num()
|
||||
.unwrap();
|
||||
|
||||
let base_transfer = base_transfer_for_zero
|
||||
.max(liqee_base_lots)
|
||||
.max(max_base_transfer)
|
||||
.min(0);
|
||||
let quote_transfer = cm!(-I80F48::from(base_transfer) * price_per_lot * fee_factor);
|
||||
let base_transfer = base_transfer_for_zero
|
||||
.max(liqee_base_lots)
|
||||
.max(max_base_transfer)
|
||||
.min(0);
|
||||
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
|
||||
// liqee and liqors entry and break even prices.
|
||||
|
|
|
@ -434,10 +434,12 @@ pub mod mango_v4 {
|
|||
base_decimals: u8,
|
||||
quote_lot_size: i64,
|
||||
base_lot_size: i64,
|
||||
maint_asset_weight: f32,
|
||||
init_asset_weight: f32,
|
||||
maint_liab_weight: f32,
|
||||
init_liab_weight: f32,
|
||||
maint_base_asset_weight: f32,
|
||||
init_base_asset_weight: f32,
|
||||
maint_base_liab_weight: f32,
|
||||
init_base_liab_weight: f32,
|
||||
maint_pnl_asset_weight: f32,
|
||||
init_pnl_asset_weight: f32,
|
||||
liquidation_fee: f32,
|
||||
maker_fee: f32,
|
||||
taker_fee: f32,
|
||||
|
@ -445,7 +447,6 @@ pub mod mango_v4 {
|
|||
max_funding: f32,
|
||||
impact_quantity: i64,
|
||||
group_insurance_fund: bool,
|
||||
trusted_market: bool,
|
||||
fee_penalty: f32,
|
||||
settle_fee_flat: f32,
|
||||
settle_fee_amount_threshold: f32,
|
||||
|
@ -463,10 +464,12 @@ pub mod mango_v4 {
|
|||
base_decimals,
|
||||
quote_lot_size,
|
||||
base_lot_size,
|
||||
maint_asset_weight,
|
||||
init_asset_weight,
|
||||
maint_liab_weight,
|
||||
init_liab_weight,
|
||||
maint_base_asset_weight,
|
||||
init_base_asset_weight,
|
||||
maint_base_liab_weight,
|
||||
init_base_liab_weight,
|
||||
maint_pnl_asset_weight,
|
||||
init_pnl_asset_weight,
|
||||
liquidation_fee,
|
||||
maker_fee,
|
||||
taker_fee,
|
||||
|
@ -474,7 +477,6 @@ pub mod mango_v4 {
|
|||
max_funding,
|
||||
impact_quantity,
|
||||
group_insurance_fund,
|
||||
trusted_market,
|
||||
fee_penalty,
|
||||
settle_fee_flat,
|
||||
settle_fee_amount_threshold,
|
||||
|
@ -490,10 +492,12 @@ pub mod mango_v4 {
|
|||
oracle_opt: Option<Pubkey>,
|
||||
oracle_config_opt: Option<OracleConfigParams>,
|
||||
base_decimals_opt: Option<u8>,
|
||||
maint_asset_weight_opt: Option<f32>,
|
||||
init_asset_weight_opt: Option<f32>,
|
||||
maint_liab_weight_opt: Option<f32>,
|
||||
init_liab_weight_opt: Option<f32>,
|
||||
maint_base_asset_weight_opt: Option<f32>,
|
||||
init_base_asset_weight_opt: Option<f32>,
|
||||
maint_base_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>,
|
||||
maker_fee_opt: Option<f32>,
|
||||
taker_fee_opt: Option<f32>,
|
||||
|
@ -501,7 +505,6 @@ pub mod mango_v4 {
|
|||
max_funding_opt: Option<f32>,
|
||||
impact_quantity_opt: Option<i64>,
|
||||
group_insurance_fund_opt: Option<bool>,
|
||||
trusted_market_opt: Option<bool>,
|
||||
fee_penalty_opt: Option<f32>,
|
||||
settle_fee_flat_opt: Option<f32>,
|
||||
settle_fee_amount_threshold_opt: Option<f32>,
|
||||
|
@ -518,10 +521,12 @@ pub mod mango_v4 {
|
|||
oracle_opt,
|
||||
oracle_config_opt,
|
||||
base_decimals_opt,
|
||||
maint_asset_weight_opt,
|
||||
init_asset_weight_opt,
|
||||
maint_liab_weight_opt,
|
||||
init_liab_weight_opt,
|
||||
maint_base_asset_weight_opt,
|
||||
init_base_asset_weight_opt,
|
||||
maint_base_liab_weight_opt,
|
||||
init_base_liab_weight_opt,
|
||||
maint_pnl_asset_weight_opt,
|
||||
init_pnl_asset_weight_opt,
|
||||
liquidation_fee_opt,
|
||||
maker_fee_opt,
|
||||
taker_fee_opt,
|
||||
|
@ -529,7 +534,6 @@ pub mod mango_v4 {
|
|||
max_funding_opt,
|
||||
impact_quantity_opt,
|
||||
group_insurance_fund_opt,
|
||||
trusted_market_opt,
|
||||
fee_penalty_opt,
|
||||
settle_fee_flat_opt,
|
||||
settle_fee_amount_threshold_opt,
|
||||
|
|
|
@ -88,10 +88,10 @@ mod tests {
|
|||
let mut perp_market = PerpMarket::zeroed();
|
||||
perp_market.quote_lot_size = 1;
|
||||
perp_market.base_lot_size = 1;
|
||||
perp_market.maint_asset_weight = I80F48::ONE;
|
||||
perp_market.maint_liab_weight = I80F48::ONE;
|
||||
perp_market.init_asset_weight = I80F48::ONE;
|
||||
perp_market.init_liab_weight = I80F48::ONE;
|
||||
perp_market.maint_base_asset_weight = I80F48::ONE;
|
||||
perp_market.maint_base_liab_weight = I80F48::ONE;
|
||||
perp_market.init_base_asset_weight = I80F48::ONE;
|
||||
perp_market.init_base_liab_weight = I80F48::ONE;
|
||||
|
||||
(perp_market, oracle_price, event_queue, book)
|
||||
}
|
||||
|
|
|
@ -26,8 +26,8 @@ pub struct PerpMarket {
|
|||
/// Lookup indices
|
||||
pub perp_market_index: PerpMarketIndex,
|
||||
|
||||
/// May this market contribute positive values to health?
|
||||
pub trusted_market: u8,
|
||||
// Used to store trusted_market here
|
||||
pub blocked1: u8,
|
||||
|
||||
/// Is this market covered by the group insurance fund?
|
||||
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
|
||||
// the health-reference token and have 1 for price and weights
|
||||
pub maint_asset_weight: I80F48,
|
||||
pub init_asset_weight: I80F48,
|
||||
pub maint_liab_weight: I80F48,
|
||||
pub init_liab_weight: I80F48,
|
||||
pub maint_base_asset_weight: I80F48,
|
||||
pub init_base_asset_weight: I80F48,
|
||||
pub maint_base_liab_weight: I80F48,
|
||||
pub init_base_liab_weight: I80F48,
|
||||
|
||||
pub open_interest: i64,
|
||||
|
||||
|
@ -114,8 +114,12 @@ pub struct PerpMarket {
|
|||
pub settle_pnl_limit_window_size_ts: u64,
|
||||
|
||||
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!(
|
||||
|
@ -149,7 +153,9 @@ const_assert_eq!(
|
|||
+ 8
|
||||
+ 8
|
||||
+ 1
|
||||
+ 1943
|
||||
+ 7
|
||||
+ 2 * 16
|
||||
+ 1904
|
||||
);
|
||||
const_assert_eq!(size_of::<PerpMarket>(), 2808);
|
||||
const_assert_eq!(size_of::<PerpMarket>() % 8, 0);
|
||||
|
@ -173,10 +179,6 @@ impl PerpMarket {
|
|||
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 {
|
||||
I80F48::from_num(self.settle_pnl_limit_factor)
|
||||
}
|
||||
|
@ -288,8 +290,8 @@ impl PerpMarket {
|
|||
oracle_price: I80F48,
|
||||
) -> bool {
|
||||
match side {
|
||||
Side::Bid => native_price <= cm!(self.maint_liab_weight * oracle_price),
|
||||
Side::Ask => native_price >= cm!(self.maint_asset_weight * oracle_price),
|
||||
Side::Bid => native_price <= cm!(self.maint_base_liab_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(),
|
||||
settle_token_index: 0,
|
||||
perp_market_index: 0,
|
||||
trusted_market: 0,
|
||||
blocked1: 0,
|
||||
group_insurance_fund: 0,
|
||||
bump: 0,
|
||||
base_decimals: 0,
|
||||
|
@ -336,10 +338,10 @@ impl PerpMarket {
|
|||
stable_price_model: StablePriceModel::default(),
|
||||
quote_lot_size: 1,
|
||||
base_lot_size: 1,
|
||||
maint_asset_weight: I80F48::from(1),
|
||||
init_asset_weight: I80F48::from(1),
|
||||
maint_liab_weight: I80F48::from(1),
|
||||
init_liab_weight: I80F48::from(1),
|
||||
maint_base_asset_weight: I80F48::from(1),
|
||||
init_base_asset_weight: I80F48::from(1),
|
||||
maint_base_liab_weight: I80F48::from(1),
|
||||
init_base_liab_weight: I80F48::from(1),
|
||||
open_interest: 0,
|
||||
seq_num: 0,
|
||||
registration_time: 0,
|
||||
|
@ -362,7 +364,10 @@ impl PerpMarket {
|
|||
padding3: Default::default(),
|
||||
settle_pnl_limit_window_size_ts: 24 * 60 * 60,
|
||||
reduce_only: 0,
|
||||
reserved: [0; 1943],
|
||||
padding4: Default::default(),
|
||||
maint_pnl_asset_weight: I80F48::ONE,
|
||||
init_pnl_asset_weight: I80F48::ONE,
|
||||
reserved: [0; 1904],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2543,15 +2543,16 @@ pub struct PerpCreateMarketInstruction {
|
|||
pub base_decimals: u8,
|
||||
pub quote_lot_size: i64,
|
||||
pub base_lot_size: i64,
|
||||
pub maint_asset_weight: f32,
|
||||
pub init_asset_weight: f32,
|
||||
pub maint_liab_weight: f32,
|
||||
pub init_liab_weight: f32,
|
||||
pub maint_base_asset_weight: f32,
|
||||
pub init_base_asset_weight: f32,
|
||||
pub maint_base_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 maker_fee: f32,
|
||||
pub taker_fee: f32,
|
||||
pub group_insurance_fund: bool,
|
||||
pub trusted_market: bool,
|
||||
pub fee_penalty: f32,
|
||||
pub settle_fee_flat: f32,
|
||||
pub settle_fee_amount_threshold: f32,
|
||||
|
@ -2599,10 +2600,12 @@ impl ClientInstruction for PerpCreateMarketInstruction {
|
|||
perp_market_index: self.perp_market_index,
|
||||
quote_lot_size: self.quote_lot_size,
|
||||
base_lot_size: self.base_lot_size,
|
||||
maint_asset_weight: self.maint_asset_weight,
|
||||
init_asset_weight: self.init_asset_weight,
|
||||
maint_liab_weight: self.maint_liab_weight,
|
||||
init_liab_weight: self.init_liab_weight,
|
||||
maint_base_asset_weight: self.maint_base_asset_weight,
|
||||
init_base_asset_weight: self.init_base_asset_weight,
|
||||
maint_base_liab_weight: self.maint_base_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,
|
||||
maker_fee: self.maker_fee,
|
||||
taker_fee: self.taker_fee,
|
||||
|
@ -2611,7 +2614,6 @@ impl ClientInstruction for PerpCreateMarketInstruction {
|
|||
impact_quantity: 100,
|
||||
base_decimals: self.base_decimals,
|
||||
group_insurance_fund: self.group_insurance_fund,
|
||||
trusted_market: self.trusted_market,
|
||||
fee_penalty: self.fee_penalty,
|
||||
settle_fee_flat: self.settle_fee_flat,
|
||||
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_config_opt: None,
|
||||
base_decimals_opt: None,
|
||||
maint_asset_weight_opt: None,
|
||||
init_asset_weight_opt: None,
|
||||
maint_liab_weight_opt: None,
|
||||
init_liab_weight_opt: None,
|
||||
maint_base_asset_weight_opt: None,
|
||||
init_base_asset_weight_opt: None,
|
||||
maint_base_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,
|
||||
maker_fee_opt: None,
|
||||
taker_fee_opt: None,
|
||||
|
@ -2667,7 +2671,6 @@ fn perp_edit_instruction_default() -> mango_v4::instruction::PerpEditMarket {
|
|||
max_funding_opt: None,
|
||||
impact_quantity_opt: None,
|
||||
group_insurance_fund_opt: None,
|
||||
trusted_market_opt: None,
|
||||
fee_penalty_opt: None,
|
||||
settle_fee_flat_opt: None,
|
||||
settle_fee_amount_threshold_opt: None,
|
||||
|
|
|
@ -215,10 +215,10 @@ async fn test_health_compute_perp() -> Result<(), TransportError> {
|
|||
perp_market_index: perp_market_index as PerpMarketIndex,
|
||||
quote_lot_size: 10,
|
||||
base_lot_size: 100,
|
||||
maint_asset_weight: 0.975,
|
||||
init_asset_weight: 0.95,
|
||||
maint_liab_weight: 1.025,
|
||||
init_liab_weight: 1.05,
|
||||
maint_base_asset_weight: 0.975,
|
||||
init_base_asset_weight: 0.95,
|
||||
maint_base_liab_weight: 1.025,
|
||||
init_base_liab_weight: 1.05,
|
||||
liquidation_fee: 0.012,
|
||||
maker_fee: 0.0002,
|
||||
taker_fee: 0.000,
|
||||
|
|
|
@ -56,10 +56,10 @@ async fn test_liq_perps_force_cancel() -> Result<(), TransportError> {
|
|||
perp_market_index: 0,
|
||||
quote_lot_size: 10,
|
||||
base_lot_size: 100,
|
||||
maint_asset_weight: 0.8,
|
||||
init_asset_weight: 0.6,
|
||||
maint_liab_weight: 1.2,
|
||||
init_liab_weight: 1.4,
|
||||
maint_base_asset_weight: 0.8,
|
||||
init_base_asset_weight: 0.6,
|
||||
maint_base_liab_weight: 1.2,
|
||||
init_base_liab_weight: 1.4,
|
||||
liquidation_fee: 0.05,
|
||||
maker_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,
|
||||
quote_lot_size: 10,
|
||||
base_lot_size: 100,
|
||||
maint_asset_weight: 0.8,
|
||||
init_asset_weight: 0.6,
|
||||
maint_liab_weight: 1.2,
|
||||
init_liab_weight: 1.4,
|
||||
maint_base_asset_weight: 0.8,
|
||||
init_base_asset_weight: 0.6,
|
||||
maint_base_liab_weight: 1.2,
|
||||
init_base_liab_weight: 1.4,
|
||||
liquidation_fee: 0.05,
|
||||
maker_fee: 0.0,
|
||||
taker_fee: 0.0,
|
||||
|
@ -843,10 +843,10 @@ async fn test_liq_perps_bankruptcy() -> Result<(), TransportError> {
|
|||
perp_market_index,
|
||||
quote_lot_size: 1,
|
||||
base_lot_size: 100,
|
||||
maint_asset_weight: 0.8,
|
||||
init_asset_weight: 0.6,
|
||||
maint_liab_weight: 1.2,
|
||||
init_liab_weight: 1.4,
|
||||
maint_base_asset_weight: 0.8,
|
||||
init_base_asset_weight: 0.6,
|
||||
maint_base_liab_weight: 1.2,
|
||||
init_base_liab_weight: 1.4,
|
||||
liquidation_fee: 0.05,
|
||||
maker_fee: 0.0,
|
||||
taker_fee: 0.0,
|
||||
|
|
|
@ -76,10 +76,10 @@ async fn test_perp_fixed() -> Result<(), TransportError> {
|
|||
perp_market_index: 0,
|
||||
quote_lot_size: 10,
|
||||
base_lot_size: 100,
|
||||
maint_asset_weight: 0.975,
|
||||
init_asset_weight: 0.95,
|
||||
maint_liab_weight: 1.025,
|
||||
init_liab_weight: 1.05,
|
||||
maint_base_asset_weight: 0.975,
|
||||
init_base_asset_weight: 0.95,
|
||||
maint_base_liab_weight: 1.025,
|
||||
init_base_liab_weight: 1.05,
|
||||
liquidation_fee: 0.012,
|
||||
maker_fee: -0.0001,
|
||||
taker_fee: 0.0002,
|
||||
|
@ -520,10 +520,10 @@ async fn test_perp_oracle_peg() -> Result<(), TransportError> {
|
|||
perp_market_index: 0,
|
||||
quote_lot_size: 10,
|
||||
base_lot_size: 10000,
|
||||
maint_asset_weight: 0.975,
|
||||
init_asset_weight: 0.95,
|
||||
maint_liab_weight: 1.025,
|
||||
init_liab_weight: 1.05,
|
||||
maint_base_asset_weight: 0.975,
|
||||
init_base_asset_weight: 0.95,
|
||||
maint_base_liab_weight: 1.025,
|
||||
init_base_liab_weight: 1.05,
|
||||
liquidation_fee: 0.012,
|
||||
maker_fee: -0.0001,
|
||||
taker_fee: 0.0002,
|
||||
|
|
|
@ -73,10 +73,10 @@ async fn test_perp_settle_pnl() -> Result<(), TransportError> {
|
|||
perp_market_index: 0,
|
||||
quote_lot_size: 10,
|
||||
base_lot_size: 100,
|
||||
maint_asset_weight: 0.975,
|
||||
init_asset_weight: 0.95,
|
||||
maint_liab_weight: 1.025,
|
||||
init_liab_weight: 1.05,
|
||||
maint_base_asset_weight: 0.975,
|
||||
init_base_asset_weight: 0.95,
|
||||
maint_base_liab_weight: 1.025,
|
||||
init_base_liab_weight: 1.05,
|
||||
liquidation_fee: 0.012,
|
||||
maker_fee: 0.0002,
|
||||
taker_fee: 0.000,
|
||||
|
@ -103,10 +103,10 @@ async fn test_perp_settle_pnl() -> Result<(), TransportError> {
|
|||
perp_market_index: 1,
|
||||
quote_lot_size: 10,
|
||||
base_lot_size: 100,
|
||||
maint_asset_weight: 0.975,
|
||||
init_asset_weight: 0.95,
|
||||
maint_liab_weight: 1.025,
|
||||
init_liab_weight: 1.05,
|
||||
maint_base_asset_weight: 0.975,
|
||||
init_base_asset_weight: 0.95,
|
||||
maint_base_liab_weight: 1.025,
|
||||
init_base_liab_weight: 1.05,
|
||||
liquidation_fee: 0.012,
|
||||
maker_fee: 0.0002,
|
||||
taker_fee: 0.000,
|
||||
|
@ -576,10 +576,10 @@ async fn test_perp_settle_pnl_fees() -> Result<(), TransportError> {
|
|||
perp_market_index: 0,
|
||||
quote_lot_size: 10,
|
||||
base_lot_size: 100,
|
||||
maint_asset_weight: 1.0,
|
||||
init_asset_weight: 1.0,
|
||||
maint_liab_weight: 1.0,
|
||||
init_liab_weight: 1.0,
|
||||
maint_base_asset_weight: 1.0,
|
||||
init_base_asset_weight: 1.0,
|
||||
maint_base_liab_weight: 1.0,
|
||||
init_base_liab_weight: 1.0,
|
||||
liquidation_fee: 0.0,
|
||||
maker_fee: 0.0,
|
||||
taker_fee: 0.0,
|
||||
|
@ -848,10 +848,10 @@ async fn test_perp_pnl_settle_limit() -> Result<(), TransportError> {
|
|||
perp_market_index: 0,
|
||||
quote_lot_size: 10,
|
||||
base_lot_size: 100,
|
||||
maint_asset_weight: 0.975,
|
||||
init_asset_weight: 0.95,
|
||||
maint_liab_weight: 1.025,
|
||||
init_liab_weight: 1.05,
|
||||
maint_base_asset_weight: 0.975,
|
||||
init_base_asset_weight: 0.95,
|
||||
maint_base_liab_weight: 1.025,
|
||||
init_base_liab_weight: 1.05,
|
||||
liquidation_fee: 0.012,
|
||||
maker_fee: 0.0,
|
||||
taker_fee: 0.0,
|
||||
|
|
|
@ -152,10 +152,10 @@ async fn test_perp_settle_fees() -> Result<(), TransportError> {
|
|||
perp_market_index: 0,
|
||||
quote_lot_size: 10,
|
||||
base_lot_size: 100,
|
||||
maint_asset_weight: 0.975,
|
||||
init_asset_weight: 0.95,
|
||||
maint_liab_weight: 1.025,
|
||||
init_liab_weight: 1.05,
|
||||
maint_base_asset_weight: 0.975,
|
||||
init_base_asset_weight: 0.95,
|
||||
maint_base_liab_weight: 1.025,
|
||||
init_base_liab_weight: 1.05,
|
||||
liquidation_fee: 0.012,
|
||||
maker_fee: 0.0002,
|
||||
taker_fee: 0.000,
|
||||
|
@ -182,10 +182,10 @@ async fn test_perp_settle_fees() -> Result<(), TransportError> {
|
|||
perp_market_index: 1,
|
||||
quote_lot_size: 10,
|
||||
base_lot_size: 100,
|
||||
maint_asset_weight: 0.975,
|
||||
init_asset_weight: 0.95,
|
||||
maint_liab_weight: 1.025,
|
||||
init_liab_weight: 1.05,
|
||||
maint_base_asset_weight: 0.975,
|
||||
init_base_asset_weight: 0.95,
|
||||
maint_base_liab_weight: 1.025,
|
||||
init_base_liab_weight: 1.05,
|
||||
liquidation_fee: 0.012,
|
||||
maker_fee: 0.0002,
|
||||
taker_fee: 0.000,
|
||||
|
|
|
@ -251,10 +251,10 @@ async fn test_perp_reduce_only() -> Result<(), TransportError> {
|
|||
perp_market_index: 0,
|
||||
quote_lot_size: 10,
|
||||
base_lot_size: 100,
|
||||
maint_asset_weight: 0.975,
|
||||
init_asset_weight: 0.95,
|
||||
maint_liab_weight: 1.025,
|
||||
init_liab_weight: 1.05,
|
||||
maint_base_asset_weight: 0.975,
|
||||
init_base_asset_weight: 0.95,
|
||||
maint_base_liab_weight: 1.025,
|
||||
init_base_liab_weight: 1.05,
|
||||
liquidation_fee: 0.012,
|
||||
maker_fee: 0.0002,
|
||||
taker_fee: 0.000,
|
||||
|
|
|
@ -31,17 +31,19 @@ function mockBankAndOracle(
|
|||
|
||||
function mockPerpMarket(
|
||||
perpMarketIndex: number,
|
||||
maintWeight: number,
|
||||
initWeight: number,
|
||||
maintBaseWeight: number,
|
||||
initBaseWeight: number,
|
||||
baseLotSize: number,
|
||||
price: number,
|
||||
): PerpMarket {
|
||||
return {
|
||||
perpMarketIndex,
|
||||
maintAssetWeight: I80F48.fromNumber(1 - maintWeight),
|
||||
initAssetWeight: I80F48.fromNumber(1 - initWeight),
|
||||
maintLiabWeight: I80F48.fromNumber(1 + maintWeight),
|
||||
initLiabWeight: I80F48.fromNumber(1 + initWeight),
|
||||
maintBaseAssetWeight: I80F48.fromNumber(1 - maintBaseWeight),
|
||||
initBaseAssetWeight: I80F48.fromNumber(1 - initBaseWeight),
|
||||
maintBaseLiabWeight: I80F48.fromNumber(1 + maintBaseWeight),
|
||||
initBaseLiabWeight: I80F48.fromNumber(1 + initBaseWeight),
|
||||
maintPnlAssetWeight: I80F48.fromNumber(1 - 0.02),
|
||||
initPnlAssetWeight: I80F48.fromNumber(1 - 0.05),
|
||||
price: I80F48.fromNumber(price),
|
||||
stablePriceModel: { stablePrice: price } as StablePriceModel,
|
||||
quoteLotSize: new BN(100),
|
||||
|
@ -231,7 +233,9 @@ describe('Health Cache', () => {
|
|||
const hc = new HealthCache([ti1, ti2, ti3], [si1, si2], [pi1]);
|
||||
const health = hc.health(HealthType.init).toNumber();
|
||||
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);
|
||||
}
|
||||
|
@ -276,18 +280,18 @@ describe('Health Cache', () => {
|
|||
});
|
||||
|
||||
testFixture({
|
||||
name: '2',
|
||||
name: '2: weighted positive perp pnl',
|
||||
token1: 0,
|
||||
token2: 0,
|
||||
token3: 0,
|
||||
oo12: [0, 0],
|
||||
oo13: [0, 0],
|
||||
perp1: [-10, 100, 0, 0],
|
||||
expectedHealth: 0,
|
||||
perp1: [-1, 100, 0, 0],
|
||||
expectedHealth: 0.95 * (100.0 - 1.2 * 1.0 * baseLotsToQuote),
|
||||
});
|
||||
|
||||
testFixture({
|
||||
name: '3',
|
||||
name: '3: negative perp pnl is not weighted',
|
||||
token1: 0,
|
||||
token2: 0,
|
||||
token3: 0,
|
||||
|
@ -298,25 +302,25 @@ describe('Health Cache', () => {
|
|||
});
|
||||
|
||||
testFixture({
|
||||
name: '4',
|
||||
name: '4: perp health',
|
||||
token1: 0,
|
||||
token2: 0,
|
||||
token3: 0,
|
||||
oo12: [0, 0],
|
||||
oo13: [0, 0],
|
||||
perp1: [10, 100, 0, 0],
|
||||
expectedHealth: 0,
|
||||
expectedHealth: 0.95 * (100.0 + 0.8 * 10.0 * baseLotsToQuote),
|
||||
});
|
||||
|
||||
testFixture({
|
||||
name: '5',
|
||||
name: '5: perp health',
|
||||
token1: 0,
|
||||
token2: 0,
|
||||
token3: 0,
|
||||
oo12: [0, 0],
|
||||
oo13: [0, 0],
|
||||
perp1: [30, -100, 0, 0],
|
||||
expectedHealth: 0,
|
||||
expectedHealth: 0.95 * (-100.0 + 0.8 * 30.0 * baseLotsToQuote),
|
||||
});
|
||||
|
||||
testFixture({
|
||||
|
@ -326,7 +330,7 @@ describe('Health Cache', () => {
|
|||
token3: -10,
|
||||
oo12: [1, 1],
|
||||
oo13: [1, 1],
|
||||
perp1: [30, -100, 0, 0],
|
||||
perp1: [0, 0, 0, 0],
|
||||
expectedHealth:
|
||||
// tokens
|
||||
-100.0 * 1.2 -
|
||||
|
|
|
@ -206,13 +206,11 @@ export class HealthCache {
|
|||
health.iadd(contrib);
|
||||
}
|
||||
for (const perpInfo of this.perpInfos) {
|
||||
if (perpInfo.trustedMarket) {
|
||||
const positiveContrib = perpInfo
|
||||
.uncappedHealthContribution(HealthType.maint)
|
||||
.max(ZERO_I80F48());
|
||||
// console.log(` - pi ${positiveContrib}`);
|
||||
health.iadd(positiveContrib);
|
||||
}
|
||||
const positiveContrib = perpInfo
|
||||
.healthContribution(HealthType.maint)
|
||||
.max(ZERO_I80F48());
|
||||
// console.log(` - pi ${positiveContrib}`);
|
||||
health.iadd(positiveContrib);
|
||||
}
|
||||
return health;
|
||||
}
|
||||
|
@ -1052,8 +1050,12 @@ export class HealthCache {
|
|||
// If the price is sufficiently good then health will just increase from trading
|
||||
const finalHealthSlope =
|
||||
direction == 1
|
||||
? perpInfo.initAssetWeight.mul(prices.asset(HealthType.init)).sub(price)
|
||||
: price.sub(perpInfo.initLiabWeight.mul(prices.liab(HealthType.init)));
|
||||
? perpInfo.initBaseAssetWeight
|
||||
.mul(prices.asset(HealthType.init))
|
||||
.sub(price)
|
||||
: price.sub(
|
||||
perpInfo.initBaseLiabWeight.mul(prices.liab(HealthType.init)),
|
||||
);
|
||||
if (finalHealthSlope.gte(ZERO_I80F48())) {
|
||||
return MAX_I80F48();
|
||||
}
|
||||
|
@ -1123,7 +1125,7 @@ export class HealthCache {
|
|||
const perpInfo = startCache.perpInfos[perpInfoIndex];
|
||||
const startHealthUncapped = startHealth
|
||||
.sub(perpInfo.healthContribution(HealthType.init))
|
||||
.add(perpInfo.uncappedHealthContribution(HealthType.init));
|
||||
.add(perpInfo.unweightedHealthContribution(HealthType.init));
|
||||
|
||||
const zeroHealthAmount = case1Start
|
||||
.sub(startHealthUncapped.div(finalHealthSlope).div(baseLotSize))
|
||||
|
@ -1420,10 +1422,12 @@ export class Serum3Info {
|
|||
export class PerpInfo {
|
||||
constructor(
|
||||
public perpMarketIndex: number,
|
||||
public maintAssetWeight: I80F48,
|
||||
public initAssetWeight: I80F48,
|
||||
public maintLiabWeight: I80F48,
|
||||
public initLiabWeight: I80F48,
|
||||
public maintBaseAssetWeight: I80F48,
|
||||
public initBaseAssetWeight: I80F48,
|
||||
public maintBaseLiabWeight: I80F48,
|
||||
public initBaseLiabWeight: I80F48,
|
||||
public maintPnlAssetWeight: I80F48,
|
||||
public initPnlAssetWeight: I80F48,
|
||||
public baseLotSize: BN,
|
||||
public baseLots: BN,
|
||||
public bidsBaseLots: BN,
|
||||
|
@ -1431,16 +1435,17 @@ export class PerpInfo {
|
|||
public quote: I80F48,
|
||||
public prices: Prices,
|
||||
public hasOpenOrders: boolean,
|
||||
public trustedMarket: boolean,
|
||||
) {}
|
||||
|
||||
static fromDto(dto: PerpInfoDto): PerpInfo {
|
||||
return new PerpInfo(
|
||||
dto.perpMarketIndex,
|
||||
I80F48.from(dto.maintAssetWeight),
|
||||
I80F48.from(dto.initAssetWeight),
|
||||
I80F48.from(dto.maintLiabWeight),
|
||||
I80F48.from(dto.initLiabWeight),
|
||||
I80F48.from(dto.maintBaseAssetWeight),
|
||||
I80F48.from(dto.initBaseAssetWeight),
|
||||
I80F48.from(dto.maintBaseLiabWeight),
|
||||
I80F48.from(dto.initBaseLiabWeight),
|
||||
I80F48.from(dto.maintPnlAssetWeight),
|
||||
I80F48.from(dto.initPnlAssetWeight),
|
||||
dto.baseLotSize,
|
||||
dto.baseLots,
|
||||
dto.bidsBaseLots,
|
||||
|
@ -1451,7 +1456,6 @@ export class PerpInfo {
|
|||
I80F48.from(dto.prices.stable),
|
||||
),
|
||||
dto.hasOpenOrders,
|
||||
dto.trustedMarket,
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -1473,10 +1477,12 @@ export class PerpInfo {
|
|||
|
||||
return new PerpInfo(
|
||||
perpMarket.perpMarketIndex,
|
||||
perpMarket.maintAssetWeight,
|
||||
perpMarket.initAssetWeight,
|
||||
perpMarket.maintLiabWeight,
|
||||
perpMarket.initLiabWeight,
|
||||
perpMarket.maintBaseAssetWeight,
|
||||
perpMarket.initBaseAssetWeight,
|
||||
perpMarket.maintBaseLiabWeight,
|
||||
perpMarket.initBaseLiabWeight,
|
||||
perpMarket.maintPnlAssetWeight,
|
||||
perpMarket.initPnlAssetWeight,
|
||||
perpMarket.baseLotSize,
|
||||
baseLots,
|
||||
perpPosition.bidsBaseLots,
|
||||
|
@ -1487,17 +1493,22 @@ export class PerpInfo {
|
|||
I80F48.fromNumber(perpMarket.stablePriceModel.stablePrice),
|
||||
),
|
||||
perpPosition.hasOpenOrders(),
|
||||
perpMarket.trustedMarket,
|
||||
);
|
||||
}
|
||||
|
||||
healthContribution(healthType: HealthType | undefined): I80F48 {
|
||||
return this.trustedMarket
|
||||
? this.uncappedHealthContribution(healthType)
|
||||
: this.uncappedHealthContribution(healthType).min(ZERO_I80F48());
|
||||
const contrib = this.unweightedHealthContribution(healthType);
|
||||
if (contrib.gt(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(
|
||||
pi: PerpInfo,
|
||||
ordersBaseLots: BN,
|
||||
|
@ -1510,18 +1521,18 @@ export class PerpInfo {
|
|||
let weight, basePrice;
|
||||
if (healthType == HealthType.init) {
|
||||
if (netBaseNative.isNeg()) {
|
||||
weight = pi.initLiabWeight;
|
||||
weight = pi.initBaseLiabWeight;
|
||||
basePrice = pi.prices.liab(healthType);
|
||||
} else {
|
||||
weight = pi.initAssetWeight;
|
||||
weight = pi.initBaseAssetWeight;
|
||||
basePrice = pi.prices.asset(healthType);
|
||||
}
|
||||
} else {
|
||||
if (netBaseNative.isNeg()) {
|
||||
weight = pi.maintLiabWeight;
|
||||
weight = pi.maintBaseLiabWeight;
|
||||
basePrice = pi.prices.liab(healthType);
|
||||
} else {
|
||||
weight = pi.maintAssetWeight;
|
||||
weight = pi.maintBaseAssetWeight;
|
||||
basePrice = pi.prices.asset(healthType);
|
||||
}
|
||||
}
|
||||
|
@ -1557,10 +1568,12 @@ export class PerpInfo {
|
|||
static emptyFromPerpMarket(perpMarket: PerpMarket): PerpInfo {
|
||||
return new PerpInfo(
|
||||
perpMarket.perpMarketIndex,
|
||||
perpMarket.maintAssetWeight,
|
||||
perpMarket.initAssetWeight,
|
||||
perpMarket.maintLiabWeight,
|
||||
perpMarket.initLiabWeight,
|
||||
perpMarket.maintBaseAssetWeight,
|
||||
perpMarket.initBaseAssetWeight,
|
||||
perpMarket.maintBaseLiabWeight,
|
||||
perpMarket.initBaseLiabWeight,
|
||||
perpMarket.maintPnlAssetWeight,
|
||||
perpMarket.initPnlAssetWeight,
|
||||
perpMarket.baseLotSize,
|
||||
new BN(0),
|
||||
new BN(0),
|
||||
|
@ -1571,7 +1584,6 @@ export class PerpInfo {
|
|||
I80F48.fromNumber(perpMarket.stablePriceModel.stablePrice),
|
||||
),
|
||||
false,
|
||||
perpMarket.trustedMarket,
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -1580,7 +1592,7 @@ export class PerpInfo {
|
|||
this.baseLots
|
||||
}, quote: ${this.quote}, oraclePrice: ${
|
||||
this.prices.oracle
|
||||
}, uncapped health contribution ${this.uncappedHealthContribution(
|
||||
}, uncapped health contribution ${this.unweightedHealthContribution(
|
||||
HealthType.init,
|
||||
)}`;
|
||||
}
|
||||
|
@ -1641,10 +1653,12 @@ export class Serum3InfoDto {
|
|||
|
||||
export class PerpInfoDto {
|
||||
perpMarketIndex: number;
|
||||
maintAssetWeight: I80F48Dto;
|
||||
initAssetWeight: I80F48Dto;
|
||||
maintLiabWeight: I80F48Dto;
|
||||
initLiabWeight: I80F48Dto;
|
||||
maintBaseAssetWeight: I80F48Dto;
|
||||
initBaseAssetWeight: I80F48Dto;
|
||||
maintBaseLiabWeight: I80F48Dto;
|
||||
initBaseLiabWeight: I80F48Dto;
|
||||
maintPnlAssetWeight: I80F48Dto;
|
||||
initPnlAssetWeight: I80F48Dto;
|
||||
public baseLotSize: BN;
|
||||
public baseLots: BN;
|
||||
public bidsBaseLots: BN;
|
||||
|
@ -1652,5 +1666,4 @@ export class PerpInfoDto {
|
|||
quote: I80F48Dto;
|
||||
prices: { oracle: I80F48Dto; stable: I80F48Dto };
|
||||
hasOpenOrders: boolean;
|
||||
trustedMarket: boolean;
|
||||
}
|
||||
|
|
|
@ -30,10 +30,10 @@ export type ParsedFillEvent = Modify<
|
|||
export class PerpMarket {
|
||||
public name: string;
|
||||
public oracleConfig: OracleConfig;
|
||||
public maintAssetWeight: I80F48;
|
||||
public initAssetWeight: I80F48;
|
||||
public maintLiabWeight: I80F48;
|
||||
public initLiabWeight: I80F48;
|
||||
public maintBaseAssetWeight: I80F48;
|
||||
public initBaseAssetWeight: I80F48;
|
||||
public maintBaseLiabWeight: I80F48;
|
||||
public initBaseLiabWeight: I80F48;
|
||||
public liquidationFee: I80F48;
|
||||
public makerFee: I80F48;
|
||||
public takerFee: I80F48;
|
||||
|
@ -43,6 +43,9 @@ export class PerpMarket {
|
|||
public shortFunding: I80F48;
|
||||
public feesAccrued: I80F48;
|
||||
public feesSettled: I80F48;
|
||||
public maintPnlAssetWeight: I80F48;
|
||||
public initPnlAssetWeight: I80F48;
|
||||
|
||||
public _price: I80F48;
|
||||
public _uiPrice: number;
|
||||
|
||||
|
@ -59,7 +62,6 @@ export class PerpMarket {
|
|||
group: PublicKey;
|
||||
settleTokenIndex: number;
|
||||
perpMarketIndex: number;
|
||||
trustedMarket: number;
|
||||
groupInsuranceFund: number;
|
||||
baseDecimals: number;
|
||||
name: number[];
|
||||
|
@ -71,10 +73,10 @@ export class PerpMarket {
|
|||
stablePriceModel: StablePriceModel;
|
||||
quoteLotSize: BN;
|
||||
baseLotSize: BN;
|
||||
maintAssetWeight: I80F48Dto;
|
||||
initAssetWeight: I80F48Dto;
|
||||
maintLiabWeight: I80F48Dto;
|
||||
initLiabWeight: I80F48Dto;
|
||||
maintBaseAssetWeight: I80F48Dto;
|
||||
initBaseAssetWeight: I80F48Dto;
|
||||
maintBaseLiabWeight: I80F48Dto;
|
||||
initBaseLiabWeight: I80F48Dto;
|
||||
openInterest: BN;
|
||||
seqNum: BN;
|
||||
registrationTime: BN;
|
||||
|
@ -96,6 +98,8 @@ export class PerpMarket {
|
|||
settlePnlLimitFactor: number;
|
||||
settlePnlLimitWindowSizeTs: BN;
|
||||
reduceOnly: number;
|
||||
maintPnlAssetWeight: I80F48Dto;
|
||||
initPnlAssetWeight: I80F48Dto;
|
||||
},
|
||||
): PerpMarket {
|
||||
return new PerpMarket(
|
||||
|
@ -103,7 +107,6 @@ export class PerpMarket {
|
|||
obj.group,
|
||||
obj.settleTokenIndex as TokenIndex,
|
||||
obj.perpMarketIndex as PerpMarketIndex,
|
||||
obj.trustedMarket == 1,
|
||||
obj.groupInsuranceFund == 1,
|
||||
obj.baseDecimals,
|
||||
obj.name,
|
||||
|
@ -115,10 +118,10 @@ export class PerpMarket {
|
|||
obj.stablePriceModel,
|
||||
obj.quoteLotSize,
|
||||
obj.baseLotSize,
|
||||
obj.maintAssetWeight,
|
||||
obj.initAssetWeight,
|
||||
obj.maintLiabWeight,
|
||||
obj.initLiabWeight,
|
||||
obj.maintBaseAssetWeight,
|
||||
obj.initBaseAssetWeight,
|
||||
obj.maintBaseLiabWeight,
|
||||
obj.initBaseLiabWeight,
|
||||
obj.openInterest,
|
||||
obj.seqNum,
|
||||
obj.registrationTime,
|
||||
|
@ -140,6 +143,8 @@ export class PerpMarket {
|
|||
obj.settlePnlLimitFactor,
|
||||
obj.settlePnlLimitWindowSizeTs,
|
||||
obj.reduceOnly == 1,
|
||||
obj.maintPnlAssetWeight,
|
||||
obj.initPnlAssetWeight,
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -148,7 +153,6 @@ export class PerpMarket {
|
|||
public group: PublicKey,
|
||||
public settleTokenIndex: TokenIndex,
|
||||
public perpMarketIndex: PerpMarketIndex, // TODO rename to marketIndex?
|
||||
public trustedMarket: boolean,
|
||||
public groupInsuranceFund: boolean,
|
||||
public baseDecimals: number,
|
||||
name: number[],
|
||||
|
@ -160,10 +164,10 @@ export class PerpMarket {
|
|||
public stablePriceModel: StablePriceModel,
|
||||
public quoteLotSize: BN,
|
||||
public baseLotSize: BN,
|
||||
maintAssetWeight: I80F48Dto,
|
||||
initAssetWeight: I80F48Dto,
|
||||
maintLiabWeight: I80F48Dto,
|
||||
initLiabWeight: I80F48Dto,
|
||||
maintBaseAssetWeight: I80F48Dto,
|
||||
initBaseAssetWeight: I80F48Dto,
|
||||
maintBaseLiabWeight: I80F48Dto,
|
||||
initBaseLiabWeight: I80F48Dto,
|
||||
public openInterest: BN,
|
||||
public seqNum: BN,
|
||||
public registrationTime: BN,
|
||||
|
@ -185,16 +189,18 @@ export class PerpMarket {
|
|||
public settlePnlLimitFactor: number,
|
||||
public settlePnlLimitWindowSizeTs: BN,
|
||||
public reduceOnly: boolean,
|
||||
maintPnlAssetWeight: I80F48Dto,
|
||||
initPnlAssetWeight: I80F48Dto,
|
||||
) {
|
||||
this.name = utf8.decode(new Uint8Array(name)).split('\x00')[0];
|
||||
this.oracleConfig = {
|
||||
confFilter: I80F48.from(oracleConfig.confFilter),
|
||||
maxStalenessSlots: oracleConfig.maxStalenessSlots,
|
||||
} as OracleConfig;
|
||||
this.maintAssetWeight = I80F48.from(maintAssetWeight);
|
||||
this.initAssetWeight = I80F48.from(initAssetWeight);
|
||||
this.maintLiabWeight = I80F48.from(maintLiabWeight);
|
||||
this.initLiabWeight = I80F48.from(initLiabWeight);
|
||||
this.maintBaseAssetWeight = I80F48.from(maintBaseAssetWeight);
|
||||
this.initBaseAssetWeight = I80F48.from(initBaseAssetWeight);
|
||||
this.maintBaseLiabWeight = I80F48.from(maintBaseLiabWeight);
|
||||
this.initBaseLiabWeight = I80F48.from(initBaseLiabWeight);
|
||||
this.liquidationFee = I80F48.from(liquidationFee);
|
||||
this.makerFee = I80F48.from(makerFee);
|
||||
this.takerFee = I80F48.from(takerFee);
|
||||
|
@ -204,6 +210,8 @@ export class PerpMarket {
|
|||
this.shortFunding = I80F48.from(shortFunding);
|
||||
this.feesAccrued = I80F48.from(feesAccrued);
|
||||
this.feesSettled = I80F48.from(feesSettled);
|
||||
this.maintPnlAssetWeight = I80F48.from(maintPnlAssetWeight);
|
||||
this.initPnlAssetWeight = I80F48.from(initPnlAssetWeight);
|
||||
|
||||
this.priceLotsToUiConverter = new Big(10)
|
||||
.pow(baseDecimals - QUOTE_DECIMALS)
|
||||
|
@ -249,9 +257,9 @@ export class PerpMarket {
|
|||
insidePriceLimit(side: PerpOrderSide, orderPrice: number): boolean {
|
||||
return (
|
||||
(side === PerpOrderSide.bid &&
|
||||
orderPrice <= this.maintLiabWeight.toNumber() * this.uiPrice) ||
|
||||
orderPrice <= this.maintBaseLiabWeight.toNumber() * this.uiPrice) ||
|
||||
(side === PerpOrderSide.ask &&
|
||||
orderPrice >= this.maintAssetWeight.toNumber() * this.uiPrice)
|
||||
orderPrice >= this.maintBaseAssetWeight.toNumber() * this.uiPrice)
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -486,13 +494,13 @@ export class PerpMarket {
|
|||
'\n perpMarketIndex -' +
|
||||
this.perpMarketIndex +
|
||||
'\n maintAssetWeight -' +
|
||||
this.maintAssetWeight.toString() +
|
||||
this.maintBaseAssetWeight.toString() +
|
||||
'\n initAssetWeight -' +
|
||||
this.initAssetWeight.toString() +
|
||||
this.initBaseAssetWeight.toString() +
|
||||
'\n maintLiabWeight -' +
|
||||
this.maintLiabWeight.toString() +
|
||||
this.maintBaseLiabWeight.toString() +
|
||||
'\n initLiabWeight -' +
|
||||
this.initLiabWeight.toString() +
|
||||
this.initBaseLiabWeight.toString() +
|
||||
'\n liquidationFee -' +
|
||||
this.liquidationFee.toString() +
|
||||
'\n makerFee -' +
|
||||
|
|
|
@ -1521,10 +1521,12 @@ export class MangoClient {
|
|||
baseDecimals: number,
|
||||
quoteLotSize: number,
|
||||
baseLotSize: number,
|
||||
maintAssetWeight: number,
|
||||
initAssetWeight: number,
|
||||
maintLiabWeight: number,
|
||||
initLiabWeight: number,
|
||||
maintBaseAssetWeight: number,
|
||||
initBaseAssetWeight: number,
|
||||
maintBaseLiabWeight: number,
|
||||
initBaseLiabWeight: number,
|
||||
maintPnlAssetWeight: number,
|
||||
initPnlAssetWeight: number,
|
||||
liquidationFee: number,
|
||||
makerFee: number,
|
||||
takerFee: number,
|
||||
|
@ -1533,7 +1535,6 @@ export class MangoClient {
|
|||
maxFunding: number,
|
||||
impactQuantity: number,
|
||||
groupInsuranceFund: boolean,
|
||||
trustedMarket: boolean,
|
||||
settleFeeFlat: number,
|
||||
settleFeeAmountThreshold: number,
|
||||
settleFeeFractionLowHealth: number,
|
||||
|
@ -1560,10 +1561,12 @@ export class MangoClient {
|
|||
baseDecimals,
|
||||
new BN(quoteLotSize),
|
||||
new BN(baseLotSize),
|
||||
maintAssetWeight,
|
||||
initAssetWeight,
|
||||
maintLiabWeight,
|
||||
initLiabWeight,
|
||||
maintBaseAssetWeight,
|
||||
initBaseAssetWeight,
|
||||
maintBaseLiabWeight,
|
||||
initBaseLiabWeight,
|
||||
maintPnlAssetWeight,
|
||||
initPnlAssetWeight,
|
||||
liquidationFee,
|
||||
makerFee,
|
||||
takerFee,
|
||||
|
@ -1571,7 +1574,6 @@ export class MangoClient {
|
|||
maxFunding,
|
||||
new BN(impactQuantity),
|
||||
groupInsuranceFund,
|
||||
trustedMarket,
|
||||
feePenalty,
|
||||
settleFeeFlat,
|
||||
settleFeeAmountThreshold,
|
||||
|
@ -1642,10 +1644,12 @@ export class MangoClient {
|
|||
params.oracle,
|
||||
params.oracleConfig,
|
||||
params.baseDecimals,
|
||||
params.maintAssetWeight,
|
||||
params.initAssetWeight,
|
||||
params.maintLiabWeight,
|
||||
params.initLiabWeight,
|
||||
params.maintBaseAssetWeight,
|
||||
params.initBaseAssetWeight,
|
||||
params.maintBaseLiabWeight,
|
||||
params.initBaseLiabWeight,
|
||||
params.maintPnlAssetWeight,
|
||||
params.initPnlAssetWeight,
|
||||
params.liquidationFee,
|
||||
params.makerFee,
|
||||
params.takerFee,
|
||||
|
@ -1653,7 +1657,6 @@ export class MangoClient {
|
|||
params.maxFunding,
|
||||
params.impactQuantity !== null ? new BN(params.impactQuantity) : null,
|
||||
params.groupInsuranceFund,
|
||||
params.trustedMarket,
|
||||
params.feePenalty,
|
||||
params.settleFeeFlat,
|
||||
params.settleFeeAmountThreshold,
|
||||
|
|
|
@ -55,10 +55,12 @@ export interface PerpEditParams {
|
|||
oracle: PublicKey | null;
|
||||
oracleConfig: OracleConfigParams | null;
|
||||
baseDecimals: number | null;
|
||||
maintAssetWeight: number | null;
|
||||
initAssetWeight: number | null;
|
||||
maintLiabWeight: number | null;
|
||||
initLiabWeight: number | null;
|
||||
maintBaseAssetWeight: number | null;
|
||||
initBaseAssetWeight: number | null;
|
||||
maintBaseLiabWeight: number | null;
|
||||
initBaseLiabWeight: number | null;
|
||||
maintPnlAssetWeight: number | null;
|
||||
initPnlAssetWeight: number | null;
|
||||
liquidationFee: number | null;
|
||||
makerFee: number | null;
|
||||
takerFee: number | null;
|
||||
|
@ -67,7 +69,6 @@ export interface PerpEditParams {
|
|||
maxFunding: number | null;
|
||||
impactQuantity: number | null;
|
||||
groupInsuranceFund: boolean | null;
|
||||
trustedMarket: boolean | null;
|
||||
settleFeeFlat: number | null;
|
||||
settleFeeAmountThreshold: number | null;
|
||||
settleFeeFractionLowHealth: number | null;
|
||||
|
@ -83,10 +84,12 @@ export const NullPerpEditParams: PerpEditParams = {
|
|||
oracle: null,
|
||||
oracleConfig: null,
|
||||
baseDecimals: null,
|
||||
maintAssetWeight: null,
|
||||
initAssetWeight: null,
|
||||
maintLiabWeight: null,
|
||||
initLiabWeight: null,
|
||||
maintBaseAssetWeight: null,
|
||||
initBaseAssetWeight: null,
|
||||
maintBaseLiabWeight: null,
|
||||
initBaseLiabWeight: null,
|
||||
maintPnlAssetWeight: null,
|
||||
initPnlAssetWeight: null,
|
||||
liquidationFee: null,
|
||||
makerFee: null,
|
||||
takerFee: null,
|
||||
|
@ -95,7 +98,6 @@ export const NullPerpEditParams: PerpEditParams = {
|
|||
maxFunding: null,
|
||||
impactQuantity: null,
|
||||
groupInsuranceFund: null,
|
||||
trustedMarket: null,
|
||||
settleFeeFlat: null,
|
||||
settleFeeAmountThreshold: null,
|
||||
settleFeeFractionLowHealth: null,
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
export type MangoV4 = {
|
||||
"version": "0.2.0",
|
||||
"version": "0.3.0",
|
||||
"name": "mango_v4",
|
||||
"instructions": [
|
||||
{
|
||||
|
@ -2508,19 +2508,27 @@ export type MangoV4 = {
|
|||
"type": "i64"
|
||||
},
|
||||
{
|
||||
"name": "maintAssetWeight",
|
||||
"name": "maintBaseAssetWeight",
|
||||
"type": "f32"
|
||||
},
|
||||
{
|
||||
"name": "initAssetWeight",
|
||||
"name": "initBaseAssetWeight",
|
||||
"type": "f32"
|
||||
},
|
||||
{
|
||||
"name": "maintLiabWeight",
|
||||
"name": "maintBaseLiabWeight",
|
||||
"type": "f32"
|
||||
},
|
||||
{
|
||||
"name": "initLiabWeight",
|
||||
"name": "initBaseLiabWeight",
|
||||
"type": "f32"
|
||||
},
|
||||
{
|
||||
"name": "maintPnlAssetWeight",
|
||||
"type": "f32"
|
||||
},
|
||||
{
|
||||
"name": "initPnlAssetWeight",
|
||||
"type": "f32"
|
||||
},
|
||||
{
|
||||
|
@ -2551,10 +2559,6 @@ export type MangoV4 = {
|
|||
"name": "groupInsuranceFund",
|
||||
"type": "bool"
|
||||
},
|
||||
{
|
||||
"name": "trustedMarket",
|
||||
"type": "bool"
|
||||
},
|
||||
{
|
||||
"name": "feePenalty",
|
||||
"type": "f32"
|
||||
|
@ -2631,25 +2635,37 @@ export type MangoV4 = {
|
|||
}
|
||||
},
|
||||
{
|
||||
"name": "maintAssetWeightOpt",
|
||||
"name": "maintBaseAssetWeightOpt",
|
||||
"type": {
|
||||
"option": "f32"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "initAssetWeightOpt",
|
||||
"name": "initBaseAssetWeightOpt",
|
||||
"type": {
|
||||
"option": "f32"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "maintLiabWeightOpt",
|
||||
"name": "maintBaseLiabWeightOpt",
|
||||
"type": {
|
||||
"option": "f32"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "initLiabWeightOpt",
|
||||
"name": "initBaseLiabWeightOpt",
|
||||
"type": {
|
||||
"option": "f32"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "maintPnlAssetWeightOpt",
|
||||
"type": {
|
||||
"option": "f32"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "initPnlAssetWeightOpt",
|
||||
"type": {
|
||||
"option": "f32"
|
||||
}
|
||||
|
@ -2696,12 +2712,6 @@ export type MangoV4 = {
|
|||
"option": "bool"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "trustedMarketOpt",
|
||||
"type": {
|
||||
"option": "bool"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "feePenaltyOpt",
|
||||
"type": {
|
||||
|
@ -4308,10 +4318,7 @@ export type MangoV4 = {
|
|||
"type": "u16"
|
||||
},
|
||||
{
|
||||
"name": "trustedMarket",
|
||||
"docs": [
|
||||
"May this market contribute positive values to health?"
|
||||
],
|
||||
"name": "blocked1",
|
||||
"type": "u8"
|
||||
},
|
||||
{
|
||||
|
@ -4386,25 +4393,25 @@ export type MangoV4 = {
|
|||
"type": "i64"
|
||||
},
|
||||
{
|
||||
"name": "maintAssetWeight",
|
||||
"name": "maintBaseAssetWeight",
|
||||
"type": {
|
||||
"defined": "I80F48"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "initAssetWeight",
|
||||
"name": "initBaseAssetWeight",
|
||||
"type": {
|
||||
"defined": "I80F48"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "maintLiabWeight",
|
||||
"name": "maintBaseLiabWeight",
|
||||
"type": {
|
||||
"defined": "I80F48"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "initLiabWeight",
|
||||
"name": "initBaseLiabWeight",
|
||||
"type": {
|
||||
"defined": "I80F48"
|
||||
}
|
||||
|
@ -4564,12 +4571,33 @@ export type MangoV4 = {
|
|||
"name": "reduceOnly",
|
||||
"type": "u8"
|
||||
},
|
||||
{
|
||||
"name": "padding4",
|
||||
"type": {
|
||||
"array": [
|
||||
"u8",
|
||||
7
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "maintPnlAssetWeight",
|
||||
"type": {
|
||||
"defined": "I80F48"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "initPnlAssetWeight",
|
||||
"type": {
|
||||
"defined": "I80F48"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "reserved",
|
||||
"type": {
|
||||
"array": [
|
||||
"u8",
|
||||
1943
|
||||
1904
|
||||
]
|
||||
}
|
||||
}
|
||||
|
@ -4869,25 +4897,37 @@ export type MangoV4 = {
|
|||
"type": "u16"
|
||||
},
|
||||
{
|
||||
"name": "maintAssetWeight",
|
||||
"name": "maintBaseAssetWeight",
|
||||
"type": {
|
||||
"defined": "I80F48"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "initAssetWeight",
|
||||
"name": "initBaseAssetWeight",
|
||||
"type": {
|
||||
"defined": "I80F48"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "maintLiabWeight",
|
||||
"name": "maintBaseLiabWeight",
|
||||
"type": {
|
||||
"defined": "I80F48"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "initLiabWeight",
|
||||
"name": "initBaseLiabWeight",
|
||||
"type": {
|
||||
"defined": "I80F48"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "maintPnlAssetWeight",
|
||||
"type": {
|
||||
"defined": "I80F48"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "initPnlAssetWeight",
|
||||
"type": {
|
||||
"defined": "I80F48"
|
||||
}
|
||||
|
@ -4923,10 +4963,6 @@ export type MangoV4 = {
|
|||
{
|
||||
"name": "hasOpenOrders",
|
||||
"type": "bool"
|
||||
},
|
||||
{
|
||||
"name": "trustedMarket",
|
||||
"type": "bool"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -7717,7 +7753,7 @@ export type MangoV4 = {
|
|||
};
|
||||
|
||||
export const IDL: MangoV4 = {
|
||||
"version": "0.2.0",
|
||||
"version": "0.3.0",
|
||||
"name": "mango_v4",
|
||||
"instructions": [
|
||||
{
|
||||
|
@ -10226,19 +10262,27 @@ export const IDL: MangoV4 = {
|
|||
"type": "i64"
|
||||
},
|
||||
{
|
||||
"name": "maintAssetWeight",
|
||||
"name": "maintBaseAssetWeight",
|
||||
"type": "f32"
|
||||
},
|
||||
{
|
||||
"name": "initAssetWeight",
|
||||
"name": "initBaseAssetWeight",
|
||||
"type": "f32"
|
||||
},
|
||||
{
|
||||
"name": "maintLiabWeight",
|
||||
"name": "maintBaseLiabWeight",
|
||||
"type": "f32"
|
||||
},
|
||||
{
|
||||
"name": "initLiabWeight",
|
||||
"name": "initBaseLiabWeight",
|
||||
"type": "f32"
|
||||
},
|
||||
{
|
||||
"name": "maintPnlAssetWeight",
|
||||
"type": "f32"
|
||||
},
|
||||
{
|
||||
"name": "initPnlAssetWeight",
|
||||
"type": "f32"
|
||||
},
|
||||
{
|
||||
|
@ -10269,10 +10313,6 @@ export const IDL: MangoV4 = {
|
|||
"name": "groupInsuranceFund",
|
||||
"type": "bool"
|
||||
},
|
||||
{
|
||||
"name": "trustedMarket",
|
||||
"type": "bool"
|
||||
},
|
||||
{
|
||||
"name": "feePenalty",
|
||||
"type": "f32"
|
||||
|
@ -10349,25 +10389,37 @@ export const IDL: MangoV4 = {
|
|||
}
|
||||
},
|
||||
{
|
||||
"name": "maintAssetWeightOpt",
|
||||
"name": "maintBaseAssetWeightOpt",
|
||||
"type": {
|
||||
"option": "f32"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "initAssetWeightOpt",
|
||||
"name": "initBaseAssetWeightOpt",
|
||||
"type": {
|
||||
"option": "f32"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "maintLiabWeightOpt",
|
||||
"name": "maintBaseLiabWeightOpt",
|
||||
"type": {
|
||||
"option": "f32"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "initLiabWeightOpt",
|
||||
"name": "initBaseLiabWeightOpt",
|
||||
"type": {
|
||||
"option": "f32"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "maintPnlAssetWeightOpt",
|
||||
"type": {
|
||||
"option": "f32"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "initPnlAssetWeightOpt",
|
||||
"type": {
|
||||
"option": "f32"
|
||||
}
|
||||
|
@ -10414,12 +10466,6 @@ export const IDL: MangoV4 = {
|
|||
"option": "bool"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "trustedMarketOpt",
|
||||
"type": {
|
||||
"option": "bool"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "feePenaltyOpt",
|
||||
"type": {
|
||||
|
@ -12026,10 +12072,7 @@ export const IDL: MangoV4 = {
|
|||
"type": "u16"
|
||||
},
|
||||
{
|
||||
"name": "trustedMarket",
|
||||
"docs": [
|
||||
"May this market contribute positive values to health?"
|
||||
],
|
||||
"name": "blocked1",
|
||||
"type": "u8"
|
||||
},
|
||||
{
|
||||
|
@ -12104,25 +12147,25 @@ export const IDL: MangoV4 = {
|
|||
"type": "i64"
|
||||
},
|
||||
{
|
||||
"name": "maintAssetWeight",
|
||||
"name": "maintBaseAssetWeight",
|
||||
"type": {
|
||||
"defined": "I80F48"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "initAssetWeight",
|
||||
"name": "initBaseAssetWeight",
|
||||
"type": {
|
||||
"defined": "I80F48"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "maintLiabWeight",
|
||||
"name": "maintBaseLiabWeight",
|
||||
"type": {
|
||||
"defined": "I80F48"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "initLiabWeight",
|
||||
"name": "initBaseLiabWeight",
|
||||
"type": {
|
||||
"defined": "I80F48"
|
||||
}
|
||||
|
@ -12282,12 +12325,33 @@ export const IDL: MangoV4 = {
|
|||
"name": "reduceOnly",
|
||||
"type": "u8"
|
||||
},
|
||||
{
|
||||
"name": "padding4",
|
||||
"type": {
|
||||
"array": [
|
||||
"u8",
|
||||
7
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "maintPnlAssetWeight",
|
||||
"type": {
|
||||
"defined": "I80F48"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "initPnlAssetWeight",
|
||||
"type": {
|
||||
"defined": "I80F48"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "reserved",
|
||||
"type": {
|
||||
"array": [
|
||||
"u8",
|
||||
1943
|
||||
1904
|
||||
]
|
||||
}
|
||||
}
|
||||
|
@ -12587,25 +12651,37 @@ export const IDL: MangoV4 = {
|
|||
"type": "u16"
|
||||
},
|
||||
{
|
||||
"name": "maintAssetWeight",
|
||||
"name": "maintBaseAssetWeight",
|
||||
"type": {
|
||||
"defined": "I80F48"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "initAssetWeight",
|
||||
"name": "initBaseAssetWeight",
|
||||
"type": {
|
||||
"defined": "I80F48"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "maintLiabWeight",
|
||||
"name": "maintBaseLiabWeight",
|
||||
"type": {
|
||||
"defined": "I80F48"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "initLiabWeight",
|
||||
"name": "initBaseLiabWeight",
|
||||
"type": {
|
||||
"defined": "I80F48"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "maintPnlAssetWeight",
|
||||
"type": {
|
||||
"defined": "I80F48"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "initPnlAssetWeight",
|
||||
"type": {
|
||||
"defined": "I80F48"
|
||||
}
|
||||
|
@ -12641,10 +12717,6 @@ export const IDL: MangoV4 = {
|
|||
{
|
||||
"name": "hasOpenOrders",
|
||||
"type": "bool"
|
||||
},
|
||||
{
|
||||
"name": "trustedMarket",
|
||||
"type": "bool"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
@ -245,13 +245,14 @@ async function main() {
|
|||
1.05,
|
||||
0.012,
|
||||
0.0002,
|
||||
1,
|
||||
1,
|
||||
0.0,
|
||||
0,
|
||||
0.05,
|
||||
0.05,
|
||||
100,
|
||||
true,
|
||||
true,
|
||||
1000,
|
||||
1000000,
|
||||
0.05,
|
||||
|
|
|
@ -424,6 +424,8 @@ async function registerPerpMarkets() {
|
|||
0.95,
|
||||
1.025,
|
||||
1.05,
|
||||
1,
|
||||
1,
|
||||
0.0125,
|
||||
-0.0001,
|
||||
0.0004,
|
||||
|
@ -432,7 +434,6 @@ async function registerPerpMarkets() {
|
|||
0.05,
|
||||
100, // if btc is at 20k, this is 200$
|
||||
true,
|
||||
true,
|
||||
1000, // solana tx fee is currently 50 native quote at a sol price of 10$
|
||||
1000000,
|
||||
0.01, // less than liquidationFee
|
||||
|
@ -454,6 +455,8 @@ async function registerPerpMarkets() {
|
|||
0.99, // 100x leverage
|
||||
1.005,
|
||||
1.01,
|
||||
0,
|
||||
0,
|
||||
0.0025,
|
||||
-0.0001,
|
||||
0.0004,
|
||||
|
@ -462,7 +465,6 @@ async function registerPerpMarkets() {
|
|||
0.05,
|
||||
1000, // if mngo price 1 cent, this is 10$
|
||||
false,
|
||||
false,
|
||||
1000,
|
||||
1000000,
|
||||
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() {
|
||||
const result = await buildAdminClient();
|
||||
const client = result[0];
|
||||
|
@ -662,7 +649,6 @@ async function main() {
|
|||
try {
|
||||
// await registerPerpMarkets();
|
||||
// await makePerpMarketReduceOnly();
|
||||
// await makePerpMarketUntrusted();
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
|
|
|
@ -228,6 +228,8 @@ async function main() {
|
|||
0.8,
|
||||
1.1,
|
||||
1.2,
|
||||
1,
|
||||
1,
|
||||
0.05,
|
||||
-0.001,
|
||||
0.002,
|
||||
|
@ -236,7 +238,6 @@ async function main() {
|
|||
0.1,
|
||||
10,
|
||||
false,
|
||||
false,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
|
|
Loading…
Reference in New Issue