|
110 | 110 | ALPACA_FILL_DELTA_EPSILON = 1e-8 |
111 | 111 |
|
112 | 112 |
|
| 113 | +def _is_final_fill( |
| 114 | + *, |
| 115 | + requested: float, |
| 116 | + filled: float, |
| 117 | + avg_price: float, |
| 118 | + status: Any = "", |
| 119 | +) -> bool: |
| 120 | + requested_qty = max(0.0, float(requested or 0.0)) |
| 121 | + filled_qty = max(0.0, float(filled or 0.0)) |
| 122 | + if requested_qty <= 0 or filled_qty <= 0 or float(avg_price or 0.0) <= 0: |
| 123 | + return False |
| 124 | + if normalize_live_order_status(status) == "filled": |
| 125 | + return True |
| 126 | + return filled_qty >= requested_qty * 0.999999 |
| 127 | + |
| 128 | + |
113 | 129 | def _broker_order_type(payload: Dict[str, Any], ref_price: float) -> Tuple[str, float]: |
114 | 130 | order_type = str(payload.get("order_type") or "market").strip().lower() |
115 | 131 | if order_type == "maker_then_market": |
@@ -2174,7 +2190,12 @@ def _execute_live_order(self, *, order_id: int, order_row: Dict[str, Any], paylo |
2174 | 2190 | filled=filled, |
2175 | 2191 | avg_price=avg_price, |
2176 | 2192 | executed_at=executed_at if filled > 0 else None, |
2177 | | - final_filled=bool(amount > 0 and filled >= amount * 0.999999), |
| 2193 | + final_filled=_is_final_fill( |
| 2194 | + requested=amount, |
| 2195 | + filled=filled, |
| 2196 | + avg_price=avg_price, |
| 2197 | + status=execution_result.status, |
| 2198 | + ), |
2178 | 2199 | ) |
2179 | 2200 | _console_print(f"[worker] order sent: strategy_id={strategy_id} pending_id={order_id} exchange={res.exchange_id} order_id={res.exchange_order_id} filled={filled} avg={avg_price}") |
2180 | 2201 | except Exception as e: |
@@ -2371,7 +2392,12 @@ def _execute_ibkr_order( |
2371 | 2392 | filled=filled, |
2372 | 2393 | avg_price=avg_price, |
2373 | 2394 | executed_at=executed_at if filled > 0 else None, |
2374 | | - final_filled=bool(amount > 0 and filled >= amount * 0.999999 and avg_price > 0), |
| 2395 | + final_filled=_is_final_fill( |
| 2396 | + requested=amount, |
| 2397 | + filled=filled, |
| 2398 | + avg_price=avg_price, |
| 2399 | + status=result.status, |
| 2400 | + ), |
2375 | 2401 | ) |
2376 | 2402 | _console_print(f"[worker] IBKR order sent: strategy_id={strategy_id} pending_id={order_id} order_id={exchange_order_id} filled={filled} avg={avg_price}") |
2377 | 2403 |
|
@@ -2549,7 +2575,12 @@ def _execute_alpaca_order( |
2549 | 2575 | filled=filled, |
2550 | 2576 | avg_price=avg_price, |
2551 | 2577 | executed_at=executed_at if filled > 0 else None, |
2552 | | - final_filled=bool(amount > 0 and filled >= amount * 0.999999 and avg_price > 0), |
| 2578 | + final_filled=_is_final_fill( |
| 2579 | + requested=amount, |
| 2580 | + filled=filled, |
| 2581 | + avg_price=avg_price, |
| 2582 | + status=result.status, |
| 2583 | + ), |
2553 | 2584 | ) |
2554 | 2585 | _console_print( |
2555 | 2586 | f"[worker] Alpaca order sent: strategy_id={strategy_id} pending_id={order_id} " |
|
0 commit comments