|
@@ -1547,6 +1547,11 @@ class MarketMonitor:
|
|
order_side = 'buy' if contracts > 0 else 'sell'
|
|
order_side = 'buy' if contracts > 0 else 'sell'
|
|
token = symbol.split('/')[0] if '/' in symbol else symbol
|
|
token = symbol.split('/')[0] if '/' in symbol else symbol
|
|
|
|
|
|
|
|
+
|
|
|
|
+ if entry_price <= 0:
|
|
|
|
+ entry_price = await self._estimate_entry_price_for_orphaned_position(symbol, contracts)
|
|
|
|
+ logger.info(f"🔄 AUTO-SYNC: Estimated entry price for orphaned {symbol}: ${entry_price:.4f}")
|
|
|
|
+
|
|
logger.warning(f"🔄 AUTO-SYNC: Orphaned position detected - {symbol} {position_side} {abs(contracts)} @ ${entry_price}")
|
|
logger.warning(f"🔄 AUTO-SYNC: Orphaned position detected - {symbol} {position_side} {abs(contracts)} @ ${entry_price}")
|
|
|
|
|
|
|
|
|
|
@@ -1594,6 +1599,51 @@ class MarketMonitor:
|
|
except Exception as e:
|
|
except Exception as e:
|
|
logger.error(f"❌ Error in auto-sync orphaned positions: {e}", exc_info=True)
|
|
logger.error(f"❌ Error in auto-sync orphaned positions: {e}", exc_info=True)
|
|
|
|
|
|
|
|
+ async def _estimate_entry_price_for_orphaned_position(self, symbol: str, contracts: float) -> float:
|
|
|
|
+ """Estimate entry price for an orphaned position by checking recent fills and market data."""
|
|
|
|
+ try:
|
|
|
|
+
|
|
|
|
+ recent_fills = self.trading_engine.get_recent_fills()
|
|
|
|
+ if recent_fills:
|
|
|
|
+
|
|
|
|
+ symbol_fills = [fill for fill in recent_fills if fill.get('symbol') == symbol]
|
|
|
|
+
|
|
|
|
+ if symbol_fills:
|
|
|
|
+
|
|
|
|
+ latest_fill = symbol_fills[0]
|
|
|
|
+ fill_price = float(latest_fill.get('price', 0))
|
|
|
|
+
|
|
|
|
+ if fill_price > 0:
|
|
|
|
+ logger.info(f"💡 AUTO-SYNC: Found recent fill price for {symbol}: ${fill_price:.4f}")
|
|
|
|
+ return fill_price
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ market_data = self.trading_engine.get_market_data(symbol)
|
|
|
|
+ if market_data and market_data.get('ticker'):
|
|
|
|
+ current_price = float(market_data['ticker'].get('last', 0))
|
|
|
|
+
|
|
|
|
+ if current_price > 0:
|
|
|
|
+ logger.warning(f"⚠️ AUTO-SYNC: Using current market price as entry estimate for {symbol}: ${current_price:.4f}")
|
|
|
|
+ return current_price
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ if market_data and market_data.get('ticker'):
|
|
|
|
+ bid = float(market_data['ticker'].get('bid', 0))
|
|
|
|
+ ask = float(market_data['ticker'].get('ask', 0))
|
|
|
|
+
|
|
|
|
+ if bid > 0 and ask > 0:
|
|
|
|
+ avg_price = (bid + ask) / 2
|
|
|
|
+ logger.warning(f"⚠️ AUTO-SYNC: Using bid/ask average as entry estimate for {symbol}: ${avg_price:.4f}")
|
|
|
|
+ return avg_price
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ logger.error(f"❌ AUTO-SYNC: Could not estimate entry price for {symbol}, using fallback value of $1.00")
|
|
|
|
+ return 1.0
|
|
|
|
+
|
|
|
|
+ except Exception as e:
|
|
|
|
+ logger.error(f"❌ AUTO-SYNC: Error estimating entry price for {symbol}: {e}")
|
|
|
|
+ return 1.0
|
|
|
|
+
|
|
async def _handle_orphaned_position(self, symbol, contracts):
|
|
async def _handle_orphaned_position(self, symbol, contracts):
|
|
"""Handle the orphaned position."""
|
|
"""Handle the orphaned position."""
|
|
try:
|
|
try:
|