在 MQL4 和 MQL5 框架下开发 OpenAI  的 ChatGPT 功能·综合运用
📘

在 MQL4 和 MQL5 框架下开发 OpenAI 的 ChatGPT 功能·综合运用

第 3/3 篇

◍ 布林带与相对ATR的底层算路

这段实现里,布林带中轨先用一段收盘价的简单求和取平均(prevBB),等价于把首值当成普通 SMA 处理;随后对同样区间跑第二遍循环,逐根把 (收盘价 - prevBB) 的平方累加到 sumSquares,最后 standardDeviation = sqrt(sumSquares / PeriodBB)。上下轨则挂在 prevEMA 上:upperBand = prevEMA + DeviationBB * standardDeviation,lowerBand = prevEMA - DeviationBB * standardDeviation。 相对 ATR 的写法值得留意:它在 True Range 求和之外,额外累加每根 K 线的开高低收四价之和 sumPrice,再用 100.0 * (sumTrueRange / PeriodATR) / (sumPrice / (PeriodATR * 4.0)) 得到百分比形式的波动率。相比传统 ATR 绝对值,这种相对值在高价贵金属与低价交叉盘之间更有可比性,但外汇和贵金属杠杆高,波动率突变时信号可能快速失效。 下面两段是核心片段,可直接贴进 MT5 自定义指标或 EA 里验证:第一块算布林带,第二块算相对 ATR。开 MT5 把 PeriodBB、DeviationBB、PeriodATR 调成你常用的参数,看上下轨与百分比 ATR 是否符合盘感。

MQL5 / C++
class="type">class="kw">double sumSquares = class="num">0.0;
class=class="str">"cmt">// Calculate the initial value for BB(the first value is considered as a normal SMA)
for (class="type">int i = StartIndex; i >= barIndex; i--) {
  class="type">class="kw">double closePrice = Charts[chartindex].CloseI[i];
  sum += closePrice;
}
prevBB = sum / PeriodBB; class=class="str">"cmt">//this is the starting value for the bar(StartIndex-class="num">1)

class=class="str">"cmt">// Calculation of standard deviation
for (class="type">int i = StartIndex; i >= barIndex; i--) {
  class="type">class="kw">double closePrice = Charts[chartindex].CloseI[i];
  sumSquares += pow(closePrice - prevBB, class="num">2);
}
class="type">class="kw">double standardDeviation = sqrt(sumSquares / PeriodBB);

class=class="str">"cmt">// Calculate Bollinger Bands
class="type">class="kw">double upperBand = prevEMA + DeviationBB * standardDeviation;
class="type">class="kw">double lowerBand = prevEMA - DeviationBB * standardDeviation;

rez.upper = upperBand;
rez.middle = prevEMA;
rez.lower = lowerBand;

LastUpdateDateTime = TimeCurrent();
class="kw">return rez;
}
class=class="str">"cmt">//class="num">5 Function for calculating Average True Range(Relative)
class="type">class="kw">double calculateRelativeATR(class="type">int PeriodATR,class="type">int Shift=class="num">0)
{
  class="type">int barIndex = Shift+class="num">1; class=class="str">"cmt">// bar index ATR is calculated for (with a shift)
  class="type">int StartIndex = barIndex + PeriodATR - class="num">1; class=class="str">"cmt">// starting bar index for calculating the first ATR
  if (StartIndex >= LastBars) class="kw">return -class="num">1.0; class=class="str">"cmt">// Check for the availability of the bars for calculating ATR and True Range(if not valid, then the value is -class="num">1)

  class="type">class="kw">double sumPrice=class="num">0.0;
  class="type">class="kw">double sumTrueRange = class="num">0.0;
  class="type">class="kw">double ATR;

  class=class="str">"cmt">// Calculating True Range for bars and the sum of values for calculating the first ATR
  for (class="type">int i = StartIndex; i >= barIndex; i--)
  {
    sumPrice+=Charts[chartindex].HighI[i]+Charts[chartindex].LowI[i]+Charts[chartindex].CloseI[i]+Charts[chartindex].OpenI[i];class=class="str">"cmt">//added by me 
    class="type">class="kw">double high = Charts[chartindex].HighI[i];
    class="type">class="kw">double low = Charts[chartindex].LowI[i];
    class="type">class="kw">double trueRange = high - low;
    sumTrueRange += trueRange;
  }

  class=class="str">"cmt">// ATR calculation
  class=class="str">"cmt">//ATR = sumTrueRange / PeriodATR; - conventional calculation
  ATR = class="num">100.0 * (sumTrueRange / PeriodATR)/(sumPrice/(PeriodATR*class="num">4.0));class=class="str">"cmt">//calculation of relative ATR in %

  LastUpdateDateTime = TimeCurrent();
  class="kw">return ATR;
}

用持仓遍历和指标边界卡死开平仓

这段逻辑先把当前账户里所有持仓扫一遍,避免同一魔术码(MagicF)重复开仓。用 PositionGetTicket 按索引取 ticket,再 PositionSelectByTicket 选中,比对 POSITION_MAGIC 相等就置 bOpened=true 并直接返回 false,说明已经有同策略单在跑。 开多条件被收得很窄:必须没有同魔术码持仓,且 EMA 已算出(EMAValues[1]>0)。核心过滤是收盘价相对 EMA 的偏离 Val1 要大于 0 且小于 ATR*(1/K),同时 RSI[1] 低于 RSIPercentBorder——也就是价格在均线上方但不远离、动量还没过热时才倾向进场。 平仓看 bCloseBuy:当 SMA1 有效时,若收盘价跌破 SMA1 或刺穿布林带上轨,就返回 true 触发 CloseBuyF。最后在主流程里依次跑指标重算、平买、平卖、开买、开卖四个判断,顺序固定。 外汇与贵金属杠杆高,这套边界参数 K 和 RSIPercentBorder 若乱填,可能在震荡里频繁挨耳光,上 MT5 用策略测试器先跑历史段再动真金。

MQL5 / C++
    for ( class="type">int i=class="num">0; i<PositionsTotal(); i++ )
      {
      ticket=PositionGetTicket(i);
      ord=PositionSelectByTicket(ticket);
      if ( ord && PositionGetInteger(POSITION_MAGIC) == MagicF)
        {
        bOpened=true;
        class="kw">return class="kw">false;
        }
      }

    if (!bOpened && EMAValues[class="num">1] > class="num">0.0)class=class="str">"cmt">//only if nothing is open and the indicator has been calculated 
      {
      class=class="str">"cmt">//K - control ratio
      class=class="str">"cmt">//RSIPercentBorder - control RSI
      class="type">class="kw">double Val1=Charts[chartindex].CloseI[class="num">1]-EMAValues[class="num">1];
      class="type">class="kw">double Val2=ATRValues[class="num">1]*(class="num">1.0/K);
      if (Val1 > class="num">0 && Val1 < Val2 && RSIValues[class="num">1] < RSIPercentBorder) class="kw">return true;      
      }
    class="kw">return class="kw">false;
    }
  class=class="str">"cmt">//to close a buy position
  class="type">bool bCloseBuy()
    {
    if (SMA1Values[class="num">1] > class="num">0.0)
      {
      if (Charts[chartindex].CloseI[class="num">1] < SMA1Values[class="num">1] || Charts[chartindex].CloseI[class="num">1] > BollingerBandsUpperValues[class="num">1] )
        {
        class="kw">return true;
        }
      }
    class="kw">return class="kw">false;  
    }
  IndicatorDataRecalculate();class=class="str">"cmt">//recalculate indicators

  if ( bCloseBuy() )
    {
      CloseBuyF();
    }
  if ( bCloseSell() )
    {
      CloseSellF();  
    }
  if ( bBuy() )
    {
      BuyF();
    }
  if ( bSell() )
    {
      SellF();
    }

「多币种优化与结果判读」

MetaTrader 5 优化器支持多币种并行优化,配合模板能力可直接对全部 28 个货币对跑 EA 寻优。相对单品种逐个调参,这种方式的显性好处是自动搜多币种形态、形态权重更高且更跟市场、成交次数因品种互补而更多、整体省去逐品种优化时间。 代价也直接:单品种无法精细优调,若要补这块得加附加逻辑,不在本篇范围。跑完优化不等于结束,从输出集里挑对结果才是关键。 我取过一组较优解:H4 周期,样本 2018–2023,并把 2023 全年六个月留作前向验算。优化段权益曲线不算漂亮,但多月盈利交易成立,说明策略并非无意义,存在实盘可用的概率。很多可优化系统连这水平都摸不到。 把 ChatGPT 当开发伙计,不背锅也不神化:编程是必修,数学期望有,模块思维和拆任务能力决定上限。模型必错,但省下的劳动力成本是真的。伙伴强度看你耐心和机变,越会用越值。

◍ 把这条线请下神坛

把 GPT 写 MQL5 这件事请下神坛:它不是一个能替你赚钱的圣杯,只是一个能把你从重复敲代码里拽出来的加速器。作者原话里提过,一开始用「两行给我写个圣杯」的思路只会撞墙,真正好用的是把逻辑拆块、逐函数下指令,比如让模型写 void findSMA(int index){} 比丢一句「写个布林带交叉 EA」有用得多。 评论区有人实测拿 MT5 代码失败、只拿到 MT4 版本,说明模型对 MQL5 语法的覆盖仍有缝隙,最终编译和边界处理还得人肉兜底。外汇与贵金属杠杆极高,用 AI 生成的策略未经严格回测就上实盘,爆仓概率不小。 腾出几个晚上跑通那套 145 KB 的 mq5 示例,比反复追问「能不能稳」更有价值;工具早晚会嵌进开发链,但踩坑的部分永远是你自己的功课。

常见问题

布林带用均值±标准差框出波动通道,相对ATR把通道宽度按真实波幅归一化,避免不同品种量纲乱套;写代码时先算ATR再缩放带宽即可。
遍历持仓先按魔术码和品种过滤,再用指标上破/下破边界做布尔锁,可杜绝重复开;建议打印持仓计数日志用复盘验证。
小布能直接读你导出的多币种优化表,标出夏普偏低和过拟合的品种,并给出该删哪条参数线的建议,省去手动翻表。
看样本外窗口收益衰减和参数敏感度:衰减超30%或微调就翻车的基本是过拟合,优先留平坦区参数。
布林带只是波动容器不是方向预言,单边市会连续假突破;把它当仓位尺度而非入场神谕,配合ATR控手数更稳。