|
@@ -634,6 +634,29 @@ class TradingStats:
|
|
|
logger.error(f"❌ Error generating summary report: {e}")
|
|
|
return {'error': str(e)}
|
|
|
|
|
|
+ def record_trade(self, symbol: str, side: str, amount: float, price: float,
|
|
|
+ exchange_fill_id: Optional[str] = None, trade_type: str = "manual",
|
|
|
+ pnl: Optional[float] = None, timestamp: Optional[str] = None,
|
|
|
+ linked_order_table_id_to_link: Optional[int] = None):
|
|
|
+ """Record a trade directly in the database (used for unmatched external fills)."""
|
|
|
+ if timestamp is None:
|
|
|
+ timestamp = datetime.now(timezone.utc).isoformat()
|
|
|
+
|
|
|
+ value = amount * price
|
|
|
+
|
|
|
+ try:
|
|
|
+ self.db_manager._execute_query(
|
|
|
+ "INSERT OR IGNORE INTO trades (symbol, side, amount, price, value, trade_type, timestamp, exchange_fill_id, pnl, linked_order_table_id) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
|
|
|
+ (symbol, side, amount, price, value, trade_type, timestamp, exchange_fill_id, pnl or 0.0, linked_order_table_id_to_link)
|
|
|
+ )
|
|
|
+
|
|
|
+ formatter = get_formatter()
|
|
|
+ base_asset_for_amount = symbol.split('/')[0] if '/' in symbol else symbol
|
|
|
+ logger.info(f"📈 Trade recorded: {side.upper()} {formatter.format_amount(amount, base_asset_for_amount)} {symbol} @ {formatter.format_price(price, symbol)} ({formatter.format_price(value, symbol)}) [{trade_type}]")
|
|
|
+
|
|
|
+ except Exception as e:
|
|
|
+ logger.error(f"Failed to record trade: {e}")
|
|
|
+
|
|
|
def health_check(self) -> Dict[str, Any]:
|
|
|
"""Perform health check on all components."""
|
|
|
try:
|