Skip to content

Commit 16f91e9

Browse files
committed
drop liquidated field from PaperOrderResult
Mirrors the real SignerClient shape where order submission returns only fill/tx info and post-order state is queried separately. Callers detect liquidation via get_position() returning None or get_health().has_been_liquidated. Fixes AttributeError in paper_trading_health.py when an aggressive order is liquidated on the same tick as the fill and get_position(0) returns None.
1 parent 2eef72e commit 16f91e9

4 files changed

Lines changed: 12 additions & 9 deletions

File tree

examples/paper_trading_health.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,13 +87,17 @@ async def main():
8787
# Show the contrast
8888
cons_liq = conservative.get_liquidation_price(0)
8989
aggr_liq = aggressive.get_liquidation_price(0)
90-
aggr_mark = aggressive.get_position(0).mark_price
90+
aggr_pos = aggressive.get_position(0)
9191
print()
9292
print("-" * 60)
9393
print("COMPARISON")
9494
cons_liq_str = "n/a (can't be liquidated)" if cons_liq == 0 else f"${cons_liq:.2f}"
9595
print(f" Conservative liq price: {cons_liq_str}")
96-
print(f" Aggressive liq price: ${aggr_liq:.2f} (${aggr_mark - aggr_liq:.2f} below mark)")
96+
if aggr_pos is None:
97+
reason = "already liquidated" if aggressive.get_health().has_been_liquidated else "no open position"
98+
print(f" Aggressive position: {reason}")
99+
else:
100+
print(f" Aggressive liq price: ${aggr_liq:.2f} (${aggr_pos.mark_price - aggr_liq:.2f} below mark)")
97101
print("-" * 60)
98102

99103
await api_client.close()

lighter/paper_client/client.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,7 @@ async def create_paper_order(
184184
avg_price = (
185185
total_quote / total_filled_size if total_filled_size > 0 else 0.0
186186
)
187-
liquidated_markets = self._check_liquidation_and_update_metrics()
187+
self._check_liquidation_and_update_metrics()
188188

189189
return PaperOrderResult(
190190
order_type=request.order_type,
@@ -197,7 +197,6 @@ async def create_paper_order(
197197
quote_amount=total_quote,
198198
unfilled=unfilled,
199199
timestamp=utc_now(),
200-
liquidated=request.market_id in liquidated_markets,
201200
)
202201

203202
def get_health(self) -> PaperAccountHealth:

lighter/paper_client/types.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,6 @@ class PaperOrderResult:
8787
quote_amount: float
8888
unfilled: float
8989
timestamp: datetime
90-
liquidated: bool = False
9190

9291

9392
@dataclass

test/paper_client/test_client.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ async def test_health_uses_cross_margin_across_markets(self) -> None:
109109
self.assertGreater(health.leverage, 0)
110110
self.assertLess(health.leverage, 2)
111111

112-
async def test_liquidated_result_is_scoped_to_request_market(self) -> None:
112+
async def test_order_can_trigger_cross_market_liquidation(self) -> None:
113113
order_api = FakeOrderApi()
114114
order_api.details[1] = default_detail(1, "BTC")
115115
order_api.details[1].maintenance_margin_fraction = 500
@@ -140,11 +140,11 @@ async def test_liquidated_result_is_scoped_to_request_market(self) -> None:
140140
)
141141
)
142142

143-
self.assertFalse(result.liquidated)
143+
self.assertIsNotNone(result)
144144
self.assertIsNone(client.get_position(0))
145145
self.assertIsNone(client.get_position(1))
146146

147-
async def test_request_market_liquidation_sets_result_flag(self) -> None:
147+
async def test_request_market_liquidation_clears_position(self) -> None:
148148
order_api = FakeOrderApi()
149149
order_api.details[0].maintenance_margin_fraction = 500
150150
order_api.details[0].closeout_margin_fraction = 250
@@ -161,8 +161,9 @@ async def test_request_market_liquidation_sets_result_flag(self) -> None:
161161
PaperOrderRequest(0, PaperOrderSide.BUY, 0.1)
162162
)
163163

164-
self.assertTrue(result.liquidated)
164+
self.assertIsNotNone(result)
165165
self.assertIsNone(client.get_position(0))
166+
self.assertTrue(client.get_health().has_been_liquidated)
166167

167168
async def test_mark_price_fallback_to_last_trade_price(self) -> None:
168169
order_api = FakeOrderApi()

0 commit comments

Comments
 (0)