📅 财经日历 📊 实时波动 📈 大盘云图 📶 行情走势 🆚 投机情绪 🚀 今日热点

    不刷新或不切换窗口箭头就不出现,请各位老师帮忙修复,不胜感激。

    2026-06-12 · 148 阅读
    只有刷新或更换图表窗口,指标箭头才能出现,请老师给修复一下。
    //+------------------------------------------------------------------+
    //|                          猎杀-修复版_低滞后指标.mq4               |
    //|                        版本:最终优化版(无滞后、无报错、实时刷新) |
    //| 修复点:解决不切换周期/窗口,新K线不显示箭头的刷新BUG               |
    //+------------------------------------------------------------------+
    #property strict                  // 强制严格语法检查,避免运行异常
    #property indicator_chart_window // 指标显示在主图窗口
    #property indicator_buffers 6    // 声明6个缓存区(轨道+箭头+计算用)
    #property indicator_color1 Crimson     // 上轨颜色:深红
    #property indicator_color2 ForestGreen// 下轨颜色:森林绿
    #property indicator_color3 Lime       // 做多箭头颜色:亮绿
    #property indicator_color4 Red         // 做空箭头颜色:红色
    #property indicator_color5 Yellow      // 计算用缓存颜色(不显示)
    #property indicator_color6 Yellow      // 计算用缓存颜色(不显示)

    //+------------------------------------------------------------------+
    //|                          输入参数设置                            |
    //+------------------------------------------------------------------+
    input int      Lookback     = 38;    // 高低点回溯周期(推荐25-38,越小越灵敏)
    input int      ATRPeriod    = 14;    // ATR周期(黄金标准14,不建议改)
    input double   ZoneATR      = 0.5;   // 猎杀区宽度系数(0.3-0.8,越大越宽)
    input int      MAPeriod     = 50;    // EMA趋势过滤周期(推荐50,过滤逆势假信号)

    //+------------------------------------------------------------------+
    //|                          指标缓存区声明                          |
    //+------------------------------------------------------------------+
    double UpperZone[];    // 上轨猎杀区(做空信号触发线)
    double LowerZone[];    // 下轨猎杀区(做多信号触发线)
    double BuyArrow[];     // 做多箭头缓存
    double SellArrow[];    // 做空箭头缓存
    double HH_Val[];       // 回溯周期内最高价(计算用缓存)
    double LL_Val[];       // 回溯周期内最低价(计算用缓存)

    //+------------------------------------------------------------------+
    //|                          指标初始化函数                          |
    //+------------------------------------------------------------------+
    int OnInit()
    {
       // 设置轨道线样式
       SetIndexStyle(0,DRAW_LINE,STYLE_SOLID,1);
       SetIndexStyle(1,DRAW_LINE,STYLE_SOLID,1);
       
       // 设置箭头样式(使用系统箭头233/234)
       SetIndexStyle(2,DRAW_ARROW,0,1);
       SetIndexStyle(3,DRAW_ARROW,0,1);
       SetIndexArrow(2,233); // 做多箭头(向上)
       SetIndexArrow(3,234); // 做空箭头(向下)

       // 绑定缓存区到指标
       SetIndexBuffer(0,UpperZone,INDICATOR_DATA);
       SetIndexBuffer(1,LowerZone,INDICATOR_DATA);
       SetIndexBuffer(2,BuyArrow,INDICATOR_DATA);
       SetIndexBuffer(3,SellArrow,INDICATOR_DATA);
       SetIndexBuffer(4,HH_Val,INDICATOR_CALCULATIONS);
       SetIndexBuffer(5,LL_Val,INDICATOR_CALCULATIONS);

       // 设置指标名称
       IndicatorShortName("猎杀-修复版_低滞后");
       return(INIT_SUCCEEDED);
    }

    //+------------------------------------------------------------------+
    //|                          主计算函数(核心逻辑+刷新修复)           |
    //+------------------------------------------------------------------+
    int OnCalculate(const int rates_total,
                    const int prev_calculated,
                    const datetime &time[],
                    const double &open[],
                    const double &high[],
                    const double &low[],
                    const double &close[],
                    const long &tick_volume[],
                    const long &volume[],
                    const int &spread[])
    {
       // 计算起始位置(取Lookback和MAPeriod的最大值,保证数据足够)
       int start = MathMax(Lookback, MAPeriod);
       
       // ========== 核心修复1:每次新Tick强制重算【最新2根K线】 ==========
       // 原逻辑只算增量,当前运行K线不重算,导致箭头不刷新
       int calcStart;
       if(prev_calculated > 0)
       {
          // 已有历史数据:从最后2根K线开始重算,保证实时更新
          calcStart = rates_total - 2;
          if(calcStart < 0) calcStart = 0;
       }
       else
       {
          // 首次加载:从头计算全部K线
          calcStart = 0;
       }

       // 循环处理每一根K线
       for(int i = calcStart; i < rates_total; i++)
       {
          // 1. 计算回溯周期内的高低点(低滞后优化:去掉嵌套循环,改用区间索引)
          if(i < Lookback)
          {
             // 不足回溯周期时,直接取当前K线高低点
             HH_Val[i] = high[i];
             LL_Val[i] = low[i];
          }
          else
          {
             // 调用函数快速获取区间内高低点索引,大幅降低滞后
             HH_Val[i] = high[GetHighestIndex(high, i - Lookback + 1, i)];
             LL_Val[i] = low[GetLowestIndex(low, i - Lookback + 1, i)];
          }

          // 初始化箭头缓存为无信号状态
          BuyArrow[i]  = EMPTY_VALUE;
          SellArrow[i] = EMPTY_VALUE;

          // 2. 计算ATR和猎杀区轨道
          double hh    = HH_Val[i];          // 回溯周期最高价
          double ll    = LL_Val[i];          // 回溯周期最低价
          double atr   = iATR(_Symbol, _Period, ATRPeriod, i); // 当前ATR值
          double zone  = atr * ZoneATR;      // 猎杀区宽度

          // 计算上下轨猎杀区(修复原逻辑:轨道靠近价格,而非远离图表)
          UpperZone[i] = hh - zone; // 上轨:最高价 - 宽度(做空触发线)
          LowerZone[i] = ll + zone; // 下轨:最低价 + 宽度(做多触发线)

          // 3. 计算EMA均线,判断趋势方向
          double ma = iMA(_Symbol, _Period, MAPeriod, 0, MODE_EMA, PRICE_CLOSE, i);
          bool trendUp = close[i] > ma; // 收盘价在EMA上方 → 多头趋势
          bool trendDn = close[i] < ma; // 收盘价在EMA下方 → 空头趋势

          // 4. 判断假突破信号(核心猎杀逻辑:刺破轨道后收回)
          // 做多信号:价格短暂跌破下轨,随后收盘收回轨道内,且在多头趋势中
          bool fakeBreakDown = (low[i] < ll + atr * 0.2 && close[i] > LowerZone[i]);
          // 做空信号:价格短暂突破上轨,随后收盘收回轨道内,且在空头趋势中
          bool fakeBreakUp   = (high[i] > hh - atr * 0.2 && close[i] < UpperZone[i]);

          // 5. 绘制箭头信号
          if(trendUp && fakeBreakDown)
             BuyArrow[i] = low[i] - atr * 0.3; // 做多箭头位置:下轨下方

          if(trendDn && fakeBreakUp)
             SellArrow[i] = high[i] + atr * 0.3; // 做空箭头位置:上轨上方
       }

       // ========== 核心修复2:强制图表实时刷新,新信号立刻渲染 ==========
       ChartRedraw(0);
       
       return rates_total;
    }

    //+------------------------------------------------------------------+
    //|                          辅助函数:获取区间最高价索引             |
    //+------------------------------------------------------------------+
    int GetHighestIndex(const double &arr[], int start, int end)
    {
       int idx = start;
       double max_val = arr[start];
       for(int k = start + 1; k <= end; k++)
       {
          if(arr[k] > max_val)
          {
             max_val = arr[k];
             idx = k;
          }
       }
       return idx;
    }

    //+------------------------------------------------------------------+
    //|                          辅助函数:获取区间最低价索引             |
    //+------------------------------------------------------------------+
    int GetLowestIndex(const double &arr[], int start, int end)
    {
       int idx = start;
       double min_val = arr[start];
       for(int k = start + 1; k <= end; k++)
       {
          if(arr[k] < min_val)
          {
             min_val = arr[k];
             idx = k;
          }
       }
       return idx;
    }
    //+------------------------------------------------------------------+
    ""
    还没有人打赏,支持一下
    回复

    举报

     

    回答|共 6 个

    da1s3da1 LV2

    发表于 2026-6-12 14:04:03 | 显示全部楼层

    这是完整源码 还是片段?

    da1s3da1 LV2

    发表于 2026-6-12 14:09:55 | 显示全部楼层

    改好了 拿去试试

    //+------------------------------------------------------------------+
    //|              猎杀-修复版_低滞后指标.mq4  (索引方向修复版)         |
    //+------------------------------------------------------------------+
    #property strict
    #property indicator_chart_window
    #property indicator_buffers 6
    #property indicator_color1 Crimson
    #property indicator_color2 ForestGreen
    #property indicator_color3 Lime
    #property indicator_color4 Red
    #property indicator_color5 Yellow
    #property indicator_color6 Yellow

    input int      Lookback     = 38;
    input int      ATRPeriod    = 14;
    input double   ZoneATR      = 0.5;
    input int      MAPeriod     = 50;

    double UpperZone[];
    double LowerZone[];
    double BuyArrow[];
    double SellArrow[];
    double HH_Val[];
    double LL_Val[];

    int OnInit()
    {
       SetIndexStyle(0,DRAW_LINE,STYLE_SOLID,1);
       SetIndexStyle(1,DRAW_LINE,STYLE_SOLID,1);
       SetIndexStyle(2,DRAW_ARROW,0,1);
       SetIndexStyle(3,DRAW_ARROW,0,1);
       SetIndexArrow(2,233);
       SetIndexArrow(3,234);

       SetIndexBuffer(0,UpperZone,INDICATOR_DATA);
       SetIndexBuffer(1,LowerZone,INDICATOR_DATA);
       SetIndexBuffer(2,BuyArrow,INDICATOR_DATA);
       SetIndexBuffer(3,SellArrow,INDICATOR_DATA);
       SetIndexBuffer(4,HH_Val,INDICATOR_CALCULATIONS);
       SetIndexBuffer(5,LL_Val,INDICATOR_CALCULATIONS);

       IndicatorShortName("猎杀-修复版_低滞后");
       return(INIT_SUCCEEDED);
    }

    int OnCalculate(const int rates_total,
                    const int prev_calculated,
                    const datetime &time[],
                    const double &open[],
                    const double &high[],
                    const double &low[],
                    const double &close[],
                    const long &tick_volume[],
                    const long &volume[],
                    const int &spread[])
    {
       // ===== 核心修复: 价格数组统一为时间序列(索引0=当前K线) =====
       ArraySetAsSeries(time, true);
       ArraySetAsSeries(open, true);
       ArraySetAsSeries(high, true);
       ArraySetAsSeries(low,  true);
       ArraySetAsSeries(close,true);

       int start = MathMax(Lookback, MAPeriod) + ATRPeriod; // 预留足够数据

       // 要重算多少根(始终包含当前bar i=0)
       int limit;
       if(prev_calculated == 0)
          limit = rates_total - start - 1;
       else
          limit = rates_total - prev_calculated + 1; // 新bar + 重算当前bar
       if(limit > rates_total - start - 1) limit = rates_total - start - 1;
       if(limit < 0) limit = 0;

       // 从较老的新bar 算到 当前bar(i=0), 保证当前bar每tick刷新
       for(int i = limit; i >= 0; i--)
       {
          BuyArrow[i]  = EMPTY_VALUE;
          SellArrow[i] = EMPTY_VALUE;

          // 区间高低点(shift=i为当前, 回溯Lookback根) —— 用内置函数, 方向正确
          int hh_idx = iHighest(_Symbol,_Period,MODE_HIGH,Lookback,i);
          int ll_idx = iLowest (_Symbol,_Period,MODE_LOW ,Lookback,i);
          if(hh_idx < 0 || ll_idx < 0) continue;
          double hh = high[hh_idx];
          double ll = low[ll_idx];
          HH_Val[i] = hh;
          LL_Val[i] = ll;

          double atr  = iATR(_Symbol,_Period,ATRPeriod,i);   // shift=i 现在正确
          double zone = atr * ZoneATR;

          UpperZone[i] = hh - zone;
          LowerZone[i] = ll + zone;

          double ma = iMA(_Symbol,_Period,MAPeriod,0,MODE_EMA,PRICE_CLOSE,i); // shift=i 正确
          bool trendUp = close[i] > ma;
          bool trendDn = close[i] < ma;

          bool fakeBreakDown = (low[i]  < ll + atr*0.2 && close[i] > LowerZone[i]);
          bool fakeBreakUp   = (high[i] > hh - atr*0.2 && close[i] < UpperZone[i]);

          if(trendUp && fakeBreakDown) BuyArrow[i]  = low[i]  - atr*0.3;
          if(trendDn && fakeBreakUp)   SellArrow[i] = high[i] + atr*0.3;
       }

       return rates_total;
    }
    //+------------------------------------------------------------------+

    641386452 LV6

    发表于 2026-6-12 14:19:12 | 显示全部楼层

    da1s3da1 发表于 2026-6-12 14:04
    这是完整源码 还是片段?

    完整原码

    641386452 LV6

    发表于 2026-6-12 14:20:09 | 显示全部楼层

    da1s3da1 发表于 2026-6-12 14:09
    改好了 拿去试试

    //+------------------------------------------------------------------+

    谢谢老师,非常感谢,祝操作赢麻

    da1s3da1 LV2

    发表于 2026-6-12 14:38:23 | 显示全部楼层

    641386452 发表于 2026-6-12 14:20
    谢谢老师,非常感谢,祝操作赢麻

    只想知道这个指标有用吗 你实盘了没 怎么样胜率

    da1s3da1 LV2

    发表于 2026-6-12 14:57:09 | 显示全部楼层

    641386452 发表于 2026-6-12 14:20
    谢谢老师,非常感谢,祝操作赢麻

    代写ea 指标 带需求逻辑预算来 物美价廉!!!!!!!!!!!!!!
    您需要登录后才可以回帖 登录 | 注册

    提醒: 禁止引战、谩骂、灌水内容

    微信二维码

    有问题联系客服