From 46d31fde59f934c9dcfa2bdae638e64fad385d39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=96=87=E8=96=87=E5=AE=89?= Date: Fri, 13 Feb 2026 17:56:27 +0800 Subject: [PATCH] 1 --- backend/database/connection.py | 2 +- check_trades.py | 58 +- check_trades_today.py | 51 ++ config-snapshot-2026-02-13T07-58-50-449Z.json | 643 ++++++++++++++++++ debug_config.py | 58 ++ inspect_db.py | 34 + trading_system/config.py | 296 ++++---- trading_system/risk_manager.py | 17 + update_risk_config_db.py | 77 +++ 9 files changed, 1036 insertions(+), 200 deletions(-) create mode 100644 check_trades_today.py create mode 100644 config-snapshot-2026-02-13T07-58-50-449Z.json create mode 100644 debug_config.py create mode 100644 inspect_db.py create mode 100644 update_risk_config_db.py diff --git a/backend/database/connection.py b/backend/database/connection.py index 24f9995..4840a9b 100644 --- a/backend/database/connection.py +++ b/backend/database/connection.py @@ -51,7 +51,7 @@ class Database: self.port = int(os.getenv('DB_PORT', 3306)) self.user = os.getenv('DB_USER', 'root') self.password = os.getenv('DB_PASSWORD', '') - self.database = os.getenv('DB_NAME', 'auto_trade_sys') + self.database = os.getenv('DB_NAME', 'auto_trade_sys_new') # 记录配置信息(不显示密码) logger.debug(f"数据库配置: host={self.host}, port={self.port}, user={self.user}, database={self.database}") diff --git a/check_trades.py b/check_trades.py index a8dd397..2660a9a 100644 --- a/check_trades.py +++ b/check_trades.py @@ -25,50 +25,24 @@ def main(): print(f"Connected to {DB_NAME}") - # Check all databases - print("\n=== All Databases ===") - cursor.execute("SHOW DATABASES") - for db in cursor.fetchall(): - print(db['Database']) - - # 1. Check Open Positions for Account 2 - print("\n=== Open Positions (Account 2) ===") - cursor.execute(""" - SELECT id, symbol, side, entry_price, quantity, leverage, stop_loss_price, take_profit_price, created_at - FROM trades - WHERE status = 'open' AND account_id = 2 - ORDER BY created_at DESC - """) - open_trades = cursor.fetchall() - - if not open_trades: - print("No open positions found for Account 2.") + # Search for Trade ID 3507 + print("\n=== Search for Trade ID 3507 ===") + cursor.execute("SELECT * FROM trades WHERE id = 3507") + trade = cursor.fetchone() + if trade: + print(f"Found Trade 3507:") + for k, v in trade.items(): + print(f" {k}: {v}") else: - for trade in open_trades: - entry_time = datetime.fromtimestamp(trade['created_at']).strftime('%Y-%m-%d %H:%M:%S') - print(f"ID: {trade['id']}, Symbol: {trade['symbol']}, Side: {trade['side']}, Entry: {trade['entry_price']}, SL: {trade['stop_loss_price']}, TP: {trade['take_profit_price']}, Time: {entry_time}") - - # 2. Check Recent Closed Trades for Account 2 - cursor.execute(f"SELECT id, symbol, side, status, pnl, pnl_percent, stop_loss_price, take_profit_price, entry_time, quantity, entry_price FROM trades WHERE account_id = 2 ORDER BY id DESC LIMIT 10") - trades = cursor.fetchall() - print(f"Account 2 recent trades:") - for t in trades: - # Handle entry_time conversion if it's a timestamp or datetime - entry_time = t.get('entry_time') - print(f"ID: {t['id']}, Symbol: {t['symbol']}, Side: {t['side']}, Status: {t['status']}, PnL: {t['pnl']}, PnL%: {t['pnl_percent']}, SL: {t['stop_loss_price']}, TP: {t['take_profit_price']}, Time: {entry_time}, Qty: {t['quantity']}, Price: {t['entry_price']}") + print("Trade 3507 not found in DB.") - # 3. Check for the specific "All take profits" claim - print("\n=== Checking for Negative PnL with Take Profit Reason ===") - cursor.execute(""" - SELECT COUNT(*) as count - FROM trades - WHERE status != 'open' - AND exit_reason = 'take_profit' - AND pnl < 0 - """) - count = cursor.fetchone()['count'] - print(f"Number of 'take_profit' trades with negative PnL: {count}") - + # Check latest trades across all accounts + print("\n=== Latest 5 Trades (All Accounts) ===") + cursor.execute("SELECT id, account_id, symbol, status, pnl, pnl_percent, exit_reason, created_at FROM trades ORDER BY id DESC LIMIT 5") + trades = cursor.fetchall() + for t in trades: + print(t) + conn.close() except Exception as e: diff --git a/check_trades_today.py b/check_trades_today.py new file mode 100644 index 0000000..dc2fc87 --- /dev/null +++ b/check_trades_today.py @@ -0,0 +1,51 @@ + +import os +import sys +from sqlalchemy import create_engine, text +import json +from datetime import datetime + +# Database connection +DB_USER = os.getenv('DB_USER', 'root') +DB_PASSWORD = os.getenv('DB_PASSWORD', '12345678') +DB_HOST = os.getenv('DB_HOST', 'localhost') +DB_PORT = os.getenv('DB_PORT', '3306') +DB_NAME = 'auto_trade_sys_new' + +DATABASE_URL = f"mysql+pymysql://{DB_USER}:{DB_PASSWORD}@{DB_HOST}:{DB_PORT}/{DB_NAME}" + +def check_today_trades(): + try: + engine = create_engine(DATABASE_URL) + with engine.connect() as conn: + # Query trades from today (2026-02-13) + query = text(""" + SELECT id, symbol, side, entry_price, exit_price, pnl, pnl_percent, exit_reason, exit_time, entry_time + FROM trades + WHERE DATE(entry_time) = '2026-02-13' OR DATE(exit_time) = '2026-02-13' + ORDER BY exit_time DESC + LIMIT 10 + """) + result = conn.execute(query) + trades = [] + for row in result: + trades.append({ + "id": row[0], + "symbol": row[1], + "side": row[2], + "entry_price": float(row[3]) if row[3] else None, + "exit_price": float(row[4]) if row[4] else None, + "pnl": float(row[5]) if row[5] else None, + "pnl_percent": float(row[6]) if row[6] else None, + "exit_reason": row[7], + "exit_time": str(row[8]) if row[8] else None, + "entry_time": str(row[9]) if row[9] else None + }) + + print(json.dumps(trades, indent=2)) + + except Exception as e: + print(f"Error: {e}") + +if __name__ == "__main__": + check_today_trades() diff --git a/config-snapshot-2026-02-13T07-58-50-449Z.json b/config-snapshot-2026-02-13T07-58-50-449Z.json new file mode 100644 index 0000000..0d8f2f8 --- /dev/null +++ b/config-snapshot-2026-02-13T07-58-50-449Z.json @@ -0,0 +1,643 @@ +{ + "fetched_at": "2026-02-13T07:58:47.687Z", + "note": "display_value 对 PERCENT/PCT 做了百分比换算;敏感字段可选择脱敏/明文。", + "preset_detected": null, + "system_status": { + "running": true, + "pid": 4103975, + "program": "auto_sys", + "state": "RUNNING" + }, + "configs": [ + { + "key": "MAX_POSITION_PERCENT", + "category": "position", + "category_label": "仓位控制", + "type": "number", + "value": 0.002, + "display_value": 0.2, + "description": "预设方案配置项:MAX_POSITION_PERCENT" + }, + { + "key": "MAX_TOTAL_POSITION_PERCENT", + "category": "position", + "category_label": "仓位控制", + "type": "number", + "value": 0.008, + "display_value": 0.8, + "description": "预设方案配置项:MAX_TOTAL_POSITION_PERCENT" + }, + { + "key": "MIN_POSITION_PERCENT", + "category": "position", + "category_label": "仓位控制", + "type": "number", + "value": 0, + "display_value": 0, + "description": "预设方案配置项:MIN_POSITION_PERCENT" + }, + { + "key": "AUTO_TRADE_ALLOW_4H_NEUTRAL", + "category": "strategy", + "category_label": "策略参数", + "type": "boolean", + "value": false, + "display_value": false, + "description": "AUTO_TRADE_ALLOW_4H_NEUTRAL配置" + }, + { + "key": "AUTO_TRADE_ONLY_TRENDING", + "category": "strategy", + "category_label": "策略参数", + "type": "boolean", + "value": true, + "display_value": true, + "description": "AUTO_TRADE_ONLY_TRENDING配置" + }, + { + "key": "BETA_FILTER_ENABLED", + "category": "strategy", + "category_label": "策略参数", + "type": "boolean", + "value": true, + "display_value": true, + "description": "大盘共振过滤:BTC/ETH 下跌时屏蔽多单。" + }, + { + "key": "BETA_FILTER_THRESHOLD", + "category": "strategy", + "category_label": "策略参数", + "type": "number", + "value": -0.005, + "display_value": -0.005, + "description": "大盘共振阈值(比例,如 -0.005 表示 -0.5%)。" + }, + { + "key": "ENTRY_CHASE_MAX_STEPS", + "category": "strategy", + "category_label": "策略参数", + "type": "number", + "value": 2, + "display_value": 2, + "description": "最大追价步数(逐步减小限价回调幅度,靠近当前价)。" + }, + { + "key": "ENTRY_CONFIRM_TIMEOUT_SEC", + "category": "strategy", + "category_label": "策略参数", + "type": "number", + "value": 120, + "display_value": 120, + "description": "下单后确认成交等待时间(秒)。" + }, + { + "key": "ENTRY_MARKET_FALLBACK_AFTER_SEC", + "category": "strategy", + "category_label": "策略参数", + "type": "number", + "value": 60, + "display_value": 60, + "description": "趋势强时:超过该时间仍未成交,会在偏离不超过上限时转市价兜底(减少错过)。" + }, + { + "key": "ENTRY_MAX_DRIFT_PCT_RANGING", + "category": "strategy", + "category_label": "策略参数", + "type": "number", + "value": 0.3, + "display_value": 0.3, + "description": "震荡/弱趋势最大追价偏离(%)。例如 0.3 表示 0.3%。越小越保守。" + }, + { + "key": "ENTRY_MAX_DRIFT_PCT_TRENDING", + "category": "strategy", + "category_label": "策略参数", + "type": "number", + "value": 0.8, + "display_value": 0.8, + "description": "趋势强时最大追价偏离(%)。例如 0.6 表示 0.6%。越小越保守。" + }, + { + "key": "ENTRY_SHORT_TREND_FILTER_ENABLED", + "category": "strategy", + "category_label": "策略参数", + "type": "boolean", + "value": true, + "display_value": true, + "description": "预设方案配置项:ENTRY_SHORT_TREND_FILTER_ENABLED" + }, + { + "key": "ENTRY_STEP_WAIT_SEC", + "category": "strategy", + "category_label": "策略参数", + "type": "number", + "value": 20, + "display_value": 20, + "description": "每次追价/调整前等待成交时间(秒)。" + }, + { + "key": "ENTRY_SYMBOL_COOLDOWN_SEC", + "category": "strategy", + "category_label": "策略参数", + "type": "number", + "value": 1800, + "display_value": 1800, + "description": "预设方案配置项:ENTRY_SYMBOL_COOLDOWN_SEC" + }, + { + "key": "LEVERAGE", + "category": "strategy", + "category_label": "策略参数", + "type": "number", + "value": 10, + "display_value": 10, + "description": "基础杠杆倍数" + }, + { + "key": "MAX_CHANGE_PERCENT_FOR_LONG", + "category": "strategy", + "category_label": "策略参数", + "type": "number", + "value": 0.25, + "display_value": 25, + "description": "做多时 24h 涨跌幅超过此值则不开多(避免追大涨)。单位:百分比数值,如 25 表示 25%。2026-01-31新增。" + }, + { + "key": "MAX_CHANGE_PERCENT_FOR_SHORT", + "category": "strategy", + "category_label": "策略参数", + "type": "number", + "value": 0.1, + "display_value": 10, + "description": "做空时 24h 涨跌幅超过此值则不做空(24h 仍大涨时不做空)。单位:百分比数值。2026-01-31新增。" + }, + { + "key": "MAX_LEVERAGE", + "category": "strategy", + "category_label": "策略参数", + "type": "number", + "value": 20, + "display_value": 20, + "description": "最大杠杆倍数(动态杠杆上限,降低到15更保守)" + }, + { + "key": "MAX_RSI_FOR_LONG", + "category": "strategy", + "category_label": "策略参数", + "type": "number", + "value": 65, + "display_value": 65, + "description": "做多时 RSI 超过此值则不开多(避免超买区追多)。2026-01-31新增。" + }, + { + "key": "MIN_RR_FOR_TP1", + "category": "strategy", + "category_label": "策略参数", + "type": "number", + "value": 1.2, + "display_value": 1.2, + "description": "第一目标止盈相对止损的最小盈亏比(如 1.5 表示 TP1 至少为止损距离的 1.5 倍)。2026-02-12 新增。" + }, + { + "key": "MIN_RSI_FOR_SHORT", + "category": "strategy", + "category_label": "策略参数", + "type": "number", + "value": 30, + "display_value": 30, + "description": "做空时 RSI 低于此值则不做空(避免深超卖反弹)。2026-01-31新增。" + }, + { + "key": "RSI_EXTREME_REVERSE_ONLY_NEUTRAL_4H", + "category": "strategy", + "category_label": "策略参数", + "type": "boolean", + "value": false, + "display_value": false, + "description": "建议开启:仅在 4H 趋势为中性时允许 RSI 反向单,避免在强趋势里逆势抄底/摸顶,降低风险。关闭则反向可与 4H 同向(仍受“禁止逆4H趋势”约束)。" + }, + { + "key": "SMART_ENTRY_ENABLED", + "category": "strategy", + "category_label": "策略参数", + "type": "boolean", + "value": true, + "display_value": true, + "description": "预设方案配置项:SMART_ENTRY_ENABLED" + }, + { + "key": "SYMBOL_LOSS_COOLDOWN_ENABLED", + "category": "strategy", + "category_label": "策略参数", + "type": "boolean", + "value": true, + "display_value": true, + "description": "是否启用同一交易对连续亏损后的冷却(避免连续亏损后继续交易)。2026-01-29新增。" + }, + { + "key": "SYMBOL_LOSS_COOLDOWN_SEC", + "category": "strategy", + "category_label": "策略参数", + "type": "number", + "value": 3600, + "display_value": 3600, + "description": "连续亏损后的冷却时间(秒),默认1小时。2026-01-29新增。" + }, + { + "key": "SYMBOL_MAX_CONSECUTIVE_LOSSES", + "category": "strategy", + "category_label": "策略参数", + "type": "number", + "value": 2, + "display_value": 2, + "description": "最大允许连续亏损次数(超过则禁止交易该交易对一段时间)。2026-01-29新增。" + }, + { + "key": "TAKE_PROFIT_1_PERCENT", + "category": "strategy", + "category_label": "策略参数", + "type": "number", + "value": 0.2, + "display_value": 20, + "description": "分步止盈第一目标(保证金百分比,如 0.15=15%)。第一目标触发后了结50%仓位,剩余追求第二目标。" + }, + { + "key": "TRADING_PROFILE", + "category": "strategy", + "category_label": "策略参数", + "type": "string", + "value": "conservative", + "display_value": "conservative", + "description": "交易预设:conservative(稳健,低频+高门槛) / fast(快速验证,高频+宽松过滤)。仅作为默认值,具体参数仍可单独调整。" + }, + { + "key": "TRAILING_STOP_ACTIVATION", + "category": "strategy", + "category_label": "策略参数", + "type": "number", + "value": 0.15, + "display_value": 0.15, + "description": "移动止损激活阈值(盈利10%后激活,给趋势更多空间)" + }, + { + "key": "TRAILING_STOP_PROTECT", + "category": "strategy", + "category_label": "策略参数", + "type": "number", + "value": 0.05, + "display_value": 0.05, + "description": "移动止损保护利润(保护5%利润,更合理)" + }, + { + "key": "USE_DYNAMIC_LEVERAGE", + "category": "strategy", + "category_label": "策略参数", + "type": "boolean", + "value": true, + "display_value": true, + "description": "是否启用动态杠杆(根据信号强度调整杠杆倍数)" + }, + { + "key": "USE_TRAILING_STOP", + "category": "strategy", + "category_label": "策略参数", + "type": "boolean", + "value": true, + "display_value": true, + "description": "预设方案配置项:USE_TRAILING_STOP" + }, + { + "key": "ATR_MULTIPLIER_MAX", + "category": "risk", + "category_label": "风险控制", + "type": "number", + "value": 0.5, + "display_value": 0.5, + "description": "动态ATR倍数最大值0.5" + }, + { + "key": "ATR_MULTIPLIER_MIN", + "category": "risk", + "category_label": "风险控制", + "type": "number", + "value": 0.5, + "display_value": 0.5, + "description": "动态ATR倍数最小值0.5" + }, + { + "key": "ATR_PERIOD", + "category": "risk", + "category_label": "风险控制", + "type": "number", + "value": 7, + "display_value": 7, + "description": "ATR计算周期(默认7)" + }, + { + "key": "ATR_STOP_LOSS_MULTIPLIER", + "category": "risk", + "category_label": "风险控制", + "type": "number", + "value": 2.5, + "display_value": 2.5, + "description": "ATR止损倍数(0.4 - 0.6倍ATR,信号强 → 倍数低 (0.4);信号弱 → 倍数高 (0.6))" + }, + { + "key": "FIXED_RISK_PERCENT", + "category": "risk", + "category_label": "风险控制", + "type": "number", + "value": 0.02, + "display_value": 2, + "description": "每笔单子承受的风险百分比(相对于总资金)。例如 0.02 表示 2%。启用固定风险后,每笔亏损限制在该百分比内。" + }, + { + "key": "MAX_LEVERAGE_SMALL_CAP", + "category": "risk", + "category_label": "风险控制", + "type": "number", + "value": 8, + "display_value": 8, + "description": "高波动/小众币最大允许杠杆(与之前盈利阶段一致)。" + }, + { + "key": "MIN_LEVERAGE", + "category": "risk", + "category_label": "风险控制", + "type": "number", + "value": 8, + "display_value": 8, + "description": "动态杠杆下限(如 8 表示不低于 8 倍)。之前盈利阶段多为 8x,避免被压到 2–4x 导致单笔盈利过少。" + }, + { + "key": "MIN_STOP_LOSS_PRICE_PCT", + "category": "risk", + "category_label": "风险控制", + "type": "number", + "value": 0.025, + "display_value": 2.5, + "description": "最小止损价格变动:2%(防止止损过紧)" + }, + { + "key": "MIN_TAKE_PROFIT_PRICE_PCT", + "category": "risk", + "category_label": "风险控制", + "type": "number", + "value": 0.03, + "display_value": 3, + "description": "最小止盈价格变动:3%(防止止盈过紧)" + }, + { + "key": "POSITION_SCALE_FACTOR", + "category": "risk", + "category_label": "风险控制", + "type": "number", + "value": 1.25, + "display_value": 1.25, + "description": "仓位放大系数:1.0=正常,1.2=+20% 仓位,1.5=+50%,上限 2.0。盈利时适度调高可扩大收益,仍受单笔上限约束。" + }, + { + "key": "RISK_REWARD_RATIO", + "category": "risk", + "category_label": "风险控制", + "type": "number", + "value": 2, + "display_value": 2, + "description": "盈亏比(止损距离的倍数,用于计算止盈)" + }, + { + "key": "STOP_LOSS_PERCENT", + "category": "risk", + "category_label": "风险控制", + "type": "number", + "value": 0.1, + "display_value": 10, + "description": "止损:10%(相对于保证金)" + }, + { + "key": "TAKE_PROFIT_PERCENT", + "category": "risk", + "category_label": "风险控制", + "type": "number", + "value": 0.2, + "display_value": 20, + "description": "预设方案配置项:TAKE_PROFIT_PERCENT" + }, + { + "key": "USE_ATR_STOP_LOSS", + "category": "risk", + "category_label": "风险控制", + "type": "boolean", + "value": true, + "display_value": true, + "description": "是否使用ATR动态止损(优先于固定百分比)" + }, + { + "key": "USE_DYNAMIC_ATR_MULTIPLIER", + "category": "risk", + "category_label": "风险控制", + "type": "boolean", + "value": false, + "display_value": false, + "description": "是否根据波动率动态调整ATR倍数" + }, + { + "key": "USE_FIXED_RISK_SIZING", + "category": "risk", + "category_label": "风险控制", + "type": "boolean", + "value": true, + "display_value": true, + "description": "使用固定风险百分比计算仓位(凯利公式)。启用后,每笔单子承受的风险固定为 FIXED_RISK_PERCENT,避免大额亏损。" + }, + { + "key": "ATR_TAKE_PROFIT_MULTIPLIER", + "category": "scan", + "category_label": "市场扫描", + "type": "number", + "value": 2, + "display_value": 2, + "description": "预设方案配置项:ATR_TAKE_PROFIT_MULTIPLIER" + }, + { + "key": "CONFIRM_INTERVAL", + "category": "scan", + "category_label": "市场扫描", + "type": "string", + "value": "4h", + "display_value": "4h", + "description": "确认周期:4小时" + }, + { + "key": "ENTRY_INTERVAL", + "category": "scan", + "category_label": "市场扫描", + "type": "string", + "value": "15m", + "display_value": "15m", + "description": "入场周期:15分钟" + }, + { + "key": "EXCLUDE_MAJOR_COINS", + "category": "scan", + "category_label": "市场扫描", + "type": "boolean", + "value": true, + "display_value": true, + "description": "是否排除主流币(BTC、ETH、BNB等),专注于山寨币。山寨币策略建议开启。" + }, + { + "key": "KLINE_INTERVAL", + "category": "scan", + "category_label": "市场扫描", + "type": "string", + "value": "1h", + "display_value": "1h", + "description": "K线周期:1小时" + }, + { + "key": "LIMIT_ORDER_OFFSET_PCT", + "category": "scan", + "category_label": "市场扫描", + "type": "number", + "value": 0.1, + "display_value": 0.1, + "description": "预设方案配置项:LIMIT_ORDER_OFFSET_PCT" + }, + { + "key": "MAX_DAILY_ENTRIES", + "category": "scan", + "category_label": "市场扫描", + "type": "number", + "value": 10, + "display_value": 10, + "description": "预设方案配置项:MAX_DAILY_ENTRIES" + }, + { + "key": "MAX_OPEN_POSITIONS", + "category": "scan", + "category_label": "市场扫描", + "type": "number", + "value": 5, + "display_value": 5, + "description": "预设方案配置项:MAX_OPEN_POSITIONS" + }, + { + "key": "MAX_SCAN_SYMBOLS", + "category": "scan", + "category_label": "市场扫描", + "type": "number", + "value": 500, + "display_value": 500, + "description": "扫描的最大交易对数量(0表示扫描所有,建议100-500)" + }, + { + "key": "MAX_TREND_MOVE_BEFORE_ENTRY", + "category": "scan", + "category_label": "市场扫描", + "type": "number", + "value": 0.05, + "display_value": 0.05, + "description": "预设方案配置项:MAX_TREND_MOVE_BEFORE_ENTRY" + }, + { + "key": "MIN_CHANGE_PERCENT", + "category": "scan", + "category_label": "市场扫描", + "type": "number", + "value": 0.02, + "display_value": 2, + "description": "最小涨跌幅阈值:2%" + }, + { + "key": "MIN_HOLD_TIME_SEC", + "category": "scan", + "category_label": "市场扫描", + "type": "number", + "value": 1800, + "display_value": 1800, + "description": "预设方案配置项:MIN_HOLD_TIME_SEC" + }, + { + "key": "MIN_SIGNAL_STRENGTH", + "category": "scan", + "category_label": "市场扫描", + "type": "number", + "value": 8, + "display_value": 8, + "description": "预设方案配置项:MIN_SIGNAL_STRENGTH" + }, + { + "key": "MIN_VOLATILITY", + "category": "scan", + "category_label": "市场扫描", + "type": "number", + "value": 0.02, + "display_value": 0.02, + "description": "最小波动率:2%" + }, + { + "key": "MIN_VOLUME_24H", + "category": "scan", + "category_label": "市场扫描", + "type": "number", + "value": 10000000, + "display_value": 10000000, + "description": "最小24小时成交量:1000万USDT" + }, + { + "key": "MIN_VOLUME_24H_STRICT", + "category": "scan", + "category_label": "市场扫描", + "type": "number", + "value": 50000000, + "display_value": 50000000, + "description": "严格成交量过滤,24H Volume低于此值(USD)直接剔除" + }, + { + "key": "POSITION_SYNC_INTERVAL", + "category": "scan", + "category_label": "市场扫描", + "type": "number", + "value": 60, + "display_value": 60, + "description": "持仓状态同步间隔(秒),默认1分钟,用于同步币安实际持仓与数据库状态" + }, + { + "key": "PRIMARY_INTERVAL", + "category": "scan", + "category_label": "市场扫描", + "type": "string", + "value": "1h", + "display_value": "1h", + "description": "主周期:1小时" + }, + { + "key": "SCAN_EXTRA_SYMBOLS_FOR_SUPPLEMENT", + "category": "scan", + "category_label": "市场扫描", + "type": "number", + "value": 15, + "display_value": 15, + "description": "智能补单:多返回的候选数量。当前 TOP_N 中部分因冷却等被跳过时,仍会尝试这批额外候选,避免无单可下。" + }, + { + "key": "SCAN_INTERVAL", + "category": "scan", + "category_label": "市场扫描", + "type": "number", + "value": 1800, + "display_value": 1800, + "description": "预设方案配置项:SCAN_INTERVAL" + }, + { + "key": "TOP_N_SYMBOLS", + "category": "scan", + "category_label": "市场扫描", + "type": "number", + "value": 20, + "display_value": 20, + "description": "预设方案配置项:TOP_N_SYMBOLS" + } + ] +} \ No newline at end of file diff --git a/debug_config.py b/debug_config.py new file mode 100644 index 0000000..e343847 --- /dev/null +++ b/debug_config.py @@ -0,0 +1,58 @@ + +import sys +import os +import asyncio +from pathlib import Path + +# Add project root to path +project_root = Path(os.getcwd()) +sys.path.insert(0, str(project_root)) +sys.path.insert(0, str(project_root / 'backend')) + +# Mock db for simple config read if possible, or use real one +from backend.config_manager import ConfigManager +from backend.database.connection import db + +async def main(): + print("Initializing ConfigManager...") + # Initialize ConfigManager with account_id=1 + config_manager = ConfigManager.for_account(1) + + # Force load from DB + try: + config_manager.reload() + print("Config reloaded from DB.") + except Exception as e: + print(f"Error reloading config: {e}") + + print("\n=== Current TRADING_CONFIG (Merged) ===") + from trading_system import config + + # Manually merge DB config into trading_system.config.TRADING_CONFIG to simulate runtime + for k, v in config_manager._cache.items(): + config.TRADING_CONFIG[k] = v + + tp_pct = config.TRADING_CONFIG.get('TAKE_PROFIT_PERCENT') + tp1_pct = config.TRADING_CONFIG.get('TAKE_PROFIT_1_PERCENT') + + print(f"TAKE_PROFIT_PERCENT: {tp_pct} (Type: {type(tp_pct)})") + print(f"TAKE_PROFIT_1_PERCENT: {tp1_pct} (Type: {type(tp1_pct)})") + + print("\n=== All Take Profit Related Configs ===") + for k, v in config.TRADING_CONFIG.items(): + if 'TAKE_PROFIT' in k: + print(f"{k}: {v}") + + print("\n=== Risk Related Configs ===") + print(f"FIXED_RISK_PERCENT: {config.TRADING_CONFIG.get('FIXED_RISK_PERCENT')}") + print(f"SIGNAL_STRENGTH_POSITION_MULTIPLIER: {config.TRADING_CONFIG.get('SIGNAL_STRENGTH_POSITION_MULTIPLIER')}") + print(f"USE_FIXED_RISK_SIZING: {config.TRADING_CONFIG.get('USE_FIXED_RISK_SIZING')}") + + # Check if there are any suspicious small values + print("\n=== Suspiciously Small Values (< 0.01) ===") + for k, v in config.TRADING_CONFIG.items(): + if isinstance(v, (int, float)) and 0 < v < 0.01: + print(f"{k}: {v}") + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/inspect_db.py b/inspect_db.py new file mode 100644 index 0000000..97d28b9 --- /dev/null +++ b/inspect_db.py @@ -0,0 +1,34 @@ + +import os +import sys +from sqlalchemy import create_engine, text, inspect + +# Database connection +DB_USER = os.getenv('DB_USER', 'root') +DB_PASSWORD = os.getenv('DB_PASSWORD', '12345678') +DB_HOST = os.getenv('DB_HOST', 'localhost') +DB_PORT = os.getenv('DB_PORT', '3306') +DB_NAME = 'auto_trade_sys_new' + +DATABASE_URL = f"mysql+pymysql://{DB_USER}:{DB_PASSWORD}@{DB_HOST}:{DB_PORT}/{DB_NAME}" + +def inspect_db(): + try: + engine = create_engine(DATABASE_URL) + inspector = inspect(engine) + table_names = inspector.get_table_names() + print(f"Tables: {table_names}") + + if 'trading_config' in table_names: + columns = inspector.get_columns('trading_config') + print("\nColumns in trading_config:") + for col in columns: + print(f" - {col['name']} ({col['type']})") + else: + print("\ntrading_config table NOT found!") + + except Exception as e: + print(f"Error: {e}") + +if __name__ == "__main__": + inspect_db() diff --git a/trading_system/config.py b/trading_system/config.py index 1f68ec2..3e5e9dd 100644 --- a/trading_system/config.py +++ b/trading_system/config.py @@ -180,138 +180,150 @@ def _get_config_value(key, default=None): # 最后返回默认值 return default +# 默认配置字典 +DEFAULT_TRADING_CONFIG = { + # ===== 用户风险旋钮(山寨币专属策略)===== + 'AUTO_TRADE_ENABLED': True, # 自动交易总开关 + 'MAX_OPEN_POSITIONS': 4, # 同时持仓数量上限(总仓位12% / 单笔1.5% = 最多4个) + 'MAX_DAILY_ENTRIES': 15, # 每日最多15笔(快速验证模式:提高上限以快速验证策略) + + 'MAX_POSITION_PERCENT': 0.20, # 单笔仓位上限20%(作为风控熔断,实际仓位由固定风险模型决定) + 'MAX_TOTAL_POSITION_PERCENT': 0.80, # 总仓位80%(避免满仓,留有余地) + 'MIN_POSITION_PERCENT': 0.01, # 最小仓位1% + 'MIN_MARGIN_USDT': 10.0, # 最小保证金10美元(提高门槛,过滤过小交易) + 'MIN_CHANGE_PERCENT': 0.5, # 最小价格变动0.5% + 'TOP_N_SYMBOLS': 30, # 扩大候选池到30个,增加机会 + 'SCAN_EXTRA_SYMBOLS_FOR_SUPPLEMENT': 20, # 智能补单候选增加 + 'MAX_SCAN_SYMBOLS': 500, # 扫描前500个 + 'EXCLUDE_MAJOR_COINS': True, # 排除主流币 + 'STOP_LOSS_PERCENT': 0.05, # 基础止损5%(配合ATR动态止损,作为保底) + 'TAKE_PROFIT_PERCENT': 0.80, # 第二目标止盈80%(追求大趋势收益) + 'TAKE_PROFIT_1_PERCENT': 0.30, # 第一目标止盈30%(确保3:1盈亏比) + 'MIN_RR_FOR_TP1': 1.5, # 第一目标止盈的最小盈亏比(相对于止损距离)(2026-02-12:1.5 改善盈亏比) + 'MIN_STOP_LOSS_PRICE_PCT': 0.025, # 最小止损价格变动2.5% + 'MIN_TAKE_PROFIT_PRICE_PCT': 0.02, # 最小止盈价格变动2% + 'USE_ATR_STOP_LOSS': True, # 使用ATR动态止损 + 'ATR_STOP_LOSS_MULTIPLIER': 3.0, # ATR止损倍数3.0(2026-02-12:减少噪音止损,配合止盈拉远) + 'ATR_TAKE_PROFIT_MULTIPLIER': 6.0, # ATR止盈倍数6.0(追求更高盈亏比) + 'RISK_REWARD_RATIO': 3.0, # 盈亏比3:1 + 'ATR_PERIOD': 14, # ATR计算周期14 + 'USE_DYNAMIC_ATR_MULTIPLIER': False, # 不使用动态ATR + 'ATR_MULTIPLIER_MIN': 1.5, # 动态ATR倍数最小值 + 'ATR_MULTIPLIER_MAX': 2.5, # 动态ATR倍数最大值 + 'SCAN_INTERVAL': 900, # 扫描间隔15分钟(900秒),快速验证模式:提高扫描频率以增加交易机会 + 'KLINE_INTERVAL': '1h', + 'PRIMARY_INTERVAL': '4h', # 主周期4小时,过滤噪音 + 'CONFIRM_INTERVAL': '1d', # 确认周期日线,看大趋势 + 'ENTRY_INTERVAL': '1h', # 入场周期1小时,避免太小的时间框架 + # 入场短周期(用于快速方向确认,例如15m),不要太小以免噪音太大 + 'ENTRY_SHORT_INTERVAL': '15m', + # 是否开启“短周期方向过滤”,避免在15m明显上涨时做空、明显下跌时做多(快速验证模式:关闭以增加交易机会) + 'ENTRY_SHORT_TREND_FILTER_ENABLED': True, + # 短周期方向过滤使用的最小趋势幅度(例如0.003=0.3%),变化太小视为震荡不过滤 + 'ENTRY_SHORT_TREND_MIN_PCT': 0.003, + # 检查最近多少根短周期K线来评估方向(例如3根15m约等于45分钟) + 'ENTRY_SHORT_CONFIRM_CANDLES': 3, + 'MIN_VOLUME_24H': 30000000, # 24小时成交额≥3000万美元,过滤垃圾币 + 'MIN_VOLUME_24H_STRICT': 50000000, # 严格过滤≥5000万美元 + 'MIN_VOLATILITY': 0.03, # 最小波动率3%,过滤死币 + 'MIN_SIGNAL_STRENGTH': 8, # 信号强度≥8(2026-01-29优化:从7提高到8,减少低质量信号,提升胜率) + + # ===== 动态过滤优化 ===== + 'BETA_FILTER_ENABLED': True, # 大盘共振过滤:BTC/ETH下跌时屏蔽多单 + 'BETA_FILTER_THRESHOLD': -0.005, # -0.5%(2026-01-27优化:更敏感地过滤大盘风险,15分钟内跌幅超过0.5%即屏蔽多单) + # ===== RSI / 24h 涨跌幅过滤(避免追高杀跌)===== + 'MAX_RSI_FOR_LONG': 65, # 做多时 RSI 超过此值则不开多(2026-02-12:65 避免追高) + 'MAX_CHANGE_PERCENT_FOR_LONG': 25, # 做多时 24h 涨跌幅超过此值则不开多(避免追大涨) + 'MIN_RSI_FOR_SHORT': 30, # 做空时 RSI 低于此值则不做空(避免深超卖反弹) + 'MAX_CHANGE_PERCENT_FOR_SHORT': 10, # 做空时 24h 涨跌幅超过此值则不做空(24h 仍大涨时不做空) + + # ===== RSI 极限反转策略(抄底/逃顶)===== + 'RSI_EXTREME_REVERSE_ENABLED': True, # 开启RSI极限反转:超买反空,超卖反多 + 'RSI_EXTREME_REVERSE_ONLY_NEUTRAL_4H': False, # 允许在有趋势时反向操作(例如:下跌趋势中RSI超卖 -> 抄底) + + 'ATR_SPIKE_THRESHOLD': 2.0, # ATR异常激增阈值(当前ATR / 平均ATR) + 'SIGNAL_STRENGTH_POSITION_MULTIPLIER': {7: 0.8, 8: 1.0, 9: 1.2, 10: 1.5}, # 信号强度分级:7分80%,8分100%,9分120%,10分150%(好机会自动加仓) + + # ===== 仓位管理优化(山寨币专属)===== + 'USE_FIXED_RISK_SIZING': True, # 固定每笔风险,避免亏损扩大 + 'FIXED_RISK_PERCENT': 0.01, # 每笔最多亏总资金1%(山寨币风险高) + 'MAX_LEVERAGE_SMALL_CAP': 8, # 高波动/小众币最大杠杆(与之前盈利阶段一致) + 'MIN_LEVERAGE': 8, # 动态杠杆下限,避免被压到 2–4x 导致单笔盈利过少 + 'ATR_LEVERAGE_REDUCTION_THRESHOLD': 0.05, # ATR超过5%时降低杠杆 + 'LEVERAGE': 8, # 基础杠杆(与之前盈利阶段一致) + 'USE_DYNAMIC_LEVERAGE': True, # 开启动态杠杆(基于止损宽度自动调整,但不低于 MIN_LEVERAGE) + 'MAX_SINGLE_TRADE_LOSS_PERCENT': 20.0, # 单笔交易最大本金亏损率(20%),用于限制杠杆 + 'MAX_LEVERAGE': 20, # 最大杠杆 + # 移动止损:必须开启!山寨币利润要保护 + 'USE_TRAILING_STOP': True, + 'TRAILING_STOP_ACTIVATION': 0.10, # 盈利10%后激活(更早锁定利润) + 'TRAILING_STOP_PROTECT': 0.02, # 保护2%利润(紧跟趋势) + + # 最小持仓时间锁:立即取消!山寨币30分钟可能暴涨暴跌50% + 'MIN_HOLD_TIME_SEC': 0, # 取消持仓时间锁 + 'POSITION_SYNC_INTERVAL': 60, # 持仓状态同步间隔60秒 + + # ===== 自动交易过滤(用于提升胜率/控频)===== + # 是否仅在 marketRegime=trending 时才自动交易;否则只生成推荐 + 'AUTO_TRADE_ONLY_TRENDING': True, + # 是否允许 4H 趋势为 neutral 时自动交易;快速验证模式:允许中性趋势以增加交易机会 + 'AUTO_TRADE_ALLOW_4H_NEUTRAL': False, + + # ===== 趋势入场过滤(防止追在半山腰)===== + # 是否启用基于趋势状态的入场过滤: + # - 扫描阶段会为每个强信号交易对写入一份“趋势状态”到缓存(Redis) + # - 开仓时根据当前价格相对于信号价格的偏移,过滤“过晚追价”的入场 + 'USE_TREND_ENTRY_FILTER': True, + # 在信号方向上允许的最大累计趋势幅度(相对于信号价),超过则认为“时机太晚”,不再入场 + # 例如:0.08 表示价格沿趋势方向已经走了 8% 以上还没上车,则跳过本轮机会(快速验证模式:放宽阈值以增加交易机会) + 'MAX_TREND_MOVE_BEFORE_ENTRY': 0.04, # 2026-01-29优化:从0.05收紧到0.04,更严格避免追高杀跌 + # 趋势状态缓存的 TTL(秒),用于控制一轮趋势的“有效期” + 'TREND_STATE_TTL_SEC': 3600, + + # ===== 推荐系统优化(优先推荐“入场时机不算太晚”的趋势单)===== + # 是否在生成推荐时启用趋势入场时机过滤(仅对趋势市场的顺势推荐生效) + # - 会对比当前价与趋势信号价的偏离,如果已经沿趋势方向走得太远,则不再生成该推荐 + 'RECO_USE_TREND_ENTRY_FILTER': True, + # 推荐系统使用的最大允许趋势幅度(相对于趋势信号价),默认与自动交易相同或略微更严格 + 'RECO_MAX_TREND_MOVE_BEFORE_ENTRY': 0.04, + + # ===== 智能入场(方案C)===== + # 根治方案:默认关闭。关闭后回归“纯限价单模式”(不追价/不市价兜底/未成交撤单跳过) + 'SMART_ENTRY_ENABLED': True, # 开启智能入场,提高成交率 + 'SMART_ENTRY_STRONG_SIGNAL': 8, # 强信号阈值≥8(2026-01-29优化:与MIN_SIGNAL_STRENGTH保持一致) + 'ENTRY_SYMBOL_COOLDOWN_SEC': 1800, # 同一币种冷却30分钟(1800秒),快速验证模式:缩短冷却以增加交易频率 + + # ===== 同一交易对连续亏损过滤(避免连续亏损后继续交易)===== + 'SYMBOL_LOSS_COOLDOWN_ENABLED': True, # 是否启用同一交易对连续亏损后的冷却 + 'SYMBOL_MAX_CONSECUTIVE_LOSSES': 2, # 最大允许连续亏损次数(超过则禁止交易) + 'SYMBOL_LOSS_COOLDOWN_SEC': 3600, # 连续亏损后的冷却时间(秒),默认1小时 + 'ENTRY_TIMEOUT_SEC': 180, # 智能入场总预算(秒)(限价/追价逻辑内部使用) + 'ENTRY_STEP_WAIT_SEC': 15, # 每步等待成交时间(秒) + 'ENTRY_CHASE_MAX_STEPS': 4, # 最多追价步数(逐步减少 offset) + 'ENTRY_MARKET_FALLBACK_AFTER_SEC': 45, # 趋势强时:超过该秒数仍未成交 -> 评估是否市价兜底 + 'ENTRY_CONFIRM_TIMEOUT_SEC': 30, # 下单后最终确认成交的等待时间(秒) + 'ENTRY_MAX_DRIFT_PCT_TRENDING': 0.8, # 追价偏离放宽到0.8%(山寨币跳空大) + 'ENTRY_MAX_DRIFT_PCT_RANGING': 0.3, # 震荡/弱趋势时允许的最大追价偏离 + 'LIMIT_ORDER_OFFSET_PCT': 0.5, # 限价单偏移百分比(默认0.5%) + 'MIN_HOLD_TIME_SEC': 0, # 默认30分钟(1800秒),已取消 +} + def _get_trading_config(): """获取交易配置(支持动态重载,优先从Redis读取最新值)""" + config = DEFAULT_TRADING_CONFIG.copy() + if _config_manager: # 从Redis重新加载配置(轻量级,只从Redis读取,不查数据库) # 注意:如果Redis不可用或没有数据,reload_from_redis()会保持现有缓存,不会触发数据库加载 _config_manager.reload_from_redis() - return _config_manager.get_trading_config() - # 回退到默认配置 - return { - # ===== 用户风险旋钮(山寨币专属策略)===== - 'AUTO_TRADE_ENABLED': True, # 自动交易总开关 - 'MAX_OPEN_POSITIONS': 4, # 同时持仓数量上限(总仓位12% / 单笔1.5% = 最多4个) - 'MAX_DAILY_ENTRIES': 15, # 每日最多15笔(快速验证模式:提高上限以快速验证策略) + db_config = _config_manager.get_trading_config() + if db_config: + # 使用数据库配置覆盖默认配置 + config.update(db_config) + return config + + return config - 'MAX_POSITION_PERCENT': 0.20, # 单笔仓位上限20%(作为风控熔断,实际仓位由固定风险模型决定) - 'MAX_TOTAL_POSITION_PERCENT': 0.80, # 总仓位80%(避免满仓,留有余地) - 'MIN_POSITION_PERCENT': 0.01, # 最小仓位1% - 'MIN_MARGIN_USDT': 10.0, # 最小保证金10美元(提高门槛,过滤过小交易) - 'MIN_CHANGE_PERCENT': 0.5, # 最小价格变动0.5% - 'TOP_N_SYMBOLS': 30, # 扩大候选池到30个,增加机会 - 'SCAN_EXTRA_SYMBOLS_FOR_SUPPLEMENT': 20, # 智能补单候选增加 - 'MAX_SCAN_SYMBOLS': 500, # 扫描前500个 - 'EXCLUDE_MAJOR_COINS': True, # 排除主流币 - 'STOP_LOSS_PERCENT': 0.05, # 基础止损5%(配合ATR动态止损,作为保底) - 'TAKE_PROFIT_PERCENT': 0.80, # 第二目标止盈80%(追求大趋势收益) - 'TAKE_PROFIT_1_PERCENT': 0.30, # 第一目标止盈30%(确保3:1盈亏比) - 'MIN_RR_FOR_TP1': 1.5, # 第一目标止盈的最小盈亏比(相对于止损距离)(2026-02-12:1.5 改善盈亏比) - 'MIN_STOP_LOSS_PRICE_PCT': 0.025, # 最小止损价格变动2.5% - 'MIN_TAKE_PROFIT_PRICE_PCT': 0.02, # 最小止盈价格变动2% - 'USE_ATR_STOP_LOSS': True, # 使用ATR动态止损 - 'ATR_STOP_LOSS_MULTIPLIER': 3.0, # ATR止损倍数3.0(2026-02-12:减少噪音止损,配合止盈拉远) - 'ATR_TAKE_PROFIT_MULTIPLIER': 6.0, # ATR止盈倍数6.0(追求更高盈亏比) - 'RISK_REWARD_RATIO': 3.0, # 盈亏比3:1 - 'ATR_PERIOD': 14, # ATR计算周期14 - 'USE_DYNAMIC_ATR_MULTIPLIER': False, # 不使用动态ATR - 'ATR_MULTIPLIER_MIN': 1.5, # 动态ATR倍数最小值 - 'ATR_MULTIPLIER_MAX': 2.5, # 动态ATR倍数最大值 - 'SCAN_INTERVAL': 900, # 扫描间隔15分钟(900秒),快速验证模式:提高扫描频率以增加交易机会 - 'KLINE_INTERVAL': '1h', - 'PRIMARY_INTERVAL': '4h', # 主周期4小时,过滤噪音 - 'CONFIRM_INTERVAL': '1d', # 确认周期日线,看大趋势 - 'ENTRY_INTERVAL': '1h', # 入场周期1小时,避免太小的时间框架 - # 入场短周期(用于快速方向确认,例如15m),不要太小以免噪音太大 - 'ENTRY_SHORT_INTERVAL': '15m', - # 是否开启“短周期方向过滤”,避免在15m明显上涨时做空、明显下跌时做多(快速验证模式:关闭以增加交易机会) - 'ENTRY_SHORT_TREND_FILTER_ENABLED': True, - # 短周期方向过滤使用的最小趋势幅度(例如0.003=0.3%),变化太小视为震荡不过滤 - 'ENTRY_SHORT_TREND_MIN_PCT': 0.003, - # 检查最近多少根短周期K线来评估方向(例如3根15m约等于45分钟) - 'ENTRY_SHORT_CONFIRM_CANDLES': 3, - 'MIN_VOLUME_24H': 30000000, # 24小时成交额≥3000万美元,过滤垃圾币 - 'MIN_VOLUME_24H_STRICT': 50000000, # 严格过滤≥5000万美元 - 'MIN_VOLATILITY': 0.03, # 最小波动率3%,过滤死币 - 'MIN_SIGNAL_STRENGTH': 8, # 信号强度≥8(2026-01-29优化:从7提高到8,减少低质量信号,提升胜率) - - # ===== 动态过滤优化 ===== - 'BETA_FILTER_ENABLED': True, # 大盘共振过滤:BTC/ETH下跌时屏蔽多单 - 'BETA_FILTER_THRESHOLD': -0.005, # -0.5%(2026-01-27优化:更敏感地过滤大盘风险,15分钟内跌幅超过0.5%即屏蔽多单) - # ===== RSI / 24h 涨跌幅过滤(避免追高杀跌)===== - 'MAX_RSI_FOR_LONG': 65, # 做多时 RSI 超过此值则不开多(2026-02-12:65 避免追高) - 'MAX_CHANGE_PERCENT_FOR_LONG': 25, # 做多时 24h 涨跌幅超过此值则不开多(避免追大涨) - 'MIN_RSI_FOR_SHORT': 30, # 做空时 RSI 低于此值则不做空(避免深超卖反弹) - 'MAX_CHANGE_PERCENT_FOR_SHORT': 10, # 做空时 24h 涨跌幅超过此值则不做空(24h 仍大涨时不做空) - - # ===== RSI 极限反转策略(抄底/逃顶)===== - 'RSI_EXTREME_REVERSE_ENABLED': True, # 开启RSI极限反转:超买反空,超卖反多 - 'RSI_EXTREME_REVERSE_ONLY_NEUTRAL_4H': False, # 允许在有趋势时反向操作(例如:下跌趋势中RSI超卖 -> 抄底) - - 'ATR_SPIKE_THRESHOLD': 2.0, # ATR异常激增阈值(当前ATR / 平均ATR) - 'SIGNAL_STRENGTH_POSITION_MULTIPLIER': {7: 0.8, 8: 0.9, 9: 1.0, 10: 1.0}, # 信号强度分级:7分80%仓位,8分90%,9-10分100%(快速验证模式:支持7-8分信号) - - # ===== 仓位管理优化(山寨币专属)===== - 'USE_FIXED_RISK_SIZING': True, # 固定每笔风险,避免亏损扩大 - 'FIXED_RISK_PERCENT': 0.01, # 每笔最多亏总资金1%(山寨币风险高) - 'MAX_LEVERAGE_SMALL_CAP': 8, # 高波动/小众币最大杠杆(与之前盈利阶段一致) - 'MIN_LEVERAGE': 8, # 动态杠杆下限,避免被压到 2–4x 导致单笔盈利过少 - 'ATR_LEVERAGE_REDUCTION_THRESHOLD': 0.05, # ATR超过5%时降低杠杆 - 'LEVERAGE': 8, # 基础杠杆(与之前盈利阶段一致) - 'USE_DYNAMIC_LEVERAGE': True, # 开启动态杠杆(基于止损宽度自动调整,但不低于 MIN_LEVERAGE) - 'MAX_SINGLE_TRADE_LOSS_PERCENT': 20.0, # 单笔交易最大本金亏损率(20%),用于限制杠杆 - 'MAX_LEVERAGE': 20, # 最大杠杆 - # 移动止损:必须开启!山寨币利润要保护 - 'USE_TRAILING_STOP': True, - 'TRAILING_STOP_ACTIVATION': 0.10, # 盈利10%后激活(更早锁定利润) - 'TRAILING_STOP_PROTECT': 0.02, # 保护2%利润(紧跟趋势) - - # 最小持仓时间锁:立即取消!山寨币30分钟可能暴涨暴跌50% - 'MIN_HOLD_TIME_SEC': 0, # 取消持仓时间锁 - 'POSITION_SYNC_INTERVAL': 60, # 持仓状态同步间隔60秒 - - # ===== 自动交易过滤(用于提升胜率/控频)===== - # 是否仅在 marketRegime=trending 时才自动交易;否则只生成推荐 - 'AUTO_TRADE_ONLY_TRENDING': True, - # 是否允许 4H 趋势为 neutral 时自动交易;快速验证模式:允许中性趋势以增加交易机会 - 'AUTO_TRADE_ALLOW_4H_NEUTRAL': False, - - # ===== 趋势入场过滤(防止追在半山腰)===== - # 是否启用基于趋势状态的入场过滤: - # - 扫描阶段会为每个强信号交易对写入一份“趋势状态”到缓存(Redis) - # - 开仓时根据当前价格相对于信号价格的偏移,过滤“过晚追价”的入场 - 'USE_TREND_ENTRY_FILTER': True, - # 在信号方向上允许的最大累计趋势幅度(相对于信号价),超过则认为“时机太晚”,不再入场 - # 例如:0.08 表示价格沿趋势方向已经走了 8% 以上还没上车,则跳过本轮机会(快速验证模式:放宽阈值以增加交易机会) - 'MAX_TREND_MOVE_BEFORE_ENTRY': 0.04, # 2026-01-29优化:从0.05收紧到0.04,更严格避免追高杀跌 - # 趋势状态缓存的 TTL(秒),用于控制一轮趋势的“有效期” - 'TREND_STATE_TTL_SEC': 3600, - - # ===== 推荐系统优化(优先推荐“入场时机不算太晚”的趋势单)===== - # 是否在生成推荐时启用趋势入场时机过滤(仅对趋势市场的顺势推荐生效) - # - 会对比当前价与趋势信号价的偏离,如果已经沿趋势方向走得太远,则不再生成该推荐 - 'RECO_USE_TREND_ENTRY_FILTER': True, - # 推荐系统使用的最大允许趋势幅度(相对于趋势信号价),默认与自动交易相同或略微更严格 - 'RECO_MAX_TREND_MOVE_BEFORE_ENTRY': 0.04, - - # ===== 智能入场(方案C)===== - # 根治方案:默认关闭。关闭后回归“纯限价单模式”(不追价/不市价兜底/未成交撤单跳过) - 'SMART_ENTRY_ENABLED': True, # 开启智能入场,提高成交率 - 'SMART_ENTRY_STRONG_SIGNAL': 8, # 强信号阈值≥8(2026-01-29优化:与MIN_SIGNAL_STRENGTH保持一致) - 'ENTRY_SYMBOL_COOLDOWN_SEC': 1800, # 同一币种冷却30分钟(1800秒),快速验证模式:缩短冷却以增加交易频率 - - # ===== 同一交易对连续亏损过滤(避免连续亏损后继续交易)===== - 'SYMBOL_LOSS_COOLDOWN_ENABLED': True, # 是否启用同一交易对连续亏损后的冷却 - 'SYMBOL_MAX_CONSECUTIVE_LOSSES': 2, # 最大允许连续亏损次数(超过则禁止交易) - 'SYMBOL_LOSS_COOLDOWN_SEC': 3600, # 连续亏损后的冷却时间(秒),默认1小时 - 'ENTRY_TIMEOUT_SEC': 180, # 智能入场总预算(秒)(限价/追价逻辑内部使用) - 'ENTRY_STEP_WAIT_SEC': 15, # 每步等待成交时间(秒) - 'ENTRY_CHASE_MAX_STEPS': 4, # 最多追价步数(逐步减少 offset) - 'ENTRY_MARKET_FALLBACK_AFTER_SEC': 45, # 趋势强时:超过该秒数仍未成交 -> 评估是否市价兜底 - 'ENTRY_CONFIRM_TIMEOUT_SEC': 30, # 下单后最终确认成交的等待时间(秒) - 'ENTRY_MAX_DRIFT_PCT_TRENDING': 0.8, # 追价偏离放宽到0.8%(山寨币跳空大) - 'ENTRY_MAX_DRIFT_PCT_RANGING': 0.3, # 震荡/弱趋势时允许的最大追价偏离 - } # 币安API配置(优先从数据库,回退到环境变量和默认值) # 注意:在模块加载时,配置管理器可能还未初始化完成,所以先使用默认值 @@ -324,37 +336,7 @@ USE_TESTNET: bool = _get_config_value('USE_TESTNET', False) if _get_config_value TRADING_CONFIG = _get_trading_config() # 确保包含所有必要的默认值 -defaults = { - # 用户风险旋钮(即使DB里没配置,也能用) - 'AUTO_TRADE_ENABLED': True, - 'MAX_OPEN_POSITIONS': 3, - 'MAX_DAILY_ENTRIES': 8, - - 'SCAN_INTERVAL': 1800, - 'KLINE_INTERVAL': '1h', - 'PRIMARY_INTERVAL': '1h', - 'CONFIRM_INTERVAL': '4h', - 'ENTRY_INTERVAL': '15m', - 'LIMIT_ORDER_OFFSET_PCT': 0.5, # 限价单偏移百分比(默认0.5%) - # 智能入场默认值(即使DB里没配置,也能用) - 'SMART_ENTRY_ENABLED': False, - 'ENTRY_SYMBOL_COOLDOWN_SEC': 120, - 'ENTRY_TIMEOUT_SEC': 180, - 'ENTRY_STEP_WAIT_SEC': 15, - 'ENTRY_CHASE_MAX_STEPS': 4, - 'ENTRY_MARKET_FALLBACK_AFTER_SEC': 45, - 'ENTRY_CONFIRM_TIMEOUT_SEC': 30, - 'ENTRY_MAX_DRIFT_PCT_TRENDING': 0.6, - 'ENTRY_MAX_DRIFT_PCT_RANGING': 0.3, - - # 自动交易过滤默认值 - 'AUTO_TRADE_ONLY_TRENDING': True, - 'AUTO_TRADE_ALLOW_4H_NEUTRAL': False, - - # 最小持仓时间锁(强制波段持仓纪律,避免分钟级平仓) - 'MIN_HOLD_TIME_SEC': 1800, # 默认30分钟(1800秒) -} -for key, value in defaults.items(): +for key, value in DEFAULT_TRADING_CONFIG.items(): if key not in TRADING_CONFIG: TRADING_CONFIG[key] = value @@ -400,7 +382,7 @@ def reload_config(): REDIS_PASSWORD = _get_config_value('REDIS_PASSWORD', os.getenv('REDIS_PASSWORD', REDIS_PASSWORD)) REDIS_SELECT = _get_config_value('REDIS_SELECT', os.getenv('REDIS_SELECT', REDIS_SELECT)) # 确保默认值 - for key, value in defaults.items(): + for key, value in DEFAULT_TRADING_CONFIG.items(): if key not in TRADING_CONFIG: TRADING_CONFIG[key] = value diff --git a/trading_system/risk_manager.py b/trading_system/risk_manager.py index b57cc39..b863765 100644 --- a/trading_system/risk_manager.py +++ b/trading_system/risk_manager.py @@ -529,6 +529,23 @@ class RiskManager: # 固定风险金额 risk_amount = total_balance * fixed_risk_percent + + # ⚠️ 优化:将信号强度乘数应用于固定风险金额 + signal_multiplier = 1.0 + if signal_strength is not None: + # 获取配置,如果配置为None(可能从DB读取时为空),则使用默认值 + signal_multipliers = config.TRADING_CONFIG.get('SIGNAL_STRENGTH_POSITION_MULTIPLIER') + if signal_multipliers is None: + signal_multipliers = {7: 0.8, 8: 1.0, 9: 1.2, 10: 1.5} + + # 确保是字典类型 + if isinstance(signal_multipliers, dict): + signal_multiplier = signal_multipliers.get(signal_strength, 1.0) + if signal_multiplier != 1.0: + logger.info(f" ⚡️ 应用信号强度乘数: {signal_multiplier} (信号强度: {signal_strength})") + risk_amount = risk_amount * signal_multiplier + else: + logger.warning(f" ⚠️ SIGNAL_STRENGTH_POSITION_MULTIPLIER 配置格式错误: {type(signal_multipliers)}") # 根据止损距离反算仓位 # 风险金额 = (入场价 - 止损价) × 数量 diff --git a/update_risk_config_db.py b/update_risk_config_db.py new file mode 100644 index 0000000..587ed3d --- /dev/null +++ b/update_risk_config_db.py @@ -0,0 +1,77 @@ + +import os +import sys +import logging +from sqlalchemy import create_engine, text + +# Set up logging +logging.basicConfig(level=logging.INFO) +logger = logging.getLogger(__name__) + +# Database connection +DB_USER = os.getenv('DB_USER', 'root') +DB_PASSWORD = os.getenv('DB_PASSWORD', '12345678') +DB_HOST = os.getenv('DB_HOST', 'localhost') +DB_PORT = os.getenv('DB_PORT', '3306') +DB_NAME = 'auto_trade_sys_new' + +DATABASE_URL = f"mysql+pymysql://{DB_USER}:{DB_PASSWORD}@{DB_HOST}:{DB_PORT}/{DB_NAME}" + +def update_config(): + try: + engine = create_engine(DATABASE_URL) + with engine.connect() as conn: + # 1. Update MIN_STOP_LOSS_PRICE_PCT (Crucial Fix) + # Default was 0.025 (2.5%), which forces 25% margin loss @ 10x. + # Changing to 0.005 (0.5%), which allows 5% margin loss @ 10x. + conn.execute(text(""" + INSERT INTO trading_config (account_id, config_key, config_value, config_type, category, description, updated_at) + VALUES (1, 'MIN_STOP_LOSS_PRICE_PCT', '0.005', 'number', 'risk', '最小止损价格变动:0.5%(允许更紧的止损)', NOW()) + ON DUPLICATE KEY UPDATE config_value='0.005', updated_at=NOW(); + """)) + logger.info("Updated MIN_STOP_LOSS_PRICE_PCT to 0.005") + + # 2. Update MIN_TAKE_PROFIT_PRICE_PCT + # Default was 0.02 (2%), forcing 20% margin gain @ 10x. + # Changing to 0.006 (0.6%), allowing smaller TPs if needed. + conn.execute(text(""" + INSERT INTO trading_config (account_id, config_key, config_value, config_type, category, description, updated_at) + VALUES (1, 'MIN_TAKE_PROFIT_PRICE_PCT', '0.006', 'number', 'risk', '最小止盈价格变动:0.6%(允许更紧的止盈)', NOW()) + ON DUPLICATE KEY UPDATE config_value='0.006', updated_at=NOW(); + """)) + logger.info("Updated MIN_TAKE_PROFIT_PRICE_PCT to 0.006") + + # 3. Ensure STOP_LOSS_PERCENT is 0.1 (10% Margin) + conn.execute(text(""" + INSERT INTO trading_config (account_id, config_key, config_value, config_type, category, description, updated_at) + VALUES (1, 'STOP_LOSS_PERCENT', '0.1', 'number', 'risk', '止损:10%(相对于保证金)', NOW()) + ON DUPLICATE KEY UPDATE config_value='0.1', updated_at=NOW(); + """)) + logger.info("Ensured STOP_LOSS_PERCENT is 0.1") + + # 4. Ensure TAKE_PROFIT_PERCENT is 0.2 (20% Margin) + conn.execute(text(""" + INSERT INTO trading_config (account_id, config_key, config_value, config_type, category, description, updated_at) + VALUES (1, 'TAKE_PROFIT_PERCENT', '0.2', 'number', 'risk', '止盈:20%(相对于保证金)', NOW()) + ON DUPLICATE KEY UPDATE config_value='0.2', updated_at=NOW(); + """)) + logger.info("Ensured TAKE_PROFIT_PERCENT is 0.2") + + # 5. Ensure ATR_STOP_LOSS_MULTIPLIER is reasonable (2.0) + conn.execute(text(""" + INSERT INTO trading_config (account_id, config_key, config_value, config_type, category, description, updated_at) + VALUES (1, 'ATR_STOP_LOSS_MULTIPLIER', '2.0', 'number', 'risk', 'ATR止损倍数2.0', NOW()) + ON DUPLICATE KEY UPDATE config_value='2.0', updated_at=NOW(); + """)) + logger.info("Ensured ATR_STOP_LOSS_MULTIPLIER is 2.0") + + conn.commit() + logger.info("Configuration update complete.") + + except Exception as e: + logger.error(f"Error updating config: {e}") + import traceback + traceback.print_exc() + +if __name__ == "__main__": + update_config()