简介
本文将介绍如何将MetaTrader 5连接到由Heaton Research开发的EnCG高级神经网络和机器学习框架。我知道MetaTrader有一些方法可以使用我之前讨论过的机器学习技术:fann、neuro solutions、matlab和neuro shell。我希望encog是一个补充的解决方案,因为它是可靠、可靠和设计良好的代码。
我为什么选择Encog?有几个原因。
- encog已经应用于另外两个商业交易软件包中。一个是以C为基础的,另一个是基于Java的。这意味着它已经被测试来预测财务时间序列数据。
- encog是一个免费的开源软件。如果你想知道神经网络中发生了什么,你可以浏览源代码。这是我理解时间序列预测问题的实际工作。C是一种清晰易懂的编程语言。
- Encog有完整的文档。Heaton Research的创始人希顿先生提供了关于神经网络、机器学习和使用EnCG预测未来数据的免费在线课程。在写这篇文章之前,我参加了他的许多课程。他们在理解人工神经网络方面帮助了我很多。此外,还有关于用Java和Engon研究EnCOG编程的电子书。完整的编码说明可以在线获得。
- encog不是停止维护的项目。在编写时,Encog2.6仍在开发中。最近发布了Encog3.0路线图。
- Encog非常强大。它设计良好,可以使用多个CPU内核和多线程加速神经网络计算。部分代码开始专门为支持GPU计算的OpenCL移植。
- ECNOG目前支持以下功能:
机器学习类型
- 前馈和简单递归(埃尔曼/乔丹)
- 遗传算法
- 整洁的
- 概率神经网络/广义回归神经网络(PNN/GRNN)
- 自组织映射(som/kohonen)
- 模拟退火算法
- 支持向量机
神经网络体系结构
- Adaline神经网络
- 自适应共振理论1(art1)
- 双向联想存储器
- 玻尔兹曼机器
- 反向传播神经网络
- 埃尔曼递归神经网络
- 前馈神经网络(感知器)
- Hopfield神经网络
- 约旦递归神经网络
- 增量拓扑神经进化
- 径向基函数网络
- 递归自组织映射(RSOM)
- 自组织映射(Kohonen)
训练技术
- 反向传播
- 弹性传播
- 定量共轭梯度
- 曼哈顿更新规则发布
- 竞争性学习
- 霍普菲尔德学习
- Levenberg-Marquart算法(LMA)
- 遗传算法训练
- 明星培训
- 外星训练
- Adaline培训
- 训练数据模型
- 被监督的
- 无监督的
- 时间(预测)
- 财务(从雅虎财务下载)
- SQL
- XML
- 猪瘟病毒
- 图像还原采样
激活函数
- 竞争功能
- 乙状结肠功能
- 坦赫
- 线性函数
- SoftMax函数
- 切线函数
- 正弦波函数
- 阶跃函数
- 双极性函数
- 高斯函数
随机化技术
- 范围随机化
- 高斯随机数
- 扇入
- 阮维德
本计划的功能如下:
- 超洁的
- RBN/深层信念
- 脉冲神经网络
如您所见,这是一个相当长的特性列表。
本文介绍了弹性传播(RPROP)训练的前馈神经网络结构。它还包括数据编译的基础——时间序列预测的时间量化和规范化。
使我能够撰写这篇文章的知识是基于《希顿研究》提供的教程和《忍者商人》最近关于预测金融时间系列的文章。请注意,EnCOG是基于Java和C语言的。如果没有我以前的文章“使用非托管导出将C代码应用于MQL5”,就不可能编写本文。此解决方案使使用C_DLL作为metatrader 5和encog时间序列预测程序之间的桥梁成为可能。
1。以技术指标值作为神经网络的输入
人工神经网络(ANN)是一种试图模拟大脑神经网络的人机工程学算法。
有各种各样的神经算法可用,也有各种各样的神经网络结构。研究领域十分广泛,对各种神经网络分别进行了专门的介绍。因为这些细节超出了本文的范围,所以我只能建议您阅读关于相关主题的Heaton研究教程或书籍。我将重点介绍前馈神经网络的输入和输出,并尝试描述金融时间序列预测的例子。
为了开始预测金融时间序列,我们必须考虑我们应该向神经网络提供什么,以及我们从中期望什么。在最抽象的黑箱思想中,我们通过长期或短期的指定证券合约来实现盈亏,并在一段时间后平仓。
通过观察投资组合的过去价格和技术指标的价值,我们试图预测未来的市场情绪和价格方向,买卖合同,并确保我们的决策不是通过抛硬币作出的。情况或多或少类似于下图:
图1。用技术指标预测财务时间序列-nbsp;
我们将努力用人工智能取得同样的成果。神经网络将尝试识别指数值,并确定价格是否有上升或下降的机会。我们如何才能实现这个目标?由于我们将使用前馈神经网络结构来预测金融时间序列,我认为我们需要介绍它的结构。
前馈神经网络由神经元分层组成。必须至少有两层:包含输入神经元的输入层和包含输出神经元的输出层。在输入层和输出层之间也可以有一个隐藏层。输入层可以简单地看作双精度值数组,而输出层可以由一个或多个同时构成双精度值数组的神经元组成。见下图:
 ;
图2。前馈神经网络层
为了简化作图,神经元之间没有联系。输入层中的每个神经元都与隐藏层中的一个神经元相连。隐藏层中的每个神经元都连接到输入层中的一个神经元。
每个连接都有它的权重,这也是一个双精度值,以及一个阈值激活功能,负责激活神经元并将信息传递给下一个神经元。这就是为什么它被称为前馈网络——基于激活神经元输出的信息从一层神经元向前传输到另一层。有关前馈神经网络的详细视频介绍,请单击以下链接:
- 神经网络计算(第1部分):前馈结构
- 神经网络计算(第2部分):激活函数与基础计算
- 神经网络计算(第3部分):前馈神经网络计算
在你理解了神经网络的结构和机制之后,你可能仍然困惑。
主要问题包括:
- 我们应该向神经网络提供什么数据?
- 我们如何提供?
- 如何为神经网络准备输入数据?
- 如何选择神经网络结构?我们需要多少输入神经元、隐藏神经元和输出神经元?
- 如何训练网络?
- 预期产量是多少?
nbsp;
2。应该向神经网络提供什么数据?
由于我们是以指标产出为基础进行财务预测的,所以我们应该为网络提供指标产出值。对于本文,我选择随机索引%k、随机慢索引%d和威廉索引%r作为输入。
图3。预测技术指标
为了提取索引的值,我们可以使用istochastic和iwpr mql5函数:
double StochKArr[], StochDArr[], WilliamsRArr[]; ArraySetAsSeries(StochKArr, true); ArraySetAsSeries(StochDArr, true); ArraySetAsSeries(WilliamsRArr, true); int hStochastic = iStochastic(Symbol(), Period(), 8, 5, 5, MODE_EMA, STO_LOWHIGH); int hWilliamsR = iWPR(Symbol(), Period(), 21); CopyBuffer(hStochastic, 0, 0, bufSize, StochKArr); CopyBuffer(hStochastic, 1, 0, bufSize, StochDArr); CopyBuffer(hWilliamsR, 0, 0, bufSize, WilliamsRArr);
执行完这段代码后,三个数组stochkarr、stochdarr和williams rarr应该用度量的输出值填充。根据培训样本的大小,它可能多达几千个值。请记住,这两个指标仅用于教育目的。
建议测试任何适合预测的指标。您可能需要向网络提供黄金和原油价格来预测股票指数,或者您可以使用相关的外汇货币对来预测另一种货币对。
nbsp;
三。时间定量输入数据
在从多个指标收集输入数据后,我们需要在将输入时间框提供给神经网络之前对其进行量化。Timeboxing是一种允许作为移动数据片段输入到网络的技术。您可以想象一个输入数据移动框在时间线上向前移动。这个过程主要包括两个步骤:
1。从每个指示器缓存收集输入数据。我们需要从开始到将来复制输入窗口元素。输入窗口是用于预测的列数。
 ;
图4。从索引缓存收集输入窗口数据-nbsp;
如上例所示,input_window等于四列,我们将元素复制到i1数组。I1[0]是第一个元素,I1[3]是最后一个元素。同样,必须将数据从其他度量复制到大小输入窗口的数组中。此数字对时间序列数组有效,其中as_series标记设置为true。
2。结合输入窗口的数目,为神经网络的输入层提供一个数组。
;
型
图5。时间量化后的输入窗口数组
有三个指标。首先,我们取每个指标的第一个值,然后取每个指标的第二个值,直到输入窗口被填满,如上图所示。从索引输出的组合数组可以提供给神经网络的输入层。当新列到达时,数据被一个元素一个元素地分割,整个过程被重复。如果您有兴趣在准备过程中了解更多有关预测数据的信息,还可以观看有关主题的视频。
nbsp;
4。输入数据的规范化
为了使神经网络有效运行,必须对数据进行归一化处理。这是正确计算激活功能所必需的。规范化是一个将数据转换为0.1或-1.1范围的数学过程。归一化数据可以进行非归一化,即转换回原始范围。
为了将神经网络的输出解码为人类可读的形式,有必要对数据进行去规范化。值得庆幸的是,Encog负责标准化和去标准化,因此不需要实施。如果您对它的工作方式很好奇,可以分析以下代码:
/** * Normalize the specified value. * @param value The value to normalize. * @return The normalized value. */ public static double normalize(final int value) { return ((value - INPUT_LOW) / (INPUT_HIGH - INPUT_LOW)) * (OUTPUT_HIGH - OUTPUT_LOW) + OUTPUT_LOW; } /** * De-normalize the specified value. * @param value The value to denormalize. * @return The denormalized value. */ public static double deNormalize(final double data) { double result = ((INPUT_LOW - INPUT_HIGH) * data - OUTPUT_HIGH * INPUT_LOW + INPUT_HIGH * OUTPUT_LOW) / (OUTPUT_LOW - OUTPUT_HIGH); return result; }
阅读有关规范化的文章以获取更多信息。
nbsp;
5。选择网络架构和神经元数量
对于这个主题的新手来说,选择正确的网络体系结构是一个困难的任务。本文将前馈神经网络的结构限定为三层:输入层、隐藏层和输出层。你可以随意尝试更多的层。
对于输入和输出层,我们可以精确计算所需的神经元数量。对于隐藏层,我们将尝试通过正向选择算法最小化神经网络误差。建议您使用其他方法;可能有一些遗传算法来计算神经元的数量。
encog使用的另一种方法称为反向选择或修剪。它基本上评估了各层之间的连接,并以零连接权重移除隐藏的神经元。你可能想试试。
5.1。输入神经元层
由于时间量化,输入层中的神经元数量应等于指标数量乘以用于预测下一列的列数。如果我们使用三个指示器作为输入,并且输入窗口的大小等于六列,那么输入层将包含18个神经元。输入层及时提供定量准备的数据。
5.2。隐藏神经元层
隐网络的数目必须根据训练后的神经网络的性能来估计。隐藏神经元的数量没有直接的数学方程。在写这篇文章之前,我使用了各种尝试和错误方法,并在Heaton Research上找到了一种有助于理解正向选择算法的算法:
;
型
图6。计算隐藏神经元数量的正向选择算法
5.3。输出神经元层
出于我们的目的,输出神经元的数量等于我们试图预测的列的数量。请记住,隐藏和输出神经元的数量越多,网络训练时间越长。在本文中,我试图预测未来的支柱,因此输出层包含一个神经元。
nbsp;
6。将培训数据从metatrader 5导出到encog
encog接收用于神经网络训练的csv文件。
我查看了从其他交易软件导出到encog的文件格式,并实现了为培训准备相同文件格式的MQL5脚本。我将从引入和导出一个指标开始,然后转到几个指标。
第一行数据是逗号分隔的标题:
DATE,TIME,CLOSE,Indicator_Name1,Indicator_Name2,Indicator_Name3
前三列包含日期、时间和收盘价,下一列包含索引名。培训文件的下一行应包含逗号分隔的数据,索引值应采用科学的计数方法表示:
20110103,0000,0.93377000,-7.8970208860e-002
为一个指标查看以下现成的脚本。
//+------------------------------------------------------------------+ //| ExportToEncog.mq5 | //| Copyright 2011, Investeo.pl | //| http:/Investeo.pl | //+------------------------------------------------------------------+ #property copyright "Copyright 2011, Investeo.pl" #property link "http:/Investeo.pl" #property version "1.00" //+------------------------------------------------------------------+ //| Script program start function | //+------------------------------------------------------------------+ // Export Indicator values for NN training by ENCOG extern string IndExportFileName = "mt5export.csv"; extern int trainSize = 400; extern int maPeriod = 210; MqlRates srcArr[]; double expBullsArr[]; void OnStart() { //--- ArraySetAsSeries(srcArr, true); ArraySetAsSeries(expBullsArr, true); int copied = CopyRates(Symbol(), Period(), 0, trainSize, srcArr); if (copied!=trainSize) { Print("Not enough data for " + Symbol()); return; } int hBullsPower = iBullsPower(Symbol(), Period(), maPeriod); CopyBuffer(hBullsPower, 0, 0, trainSize, expBullsArr); int hFile = FileOpen(IndExportFileName, FILE_CSV | FILE_ANSI | FILE_WRITE | FILE_REWRITE, ",", CP_ACP); FileWriteString(hFile, "DATE,TIME,CLOSE,BullsPower/n"); Print("Exporting indicator data to " + IndExportFileName); for (int i=trainSize-1; i>=0; i--) { string candleDate = TimeToString(srcArr[i].time, TIME_DATE); StringReplace(candleDate,".",""); string candleTime = TimeToString(srcArr[i].time, TIME_MINUTES); StringReplace(candleTime,":",""); FileWrite(hFile, candleDate, candleTime, DoubleToString(srcArr[i].close), DoubleToString(expBullsArr[i], -10)); } FileClose(hFile); Print("Indicator data exported."); } //+------------------------------------------------------------------+
&可用于培训的结果文件应如下所示:
DATE,TIME,CLOSE,BullsPower 20110103,0000,0.93377000,-7.8970208860e-002 20110104,0000,0.94780000,-6.4962292188e-002 20110105,0000,0.96571000,-4.7640374727e-002 20110106,0000,0.96527000,-4.4878854587e-002 20110107,0000,0.96697000,-4.6178012364e-002 20110110,0000,0.96772000,-4.2078647318e-002 20110111,0000,0.97359000,-3.6029181466e-002 20110112,0000,0.96645000,-3.8335729509e-002 20110113,0000,0.96416000,-3.7054869514e-002 20110114,0000,0.96320000,-4.4259373120e-002 20110117,0000,0.96503000,-4.4835729773e-002 20110118,0000,0.96340000,-4.6420936126e-002 20110119,0000,0.95585000,-4.6868984125e-002 20110120,0000,0.96723000,-4.2709941621e-002 20110121,0000,0.95810000,-4.1918330800e-002 20110124,0000,0.94873000,-4.7722659418e-002 20110125,0000,0.94230000,-5.7111591557e-002 20110126,0000,0.94282000,-6.2231529077e-002 20110127,0000,0.94603000,-5.9997865295e-002 20110128,0000,0.94165000,-6.0378312069e-002 20110131,0000,0.94414000,-6.2038328069e-002 20110201,0000,0.93531000,-6.0710334438e-002 20110202,0000,0.94034000,-6.1446445012e-002 20110203,0000,0.94586000,-5.2580791504e-002 20110204,0000,0.95496000,-4.5246755566e-002 20110207,0000,0.95730000,-4.4439392954e-002
回到使用随机度量和威廉度量的原始文章示例,我们需要导出三个逗号分隔的列,每个列包含一个单独的度量值,因此我们需要展开文件并添加其他缓存:
//+------------------------------------------------------------------+ //| ExportToEncog.mq5 | //| Copyright 2011, Investeo.pl | //| http:/Investeo.pl | //+------------------------------------------------------------------+ #property copyright "Copyright 2011, Investeo.pl" #property link "http:/Investeo.pl" #property version "1.00" //+------------------------------------------------------------------+ //| Script program start function | //+------------------------------------------------------------------+ // Export Indicator values for NN training by ENCOG extern string IndExportFileName = "mt5export.csv"; extern int trainSize = 2000; MqlRates srcArr[]; double StochKArr[], StochDArr[], WilliamsRArr[]; void OnStart() { //--- ArraySetAsSeries(srcArr, true); ArraySetAsSeries(StochKArr, true); ArraySetAsSeries(StochDArr, true); ArraySetAsSeries(WilliamsRArr, true); int copied = CopyRates(Symbol(), Period(), 0, trainSize, srcArr); if (copied!=trainSize) { Print("Not enough data for " + Symbol()); return; } int hStochastic = iStochastic(Symbol(), Period(), 8, 5, 5, MODE_EMA, STO_LOWHIGH); int hWilliamsR = iWPR(Symbol(), Period(), 21); CopyBuffer(hStochastic, 0, 0, trainSize, StochKArr); CopyBuffer(hStochastic, 1, 0, trainSize, StochDArr); CopyBuffer(hWilliamsR, 0, 0, trainSize, WilliamsRArr); int hFile = FileOpen(IndExportFileName, FILE_CSV | FILE_ANSI | FILE_WRITE | FILE_REWRITE, ",", CP_ACP); FileWriteString(hFile, "DATE,TIME,CLOSE,StochK,StochD,WilliamsR/n"); Print("Exporting indicator data to " + IndExportFileName); for (int i=trainSize-1; i>=0; i--) { string candleDate = TimeToString(srcArr[i].time, TIME_DATE); StringReplace(candleDate,".",""); string candleTime = TimeToString(srcArr[i].time, TIME_MINUTES); StringReplace(candleTime,":",""); FileWrite(hFile, candleDate, candleTime, DoubleToString(srcArr[i].close), DoubleToString(StochKArr[i], -10), DoubleToString(StochDArr[i], -10), DoubleToString(WilliamsRArr[i], -10) ); } FileClose(hFile); Print("Indicator data exported."); } //+------------------------------------------------------------------+
结果文件应包含所有指标:
DATE,TIME,CLOSE,StochK,StochD,WilliamsR 20030707,0000,1.37370000,7.1743119266e+001,7.2390220187e+001,-6.2189054726e-001 20030708,0000,1.36870000,7.5140977444e+001,7.3307139273e+001,-1.2500000000e+001 20030709,0000,1.35990000,7.3831775701e+001,7.3482018082e+001,-2.2780373832e+001 20030710,0000,1.36100000,7.1421933086e+001,7.2795323083e+001,-2.1495327103e+001 20030711,0000,1.37600000,7.5398313027e+001,7.3662986398e+001,-3.9719626168e+000 20030714,0000,1.37370000,7.0955352856e+001,7.2760441884e+001,-9.6153846154e+000 20030715,0000,1.38560000,7.4975891996e+001,7.3498925255e+001,-2.3890784983e+000 20030716,0000,1.37530000,7.5354107649e+001,7.4117319386e+001,-2.2322435175e+001 20030717,0000,1.36960000,7.1775345074e+001,7.3336661282e+001,-3.0429594272e+001 20030718,0000,1.36280000,5.8474576271e+001,6.8382632945e+001,-3.9778325123e+001 20030721,0000,1.35400000,4.3498596819e+001,6.0087954237e+001,-5.4946524064e+001 20030722,0000,1.36130000,2.9036761284e+001,4.9737556586e+001,-4.5187165775e+001 20030723,0000,1.34640000,1.6979405034e+001,3.8818172735e+001,-6.5989159892e+001 20030724,0000,1.34680000,1.0634573304e+001,2.9423639592e+001,-7.1555555556e+001 20030725,0000,1.34400000,9.0909090909e+000,2.2646062758e+001,-8.7500000000e+001 20030728,0000,1.34680000,1.2264922322e+001,1.9185682613e+001,-8.2705479452e+001 20030729,0000,1.35250000,1.4960629921e+001,1.7777331716e+001,-7.2945205479e+001 20030730,0000,1.36390000,2.7553336360e+001,2.1035999930e+001,-5.3979238754e+001 20030731,0000,1.36990000,4.3307839388e+001,2.8459946416e+001,-4.3598615917e+001 20030801,0000,1.36460000,5.6996412096e+001,3.7972101643e+001,-5.2768166090e+001 20030804,0000,1.34780000,5.7070193286e+001,4.4338132191e+001,-8.1833910035e+001 20030805,0000,1.34770000,5.3512705531e+001,4.7396323304e+001,-8.2006920415e+001 20030806,0000,1.35350000,4.4481132075e+001,4.6424592894e+001,-7.1972318339e+001 20030807,0000,1.35020000,3.3740028156e+001,4.2196404648e+001,-7.7681660900e+001 20030808,0000,1.35970000,3.0395426394e+001,3.8262745230e+001,-6.1245674740e+001 20030811,0000,1.35780000,3.4155781326e+001,3.6893757262e+001,-6.4532871972e+001 20030812,0000,1.36880000,4.3488943489e+001,3.9092152671e+001,-4.5501730104e+001 20030813,0000,1.36690000,5.1160443996e+001,4.3114916446e+001,-4.8788927336e+001 20030814,0000,1.36980000,6.2467599793e+001,4.9565810895e+001,-2.5629290618e+001 20030815,0000,1.37150000,6.9668246445e+001,5.6266622745e+001,-2.1739130435e+001 20030818,0000,1.38910000,7.9908906883e+001,6.4147384124e+001,-9.2819614711e+000
您可以修改第二个示例,以便轻松生成满足您需求的脚本。
7。神经网络训练
Heaton Research使用C为网络准备培训。encog 2.6实现了encog。应用程序。定量名称空间,是财务时间序列预测的基础。培训脚本非常灵活,可以很容易地调整到任何数量的输入指标。您应该只在目录常量中更改metatrader 5目录的位置。
您可以通过更改以下变量轻松自定义网络架构和培训参数:
/// <summary> /// The size of the input window. This is the number of bars used to predict the next bar. /// </summary> public const int INPUT_WINDOW = 6; /// <summary> /// The number of bars forward we are trying to predict. This is usually just 1 bar. The future indicator used in step 1 may /// well look more forward into the future. /// </summary> public const int PREDICT_WINDOW = 1; /// <summary> /// The number of bars forward to look for the best result. /// </summary> public const int RESULT_WINDOW = 5; /// <summary> /// The number of neurons in the first hidden layer. /// </summary> public const int HIDDEN1_NEURONS = 12; /// <summary> /// The target error to train to. /// </summary> public const double TARGET_ERROR = 0.01;
代码包含非常完整的解释,因此最好仔细阅读代码:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using Encog.App.Quant.Normalize; using Encog.Util.CSV; using Encog.App.Quant.Indicators; using Encog.App.Quant.Indicators.Predictive; using Encog.App.Quant.Temporal; using Encog.Neural.NeuralData; using Encog.Neural.Data.Basic; using Encog.Util.Simple; using Encog.Neural.Networks; using Encog.Neural.Networks.Layers; using Encog.Engine.Network.Activation; using Encog.Persist; namespace NetworkTrainer { public class Program { /// <summary> /// The directory that all of the files will be stored in. /// </summary> public const String DIRECTORY = "d://mt5//MQL5//Files//"; /// <summary> /// The input file that starts the whole process. This file should be downloaded from NinjaTrader using the EncogStreamWriter object. /// </summary> public const String STEP1_FILENAME = DIRECTORY + "mt5export.csv"; /// <summary> /// We apply a predictive future indicator and generate a second file, with the additional predictive field added. /// </summary> public const String STEP2_FILENAME = DIRECTORY + "step2_future.csv"; /// <summary> /// Next the entire file is normalized and stored into this file. /// </summary> public const String STEP3_FILENAME = DIRECTORY + "step3_norm.csv"; /// <summary> /// The file is time-boxed to create training data. /// </summary> public const String STEP4_FILENAME = DIRECTORY + "step4_train.csv"; /// <summary> /// Finally, the trained neural network is written to this file. /// </summary> public const String STEP5_FILENAME = DIRECTORY + "step5_network.eg"; /// <summary> /// The size of the input window. This is the number of bars used to predict the next bar. /// </summary> public const int INPUT_WINDOW = 6; /// <summary> /// The number of bars forward we are trying to predict. This is usually just 1 bar. The future indicator used in step 1 may /// well look more forward into the future. /// </summary> public const int PREDICT_WINDOW = 1; /// <summary> /// The number of bars forward to look for the best result. /// </summary> public const int RESULT_WINDOW = 5; /// <summary> /// The number of neurons in the first hidden layer. /// </summary> public const int HIDDEN1_NEURONS = 12; /// <summary> /// The target error to train to. /// </summary> public const double TARGET_ERROR = 0.01; static void Main(string[] args) { // Step 1: Create future indicators Console.WriteLine("Step 1: Analyze MT5 Export & Create Future Indicators"); ProcessIndicators ind = new ProcessIndicators(); ind.Analyze(STEP1_FILENAME, true, CSVFormat.DECIMAL_POINT); int externalIndicatorCount = ind.Columns.Count - 3; ind.AddColumn(new BestReturn(RESULT_WINDOW,true)); ind.Process(STEP2_FILENAME); Console.WriteLine("External indicators found: " + externalIndicatorCount); //Console.ReadKey(); // Step 2: Normalize Console.WriteLine("Step 2: Create Future Indicators"); EncogNormalize norm = new EncogNormalize(); norm.Analyze(STEP2_FILENAME, true, CSVFormat.ENGLISH); norm.Stats[0].Action = NormalizationDesired.PassThrough; // Date norm.Stats[1].Action = NormalizationDesired.PassThrough; // Time norm.Stats[2].Action = NormalizationDesired.Normalize; // Close norm.Stats[3].Action = NormalizationDesired.Normalize; // Stoch K norm.Stats[4].Action = NormalizationDesired.Normalize; // Stoch Dd norm.Stats[5].Action = NormalizationDesired.Normalize; // WilliamsR norm.Stats[6].Action = NormalizationDesired.Normalize; // best return [RESULT_WINDOW] norm.Normalize(STEP3_FILENAME); // neuron counts int inputNeurons = INPUT_WINDOW * externalIndicatorCount; int outputNeurons = PREDICT_WINDOW; // Step 3: Time-box Console.WriteLine("Step 3: Timebox"); //Console.ReadKey(); TemporalWindow window = new TemporalWindow(); window.Analyze(STEP3_FILENAME, true, CSVFormat.ENGLISH); window.InputWindow = INPUT_WINDOW; window.PredictWindow = PREDICT_WINDOW; int index = 0; window.Fields[index++].Action = TemporalType.Ignore; // date window.Fields[index++].Action = TemporalType.Ignore; // time window.Fields[index++].Action = TemporalType.Ignore; // close for(int i=0;i<externalIndicatorCount;i++) window.Fields[index++].Action = TemporalType.Input; // external indicators window.Fields[index++].Action = TemporalType.Predict; // PredictBestReturn window.Process(STEP4_FILENAME); // Step 4: Train neural network Console.WriteLine("Step 4: Train"); Console.ReadKey(); INeuralDataSet training = (BasicNeuralDataSet)EncogUtility.LoadCSV2Memory(STEP4_FILENAME, inputNeurons, outputNeurons, true, CSVFormat.ENGLISH); BasicNetwork network = new BasicNetwork(); network.AddLayer(new BasicLayer(new ActivationTANH(), true, inputNeurons)); network.AddLayer(new BasicLayer(new ActivationTANH(), true, HIDDEN1_NEURONS)); network.AddLayer(new BasicLayer(new ActivationLinear(), true, outputNeurons)); network.Structure.FinalizeStructure(); network.Reset(); //EncogUtility.TrainToError(network, training, TARGET_ERROR); EncogUtility.TrainConsole(network, training, 3); // Step 5: Save neural network and stats EncogMemoryCollection encog = new EncogMemoryCollection(); encog.Add("network", network); encog.Add("stat", norm.Stats); encog.Save(STEP5_FILENAME); Console.ReadKey(); } } }
你可能会注意到我评论了一句话,把训练功能从鼓励改了。训练错误()到鼓励性。trainconsole()。
EncogUtility.TrainConsole(network, training, 3);
trainconsole方法指定培训网络的分钟数。在这个例子中,我训练网络三分钟。根据网络的复杂性和培训数据的大小,培训网络可能需要几分钟、几小时甚至几天的时间。我建议更详细地理解关于希顿研究的误差计算和训练算法,或者在任何其他有关主题的书中。
鼓励性。traintoError()方法在到达目标网络错误后停止网络训练。你可以用注释来解释。trainconsole()并取消“鼓励性”注释。traintoError()将网络训练为所需的错误,如原始示例中所示。
EncogUtility.TrainToError(network, training, TARGET_ERROR);
注意,有时由于神经元数量少,网络可能不会被训练成一定的错误。
8。利用训练神经网络建立元交易者5神经指标
训练后的网络可以作为神经网络指标,试图预测投资的最佳回报。
MetaTrader 5的Encog神经指数由两部分组成。其中一部分是用MQL5编写的,它使用与培训网络相同的索引,并向网络提供输入窗口索引值。第二部分用C编写,它量化输入数据的时间,并将神经网络的输出返回到MQL5。C Indicators部分基于我之前关于“将C代码应用于MQL5”的文章。
using System; using System.Collections.Generic; using System.Text; using RGiesecke.DllExport; using System.Runtime.InteropServices; using Encog.Neural.Networks; using Encog.Persist; using Encog.App.Quant.Normalize; using Encog.Neural.Data; using Encog.Neural.Data.Basic; namespace EncogNeuralIndicatorMT5DLL { public class NeuralNET { private EncogMemoryCollection encog; public BasicNetwork network; public NormalizationStats stats; public NeuralNET(string nnPath) { initializeNN(nnPath); } public void initializeNN(string nnPath) { try { encog = new EncogMemoryCollection(); encog.Load(nnPath); network = (BasicNetwork)encog.Find("network"); stats = (NormalizationStats)encog.Find("stat"); } catch (Exception e) { Console.WriteLine(e.StackTrace); } } }; class UnmanagedExports { static NeuralNET neuralnet; [DllExport("initializeTrainedNN", CallingConvention = CallingConvention.StdCall)] static int initializeTrainedNN([MarshalAs(UnmanagedType.LPWStr)]string nnPath) { neuralnet = new NeuralNET(nnPath); if (neuralnet.network != null) return 0; else return -1; } [DllExport("computeNNIndicator", CallingConvention = CallingConvention.StdCall)] public static int computeNNIndicator([MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)] double[] t1, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)] double[] t2, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)] double[] t3, int len, [In, Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 5)] double[] result, int rates_total) { INeuralData input = new BasicNeuralData(3 * len); int index = 0; for (int i = 0; i <len; i++) { input[index++] = neuralnet.stats[3].Normalize(t1[i]); input[index++] = neuralnet.stats[4].Normalize(t2[i]); input[index++] = neuralnet.stats[5].Normalize(t3[i]); } INeuralData output = neuralnet.network.Compute(input); double d = output[0]; d = neuralnet.stats[6].DeNormalize(d); result[rates_total-1]=d; return 0; } } }
如果您喜欢使用除三个以外的任何数量的度量,则需要更改ComputenIndicator()方法以满足您的需要。
[DllExport("computeNNIndicator", CallingConvention = CallingConvention.StdCall)] public static int computeNNIndicator([MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)] double[] t1, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)] double[] t2, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)] double[] t3, int len, [In, Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 5)] double[] result, int rates_total)
在这种情况下,前三个输入参数是包含索引输入值的表,第四个参数是输入窗口的长度。
sizeParamIndex=3指向输入窗口长度变量,因为输入变量从零开始计数。第五个参数是包含神经网络结果的表。
mql5 index部分需要导入c encontraindll。并使用从dll派生的initializetrainednn()和computennindicator()函数。
//+------------------------------------------------------------------+ //| NeuralEncogIndicator.mq5 | //| Copyright 2011, Investeo.pl | //| http:/Investeo.pl | //+------------------------------------------------------------------+ #property copyright "Copyright 2011, Investeo.pl" #property link "http:/Investeo.pl" #property version "1.00" #property indicator_separate_window #property indicator_plots 1 #property indicator_buffers 1 #property indicator_color1 Blue #property indicator_type1 DRAW_LINE #property indicator_style1 STYLE_SOLID #property indicator_width1 2 #import "EncogNNTrainDLL.dll" int initializeTrainedNN(string nnFile); int computeNNIndicator(double& ind1[], double& ind2[],double& ind3[], int size, double& result[], int rates); #import int INPUT_WINDOW = 6; int PREDICT_WINDOW = 1; double ind1Arr[], ind2Arr[], ind3Arr[]; double neuralArr[]; int hStochastic; int hWilliamsR; int hNeuralMA; //+------------------------------------------------------------------+ //| Custom indicator initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- indicator buffers mapping SetIndexBuffer(0, neuralArr, INDICATOR_DATA); PlotIndexSetInteger(0, PLOT_SHIFT, 1); ArrayResize(ind1Arr, INPUT_WINDOW); ArrayResize(ind2Arr, INPUT_WINDOW); ArrayResize(ind3Arr, INPUT_WINDOW); ArrayInitialize(neuralArr, 0.0); ArraySetAsSeries(ind1Arr, true); ArraySetAsSeries(ind2Arr, true); ArraySetAsSeries(ind3Arr, true); ArraySetAsSeries(neuralArr, true); hStochastic = iStochastic(NULL, 0, 8, 5, 5, MODE_EMA, STO_LOWHIGH); hWilliamsR = iWPR(NULL, 0, 21); Print(TerminalInfoString(TERMINAL_DATA_PATH)+"//MQL5/Files/step5_network.eg"); initializeTrainedNN(TerminalInfoString(TERMINAL_DATA_PATH)+"//MQL5/Files/step5_network.eg"); //--- return(0); } //+------------------------------------------------------------------+ //| Custom indicator iteration function | //+------------------------------------------------------------------+ 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[]) { //--- int calc_limit; if(prev_calculated==0) // First execution of the OnCalculate() function after the indicator start calc_limit=rates_total-34; else calc_limit=rates_total-prev_calculated; ArrayResize(neuralArr, rates_total); for (int i=0; i<calc_limit; i++) { CopyBuffer(hStochastic, 0, i, INPUT_WINDOW, ind1Arr); CopyBuffer(hStochastic, 1, i, INPUT_WINDOW, ind2Arr); CopyBuffer(hWilliamsR, 0, i, INPUT_WINDOW, ind3Arr); computeNNIndicator(ind1Arr, ind2Arr, ind3Arr, INPUT_WINDOW, neuralArr, rates_total-i); } //Print("neuralArr[0] = " + neuralArr[0]); //--- return value of prev_calculated for next call return(rates_total); } //+------------------------------------------------------------------+
见使用USDCHF每日数据和随机指标以及威廉指标%r培训的指标输出:
图7。神经系统指标
指标显示了下一个支柱的最佳预测投资回报。
你可能已经注意到我已经将指示器移到了未来方向的位置:
PlotIndexSetInteger(0, PLOT_SHIFT, 1);
这表示该索引是一个预测值。因为我们构建了一个神经指标,所以我们准备基于该指标构建一个EA事务。
9。基于神经指标的电子交易
EA交易使用神经指标来输出和决定是否购买或出售证券。我的第一个印象是,我们应该在指数大于零的时候买入,在指数小于零的时候卖出,也就是说,我们应该在某个时间窗的最佳回报预测值为正的时候买入,在最佳回报预测值为负的时候卖出。
经过一些初步的测试,我们发现业绩应该更好,所以我介绍了“强上升趋势”和“强下降趋势”的变量,也就是说,根据著名的“趋势是你的朋友”原则,我们没有理由在强趋势下退出市场。
另外,我在Heaton Research Forum上得到了使用ATR进行移动站点的建议,所以我使用了在MQL5 Forum中找到的枝形吊灯ATR索引。在重新测试期间,资产净值确实增加了。我把EA事务的源代码粘贴在下面。
//+------------------------------------------------------------------+ //| NeuralEncogAdvisor.mq5 | //| Copyright 2011, Investeo.pl | //| http:/Investeo.pl | //+------------------------------------------------------------------+ #property copyright "Copyright 2011, Investeo.pl" #property link "http:/Investeo.pl" #property version "1.00" double neuralArr[]; double trend; double Lots=0.3; int INPUT_WINDOW=8; int hNeural,hChandelier; //+------------------------------------------------------------------+ #include <Trade/Trade.mqh> //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- ArrayResize(neuralArr,INPUT_WINDOW); ArraySetAsSeries(neuralArr,true); ArrayInitialize(neuralArr,0.0); hNeural=iCustom(Symbol(),Period(),"NeuralEncogIndicator"); Print("hNeural = ",hNeural," error = ",GetLastError()); if(hNeural<0) { Print("The creation of ENCOG indicator has failed: Runtime error =",GetLastError()); //--- forced program termination return(-1); } else Print("ENCOG indicator initialized"); hChandelier=iCustom(Symbol(),Period(),"Chandelier"); Print("hChandelier = ",hChandelier," error = ",GetLastError()); if(hChandelier<0) { Print("The creation of Chandelier indicator has failed: Runtime error =",GetLastError()); //--- forced program termination return(-1); } else Print("Chandelier indicator initialized"); //--- return(0); } //+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { //--- } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { //--- long tickCnt[1]; int ticks=CopyTickVolume(Symbol(),0,0,1,tickCnt); if(tickCnt[0]==1) { if(!CopyBuffer(hNeural,0,0,INPUT_WINDOW,neuralArr)) { Print("Copy1 error"); return; } // Print("neuralArr[0] = "+neuralArr[0]+"neuralArr[1] = "+neuralArr[1]+"neuralArr[2] = "+neuralArr[2]); trend=0; if(neuralArr[0]<0 && neuralArr[1]>0) trend=-1; if(neuralArr[0]>0 && neuralArr[1]<0) trend=1; Trade(); } } //+------------------------------------------------------------------+ //| Tester function | //+------------------------------------------------------------------+ double OnTester() { //--- //--- return(0.0); } //+------------------------------------------------------------------+ void Trade() { double bufChandelierUP[2]; double bufChandelierDN[2]; double bufMA[2]; ArraySetAsSeries(bufChandelierUP,true); ArraySetAsSeries(bufChandelierUP,true); ArraySetAsSeries(bufMA,true); CopyBuffer(hChandelier,0,0,2,bufChandelierUP); CopyBuffer(hChandelier,1,0,2,bufChandelierDN); MqlRates rates[]; ArraySetAsSeries(rates,true); int copied=CopyRates(Symbol(),PERIOD_CURRENT,0,3,rates); bool strong_uptrend=neuralArr[0]>0 && neuralArr[1]>0 && neuralArr[2]>0 && neuralArr[3]>0 && neuralArr[4]>0 && neuralArr[5]>0 && neuralArr[6]>0 && neuralArr[7]>0; bool strong_downtrend=neuralArr[0]<0 && neuralArr[1]<0 && neuralArr[2]<0 && neuralArr[3]<0 && neuralArr[4]<0 && neuralArr[5]<0 && neuralArr[6]<0 && neuralArr[7]<0; if(PositionSelect(_Symbol)) { long type=PositionGetInteger(POSITION_TYPE); bool close=false; if((type==POSITION_TYPE_BUY) && (trend==-1)) if(!(strong_uptrend) || (bufChandelierUP[0]==EMPTY_VALUE)) close=true; if((type==POSITION_TYPE_SELL) && (trend==1)) if(!(strong_downtrend) || (bufChandelierDN[0]==EMPTY_VALUE)) close=true; if(close) { CTrade trade; trade.PositionClose(_Symbol); } else // adjust s/l { CTrade trade; if(copied>0) { if(type==POSITION_TYPE_BUY) { if(bufChandelierUP[0]!=EMPTY_VALUE) trade.PositionModify(Symbol(),bufChandelierUP[0],0.0); } if(type==POSITION_TYPE_SELL) { if(bufChandelierDN[0]!=EMPTY_VALUE) trade.PositionModify(Symbol(),bufChandelierDN[0],0.0); } } } } if((trend!=0) && (!PositionSelect(_Symbol))) { CTrade trade; MqlTick tick; MqlRates rates[]; ArraySetAsSeries(rates,true); int copied=CopyRates(Symbol(),PERIOD_CURRENT,0,INPUT_WINDOW,rates); if(copied>0) { if(SymbolInfoTick(_Symbol,tick)==true) { if(trend>0) { trade.Buy(Lots,_Symbol,tick.ask); Print("Buy at "+tick.ask+" trend = "+trend+" neuralArr = "+neuralArr[0]); } if(trend<0) { trade.Sell(Lots,_Symbol,tick.bid); Print("Sell at "+tick.ask+" trend = "+trend+" neuralArr = "+neuralArr[0]); } } } } } //+------------------------------------------------------------------+
EA交易使用USDCHF货币D1数据。大约50%的数据来自培训样本。
10。EA交易结果
我把测试结果贴在下面。试验所用数据为2000年1月1日至2011年3月26日。
图8。神经网络EA交易收益测试结果
图9。神经网络EA交易余额/净资产收益图
请注意,对于其他时间框架和其他证券,此性能可能完全不同。
请将此EA视为教育用途,并将其作为进一步研究的起点。我个人的观点是,每次都可以重新训练互联网,使其更强大。有人可能或可能已经找到了实现这一目标的好方法。有一种更好的方法可以根据神经系统指标做出买卖预测。我鼓励读者尝试。
总结
在下面的文章中,我提出了一种利用encog机器学习框架构造神经预测指标和基于该指标的EA事务的方法。本文还包括所有源代码、编译的二进制文件、DLL和可以仿真的经过训练的网络。
cloo.dll、encog-core-cs.dll和log4net.dll文件应位于客户端的文件夹中,因为“双dll打包”。NET“。
encogntrantell.dll文件应位于/terminal data folder/mql5/libraries/folder中。
由MetaQuotes Software Corp.从英文翻译为
原文。https://www.mql5.com/en/articles/252
MyFxtop迈投(www.myfxtop.com)-靠谱的外汇跟单社区,免费跟随高手做交易!
免责声明:本文系转载自网络,如有侵犯,请联系我们立即删除,另:本文仅代表作者个人观点,与迈投财经(www.myfxtop.cn)无关。其原创性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容、文字的真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
著作权归作者所有。
商业转载请联系作者获得授权,非商业转载请注明出处。