有好工具,才能充分发掘技术交易的潜力。
而经验、判断力以及好的交易计算机程序所提供的数学层级,则是杰出交易者不可或缺的工具。
William Blau
本文的第一部分 - <William Blau 的 MQL5 指标与交易系统。第一部分:指标>,是对技术指标与摆动指标的描述,详见 William Blau 下述书中内容 《动量、方向和背离》。
本文中所述之技术指标与摆动指标,均作为 MQL5 语言中的源代码呈现,且已附到归档文件 "Blau_Indicators_MQL5_en.zip" 中。
William Blau 提出的关键分析理念
William Blau 的技术分析由四个阶段构成:
本文讲解下述几组指标:
针对每组指标如下显示:
真实强弱指数部分包含:
William Blau 将指数平滑移动平均线 (EMA) 作为平滑方法使用。而“指数移动平均线”则通过向移动平均线的前一值添加当前价的特定百分比计算得出。
使用 EMA 时,最新价格的权重较大。
EMA 的计算函数:
EMA(k,n) = EMA(k-1,n) + 2/(n+1) * (price(k) - EMA(k-1,n)) = price(k) * 2/(n+1) + EMA(k-1,n) * (1 - 2/(n+1))
其中:
四种移动平均线类型及其在技术分析中使用方法的描述(亦见 iMA),请见《MetaTrader 5 帮助》(“分析/技术指标/趋势指标/移动平均线”)。
函数库
移动平均线计算函数的库位于 "MovingAverages.mqh"。我们关心的是 ExponentialMAOnBuffer(),它会用输入数组 price[] 的 EMA 值填写输出数组 buffer[]。但是,"MovingAverages.mqh" 中所示的 ExponentialMAOnBuffer() 的实施有一个缺点,那就是在周期 n = 1 时不运行。
参见源代码:
if(period<=1 || rates_total-begin<period) return(0);
但是,William Blau 在书中是用平滑周期 n = 1 表示没有平滑。
由此,ExponentialMAOnBuffer() 函数的代码出现了一些变化:
if(period<1 || rates_total-begin<period) return(0);
而我们则得到了 ExponentialMAOnBufferWB()。此函数的代码位于 "WilliamBlau.mqh" 文件中。
"WilliamBlau.mqh" 文件中亦包含下述函数:
string PriceName( const int applied_price // 价格类型 )
int CalculatePriceBuffer( const int applied_price, // 价格类型 const int rates_total, // 柱形数量 const int prev_calculated, // 最近一次调用计算的柱形 const double &Open[], // Open[] const double &High[], // High[] const double &Low[], // Low[] const double &Close[], // Close[] double &Price[] // 计算价格数组 )
价格图表应用的价格类型及时间表
William Blau 考虑到了日时间表的收盘价。本文中制定的指标允许您选择价格类型(参见价格常量),并根据指标的时间表选择价格图表的时间表(参见图表时间表)。
要探讨的指标(参见附件):
1.1. 动量
内置技术指标动量的相关描述及其技术分析用途,均载于“分析/技术指标/摆动指标/动量” 《MetaTrader 5 帮助》部分(亦见 iMomentum)。与标准的动量 (iMomentum) 相比,William Blau 动量会将动量作为绝对价格变化进行计算。
《MQL5:创建自己的指标》一文中,有 William Blau 关于“真实强弱指标” (TSI) MQL5 实施的一个示例。
1.1.1. 利用动量指标进行的技术分析
技术分析的对象,即金融工具的价格图表。图表中的每个元素都是一个价格柱。价格柱具备下述特性:开盘时间、开盘价、最高价、最低价、收盘价、交易量及其它。价格柱会形成并体现某特定离散时间周期(图表时间表)内的价格行为。
价格图表技术分析的任务,就是确定价格变化的当前趋势,揭示价格峰值底值,并预测未来时间周期内的价格变化走向。这里复杂的地方在于价格 - 在其基本走向的限制内移动的同时,生成了多个方向的波动,从而形成了所谓的价格噪声。
William Blau 的主张内容。第一项差异:动量。William Blau 将动量作为每 [日] 价格变化 [收盘] 的相对值进行计算;而且创建了动量指标。从数学的角度来看,该动量函数是价格的一阶导数。
图 1.1.动量指标(q 周期动量)
动量会显示一天周期内的价格波动,呈现整个周期内价格变化的速度(量级)和方向,但它不会体现价格变动的整体趋势,也不会确定趋势反转点。
第二种差异在于平滑。动量移动平均线(日价格波动的累积和)几乎是曲线价格主变量与局部变量两者的精确重现。子窗口 I、 II 中的图 1.2 (a) 所示即为平滑动量(分别是周期为 20 和 300 的移动平均线)。
移动平均线的周期越高,平滑动量就越能精确地接近(重现)价格曲线的波动。从数学的角度来看,动量的平滑函数是动量的整函数,或是价格的恢复函数。
图 1.2 (a).动量指标(平滑 q 周期动量)
图 1.2 (b).动量指标(平滑 q 周期动量)
在图 1.2 (a) 的主窗口中,展示的是平滑 EMA (周期为 5, 20, 100)指标。移动平均线周期内一个轻微的增加导致了一次延迟,而移动平均线实际上已经不能再重现价格曲线的波动了。
第三个差异是再平滑。 动量的第一次平滑定义了价格变动的总体趋势和反转点,但未能消除噪声。要消除价格噪声,就需要针对移动平均线的一个小 周期执行再平滑。
图 1.2 (b) 子窗口 I 中展示的是平滑动量指标(移动平均线周期为 20),子窗口 II 和 III 中展示的是双平滑与三平滑动量(移动平均线周期为 5, 3)。重复平滑会消除价格噪声,但也会向曲线添加少许平移(延迟)。
第四项差异:走向变化信号方面的差异。带有一个小平均线周期的动量平滑,可能会导致平滑动量于价格曲线趋势的背离。
图 1.2 (a) 的子窗口 I 以及图 1.2 (b) 的子窗口 I、II、III 中可见差异(价格变动的方向,与平滑动量中的变化方向有所背离)。这种差异往往意味着走向变化。从数学的角度来看,该背离是平滑周期的一个函数。
我们只要考量超买或超卖区域的背离,就能改善作为趋势改变信号的上述差异解释的可靠性(参见 п. 1.2.1)。
1.1.2. 动量的定义
动量是指一种相对的价格变动。
动量的标志会指明价格变动的方向:正动量 - 整个周期价格上涨;负动量 - 整个周期价格下滑。动量的量级 - 价格变动的相对速度(价格的一阶导数)。
图 1.3.动量的定义
动量公式:
mtm(price) = price - price[1]
其中:
William Blau 将动量作为当前周期价格 [收盘] 与前一周期价格 [收盘] 的差异进行检查。William Blau 在其单周期动量的计算过程中,采用的是两个周期的价格(当前周期与前一周期)。
我们引入公式以计算某一周期指标的动量,q - 指计算中涉及的时间周期的数量(按 William Blau 的设置,q = 2)。
q 周期动量公式:
mtm(price,q) = price - price[q-1]
其中:
在生成的公式中,我们的两个周期动量对应的是 William Blau 的单周期相对动量。
平滑 q 周期动量公式:
Mtm(price,q,r,s,u) = EMA(EMA(EMA( mtm(price,q) ,r),s),u)
其中:
1.2.1. 利用“真实强弱指数”进行技术分析
续:参见章节 1.1.1 的开头。
第五:标准化。通过平滑动量值的标准化实现单一标度(映射至区间 [-1, +1]),允许我们确定市场的超买或超卖状态。利用标准化平滑动量的值重复乘以系数 100,就能将数值系列转换为百分比范围(映射至区间 [-100, 100])。
图 1.4.标准化平滑动量
如果标准化的平滑动量处于超买或超卖状态,则作为走向变动信号的背离可被视为可靠。
1.2.2. “真实强弱指数”的定义
真实强弱指数 (TSI) - 是标准化动量的一个指标(标准化 q 周期动量)。将平滑动量的值加到单标度(映射至区间 [-1, +1]),再配以平滑动量每个值的标准化(平滑 q 周期价格波动的累积和) - 利用平滑动量值,取绝对值。
乘以系数 100,显示区间变为 [-100, +100] (百分比)。标准化允许将 TSI 值解释为超买(积极)或超卖(消极)市场的量。
“真实强弱指数”公式:
100 * EMA(EMA(EMA( mtm(price,q) ,r),s),u) 100 * Mtm(price,q,r,s,u) TSI(price,q,r,s,u) = –––––––––––––––––––––––––------–––––––––– = ––––––––––––––––------––––––––––––––– EMA(EMA(EMA( |mtm(price,q)| ,r),s),u) EMA(EMA(EMA( |mtm(price,q)| ,r),s),u)
if EMA(EMA(EMA(|mtm(price,q)|,r),s),u)=0, then TSI(price,q,r,s,u)=0
其中:
1.3.1. 利用遍历摆动指标进行技术分析
续:参见下述章节开头 1.1.1, 1.2.1.
第六:超买与超卖市场区域。单位区间 [-1, +1] 或百分比区间 [-100.100],标准化平滑动量值在上述区间内的变化,允许您定义超买或超卖市场区域。
而表现超买或超卖市场状态特征的技术分析指数类,被称为摆动指标。 每个摆动指标的水平,都在接收到一个超买或超卖市场信号时被确定。摆动指标于趋势市场无效,因为该市场可能处于任意长度周期的某种超买/超卖状况下。
第七:信号线。要获取某个趋势结束或价格变动反转点的相关信号,就要用到信号线。如果主线由下到上穿越了信号线,则会收到买入信号。如果主线由上到下穿越了信号线,则会收到买入信号。如果有条主线 - 则为遍历(真实强弱指数),那么遍历的再平滑则会形成一条信号线。该再平滑流程等同于遍历平滑的最后一次过程。
第八:价格变动的走向。如果主线(遍历)从信号线上方通过,则价格变动的走向为上行(上涨趋势)。如果主线(遍历)从信号线下方通过,则价格变动的走向为下行(下滑趋势)。
图 1.5.遍历摆动指标
1.3.2. 遍历摆动指标的定义
Ergodic(price,q,r,s,u) = TSI(price,q,r,s,u)
SignalLine(price,q,r,s,u,ul) = EMA( Ergodic(price,q,r,s,u) ,ul)
其中:
1.4. 代码(详述)
1.4.1. "Blau_Mtm.mq5" - 指标 Mtm(price,q,r,s,u) - 动量
指标 Mtm (price,q,r,s,u) 的代码:
//+------------------------------------------------------------------ //| Blau_Mtm.mq5 | //| Copyright 2011, MetaQuotes Software Corp. | //| https://www.mql5.com | //+------------------------------------------------------------------ #property copyright "Copyright 2011, MetaQuotes Software Corp." // 版权 #property link "https://www.mql5.com" // url #property description "q-period Momentum (William Blau)" // 描述 #include <WilliamBlau.mqh> // 包含文件 (terminal_data_folder\MQL5\Include) //--- 指标设置 #property indicator_separate_window // 指标显示在独立窗口 #property indicator_buffers 5 // 使用的缓存数量 #property indicator_plots 1 // 绘图图形个数 //--- 绘制 #0主图形 #property indicator_label1 "Mtm" // #0绘图图形的标签 #property indicator_type1 DRAW_LINE // 画线 #property indicator_color1 Blue // 颜色 #property indicator_style1 STYLE_SOLID // 线形 - 实线 #property indicator_width1 1 // 线宽 //--- 输入参数 input int q=2; // Momentum 的周期q input int r=20; // r - 1st EMA,应用于Momentum input int s=5; // s - 2nd EMA,应用于 1st EMA input int u=3; // u - 3rd EMA,应用于 2nd EMA input ENUM_APPLIED_PRICE AppliedPrice=PRICE_CLOSE; // AppliedPrice - 价格类型 //--- 动态数组 double MainBuffer[]; // u-周期 3rd EMA(绘制#0图形) double PriceBuffer[]; // 价格数组 double MtmBuffer[]; // q-周期动量 double EMA_MtmBuffer[]; // r-周期1st EMA double DEMA_MtmBuffer[]; // s-周期 2nd EMA //--- 全局变量 int begin1, begin2, begin3, begin4; // 数据的起始索引 int rates_total_min; // 最小柱形数量 //+------------------------------------------------------------------ //| 自定义指标初始化函数 | //+------------------------------------------------------------------ int OnInit() { //--- 指标缓存 // plot buffers // 绘制 #0图形 SetIndexBuffer(0,MainBuffer,INDICATOR_DATA); // u-周期的 3rd EMA // 缓存,用于计算的中间过程 SetIndexBuffer(1,PriceBuffer,INDICATOR_CALCULATIONS); // 价格缓存 SetIndexBuffer(2,MtmBuffer,INDICATOR_CALCULATIONS); // q-周期动量 SetIndexBuffer(3,EMA_MtmBuffer,INDICATOR_CALCULATIONS); // r-周期 1st EMA SetIndexBuffer(4,DEMA_MtmBuffer,INDICATOR_CALCULATIONS); // s-周期 2nd EMA /* //--- 图形绘制 #0 (主) PlotIndexSetString(0,PLOT_LABEL,"Mtm"); // 标签 PlotIndexSetInteger(0,PLOT_DRAW_TYPE,DRAW_LINE); // 画线 PlotIndexSetInteger(0,PLOT_LINE_COLOR,Blue); // 线的颜色 PlotIndexSetInteger(0,PLOT_LINE_STYLE,STYLE_SOLID); // 线形 PlotIndexSetInteger(0,PLOT_LINE_WIDTH,1); // 线宽 */ //--- 精度 IndicatorSetInteger(INDICATOR_DIGITS,_Digits); //--- begin1=q-1; // - MtmBuffer[] begin2=begin1+r-1; // 或 =(q-1)+(r-1) - EMA_MtmBuffer[] begin3=begin2+s-1; // 或 =(q-1)+(r-1)+(s-1) - DEMA_MtmBuffer[] begin4=begin3+u-1; // 或 =(q-1)+(r-1)+(s-1)+(u-1) - MainBuffer[] // rates_total_min=begin4+1; // 最小数量 //---绘制#0图形的开始索引 PlotIndexSetInteger(0,PLOT_DRAW_BEGIN,begin4); //--- 指标简称 string shortname=PriceName(AppliedPrice)+","+string(q)+","+string(r)+","+string(s)+","+string(u); IndicatorSetString(INDICATOR_SHORTNAME,"Blau_Mtm("+shortname+")"); //--- 初始化完成 return(0); } //+------------------------------------------------------------------ //| 自定义指标迭代函数 | //+------------------------------------------------------------------ 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 &TickVolume[], // Tick成交量 const long &Volume[], // 真实成交量 const int &Spread[] // 点差 ) { int i,pos; //--- 检查柱形 if(rates_total<rates_total_min) return(0); //--- 计算PriceBuffer[] CalculatePriceBuffer( AppliedPrice, // 应用的价格 rates_total, // 所有柱形数量 prev_calculated, // 前一次计算的柱形 Open,High,Low,Close, // Open[], High[], Low[], Close[] 数组 PriceBuffer // 价格缓存 ); //--- 计算q-周期动量 if(prev_calculated==0) // 首次调用 { pos=begin1; // 从begin1开始计算所有值 for(i=0;i<pos;i++) // pos 值 MtmBuffer[i]=0.0; // 置零值 } else pos=prev_calculated-1; // 否则仅重算最近一个值 // 计算MtmBuffer[] for(i=pos;i<rates_total;i++) MtmBuffer[i]=PriceBuffer[i]-PriceBuffer[i-(q-1)]; //--- EMA 平滑 // r-周期 1st EMA ExponentialMAOnBufferWB( rates_total, // 所有柱形 prev_calculated, // 前一次计算的柱形 begin1, // 起始索引 r, // 平滑周期 MtmBuffer, // 输入数组 EMA_MtmBuffer // 输出数组 ); // s-周期 2nd EMA ExponentialMAOnBufferWB(rates_total,prev_calculated,begin2,s,EMA_MtmBuffer,DEMA_MtmBuffer); // u-周期 3rd EMA(绘制#0图形) ExponentialMAOnBufferWB(rates_total,prev_calculated,begin3,u,DEMA_MtmBuffer,MainBuffer); //--- OnCalculate函数结束。返回prev_calculated的值用于下一次调用 return(rates_total); } //+------------------------------------------------------------------
我们更仔细地讲讲它们。
《MQL5 参考》中有哪些要读的指标设置相关内容:
#property copyright "Copyright 2011, MetaQuotes Software Corp." // 版权 #property link "https://www.mql5.com" // url #property description "q-period Momentum (William Blau)" // 描述
仅通过 #property 预处理程序指令进行的设置。版本(copyright 与 link 参数)、版本(version 参数)和 mql5 程序的描述(description 参数),均显示于指标窗口的 "Properties" 中("Properties" 选项卡、"Additional" 选框)。
#include <WilliamBlau.mqh> // 包含文件 (terminal_data_folder\MQL5\Include)
预处理程序会利用 "WilliamBlau.mqh" 文件中的内容,替换 #Include <WilliamBlau.mqh> 行。尖括号表明 "WilliamBlau.mqh" 文件要从终端数据文件处获取。更多详情,请见包含文件。
根据 "WilliamBlau.mqh" 文件的目录查看介绍。
自定义指标 - 几种图形绘制。指标的图形绘制,既可以显示于价格图表的主窗口,亦可单独窗口显示。每个图形绘制都有特定的绘图方法、颜色、风格和粗细。
图形标绘渲染所用的数据,来自指标缓冲区(每个图形标绘都对应着一到五个指标缓冲区)。我们利用一个指标数组作为一个指标缓冲区。
要设置指标,则有必要(参见图 1.6):
图 1.6.动量指标 Mtm (price,q,r,s,u)
指标设置的执行:
更多详情,请参见《指标属性与对应函数之间的关系》。
设置指标的两种方法的区别在于,如果通过 #property 指令,在指标附至价格图表之前就可以使用;而通过专用函数则要等到指标附至价格图表之后才可以。设置的配置由指标的 "Properties" 窗口执行。
#property indicator_separate_window // 指标显示在独立窗口
配置为强制填写,而且只能通过 #property 预处理程序指令。指标显示有两个选项:
#property indicator_buffers 5 // 使用的缓存数量 #property indicator_plots 1 // 绘图图形个数
配置为强制填写,而且只能通过 #property 预处理程序指令。指标缓冲区的数量(indicator_buffers 参数)和图形标绘的数量(indicator_plots 参数)没有限制。
//--- 动态数组 double MainBuffer[]; // u-周期 3rd EMA(绘制#0图形) double PriceBuffer[]; // 价格数组 double MtmBuffer[]; // q-周期动量 double EMA_MtmBuffer[]; // r-周期1st EMA double DEMA_MtmBuffer[]; // s-周期 2nd EMA
指标数组会在全局层面作为一维的双精度类型动态数组声明。
// 绘制 #0图形 SetIndexBuffer(0,MainBuffer,INDICATOR_DATA); // u-周期的 3rd EMA // 缓存,用于计算的中间过程 SetIndexBuffer(1,PriceBuffer,INDICATOR_CALCULATIONS); // 价格缓存 SetIndexBuffer(2,MtmBuffer,INDICATOR_CALCULATIONS); // q-周期动量 SetIndexBuffer(3,EMA_MtmBuffer,INDICATOR_CALCULATIONS); // r-周期 1st EMA SetIndexBuffer(4,DEMA_MtmBuffer,INDICATOR_CALCULATIONS); // s-周期 2nd EMA
此代码被写入事件处理程序 Init() 的 OnInit() 函数中。
而指标缓冲区与对应一维数组的链接,则利用 SetIndexBuffer() 函数进行设置:
bool SetIndexBuffer( int index, // 指标缓存索引(从0开始) double buffer[], // 动态数组 ENUM_INDEXBUFFER_TYPE data_type // 数据类型,保存在指标数组中 );
指标缓冲区是一种一维双精度类型 动态数组,大小由客户端控制,以使其始终与指标计算所依据的柱数相符。指标缓冲区的索引从 0 开始。
指标缓冲区可以存储三种数据类型:INDICATOR_DATA, INDICATOR_COLOR_INDEX, INDICATOR_CALCULATIONS。据其显示方法,每个图形标绘都可以对应一到五个指标缓冲区:一到四为指标缓冲区值(数据类型 INDICATOR_DATA),还有一个颜色缓冲区(数据类型 INDICATOR_COLOR_INDEX。)
带有 INDICATOR_CALCULATIONS 类型数据的指标缓冲区,专为中间计算而设计。绑定后,指标数组的索引就和传统数组差不多了(参见下文 1.4.1.2 部分)。
针对每组图形标绘的配置,指定下述事项:
配置方式有两种可能:
1) 通过 #property 预处理程序指令(实施如下):
//--- 图形绘制 #0 (主) #property indicator_label1 "Mtm" // #0图形的标签 #property indicator_type1 DRAW_LINE // 绘图类型: DRAW_LINE - 线条 #property indicator_color1 Blue // 线的颜色 - Blue #property indicator_style1 STYLE_SOLID // 线风格:STYLE_SOLID - 实线 #property indicator_width1 1 // 线宽
2) 利用图形标绘属性设置的一组函数 - PlotIndexSetDouble()、PlotIndexSetInteger()、PlotIndexSetString():
//--- 图形绘制 #0 (主) PlotIndexSetString(0,PLOT_LABEL,"Mtm"); // 标签 PlotIndexSetInteger(0,PLOT_DRAW_TYPE,DRAW_LINE); // 画线 PlotIndexSetInteger(0,PLOT_LINE_COLOR,Blue); // 线的颜色 PlotIndexSetInteger(0,PLOT_LINE_STYLE,STYLE_SOLID); // 线形 PlotIndexSetInteger(0,PLOT_LINE_WIDTH,1); // 线宽
此代码被写入事件处理程序 Init() 的 OnInit() 函数中。PlotIndexSet *() 函数的指定:
bool PlotIndexSetDouble|Integer|String( int plot_index, // 绘图图形的索引 int prop_id, // 图形属性的标识符 double|int,char,bool,color|string prop_value // 属性的新值 );
为改进选定类型图标标绘的显示,我们采用 ENUM_PLOT_PROPERTY 枚举中列出的图形标绘属性 ID。
图形标绘的索引从 0 开始。至于通过 #property 指令进行配置有何益处,请参见上文的《指标参数设置》部分。有些图形标绘属性(颜色、风格、线宽)可通过指标的 "Properties" 窗口("Colors" 选项卡)进行更改。
//--- 精度 IndicatorSetInteger(INDICATOR_DIGITS,_Digits);
此代码被写入事件处理程序 Init() 的 OnInit() 函数中。指标设置配置函数 IndicatorSet * () 的指定:
bool IndicatorSetDouble|Integer|String( int prop_id, // 指标属性的ID double|int,color|string prop_value // 属性的新值 );
指标属性的标识符,均于 ENUM_CUSTOMIND_PROPERTY 枚举中列出。
指标值的显示精度只能通过 IndicatorSetInteger() 函数、INDICATOR_DIGITS 指标属性的 ID 以及 ENUM_CUSTOMIND_PROPERTY_INTEGER 枚举指定。
在一个指标缓冲区正要渲染、值已显示的示例中:邻近指标的短名称、在一个弹出消息中、当鼠标指针置于指标线上方时 - 将被取整为位数 - 该指标所附的工具价格小数点后的位数。
渲染 William Blau q 周期动量的数据,分四步形成:
第 1 步,根据来自 PriceBuffer[] 价格数组的数据计算出动量(周期 q)。q 周期动量的值被存放于 MtmBuffer[] 数组中。因为价格数组的索引从 0 开始,价格数组中的有效数据亦由索引 0 开始,所以,MtmBuffer[] 数组中的有效数据会从索引 (q-1) 开始。
第 2 步,平滑 MtmBuffer[] 数组中的有效数据(平滑周期 r)。q 周期动量的平滑值被存放于 EMA_MtmBuffer[] 数组中。因为 MtmBuffer[] 数组的索引从 0 开始,MtmBuffer[] 数组中的有效数据从索引 (q-1) 开始,所以 EMA_MtmBuffer[] 数组中的有效数据会从索引 (q-1) + (r-1) 开始。
第 3 步和第 4 步,完成类似上述的考量,确定 DEMA_MtmBuffer[] 数组(平滑周期 s)以及 MainBuffer[] 数组(平滑周期 u)中的有意义数据从哪个柱开始。参见图 1.7。
图 1.7.Mtm (price,q,r,s,u) 指标的有意义数据
在全局层面声明这些变量:
//--- 全局变量 int begin1, begin2, begin3, begin4; // 数据的起始索引
变量的值 - 是柱的索引,从此开始即为有意义数据,对应变量指标数组。变量值于函数 OnInit() (事件处理程序 Init)中计算,且会被用于 Calculate 事件处理程序的 OnCalculate() 函数中。
//--- begin1=q-1; // - MtmBuffer[] begin2=begin1+r-1; // 或 =(q-1)+(r-1) - EMA_MtmBuffer[] begin3=begin2+s-1; // 或 =(q-1)+(r-1)+(s-1) - DEMA_MtmBuffer[] begin4=begin3+u-1; // 或 =(q-1)+(r-1)+(s-1)+(u-1) - MainBuffer[] // rates_total_min=begin4+1; // 最小数量 //---绘制#0图形的开始索引 PlotIndexSetInteger(0,PLOT_DRAW_BEGIN,begin4);
利用 PlotIndexSetInteger() 函数、指标属性 PLOT_DRAW_BEGIN 枚举 ENUM_PLOT_PROPERTY_INTEGER 标识符指定图形标绘不显示的初始柱的数量。
//--- 指标简称 string shortname=PriceName(AppliedPrice)+","+string(q)+","+string(r)+","+string(s)+","+string(u); IndicatorSetString(INDICATOR_SHORTNAME,"Blau_Mtm("+shortname+")");
此代码被写入事件处理程序 Init() 的 OnInit() 函数中。只能利用 IndicatorSetString() 函数、指标属性 INDICATOR_SHORTNAME (ENUM_CUSTOMIND_PROPERTY_STRING 枚举)的标识符,来指定指标的短名称。PriceName () 函数会返回价格类型的名称 - 根据 AppliedPrice 输入参数的值。PriceName () 函数的代码位于 "WilliamBlau.mqh" 文件中(参见《简介》)。
//--- 输入参数 input int q=2; // Momentum 的周期q input int r=20; // r - 1st EMA,应用于Momentum input int s=5; // s - 2nd EMA,应用于 1st EMA input int u=3; // u - 3rd EMA,应用于 2nd EMA input ENUM_APPLIED_PRICE AppliedPrice=PRICE_CLOSE; // AppliedPrice - 价格类型
更多详情,请见输入变量。输入参数可通过指标的 "Properties" 窗口("Inputs" 选项卡)进行更改。
计算指标 Mtm(price,q,r,s,u) 的算法:
指标值的计算,在 Calculate 事件处理程序的 OnCalculate() 函数中执行。我们采用第二种形式的 OnCalculate() 函数调用。
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 &TickVolume[], // Tick成交量 const long &Volume[], // 真实成交量 const int &Spread[] // 点差 ) { //--- //--- OnCalculate函数结束。返回prev_calculated的值用于下一次调用 return(rates_total); }
rates_total 自变量是价格图表会被渲染且可供指标处理的柱数。prev_calculated - 是当前OnCalculate() 函数开始调用时该指标处理的价格图表的柱数。
OnCalculate() - 函数返回该指标在当前调用结束时处理的价格图表的柱数。此函数会返回 rates_total 参数且必须如此构建,即,在第一次调用时,价格图表所有未被处理的柱都要被处理。
也就是说,如果第一次调用 OnCalculate() 函数时,prev_calculated 参数等于 0,那么到第二次调用时,prev_calculated 参数或者等于 rates_total、或者等于 rates_total +1,而且从第二次调用开始,OnCalculate() 函数只处理(计入)最后一个柱。想要更加深入的例证解析,请看这里。
指标缓冲区与 Time[]、Open[]、High[]、Low[]、Close[]、TickVolume[]、Volume[] 及 Spread[] 数组,都默认从左到右、从数组开头到结尾、从最老到最新数据的索引方向。第一个元素的索引等于 0。指标缓冲区的大小由客户端控制,以使其始终与指标计算所依柱数相符。
//--- 检查柱形 if(rates_total<rates_total_min) return(0);
全局变量 rates_total_min 是指标输入时间序列的最小值,通过 Init 事件处理程序的 OnInit() 函数计算得出。
rates_total_min=begin4+1; // 指标输入数组的最小尺寸
//--- 计算价格数组PriceBuffer[] CalculatePriceBuffer( AppliedPrice, // 价格类型 rates_total, // 输入时间序列的尺寸 prev_calculated, // 前次调用时计算的柱形 Open,High,Low,Close, // Open[], High[], Low[], Close[] PriceBuffer // 计算价格数组 );
要填充 PriceBuffer[] 价格数组,则使用 CalculatePriceBuffer() 函数。CalculatePriceBuffer() 函数的代码位于 "WilliamBlau.mqh" 文件中(参见《简介》)。价格类型于输入参数 AppliedPrice 中指定。
pos 局部变量 是指标会根据当前调用的 OnCalculate() 函数从此开始的柱索引。我们将带有 MtmBuffer[] 数组准备阶段的 pos 变量的计算,与 MtmBuffer[] 数组非有效元素归零阶段的计算合并起来。
//--- 计算q-周期动量 if(prev_calculated==0) // 首次调用 { pos=begin1; // 从begin1开始计算所有值 for(i=0;i<pos;i++) // pos 值 MtmBuffer[i]=0.0; // 置零值 } else pos=prev_calculated-1; // 否则仅重算最近一个值 // 计算MtmBuffer[] for(i=pos;i<rates_total;i++) MtmBuffer[i]=PriceBuffer[i]-PriceBuffer[i-(q-1)];
q 周期动量是作为当前周期 PriceBuffer[i] 与前面各周期 PriceBuffer[i-(q-1)] 的 price(q-1) 之间的差异进行计算的。
//--- EMA 平滑 // r-周期 1st EMA ExponentialMAOnBufferWB( rates_total, // 所有柱形 prev_calculated, // 前一次计算的柱形 begin1, // 起始索引 r, // 平滑周期 MtmBuffer, // 输入数组 EMA_MtmBuffer // 输出数组 ); // s-周期 2nd EMA ExponentialMAOnBufferWB(rates_total,prev_calculated,begin2,s,EMA_MtmBuffer,DEMA_MtmBuffer); // u-周期 3rd EMA(绘制#0图形) ExponentialMAOnBufferWB(rates_total,prev_calculated,begin3,u,DEMA_MtmBuffer,MainBuffer);
ExponentialMAOnBuffer() 函数在简介中已经讲过。根据 r 周期移动第一次 EMA 的计算示例:ExponentialMAOnBuffer() 函数会利用 MtmBuffer[] 输入数组的 EMA (r) 值来填充 EMA_MtmBuffer[] 输出数组;而且直到索引 (begin1-1) (含)的非有效数据,均用零值填充。
1.4.2. "Blau_TSI.mq5" - 指标 TSI(price,q,r,s,u) - 真实强弱指数
TSI (price,q,r,s,u) 指标代码(基于代码 "Blau_Mtm.mq5" 的变更与添加构建):
//+------------------------------------------------------------------ //| Blau_TSI.mq5 | //| Copyright 2011, MetaQuotes Software Corp. | //| https://www.mql5.com | //+------------------------------------------------------------------ #property copyright "Copyright 2011, MetaQuotes Software Corp." // 版权 #property link "https://www.mql5.com" // URL #property description "True Strength Index (William Blau)" // 描述 #include <WilliamBlau.mqh> // 包含文件 (terminal_data_folder\MQL5\Include) //--- 指标设置 #property indicator_separate_window // 指标显示在独立窗口 #property indicator_buffers 10 // 使用的缓存数量 #property indicator_plots 1 // 绘图图形个数 //--- 水平级别 #property indicator_level1 -25 // 水平 #0 (垂直坐标) #property indicator_level2 25 // 水平 #1 (垂直坐标) #property indicator_levelcolor Silver // 级别颜色 #property indicator_levelstyle STYLE_DOT // 水平线类型 #property indicator_levelwidth 1 // 宽度 //--- 指标的最小/最大值 #property indicator_minimum -100 // 最小 #property indicator_maximum 100 // 最大 //--- 图形绘制 #0 (主) #property indicator_label1 "TSI" // #0图形的标签 #property indicator_type1 DRAW_LINE // 画线 #property indicator_color1 Blue // 线的颜色 #property indicator_style1 STYLE_SOLID // 线形 #property indicator_width1 1 // 线宽 //--- 输入参数 input int q=2; // Momentum 的周期q input int r=20; // r - 1st EMA,应用于Momentum input int s=5; // s - 2nd EMA,应用于首次平滑 input int u=3; // u - 3rd EMA,应用于二次平滑 input ENUM_APPLIED_PRICE AppliedPrice=PRICE_CLOSE; // AppliedPrice - 价格类型 //--- 动态数组 double MainBuffer[]; // TSI(#0绘图图形) double PriceBuffer[]; // 价格数组 double MtmBuffer[]; // q-周期动量 double EMA_MtmBuffer[]; // r-周期1st EMA double DEMA_MtmBuffer[]; // s-周期 2nd EMA double TEMA_MtmBuffer[]; // u-周期 3rd EMA double AbsMtmBuffer[]; // q-周期蜡烛线动量(绝对值) double EMA_AbsMtmBuffer[]; // r-周期1st EMA(绝对值) double DEMA_AbsMtmBuffer[]; // s-周期 2nd EMA(绝对值) double TEMA_AbsMtmBuffer[]; // u-周期 3rd EMA (绝对值) //--- 全局变量 int begin1, begin2, begin3, begin4; // 起始索引 int rates_total_min; // 最小柱形数量 //+------------------------------------------------------------------ //| 自定义指标初始化函数 | //+------------------------------------------------------------------ int OnInit() { //--- 指标缓存 // 绘制 #0图形 SetIndexBuffer(0,MainBuffer,INDICATOR_DATA); // TSI // 用于计算的中间过程的缓存(不是用来绘图的) SetIndexBuffer(1,PriceBuffer,INDICATOR_CALCULATIONS); // 价格数组 SetIndexBuffer(2,MtmBuffer,INDICATOR_CALCULATIONS); // q-周期动量 SetIndexBuffer(3,EMA_MtmBuffer,INDICATOR_CALCULATIONS); // r-周期 1st EMA SetIndexBuffer(4,DEMA_MtmBuffer,INDICATOR_CALCULATIONS); // s-周期 2nd EMA SetIndexBuffer(5,TEMA_MtmBuffer,INDICATOR_CALCULATIONS); // u-周期 3rd EMA SetIndexBuffer(6,AbsMtmBuffer,INDICATOR_CALCULATIONS); // q-周期动量(绝对值) SetIndexBuffer(7,EMA_AbsMtmBuffer,INDICATOR_CALCULATIONS); // r-周期1st EMA(绝对值) SetIndexBuffer(8,DEMA_AbsMtmBuffer,INDICATOR_CALCULATIONS); // s-周期 2nd EMA(绝对值) SetIndexBuffer(9,TEMA_AbsMtmBuffer,INDICATOR_CALCULATIONS); // u-周期 3rd EMA (绝对值) /* //--- 图形绘制 #0 (主) PlotIndexSetString(0,PLOT_LABEL,"TSI"); // #0图形的标签 PlotIndexSetInteger(0,PLOT_DRAW_TYPE,DRAW_LINE); // 画线 PlotIndexSetInteger(0,PLOT_LINE_COLOR,Blue); // 线的颜色 PlotIndexSetInteger(0,PLOT_LINE_STYLE,STYLE_SOLID); // 线形 PlotIndexSetInteger(0,PLOT_LINE_WIDTH,1); // 线宽 */ //--- 精度 IndicatorSetInteger(INDICATOR_DIGITS,2); /* //--- 水平级别 IndicatorSetInteger(INDICATOR_LEVELS,2); // 指标水平的数量 IndicatorSetDouble(INDICATOR_LEVELVALUE,0,-25); // 水平 #0 IndicatorSetDouble(INDICATOR_LEVELVALUE,1,25); // 水平 #1 IndicatorSetInteger(INDICATOR_LEVELCOLOR,Silver); // 水平颜色 IndicatorSetInteger(INDICATOR_LEVELSTYLE,STYLE_DOT); // 水平线形 IndicatorSetInteger(INDICATOR_LEVELWIDTH,1); // 线宽 IndicatorSetString(INDICATOR_LEVELTEXT,0,"Oversold"); // #0 水平线的描述“超卖” IndicatorSetString(INDICATOR_LEVELTEXT,1,"Overbought"); // #1 水平线的描述“超买” //--- 指标范围 IndicatorSetDouble(INDICATOR_MINIMUM,-100); // 最小 IndicatorSetDouble(INDICATOR_MAXIMUM,100); // 最大 */ //--- begin1=q-1; // - MtmBuffer[], AbsMtmBuffer[] begin2=begin1+r-1; // 或者 =(q-1)+(r-1) - EMA_...[] begin3=begin2+s-1; // 或者 =(q-1)+(r-1)+(s-1) - DEMA_...[] begin4=begin3+u-1; // 或者 =(q-1)+(r-1)+(s-1)+(u-1) - TEMA_...[], MainBuffer[] // rates_total_min=begin4+1; // 最小柱形数量 //---绘制#0图形的开始索引 PlotIndexSetInteger(0,PLOT_DRAW_BEGIN,begin4); //--- 指标简称 string shortname=PriceName(AppliedPrice)+","+string(q)+","+string(r)+","+string(s)+","+string(u); IndicatorSetString(INDICATOR_SHORTNAME,"Blau_TSI("+shortname+")"); //--- 初始化完成 return(0); } //+------------------------------------------------------------------ //| 自定义指标迭代函数 | //+------------------------------------------------------------------ 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 &TickVolume[], // Tick成交量 const long &Volume[], // 真实成交量 const int &Spread[] // 点差 ) { int i,pos; double value1,value2; //--- 检查柱形 if(rates_total<rates_total_min) return(0); //--- 计算PriceBuffer[] CalculatePriceBuffer( AppliedPrice, // 价格类型 rates_total, // 所有柱形数量 prev_calculated, // 前一次计算的柱形 Open,High,Low,Close, // Open[], High[], Low[], Close[] PriceBuffer // 价格缓存 ); //--- 计算 HLM 和 |HLM| if(prev_calculated==0) // 首次调用 { pos=begin1; // 从begin1开始计算所有值 for(i=0;i<pos;i++) // pos { MtmBuffer[i]=0.0; // 置零值 AbsMtmBuffer[i]=0.0; // } } else pos=prev_calculated-1; // 否则仅计算最近一次的值 // 计算 MtmBuffer[] 和 AbsMtmBuffer[] for(i=pos;i<rates_total;i++) { MtmBuffer[i]=PriceBuffer[i]-PriceBuffer[i-(q-1)]; AbsMtmBuffer[i]=MathAbs(MtmBuffer[i]); } //--- EMA 平滑 // r-周期 1st EMA ExponentialMAOnBufferWB( rates_total, // 所有柱形 prev_calculated, // 前一次计算的柱形 begin1, // 起始索引 r, // 平滑周期 MtmBuffer, // 输入数组 EMA_MtmBuffer // 输出数组 ); ExponentialMAOnBufferWB(rates_total,prev_calculated,begin1,r,AbsMtmBuffer,EMA_AbsMtmBuffer); // s-周期 2nd EMA ExponentialMAOnBufferWB(rates_total,prev_calculated,begin2,s,EMA_MtmBuffer,DEMA_MtmBuffer); ExponentialMAOnBufferWB(rates_total,prev_calculated,begin2,s,EMA_AbsMtmBuffer,DEMA_AbsMtmBuffer); // u-周期 3rd EMA ExponentialMAOnBufferWB(rates_total,prev_calculated,begin3,u,DEMA_MtmBuffer,TEMA_MtmBuffer); ExponentialMAOnBufferWB(rates_total,prev_calculated,begin3,u,DEMA_AbsMtmBuffer,TEMA_AbsMtmBuffer); //--- TSI 计算 (绘制 #0图形) if(prev_calculated==0) // 首次调用 { pos=begin4; // 从begin4开始计算所有值 for(i=0;i<pos;i++) // MainBuffer[i]=0.0; // 零值 } else pos=prev_calculated-1; // 否则仅计算最近一次的值 // 计算 MainBuffer[] for(i=pos;i<rates_total;i++) { value1=100*TEMA_MtmBuffer[i]; value2=TEMA_AbsMtmBuffer[i]; MainBuffer[i]=(value2>0)?value1/value2:0; } //--- OnCalculate函数结束。返回prev_calculated的值用于下一次调用 return(rates_total); } //+------------------------------------------------------------------
下面我们只是仔细研究一下代码 "Blau_Mtm.mq5" 的修改与添加。
指标 TSI(price,q,r,s,u) 的配置与指标 Mtm(price,q,r,s,u) 的配置有所区别(见图 1.8):
图 1.8.真实强弱指数 TSI (price,q,r,s,u) 指标
在代码 "Blau_Mtm.mq5" 中完成下述细微修改。
1. mql5 程序的简短描述有变化:
#property description "True Strength Index (William Blau)" // 描述
2. (配置 6 中)图形标绘的数量未增长,绘制方法(DRAW_LINE - 线)、线条颜色(蓝)、线条风格(STYLE_SOLID - 实线)及线宽 (1) 都保留不变,#0 图形标绘的标签已变:
#property indicator_label1 "TSI" // #0图形的标签
3. (配置 7 中)指标值的显示精度已有变化:
IndicatorSetInteger(INDICATOR_DIGITS,2);
4. (配置 11 中)指标的短名称已变:
IndicatorSetString(INDICATOR_SHORTNAME,"Blau_TSI("+shortname+")");
要配置水平等级,必须针对每一等级指定下述内容:
配置方式有两种可能:
1) 利用 #property 预处理程序指令(实施如下)。
//--- 水平级别 #property indicator_level1 -25 // 水平 #0 (垂直坐标) #property indicator_level2 25 // 水平 #1 (垂直坐标) #property indicator_levelcolor Silver // 级别颜色 #property indicator_levelstyle STYLE_DOT // 水平线类型 #property indicator_levelwidth 1 // 宽度
2) 利用一组 IndicatorSet *() 函数:
//--- 水平级别 IndicatorSetInteger(INDICATOR_LEVELS,2); // 指标水平的数量 IndicatorSetDouble(INDICATOR_LEVELVALUE,0,-25); // 水平 #0 IndicatorSetDouble(INDICATOR_LEVELVALUE,1,25); // 水平 #1 IndicatorSetInteger(INDICATOR_LEVELCOLOR,Silver); // 水平颜色 IndicatorSetInteger(INDICATOR_LEVELSTYLE,STYLE_DOT); // 水平线类型 IndicatorSetInteger(INDICATOR_LEVELWIDTH,1); // 水平宽度 IndicatorSetString(INDICATOR_LEVELTEXT,0,"Oversold"); // #0 水平线的描述“超卖” IndicatorSetString(INDICATOR_LEVELTEXT,1,"Overbought"); // #1 水平线的描述“超买”
此代码被写入事件处理程序 Init() 的 OnInit() 函数中。水平等级的索引从 0 开始。要改进水平等级的显示,就要用到 INDICATOR_LEVEL * 指数属性的标识符 - 均于 ENUM_CUSTOMIND_PROPERTY 枚举中列出。
每个等级的描述,都只利用 IndicatorSetString() 函数、INDICATOR_LEVELTEXT 指标属性标识符(ENUM_CUSTOMIND_PROPERTY_STRING 枚举)来设定。等级描述直接置于等级左上方。
通过指标的 "Properties" 窗口("Levels" 选项卡),您可以添加/移除水平等级、更改每个等级的值和描述,以及等级渲染的风格。
配置方式有两种可能:
1) 利用 #property 预处理程序指令(实施如下)。
//--- 指标的最小/最大值 #property indicator_minimum -100 // 最小 #property indicator_maximum 100 // 最大
2) 利用 IndicatorSetDouble() 函数、INDICATOR_MINIMUM 指标属性的标识符以及 INDICATOR_MAXIMUM (ENUM_CUSTOMIND_PROPERTY_DOUBLE 枚举)。
//--- 指标范围 IndicatorSetDouble(INDICATOR_MINIMUM,-100); // 最小 IndicatorSetDouble(INDICATOR_MAXIMUM,100); // 最大
此代码被写入事件处理程序 Init() 的 OnInit() 函数中。独立指标窗口标度的上限和下限,可通过指标 "Properties" 窗口("Scale" 选项卡)进行更改。
配置中的变化“指标数组 -> 指标缓冲区 -> 图形标绘”:
1. (配置 3 中)缓冲区数量有增长:
#property indicator_buffers 10 // 用于指标计算的缓存区数量
2. (配置 4)计算 q 周期动量绝对值所需的指标数组添加:
double AbsMtmBuffer[]; // q-周期蜡烛线动量(绝对值) double EMA_AbsMtmBuffer[]; // r-周期1st EMA(绝对值) double DEMA_AbsMtmBuffer[]; // s-周期 2nd EMA(绝对值) double TEMA_AbsMtmBuffer[]; // u-周期 3rd EMA (绝对值)
MainBuffer[] 数组的目的有改变:
double MainBuffer[]; // TSI(#0绘图图形) double TEMA_MtmBuffer[]; // u-周期 3rd EMA
3. (配置 5 中)“指标数组 -> 指标缓冲区 -> 图形标绘”的连接有变化:
// 绘制 #0图形 SetIndexBuffer(0,MainBuffer,INDICATOR_DATA); // TSI // 用于计算的中间过程的缓存(不是用来绘图的) SetIndexBuffer(1,PriceBuffer,INDICATOR_CALCULATIONS); // 价格数组 SetIndexBuffer(2,MtmBuffer,INDICATOR_CALCULATIONS); // q-周期动量 SetIndexBuffer(3,EMA_MtmBuffer,INDICATOR_CALCULATIONS); // r-周期 1st EMA SetIndexBuffer(4,DEMA_MtmBuffer,INDICATOR_CALCULATIONS); // s-周期 2nd EMA SetIndexBuffer(5,TEMA_MtmBuffer,INDICATOR_CALCULATIONS); // u-周期 3rd EMA SetIndexBuffer(6,AbsMtmBuffer,INDICATOR_CALCULATIONS); // q-周期动量(绝对值) SetIndexBuffer(7,EMA_AbsMtmBuffer,INDICATOR_CALCULATIONS); // r-周期1st EMA(绝对值) SetIndexBuffer(8,DEMA_AbsMtmBuffer,INDICATOR_CALCULATIONS); // s-周期 2nd EMA(绝对值) SetIndexBuffer(9,TEMA_AbsMtmBuffer,INDICATOR_CALCULATIONS); // u-周期 3rd EMA (绝对值)
计算指标 TSI (price,q,r,s,u) 的算法:
算法变化的本质(简述):
//--- 计算 HLM 和 |HLM| if(prev_calculated==0) // 首次调用 { pos=begin1; // 从begin1开始计算所有值 for(i=0;i<pos;i++) // pos { MtmBuffer[i]=0.0; // 置零值 AbsMtmBuffer[i]=0.0; // } } else pos=prev_calculated-1; // 否则仅计算最近一次的值 // 计算 MtmBuffer[] 和 AbsMtmBuffer[] for(i=pos;i<rates_total;i++) { MtmBuffer[i]=PriceBuffer[i]-PriceBuffer[i-(q-1)]; AbsMtmBuffer[i]=MathAbs(MtmBuffer[i]); } //--- EMA 平滑 // r-周期 1st EMA ExponentialMAOnBufferWB( rates_total, // 所有柱形 prev_calculated, // 前一次计算的柱形 begin1, // 起始索引 r, // 平滑周期 MtmBuffer, // 输入数组 EMA_MtmBuffer // 输出数组 ); ExponentialMAOnBufferWB(rates_total,prev_calculated,begin1,r,AbsMtmBuffer,EMA_AbsMtmBuffer); // s-周期 2nd EMA ExponentialMAOnBufferWB(rates_total,prev_calculated,begin2,s,EMA_MtmBuffer,DEMA_MtmBuffer); ExponentialMAOnBufferWB(rates_total,prev_calculated,begin2,s,EMA_AbsMtmBuffer,DEMA_AbsMtmBuffer); // u-周期 3rd EMA ExponentialMAOnBufferWB(rates_total,prev_calculated,begin3,u,DEMA_MtmBuffer,TEMA_MtmBuffer); ExponentialMAOnBufferWB(rates_total,prev_calculated,begin3,u,DEMA_AbsMtmBuffer,TEMA_AbsMtmBuffer);
计算:真实强弱指数 (8-9)
//--- TSI 计算 (绘制 #0图形) if(prev_calculated==0) // 首次调用 { pos=begin4; // 从begin4开始计算所有值 for(i=0;i<pos;i++) // MainBuffer[i]=0.0; // 零值 } else pos=prev_calculated-1; // 否则仅计算最近一次的值 // 计算 MainBuffer[] for(i=pos;i<rates_total;i++) { value1=100*TEMA_MtmBuffer[i]; value2=TEMA_AbsMtmBuffer[i]; MainBuffer[i]=(value2>0)?value1/value2:0; }
1.4.3. "Blau_Ergodic.mq5" - Ergodic(price,q,r,s,u,ul) - 遍历摆动指标
Ergodic (price,q,r,s,u,ul) 指标的代码基于 "Blau_TSI.mq5" 代码的变化:
//+------------------------------------------------------------------ //| Blau_Ergodic.mq5 | //| Copyright 2011, MetaQuotes Software Corp. | //| https://www.mql5.com | //+------------------------------------------------------------------ #property copyright "Copyright 2011, MetaQuotes Software Corp." // 版权 #property link "https://www.mql5.com" // URL #property description "Ergodic Oscillator (William Blau)" // 描述 #include <WilliamBlau.mqh> // 包含文件 (terminal_data_folder\MQL5\Include) //--- 指标设置 #property indicator_separate_window // 指标显示在独立窗口 #property indicator_buffers 11 // 缓存数量 #property indicator_plots 2 // 指标绘图图形个数 //--- 水平级别 #property indicator_level1 -25 // 水平 #0 #property indicator_level2 25 // 水平 #1 #property indicator_levelcolor Silver // 水平颜色 #property indicator_levelstyle STYLE_DOT // 水平类型 #property indicator_levelwidth 1 // 宽度 //--- 最小/最大值 #property indicator_minimum -100 // 最小 #property indicator_maximum 100 // 最大 //--- 图形绘制 #0 (主) #property indicator_label1 "Ergodic" // 绘制#0图形 #property indicator_type1 DRAW_HISTOGRAM // 画直方图 #property indicator_color1 Silver // 直方图颜色 #property indicator_style1 STYLE_SOLID // 线形 #property indicator_width1 2 // 线宽 //--- 绘制 #1图形(信号线) #property indicator_label2 "Signal" // 绘制#1图形 #property indicator_type2 DRAW_LINE // 画线 #property indicator_color2 Red // 线的颜色 #property indicator_style2 STYLE_SOLID // 线形 #property indicator_width2 1 // 线宽 //--- 输入参数 input int q=2; // Momentum 的周期q input int r=20; // r - 1st EMA,应用于Momentum input int s=5; // s - 2nd EMA,应用于首次平滑 input int u=3; // u - 3rd EMA,应用于二次平滑 input int ul=3; // 信号线的ul - 周期 input ENUM_APPLIED_PRICE AppliedPrice=PRICE_CLOSE; // AppliedPrice - 价格类型 //--- 动态数组 double MainBuffer[]; // Ergodic(#0绘图图形) double SignalBuffer[]; // 信号线:ul-周期 EMA,应用于Ergodic(#1绘图图形) double PriceBuffer[]; // 价格数组 double MtmBuffer[]; // q-周期动量 double EMA_MtmBuffer[]; // r-周期 1st EMA double DEMA_MtmBuffer[]; // s-周期 2nd EMA double TEMA_MtmBuffer[]; // u-周期 3rd EMA double AbsMtmBuffer[]; // q-周期蜡烛线动量(绝对值) double EMA_AbsMtmBuffer[]; // r-周期1st EMA(绝对值) double DEMA_AbsMtmBuffer[]; // s-周期 2nd EMA(绝对值) double TEMA_AbsMtmBuffer[]; // u-周期 3rd EMA (绝对值) //--- 全局变量 int begin1, begin2, begin3, begin4, begin5; // 起始索引 int rates_total_min; // 最小柱形数量 //+------------------------------------------------------------------ //| 自定义指标初始化函数 | //+------------------------------------------------------------------ int OnInit() { //--- 指标缓存 // 绘制 #0图形 SetIndexBuffer(0,MainBuffer,INDICATOR_DATA); // Ergodic指标 // 绘制 #1图形 SetIndexBuffer(1,SignalBuffer,INDICATOR_DATA); // 信号线:ul-周期 EMA,应用于Ergodic // 缓存,用于计算的中间过程 SetIndexBuffer(2,PriceBuffer,INDICATOR_CALCULATIONS); // 价格数组 SetIndexBuffer(3,MtmBuffer,INDICATOR_CALCULATIONS); // q-周期动量 SetIndexBuffer(4,EMA_MtmBuffer,INDICATOR_CALCULATIONS); // r-周期 1st EMA SetIndexBuffer(5,DEMA_MtmBuffer,INDICATOR_CALCULATIONS); // s-周期 2nd EMA SetIndexBuffer(6,TEMA_MtmBuffer,INDICATOR_CALCULATIONS); //u-周期 3rd EMA SetIndexBuffer(7,AbsMtmBuffer,INDICATOR_CALCULATIONS); // q-周期蜡烛线动量(绝对值) SetIndexBuffer(8,EMA_AbsMtmBuffer,INDICATOR_CALCULATIONS); // r-周期1st EMA(绝对值) SetIndexBuffer(9,DEMA_AbsMtmBuffer,INDICATOR_CALCULATIONS); // s-周期 2nd EMA(绝对值) SetIndexBuffer(10,TEMA_AbsMtmBuffer,INDICATOR_CALCULATIONS); // u-周期 3rd EMA (绝对值) /* //--- 图形绘制 #0 (主) PlotIndexSetString(0,PLOT_LABEL,"Ergodic"); // #0图形的标签 PlotIndexSetInteger(0,PLOT_DRAW_TYPE,DRAW_HISTOGRAM); // 画直方图 PlotIndexSetInteger(0,PLOT_LINE_COLOR,Silver); // 线的颜色 PlotIndexSetInteger(0,PLOT_LINE_STYLE,STYLE_SOLID); // 线形 PlotIndexSetInteger(0,PLOT_LINE_WIDTH,2); // 线宽 //--- 绘制 #1图形(信号线) PlotIndexSetString(1,PLOT_LABEL,"Signal"); // #1绘图图形标签 PlotIndexSetInteger(1,PLOT_DRAW_TYPE,DRAW_LINE); // 画线 PlotIndexSetInteger(1,PLOT_LINE_COLOR,Red); // 线的颜色 PlotIndexSetInteger(1,PLOT_LINE_STYLE,STYLE_SOLID); // 线形 PlotIndexSetInteger(1,PLOT_LINE_WIDTH,1); // 线宽 */ //--- 精度 IndicatorSetInteger(INDICATOR_DIGITS,2); /* //--- 水平级别 IndicatorSetInteger(INDICATOR_LEVELS,2); // 指标水平的数量 IndicatorSetDouble(INDICATOR_LEVELVALUE,0,-25); // 水平 #0 IndicatorSetDouble(INDICATOR_LEVELVALUE,1,25); // 水平 #1 IndicatorSetInteger(INDICATOR_LEVELCOLOR,Silver); // 水平颜色 IndicatorSetInteger(INDICATOR_LEVELSTYLE,STYLE_DOT); // 水平线形 IndicatorSetInteger(INDICATOR_LEVELWIDTH,1); // 线宽 IndicatorSetString(INDICATOR_LEVELTEXT,0,"Oversold"); // #0 水平线“超卖” IndicatorSetString(INDICATOR_LEVELTEXT,1,"Overbought"); // #1 水平线“超买” //--- 最小/最大值 IndicatorSetDouble(INDICATOR_MINIMUM,-100); // 最小 IndicatorSetDouble(INDICATOR_MAXIMUM,100); // 最大 */ //--- begin1=q-1; // - MtmBuffer[], AbsMtmBuffer[] begin2=begin1+r-1; // 或者=(q-1)+(r-1) - EMA_...[] begin3=begin2+s-1; // 或者 =(q-1)+(r-1)+(s-1) - DEMA_...[] begin4=begin3+u-1; // 或者 =(q-1)+(r-1)+(s-1)+(u-1) - TEMA_...[], MainBuffer[] begin5=begin4+ul-1; // 或者 =(q-1)+(r-1)+(s-1)+(u-1)+(ul-1) - SignalBuffer[] // rates_total_min=begin5+1; // 最小柱形数量 //---绘制#0图形的开始索引 PlotIndexSetInteger(0,PLOT_DRAW_BEGIN,begin4); //--- 绘制#1图形的开始索引 PlotIndexSetInteger(1,PLOT_DRAW_BEGIN,begin5); //--- 指标简称 string shortname=PriceName(AppliedPrice)+","+string(q)+","+string(r)+","+string(s)+","+string(u)+","+string(ul); IndicatorSetString(INDICATOR_SHORTNAME,"Blau_Ergodic("+shortname+")"); //--- 初始化完成 return(0); } //+------------------------------------------------------------------ //| 自定义指标迭代函数 | //+------------------------------------------------------------------ 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 &TickVolume[], // Tick成交量 const long &Volume[], // 真实成交量 const int &Spread[] // 点差 ) { int i,pos; double value1,value2; //--- 所有柱形数量 if(rates_total<rates_total_min) return(0); //--- 计算PriceBuffer[] CalculatePriceBuffer( AppliedPrice, // 价格类型 rates_total, // 所有柱形数量 prev_calculated, // 前次调用时计算的柱形 Open,High,Low,Close, // Open[], High[], Low[], Close[] PriceBuffer // 价格数组 ); //--- 计算 HLM 和 |HLM| if(prev_calculated==0) // 首次调用 { pos=begin1; // 从begin1开始 for(i=0;i<pos;i++) // pos { MtmBuffer[i]=0.0; // 置零值 AbsMtmBuffer[i]=0.0; // } } else pos=prev_calculated-1; // 否则仅计算最近一次的值 // 计算 MtmBuffer[] 和 AbsMtmBuffer[] for(i=pos;i<rates_total;i++) { MtmBuffer[i]=PriceBuffer[i]-PriceBuffer[i-(q-1)]; AbsMtmBuffer[i]=MathAbs(MtmBuffer[i]); } //--- EMA 平滑 // r-周期 1st EMA ExponentialMAOnBufferWB( rates_total, // 所有柱形 prev_calculated, // 前一次计算的柱形 begin1, // 起始索引 r, // 平滑周期 MtmBuffer, // 输入数组 EMA_MtmBuffer // 输出数组 ); ExponentialMAOnBufferWB(rates_total,prev_calculated,begin1,r,AbsMtmBuffer,EMA_AbsMtmBuffer); // s-周期 2nd EMA ExponentialMAOnBufferWB(rates_total,prev_calculated,begin2,s,EMA_MtmBuffer,DEMA_MtmBuffer); ExponentialMAOnBufferWB(rates_total,prev_calculated,begin2,s,EMA_AbsMtmBuffer,DEMA_AbsMtmBuffer); // u-周期 3rd EMA ExponentialMAOnBufferWB(rates_total,prev_calculated,begin3,u,DEMA_MtmBuffer,TEMA_MtmBuffer); ExponentialMAOnBufferWB(rates_total,prev_calculated,begin3,u,DEMA_AbsMtmBuffer,TEMA_AbsMtmBuffer); //---计算Ergodic( 绘制#0图形) if(prev_calculated==0) // 首次调用 { pos=begin4; // 从begin4开始 for(i=0;i<pos;i++) // pos MainBuffer[i]=0.0; // 零值 } else pos=prev_calculated-1; // 否则仅计算最近一个柱形 // 计算 MainBuffer[] for(i=pos;i<rates_total;i++) { value1=100*TEMA_MtmBuffer[i]; value2=TEMA_AbsMtmBuffer[i]; MainBuffer[i]=(value2>0)?value1/value2:0; } //--- 计算信号线( 绘制#1图形) ExponentialMAOnBufferWB(rates_total,prev_calculated,begin4,ul,MainBuffer,SignalBuffer); //--- OnCalculate函数结束。返回prev_calculated的值用于下一次调用 return(rates_total); } //+------------------------------------------------------------------
下面我们只是仔细研究一下代码 "Blau_TSI.mq5" 的修改与添加。
指标 Ergodic (price,q,r,s,u,ul) 的配置与指标 TSI (price,q,r,s,u) 的配置有所区别(见图 1.9):
图 1.9.遍历 (price,q,r,s,u,ul) 指标
"Blau_TSI.mq5" 代码已有如下更改。
1. mql5 程序的简短描述有变化:
#property description "Ergodic Oscillator (William Blau)" // 描述
2. 添加了一个输入参数:
input int ul=3; // 信号线的ul - 周期
3. (配置 11 中)指标的短名称已变:
//--- 指标简称 string shortname=PriceName(AppliedPrice)+","+string(q)+","+string(r)+","+string(s)+","+string(u)+","+string(ul); IndicatorSetString(INDICATOR_SHORTNAME,"Blau_Ergodic("+shortname+")");
1. (配置 2 中)又添加了一个图形标绘(信号线):
#property indicator_plots 2 // 指标绘图图形个数
2. (配置 6 中) a) 改变了第一个图形标绘 #0 "Ergodic" 的属性。
此前,我们使用(标识符 DRAW_LINE)作为行显示的一种方式,现在我们则用来自零线的一个直方图(DRAW_HISTOGRAM,源于 ENUM_DRAW_TYPE 枚举)
更改了线条的显示颜色和线宽:
//--- 图形绘制 #0 (主) #property indicator_label1 "Ergodic" // 绘制#0图形 #property indicator_type1 DRAW_HISTOGRAM // 画直方图 #property indicator_color1 Silver // 直方图颜色 #property indicator_style1 STYLE_SOLID // 线形 #property indicator_width1 2 // 线宽
b) 添加了一个图形标绘 #1 "Signal" (信号线):
//--- 绘制 #1图形(信号线) #property indicator_label2 "Signal" // 绘制#1图形 #property indicator_type2 DRAW_LINE // 画线 #property indicator_color2 Red // 线的颜色 #property indicator_style2 STYLE_SOLID // 线形 #property indicator_width2 1 // 线宽
配置中的变化“指标数组 -> 指标缓冲区 -> 图形结构”:
1. (配置 3 中)缓冲区数量有增长:
#property indicator_buffers 11 // 缓存数量
2. (配置 4 中)添加了一个计算和渲染信号线值所需的指标数组:
double SignalBuffer[]; // 信号线:ul-周期 EMA,应用于Ergodic(#1绘图图形)
3. (配置 5 中)“指标数组 -> 指标缓冲区 -> 图形标绘”的关系有变化:
//--- 指标缓存 // 绘制 #0图形 SetIndexBuffer(0,MainBuffer,INDICATOR_DATA); // Ergodic指标 // 绘制 #1图形 SetIndexBuffer(1,SignalBuffer,INDICATOR_DATA); // 信号线:ul-周期 EMA,应用于Ergodic // 缓存,用于计算的中间过程 SetIndexBuffer(2,PriceBuffer,INDICATOR_CALCULATIONS); // 价格数组 SetIndexBuffer(3,MtmBuffer,INDICATOR_CALCULATIONS); // q-周期动量 SetIndexBuffer(4,EMA_MtmBuffer,INDICATOR_CALCULATIONS); // r-周期 1st EMA SetIndexBuffer(5,DEMA_MtmBuffer,INDICATOR_CALCULATIONS); // s-周期 2nd EMA SetIndexBuffer(6,TEMA_MtmBuffer,INDICATOR_CALCULATIONS); //u-周期 3rd EMA SetIndexBuffer(7,AbsMtmBuffer,INDICATOR_CALCULATIONS); // q-周期蜡烛线动量(绝对值) SetIndexBuffer(8,EMA_AbsMtmBuffer,INDICATOR_CALCULATIONS); // r-周期1st EMA(绝对值) SetIndexBuffer(9,DEMA_AbsMtmBuffer,INDICATOR_CALCULATIONS); // s-周期 2nd EMA(绝对值) SetIndexBuffer(10,TEMA_AbsMtmBuffer,INDICATOR_CALCULATIONS); // u-周期 3rd EMA (绝对值)
因为 MainBuffer[] 数组的索引从 0 开始,所以 MainBuffer[] 数组的有效数据从索引 (q-1)+(r-1)+(s-1)+(u-1) 开始,SignalBuffer[] 数组的有效数据从索引 (q-1)+(r-1)+(s-1)+(u-1)+(ul-1) 开始。
声明了全局变量 begin5:
int begin1, begin2, begin3, begin4, begin5; // 起始索引
计算(完成,更多内容请见 1.4.1.1 部分):
//--- begin1=q-1; // - MtmBuffer[], AbsMtmBuffer[] begin2=begin1+r-1; // 或者=(q-1)+(r-1) - EMA_...[] begin3=begin2+s-1; // 或者 =(q-1)+(r-1)+(s-1) - DEMA_...[] begin4=begin3+u-1; // 或者 =(q-1)+(r-1)+(s-1)+(u-1) - TEMA_...[], MainBuffer[] begin5=begin4+ul-1; // 或者 =(q-1)+(r-1)+(s-1)+(u-1)+(ul-1) - SignalBuffer[] // rates_total_min=begin5+1; // 最小柱形数量 //---绘制#0图形的开始索引 PlotIndexSetInteger(0,PLOT_DRAW_BEGIN,begin4); //--- 绘制#1图形的开始索引 PlotIndexSetInteger(1,PLOT_DRAW_BEGIN,begin5);
计算指标 Ergodic (price,q,r,s,ul) 的算法:
算法中的本质变化(简述) a) (参见第 1 部分)指标输入时间序列最小值要求已变更;b) (参见段落 10)信号线计算已变更。
算法中没有变化:
//--- 所有柱形数量 if(rates_total<rates_total_min) return(0);
全局变量 rates_total_min 的值已变更,(指标输入时间序列的最小值,通过 Init 事件处理程序的 OnInit() 函数计算得出):
rates_total_min=begin5+1; // 指标输入数组的最小尺寸
//--- 计算信号线( 绘制#1图形)
ExponentialMAOnBufferWB(rates_total,prev_calculated,begin4,ul,MainBuffer,SignalBuffer);
将探讨过的指标(参见附件)划分为两个组。
I. 基于随机变量的指标:
II.基于随机动量的指标:
2.1. 基于随机变量的指标
"分析/技术指标/摆动指标/随机摆动指标"部分的《MetaTrader 客户端用户指南》,讲述了内置于MetaTrader 5 客户端的随机摆动指标的技术指标,及其在技术分析中的应用方式(亦请参见 iStochastic。)
2.1.1. George Lane 的随机摆动指标
随机变量、随机摆动指标 (Stochastic, Stochastic Oscillator) - 是一个显示与之前 q 周期价格波动相关价格的指标。而 George Lane 则是该指标的创造者和推广者。
区别:
George Lane 提出的随机指标公式:
price - LL(q)
%K = 100 * -------------
HH(q) - LL(q)
%D = SMA(%k, ul)
其中:
根据 George Lane 的解释,基础理念即为:在某个价格上涨趋势期间(上行走势),价格倾向于靠近之前的最大值停止。如果是在某个价格下滑期间(下行走势),则价格倾向于靠近之前最小值停止。
2.1.2. William Blau 的随机摆动指标
图 2.1.William Blau 基于随机变量的指标
随机变量 - 是当前周期的价格 [收盘] 与之前 q 周期价格波动范围最低点的距离。q 周期随机变量的值会显示为价格平移量 - 相对于 q 周期价格波动范围最低点。q 周期随机变量值为正数或等于零。
图 2.2.随机变量的定义
q 周期随机变量公式:
stoch(price,q) = price - LL(q)
其中:
q 周期随机变量公式:
TStoch(price,q,r,s,u) = EMA(EMA(EMA( stoch(price,q) ,r),s),u)
其中:
2.1.2.2. 随机指数
随机指数指标是标准化的平滑 q-周期随机变量。
平滑 q-周期随机变量的值,被映射至某个百分比格式(区间 [0, 100])。平滑 q-周期随机变量的每个值,均按 q-周期价格范围的值标准化。标准化允许将平滑标准化 q-周期随机变量的值,解释为市场超买/超卖状态的程度。
随机指数公式:
100 * EMA(EMA(EMA( price-LL(q) ,r),s),u) 100 * TStoch(price,q,r,s,u) TStochI(price,q,r,s,u) = ---------------------------------------- = ---------------------------------- EMA(EMA(EMA( HH(q)-LL(q) ,r),s),u) EMA(EMA(EMA( HH(q)-LL(q) ,r),s),u)
if EMA(EMA(EMA(HH(q)-LL(q),r),s),u)=0, then TStochI(price,q,r,s,u)=0
其中:
TStochI(price,q,r,s,u) - 随机指数。规范
随机摆动指标的定义:
TS_Stochastic(price,q,r,s,u) = TStochI(price,q,r,s,u)
SignalLine(price,q,r,s,u,ul) = EMA( TS_Stochastic(price,q,r,s,u) ,ul)
其中:
TS_Stochastic(price,q,r,s,u,ul) - 随机摆动指标。规范
William Blau' 的随机摆动指标包括 George Lane 的随机摆动指标。要在 MetaTrader 5 中实现 TS_Stochastic (William Blau) 与标准随机摆动指标 (George Lane) 的对应,必须指定下述内容:
TS_Stochastic( price=Close, q=KPeriod, r=1, s=1, u=1, ul=DPeriod )
Stochastic( KPeriod=q, DPeriod=ul, Slowing=1, price="Low/High", method="Exponential" )
图 2.3.William Blau 随机摆动指标包含 George Lane 的随机摆动指标
基于 TS_Stochastic (price,q,r,s,u,ul) 指标示例:
1) 指标数组、指标缓冲区与图形标绘之间的关联:
//--- 指标缓存 // 绘制 #0图形 SetIndexBuffer(0,MainBuffer,INDICATOR_DATA); // 快速随机 // 绘制 #1图形 SetIndexBuffer(1,SignalBuffer,INDICATOR_DATA); // 慢速随机:快速随机的ul-周期 EMA // 缓存,用于计算的中间过程 SetIndexBuffer(2,PriceBuffer,INDICATOR_CALCULATIONS); // 价格数组 SetIndexBuffer(3,LLBuffer,INDICATOR_CALCULATIONS); // 最小值(q个柱形) SetIndexBuffer(4,HHBuffer,INDICATOR_CALCULATIONS); // 最大值(q个柱形) SetIndexBuffer(5,StochBuffer,INDICATOR_CALCULATIONS); // q-周期随机指数 SetIndexBuffer(6,EMA_StochBuffer,INDICATOR_CALCULATIONS); // r-周期 1st EMA SetIndexBuffer(7,DEMA_StochBuffer,INDICATOR_CALCULATIONS); // s-周期 2nd EMA SetIndexBuffer(8,TEMA_StochBuffer,INDICATOR_CALCULATIONS); // u-周期 3rd EMA SetIndexBuffer(9,HHLLBuffer,INDICATOR_CALCULATIONS); // q-周期价格波动范围 SetIndexBuffer(10,EMA_HHLLBuffer,INDICATOR_CALCULATIONS); // r-周期 1st EMA (价格范围) SetIndexBuffer(11,DEMA_HHLLBuffer,INDICATOR_CALCULATIONS); // s-周期 2nd EMA(价格范围) SetIndexBuffer(12,TEMA_HHLLBuffer,INDICATOR_CALCULATIONS); // u-周期 3rd EMA(价格范围)
2) q-周期随机指标与 q-周期价格范围的计算算法:
// 计算StochBuffer[], HHLLBuffer[], LLBuffer[], HHBuffer[] for(i=pos;i<rates_total;i++) { // LLBuffer[] - 搜索最低价(q个柱形) // HHBuffer[] - 搜索最高价(q个柱形) min=1000000.0; max=-1000000.0; for(k=i-(q-1);k<=i;k++) { if(min>Low[k]) min=Low[k]; if(max<High[k]) max=High[k]; } LLBuffer[i]=min; HHBuffer[i]=max; // StochBuffer[] - q-周期随机指数 StochBuffer[i]=PriceBuffer[i]-LLBuffer[i]; // HHLLBuffer[] - q-周期价格范围 HHLLBuffer[i]=HHBuffer[i]-LLBuffer[i]; }
2.2. 基于随机动量的指标
图 2.4.William Blau 基于随机动量的指标
2.2.1. 随机动量
随机动量(随机动量,SM) - 是指当前周期价格与之前整个 q 周期的价格范围中间位置的距离。q-周期随机动量的值会呈现价格在价格范围中的位置。
q-周期随机动量的标志会呈现价格相对于 q-周期价格范围中间位置的位置:正随机动量 - 价格在中间点以上;负随机动量 - 价格在中间点以下。
图 2.5.随机动量的定义
q-周期随机动量公式:
sm(price,q) = price - 1/2 * [LL(q) + HH(q)]
其中:
平滑 q-周期随机动量公式:
SM(price,q,r,s,u) = EMA(EMA(EMA( sm(price,q) ,r),s),u)
其中:
2.2.2. 随机动量指数
随机动量指数 (SMI) - 是一个标准化的随机率指标(标准化平滑 q-周期随机动量)。平滑 q-周期随机动量的值,以百分比格式给出(区间 [-100, 100])。
平滑 q-周期随机动量的每个值,均按 q-周期价格波动范围的半数值标准化。标准化允许将 SMI 的值解释为市场的超买水平(正值)或超卖水平(负值)的程度。
随机动量指数公式:
100 * EMA(EMA(EMA( price-1/2*[LL(q)+HH(q)] ,r),s),u) 100 * SM(price,q,r,s,u) SMI(price,q,r,s,u) = ---------------------------------------------------- = ---------------------------------------- EMA(EMA(EMA( 1/2*[HH(q)-LL(q)] ,r),s),u) EMA(EMA(EMA( 1/2*[HH(q)-LL(q)] ,r),s),u)
if EMA(EMA(EMA(1/2*[HH(q)-LL(q)],r),s),u)=0, then SMI(price,q,r,s,u)=0
其中:
2.2.3. 随机摆动指标
随机摆动指标的定义:SM_Stochastic(price,q,r,s,u) = SMI(price,q,r,s,u)
SignalLine(price,q,r,s,u,ul) = EMA( SM_Stochastic(price,q,r,s,u) ,ul)
其中:
2.2.4. 随机摆动指标的代码
SM_Stochastic (price, q, r, s, u, ul):
1) 指标数组、指标缓冲区与图形标绘之间的关联:
//--- 指标缓存 // 绘制 #0图形 SetIndexBuffer(0,MainBuffer,INDICATOR_DATA); // 随机动量指数 // 绘制 #1图形 SetIndexBuffer(1,SignalBuffer,INDICATOR_DATA); // 信号线:ul-周期 EMA,应用于随机动量指数 // 用于计算的中间过程的缓存(不是用来绘图的) SetIndexBuffer(2,PriceBuffer,INDICATOR_CALCULATIONS); // 价格数组 SetIndexBuffer(3,LLBuffer,INDICATOR_CALCULATIONS); // 最低价(q个柱形) SetIndexBuffer(4,HHBuffer,INDICATOR_CALCULATIONS); // 最高价(q个柱形)/s3> SetIndexBuffer(5,SMBuffer,INDICATOR_CALCULATIONS); // q-周期随机动量 SetIndexBuffer(6,EMA_SMBuffer,INDICATOR_CALCULATIONS); // r-周期 1st EMA SetIndexBuffer(7,DEMA_SMBuffer,INDICATOR_CALCULATIONS); // s-周期 2nd EMA SetIndexBuffer(8,TEMA_SMBuffer,INDICATOR_CALCULATIONS); // u-周期 3rd EMA SetIndexBuffer(9,HalfHHLLBuffer,INDICATOR_CALCULATIONS); // 价格范围的一半(q个柱形) SetIndexBuffer(10,EMA_HalfHHLLBuffer,INDICATOR_CALCULATIONS); // r-周期1st EMA(价格范围的一半) SetIndexBuffer(11,DEMA_HalfHHLLBuffer,INDICATOR_CALCULATIONS); // s-周期 2nd EMA (价格范围的一半) SetIndexBuffer(12,TEMA_HalfHHLLBuffer,INDICATOR_CALCULATIONS); // u-周期 3rd EMA (价格范围的一半)
2) q-周期随机动量与 q-周期价格范围一半位置的计算算法:
//--- 计算q-周期随机动量和价格波动范围的一半(q个柱形) if(prev_calculated==0) // 首次调用 { pos=begin1; // 从0开始 for(i=0;i<pos;i++) // pos 值 { SMBuffer[i]=0.0; // 零值 HalfHHLLBuffer[i]=0.0; // LLBuffer[i]=0.0; // HHBuffer[i]=0.0; // } } else pos=prev_calculated-1; // 否则仅计算最近一次的值 //计算SMBuffer[], HalfHHLLBuffer[], LLBuffer[], HHBuffer[] for(i=pos;i<rates_total;i++) { // 计算LLBuffer[] - 查找最低价格(q个柱形) // 计算HHBuffer[] - 查找最高价格(q个柱形) min=1000000.0; max=-1000000.0; for(k=i-(q-1);k<=i;k++) { if(min>Low[k]) min=Low[k]; if(max<High[k]) max=High[k]; } LLBuffer[i]=min; HHBuffer[i]=max; // 计算SMBuffer[] - q-周期随机动量 SMBuffer[i]=PriceBuffer[i]-0.5*(LLBuffer[i]+HHBuffer[i]); // 计算 HalfHHLLBuffer[] - 价格波动范围的一半(q个柱形) HalfHHLLBuffer[i]=0.5*(HHBuffer[i]-LLBuffer[i]); }
将探讨过的指标(参见附件)划分为两个组。
I. 基于市场趋势偏差的指标。
II.基于平滑/异同移动平均线的指标。
3.1. 基于市场趋势偏差的指标。
图 3.1.William Blau 基于市场趋势偏差的指标
3.1.1. 平均偏差指标
趋势平均偏差是指价格与应用于价格的 r 周期 EMA (指数平滑移动平均线)的距离。
市场发展的趋势:应用于价格的 EMA(r) 用于确定价格的上升趋势(指数增长)或下滑趋势(指数下降)。
移动平均线会平滑价格曲线,但移动平均线周期的少许增长会导致延迟,且在价格反转点清晰可见(参见附加的 1.1.1 和图 1.2)。与趋势的平均偏差值会呈现出应用于价格的 EMA(r) 的距离。
与趋势的平均偏差标志会呈现出应用到价格的相对于 EMA(r) 的价格位置:与趋势的正偏差 - 价格高于指数;负偏差 - 价格低于指数。
与趋势平均偏差的公式:
md(price,r) = price - EMA(price,r)
其中:
参见“分析/技术指标/趋势指标”部分中的《客户端 MetaTrader 用户指南》:
Alexander Elder 在其“熊市力量指标”与“牛市力量指标”中使用了类似的指数。参见“分析/技术指标/摆动指标”部分中的《客户端 MetaTrader 用户指南》:
与趋势平均偏差指标(平均偏差指数,MDI) - 是一种与市场趋势的平滑平均偏差。
与趋势平均偏差指标的公式:
MDI(price,r,s,u) = EMA(EMA( md(price,r) ,s),u) = EMA(EMA( price-EMA(price,r) ,s),u)
其中:
3.1.2. 遍历 MDI 摆动指标
遍历 MDI 摆动指标的定义:Ergodic_MDI(price,r,s,u) = MDI(price,r,s,u)
SignalLine(price,r,s,u,ul) = EMA( Ergodic_MDI(price,r,s,u) ,ul)
其中:
3.1.3. 遍历摆动指标的代码
作为示例,我们来研究研究 Ergodic_MDI (price,r,s,u,ul) 指标:
1) 指标数组、指标缓冲区与图形标绘之间的关联:
//--- 指标缓存 // 绘制 #0图形 SetIndexBuffer(0,MainBuffer,INDICATOR_DATA); // Ergodic:u-周期 3rd EMA // 绘制 #1图形 SetIndexBuffer(1,SignalBuffer,INDICATOR_DATA); // 信号线:ul-周期 EMA,应用于Ergodic // 用于计算的中间过程的缓存;不是用来绘图的 SetIndexBuffer(2,PriceBuffer,INDICATOR_CALCULATIONS); // 价格数组 SetIndexBuffer(3,EMA_PriceBuffer,INDICATOR_CALCULATIONS); // r-周期 1st EMA (价格) SetIndexBuffer(4,MDBuffer,INDICATOR_CALCULATIONS); // SetIndexBuffer(5,DEMA_MDBuffer,INDICATOR_CALCULATIONS); // s-周期 2nd EMA
2) 平均偏差计算的算法:
//---计算标准偏差 if(prev_calculated==0) // 首次调用 { pos=begin2; // 从0开始 for(i=0;i<pos;i++) // pos 数据 MDBuffer[i]=0.0; // 零值 } else pos=prev_calculated-1; // 否则仅计算最近一个柱形 // r-周期 1st EMA:计算EMA1_PriceBuffer[] ExponentialMAOnBufferWB(rates_total,prev_calculated,begin1,r,PriceBuffer,EMA_PriceBuffer); // 计算MDBuffer[] for(i=pos;i<rates_total;i++) MDBuffer[i]=PriceBuffer[i]-EMA_PriceBuffer[i];
3.2. 基于平滑/异同移动平均线的指标
图 3.2.William Blau 的指标基于平滑/异同移动平均线
3.2.1. 平滑/异同移动平均线的指标
平滑/异同移动平均线(平滑/异同移动平均线,MACD) - 是两个指数平滑移动平均线之间的区别:应用于价格的快 EMA(s) 和慢 EMA(r)。
MACD 标志会显示快 EMA(s) 相对 EMA(r) 的位置:正 MACD - EMA(s) 在 EMA(r) 上方;负 MACD - EMA(s) 在 EMA(r) 下方。按绝对值更改 MACD:|MACD| 增长表明移动平均线之间有背离,而 |MACD| 下降则表明移动平均线之间有会聚。
平滑/异同移动平均线的公式:
macd(price,r,s) = EMA(price,s) - EMA(price,r)
s < r
其中:
MACD 指标会显示快慢指数平均线(平滑/异同移动平均线)之间的关系。
MACD 指标的公式:
MACD(price,r,s,u) = EMA( macd(price,r,s) ,u) = EMA( EMA(price,s)-EMA(price,r) ,u)
s < r
其中:
3.2.2. 遍历 MACD 摆动指标
遍历 MACD 摆动指标的定义:
Ergodic_MACD(price,r,s,u) = MACD(price,r,s,u)
SignalLine(price,r,s,u,ul) = EMA( Ergodic_MACD(price,r,s,u) ,ul)
其中:
在“分析/技术指标/摆动指标/MACD”部分的《MetaTrader 客户端用户指南》中,讲述的是内置于 MetaTrader 5 客户端中的平滑/异同移动平均线 (MACD),以及其在技术分析中的使用方式(亦见 iMACD。)
对比标准 MACD,William Blau 会采用指数平滑移动平均线(标准 MACD 中采用的是简单移动平均线)。
3.2.3. 遍历 MACD 摆动指标的代码
作为示例,我们来研究研究 Ergodic_MACD (price,r,s,u,ul) 指标:
1) 指标数组、指标缓冲区与图形标绘之间的关联:
//--- 指标缓存 // 绘制 #0图形 SetIndexBuffer(0,MainBuffer,INDICATOR_DATA); // Ergodic:u-周期 3rd EMA // 绘制 #1图形 SetIndexBuffer(1,SignalBuffer,INDICATOR_DATA); // 信号线:ul-周期 EMA,应用于Ergodic // 缓存,用于计算的中间过程 SetIndexBuffer(2,PriceBuffer,INDICATOR_CALCULATIONS); // 价格数组 SetIndexBuffer(3,EMA1_PriceBuffer,INDICATOR_CALCULATIONS); // r - 1st EMA(慢速),应用于价格 SetIndexBuffer(4,EMA2_PriceBuffer,INDICATOR_CALCULATIONS); // s - 2nd EMA(快速),应用于价格 SetIndexBuffer(5,MACDBuffer,INDICATOR_CALCULATIONS); // 移动平均的收敛/发散
2) 平滑/异同移动平均线的算法:
//--- 计算移动平均的收敛/发散 if(prev_calculated==0) // 首次调用 { pos=begin2; // for(i=0;i<pos;i++) // pos MACDBuffer[i]=0.0; // 零值 } else pos=prev_calculated-1; // 否则仅计算最近一次的值 // r-周期 1st EMA:计算EMA1_PriceBuffer[] ExponentialMAOnBufferWB(rates_total,prev_calculated,begin1,r,PriceBuffer,EMA1_PriceBuffer); // s-周期 2nd EMA: 计算EMA2_PriceBuffer[] ExponentialMAOnBufferWB(rates_total,prev_calculated,begin1,s,PriceBuffer,EMA2_PriceBuffer); // 计算MACDBuffer[] for(i=pos;i<rates_total;i++) MACDBuffer[i]=EMA2_PriceBuffer[i]-EMA1_PriceBuffer[i];
3.3. 增加
在根据 William Blau 计算 MDI 摆动指标与 MACD 摆动指标时,不能采用标准化(请参考页面1.2.1, 1.3.1). 因此,遍历 MDI 摆动指标与 MACD 摆动指标不能用于解释市场的超买或超卖程度。
比如说,建议采用 “分析/技术指标/摆动指标/MACD”部分《MetaTrader 客户端用户指南》的 MACD 指标信息:
MACD 亦可用作一个超买/超卖指标。如果较短的移动平均线明显远离较长的移动平均线(即 MACD 升高),则很可能是安全价格过多放开,很快就会返回更加合理的水平。
本例中是通过技术分析的角度。
将探讨过的指标(参见附件)划分为两个组。
图 4.1.William Blau 基于烛形动量的指标(按 q-周期烛形动量绝对值标准化)
图 4.2.William Blau 基于烛形动量的指标(按 q-周期烛形的长度标准化)
4.1. 烛形动量
4.1.1. 烛形动量的定义
动量(参阅段落 1.1) - 是当前价格(通常是今日收盘价)与之前价格(通常是昨天收盘价)之间的差别。该动量可以体现出价格图中任意时间周期的价格变动。
烛形动量(依 William Blau) - 是同一周期内(一个烛形内),收盘价与开盘价之间的差异。烛形动量的标志会指明价格变动的方向:正烛形动量 - 整个周期价格上涨;负烛形动量 - 整个周期价格下滑。
烛形动量的公式:
cmtm = close - open
其中:
从通用性的角度考虑,我们来展开一下烛形动量的定义:
图 4.3.q 周期烛形的定义
q-周期烛形动量公式:
cmtm(price1,price2,q) = price1 - price2[q-1]
其中:
平滑 q-周期烛形动量公式:
CMtm(price1,price2,q,r,s,u) = EMA(EMA(EMA( cmtm(price1,price2,q) ,r),s),u)
其中:
4.2. 标准化烛形动量
4.2.1. 烛形动量指数
烛形动量指数 (CMI) - 是指标准化 q-周期烛形动量。
平滑 q-周期烛形动量的值作为一个百分比给出(映射区间 [-100, 100])。q-周期烛形平滑动量的每个值,均按平滑 q-周期烛形动量的值标准化,取绝对值。标准化允许将 CMI 值解释为市场超买(正值)或超卖(负值)的程度。
烛形动量指数的公式:
100 * EMA(EMA(EMA( cmtm(price1,pric2,q) ,r),s),u) 100 * CMtm(price1,pric2,q,r,s,u) CMI(price1,price2,q,r,s,u) = –––––––––––-------------––––––––-–––––––––––––––– = –––––––––––––––-------------–––-––––––––––––– EMA(EMA(EMA( |cmtm(price1,pric2,q)| ,r),s),u) EMA(EMA(EMA( |cmtm(price1,pric2,q)| ,r),s),u)
if EMA(EMA(EMA(|cmtm(price1,pric2,q)|,r),s),u)=0, then CMI(price1,price2,q,r,s,u)=0
其中:
4.2.2. 烛形指数
烛形指数 (CSI) - 是标准化 q-周期烛形动量(标准化平滑 q-周期烛形动量)标准化的一个指标。平滑 q-周期烛形动量的值作为一个标度百分比给出(映射区间 [-100, 100])。
平滑 q-周期烛形动量的每个值,都按 q-周期价格范围(或按 q-周期烛形的长度)的值标准化。标准化允许将 CSI 值解释为市场超买(正值)或超卖(负值)的程度。
烛形指数的公式:
100 * EMA(EMA(EMA( cmtm(price1,pric2,q) ,r),s),u) 100 * CMtm(price1,pric2,q,r,s,u) CSI(price1,price2,q,r,s,u) = –––––––––––––––––––-–––-------------––––––––––––– = ––––––––––––––––--––-––––––––––––– EMA(EMA(EMA( HH(q)-LL(q) ,r),s),u) EMA(EMA(EMA( HH(q)-LL(q) ,r),s),u)
if EMA(EMA(EMA(HH(q)-LL(q),r),s),u)=0, then CSI(price1,price2,q,r,s,u)=0
其中:
4.3. 烛形的遍历摆动指标
4.3.1. 遍历 CMI 摆动指标
遍历 CMI 摆动指标的定义:Ergodic_CMI(price1,pric2,q,r,s,u) = CMI(price1,pric2,q,r,s,u)
SignalLine(price1,pric2,q,r,s,u,ul) = EMA( Ergodic_CMI(price1,pric2,q,r,s,u) ,ul)
其中:
作为示例,我们来研究研究 Ergodic_CMI (price1,price2,r,s,u,ul) 指标:
1) 指标数组、指标缓冲区与图形标绘之间的关联:
//--- 指标缓存 // 绘制 #0图形 SetIndexBuffer(0,MainBuffer,INDICATOR_DATA); // Ergodic // 绘制 #1图形 SetIndexBuffer(1,SignalBuffer,INDICATOR_DATA); // 信号线: EMA(ul),应用于Ergodic // 缓存,用于计算的中间过程 SetIndexBuffer(2,Price1Buffer,INDICATOR_CALCULATIONS); // 价格数组【收盘价】 SetIndexBuffer(3,Price2Buffer,INDICATOR_CALCULATIONS); // 价格数组【开盘价】 SetIndexBuffer(4,CMtmBuffer,INDICATOR_CALCULATIONS); // q-周期 蜡烛线动量 SetIndexBuffer(5,EMA_CMtmBuffer,INDICATOR_CALCULATIONS); // r-周期 1st EMA SetIndexBuffer(6,DEMA_CMtmBuffer,INDICATOR_CALCULATIONS); // s-周期 2nd EMA SetIndexBuffer(7,TEMA_CMtmBuffer,INDICATOR_CALCULATIONS); // u-周期 3rd EMA SetIndexBuffer(8,AbsCMtmBuffer,INDICATOR_CALCULATIONS); // q-周期蜡烛线动量(绝对值) SetIndexBuffer(9,EMA_AbsCMtmBuffer,INDICATOR_CALCULATIONS); //r-周期1st EMA(绝对值) SetIndexBuffer(10,DEMA_AbsCMtmBuffer,INDICATOR_CALCULATIONS); // s-周期 2nd EMA(绝对值) SetIndexBuffer(11,TEMA_AbsCMtmBuffer,INDICATOR_CALCULATIONS); // u-周期 3rd EMA (绝对值)
2) 计算 cmtm 与 |cmtm| 的算法:
//--- 计算Price1Buffer[] 和 Price2Buffer[] CalculatePriceBuffer( AppliedPrice1, // 应用的价格【收盘价】 rates_total, // 所有柱形数量 prev_calculated, // 前一次调用时计算的柱形编号 Open,High,Low,Close, // Open[], High[], Low[], Close[] Price1Buffer // 目标数组 ); CalculatePriceBuffer(AppliedPrice2,rates_total,prev_calculated,Open,High,Low,Close,Price2Buffer); //--- 计算 cmtm 和 |cmtm| if(prev_calculated==0) // 首次调用 { pos=begin1; // for(i=0;i<pos;i++) // { CMtmBuffer[i]=0.0; // 零值 AbsCMtmBuffer[i]=0.0; // } } else pos=prev_calculated-1; // 否则仅计算最近一次的值 // 计算CMtmBuffer[] and AbsCMtmBuffer[] for(i=pos;i<rates_total;i++) { CMtmBuffer[i]=Price1Buffer[i]-Price2Buffer[i-(q-1)]; AbsCMtmBuffer[i]=MathAbs(CMtmBuffer[i]); }
4.3.2. 遍历 CSI 摆动指标
遍历 CSI 摆动指标定义如下:
Ergodic_CSI(price1,pric2,q,r,s,u) = CSI(price1,pric2,q,r,s,u)
SignalLine(price1,pric2,q,r,s,u,ul) = EMA( Ergodic_CSI(price1,pric2,q,r,s,u) ,ul)
其中:
基于 Ergodic_CSI (price1, price2,r,s,u,ul) 指标示例:
1) 指标数组、指标缓冲区与图形标绘之间的关联:
//--- 指标缓存 // 绘制 #0图形 SetIndexBuffer(0,MainBuffer,INDICATOR_DATA); // Ergodic // 绘制 #1图形 SetIndexBuffer(1,SignalBuffer,INDICATOR_DATA); // 信号线: EMA(ul),应用于Ergodic // 缓存,用于计算的中间过程 SetIndexBuffer(2,Price1Buffer,INDICATOR_CALCULATIONS); // 价格数组【收盘价】 SetIndexBuffer(3,Price2Buffer,INDICATOR_CALCULATIONS); // 价格数组【开盘价】 SetIndexBuffer(4,LLBuffer,INDICATOR_CALCULATIONS); // 最低价(q个柱形) SetIndexBuffer(5,HHBuffer,INDICATOR_CALCULATIONS); // 最高价(q个柱形) SetIndexBuffer(6,CMtmBuffer,INDICATOR_CALCULATIONS); // q-周期 蜡烛线动量 SetIndexBuffer(7,EMA_CMtmBuffer,INDICATOR_CALCULATIONS); // r-周期 1st EMA SetIndexBuffer(8,DEMA_CMtmBuffer,INDICATOR_CALCULATIONS); // s-周期 2nd EMA SetIndexBuffer(9,TEMA_CMtmBuffer,INDICATOR_CALCULATIONS); // u-周期 3rd EMA SetIndexBuffer(10,HHLLBuffer,INDICATOR_CALCULATIONS); // 价格范围(q个柱形) SetIndexBuffer(11,EMA_HHLLBuffer,INDICATOR_CALCULATIONS); // r-周期 1st EMA (价格范围) SetIndexBuffer(12,DEMA_HHLLBuffer,INDICATOR_CALCULATIONS); // s-周期 2nd EMA(价格范围) SetIndexBuffer(13,TEMA_HHLLBuffer,INDICATOR_CALCULATIONS); // u-周期 3rd EMA(价格范围)
2) cmtm 与 q-周期价格范围计算的算法:
//--- 计算Price1Buffer[] 和 Price2Buffer[] CalculatePriceBuffer( AppliedPrice1, // 价格类型【收盘价格】 rates_total, // 所有柱形数量 prev_calculated, // 前一次调用时计算的柱形编号 Open,High,Low,Close, // Open[], High[], Low[], Close[] Price1Buffer // 目标数组 ); CalculatePriceBuffer(AppliedPrice2,rates_total,prev_calculated,Open,High,Low,Close,Price2Buffer); //--- 计算cmtm 和 价格范围(q个柱形) if(prev_calculated==0) // 首次调用 { pos=begin1; // for(i=0;i<pos;i++) // { CMtmBuffer[i]=0.0; // 零值 HHLLBuffer[i]=0.0; // LLBuffer[i]=0.0; // HHBuffer[i]=0.0; // } } else pos=prev_calculated-1; // 否则仅计算最近一次的值 // 计算CMtmBuffer[], HHLLBuffer[], LLBuffer[], HHBuffer[] for(i=pos;i<rates_total;i++) { // CMtmBuffer[] - q-周期蜡烛线动量 CMtmBuffer[i]=Price1Buffer[i]-Price2Buffer[i-(q-1)]; // LLBuffer[] - 搜索最低价(q个柱形) // HHBuffer[] - 搜索最高价(q个柱形) min=1000000.0; max=-1000000.0; for(k=i-(q-1);k<=i;k++) { if(min>Low[k]) min=Low[k]; if(max<High[k]) max=High[k]; } LLBuffer[i]=min; HHBuffer[i]=max; // HHLLBuffer[] - 价格范围(q个柱形) HHLLBuffer[i]=HHBuffer[i]-LLBuffer[i]; }
要探讨的指标(参见附件):
图 5.1.方向趋势指数指标
5.1. 复合高低动量
5.1.1. 上涨趋势与下降趋势动量的定义
趋势定义之一。 如果最高价格的值有增长,则有一个上涨趋势。如果最低价格的值有下降,则有一个下降趋势。
第 1 部分中讨论过的一组动量指标,则可被用于计算价格最大值动量:
Mtm( price=High, q, r, s, u ) TSI( price=High, q, r, s, u ) Ergodic( price=High, q, r, s, u )
亦可用于最低价格的计算:
Mtm( price=Low, q, r, s, u ) TSI( price=Low, q, r, s, u ) Ergodic( price=Low, q, r, s, u )
上涨趋势动量或高动量上行 (HMU) 是当前周期最高价格与 q-周期价格范围开头最高价格之间的正差异。q-周期上涨趋势动量的值,会呈现当前周期最高价格对比 q-周期价格波动范围开头最高价格的相对增长速率。
q-周期上涨趋势动量公式:
HMU(q) = High - High[q-1], if High - High[q-1] > 0
HMU(q) = 0, if High - High[q-1] <= 0
其中:
下降趋势动量或低动量下行 (LMD) 是当前周期最低价格与 q-周期价格波动范围开头最低价格之间的正差异。q-周期下降趋势动量的值,会呈现当前周期最低价格对比 q-周期价格范围开头最低价格的相对下降速率。
q-周期下降趋势动量公式:
LMD(q) = -(Low - Low[q-1]), if Low - Low[q-1] < 0
LMD(q) = 0, if Low - Low[q-1] >= 0
其中:
复合高低动量(高低动量,HLM) - 是 q-周期上涨趋势动量与 q-周期下降趋势动量之间的差异。复合高低动量的标志表明价格变动的趋势:正 HLM - 价格增长趋势(上涨趋势);而负 HLM - 则是价格降低趋势(下降趋势)。
公式:
HLM(q) = HMU(q) - LMD(q)
其中:
q-周期复合高低动量公式(虚拟平仓):
HLM(q,r,s,u) = EMA(EMA(EMA( HLM(q) ,r),s),u) = EMA(EMA(EMA( HMU(q)-HMD(q) ,r),s),u)
其中:
最大值与最小值复杂动量的累积和的曲线图,被称为虚拟平仓。
5.2. 方向趋势指数
5.2.1. “方向趋势指数”的定义
方向趋势指数(方向趋势指数,DTI) - 是标准化 q-周期复合高低动量(标准化平滑 HLM)的一个指标。平滑 HLM 的值作为一个标度百分比给出(显示区间 [-100, 100])。
平滑 HLM 的每个值都按某平滑 HLM 的值进行标准化,取绝对值。标准化允许将 DTI 值解释为市场超买(正值)或超卖(负值)的程度。
方向趋势指数的公式:
100 * EMA(EMA(EMA( HLM(q) ,r),s),u) 100 * HLM(q,r,s,u) DTI(q,r,s,u) = –––––––––––––––––––––––––---––––––– = ––––––––––––––--––––––––––––––– EMA(EMA(EMA( |HLM(q)| ,r),s),u) EMA(EMA(EMA( |HLM(q)| ,r),s),u)
if EMA(EMA(EMA(|HLM(q)|,r),s),u)=0, then DTI(price,q,r,s,u)=0
其中:
5.3. 遍历 DTI 摆动指标
5.3.1. 遍历 DTI 摆动指标的定义:
Ergodic_DTI(q,r,s,u) = DTI(q,r,s,u)
SignalLine(q,r,s,u,ul) = EMA( Ergodic_DTI(q,r,s,u) ,ul)
其中:
5.4. 遍历 DTI 摆动指标的代码
Ergodic_DTI (q,r,s,u,ul) 指标:
1) 指标数组、指标缓冲区与图形标绘之间的关联:
//--- 指标缓存 // 绘制 #0图形 SetIndexBuffer(0,MainBuffer,INDICATOR_DATA); // Ergodic 线 // 绘制 #1图形 SetIndexBuffer(1,SignalBuffer,INDICATOR_DATA); // 信号线: EMA(ul),应用于Ergodic // 缓存,用于计算的中间过程 SetIndexBuffer(2,HMUBuffer,INDICATOR_CALCULATIONS); // q-周期的上升趋势动量 SetIndexBuffer(3,LMDBuffer,INDICATOR_CALCULATIONS); // q-周期的下降趋势动量 SetIndexBuffer(4,HLMBuffer,INDICATOR_CALCULATIONS); // 综合q-周期高/低动量 SetIndexBuffer(5,EMA_HLMBuffer,INDICATOR_CALCULATIONS); // r-周期 1st EMA SetIndexBuffer(6,DEMA_HLMBuffer,INDICATOR_CALCULATIONS); // s-周期 2nd EMA SetIndexBuffer(7,TEMA_HLMBuffer,INDICATOR_CALCULATIONS); // u-周期 3rd EMA SetIndexBuffer(8,AbsHLMBuffer,INDICATOR_CALCULATIONS); // 综合q-周期高/低动量(绝对值) SetIndexBuffer(9,EMA_AbsHLMBuffer,INDICATOR_CALCULATIONS); // r-周期1st EMA(绝对值) SetIndexBuffer(10,DEMA_AbsHLMBuffer,INDICATOR_CALCULATIONS); // s-周期 2nd EMA(绝对值) SetIndexBuffer(11,TEMA_AbsHLMBuffer,INDICATOR_CALCULATIONS); // u-周期 3rd EMA (绝对值)
2) 计算 HLM 与 |HML| 的算法:
//--- 计算 HLM 和 |HLM| if(prev_calculated==0) // 首次调用 { pos=begin1; // for(i=0;i<pos;i++) // { HLMBuffer[i]=0.0; // 零值 AbsHLMBuffer[i]=0.0; // HMUBuffer[i]=0.0; // LMDBuffer[i]=0.0; // } } else pos=prev_calculated-1; // 否则仅计算最近一次的值 // 计算HLMBuffer[], AbsHLMBuffer[], HMUBuffer[], LMDBuffer[] for(i=pos;i<rates_total;i++) { HMUBuffer[i]=High[i]-High[i-(q-1)]; HMUBuffer[i]=(HMUBuffer[i]>0)?HMUBuffer[i]:0; LMDBuffer[i]=-1*(Low[i]-Low[i-(q-1)]); LMDBuffer[i]=(LMDBuffer[i]>0)?LMDBuffer[i]:0; HLMBuffer[i]=HMUBuffer[i]-LMDBuffer[i]; AbsHLMBuffer[i]=MathAbs(HLMBuffer[i]); }
《William Blau 的 MQL5 中的指标与交易系统。第一部分:指标》,是对 MQL5 中开发指标与摆动指标的描述,详见 William Blau 下述书中内容 《动量、方向和背离》。
而上述指标与摆动指标在制定交易决策过程中的使用,则会于《William Blau 的 MQL5 中的指标与交易系统。第二部分:交易系统》中讲到。
本文随附档案 ("Blau_Indicators_MQL5_en.zip") 的目录:
文件 | 说明 |
---|---|
包含文件。位置:"terminal_data_folder\MQL5\Include" | |
WilliamBlau.mqh | |
指标。位置:"terminal_data_folder\MQL5\Indicators" | |
基于动量的指标 | |
Blau_Mtm.mq5 | 动量指标 (q-周期动量、平滑 q-周期动量) |
Blau_TSI.mq5 | 真实强弱指数 (标准化平滑 q-周期动量) |
Blau_Ergodic.mq5 | 遍历摆动指标 (基于真实强弱指数) |
基于随机的指标 | |
Blau_TStoch.mq5 | 随机指标 (q-周期随机指标、平滑 q-周期随机指标) |
Blau_TStochI.mq5 | 随机指数 (标准化平滑 q-周期随机指标) |
Blau_TS_Stochastic.mq5 | 随机 TS 摆动指标 (基于随机指数) |
基于随机动量的指标 | |
Blau_SM.mq5 | 随机动量 (q-周期随机动量,平滑 q-周期随机动量) |
Blau_SMI.mq5 | 随机动量指数(平滑标准化 q-周期随机动量 RSI) |
Blau_SM_Stochastic.mq5 | 随机 SM 摆动指标 (基于随机动量指数) |
基于市场趋势偏差的指标 | |
Blau_MDI.mq5 | 平均偏差指标 (平均偏差、平滑平均偏差) |
Blau_Ergodic_MDI.mq5 | 遍历 MDI 摆动指标 (基于平均偏差指标) |
基于平滑/异同移动平均线的指标 | |
Blau_MACD.mq5 | 平滑/异同移动平均线指标 (MACD,平滑 MACD) |
Blau_Ergodic_MACD.mq5 | 遍历 MACD 摆动指标 (基于 MACD 指标) |
基于烛形动量的指标 | |
Blau_CMtm.mq5 | 烛形动量指标 (q-周期烛形动量、平滑 q-周期烛形动量) |
Blau_CMI.mq5 | 烛形动量指数 (标准化平滑 q-周期烛形动量;按 q-周期烛形动量绝对值的标准化) |
Blau_CSI.mq5 | 烛形指数 (标准化平滑 q-周期烛形动量;按 q-周期烛形烛形长度的标准化) |
Blau_Ergodic_CMI.mq5 | 遍历 CMI 摆动指标 (基于烛形动量指数) |
Blau_Ergodic_CSI.mq5 | 遍历 CSI 摆动指标 (基于烛形指数) |
基于复合动量的指标 | |
Blau_HLM.mq5 | 虚拟平仓指标 (q-周期复合高低动量;平滑 q-周期复合高低动量) |
Blau_DTI.mq5 | 方向趋势指数 (标准化平滑 q-周期复合高低动量) |
Blau_Ergodic_DTI.mq5 | 遍历 DTI 摆动指标 (基于方向趋势指数) |
本社区仅针对特定人员开放
查看需注册登录并通过风险意识测评
5秒后跳转登录页面...
移动端课程