![学习如何基于 VIDYA 设计交易系统](https://c.mql5.com/2/49/learn_how_to_design_trading_system_vidya_600x314.jpg)
学习如何基于 VIDYA 设计交易系统
概述
这是我们系列中的一篇新文章,供初学者学习新的技术工具,以及如何基于简单策略设计交易系统。 它是可变指数动态平均线(VIDYA)指标。 该指标是我们交易时可用的趋势跟踪指标之一,该术语的概念意味着该指标跟随趋势。 因此,它是一个滞后指标,而这意味着它在价格走势之后移动。 我们会通过以下主题涵盖该指标:
如果您打算开发自己的编程技能,可以应用您学到的东西来加深自己的理解,因为实践是任何学习过程中非常重要的一步。 我们将利用 MetaTrader 5 交易终端中内置的 MQL5(MetaQuotes 语言 5),如果您不知道如何下载和使用它们,您可以阅读上一篇文章中的在 MetaEditor 中编写 MQL5 代码主题。
免责声明:所有信息“按原样”提供仅用于教学目的,并非出于交易目的或建议。 这些信息不能保证任何结果。 如果您选择在您的任何交易账户上使用这些材料,您将自行承担风险,您是唯一的责任人。
VIDYA 定义
可变指数动态平均线(VIDYA)是由 Tushar Chande 开发的趋势跟踪指标。 它看起来像指数移动平均线,但它将依据相对价格波动进行动态调整。 波动性由该指标中的钱德(Chande)动量振荡器 (CMO) 通过测量正负走势累计之间的比率来衡量,就像我们在学习如何计算它时看到的那样。 (CMO)用于平滑指数移动平均线。 故此,如同我们将看到那样,我们可以发现该指标的设置参数就是 CMO 周期和 EMA 周期。 它可以与任何移动平均线相同,从而获得趋势类型,譬如它是上升趋势或下降趋势。 如果您打算学习有关趋势类型,以及如何识别它们的更多信息,您可以阅读上一篇文章中的趋势定义主题。 或者您可以用它来生成买入或卖出信号,我们将在浏览 VIDYA 策略的主题时看到一些基于它的简单策略。
现在,我们需要学习如何计算 VIDYA 指标,从而更多地理解其背后的主要概念。 以下步骤是如何手工计算它。
- 计算 EMA:
EMA(i) = Price(i) * F + EMA(i-1)*(1-F)
其中:
EMA(i) = 当期 EMA
Price(i) = 当期价格
F (平滑因子) = 2/(EMA 的周期+1)
EMA(i-1) = 前期 EMA 值
- 计算可变指数动态平均值 (VIDYA) 值:
VIDYA(i) = Price(i) * F * ABS(CMO(i)) + VIDYA(i-1) * (1 - F* ABS(CMO(i)))
其中:
VIDYA(i) = 当期 VIDYA
ABS(CMO(i)) = 钱德动量振荡器的绝对当期值
VIDYA(i-1) = 前期 VIDYA 值
- 计算钱德动量振荡器(CMO):
CMO(i) = (UpSum(i) - DnSum(i))/(UpSum(i) + DnSum(i))
其中:
UpSum(i) = 区间正走势总和的当期值
DnSum(i) = 区间负走势总和的当期值
之后,我们就可得到 VIDYA 指标。 如今,我们不需要手工计算它,但我们可从 MetaTrader 5 交易平台的可用指标中选择它,并插入到图表之中。 此为如何插入它。
插入 --> 指标 --> 趋势 --> 可变指数动态平均线
这会打开以下窗口,其中包含指标参数:
1 - 钱德动量振荡器(CMO)周期
2 - 指数移动平均线(EMA)周期
3 - 价格类型
4 - VIDYA 线的颜色
5 - VIDYA 线的样式
6 - VIDYA 线的宽度
确定所有之前的参数,并按“确定”后,我们会发现附加到图表的指标,如下所示:
正如我们在上一张图表中所见,该指标加载到图表之中,它是一条基于其值和价格走势,位于价格上方或下方的曲线。 当我们看到 VIDYA 线处于价格上方时,这意味着由空头控盘,反之亦然,当 VIDYA 线处于价格下方时,这意味着多头控盘。
VIDYA 策略
在本主题中,我们将学习如何依据该指标的主要概念在简单策略里运用 VIDYA 指标。 最好将此指标与其它技术工具或指标结合运用,从而获得更可靠和更有效的结果。 因为它会从多个角度为您提供更多见解,这是技术分析的特点之一。
我们需要获取趋势类型的信号,譬如它是向上亦或向下,这是基于比较当期收盘价与默认设置(9,12)的 VIDYA 的当期值。 如果当期收盘价高于 VIDYA,我们要求设置一个带有上升趋势的信号。 在另一种情况下,如果当期收盘价低于 VIDYA,我们要求获得具有下降趋势的信号。
当期收盘价 > VIDYA --> 上升趋势
当期收盘价 < VIDYA --> 下降趋势
我们需要比较前一个策略的相同值,来获得买入或卖出信号。 如果当期收盘价高于 VIDYA,我们要求获得买入信号。 反之亦然,如果当期收盘价低于当期 VIDYA,我们要求获得卖出信号。
当期收盘价 > VIDYA --> 买入信号
当期收盘价 < VIDYA --> 卖出信号
我们需要比较设置分别为(9,12)和(20,50)的两条 VIDYA 线,来获得买入或卖出信号。 当 VIDYA(9,12)大于 VIDYA(20,50)时,我们要求获得买入信号。 在另一种场景下,如果当期 VIDYA(9,12)低于当期 VIDYA(20,50),则它是一个卖出信号。
VIDYA (9, 12) > VIDYA (20, 50) --> 买入信号
VIDYA (9, 12) < VIDYA (20, 50) --> 卖出信号
通过前面的三个简单策略,我们依据 VIDYA 指标背后的主要概念,学习到如何运用它。
VIDYA 策略蓝图
在本主题中,我们将设计一个分步蓝图,来帮助我们顺滑地为每个提到的策略创建自己的交易系统。
根据此策略,我们需要创建一个可生成趋势类型信号的交易系统。 我们需要交易系统检查两个值,即当期收盘价和当期 VIDYA 值,来判定趋势类型。 如果当期收盘价大于 VIDYA 值,则表明趋势上升。
故此,我们需要交易系统在图表上返回含有以下值的注释:
- 上行趋势
- 当期收盘价
- 当期 VIDYA 值
另一种场景是,如果当期收盘价低于当期 VIDYA 值,则应是趋势下降的信号。
故此,我们需要交易系统在图表上返回含有以下值的注释:
- 下行趋势
- 当期收盘价
- 当期 VIDYA 值
以下是此策略的蓝图:
根据这个策略,我们需要创建一个交易系统,在出现买入或卖出信号时提醒我们。 在此策略中,我们将使用 VIDYA 趋势识别器的相同值,但得到不同的信号。 我们需要交易系统检查两个值,它们是当期收盘价和当期 VIDYA 值,如果当期收盘价大于 VIDYA 值,则它应是一个买入信号。
因此,我们需要交易系统返回以下值:
- 买入信号
- 当期收盘价
- 当期 VIDYA 值
反之亦然,如果当期收盘价低于 VIDYA,则为卖出信号。
故此,我们需要交易系统在图表上返回含有以下值的注释:
- 卖出信号
- 当期收盘价
- 当期 VIDYA 值
根据这个策略,我们需要创建一个可生成买入和卖出信号的交易系统。 我们需要连续检查两个值,它们是当期(9,12)VIDYA 和当期 VIDYA(20,50)。 如果当期(9,12)值大于当期(20,50),则为买入信号。
因此,我们需要交易系统返回以下值:
- 买入信号
- 当期收盘价
- 当期 VIDYA (9, 12) 值
- 当期 VIDYA (20, 50) 值
在另一种场景下,如果当期(9,12)VIDYA 值低于当期(20,50)VIDYA 值,则为卖出信号。
因此,我们需要交易系统返回以下值:
- 卖出信号
- 当期收盘价
- 当期 VIDYA (9, 12) 值
- 当期 VIDYA (20, 50) 值
以下是此策略的蓝图:
现在,我们已为提到的每个策略设计了一个简单的分步蓝图,来帮助我们创建自动交易系统,我们准备好进入 VIDYA 交易系统最有趣的主题,即为每个策略创建一个交易系统。
VIDYA 交易系统
这个简单的交易系统能帮助我们连续查看 VIDYA 指标的当期值,因为我们需要在图表上的注释里查看此值。
以下步骤是如何创建一个交易系统来达成我们的需要。
我们将创建一个 double 数据类型的数组 “vidyaArray”,它是实数型或浮点型之一,能表示分数值。
double vidyaArray[];
我们调用 “ArraySetAsSeries” 函数为所创建的 “vidyaArray” 数组设置排序,并返回一个布尔值。
ArraySetAsSeries(vidyaArray,true);
我们将调用 “iVIDyA” 函数返回指标的句柄,并创建一个整数变量 “vidyaDef”,存储 VIDYA 指标句柄。
参数为:
- symbol: 我们将采用(_Symbol)应用于当前交易品种
- period: 我们将采用使(_Period)应用于当前周期或时间帧
- cmo_period: 确定钱德动量周期,我们采用 9
- ema_period: 确定指数移动平均平滑周期,我们采用 12
- ma_shift: 如果需要,确定图表上的水平偏移,我们采用 0
- applied_price: 确定价格类型,我们采用收盘价
int vidyaDef = iVIDyA(_Symbol,_Period,9,12,0,PRICE_CLOSE);
我们将调用 “CopyBuffer” 函数填充已创建数组,它从 VIDYA 指标获取数据。
该函数参数:
- indicator_handle: 确定指标句柄,我们取(vidyaDef)的值
- buffer_num: 确定指标缓冲区编号,我们采用(0)
- start_pos: 确定起始位置,我们采用(0)
- count: 确定要复制的额度,我们采用(3)
- buffer[]: 确定要复制的目标数组,我们将使用(vidyaArray)
CopyBuffer(vidyaDef,0,0,3,vidyaArray);
我们创建变量 “vidyaVal” 后,调用 “NormalizeDouble” 函数返回规范化的双精度型数值。
该函数参数:
- value: 我们将取(vidyaArray[0])里的值作为规范化数字
- digits: 我们采用(6) 作为小数点后的数字位数
double vidyaVal = NormalizeDouble(vidyaArray[0],6);
我们将调用 Comment 函数在图表上生成含有当期 VIDYA 值的注释:
Comment("VIDYA Value is ",vidyaVal);
因此,我们可以找到该交易系统的完整代码,如下所示:
//+------------------------------------------------------------------+ //| Simple VIDYA.mq5 | //| Copyright 2022, MetaQuotes Ltd. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2022, MetaQuotes Ltd." #property link "https://www.mql5.com" #property version "1.00" //+------------------------------------------------------------------+ void OnTick() { double vidyaArray[]; ArraySetAsSeries(vidyaArray,true); int vidyaDef = iVIDyA(_Symbol,_Period,9,12,0,PRICE_CLOSE); CopyBuffer(vidyaDef,0,0,3,vidyaArray); double vidyaVal = NormalizeDouble(vidyaArray[0],6); Comment("VIDYA Value is ",vidyaVal); } //+------------------------------------------------------------------+
这段代码编译完毕后,我们将在导航器中找到该交易系统的智能系统,如下所示:
将其拖放到图表上后,我们将发现此交易系统的窗口,如下所示:
按下“确定”,我们会发现智能系统已加载,如下相同:
正如我们在上一张图表中所见,我们加载的智能系统与在右上角看到的相同。 然后我们可以发现期望的信号出现,如下相同:
正如我们在上一张图表中所见,在左上角我们看到含有当前 VIDYA 值的注释。 如果我们需要确保我们的值与内置 VIDYA 指标的值相同,我们可以在加载的智能系统后插入与设置相同的内置指标,如下所示:
正如我们在上一张图表中所见,我们在右上角看到智能系统加载到图表上,我们在图表的左上角看到含有智能系统的当期值,加载到价格图表的内置指标及其值,一切都如我们在右侧数据窗口中看到的那样。 显然,我们发现这两个值是相同的。
如果我们需要为此策略创建一个交易系统,我们可以找到该策略的以下完整代码:
//+------------------------------------------------------------------+ //| VIDYA trend identifier.mq5 | //| Copyright 2022, MetaQuotes Ltd. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2022, MetaQuotes Ltd." #property link "https://www.mql5.com" #property version "1.00" //+------------------------------------------------------------------+ void OnTick() { MqlRates priceArray[]; double vidyaArray[]; int Data=CopyRates(_Symbol,_Period,0,3,priceArray); ArraySetAsSeries(vidyaArray,true); int vidyaDef = iVIDyA(_Symbol,_Period,9,12,0,PRICE_CLOSE); CopyBuffer(vidyaDef,0,0,3,vidyaArray); double currentClose=NormalizeDouble(priceArray[2].close,6); double vidyaVal = NormalizeDouble(vidyaArray[0],6); if(currentClose>vidyaVal) { Comment("Uptrend","\n", "Current Close Value is ",currentClose,"\n", "Current VIDYA Value is ",vidyaVal); } if(currentClose<vidyaVal) { Comment("Downtrend","\n", "Current Close Value is ",currentClose,"\n", "Current VIDYA Value is ",vidyaVal); } } //+------------------------------------------------------------------+
此代码中的区别:
如前所述,创建两个 “MqlRates” 数据类型的价格数组,以及创建两个 “double” 数据类型的 VIDYA 数组。
MqlRates priceArray[]; double vidyaArray[];
为这些创建的数组设置排序,对于 priceArray,我们调用 “CopyRates” 函数来获取 “MqlRates” 型的历史数据。 其参数为:
- symbol name: 我们采用 (_Symbol)
- timeframe: 我们采用 (_Period)
- start time: 我们采用 (0)
- stop time: 我们采用 (3)
- rates array: 我们取用 (priceArray)
对于 vidyaArray,我们调用 “ArraySetAsSeries” 函数,就像我们之前提到的一样。
int Data=CopyRates(_Symbol,_Period,0,3,priceArray); ArraySetAsSeries(vidyaArray,true);
定义当期收盘价和当期 VIDYA 值。
double currentClose=NormalizeDouble(priceArray[2].close,6); double vidyaVal = NormalizeDouble(vidyaArray[0],6);
此策略的条件:
1. 上升趋势的情况
if(currentClose>vidyaVal) { Comment("Uptrend","\n", "Current Close Value is ",currentClose,"\n", "Current VIDYA Value is ",vidyaVal); }
2. 下降趋势的情况
if(currentClose<vidyaVal) { Comment("Downtrend","\n", "Current Close Value is ",currentClose,"\n", "Current VIDYA Value is ",vidyaVal); }
编译此代码,并将其插入到所需的图表后,它将与如下相同:
正如我们所看到的,智能系统 VIDYA 趋势识别器已加载,正如我们在上一个图表的右上角看到的那样。 现在,我们可以开始从中接收信号了。 下面展示了在测试期间获得的一些信号的示例。
1. 上升趋势的情况
正如我们在上一张图表中左上角看到的那样,我们可以找到以下值:
- 上行趋势
- 当期收盘价
- 当期 VIDYA 值
2. 下降趋势的情况
基于前面的图表,我们可以找到以下值:
- 下行趋势
- 当期收盘价
- 当期 VIDYA 值
以下是为该策略创建交易系统的完整代码:
//+------------------------------------------------------------------+ //| VIDYA one crossover.mq5 | //| Copyright 2022, MetaQuotes Ltd. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2022, MetaQuotes Ltd." #property link "https://www.mql5.com" #property version "1.00" //+------------------------------------------------------------------+ void OnTick() { MqlRates priceArray[]; double vidyaArray[]; int Data=CopyRates(_Symbol,_Period,0,3,priceArray); ArraySetAsSeries(vidyaArray,true); int vidyaDef = iVIDyA(_Symbol,_Period,9,12,0,PRICE_CLOSE); CopyBuffer(vidyaDef,0,0,3,vidyaArray); double currentClose=NormalizeDouble(priceArray[2].close,6); double vidyaVal = NormalizeDouble(vidyaArray[0],6); if(currentClose>vidyaVal) { Comment("Buy signal","\n", "Current Close Value is ",currentClose,"\n", "Current VIDYA Value is ",vidyaVal); } if(currentClose<vidyaVal) { Comment("Sell signal","\n", "Current Close Value is ",currentClose,"\n", "Current VIDYA Value is ",vidyaVal); } } //+------------------------------------------------------------------+
此代码中的区别:
基于此策略的注释。
1. 买入信号的情况
if(currentClose>vidyaVal) { Comment("Buy signal","\n", "Current Close Value is ",currentClose,"\n", "Current VIDYA Value is ",vidyaVal); }
2. 卖出信号情况
if(currentClose<vidyaVal) { Comment("Sell signal","\n", "Current Close Value is ",currentClose,"\n", "Current VIDYA Value is ",vidyaVal); }
编译此代码,并将其插入到所需的图表中后,如下所示:
正如我们在上一张图表中右上角所见,智能交易被加载到图表上。 之后,我们就能获得基于此策略的买入和卖出信号。 系统测试示例如下所示。
1. 买入信号的情况
正如我们在上一张图表中左上角所见,我们可以依据 VIDYA 一线交叉找到以下值:
- 买入信号
- 当期收盘价
- 当期 VIDYA 值
2. 卖出信号情况
正如我们在上一张图表中左上角看到的那样,我们可以找到以下值:
- 卖出信号
- 当期收盘价
- 当期 VIDYA 值
以下是 VIDYA 两线交叉策略的完整代码,为其创建交易系统。
//+------------------------------------------------------------------+ //| VIDYA two crossover.mq5 | //| Copyright 2022, MetaQuotes Ltd. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2022, MetaQuotes Ltd." #property link "https://www.mql5.com" #property version "1.00" //+------------------------------------------------------------------+ void OnTick() { MqlRates priceArray[]; double vidyaArray[]; double vidyaArray1[]; int Data=CopyRates(_Symbol,_Period,0,3,priceArray); ArraySetAsSeries(vidyaArray,true); ArraySetAsSeries(vidyaArray1,true); int vidyaDef = iVIDyA(_Symbol,_Period,9,12,0,PRICE_CLOSE); int vidyaDef1 = iVIDyA(_Symbol,_Period,20,50,0,PRICE_CLOSE); CopyBuffer(vidyaDef,0,0,3,vidyaArray); CopyBuffer(vidyaDef1,0,0,3,vidyaArray1); double currentClose=NormalizeDouble(priceArray[2].close,6); double vidyaVal = NormalizeDouble(vidyaArray[0],6); double vidyaVal1 = NormalizeDouble(vidyaArray1[0],6); if(vidyaVal>vidyaVal1) { Comment("Buy signal","\n", "Current Close Value is ",currentClose,"\n", "Current VIDYA (9,12) Value is ",vidyaVal,"\n", "Current VIDYA (20,50) Value is ",vidyaVal1); } if(vidyaVal<vidyaVal1) { Comment("Sell signal","\n", "Current Close Value is ",currentClose,"\n", "Current VIDYA (9,12) Value is ",vidyaVal,"\n", "Current VIDYA (20,50) Value is ",vidyaVal1); } } //+------------------------------------------------------------------+
此代码中的区别:
创建三个数组 price、vidyaArray、vidyaArray1
MqlRates priceArray[]; double vidyaArray[]; double vidyaArray1[];
为所创建数组设置排序
int Data=CopyRates(_Symbol,_Period,0,3,priceArray); ArraySetAsSeries(vidyaArray,true); ArraySetAsSeries(vidyaArray1,true);
定义 “vidyaDef” 和 “vidyaDef1”
int vidyaDef = iVIDyA(_Symbol,_Period,9,12,0,PRICE_CLOSE); int vidyaDef1 = iVIDyA(_Symbol,_Period,20,50,0,PRICE_CLOSE);
填充 “vidyaArray” 和 “vidyaArray1” 数组
CopyBuffer(vidyaDef,0,0,3,vidyaArray); CopyBuffer(vidyaDef1,0,0,3,vidyaArray1);
定义 currentClose、“vidyaVal” 和 “vidyaVal1” 的值
double currentClose=NormalizeDouble(priceArray[2].close,6); double vidyaVal = NormalizeDouble(vidyaArray[0],6); double vidyaVal1 = NormalizeDouble(vidyaArray1[0],6);
基于此策略的信号条件:
1. 买入信号的情况
if(vidyaVal>vidyaVal1) { Comment("Buy signal","\n", "Current Close Value is ",currentClose,"\n", "Current VIDYA (9,12) Value is ",vidyaVal,"\n", "Current VIDYA (20,50) Value is ",vidyaVal1); }
2. 卖出信号情况
if(vidyaVal<vidyaVal1) { Comment("Sell signal","\n", "Current Close Value is ",currentClose,"\n", "Current VIDYA (9,12) Value is ",vidyaVal,"\n", "Current VIDYA (20,50) Value is ",vidyaVal1); }
编译此代码,并将其插入到所需的图表后,它将与如下相同:
正如我们在上一张图表中右上角看到的那样,我们将智能系统加载到图表上。 现在,我们可以看到基于此策略的买入和卖出信号。 系统测试中的一些示例如下所示。
买入信号情况:
正如我们在上一张图表中左上角看到的,我们在交叉后有以下值:
- 买入信号
- 当期收盘价
- 当期 (9,12) VIDYA 值
- 当期 (20,50) VIDYA 值
卖出信号情况:
在另一种场景下,正如我们在上一张图表中左上角看到的那样,我们在交叉后有以下值:
- 卖出信号
- 当期收盘价
- 当期 (9,12) VIDYA 值
- 当期 (20,50) VIDYA 值
结束语
现在,讲述完所有提到的主题之后,您现在应当知道什么是可变指数动态平均线 (VIDYA),我们在本文涵盖了众多能够澄清其细节的主题。 我们能辨别出什么是可变指数动态平均线(VIDYA)指标,它测量什么,我们如何手工计算它,从而理解其背后的主要概念,以及如何将其插入图表并读取它。 我们通览了 VIDYA 定义主题来学习所有内容。 然后,我们学习如何基于指标背后主要概念在简单策略中运用它,我们通览了 VIDYA 策略主题,学习到以下策略:
- VIDYA 趋势识别器策略:如果存在上升趋势或下降趋势,则获取趋势类型的信号。
- VIDYA 一线交叉策略:根据价格与 VIDYA 线之间的交叉获取买入或卖出信号。
- VIDYA 两线交叉策略:根据设置为(9,12)和设置为(20,50)的两条 VIDYA 之间的交叉来获取买入或卖出信号的信号。
我希望您尝试自行设计交易系统,并编写代码,从而开发您作为初学者的编程技能,因为这种实践是非常重要的一步,您需要加深理解,并提高您的技能,不仅在编程中,且在任何主题的学习过程当中。 我不会忘记再次确认,当您在实盘账户上投入真金白银运用任何策略之前,您必须对其进行测试,因为本文的主旨仅限于教学目的,您可能会发现您需要优化或修改它们,或者您会发现它们不适合您的交易风格,因为没有适合每个人的策略。
我希望您发现本文对您的用处,并让您对文章主题或任何相关主题有更好的见解。 如果您想阅读更多类似的文章来学习最流行的技术指标、如何使用它们、以及如何为它们设计交易系统,您可以阅读我之前在本系列中的文章,初学者可从中学习更多关于它们的信息,譬如您可以找到有关依据 RSI、平滑异动移动平均线、随机指标、移动平均线、布林带、轨道线...等等,设计交易系统的文章。
本文由MetaQuotes Ltd译自英文
原文地址: https://www.mql5.com/en/articles/11341
![神经网络变得轻松(第二十八部分):政策梯度算法](https://c.mql5.com/2/48/Neural_networks_made_easy_021__1.png)
![神经网络变得轻松(第二十七部分):深度 Q-学习(DQN)](https://c.mql5.com/2/48/Neural_networks_made_easy.png)
![DoEasy. 控件(第 16 部分):TabControl WinForms 对象 — 多行选项卡标题,拉伸标题适配容器](https://c.mql5.com/2/48/MQL5-avatar-doeasy-library-2__4.png)