Fix settle limit accounting for positive pnl takeover (#562)

This commit is contained in:
Christian Kamm 2023-04-25 13:37:34 +02:00 committed by GitHub
parent 77f04d62c1
commit 507cb500e9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 32 additions and 16 deletions

View File

@ -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),

View File

@ -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);
}
}