From 98f81a3b663be5ddb3573bb63597c1b254b2638d Mon Sep 17 00:00:00 2001 From: "zhangkun9038@dingtalk.com" Date: Fri, 6 Feb 2026 12:45:08 +0800 Subject: [PATCH] =?UTF-8?q?=E8=BF=98=E6=98=AF=E4=B8=89=E5=85=83=E8=A1=A8?= =?UTF-8?q?=E8=BE=BE=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .qoder/specs/grid-strategy-optimizer.md | 131 ++++++++++++++++++++++++ freqtrade/templates/freqaiprimer.py | 17 ++- 2 files changed, 145 insertions(+), 3 deletions(-) create mode 100644 .qoder/specs/grid-strategy-optimizer.md diff --git a/.qoder/specs/grid-strategy-optimizer.md b/.qoder/specs/grid-strategy-optimizer.md new file mode 100644 index 00000000..3d0e4a85 --- /dev/null +++ b/.qoder/specs/grid-strategy-optimizer.md @@ -0,0 +1,131 @@ +# 网格策略参数优化器设计方案 + +## 目标 +构建一个独立的Python模拟框架,通过蒙特卡洛模拟寻找网格交易策略的最优参数组合。 + +## 核心设计决策 + +| 决策项 | 选择 | 理由 | +|--------|------|------| +| 交易方向 | 仅做多 | 现货市场最常见场景 | +| 评价指标 | 收益/最大回撤比 | 用户指定 | +| 资金利用率 | 80% | 常量,保留20%缓冲 | +| 搜索方式 | 网格搜索 | 结果全面,便于可视化热力图 | +| 模拟次数 | 500次/参数组合 | 平衡速度与统计稳健性 | +| 价格模型 | 混合场景(震荡70% + 趋势30%) | 用户指定 | + +## 文件结构 + +``` +/Users/zhangkun/myTestFreqAI/grid_optimizer/ +├── grid_optimizer.py # 主文件,包含所有模块 +``` + +单文件设计,简洁直接。 + +## 模块设计 + +### 1. 价格模拟器 (PriceSimulator) + +```python +class PriceSimulator: + """生成混合场景价格序列""" + + def generate(self, + initial_price: float = 100, + num_steps: int = 1000, + volatility: float = 0.02) -> np.ndarray: + """ + 70%概率生成震荡市(均值回归) + 30%概率生成趋势市(带漂移的随机游走) + """ +``` + +**价格模型**: +- 震荡市:Ornstein-Uhlenbeck过程(均值回归) +- 趋势市:几何布朗运动(带方向漂移) + +### 2. 网格策略引擎 (GridStrategy) + +```python +@dataclass +class GridParams: + num_grids: int # 网格数量 [5, 30] + upper_price: float # 上沿价格(相对初始价格比例)[1.05, 1.30] + lower_price: float # 下沿价格(相对初始价格比例)[0.70, 0.95] + spacing_mode: str # 'uniform' | 'progressive' + bet_mode: str # 'fixed' | 'martingale' + bet_multiplier: float # 马丁格尔倍数 [1.0, 2.0] + stop_loss: float # 止损位(相对下沿)[0.90, 1.0] + take_profit: float # 止盈位(相对上沿)[1.0, 1.10] + +class GridStrategy: + """执行网格交易逻辑""" + + def run(self, prices: np.ndarray, params: GridParams) -> TradeResult: + """ + 返回: 总收益率、最大回撤、交易次数、收益回撤比 + """ +``` + +**交易逻辑**(仅做多): +1. 初始化N条网格线,均匀或渐进分布在上下沿之间 +2. 每条网格线对应一个"格子",有独立的持仓状态 +3. **买入**:价格从上向下穿过某网格线 → 该格子买入 +4. **卖出**:价格从下向上穿过某网格线 → 卖出该格子下方相邻格子的持仓(赚取格差利润) +5. 触及止损 → 全部平仓退出;触及止盈 → 全部平仓锁定利润 + +### 3. 参数优化器 (GridSearchOptimizer) + +```python +class GridSearchOptimizer: + """网格搜索最优参数""" + + def __init__(self, + num_simulations: int = 500, + capital_utilization: float = 0.80): + ... + + def optimize(self) -> pd.DataFrame: + """ + 遍历参数空间,每组参数运行num_simulations次模拟 + 返回按收益回撤比排序的结果表 + """ +``` + +**搜索空间**: +| 参数 | 范围 | 步长 | +|------|------|------| +| num_grids | 5-25 | 5 | +| upper_ratio | 1.10-1.25 | 0.05 | +| lower_ratio | 0.75-0.90 | 0.05 | +| spacing_mode | uniform, progressive | - | +| bet_mode | fixed, martingale | - | +| bet_multiplier | 1.2, 1.5 | - | + +### 4. 可视化模块 + +使用matplotlib生成: +1. **参数热力图**:网格数量 vs 上下沿范围 → 收益回撤比 +2. **收益分布直方图**:最优参数组合的收益分布 +3. **示例交易图**:价格走势 + 网格线 + 买卖点标记 + +## 输出结果 + +1. **控制台输出**:Top 10 参数组合及其指标 +2. **图表文件**: + - `heatmap.png` - 参数热力图 + - `distribution.png` - 收益分布 + - `example_trade.png` - 示例交易 + +## 验证方法 + +1. 运行 `python grid_optimizer.py` +2. 检查输出的Top 10参数组合是否合理 +3. 查看生成的可视化图表 + +## 实现步骤 + +1. 创建 `grid_optimizer/` 目录 +2. 实现 `grid_optimizer.py` 主文件 +3. 运行测试验证结果 diff --git a/freqtrade/templates/freqaiprimer.py b/freqtrade/templates/freqaiprimer.py index a77c08a4..1ec3720a 100644 --- a/freqtrade/templates/freqaiprimer.py +++ b/freqtrade/templates/freqaiprimer.py @@ -763,7 +763,10 @@ class FreqaiPrimer(IStrategy): pass # 输出诊断日志 - ml_prob_str = f"{entry_prob:.2f}" if entry_prob is not None else "N/A" + if entry_prob is not None: + ml_prob_str = f"{entry_prob:.2f}" + else: + ml_prob_str = "N/A" self.strategy_log( f"[入场诊断] {metadata['pair']} | " f"价格: {current_close:.6f} | " @@ -983,6 +986,10 @@ class FreqaiPrimer(IStrategy): market_state = str(last_row.get('market_state', 'unknown')) # 输出诊断日志 + if entry_prob is not None: + ml_prob_str = f"{entry_prob:.2f}" + else: + ml_prob_str = "N/A" self.strategy_log( f"[入场诊断] {pair} | " f"价格: {current_close:.6f} | " @@ -992,7 +999,7 @@ class FreqaiPrimer(IStrategy): f"RSI: {rsi_1h:.1f} | " f"MACD: {macd_cross} | " f"市场: {market_state} | " - f"ML入场概率: {entry_prob:.2f if entry_prob is not None else 'N/A'}" + f"ML入场概率: {ml_prob_str}" ) # ========== 诊断统计结束 ========== @@ -1115,10 +1122,14 @@ class FreqaiPrimer(IStrategy): ) allow_exit = False else: + if future_vol_signal is not None: + future_vol_str = f"{future_vol_signal:.2f}" + else: + future_vol_str = "N/A" self.strategy_log( f"[{pair}] ML 审核官允许出场: exit_signal 概率 {exit_prob:.2f} >= 动态阈值 {dynamic_threshold:.2f}" f" | 出场原因: {exit_reason} | 持仓: {trade_age_minutes:.1f}min, 利润: {current_profit:.4f}" - f" | 波动率AI: {future_vol_signal if future_vol_signal is not None else 'N/A'}" + f" | 波动率AI: {future_vol_str}" ) except Exception as e: logger.warning(f"[{pair}] ML 审核官出场检查失败,允许出场: {e}")