diff --git a/backend/api/routes/account.py b/backend/api/routes/account.py index d415885..cf28239 100644 --- a/backend/api/routes/account.py +++ b/backend/api/routes/account.py @@ -1764,8 +1764,13 @@ async def sync_positions( recovered_count = 0 system_order_prefix = "" try: - from database.models import TradingConfig - system_order_prefix = (TradingConfig.get_value("SYSTEM_ORDER_ID_PREFIX", "", account_id=account_id) or "").strip() + from database.models import TradingConfig, GlobalStrategyConfig + system_order_prefix = ( + TradingConfig.get_value("SYSTEM_ORDER_ID_PREFIX", None, account_id=account_id) + or GlobalStrategyConfig.get_value("SYSTEM_ORDER_ID_PREFIX", "") + or "" + ) + system_order_prefix = (system_order_prefix or "").strip() except Exception: pass if missing_in_db: diff --git a/backend/api/routes/config.py b/backend/api/routes/config.py index 2c3990c..898dca4 100644 --- a/backend/api/routes/config.py +++ b/backend/api/routes/config.py @@ -40,10 +40,6 @@ USER_RISK_KNOBS = { "AUTO_TRADE_ENABLED", # 总开关:关闭则只生成推荐不自动下单 "MAX_OPEN_POSITIONS", # 同时持仓数量上限 "MAX_DAILY_ENTRIES", # 每日最多开仓次数 - # 同步/系统单标识(仓位控制) - "SYNC_RECOVER_MISSING_POSITIONS", - "SYNC_RECOVER_ONLY_WHEN_HAS_SLTP", - "SYSTEM_ORDER_ID_PREFIX", # 策略筛选(允许用户调整) "TOP_N_SYMBOLS", "MIN_SIGNAL_STRENGTH", @@ -64,9 +60,6 @@ USER_VISIBLE_DEFAULTS = { "MAX_TOTAL_POSITION_PERCENT": {"value": 20.0, "type": "number", "category": "position", "description": "总仓位最大保证金占比(%)"}, "AUTO_TRADE_ENABLED": {"value": True, "type": "boolean", "category": "risk", "description": "自动交易总开关:关闭后仅生成推荐,不会自动下单"}, "MAX_OPEN_POSITIONS": {"value": 3, "type": "number", "category": "position", "description": "同时持仓数量上限"}, - "SYNC_RECOVER_MISSING_POSITIONS": {"value": True, "type": "boolean", "category": "position", "description": "同步时补建「币安有仓、DB 无记录」的交易记录(便于订单记录与统计)"}, - "SYNC_RECOVER_ONLY_WHEN_HAS_SLTP": {"value": True, "type": "boolean", "category": "position", "description": "仅当该持仓存在止损/止盈单时才补建(未配置 SYSTEM_ORDER_ID_PREFIX 时生效)"}, - "SYSTEM_ORDER_ID_PREFIX": {"value": "SYS", "type": "string", "category": "position", "description": "系统单标识:下单时写入 newClientOrderId 前缀,同步时仅对「开仓订单 clientOrderId 以此前缀开头」的持仓补建;设空则用「是否有止损止盈单」判断"}, "MAX_DAILY_ENTRIES": {"value": 8, "type": "number", "category": "risk", "description": "每日最多开仓次数"}, "TOP_N_SYMBOLS": {"value": 8, "type": "number", "category": "scan", "description": "每次扫描后优先处理的交易对数量"}, "MIN_SIGNAL_STRENGTH": {"value": 8, "type": "number", "category": "scan", "description": "最小信号强度(0-10)"}, @@ -492,6 +485,24 @@ async def get_global_configs( "category": "strategy", "description": "是否启用移动止损(默认关闭,让利润奔跑)", }, + "SYNC_RECOVER_MISSING_POSITIONS": { + "value": True, + "type": "boolean", + "category": "position", + "description": "同步时补建「币安有仓、DB 无记录」的交易记录(便于订单记录与统计)", + }, + "SYNC_RECOVER_ONLY_WHEN_HAS_SLTP": { + "value": True, + "type": "boolean", + "category": "position", + "description": "仅当该持仓存在止损/止盈单时才补建(未配置 SYSTEM_ORDER_ID_PREFIX 时生效)", + }, + "SYSTEM_ORDER_ID_PREFIX": { + "value": "SYS", + "type": "string", + "category": "position", + "description": "系统单标识:下单时写入 newClientOrderId 前缀,同步时仅对「开仓订单 clientOrderId 以此前缀开头」的持仓补建;设空则用「是否有止损止盈单」判断", + }, "SMART_ENTRY_ENABLED": { "value": False, "type": "boolean", diff --git a/backend/config_manager.py b/backend/config_manager.py index a2c9f74..f948bcf 100644 --- a/backend/config_manager.py +++ b/backend/config_manager.py @@ -825,6 +825,11 @@ class ConfigManager: 'AUTO_TRADE_ENABLED': eff_get('AUTO_TRADE_ENABLED', True), 'MAX_OPEN_POSITIONS': eff_get('MAX_OPEN_POSITIONS', 3), 'MAX_DAILY_ENTRIES': eff_get('MAX_DAILY_ENTRIES', max_daily_default), + + # 同步/系统单标识(全局配置,账号可覆盖) + 'SYNC_RECOVER_MISSING_POSITIONS': eff_get('SYNC_RECOVER_MISSING_POSITIONS', True), + 'SYNC_RECOVER_ONLY_WHEN_HAS_SLTP': eff_get('SYNC_RECOVER_ONLY_WHEN_HAS_SLTP', True), + 'SYSTEM_ORDER_ID_PREFIX': eff_get('SYSTEM_ORDER_ID_PREFIX', 'SYS') or '', # 涨跌幅阈值 'MIN_CHANGE_PERCENT': eff_get('MIN_CHANGE_PERCENT', 2.0), diff --git a/frontend/src/components/ConfigPanel.jsx b/frontend/src/components/ConfigPanel.jsx index cd83b04..54c8824 100644 --- a/frontend/src/components/ConfigPanel.jsx +++ b/frontend/src/components/ConfigPanel.jsx @@ -46,7 +46,6 @@ const ConfigPanel = () => { const USER_RISK_KNOBS_SET = new Set([ 'MIN_MARGIN_USDT', 'MIN_POSITION_PERCENT', 'MAX_POSITION_PERCENT', 'MAX_TOTAL_POSITION_PERCENT', 'AUTO_TRADE_ENABLED', 'MAX_OPEN_POSITIONS', 'MAX_DAILY_ENTRIES', - 'SYNC_RECOVER_MISSING_POSITIONS', 'SYNC_RECOVER_ONLY_WHEN_HAS_SLTP', 'SYSTEM_ORDER_ID_PREFIX', 'TOP_N_SYMBOLS', 'MIN_SIGNAL_STRENGTH', 'MIN_VOLUME_24H', 'MIN_VOLATILITY', 'SCAN_EXTRA_SYMBOLS_FOR_SUPPLEMENT', 'EXCLUDE_MAJOR_COINS', 'MAX_SCAN_SYMBOLS', 'SCAN_INTERVAL', ]) diff --git a/frontend/src/components/GlobalConfig.jsx b/frontend/src/components/GlobalConfig.jsx index 9899def..cf511bd 100644 --- a/frontend/src/components/GlobalConfig.jsx +++ b/frontend/src/components/GlobalConfig.jsx @@ -32,6 +32,9 @@ const KEY_LABELS = { MIN_RR_FOR_TP1: '第一目标最小盈亏比(相对止损)', AUTO_TRADE_ALLOW_4H_NEUTRAL: '允许 4H 中性时自动交易', POSITION_SCALE_FACTOR: '仓位放大系数', + SYNC_RECOVER_MISSING_POSITIONS: '同步时补建缺失持仓', + SYNC_RECOVER_ONLY_WHEN_HAS_SLTP: '仅当有止损/止盈单时补建', + SYSTEM_ORDER_ID_PREFIX: '系统单 clientOrderId 前缀', } const ConfigItem = ({ label, config, onUpdate, disabled }) => {