|
只有刷新或更换图表窗口,指标箭头才能出现,请老师给修复一下。 //+------------------------------------------------------------------+ //| 猎杀-修复版_低滞后指标.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; } //+------------------------------------------------------------------+ |
指标发布