diff --git a/backend/api/routes/config.py b/backend/api/routes/config.py index e2112da..54d9255 100644 --- a/backend/api/routes/config.py +++ b/backend/api/routes/config.py @@ -851,6 +851,7 @@ async def get_global_configs( try: from database.models import GlobalStrategyConfig configs = GlobalStrategyConfig.get_all() + logger.info(f"从数据库加载了 {len(configs)} 个全局配置项") result = {} for config in configs: key = config['config_key'] @@ -864,6 +865,7 @@ async def get_global_configs( "category": config['category'], "description": config.get('description'), } + logger.debug(f"加载配置项: {key} = {value} (type: {config['config_type']}, category: {config['category']})") # 添加默认配置(如果数据库中没有) for k, meta in CORE_STRATEGY_CONFIG_DEFAULTS.items(): @@ -889,6 +891,80 @@ async def get_global_configs( if k not in result: result[k] = meta + # 添加更多核心策略配置的默认值(确保前端能显示所有重要配置) + ADDITIONAL_STRATEGY_DEFAULTS = { + "USE_ATR_STOP_LOSS": { + "value": True, + "type": "boolean", + "category": "strategy", + "description": "是否使用ATR动态止损(优先于固定百分比)", + }, + "ATR_PERIOD": { + "value": 14, + "type": "number", + "category": "strategy", + "description": "ATR计算周期(默认14)", + }, + "USE_DYNAMIC_ATR_MULTIPLIER": { + "value": False, + "type": "boolean", + "category": "strategy", + "description": "是否根据波动率动态调整ATR倍数", + }, + "ATR_MULTIPLIER_MIN": { + "value": 1.5, + "type": "number", + "category": "strategy", + "description": "动态ATR倍数最小值", + }, + "ATR_MULTIPLIER_MAX": { + "value": 2.5, + "type": "number", + "category": "strategy", + "description": "动态ATR倍数最大值", + }, + "MIN_SIGNAL_STRENGTH": { + "value": 8, + "type": "number", + "category": "strategy", + "description": "最小信号强度(0-10),只交易高质量信号", + }, + "SCAN_INTERVAL": { + "value": 1800, + "type": "number", + "category": "scan", + "description": "市场扫描间隔(秒),默认30分钟", + }, + "TOP_N_SYMBOLS": { + "value": 8, + "type": "number", + "category": "scan", + "description": "每次扫描后处理的交易对数量", + }, + "MIN_VOLUME_24H_STRICT": { + "value": 10000000, + "type": "number", + "category": "scan", + "description": "严格成交量过滤,24H Volume低于此值(USD)直接剔除", + }, + "USE_TRAILING_STOP": { + "value": False, + "type": "boolean", + "category": "strategy", + "description": "是否启用移动止损(默认关闭,让利润奔跑)", + }, + "SMART_ENTRY_ENABLED": { + "value": False, + "type": "boolean", + "category": "strategy", + "description": "智能入场开关。关闭后回归纯限价单模式", + }, + } + for k, meta in ADDITIONAL_STRATEGY_DEFAULTS.items(): + if k not in result: + result[k] = meta + + logger.info(f"返回全局配置项数量: {len(result)}") return result except Exception as e: raise HTTPException(status_code=500, detail=str(e)) diff --git a/frontend/src/components/GlobalConfig.jsx b/frontend/src/components/GlobalConfig.jsx index 02e5dfd..0536af2 100644 --- a/frontend/src/components/GlobalConfig.jsx +++ b/frontend/src/components/GlobalConfig.jsx @@ -386,7 +386,8 @@ const GlobalConfig = () => { // 管理员全局配置:从独立的全局配置表读取,不依赖任何 account if (isAdmin) { const data = await api.getGlobalConfigs() - setConfigs(data) + console.log('Loaded global configs:', data, 'Keys:', Object.keys(data || {})) + setConfigs(data || {}) } else { // 非管理员不应该访问这个页面 setConfigs({}) @@ -1158,7 +1159,12 @@ const GlobalConfig = () => { } return Object.entries(configCategories).map(([category, label]) => { const categoryConfigs = Object.entries(configs).filter(([key, config]) => { - if (config.category !== category) return false + // 确保config是对象且有category字段 + if (!config || typeof config !== 'object') { + console.warn(`Config ${key} is not an object:`, config) + return false + } + if (!config.category || config.category !== category) return false // 排除风险旋钮(这些由用户自己控制) const RISK_KNOBS_KEYS = ['MIN_MARGIN_USDT', 'MIN_POSITION_PERCENT', 'MAX_POSITION_PERCENT', 'MAX_TOTAL_POSITION_PERCENT', 'AUTO_TRADE_ENABLED', 'MAX_OPEN_POSITIONS', 'MAX_DAILY_ENTRIES'] @@ -1168,6 +1174,7 @@ const GlobalConfig = () => { return true }) if (categoryConfigs.length === 0) return null + console.log(`Category ${category} (${label}): ${categoryConfigs.length} configs`, categoryConfigs.map(([k]) => k)) return (