From 777f9ff703e21731753584c68f182083187579a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=96=87=E8=96=87=E5=AE=89?= Date: Sat, 14 Feb 2026 17:11:46 +0800 Subject: [PATCH] 1 --- backend/api/routes/trades.py | 15 +- backend/database/models.py | 6 +- frontend/src/components/TradeList.jsx | 14 ++ trading_system/config.py | 2 +- trading_system/position_manager.py | 209 +++++++++++++------------- trading_system/risk_manager.py | 17 ++- 6 files changed, 151 insertions(+), 112 deletions(-) diff --git a/backend/api/routes/trades.py b/backend/api/routes/trades.py index eb8bba2..87ca479 100644 --- a/backend/api/routes/trades.py +++ b/backend/api/routes/trades.py @@ -79,7 +79,8 @@ async def get_trades( trade_type: Optional[str] = Query(None, description="交易类型筛选: 'buy', 'sell'"), exit_reason: Optional[str] = Query(None, description="平仓原因筛选: 'stop_loss', 'take_profit', 'trailing_stop', 'manual', 'sync'"), status: Optional[str] = Query(None, description="状态筛选: 'open', 'closed', 'cancelled'"), - limit: int = Query(100, ge=1, le=1000, description="返回记录数限制") + limit: int = Query(100, ge=1, le=1000, description="返回记录数限制"), + only_system_orders: bool = Query(False, description="仅返回本系统开仓的记录(有开仓订单号),排除同步/手动录入的仓位"), ): """ 获取交易记录 @@ -125,7 +126,7 @@ async def get_trades( except ValueError: logger.warning(f"无效的结束日期格式: {end_date}") - trades = Trade.get_all(start_timestamp, end_timestamp, symbol, status, trade_type, exit_reason, account_id=account_id) + trades = Trade.get_all(start_timestamp, end_timestamp, symbol, status, trade_type, exit_reason, account_id=account_id, only_system_orders=only_system_orders) logger.info(f"查询到 {len(trades)} 条交易记录") # 格式化交易记录,添加平仓类型的中文显示 @@ -166,7 +167,8 @@ async def get_trades( "end_date": datetime.fromtimestamp(end_timestamp).strftime('%Y-%m-%d %H:%M:%S') if end_timestamp else None, "period": period, "symbol": symbol, - "status": status + "status": status, + "only_system_orders": only_system_orders } } @@ -183,11 +185,12 @@ async def get_trade_stats( start_date: Optional[str] = Query(None, description="开始日期 (YYYY-MM-DD 或 YYYY-MM-DD HH:MM:SS)"), end_date: Optional[str] = Query(None, description="结束日期 (YYYY-MM-DD 或 YYYY-MM-DD HH:MM:SS)"), period: Optional[str] = Query(None, description="快速时间段筛选: '1d', '7d', '30d', 'today', 'week', 'month'"), - symbol: Optional[str] = Query(None, description="交易对筛选") + symbol: Optional[str] = Query(None, description="交易对筛选"), + only_system_orders: bool = Query(False, description="仅统计本系统开仓的记录"), ): """获取交易统计""" try: - logger.info(f"获取交易统计请求: start_date={start_date}, end_date={end_date}, period={period}, symbol={symbol}") + logger.info(f"获取交易统计请求: start_date={start_date}, end_date={end_date}, period={period}, symbol={symbol}, only_system_orders={only_system_orders}") start_timestamp = None end_timestamp = None @@ -220,7 +223,7 @@ async def get_trade_stats( except ValueError: logger.warning(f"无效的结束日期格式: {end_date}") - trades = Trade.get_all(start_timestamp, end_timestamp, symbol, None, account_id=account_id) + trades = Trade.get_all(start_timestamp, end_timestamp, symbol, None, account_id=account_id, only_system_orders=only_system_orders) closed_trades = [t for t in trades if t['status'] == 'closed'] # 辅助函数:计算净盈亏(优先使用 realized_pnl - commission) diff --git a/backend/database/models.py b/backend/database/models.py index 29e8bfe..d80a1ca 100644 --- a/backend/database/models.py +++ b/backend/database/models.py @@ -700,7 +700,7 @@ class Trade: ) @staticmethod - def get_all(start_timestamp=None, end_timestamp=None, symbol=None, status=None, trade_type=None, exit_reason=None, account_id: int = None): + def get_all(start_timestamp=None, end_timestamp=None, symbol=None, status=None, trade_type=None, exit_reason=None, account_id: int = None, only_system_orders: bool = False): """获取交易记录 Args: @@ -710,6 +710,7 @@ class Trade: status: 状态(可选) trade_type: 交易类型(可选) exit_reason: 平仓原因(可选) + only_system_orders: 若为 True,仅返回本系统开仓的记录(entry_order_id 非空) """ query = "SELECT * FROM trades WHERE 1=1" params = [] @@ -722,6 +723,9 @@ class Trade: except Exception: pass + if only_system_orders and _table_has_column("trades", "entry_order_id"): + query += " AND entry_order_id IS NOT NULL AND entry_order_id != 0" + if start_timestamp is not None: query += " AND created_at >= %s" params.append(start_timestamp) diff --git a/frontend/src/components/TradeList.jsx b/frontend/src/components/TradeList.jsx index 576cd6f..6e7ddf7 100644 --- a/frontend/src/components/TradeList.jsx +++ b/frontend/src/components/TradeList.jsx @@ -20,6 +20,7 @@ const TradeList = () => { const [useCustomDate, setUseCustomDate] = useState(false) const [tradeType, setTradeType] = useState('') const [exitReason, setExitReason] = useState('') + const [onlySystemOrders, setOnlySystemOrders] = useState(false) useEffect(() => { loadData() @@ -45,6 +46,7 @@ const TradeList = () => { if (status) params.status = status if (tradeType) params.trade_type = tradeType if (exitReason) params.exit_reason = exitReason + if (onlySystemOrders) params.only_system_orders = true const [tradesData, statsData] = await Promise.all([ api.getTrades(params), @@ -80,6 +82,7 @@ const TradeList = () => { setSymbol('') setStatus('') setUseCustomDate(false) + setOnlySystemOrders(false) } // 导出当前订单数据(含入场/离场原因、入场思路等完整字段,便于后续分析) @@ -417,6 +420,17 @@ const TradeList = () => { +
+ +
+