如何利用 MQL5 创建自定义唐奇安(Donchian)通道指标(基础篇)
「用 MQL5 手搓一条唐奇安通道」
唐奇安通道的核心就是取最近 N 根 K 线的最高价与最低价,分别画出上轨和下轨。在 MT5 里做自定义指标,不需要依赖现成脚本,直接写个 CI ndicator 派生类就能跑。 下面这段 MQL5 代码定义了一个 20 周期通道:上轨取 20 根最高价的最大值,下轨取 20 根最低价的最小值。参数 Period 可在加载指标时改,默认 20。 外汇与贵金属波动剧烈,通道突破策略仅代表价格走出近期边界的概率倾向,实盘需自担高风险。
class="macro">#class="kw">property indicator_chart_window class="macro">#class="kw">property indicator_buffers class="num">2 class="macro">#class="kw">property indicator_plots class="num">2 class="macro">#class="kw">property indicator_type1 DRAW_LINE class="macro">#class="kw">property indicator_type2 DRAW_LINE class="macro">#class="kw">property indicator_color1 clrRed class="macro">#class="kw">property indicator_color2 clrBlue input class="type">int Period = class="num">20; class="type">class="kw">double UpperBuffer[]; class="type">class="kw">double LowerBuffer[]; class="type">int OnInit() { SetIndexBuffer(class="num">0, UpperBuffer, INDICATOR_DATA); SetIndexBuffer(class="num">1, LowerBuffer, INDICATOR_DATA); PlotIndexSetInteger(class="num">0, PLOT_DRAW_BEGIN, Period); PlotIndexSetInteger(class="num">1, PLOT_DRAW_BEGIN, Period); class="kw">return(INIT_SUCCEEDED); } class="type">int OnCalculate(const class="type">int rates_total, const class="type">int prev_calculated, const class="type">class="kw">datetime &time[], const class="type">class="kw">double &open[], const class="type">class="kw">double &high[], const class="type">class="kw">double &low[], const class="type">class="kw">double &close[], const class="type">long &tick_volume[], const class="type">long &volume[], const class="type">int &spread[]) { if(rates_total < Period) class="kw">return(class="num">0); class="type">int start = prev_calculated > Period ? prev_calculated - class="num">1 : Period; for(class="type">int i = start; i < rates_total; i++) { class="type">class="kw">double max_high = high[i]; class="type">class="kw">double min_low = low[i]; for(class="type">int j = class="num">0; j < Period; j++) { if(high[i - j] > max_high) max_high = high[i - j]; if(low[i - j] < min_low) min_low = low[i - j]; } UpperBuffer[i] = max_high; LowerBuffer[i] = min_low; } class="kw">return(rates_total); }
为什么先盯唐奇安通道
趋势识别是价格行为交易里绕不开的环节,而唐奇安(Donchian)通道把“N根K线的最高/最低”直接画成轨道,帮交易者一眼看出突破与区间。它不参与预测,只忠实追踪已发生的极端价格,适合作为趋势启动的初筛工具。 后续我们会拆指标定义、改写自定义版本、再把它塞进EA里自动跑。外汇与贵金属波动大、杠杆高,任何通道信号都只是概率参考,实盘前请在MT5策略测试器里先验证。
◍ 唐奇安通道的三条线怎么读
唐奇安通道由 Richard Donchian 提出,本质是一款趋势跟踪的滞后指标:用三条线把价格夹在中间,上轨取最近 N 根 K 线的最高价,下轨取最近 N 根的最低价,中线就是两者均值。 它的核心用法是看突破。当价格向上越过上轨,说明多头动能可能占优,倾向视为买入信号;向下跌破下轨则可能是空头信号。N 的取值直接决定灵敏度,N 越小通道越窄、假突破越多,N 越大越平滑但滞后更明显。 实战中这两条轨道还能当仓位管理的参考价。比如做多时,下轨可设为止损;做空时,下轨又能当止盈目标。上轨则反过来用。外汇和贵金属波动剧烈,用轨道位挂单前最好在 MT5 里用不同 N 值回测一遍再上实盘。 和布林带别搞混:唐奇安只看极端价(最高高、最低低),布林带是基于均加减两倍标准差。两者逻辑不同,混用参数会出乱子。 计算就三步:CH = 最近 N 周期最高高点;CL = 最近 N 周期最低低点;ML = (CH+CL)/2。在 MT5 自定义指标里写这三个数组就能画出通道。
「手搓唐奇安通道指标的三条线」
在 MT5 里自建唐奇安通道,核心是把上轨、下轨、中轨拆成 3 个缓冲区与 3 条绘图序列。源码里写死 indicator_buffers=3、indicator_plots=3,输入参数只留 indPeriod(默认 20)和 indColor(默认蓝),其余交给终端。 自定义函数 indInit 干四件事:用 SetIndexBuffer 把动态数组绑到指标缓冲;用 PlotIndexSetInteger 连发五次设线型、线宽 2、起绘偏移 indPeriod-1、右移 1、颜色;PlotIndexSetString 写标签;PlotIndexSetDouble 设空值为 EMPTY_VALUE。OnInit 里调三次,分别挂 upper / lower / middle。 OnCalculate 先拦 rates_total < indPeriod+1 直接 return 0;start 用三元运算符判断首跑取 20 否则取 prev_calculated-1。for 循环里 upperLine 取 high 数组近 20 根最大值,lowerLine 取 low 近 20 根最小值,中轨即二者均值。 编译零警告后,在导航窗 Indicator 文件夹加载,周期和颜色可改。外汇与贵金属波动剧烈,通道突破仅代表价格可能走出区间,实际触发假突破概率不低,需结合其他信号。
class="macro">#class="kw">property indicator_chart_window class="macro">#class="kw">property indicator_buffers class="num">3 class="macro">#class="kw">property indicator_plots class="num">3 input class="type">int indPeriod=class="num">20; class=class="str">"cmt">//Period input class="type">color indColor=clrBlue; class=class="str">"cmt">//Color class="type">class="kw">double upperBuff[]; class="type">class="kw">double lowerBuff[]; class="type">class="kw">double middleBuff[]; class="type">class="kw">double upperLine,lowerLine,middleLine; class="type">int start, bar; class="type">void indInit(class="type">int index, class="type">class="kw">double &buffer[],class="type">class="kw">string label) { SetIndexBuffer(index,buffer,INDICATOR_DATA); PlotIndexSetInteger(index,PLOT_DRAW_TYPE,DRAW_LINE); PlotIndexSetInteger(index,PLOT_LINE_WIDTH,class="num">2); PlotIndexSetInteger(index,PLOT_DRAW_BEGIN,indPeriod-class="num">1); PlotIndexSetInteger(index,PLOT_SHIFT,class="num">1); PlotIndexSetInteger(index,PLOT_LINE_COLOR,indColor); PlotIndexSetString(index,PLOT_LABEL,label); PlotIndexSetDouble(index,PLOT_EMPTY_VALUE,EMPTY_VALUE); } indInit(class="num">0,upperBuff,"Donchian Channel"); indInit(class="num">1,lowerBuff,"Donchian Channel"); indInit(class="num">2,middleBuff,"Middle Donchian"); IndicatorSetString(INDICATOR_SHORTNAME,"Donchian("+IntegerToString(indPeriod)+")"); if(rates_total<indPeriod+class="num">1) { class="kw">return class="num">0; } start=prev_calculated==class="num">0? indPeriod: prev_calculated-class="num">1; for(bar=start;bar<rates_total;bar++) { upperLine=high[ArrayMaximum(high,bar-indPeriod+class="num">1,indPeriod)]; lowerLine=low[ArrayMinimum(low,bar-indPeriod+class="num">1,indPeriod)]; middleLine=(upperLine+lowerLine)/class="num">2; upperBuff[bar]=upperLine-(upperLine-lowerLine); lowerBuff[bar]=lowerLine+(upperLine-lowerLine); middleBuff[bar]=middleLine; } class="macro">#class="kw">property indicator_chart_window