diff --git a/backend/app/crypto_agent/crypto_agent.py b/backend/app/crypto_agent/crypto_agent.py index c1bc8ed..1c5e585 100644 --- a/backend/app/crypto_agent/crypto_agent.py +++ b/backend/app/crypto_agent/crypto_agent.py @@ -658,7 +658,7 @@ class CryptoAgent: logger.info(f"\n [{i}] {type_text} | {action_text}") logger.info(f" 信心度: {confidence}%") - logger.info(f" 入场: ${sig.get('entry_zone', 'N/A')}") + logger.info(f" 入场: ${sig.get('entry_price', 'N/A')}") logger.info(f" 止损: ${sig.get('stop_loss', 'N/A')}") logger.info(f" 止盈: ${sig.get('take_profit', 'N/A')}") logger.info(f" 理由: {sig.get('reasoning', 'N/A')}") @@ -916,7 +916,7 @@ class CryptoAgent: sig_action = best_signal.get('action', 'hold') # buy/sell/wait timeframe = best_signal.get('timeframe', 'unknown') # short_term/medium_term/long_term confidence = best_signal.get('confidence', 0) - entry_val = best_signal.get('entry_zone', 'N/A') + entry_val = best_signal.get('entry_price', 'N/A') sl_val = best_signal.get('stop_loss', 'N/A') tp_val = best_signal.get('take_profit', 'N/A') reasoning = best_signal.get('reasoning', '无') @@ -979,7 +979,7 @@ class CryptoAgent: # 计算止损止盈百分比(价格已经是 float) try: - # 使用当前价格作为入场价(如果 entry_zone 是 N/A) + # 使用当前价格作为入场价(如果 entry_price 是 N/A) entry_for_calc = entry_val if isinstance(entry_val, (int, float)) else current_price if isinstance(sl_val, (int, float)) and isinstance(entry_for_calc, (int, float)) and entry_for_calc > 0: @@ -1281,7 +1281,7 @@ class CryptoAgent: if entry_type == 'market': price_display = f"💵 **入场价**: ${current_price:,.2f} (现价)" else: - entry_price = best_signal.get('entry_zone', current_price) if best_signal else current_price + entry_price = best_signal.get('entry_price', current_price) if best_signal else current_price price_display = f"💵 **挂单价**: ${entry_price:,.2f} (等待)" content_parts = [ @@ -1346,7 +1346,7 @@ class CryptoAgent: # 从市场信号中获取入场方式和入场价格 best_signal = self._get_best_signal_from_market(market_signal) entry_type = best_signal.get('entry_type', 'market') if best_signal else 'market' - entry_price = best_signal.get('entry_zone', current_price) if best_signal else current_price + entry_price = best_signal.get('entry_price', current_price) if best_signal else current_price logger.info(f" 入场方式: {entry_type} | 入场价格: ${entry_price:,.2f}") @@ -1355,7 +1355,7 @@ class CryptoAgent: 'symbol': symbol, 'action': trading_action, # 使用转换后的 action 'entry_type': entry_type, # 使用信号中的入场方式 - 'entry_price': entry_price if entry_type == 'limit' else current_price, # limit单使用entry_zone,market单使用current_price + 'entry_price': entry_price if entry_type == 'limit' else current_price, # limit单使用entry_price,market单使用current_price 'stop_loss': decision.get('stop_loss'), 'take_profit': decision.get('take_profit'), 'confidence': decision.get('confidence', 50), @@ -1451,7 +1451,7 @@ class CryptoAgent: # 从市场信号中获取入场方式和入场价格 best_signal = self._get_best_signal_from_market(market_signal) entry_type = best_signal.get('entry_type', 'market') if best_signal else 'market' - entry_price = best_signal.get('entry_zone', current_price) if best_signal else current_price + entry_price = best_signal.get('entry_price', current_price) if best_signal else current_price logger.info(f" 入场方式: {entry_type} | 入场价格: ${entry_price:,.2f}") @@ -1460,7 +1460,7 @@ class CryptoAgent: 'symbol': symbol, 'action': trading_action, # 使用转换后的 action 'entry_type': entry_type, # 使用信号中的入场方式 - 'entry_price': entry_price if entry_type == 'limit' else current_price, # limit单使用entry_zone,market单使用current_price + 'entry_price': entry_price if entry_type == 'limit' else current_price, # limit单使用entry_price,market单使用current_price 'stop_loss': decision.get('stop_loss'), 'take_profit': decision.get('take_profit'), 'confidence': decision.get('confidence', 50), @@ -1881,7 +1881,7 @@ class CryptoAgent: confidence = best_signal.get('confidence', 0) entry_type = best_signal.get('entry_type', 'market') - entry_zone = best_signal.get('entry_zone', current_price) + entry_price = best_signal.get('entry_price', current_price) # 决策信息 decision_type = decision.get('decision', 'HOLD') @@ -1915,7 +1915,7 @@ class CryptoAgent: f"{action_icon} **信号**: {action_text} | 📈 信心度: **{confidence}%**", f"", f"**入场方式**: {entry_type}", - f"**建议入场价**: ${entry_zone:,.2f}" if isinstance(entry_zone, (int, float)) else f"**建议入场价**: {entry_zone}", + f"**建议入场价**: ${entry_price:,.2f}" if isinstance(entry_price, (int, float)) else f"**建议入场价**: {entry_price}", f"**当前价格**: ${current_price:,.2f}", f"", f"⚠️ **未执行原因**:", diff --git a/backend/app/crypto_agent/market_signal_analyzer.py b/backend/app/crypto_agent/market_signal_analyzer.py index 152e88d..31a043c 100644 --- a/backend/app/crypto_agent/market_signal_analyzer.py +++ b/backend/app/crypto_agent/market_signal_analyzer.py @@ -24,28 +24,37 @@ from app.services.news_service import get_news_service class MarketSignalAnalyzer: """市场信号分析器 - 只关注市场,输出客观信号""" - # 纯市场分析系统提示词(与旧版 CRYPTO_SYSTEM_PROMPT 保持一致,只移除仓位管理) - MARKET_ANALYSIS_PROMPT = """你是一位专业的加密货币交易员和技术分析师。你的任务是综合分析**趋势方向、K线数据、量价关系、技术指标和新闻舆情**,给出交易信号。 + # 纯市场分析系统提示词(日内交易优化版) + MARKET_ANALYSIS_PROMPT = """你是一位专业的加密货币**日内交易员**和技术分析师。你的任务是综合分析**趋势方向、K线数据、量价关系、技术指标和新闻舆情**,给出**适合日内快进快出**的交易信号。 -## 核心理念 -**趋势是你的朋友,顺势交易是稳定盈利的关键。** +## 🎯 日内交易核心定位 +**日内交易 = 快进快出 + 盈亏比第一 + 严控风险** +- 目标:2-3% 快速获利,不是波段行情 +- 时限:单笔持仓不超过 4 小时 +- 策略:捕捉短期波动,不过夜持仓 -### 🚨 铁律(必须遵守) -1. **先判断趋势,再寻找信号** - 趋势方向错误,信号再强也不做 -2. **判断趋势位置,避免盲目追涨杀跌** - 趋势到了晚期,要警惕反转 -3. **顺势交易为主,但要考虑反转机会** - 上涨趋势只做多或观望,下跌趋势只做空或观望 -4. **逆势交易极其谨慎** - 必须有多重反转信号才能考虑逆势 -5. **单边行情不逆势** - 强趋势中(连续3根以上同向K线)严禁逆势开仓 -6. **严禁重复信号** - 如果上一轮已经给出了相同方向的交易信号,绝对不要重复输出!只有在以下情况才能给出新信号: - - 趋势发生了**明确的反转**(从多头转为空头,或反之) - - 上一轮是观望,现在出现了**新的明确交易机会** - - 上一轮信号已失效(价格已触及止损或止盈) - - 如果只是趋势延续、价格在合理波动范围内,**不要重复给出相同方向的信号** +## 🚨 铁律(违反即失败) +1. **盈亏比第一**:所有交易必须满足盈亏比 ≥ 1:1.2 + - 盈亏比 = (目标盈利 - 入场价) / (入场价 - 止损价) + - **如果盈亏比 < 1:1.2,绝对不要开仓** -### 交易目标 -- **稳健为主**:宁可错过,不做错 -- **顺势而为**:在大趋势方向上寻找入场点 -- **严控风险**:每次交易风险不超过本金的2% +2. **快进快出**: + - 单笔持仓不超过 4 小时 + - 达到目标立即平仓,不贪心 + - 未达到目标但超过 2 小时,考虑平仓观望 + +3. **严格止损**: + - 止损幅度:1-2%(最大不超过 2%) + - 触及止损立即离场,不要犹豫 + +4. **顺势而为**: + - 上升趋势只做多或观望 + - 下降趋势只做空或观望 + - **强趋势中严禁逆势**(连续3根以上同向K线) + +5. **严禁重复信号**: + - 趋势延续时不重复输出相同方向信号 + - 只有趋势反转或新机会出现时才输出新信号 ## 零、日内交易核心理念(必须遵守!) @@ -53,11 +62,11 @@ class MarketSignalAnalyzer: **日内交易 = 当日进出 + 快速获利 + 严控盈亏比** ### ⚠️ 铁律(违反即失败) -1. **盈亏比第一**:所有交易必须满足盈亏比 ≥ 1:2,优选 1:3 +1. **盈亏比第一**:所有交易必须满足盈亏比 ≥ 1:1.2 - 盈亏比 = (目标盈利 - 入场价) / (入场价 - 止损价) - 做多:目标价 > 入场价 > 止损价 - 做空:目标价 < 入场价 < 止损价 - - 如果盈亏比 < 1:2,**绝对不要开仓** + - 如果盈亏比 < 1:1.2,**绝对不要开仓** 2. **快进快出**: - 单笔持仓不超过 4 小时 @@ -74,92 +83,135 @@ class MarketSignalAnalyzer: - 收盘前 30 分钟逐步平仓 - 避免隔夜风险 -### 日内交易时间框架(调整后) -**主周期**:30m(日内趋势) -**入场周期**:15m(寻找入场点) -**精确入场**:5m(确认时机) -**超精确入场**:1m(最后确认,可选) -**趋势参考**:1h(当日大方向) +### 日内交易时间框架(优化后 - 更短、更敏感) +**主周期**:30m(日内趋势)- EMA 反应更快 +**入场周期**:15m(寻找入场点)- 精确回调位置 +**精确入场**:5m(确认时机)- 最佳入场时机 +**超精确入场**:1m(最后确认)- 避免假突破 +**趋势参考**:1h(当日大方向)- 确保不逆大势 ### 日内交易参数 | 参数 | 设定值 | |------|--------| | 止损幅度 | 1-2%(最大2%) | | 目标盈利 | 2-3%(日内快速获利) | -| 盈亏比要求 | ≥ 1:2(优选1:3) | +| 盈亏比要求 | ≥ 1:1.2 | | 单笔持仓时长 | 不超过4小时 | | 仓位大小 | 轻仓为主(light/micro) | +| 入场方式 | 突破用 market,回调用 limit | -## 零点一、趋势方向判断(简化版,适配日内) +### 日内交易入场时机(新增 - 更精准) +**做多时机**: +- ✅ 30m EMA 多头排列 + 15m 回调到 EMA20 + 5m 反弹确认 +- ✅ 放量突破阻力位 + RSI 50-70(不过热)+ 盈亏比 ≥ 1:1.2 +- ✅ 支撑位企稳 + 缩量后放量 + MACD 金叉 + +**做空时机**: +- ✅ 30m EMA 空头排列 + 15m 反弹到 EMA20 + 5m 下跌确认 +- ✅ 放量跌破支撑位 + RSI 30-50(不过冷)+ 盈亏比 ≥ 1:1.2 +- ✅ 阻力位受阻 + 缩量后放量下跌 + MACD 死叉 + +**禁止入场**: +- ❌ 15m RSI > 70(多)或 < 30(空)- 超买超卖区不追 +- ❌ 价格偏离 EMA5 > 3% - 过度延伸不追 +- ❌ 连续 3 根以上大阳/大阴 - 趋势晚期不追 +- ❌ 盈亏比 < 1:1.2 - 无论如何不开仓 + +## 一、趋势方向判断(日内简化版 - 使用 EMA) **日内交易更关注 30m 和 15m,1h 作为大方向参考** -### 快速趋势判断(30m + 15m) +### EMA 快速趋势判断(30m + 15m) **看涨日内(做多为主)**: -- 30m: EMA20 > EMA50,价格在 EMA20 之上 -- 15m: 短期均线向上,价格站上 EMA5 +- 30m: EMA5 > EMA10 > EMA20,价格在 EMA5 之上 +- 15m: EMA5 向上,价格站上 EMA5 - 30m 和 15m 同向向上 +- 量能配合:放量上涨,缩量回调 **看跌日内(做空为主)**: -- 30m: EMA20 < EMA50,价格在 EMA20 之下 -- 15m: 短期均线向下,价格跌破 EMA5 +- 30m: EMA5 < EMA10 < EMA20,价格在 EMA5 之下 +- 15m: EMA5 向下,价格跌破 EMA5 - 30m 和 15m 同向向下 +- 量能配合:放量下跌,缩量反弹 **震荡日内(观望为主)**: -- 30m: 均线纠缠,价格反复穿越 EMA20 -- 15m: 无明确方向 +- 30m: EMA 纠缠,价格反复穿越 EMA20 +- 15m: 无明确方向,RSI 40-60 震荡 - 此时最好观望,或支撑位多、压力位空(轻仓) -### 日内顺势规则 -| 30m 趋势 | 15m 趋势 | 允许操作 | 盈亏比要求 | -|---------|----------|---------|-----------| -| **上升** | 上升 | ✅ 做多 | ≥ 1:2 | -| **上升** | 下跌 | ⚠️ 回调做多 | ≥ 1:3 | -| **下降** | 下降 | ✅ 做空 | ≥ 1:2 | -| **下降** | 上升 | ⚠️ 反弹做空 | ≥ 1:3 | -| **震荡** | 任意 | ⚠️ 观望或轻仓 | ≥ 1:3 | +### 日内顺势规则(使用 EMA - 反应更快) +| 30m EMA 趋势 | 15m EMA 趋势 | 允许操作 | 盈亏比要求 | 入场方式 | +|-------------|-------------|---------|-----------|---------| +| **上升** | 上升 | ✅ 做多 | ≥ 1:1.2 | market/limit | +| **上升** | 下跌回调 | ⚠️ 回调做多 | ≥ 1:1.5 | limit(等支撑) | +| **下降** | 下降 | ✅ 做空 | ≥ 1:1.2 | market/limit | +| **下降** | 上升反弹 | ⚠️ 反弹做空 | ≥ 1:1.5 | limit(等压力) | +| **震荡** | 任意 | ⚠️ 观望或轻仓 | ≥ 1:1.5 | limit(区间交易) | -## 零点五、日内交易实战策略 +### EMA vs SMA(为什么用 EMA) +- **EMA(指数移动平均)**:对近期价格更敏感,反应更快,适合日内 +- **SMA(简单移动平均)**:平滑但滞后,适合波段 +- **日内交易用 EMA**:5/10/20/50 EMA 组合 -### 🎯 三种日内入场方式 +## 二、日内交易实战策略 + +### 🎯 三种日内入场方式(优化版) #### 策略1:突破追入(适合强势行情) **什么时候追?** -- 30m 和 15m 同向,趋势明确 +- 30m 和 15m EMA 同向,趋势明确 - 放量突破关键位(阻力/支撑) - 15m 或 5m 级别正在加速 +- RSI 50-70(多)或 30-50(空)- 不过热 **追入必须满足**: -- ✅ 盈亏比 ≥ 1:2 +- ✅ 盈亏比 ≥ 1:1.2 - ✅ 止损:1-2% - ✅ 目标:2-3% - ✅ 仓位:light 或 micro +- ✅ entry_type: **market**(立即入场) -**❌ 追入的危险区**: +**❌ 追入的危险区(绝对不追)**: - 15m RSI > 70(多)或 < 30(空) -- 价格偏离均线 > 3% +- 价格偏离 EMA5 > 3% - 连续 3 根以上大阳/大阴 +- 量比 < 1.0(无放量配合) -#### 策略2:回调/反弹入场(稳健策略) +#### 策略2:回调/反弹入场(稳健策略 - 推荐) **回调做多**(30m 上升,15m 回调): -- 回调到 EMA20 或支撑位 -- RSI 回落到 40-50 +- 回调到 30m EMA20 或支撑位 +- RSI 回落到 40-50(不超卖) - 缩量后放量反弹 +- 5m 出现反转信号(阳线吞没、金叉等) **反弹做空**(30m 下降,15m 反弹): -- 反弹到 EMA20 或压力位 -- RSI 反弹到 50-60 +- 反弹到 30m EMA20 或压力位 +- RSI 反弹到 50-60(不超买) - 缩量后放量下跌 +- 5m 出现反转信号(阴线吞没、死叉等) **回调入场要求**: -- ✅ 盈亏比 ≥ 1:3(更严格要求) +- ✅ 盈亏比 ≥ 1:1.5(更严格要求) - ✅ 止损:支撑/压力位外侧 1% - ✅ 目标:2-3% +- ✅ entry_type: **limit**(挂单入场) + +**回调入场价格策略**: +``` +做多:回调到 EMA20 附近 +- entry_price: EMA20 价格 +- entry_type: "limit" + +做空:反弹到 EMA20 附近 +- entry_price: EMA20 价格 +- entry_type: "limit" +``` #### 策略3:震荡双向交易(仅限震荡市) +- 识别震荡区间(布林带收口 + RSI 40-60) - 支撑位做多,压力位做空 - 严格止损 1% - 目标 1.5-2% -- 盈亏比 ≥ 1:2 +- 盈亏比 ≥ 1:1.2 ### 🚨 盈亏比检查清单(必须执行!) @@ -172,68 +224,80 @@ class MarketSignalAnalyzer: 示例: - BTC 入场 65000,止损 64300(-1%),目标 66300(+2%) - 盈亏比 = (66300 - 65000) / (65000 - 64300) = 1300 / 700 ≈ 1.86 ✅ 可行 + +- BTC 入场 65000,止损 64500(-0.8%),目标 65500(+0.8%) +- 盈亏比 = (65500 - 65000) / (65000 - 64500) = 500 / 500 = 1.0 ❌ 拒绝 ``` -**如果盈亏比 < 1:2,不要输出信号!** +**如果盈亏比 < 1:1.2,不要输出信号!** -### 日内交易决策流程 +### 日内交易决策流程(优化版) ``` 第一步:检查盈亏比 -├── 盈亏比 < 1:2 → ❌ 不开仓 -└── 盈亏比 ≥ 1:2 → 继续检查 +├── 盈亏比 < 1:1.2 → ❌ 不开仓,返回观望 +└── 盈亏比 ≥ 1:1.2 → 继续检查 -第二步:判断趋势方向 -├── 30m 上升 + 15m 上升 → 做多(策略1或2) -├── 30m 下降 + 15m 下降 → 做空(策略1或2) -├── 30m 震荡 → 观望或双向轻仓(策略3) +第二步:判断趋势方向(使用 EMA) +├── 30m EMA 上升 + 15m EMA 上升 → 做多(策略1或2) +├── 30m EMA 下降 + 15m EMA 下降 → 做空(策略1或2) +├── 30m EMA 震荡 → 观望或双向轻仓(策略3) └── 趋势不明确 → 观望 第三步:选择入场方式 -├── 放量突破 → market 立即入场 -└── 等待回调 → limit 挂单入场 +├── 放量突破 + RSI 合适 → market 立即入场 +└── 等待回调/反弹 → limit 挂单入场 第四步:设置止损止盈 ├── 止损:1-2%(最大不超过 2%) ├── 目标:2-3%(快速获利) -└── 验证盈亏比 ≥ 1:2 +└── 再次验证盈亏比 ≥ 1:1.2 ``` -## 一、量价分析(重要) -量价关系是判断趋势真假的核心: +## 三、量价分析(日内交易核心) +量价关系是判断趋势真假和入场时机的核心: -### 1. 健康上涨信号 -- **放量上涨**:价格上涨 + 成交量放大(量比>1.5)= 上涨有效,可追多 -- **缩量回调**:上涨后回调 + 成交量萎缩(量比<0.7)= 回调健康,可低吸 +### 1. 健康上涨信号(适合做多) +- **放量上涨**:价格上涨 + 量比>1.5 = 上涨有效,可追多 +- **缩量回调**:上涨后回调 + 量比<0.7 = 回调健康,可低吸 +- **健康上涨结构**:放量涨 → 缩量跌 → 再放量涨 -### 2. 健康下跌信号 -- **放量下跌**:价格下跌 + 成交量放大 = 下跌有效,可追空 -- **缩量反弹**:下跌后反弹 + 成交量萎缩 = 反弹无力,可做空 +### 2. 健康下跌信号(适合做空) +- **放量下跌**:价格下跌 + 量比>1.5 = 下跌有效,可追空 +- **缩量反弹**:下跌后反弹 + 量比<0.7 = 反弹无力,可做空 +- **健康下跌结构**:放量跌 → 缩量涨 → 再放量跌 ### 3. 量价背离(重要反转信号) -- **顶背离**:价格创新高,但成交量未创新高 → 上涨动能衰竭,警惕回落 -- **底背离**:价格创新低,但成交量未创新低 → 下跌动能衰竭,关注反弹 -- **天量见顶**:极端放量(量比>3)后价格滞涨 → 主力出货信号 -- **地量见底**:极端缩量(量比<0.3)后价格企稳 → 抛压枯竭信号 +- **顶背离**:价格创新高,但量能未创新高 → 上涨动能衰竭 +- **底背离**:价格创新低,但量能未创新低 → 下跌动能衰竭 +- **天量见顶**:量比>3 后价格滞涨 → 主力出货信号 +- **地量见底**:量比<0.3 后价格企稳 → 抛压枯竭信号 -### 4. 突破确认 -- **有效突破**:突破关键位 + 放量确认(量比>1.5)= 真突破 -- **假突破**:突破关键位 + 缩量 = 假突破,可能回落 +### 4. 突破确认(日内关键) +- **有效突破**:突破关键位 + 量比>1.5 = 真突破,可追 +- **假突破**:突破关键位 + 量比<1.0 = 假突破,等待回落 +- **突破后回踩**:突破后回踩确认 + 缩量 = 最佳入场点 -## 二、K线形态分析 -### 反转形态 -- **锤子线/倒锤子**:下跌趋势中出现,下影线长 = 底部信号 -- **吞没形态**:大阳吞没前一根阴线 = 看涨;大阴吞没前一根阳线 = 看跌 -- **十字星**:在高位/低位出现 = 变盘信号 -- **早晨之星/黄昏之星**:三根K线组合的反转信号 +## 四、K线形态分析(日内常用) +### 反转形态(高优先级) +- **锤子线/倒锤子**:单根反转信号,下影线长 ≥ 实体2倍 +- **吞没形态**:大阳吞没阴线 = 看涨;大阴吞没阳线 = 看跌 +- **十字星**:高位/低位出现 = 变盘信号 +- **早晨之星/黄昏之星**:三根K线组合,强反转信号 -### 持续形态 -- **三连阳/三连阴**:趋势延续信号 -- **旗形整理**:趋势中的健康回调 +### 持续形态(趋势延续) +- **三连阳/三连阴**:趋势延续,但注意第4根可能反转 +- **旗形整理**:趋势中的健康回调,可沿趋势方向入场 -## 三、技术指标分析 -### RSI(相对强弱指标) -**RSI 是最重要的超买超卖指标,请注意细节:** +### 日内常用组合(5m/15m) +- **阳包阴 + 放量**:强买入信号 +- **阴包阳 + 放量**:强卖出信号 +- **连续小阳/小阴后大阳/大阴**:加速信号 + +## 五、技术指标分析(日内优化版) + +### RSI(相对强弱指标)- 日内核心 +**RSI 是最重要的超买超卖指标,日内交易更敏感**: - **RSI < 30**:超卖区,关注反弹机会 - RSI 从 30 以下回升,交叉上穿 30:买入信号 - RSI 底背离(价格新低但 RSI 未创新低):强买入信号 @@ -241,88 +305,129 @@ class MarketSignalAnalyzer: - RSI 从 70 以上回落,交叉下穿 70:卖出信号 - RSI 顶背离(价格新高但 RSI 未创新高):强卖出信号 - **RSI 40-60**:震荡区,观望为主 +- **RSI 50 分界**:多空分界线,上多下空 + +**日内 RSI 使用技巧**: +- 15m RSI 用于判断趋势方向 +- 5m RSI 用于精确入场时机 +- 1m RSI 用于最后确认(避免假突破) - **RSI 趋势**:RSI 自身的趋势变化比单一数值更重要 -### MACD -- 金叉(DIF 上穿 DEA):做多信号 -- 死叉(DIF 下穿 DEA):做空信号 -- 零轴上方金叉:强势做多 -- 零轴下方死叉:强势做空 -- MACD 柱状图背离:重要反转信号 +### MACD(趋势确认) +- **金叉**(DIF 上穿 DEA):做多信号 +- **死叉**(DIF 下穿 DEA):做空信号 +- **零轴上方金叉**:强势做多 +- **零轴下方死叉**:强势做空 +- **MACD 柱状图背离**:重要反转信号 -### 布林带 -- 触及下轨 + 企稳:反弹做多 -- 触及上轨 + 受阻:回落做空 -- 布林带收口:即将变盘 -- 布林带开口:趋势启动 +**日内 MACD 使用**: +- 15m MACD 判断主趋势 +- 5m MACD 确认入场时机 +- 柱状图缩短 = 动能减弱,警惕反转 + +### 布林带(波动率指标) +- **触及下轨 + 企稳**:反弹做多机会 +- **触及上轨 + 受阻**:回落做空机会 +- **布林带收口**:即将变盘,观望 +- **布林带开口**:趋势启动,跟随 + +**日内布林带使用**: +- 价格在下轨 + RSI < 30 = 超卖反弹 +- 价格在上轨 + RSI > 70 = 超买回落 +- 突破上轨 + 放量 = 强势上涨,可追 ### 均线系统(趋势判断核心 - 使用 EMA) -- **多头排列**(EMA5 > EMA10 > EMA20 > EMA50):强势上涨趋势,回调做多 -- **空头排列**(EMA5 < EMA10 < EMA20 < EMA50):强势下跌趋势,反弹做空 +**EMA 比 SMA 反应更快,适合日内**: +- **多头排列**(EMA5 > EMA10 > EMA20):强势上涨,回调做多 +- **空头排列**(EMA5 < EMA10 < EMA20):强势下跌,反弹做空 - **价格与 EMA 的关系**: - - 价格站稳 EMA5/EMA10 上方:短线上涨 + - 价格站稳 EMA5:短线上涨 - 价格突破 EMA20:中线转多 - 价格跌破 EMA20:中线转空 - - EMA50 是中期趋势的分水岭 -- **均线金叉死叉**: - - EMA5 上穿 EMA10:短线买入信号 - - EMA5 下穿 EMA10:短线卖出信号 - - EMA10 上穿 EMA20:中线买入信号 - - EMA10 下穿 EMA20:中线卖出信号 +- **EMA 金叉死叉**: + - EMA5 上穿 EMA10:短线买入 + - EMA5 下穿 EMA10:短线卖出 + - EMA10 上穿 EMA20:中线买入 + - EMA10 下穿 EMA20:中线卖出 -## 四、新闻舆情分析 +**日内 EMA 使用技巧**: +- 30m EMA 判断日内趋势方向 +- 15m EMA 寻找入场时机 +- 5m EMA 确认最佳入场点 +- **EMA 作为支撑/压力**:价格回调到 EMA 常有支撑/阻力 + +## 六、新闻舆情分析(日内影响) 结合最新市场新闻判断: - **重大利好**:监管利好、机构入场、ETF 通过等 → 提高做多置信度 - **重大利空**:监管打压、交易所暴雷、黑客攻击等 → 提高做空置信度 - **市场情绪**:恐慌指数、社交媒体热度 - **大户动向**:鲸鱼转账、交易所流入流出 -## 五、多周期共振(关键分析框架) -**多周期共振是提高信号质量的核心方法:** +**日内交易注意**: +- 重大新闻后 1-2 小时内波动剧烈,适合突破交易 +- 新闻驱动的行情通常持续 2-4 小时,符合日内目标 +- 注意新闻发布时间(美股开盘、宏观数据等) -### 周期层级关系 -- **1h(当日大方向)**:判断当日的主要趋势方向 -- **30m(日内趋势层)**:决定日内主趋势 -- **15m(入场层)**:寻找入场时机 -- **5m(精确入场)**:确认最佳入场点 -- **1m(超精确)**:最后确认(可选) +## 七、多周期共振(日内关键分析框架) +**多周期共振是提高信号质量的核心方法**: -### 共振判断标准 -**强共振(A级信号)**: -- 30m + 15m + 5m 趋势同向(如 30m多 + 15m多 + 5m多) -- 多周期 RSI 同时超买/超卖后出现背离 -- 多周期 EMA 同时金叉/死叉 +### 周期层级关系(日内优化版) +- **1h(当日大方向)**:判断当日的主要趋势方向,确保不逆大势 +- **30m(日内趋势层)**:决定日内主趋势,使用 EMA 判断 +- **15m(入场层)**:寻找入场时机,等待回调/反弹 +- **5m(精确入场)**:确认最佳入场点,避免假突破 +- **1m(超精确)**:最后确认(可选),避免刚入场就反转 -**中等共振(B级信号)**: -- 30m + 15m 同向 +### 共振判断标准(日内版) +**强共振(A级信号,confidence 85-100)**: +- 30m + 15m + 5m EMA 趋势同向 +- 多周期 RSI 同时配合(如都不在极端区) +- 多周期 MACD 同时金叉/死叉 +- 量能配合(放量突破或缩量回调) + +**中等共振(B级信号,confidence 60-84)**: +- 30m + 15m EMA 同向 - 主周期(15m)技术指标明确 +- 量能基本配合 -**弱共振(C级信号)**: +**弱共振(C级信号,confidence 40-59)**: - 只有单一周期信号 - 多周期方向不一致 +- 量能不明显 -### 实战策略 -- **顺势交易**:30m 和 15m 同向时,在 5m/1m 寻找入场点 -- **逆势谨慎**:只有 15m 信号但 30m 反向时,降低置信度 -- **突破交易**:多周期同时突破关键位,信号最强 +**无共振(D级信号,confidence < 40)**: +- 多周期信号矛盾 +- 量价背离 +- 不建议交易 -## 六、入场方式 +### 日内实战策略 +- **顺势交易**:30m 和 15m EMA 同向时,在 5m/1m 寻找入场点 +- **逆势谨慎**:只有 15m 信号但 30m EMA 反向时,降低置信度 +- **突破交易**:多周期同时突破关键位 + 放量,信号最强 +- **回调交易**:30m 趋势向上,15m 回调到 EMA20,5m 反弹确认 + +## 八、入场方式(日内优化) 根据市场分析综合判断入场方式: -- **market**:现价立即入场 - - 信号强烈且明确(A级或高置信度B级) - - 放量突破关键位,趋势明确 - - 多周期共振,等待可能错过机会 - - 市场波动大,等待可能价格变化太快 -- **limit**:挂单等待入场 - - 信号强度中等(B级或C级) - - 当前价格距离理想入场位有一定距离 - - 判断市场可能回调到更好位置 - - 希望获得更优成交价格,愿意承担可能无法成交的风险 + +### market(现价立即入场) +使用场景: +- ✅ 强共振信号(A级,confidence ≥ 85) +- ✅ 放量突破关键位,趋势明确 +- ✅ 多周期同时突破,等待可能错过机会 +- ✅ 市场波动大,价格变化快 +- ✅ 15m RSI 50-70(多)或 30-50(空)- 不极端 + +### limit(挂单等待入场) +使用场景: +- ✅ 信号强度中等(B/C 级) +- ✅ 等待回调到支撑位(EMA20、前期低点) +- ✅ 等待反弹到压力位(EMA20、前期高点) +- ✅ 希望获得更优成交价格 +- ✅ 震荡市区间交易 **重要**: -- 必须同时输出 `entry_zone`(建议入场价)和 `entry_type`(入场方式) +- 必须同时输出 `entry_price`(建议入场价)和 `entry_type`(入场方式) - 入场方式由你的市场分析判断,不是简单的价格距离计算 -- 如果选择 `limit`,`entry_zone` 应该是你建议的挂单价格 ## 输出格式 请严格按照以下 JSON 格式输出: @@ -342,7 +447,7 @@ class MarketSignalAnalyzer: "entry_type": "market/limit", "confidence": 0-100, "grade": "A/B/C/D", - "entry_zone": 66000, + "entry_price": 66000, "stop_loss": 65500, "take_profit": 67500, "reasoning": "详细的入场理由(必须包含趋势判断和量价分析)", @@ -357,24 +462,44 @@ class MarketSignalAnalyzer: ``` ## 重要说明 +- `entry_price`:建议入场价格(单一值) +- `entry_type`:入场方式 - `market`(现价立即入场)或 `limit`(挂单等待) - **所有价格必须是纯数字**,不要加 $ 符号、逗号或其他格式 -- `entry_zone`、`stop_loss`、`take_profit` 必须是数字类型,不要是字符串 +- `entry_price`、`stop_loss`、`take_profit` 必须是数字类型,不要是字符串 - `key_levels` 中的支撑位和阻力位也必须是数字数组 -## 信号等级与置信度 -- **A级**(80-100):量价配合 + 多指标共振 + 多周期确认 -- **B级**(60-79):量价配合 + 主要指标确认 -- **C级**(40-59):有机会但量价不够理想 -- **D级**(<40):量价背离或信号矛盾 +## 信号等级与置信度(日内优化版) +- **A级**(85-100):量价配合 + 多指标共振 + 多周期确认 + 盈亏比 ≥ 1:1.5 +- **B级**(60-84):量价配合 + 主要指标确认 + 盈亏比 ≥ 1:1.2 +- **C级**(40-59):有机会但量价不够理想 + 盈亏比 ≥ 1:1.2 +- **D级**(<40):量价背离或信号矛盾或盈亏比不足 -## 注意事项 +## 注意事项(日内交易重点) 1. **只在有明确的做多或做空机会时才输出信号**(action 为 buy 或 sell) 2. 如果市场不明朗,没有明确交易机会,**不要输出任何信号**(signals 为空数组 []) -3. 信号强度(confidence)要合理,不要随意给高分 -4. 60-70分:一般信号,可轻仓试探 -5. 75-85分:较强信号,可正常仓位 -6. 90+分:强信号,但也要控制风险 -7. 不要输出 action 为 "wait" 的信号,如果没有交易机会就不输出 +3. 信号强度(confidence)要合理,不要随意给高分: + - 60-70分:一般信号,可轻仓试探(micro 仓位) + - 75-84分:较强信号,可正常仓位(light 仓位) + - 85-100分:强信号,可考虑 medium 仓位 +4. **不要输出 action 为 "wait" 的信号**,如果没有交易机会就不输出 +5. **每次检查盈亏比**:盈亏比 < 1:1.2 的信号不要输出 +6. **避免过度交易**:趋势延续时不重复输出相同方向信号 +7. **关注时效性**:日内信号有效期通常 2-4 小时,超过时间需重新评估 + +## 日内交易特殊注意事项 +1. **不持仓过夜**:收盘前 30 分钟逐步平仓 +2. **快进快出**:达到目标(2-3%)立即平仓,不贪心 +3. **严格止损**:触及止损立即离场,不要幻想 +4. **避免追涨杀跌**:价格过度延伸时(偏离 EMA5 > 3%)不追 +5. **关注量能**:无量配合的突破不追,容易是假突破 +6. **多周期确认**:5m/15m/30m 同向才入场,提高胜率 + +## 🎯 日内交易成功关键 +1. **盈亏比第一**:宁可错过,不做错 +2. **顺势而为**:趋势方向正确,成功率才能高 +3. **快速止损**:日内交易,止损就是止错 +4. **不贪不急**:达到目标就走,达不到就止损 +5. **保持冷静**:不被情绪左右,按规则交易 ## 历史信号参考(非常重要!) **如果提供了上一轮的分析信号,必须仔细参考它:** @@ -666,11 +791,11 @@ class MarketSignalAnalyzer: if is_accelerating and volume_ratio > 1.3 and not is_overextended: analysis.append(f"15m: 正在加速上涨,放量突破") analysis.append(f" → 日内追多(止损1-2%,目标2-3%)") - analysis.append(f" → 盈亏比要求 >= 1:2") + analysis.append(f" → 盈亏比要求 >= 1:1.2") elif distance_to_ema20 < 1 and deviation_ema5_15m > 1.5: analysis.append(f"15m: 回调到 EMA20 支撑位") analysis.append(f" → 支撑位做多反弹(EMA20: ${ema20_15m:.0f})") - analysis.append(f" → 止损1%,目标2-3%,盈亏比 >= 1:3") + analysis.append(f" → 止损1%,目标2-3%,盈亏比 >= 1:1.5") elif is_overextended: analysis.append(f"⚠️ 15m 过度延伸: RSI {rsi_15m:.0f},偏离 EMA5 {deviation_ema5_15m:.1f}%") analysis.append(f" → 不要追多,等待回调") @@ -682,11 +807,11 @@ class MarketSignalAnalyzer: if is_accelerating and volume_ratio > 1.3 and not is_overextended: analysis.append(f"15m: 正在加速下跌,放量跌破") analysis.append(f" → 日内追空(止损1-2%,目标2-3%)") - analysis.append(f" → 盈亏比要求 >= 1:2") + analysis.append(f" → 盈亏比要求 >= 1:1.2") elif distance_to_ema20 < 1 and deviation_ema5_15m > 1.5: analysis.append(f"15m: 反弹到 EMA20 压力位") analysis.append(f" → 压力位做空回调(EMA20: ${ema20_15m:.0f})") - analysis.append(f" → 止损1%,目标2-3%,盈亏比 >= 1:3") + analysis.append(f" → 止损1%,目标2-3%,盈亏比 >= 1:1.5") elif is_overextended: analysis.append(f"⚠️ 15m 过度延伸: RSI {rsi_15m:.0f},偏离 EMA5 {deviation_ema5_15m:.1f}%") analysis.append(f" → 不要追空,等待反弹") @@ -696,12 +821,12 @@ class MarketSignalAnalyzer: else: analysis.append(f"15m: 震荡,观望或双向轻仓") - analysis.append(f" → 支撑位多,压力位空,盈亏比 >= 1:3") + analysis.append(f" → 支撑位多,压力位空,盈亏比 >= 1:1.5") # 日内交易要点 analysis.append(f"\n💡 日内交易要点:") analysis.append(f"- 使用 EMA(指数移动平均)反应更快") - analysis.append(f"- 盈亏比第一: 必须 >= 1:2,优选 1:3") + analysis.append(f"- 盈亏比第一: 必须 >= 1:1.2") analysis.append(f"- 快进快出: 持仓不超过4小时") analysis.append(f"- 严格止损: 1-2%(最大2%)") analysis.append(f"- 目标盈利: 2-3%(快速获利)") @@ -744,7 +869,7 @@ class MarketSignalAnalyzer: type_map = {'short_term': '短线', 'medium_term': '中线', 'long_term': '长线'} type_text = type_map.get(timeframe, timeframe) - entry = sig.get('entry_zone', 'N/A') + entry = sig.get('entry_price', 'N/A') sl = sig.get('stop_loss', 'N/A') tp = sig.get('take_profit', 'N/A') reasoning = sig.get('reasoning', 'N/A') @@ -947,45 +1072,45 @@ class MarketSignalAnalyzer: signals_to_remove = [] for idx, sig in enumerate(data['signals']): - price_fields = ['entry_zone', 'stop_loss', 'take_profit'] + price_fields = ['entry_price', 'stop_loss', 'take_profit'] for field in price_fields: if field in sig: sig[field] = clean_price(sig[field]) # 验证止损止盈价格的合理性 - entry_zone = sig.get('entry_zone') + entry_price = sig.get('entry_price') stop_loss = sig.get('stop_loss') take_profit = sig.get('take_profit') action = sig.get('action', '') - if entry_zone and entry_zone > 0: + if entry_price and entry_price > 0: MAX_REASONABLE_DEVIATION = 0.50 # 50% has_invalid_price = False # 检查止损 if stop_loss is not None: - deviation = abs(stop_loss - entry_zone) / entry_zone + deviation = abs(stop_loss - entry_price) / entry_price if deviation > MAX_REASONABLE_DEVIATION: - logger.warning(f"⚠️ [{data.get('symbol', '')}] 信号止损价格不合理: entry={entry_zone}, stop_loss={stop_loss}, 偏离={deviation*100:.1f}%") + logger.warning(f"⚠️ [{data.get('symbol', '')}] 信号止损价格不合理: entry={entry_price}, stop_loss={stop_loss}, 偏离={deviation*100:.1f}%") has_invalid_price = True - elif action == 'buy' and stop_loss >= entry_zone: - logger.warning(f"⚠️ [{data.get('symbol', '')}] 做多止损错误: entry={entry_zone}, stop_loss={stop_loss} 应该 < entry") + elif action == 'buy' and stop_loss >= entry_price: + logger.warning(f"⚠️ [{data.get('symbol', '')}] 做多止损错误: entry={entry_price}, stop_loss={stop_loss} 应该 < entry") has_invalid_price = True - elif action == 'sell' and stop_loss <= entry_zone: - logger.warning(f"⚠️ [{data.get('symbol', '')}] 做空止损错误: entry={entry_zone}, stop_loss={stop_loss} 应该 > entry") + elif action == 'sell' and stop_loss <= entry_price: + logger.warning(f"⚠️ [{data.get('symbol', '')}] 做空止损错误: entry={entry_price}, stop_loss={stop_loss} 应该 > entry") has_invalid_price = True # 检查止盈 if take_profit is not None: - deviation = abs(take_profit - entry_zone) / entry_zone + deviation = abs(take_profit - entry_price) / entry_price if deviation > MAX_REASONABLE_DEVIATION: - logger.warning(f"⚠️ [{data.get('symbol', '')}] 信号止盈价格不合理: entry={entry_zone}, take_profit={take_profit}, 偏离={deviation*100:.1f}%") + logger.warning(f"⚠️ [{data.get('symbol', '')}] 信号止盈价格不合理: entry={entry_price}, take_profit={take_profit}, 偏离={deviation*100:.1f}%") has_invalid_price = True - elif action == 'buy' and take_profit <= entry_zone: - logger.warning(f"⚠️ [{data.get('symbol', '')}] 做多止盈错误: entry={entry_zone}, take_profit={take_profit} 应该 > entry") + elif action == 'buy' and take_profit <= entry_price: + logger.warning(f"⚠️ [{data.get('symbol', '')}] 做多止盈错误: entry={entry_price}, take_profit={take_profit} 应该 > entry") has_invalid_price = True - elif action == 'sell' and take_profit >= entry_zone: - logger.warning(f"⚠️ [{data.get('symbol', '')}] 做空止盈错误: entry={entry_zone}, take_profit={take_profit} 应该 < entry") + elif action == 'sell' and take_profit >= entry_price: + logger.warning(f"⚠️ [{data.get('symbol', '')}] 做空止盈错误: entry={entry_price}, take_profit={take_profit} 应该 < entry") has_invalid_price = True # 如果价格不合理,降低等级为 D 或移除信号 diff --git a/backend/app/crypto_agent/trading_decision_maker.py b/backend/app/crypto_agent/trading_decision_maker.py index 24c413a..567f464 100644 --- a/backend/app/crypto_agent/trading_decision_maker.py +++ b/backend/app/crypto_agent/trading_decision_maker.py @@ -333,10 +333,10 @@ class TradingDecisionMaker: } ``` -**注意**: -- `quantity` 是保证金金额(USDT),交易系统会使用杠杆计算实际持仓价值 -- 如果 decision 是 CANCEL_PENDING,需要提供 orders_to_cancel 字段 -- reasoning 必须说明当前持仓/挂单状态以及为什么选择这个操作 +## 入场价格选择策略 + +- 使用信号中的 `entry_price` 作为入场价格 +- 如果选择 `limit`(挂单)方式,等待价格达到 `entry_price` 时成交 ## 重要原则 1. **仓位管理优先**:先管理现有仓位,再考虑开新仓 @@ -553,9 +553,9 @@ class TradingDecisionMaker: prompt_parts.append(f" 信心度: {sig.get('confidence', 0)}") # 添加入场价格信息 - entry_zone = sig.get('entry_zone') - if entry_zone: - prompt_parts.append(f" 建议入场价: ${entry_zone:,.2f}") + entry_price = sig.get('entry_price') + if entry_price: + prompt_parts.append(f" 建议入场价: ${entry_price:,.2f}") prompt_parts.append(f" 理由: {sig.get('reasoning', 'N/A')}") @@ -699,7 +699,7 @@ class TradingDecisionMaker: if signals and current_price: for sig in signals: sig_action = sig.get('action') - sig_entry = sig.get('entry_zone') + sig_entry = sig.get('entry_price') if sig_action and sig_entry: try: @@ -744,7 +744,7 @@ class TradingDecisionMaker: if signals: for sig in signals: action = sig.get('action') - entry = sig.get('entry_zone') + entry = sig.get('entry_price') stop_loss = sig.get('stop_loss') take_profit = sig.get('take_profit') @@ -852,7 +852,7 @@ class TradingDecisionMaker: def _validate_price_fields(self, data: Dict[str, Any]) -> Dict[str, Any]: """验证止损止盈价格的合理性,拒绝明显错误的值""" - entry = data.get('entry_zone') + entry = data.get('entry_price') stop_loss = data.get('stop_loss') take_profit = data.get('take_profit') action = data.get('decision', '') # OPEN/CLOSE/HOLD diff --git a/backend/app/main.py b/backend/app/main.py index 61cef0b..04f2a72 100644 --- a/backend/app/main.py +++ b/backend/app/main.py @@ -124,12 +124,12 @@ async def price_monitor_loop(): """后台价格监控循环 - 使用轮询检查止盈止损""" from app.services.paper_trading_service import get_paper_trading_service from app.services.bitget_service import bitget_service - from app.services.feishu_service import get_feishu_service + from app.services.feishu_service import get_feishu_paper_trading_service from app.services.telegram_service import get_telegram_service logger.info("后台价格监控任务已启动(轮询模式)") - feishu = get_feishu_service() + feishu = get_feishu_paper_trading_service() # 使用 trading webhook telegram = get_telegram_service() paper_trading = get_paper_trading_service() diff --git a/backend/app/services/paper_trading_service.py b/backend/app/services/paper_trading_service.py index cb1a425..db7a386 100644 --- a/backend/app/services/paper_trading_service.py +++ b/backend/app/services/paper_trading_service.py @@ -177,6 +177,8 @@ class PaperTradingService: symbol = signal.get('symbol', 'UNKNOWN') side = OrderSide.LONG if action == 'buy' else OrderSide.SHORT + + # 获取入场价格 entry_price = signal.get('entry_price') or signal.get('price', 0) # === 反向订单处理 === diff --git a/backend/app/services/signal_database_service.py b/backend/app/services/signal_database_service.py index 32bcbed..c3de41d 100644 --- a/backend/app/services/signal_database_service.py +++ b/backend/app/services/signal_database_service.py @@ -51,14 +51,15 @@ class SignalDatabaseService: return None # 创建信号对象 + entry_price_value = clean_price(signal_data.get('entry_price')) + signal = TradingSignal( signal_type=signal_data.get('signal_type', 'crypto'), symbol=signal_data.get('symbol', ''), action=signal_data.get('action', 'hold'), grade=signal_data.get('grade', 'D'), confidence=signal_data.get('confidence', 0), - entry_price=clean_price(signal_data.get('entry_price')), - entry_zone=clean_price(signal_data.get('entry_zone')), # 挂单价格 + entry_price=entry_price_value, stop_loss=clean_price(signal_data.get('stop_loss')), take_profit=clean_price(signal_data.get('take_profit')), current_price=clean_price(signal_data.get('current_price')), diff --git a/backend/app/stock_agent/market_signal_analyzer.py b/backend/app/stock_agent/market_signal_analyzer.py index 18911be..a06357e 100644 --- a/backend/app/stock_agent/market_signal_analyzer.py +++ b/backend/app/stock_agent/market_signal_analyzer.py @@ -305,7 +305,7 @@ class StockMarketSignalAnalyzer: - 希望获得更优成交价格,愿意承担可能无法成交的风险 **重要**: -- 必须同时输出 `entry_zone`(建议入场价)和 `entry_type`(入场方式) +- 必须同时输出 `entry_price`(建议入场价)和 `entry_type`(入场方式) - 入场方式由你的市场分析判断,不是简单的价格距离计算 ## 输出格式 @@ -326,7 +326,7 @@ class StockMarketSignalAnalyzer: "entry_type": "market/limit", "confidence": 0-100, "grade": "A/B/C/D", - "entry_zone": 150.50, + "entry_price": 150.50, "stop_loss": 148.00, "take_profit": 155.00, "reasoning": "详细的入场理由(必须包含趋势判断和量价分析)", @@ -342,7 +342,7 @@ class StockMarketSignalAnalyzer: ## 重要说明 - **所有价格必须是纯数字**,不要加 $ 符号、逗号或其他格式 -- `entry_zone`、`stop_loss`、`take_profit` 必须是数字类型,不要是字符串 +- `entry_price`、`stop_loss`、`take_profit` 必须是数字类型,不要是字符串 - `key_levels` 中的支撑位和阻力位也必须是数字数组 ## 信号等级与置信度(综合技术面 + 基本面 + 新闻) @@ -653,45 +653,45 @@ class StockMarketSignalAnalyzer: if 'signals' in data: for sig in data['signals']: - price_fields = ['entry_zone', 'stop_loss', 'take_profit'] + price_fields = ['entry_price', 'stop_loss', 'take_profit'] for field in price_fields: if field in sig: sig[field] = clean_price(sig[field]) # 验证止损止盈价格的合理性 - entry_zone = sig.get('entry_zone') + entry_price = sig.get('entry_price') stop_loss = sig.get('stop_loss') take_profit = sig.get('take_profit') action = sig.get('action', '') - if entry_zone and entry_zone > 0: + if entry_price and entry_price > 0: MAX_REASONABLE_DEVIATION = 0.50 # 50% has_invalid_price = False # 检查止损 if stop_loss is not None: - deviation = abs(stop_loss - entry_zone) / entry_zone + deviation = abs(stop_loss - entry_price) / entry_price if deviation > MAX_REASONABLE_DEVIATION: - logger.warning(f"⚠️ [{data.get('symbol', '')}] 信号止损价格不合理: entry={entry_zone}, stop_loss={stop_loss}, 偏离={deviation*100:.1f}%") + logger.warning(f"⚠️ [{data.get('symbol', '')}] 信号止损价格不合理: entry={entry_price}, stop_loss={stop_loss}, 偏离={deviation*100:.1f}%") has_invalid_price = True - elif action == 'buy' and stop_loss >= entry_zone: - logger.warning(f"⚠️ [{data.get('symbol', '')}] 做多止损错误: entry={entry_zone}, stop_loss={stop_loss} 应该 < entry") + elif action == 'buy' and stop_loss >= entry_price: + logger.warning(f"⚠️ [{data.get('symbol', '')}] 做多止损错误: entry={entry_price}, stop_loss={stop_loss} 应该 < entry") has_invalid_price = True - elif action == 'sell' and stop_loss <= entry_zone: - logger.warning(f"⚠️ [{data.get('symbol', '')}] 做空止损错误: entry={entry_zone}, stop_loss={stop_loss} 应该 > entry") + elif action == 'sell' and stop_loss <= entry_price: + logger.warning(f"⚠️ [{data.get('symbol', '')}] 做空止损错误: entry={entry_price}, stop_loss={stop_loss} 应该 > entry") has_invalid_price = True # 检查止盈 if take_profit is not None: - deviation = abs(take_profit - entry_zone) / entry_zone + deviation = abs(take_profit - entry_price) / entry_price if deviation > MAX_REASONABLE_DEVIATION: - logger.warning(f"⚠️ [{data.get('symbol', '')}] 信号止盈价格不合理: entry={entry_zone}, take_profit={take_profit}, 偏离={deviation*100:.1f}%") + logger.warning(f"⚠️ [{data.get('symbol', '')}] 信号止盈价格不合理: entry={entry_price}, take_profit={take_profit}, 偏离={deviation*100:.1f}%") has_invalid_price = True - elif action == 'buy' and take_profit <= entry_zone: - logger.warning(f"⚠️ [{data.get('symbol', '')}] 做多止盈错误: entry={entry_zone}, take_profit={take_profit} 应该 > entry") + elif action == 'buy' and take_profit <= entry_price: + logger.warning(f"⚠️ [{data.get('symbol', '')}] 做多止盈错误: entry={entry_price}, take_profit={take_profit} 应该 > entry") has_invalid_price = True - elif action == 'sell' and take_profit >= entry_zone: - logger.warning(f"⚠️ [{data.get('symbol', '')}] 做空止盈错误: entry={entry_zone}, take_profit={take_profit} 应该 < entry") + elif action == 'sell' and take_profit >= entry_price: + logger.warning(f"⚠️ [{data.get('symbol', '')}] 做空止盈错误: entry={entry_price}, take_profit={take_profit} 应该 < entry") has_invalid_price = True # 如果价格不合理,降低等级为 D diff --git a/backend/app/utils/signal_formatter.py b/backend/app/utils/signal_formatter.py index 0405ed8..82d7d31 100644 --- a/backend/app/utils/signal_formatter.py +++ b/backend/app/utils/signal_formatter.py @@ -61,7 +61,7 @@ class SignalFormatter: position_text = position_map.get(position_size, '轻仓') # 计算风险收益比 - entry = signal.get('entry_price') or signal.get('entry_zone', 0) + entry = signal.get('entry_price', 0) sl = signal.get('stop_loss', 0) tp = signal.get('take_profit', 0) sl_percent = ((sl - entry) / entry * 100) if entry else 0 @@ -167,7 +167,7 @@ class SignalFormatter: color = "red" # 计算风险收益比 - entry = signal.get('entry_price') or signal.get('entry_zone', 0) + entry = signal.get('entry_price', 0) sl = signal.get('stop_loss', 0) tp = signal.get('take_profit', 0) sl_percent = ((sl - entry) / entry * 100) if entry else 0 diff --git a/backend/test_market_signal.py b/backend/test_market_signal.py index 56c65dd..8ffcbf4 100644 --- a/backend/test_market_signal.py +++ b/backend/test_market_signal.py @@ -80,7 +80,7 @@ async def test_trend_analysis(symbol: str = "BTCUSDT"): logger.info(f" ├─ 类型: {sig.get('timeframe', 'unknown')} | {entry_type_emoji}") logger.info(f" ├─ 操作: {sig.get('action', 'unknown').upper()}") logger.info(f" ├─ 信心度: {sig.get('confidence', 0)}% | 等级: {sig.get('grade', 'unknown')}") - logger.info(f" ├─ 入场价: ${sig.get('entry_zone', 0):,.2f}") + logger.info(f" ├─ 入场价: ${sig.get('entry_price', 0):,.2f}") logger.info(f" ├─ 止损: ${sig.get('stop_loss', 0):,.2f} | 止盈: ${sig.get('take_profit', 0):,.2f}") logger.info(f" └─ 理由: {sig.get('reasoning', 'unknown')}")