ソースを参照

增强了止盈止损部分的日志,检查是否有问题

maxfeng 2 ヶ月 前
コミット
d1bef407ba
2 ファイル変更87 行追加9 行削除
  1. 80 8
      Lib/future/MAPatternStrategy_v002.py
  2. 7 1
      Lib/future/README.md

+ 80 - 8
Lib/future/MAPatternStrategy_v002.py

@@ -3,6 +3,7 @@ from jqdata import *
 from jqdata import finance
 import pandas as pd
 import numpy as np
+import math
 from datetime import date, datetime, timedelta, time
 import re
 
@@ -56,6 +57,9 @@ def initialize(context):
     g.check_intraday_spread = False  # 是否检查日内价差(True: 检查, False: 跳过)
     g.ma_proximity_min_threshold = 8  # MA5与MA10贴近计数和的最低阈值
     g.ma_pattern_extreme_days_threshold = 4  # 极端趋势天数阈值
+    g.ma_distribution_lookback_days = 5  # MA5分布过滤回溯天数
+    g.ma_distribution_min_ratio = 0.4  # MA5分布满足比例阈值
+    g.enable_ma_distribution_filter = True  # 是否启用MA5分布过滤
     
     # 均线价差策略方案选择
     g.ma_gap_strategy_mode = 3  # 策略模式选择(1: 原方案, 2: 新方案, 3: 方案3)
@@ -79,6 +83,9 @@ def initialize(context):
     log.info(f"  历史均线模式一致性阈值: {g.ma_pattern_consistency_threshold:.1%}")
     log.info(f"  极端趋势天数阈值: {g.ma_pattern_extreme_days_threshold}")
     log.info(f"  均线贴近计数阈值: {g.ma_proximity_min_threshold}")
+    log.info(f"  MA5分布过滤天数: {g.ma_distribution_lookback_days}")
+    log.info(f"  MA5分布最低比例: {g.ma_distribution_min_ratio:.0%}")
+    log.info(f"  启用MA5分布过滤: {g.enable_ma_distribution_filter}")
     log.info(f"  是否检查日内价差: {g.check_intraday_spread}")
     log.info(f"  固定止损: {g.fixed_stop_loss_rate:.1%}")
     log.info(f"  均线跟踪止盈常规偏移: {g.ma_offset_ratio_normal:.1%}")
@@ -462,6 +469,30 @@ def check_ma_trend_and_open_gap(context):
                 }
                 continue
             
+            if g.enable_ma_distribution_filter:
+                distribution_passed, distribution_stats = check_ma5_distribution_filter(
+                    data_upto_yesterday,
+                    g.ma_distribution_lookback_days,
+                    direction,
+                    g.ma_distribution_min_ratio
+                )
+                log.info(
+                    f"  MA5分布过滤: 方向 {direction}, 有效天数 "
+                    f"{distribution_stats['valid_days']}/{distribution_stats['lookback_days']},"
+                    f"满足天数 {distribution_stats['qualified_days']}/{distribution_stats['required_days']}"
+                )
+                if not distribution_passed:
+                    insufficiency = distribution_stats['valid_days'] < distribution_stats['lookback_days']
+                    reason = "有效数据不足" if insufficiency else "满足天数不足"
+                    log.info(
+                        f"  {symbol}({dominant_future}) ✗ MA5分布过滤未通过({reason})"
+                    )
+                    g.excluded_contracts[dominant_future] = {
+                        'reason': 'ma5_distribution',
+                        'trading_day': current_trading_day
+                    }
+                    continue
+            
             # 检查历史均线模式一致性
             consistency_passed, consistency_ratio = check_historical_ma_pattern_consistency(
                 historical_data, direction, g.ma_pattern_lookback_days, g.ma_pattern_consistency_threshold
@@ -723,6 +754,9 @@ def check_position_stop_loss_profit(context, position):
                 f"成本价: {entry_price:.2f}, 当前价格: {current_price:.2f}")
         close_position(context, security, direction)
         return True
+    else:
+        log.debug(f"未触发固定止损 {security} {direction}, 当前亏损率: {profit_rate:.3%}, "
+                f"成本价: {entry_price:.2f}, 当前价格: {current_price:.2f}")
 
     if entry_trading_day is not None and entry_trading_day == current_trading_day:
         log.info(f"{security} 建仓交易日内跳过动态止盈检查")
@@ -751,9 +785,10 @@ def check_position_stop_loss_profit(context, position):
     target_time = datetime.strptime('14:55:00', '%H:%M:%S').time()
     if current_time > target_time:
         offset_ratio = g.ma_offset_ratio_close
+        log.debug(f"当前时间是:{current_time},使用偏移量: {offset_ratio:.3%}")
     else:
         offset_ratio = g.ma_offset_ratio_normal
-    
+        log.debug(f"当前时间是:{current_time},使用偏移量: {offset_ratio:.3%}")
     # 选择止损均线
     close_line = None
     if today_change_rate >= 1.5 * avg_daily_change_rate:
@@ -781,6 +816,10 @@ def check_position_stop_loss_profit(context, position):
                 f"当前价: {today_price:.2f}, 持仓天数: {holding_days}")
         close_position(context, security, direction)
         return True
+    else:
+        log.debug(f"未触发均线跟踪止盈 {security} {direction}, 止损均线: {close_line}, "
+                f"均线值: {ma_value:.2f}, 调整后: {adjusted_ma_value:.2f}, "
+                f"当前价: {today_price:.2f}, 持仓天数: {holding_days}")
     
     return False
 
@@ -877,6 +916,39 @@ def calculate_extreme_trend_days(data, periods, lookback_days):
     return above_count, below_count
 
 
+def check_ma5_distribution_filter(data, lookback_days, direction, min_ratio):
+    """检查近 lookback_days 天收盘价相对于MA5的分布情况"""
+    stats = {
+        'lookback_days': lookback_days,
+        'valid_days': 0,
+        'qualified_days': 0,
+        'required_days': max(0, math.ceil(lookback_days * min_ratio))
+    }
+
+    if lookback_days <= 0:
+        return True, stats
+
+    if len(data) < max(lookback_days, 5):
+        return False, stats
+
+    recent_closes = data['close'].iloc[-lookback_days:]
+    ma5_series = data['close'].rolling(window=5).mean().iloc[-lookback_days:]
+
+    for close_price, ma5_value in zip(recent_closes, ma5_series):
+        if pd.isna(ma5_value):
+            continue
+        stats['valid_days'] += 1
+        if direction == 'long' and close_price < ma5_value:
+            stats['qualified_days'] += 1
+        elif direction == 'short' and close_price > ma5_value:
+            stats['qualified_days'] += 1
+
+    if stats['valid_days'] < lookback_days:
+        return False, stats
+
+    return stats['qualified_days'] >= stats['required_days'], stats
+
+
 def check_ma_pattern(ma_values, direction):
     """检查均线排列模式是否符合方向要求
     
@@ -1216,14 +1288,14 @@ def position_auto_switch(context, pindex=0, switch_func=None, callback=None):
             underlying_symbol = match.groupdict()["underlying_symbol"]
             trading_start = get_futures_config(underlying_symbol, 'trading_start_time', None)
             has_night_session = get_futures_config(underlying_symbol, 'has_night_session', False)
-            log.debug(f"移仓换月: {symbol}, 交易开始时间: {trading_start}, 夜盘: {has_night_session}")
+            # log.debug(f"移仓换月: {symbol}, 交易开始时间: {trading_start}, 夜盘: {has_night_session}")
             if trading_start and not has_reached_trading_start(context.current_dt, trading_start, has_night_session):
-                log.info("{} 当前时间 {} 未到达交易开始时间 {} (夜盘:{} ),跳过移仓".format(
-                    symbol,
-                    context.current_dt.strftime('%H:%M:%S'),
-                    trading_start,
-                    has_night_session
-                ))
+                # log.info("{} 当前时间 {} 未到达交易开始时间 {} (夜盘:{} ),跳过移仓".format(
+                #     symbol,
+                #     context.current_dt.strftime('%H:%M:%S'),
+                #     trading_start,
+                #     has_night_session
+                # ))
                 continue
             dominant = get_dominant_future(underlying_symbol)
             cur = get_current_data()

+ 7 - 1
Lib/future/README.md

@@ -22,6 +22,9 @@
 - **极端趋势过滤器**:
   - `calculate_extreme_trend_days`会统计过去10个交易日中,收盘价高于所有均线的天数A和低于所有均线的天数B。
   - 当A和B都大于0且`min(A,B) ≥ max(2, g.ma_pattern_extreme_days_threshold)`(默认阈值4)时,视为多空急速转换,过滤该标的,不进入候选列表。
+- **MA5分布过滤**:
+  - 参数:`g.ma_distribution_lookback_days = 5`,`g.ma_distribution_min_ratio = 0.4`,`g.enable_ma_distribution_filter = True`。
+  - 多头要求最近5日中至少40%的交易日收盘价低于MA5;空头要求至少40%交易日收盘价高于MA5。
 - **开盘价差要求**:
   - 策略模式由`g.ma_gap_strategy_mode`决定(默认2)。
   - 方案1:多头需上跳≥`g.ma_open_gap_threshold`(默认0.002),空头需下跳≤`-g.ma_open_gap_threshold`。
@@ -63,6 +66,9 @@
 | `g.ma_open_gap_threshold` | `0.002` | 方案1开盘价差阈值 |
 | `g.ma_open_gap_threshold2` | `0.002` | 方案2开盘价差阈值 |
 | `g.ma_intraday_threshold_scheme2` | `0.005` | 方案2日内变化阈值 |
+| `g.ma_distribution_lookback_days` | `5` | MA5分布过滤回溯天数 |
+| `g.ma_distribution_min_ratio` | `0.4` | MA5分布满足比例阈值 |
+| `g.enable_ma_distribution_filter` | `True` | 是否启用MA5分布过滤 |
 | `g.fixed_stop_loss_rate` | `0.01` | 固定止损比例 |
 | `g.ma_offset_ratio_normal` | `0.003` | 常规追踪止盈偏移 |
 | `g.ma_offset_ratio_close` | `0.01` | 收盘前追踪止盈偏移 |
@@ -77,7 +83,7 @@
 
 ### 日志与排错
 - 每次筛选都会输出趋势状态、均线贴近统计、极端趋势天数、开盘价差等详细日志。
-- 被过滤的合约会记录在`g.excluded_contracts`,原因包括`ma_extreme_trend`、`ma_trend`、`open_gap`等,便于复盘。
+- 被过滤的合约会记录在`g.excluded_contracts`,原因包括`ma_extreme_trend`、`ma_trend`、`ma5_distribution`、`open_gap`等,便于复盘。
 
 ---