fix: handle 404 errors by checking portfolio for filled/closed positions
This commit is contained in:
+51
-10
@@ -53,6 +53,17 @@ class ExecutionManager:
|
||||
logger.error(f"Failed to place entry order: {e}")
|
||||
return False
|
||||
|
||||
def _is_ticker_in_portfolio(self, ticker: str) -> bool:
|
||||
"""Helper to check if a ticker currently has an open position."""
|
||||
try:
|
||||
positions = self.client.get_all_open_positions()
|
||||
for pos in positions:
|
||||
if pos.get('ticker') == ticker:
|
||||
return True
|
||||
except Exception as e:
|
||||
logger.error(f"Error checking portfolio: {e}")
|
||||
return False
|
||||
|
||||
def monitor_and_bracket(self, params: Dict[str, Any]):
|
||||
"""Polls the entry order and places SL/TP once filled."""
|
||||
if not self.current_order_id:
|
||||
@@ -87,6 +98,15 @@ class ExecutionManager:
|
||||
logger.warning(f"Entry order was {status}. Aborting.")
|
||||
return False
|
||||
except Exception as e:
|
||||
# Trading212 404s if an order is no longer active (filled or cancelled)
|
||||
if "404" in str(e):
|
||||
if self._is_ticker_in_portfolio(ticker):
|
||||
self.is_in_position = True
|
||||
logger.info(f"Order {self.current_order_id} disappeared but position detected. Assuming filled.")
|
||||
break
|
||||
else:
|
||||
logger.warning(f"Order {self.current_order_id} disappeared and no position found. Assuming cancelled/rejected.")
|
||||
return False
|
||||
logger.error(f"Error checking order status: {e}")
|
||||
|
||||
time.sleep(10) # Poll every 10 seconds
|
||||
@@ -118,20 +138,41 @@ class ExecutionManager:
|
||||
if not self.is_in_position:
|
||||
return False, "", 0.0
|
||||
|
||||
ticker = self.params.get('ticker')
|
||||
|
||||
try:
|
||||
if self.tp_order_id:
|
||||
tp_info = self.client.get_order_status(self.tp_order_id)
|
||||
if tp_info.get('status') == "FILLED":
|
||||
fill_price = tp_info.get('filledPrice', tp_info.get('limitPrice', self.params.get('target_price')))
|
||||
self.is_in_position = False
|
||||
return True, "TP Hit", float(fill_price)
|
||||
try:
|
||||
tp_info = self.client.get_order_status(self.tp_order_id)
|
||||
if tp_info.get('status') == "FILLED":
|
||||
fill_price = tp_info.get('filledPrice', tp_info.get('limitPrice', self.params.get('target_price')))
|
||||
self.is_in_position = False
|
||||
return True, "TP Hit", float(fill_price)
|
||||
except Exception as e:
|
||||
if "404" in str(e):
|
||||
if not self._is_ticker_in_portfolio(ticker):
|
||||
self.is_in_position = False
|
||||
logger.info(f"TP order {self.tp_order_id} disappeared and position closed. Assuming TP hit.")
|
||||
return True, "TP Hit", float(self.params.get('target_price'))
|
||||
else:
|
||||
raise e
|
||||
|
||||
if self.sl_order_id:
|
||||
sl_info = self.client.get_order_status(self.sl_order_id)
|
||||
if sl_info.get('status') == "FILLED":
|
||||
fill_price = sl_info.get('filledPrice', sl_info.get('stopPrice', self.params.get('stop_loss')))
|
||||
self.is_in_position = False
|
||||
return True, "SL Hit", float(fill_price)
|
||||
try:
|
||||
sl_info = self.client.get_order_status(self.sl_order_id)
|
||||
if sl_info.get('status') == "FILLED":
|
||||
fill_price = sl_info.get('filledPrice', sl_info.get('stopPrice', self.params.get('stop_loss')))
|
||||
self.is_in_position = False
|
||||
return True, "SL Hit", float(fill_price)
|
||||
except Exception as e:
|
||||
if "404" in str(e):
|
||||
if not self._is_ticker_in_portfolio(ticker):
|
||||
self.is_in_position = False
|
||||
logger.info(f"SL order {self.sl_order_id} disappeared and position closed. Assuming SL hit.")
|
||||
return True, "SL Hit", float(self.params.get('stop_loss'))
|
||||
else:
|
||||
raise e
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error checking exit status: {e}")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user