Fix settle limit accounting for positive pnl takeover (#562)
This commit is contained in:
parent
77f04d62c1
commit
507cb500e9
|
@ -739,11 +739,15 @@ mod tests {
|
|||
pm.init_overall_asset_weight = I80F48::from_num(overall_weight);
|
||||
}
|
||||
{
|
||||
perp_p(&mut setup.liqee).record_trade(
|
||||
let p = perp_p(&mut setup.liqee);
|
||||
p.record_trade(
|
||||
setup.perp_market.data(),
|
||||
init_liqee_base,
|
||||
I80F48::from_num(init_liqee_quote),
|
||||
);
|
||||
p.realized_other_pnl_native = p
|
||||
.unsettled_pnl(setup.perp_market.data(), I80F48::ONE)
|
||||
.unwrap();
|
||||
|
||||
let settle_bank = setup.settle_bank.data();
|
||||
settle_bank
|
||||
|
@ -773,6 +777,15 @@ mod tests {
|
|||
-(exp_liqee_quote - init_liqee_quote),
|
||||
0.01
|
||||
);
|
||||
// The settle limit taken over matches the quote pos when removing the
|
||||
// quote gains from giving away base lots
|
||||
assert_eq_f!(
|
||||
I80F48::from_num(liqor_perp.settle_pnl_limit_realized_trade),
|
||||
liqor_perp.quote_position_native.to_num::<f64>()
|
||||
+ liqor_perp.base_position_lots as f64,
|
||||
1.1
|
||||
);
|
||||
|
||||
let settle_bank = result.settle_bank.data();
|
||||
assert_eq_f!(
|
||||
token_p(&mut result.liqee).native(settle_bank),
|
||||
|
|
|
@ -467,6 +467,20 @@ impl PerpPosition {
|
|||
}
|
||||
}
|
||||
|
||||
// Bump the realized trade pnl settle limit for a fraction of the stable price value,
|
||||
// allowing gradual settlement of very high-pnl trades.
|
||||
let realized_stable_value = I80F48::from(reduced_lots.abs() * perp_market.base_lot_size)
|
||||
* perp_market.stable_price();
|
||||
let stable_value_fraction =
|
||||
I80F48::from_num(perp_market.settle_pnl_limit_factor) * realized_stable_value;
|
||||
self.increase_realized_trade_pnl_settle_limit(newly_realized_pnl, stable_value_fraction);
|
||||
}
|
||||
|
||||
fn increase_realized_trade_pnl_settle_limit(
|
||||
&mut self,
|
||||
newly_realized_pnl: I80F48,
|
||||
limit: I80F48,
|
||||
) {
|
||||
// When realized limit has a different sign from realized pnl, reset it completely
|
||||
if (self.settle_pnl_limit_realized_trade > 0 && self.realized_trade_pnl_native <= 0)
|
||||
|| (self.settle_pnl_limit_realized_trade < 0 && self.realized_trade_pnl_native >= 0)
|
||||
|
@ -477,25 +491,13 @@ impl PerpPosition {
|
|||
// Whenever realized pnl increases in magnitude, also increase realized pnl settle limit
|
||||
// magnitude.
|
||||
if newly_realized_pnl.signum() == self.realized_trade_pnl_native.signum() {
|
||||
let realized_stable_value =
|
||||
I80F48::from(reduced_lots.abs() * perp_market.base_lot_size)
|
||||
* perp_market.stable_price();
|
||||
let stable_value_fraction =
|
||||
I80F48::from_num(perp_market.settle_pnl_limit_factor) * realized_stable_value;
|
||||
|
||||
// The realized pnl settle limit change is restricted to actually realized pnl:
|
||||
// buying and then selling some base lots at the same price shouldn't affect
|
||||
// the settle limit.
|
||||
let limit_change = if newly_realized_pnl > 0 {
|
||||
newly_realized_pnl
|
||||
.min(stable_value_fraction)
|
||||
.ceil()
|
||||
.clamp_to_i64()
|
||||
newly_realized_pnl.min(limit).ceil().clamp_to_i64()
|
||||
} else {
|
||||
newly_realized_pnl
|
||||
.max(-stable_value_fraction)
|
||||
.floor()
|
||||
.clamp_to_i64()
|
||||
newly_realized_pnl.max(-limit).floor().clamp_to_i64()
|
||||
};
|
||||
self.settle_pnl_limit_realized_trade += limit_change;
|
||||
}
|
||||
|
@ -774,7 +776,8 @@ impl PerpPosition {
|
|||
/// Adds to the quote position and adds a recurring ("realized trade") settle limit
|
||||
pub fn record_liquidation_pnl_takeover(&mut self, change: I80F48, recurring_limit: I80F48) {
|
||||
self.change_quote_position(change);
|
||||
self.realized_trade_pnl_native += recurring_limit;
|
||||
self.realized_trade_pnl_native += change;
|
||||
self.increase_realized_trade_pnl_settle_limit(change, recurring_limit);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue