Enhance SL/TP calculation and order handling in LiveRegimeStrategy and OKXClient

- Updated `calculate_sl_tp` method to handle invalid entry prices and sides, returning (None, None) when necessary.
- Improved logging for SL/TP values in `LiveTradingBot` to display "N/A" for invalid values.
- Refined order placement in `OKXClient` to ensure guaranteed fill price retrieval, with fallback mechanisms for fetching order details and ticker prices if needed.
- Added error handling for scenarios where fill prices cannot be determined.
This commit is contained in:
2026-01-16 13:54:26 +08:00
parent 62c470b3de
commit 35992ee374
3 changed files with 75 additions and 22 deletions

View File

@@ -200,34 +200,33 @@ class LiveTradingBot:
size_eth = size_usdt / current_price
# Calculate SL/TP
# Calculate SL/TP for logging
stop_loss, take_profit = self.strategy.calculate_sl_tp(current_price, side)
sl_str = f"{stop_loss:.2f}" if stop_loss else "N/A"
tp_str = f"{take_profit:.2f}" if take_profit else "N/A"
self.logger.info(
f"Executing {side.upper()} entry: {size_eth:.4f} ETH @ {current_price:.2f} "
f"(${size_usdt:.2f}), SL={stop_loss:.2f}, TP={take_profit:.2f}"
f"(${size_usdt:.2f}), SL={sl_str}, TP={tp_str}"
)
try:
# Place market order
# Place market order (guaranteed to have fill price or raises)
order_side = "buy" if side == "long" else "sell"
order = self.okx_client.place_market_order(symbol, order_side, size_eth)
# Get filled price (handle None values from OKX response)
filled_price = order.get('average') or order.get('price') or current_price
filled_amount = order.get('filled') or order.get('amount') or size_eth
# Get filled price and amount (guaranteed by OKX client)
filled_price = order['average']
filled_amount = order.get('filled') or size_eth
# Ensure we have valid numeric values
if filled_price is None or filled_price == 0:
self.logger.warning(f"No fill price in order response, using current price: {current_price}")
filled_price = current_price
if filled_amount is None or filled_amount == 0:
self.logger.warning(f"No fill amount in order response, using requested: {size_eth}")
filled_amount = size_eth
# Recalculate SL/TP with filled price
# Calculate SL/TP with filled price
stop_loss, take_profit = self.strategy.calculate_sl_tp(filled_price, side)
if stop_loss is None or take_profit is None:
raise RuntimeError(
f"Failed to calculate SL/TP: filled_price={filled_price}, side={side}"
)
# Get order ID from response
order_id = order.get('id', '')