神经网络实验(第 7 部分):传递指标
概述
在本文中,我们将更详尽地探讨在神经网络中传递有意义的数据(即所谓的时间序列)的重要性。特别是,我们将传递最喜欢的指标。为了达成这一点,我将介绍一些我在操控神经网络时所用的新概念。虽然,我认为这不是极限,随着时间的推移,我对于理解到底需要传递什么、以及如何传递,会有一个新的视界。
背景和观察
阅读大量这个主题的文章,我持续观察到一个悲伤的场面,那就是基于神经网络的交易系统的直接结果。许多好的思路和算法却并未带来期待的结果。
在传递输入参数时,始终会观察到相同的画面。例如,振荡器值的直接传递,以我的观点,这与资产价格没有任何共通之处。振荡器有一个众所周知的问题 — 所谓的背离。这些是开盘价、收盘价、最高价和最低价的值,当直接传递时,它们不携带任何意义,但会给系统带来难以理解的噪音。这些值与任何事物无关,并且随时间推移会有明显的散离。例如,打开任何货币对的日线图,查看收盘价的波动范围。
理论和概念
在本节中,我将讲述一些我为自己分类,并在实验中运用的概念。
- 距离 — 任何指标至另一个指标或其零值的距离。以我的观点,主要原则是将当前状况与历史上的稳定价值链接起来。如果我们直接传递 MA 1 指标的值,我们将得到一个难以理解的样本散离,因为价格值随时间变化,且无任何确定的范围,这意味着分类或统计行为的略微暗示。当我们传达两个指标之间的差值时(例如,以点数为单位的 MA 1 和 MA 100,或 MACD 指标当前零号蜡烛与前 4 根蜡烛数值的距离),情况就不同了。因此,通过使用距离,我们可以判定行情是否远离其平均水平,以及与当前历史样本相比,它是否明显超买或超卖。此外,使用距离,我们判定行情在何处上涨或下跌。该值即可以是正数,也可以是负数。
- 累积 — 计算一个或多个指标相对于彼此、或它们的零点、或其它非零指标零值点的总合值。因此,累积令我们能够判定在某个方向上的特定走势持续了多长时间。如果积累很小,大概现在正在进行盘整。相反,如果积累量很大,则是一个长期趋势。方向取决于符号(- 或 +)。换言之,在盘整“动荡”期间,累积值并不很大,而在趋势期它们则会被取代。
- 倾角 — 指标的当前倾角是通知神经网络当前金融产品处于脉动走势、或其活跃度较差的良好方式。针对某段历史判定指标倾角的能力,例如 10 根蜡烛,已证明其在分析当前局势方面比之从历史里抽样的结果更好。我以弧度测量倾角。这是仅适合我个人的方法,不依赖于图表比例。
示例
使用距离的示例:
- 传递当前零号蜡烛的距离。MA 1 指标相对于 MA 100。MACD 指标当前值相对于其零值。CCI 指标当前值相对于其零值。
#property copyright "2023, Roman Poshtar" #property link "https://www.mql5.com/ru/users/romanuch" #property strict #property version "1.0" input int x1 = 1; input int x2 = 1; input int x3 = 1; int handle_In1S1; int handle_In2S1; int handle_In3S1; int handle_In4S1; double ind_In1S1[]; double ind_In2S1[]; double ind_In3S1[]; double ind_In4S1[]; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ int OnInit() { handle_In1S1=iMA(Symbol(),PERIOD_CURRENT,1,0,MODE_SMA,PRICE_CLOSE); //--- if the handle is not created if(handle_In1S1==INVALID_HANDLE) { return(INIT_FAILED); } //--- handle_In2S1=iMA(Symbol(),PERIOD_CURRENT,100,0,MODE_SMA,PRICE_CLOSE); //--- if the handle is not created if(handle_In2S1==INVALID_HANDLE) { return(INIT_FAILED); } //--- handle_In3S1=iMACD(Symbol(),PERIOD_CURRENT,12,26,9,PRICE_CLOSE); //--- if the handle is not created if(handle_In3S1==INVALID_HANDLE) { return(INIT_FAILED); } //--- handle_In4S1=iCCI(Symbol(),PERIOD_CURRENT,14,PRICE_CLOSE); //--- if the handle is not created if(handle_In4S1==INVALID_HANDLE) { return(INIT_FAILED); } //--- return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { //--- get data from the three buffers of the i-Regr indicator ArraySetAsSeries(ind_In1S1,true); if(!iGetArray(handle_In1S1,0,0,1010,ind_In1S1)) { return; } //--- //--- get data from the three buffers of the i-Regr indicator ArraySetAsSeries(ind_In2S1,true); if(!iGetArray(handle_In2S1,0,0,1010,ind_In2S1)) { return; } //--- //--- get data from the three buffers of the i-Regr indicator ArraySetAsSeries(ind_In3S1,true); if(!iGetArray(handle_In3S1,0,0,1010,ind_In3S1)) { return; } //--- //--- get data from the three buffers of the i-Regr indicator ArraySetAsSeries(ind_In4S1,true); if(!iGetArray(handle_In4S1,0,0,1010,ind_In4S1)) { return; } //--- perceptron1(); } //+------------------------------------------------------------------+ //| The PERCEPRRON - a perceiving and recognizing function | //+------------------------------------------------------------------+ double perceptron1() { double w1 = x1 - 10.0; double w2 = x2 - 10.0; double w3 = x3 - 10.0; double a1 = ((ind_In1S1[0]-ind_In2S1[0])/Point()); double a2 = ind_In3S1[0]; double a3 = ind_In4S1[0]; Print("a1 = ", a1); Print("a2 = ", a2); Print("a3 = ", a3); Print("Perceptron = ", (w1 * a1 + w2 * a2 + w3 * a3)); Print(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"); return (w1 * a1 + w2 * a2 + w3 * a3); }
日志数据:
a1 - MA 1 和 MA 100 指标之间的差值,货币对点数为单位。它可以取正数值和负数值。
a2 - MACD 指标的当前值。它可以取正数值和负数值。
a3 - CCI 指标的当前值。它可以取正数值和负数值。
- 传递过去 N 根蜡烛的距离。MA 1 指标。MA 100 指标。MACD 指标。CCI 指标。
#property copyright "2023, Roman Poshtar" #property link "https://www.mql5.com/ru/users/romanuch" #property strict #property version "1.0" input int Candles= 10; input int x1 = 1; input int x2 = 1; input int x3 = 1; input int x4 = 1; int handle_In1S1; int handle_In2S1; int handle_In3S1; int handle_In4S1; double ind_In1S1[]; double ind_In2S1[]; double ind_In3S1[]; double ind_In4S1[]; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ int OnInit() { handle_In1S1=iMA(Symbol(),PERIOD_CURRENT,1,0,MODE_SMA,PRICE_CLOSE); //--- if the handle is not created if(handle_In1S1==INVALID_HANDLE) { return(INIT_FAILED); } //--- handle_In2S1=iMA(Symbol(),PERIOD_CURRENT,100,0,MODE_SMA,PRICE_CLOSE); //--- if the handle is not created if(handle_In2S1==INVALID_HANDLE) { return(INIT_FAILED); } //--- handle_In3S1=iMACD(Symbol(),PERIOD_CURRENT,12,26,9,PRICE_CLOSE); //--- if the handle is not created if(handle_In3S1==INVALID_HANDLE) { return(INIT_FAILED); } //--- handle_In4S1=iCCI(Symbol(),PERIOD_CURRENT,14,PRICE_CLOSE); //--- if the handle is not created if(handle_In4S1==INVALID_HANDLE) { return(INIT_FAILED); } //--- return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { //--- get data from the three buffers of the i-Regr indicator ArraySetAsSeries(ind_In1S1,true); if(!iGetArray(handle_In1S1,0,0,1010,ind_In1S1)) { return; } //--- //--- get data from the three buffers of the i-Regr indicator ArraySetAsSeries(ind_In2S1,true); if(!iGetArray(handle_In2S1,0,0,1010,ind_In2S1)) { return; } //--- //--- get data from the three buffers of the i-Regr indicator ArraySetAsSeries(ind_In3S1,true); if(!iGetArray(handle_In3S1,0,0,1010,ind_In3S1)) { return; } //--- //--- get data from the three buffers of the i-Regr indicator ArraySetAsSeries(ind_In4S1,true); if(!iGetArray(handle_In4S1,0,0,1010,ind_In4S1)) { return; } //--- perceptron1(); } //+------------------------------------------------------------------+ //| The PERCEPRRON - a perceiving and recognizing function | //+------------------------------------------------------------------+ double perceptron1() { double w1 = x1 - 10.0; double w2 = x2 - 10.0; double w3 = x3 - 10.0; double w4 = x4 - 10.0; double a1 = ((ind_In1S1[0]-ind_In1S1[Candles])/Point()); double a2 = ((ind_In2S1[0]-ind_In2S1[Candles])/Point()); double a3 = ind_In3S1[0]-ind_In3S1[Candles]; double a4 = ind_In4S1[0]-ind_In4S1[Candles]; Print("a1 = ", a1); Print("a2 = ", a2); Print("a3 = ", a3); Print("a3 = ", a4); Print("Perceptron = ", (w1 * a1 + w2 * a2 + w3 * a3 + w4 * a4)); Print(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"); return (w1 * a1 + w2 * a2 + w3 * a3 + w4 * a4); }
日志数据:
a1 - MA 1 指标在蜡烛 0 和蜡烛 10 上的差值,以货币对点数为单位。它可以取正数值和负数值。
a2 - MA 100 指标在蜡烛 0 和蜡烛 10 上差值,以货币对点数为单位。它可以取正数值和负数值。
a3 - MACD 指标在蜡烛 0 和蜡烛 10 上的差值。它可以取正数值和负数值。
a4 - CCI 指标在蜡烛 0 和蜡烛 10 上的差值。它可以取正数值和负数值。
- 传递 MA1 和 MA 100 指标的交叉点相对于其过去的零值的距离。MACD 指标相对于其过去的零值。CCI 指标相对于其过去的零值。
#property copyright "2023, Roman Poshtar" #property link "https://www.mql5.com/ru/users/romanuch" #property strict #property version "1.0" input int Candles= 10; input int x1 = 1; input int x2 = 1; input int x3 = 1; input int x4 = 1; int handle_In1S1; int handle_In2S1; int handle_In3S1; int handle_In4S1; double ind_In1S1[]; double ind_In2S1[]; double ind_In3S1[]; double ind_In4S1[]; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ int OnInit() { handle_In1S1=iMA(Symbol(),PERIOD_CURRENT,1,0,MODE_SMA,PRICE_CLOSE); //--- if the handle is not created if(handle_In1S1==INVALID_HANDLE) { return(INIT_FAILED); } //--- handle_In2S1=iMA(Symbol(),PERIOD_CURRENT,100,0,MODE_SMA,PRICE_CLOSE); //--- if the handle is not created if(handle_In2S1==INVALID_HANDLE) { return(INIT_FAILED); } //--- handle_In3S1=iMACD(Symbol(),PERIOD_CURRENT,12,26,9,PRICE_CLOSE); //--- if the handle is not created if(handle_In3S1==INVALID_HANDLE) { return(INIT_FAILED); } //--- handle_In4S1=iCCI(Symbol(),PERIOD_CURRENT,14,PRICE_CLOSE); //--- if the handle is not created if(handle_In4S1==INVALID_HANDLE) { return(INIT_FAILED); } //--- return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { //--- get data from the three buffers of the i-Regr indicator ArraySetAsSeries(ind_In1S1,true); if(!iGetArray(handle_In1S1,0,0,1010,ind_In1S1)) { return; } //--- //--- get data from the three buffers of the i-Regr indicator ArraySetAsSeries(ind_In2S1,true); if(!iGetArray(handle_In2S1,0,0,1010,ind_In2S1)) { return; } //--- //--- get data from the three buffers of the i-Regr indicator ArraySetAsSeries(ind_In3S1,true); if(!iGetArray(handle_In3S1,0,0,1010,ind_In3S1)) { return; } //--- //--- get data from the three buffers of the i-Regr indicator ArraySetAsSeries(ind_In4S1,true); if(!iGetArray(handle_In4S1,0,0,1010,ind_In4S1)) { return; } //--- perceptron1(); } //+------------------------------------------------------------------+ //| The PERCEPRRON - a perceiving and recognizing function | //+------------------------------------------------------------------+ double perceptron1() { int c1=0; int c2=0; int c3=0; double w1 = x1 - 10.0; double w2 = x2 - 10.0; double w3 = x3 - 10.0; double w4 = x4 - 10.0; for(int i=0; i<=1000; i++){ if(ind_In1S1[0]>ind_In2S1[0]){if (ind_In1S1[i]<ind_In2S1[i]){c1=i; break;}} if(ind_In1S1[0]<ind_In2S1[0]){if (ind_In1S1[i]>ind_In2S1[i]){c1=i; break;}} } double a1 = ((ind_In1S1[0]-ind_In1S1[c1])/Point()); double a2 = ((ind_In2S1[0]-ind_In2S1[c1])/Point()); for(int i=0; i<=1000; i++){ if(ind_In3S1[0]>0){if (ind_In3S1[i]<0){c2=i; break;}} if(ind_In3S1[0]<0){if (ind_In3S1[i]>0){c2=i; break;}} } double a3 = ind_In3S1[0]-ind_In3S1[c2]; for(int i=0; i<=1000; i++){ if(ind_In4S1[0]>0){if (ind_In4S1[i]<0){c3=i; break;}} if(ind_In4S1[0]<0){if (ind_In4S1[i]>0){c3=i; break;}} } double a4 = ind_In4S1[0]-ind_In4S1[c3]; Print("a1 = ", a1); Print("a2 = ", a2); Print("a3 = ", a3); Print("a4 = ", a4); Print("Perceptron = ", (w1 * a1 + w2 * a2 + w3 * a3 + w4 * a4)); Print(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"); return (w1 * a1 + w2 * a2 + w3 * a3 + w4 * a4); }
日志数据:
a1 - MA 1 指标在蜡烛 0 上的数值,与 MA1 和 MA 100 指标最后交叉处蜡烛的差值,以货币对点数为单位。它可以取正数值和负数值。
a2 - MA 100 指标在蜡烛 0 上的数值,与 MA1 和 MA 100 指标最后交叉处蜡烛的差值,以货币对点数为单位。它可以取正数值和负数值。
a3 - 蜡烛 0 上的 MACD 指标值,与其最后一个零值处蜡烛的差值。它可以取正数值和负数值。
a4 - 蜡烛 0 上的 CCI 指标值,与其最后一个零值处蜡烛的差值。它可以取正数值和负数值。
首先在循环中搜索交叉值。
把累积传递给感知器的示例:
- 传递 N 根指标蜡烛的累积。
#property copyright "2023, Roman Poshtar" #property link "https://www.mql5.com/ru/users/romanuch" #property strict #property version "1.0" input int Candles= 10; input int x1 = 1; input int x2 = 1; input int x3 = 1; int handle_In1S1; int handle_In2S1; int handle_In3S1; int handle_In4S1; double ind_In1S1[]; double ind_In2S1[]; double ind_In3S1[]; double ind_In4S1[]; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ int OnInit() { handle_In1S1=iMA(Symbol(),PERIOD_CURRENT,1,0,MODE_SMA,PRICE_CLOSE); //--- if the handle is not created if(handle_In1S1==INVALID_HANDLE) { return(INIT_FAILED); } //--- handle_In2S1=iMA(Symbol(),PERIOD_CURRENT,100,0,MODE_SMA,PRICE_CLOSE); //--- if the handle is not created if(handle_In2S1==INVALID_HANDLE) { return(INIT_FAILED); } //--- handle_In3S1=iMACD(Symbol(),PERIOD_CURRENT,12,26,9,PRICE_CLOSE); //--- if the handle is not created if(handle_In3S1==INVALID_HANDLE) { return(INIT_FAILED); } //--- handle_In4S1=iCCI(Symbol(),PERIOD_CURRENT,14,PRICE_CLOSE); //--- if the handle is not created if(handle_In4S1==INVALID_HANDLE) { return(INIT_FAILED); } //--- return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { //--- get data from the three buffers of the i-Regr indicator ArraySetAsSeries(ind_In1S1,true); if(!iGetArray(handle_In1S1,0,0,1010,ind_In1S1)) { return; } //--- //--- get data from the three buffers of the i-Regr indicator ArraySetAsSeries(ind_In2S1,true); if(!iGetArray(handle_In2S1,0,0,1010,ind_In2S1)) { return; } //--- //--- get data from the three buffers of the i-Regr indicator ArraySetAsSeries(ind_In3S1,true); if(!iGetArray(handle_In3S1,0,0,1010,ind_In3S1)) { return; } //--- //--- get data from the three buffers of the i-Regr indicator ArraySetAsSeries(ind_In4S1,true); if(!iGetArray(handle_In4S1,0,0,1010,ind_In4S1)) { return; } //--- perceptron1(); } //+------------------------------------------------------------------+ //| The PERCEPRRON - a perceiving and recognizing function | //+------------------------------------------------------------------+ double perceptron1() { double sum1 = 0; double sum2 = 0; double sum3 = 0; double w1 = x1 - 10.0; double w2 = x2 - 10.0; double w3 = x3 - 10.0; for(int i=0; i<=Candles; i++) { sum1+=ind_In1S1[i]-ind_In2S1[i]; } double a1 = sum1; for(int i=0; i<=Candles; i++) { sum2+=ind_In3S1[i]; } double a2 = sum2; for(int i=0; i<=Candles; i++) { sum3+=ind_In4S1[i]; } double a3 = sum3; Print("a1 = ", a1); Print("a2 = ", a2); Print("a3 = ", a3); Print("Perceptron = ", (w1 * a1 + w2 * a2 + w3 * a3)); Print(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"); return (w1 * a1 + w2 * a2 + w3 * a3); }
日志数据:
a1 - 累积 MA1 和 MA 100 指标之间 Candles 参数指定数量蜡烛的差值。它可以取正数值和负数值。
a2 - 累积 MACD 指标与 Candles 参数指定数量蜡烛的差值。它可以取正数值和负数值。
a3 - 累积 CCI 指标与 Candles 参数指定数量蜡烛的差值。它可以取正数值和负数值。
- 传递从指标过去的零点、或指标过去最后一个交叉点开始的累积。
#property copyright "2023, Roman Poshtar" #property link "https://www.mql5.com/ru/users/romanuch" #property strict #property version "1.0" input int Candles= 10; input int x1 = 1; input int x2 = 1; input int x3 = 1; int handle_In1S1; int handle_In2S1; int handle_In3S1; int handle_In4S1; double ind_In1S1[]; double ind_In2S1[]; double ind_In3S1[]; double ind_In4S1[]; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ int OnInit() { handle_In1S1=iMA(Symbol(),PERIOD_CURRENT,1,0,MODE_SMA,PRICE_CLOSE); //--- if the handle is not created if(handle_In1S1==INVALID_HANDLE) { return(INIT_FAILED); } //--- handle_In2S1=iMA(Symbol(),PERIOD_CURRENT,100,0,MODE_SMA,PRICE_CLOSE); //--- if the handle is not created if(handle_In2S1==INVALID_HANDLE) { return(INIT_FAILED); } //--- handle_In3S1=iMACD(Symbol(),PERIOD_CURRENT,12,26,9,PRICE_CLOSE); //--- if the handle is not created if(handle_In3S1==INVALID_HANDLE) { return(INIT_FAILED); } //--- handle_In4S1=iCCI(Symbol(),PERIOD_CURRENT,14,PRICE_CLOSE); //--- if the handle is not created if(handle_In4S1==INVALID_HANDLE) { return(INIT_FAILED); } //--- return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { //--- get data from the three buffers of the i-Regr indicator ArraySetAsSeries(ind_In1S1,true); if(!iGetArray(handle_In1S1,0,0,1010,ind_In1S1)) { return; } //--- //--- get data from the three buffers of the i-Regr indicator ArraySetAsSeries(ind_In2S1,true); if(!iGetArray(handle_In2S1,0,0,1010,ind_In2S1)) { return; } //--- //--- get data from the three buffers of the i-Regr indicator ArraySetAsSeries(ind_In3S1,true); if(!iGetArray(handle_In3S1,0,0,1010,ind_In3S1)) { return; } //--- //--- get data from the three buffers of the i-Regr indicator ArraySetAsSeries(ind_In4S1,true); if(!iGetArray(handle_In4S1,0,0,1010,ind_In4S1)) { return; } //--- perceptron1(); } //+------------------------------------------------------------------+ //| The PERCEPRRON - a perceiving and recognizing function | //+------------------------------------------------------------------+ double perceptron1() { double sum1 = 0; double sum2 = 0; double sum3 = 0; double w1 = x1 - 10.0; double w2 = x2 - 10.0; double w3 = x3 - 10.0; for(int i=0; i<=1000; i++) { if(ind_In1S1[0]>ind_In2S1[0]) { if(ind_In1S1[i]<ind_In2S1[i]) { break; }; sum1+=(ind_In1S1[i]-ind_In2S1[i]); } if(ind_In1S1[0]<ind_In2S1[0]) { if(ind_In1S1[i]>ind_In2S1[i]) { break; }; sum1+=(ind_In1S1[i]-ind_In2S1[i]); } } double a1 = sum1; for(int i=0; i<=1000; i++) { if(ind_In3S1[0]>0) { if(ind_In3S1[i]<0) { break; }; sum2+=ind_In3S1[i]; } if(ind_In3S1[0]<0) { if(ind_In3S1[i]>0) { break; }; sum2+=ind_In3S1[i]; } } double a2 = sum2; for(int i=0; i<=1000; i++) { if(ind_In4S1[0]>0) { if(ind_In4S1[i]<0) { break; }; sum3+=ind_In4S1[i]; } if(ind_In4S1[0]<0) { if(ind_In4S1[i]>0) { break; }; sum3+=ind_In4S1[i]; } } double a3 = sum3; Print("a1 = ", a1); Print("a2 = ", a2); Print("a3 = ", a3); Print("Perceptron = ", (w1 * a1 + w2 * a2 + w3 * a3)); Print(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"); return (w1 * a1 + w2 * a2 + w3 * a3); }
日志数据:
a1 - MA1 和 MA 100 指标与最后一个交叉点之间的差值累积。它可以取正数值和负数值。
a2 - MACD 指标从最后一个零值交叉点开始的累积。它可以取正数值和负数值。
a3 - CCI 指标从最后一个零值交叉点开始的累积。它可以取正数值和负数值。
使用指标倾角的示例:
- 传递 N 根指标蜡烛的倾角。
#property copyright "2023, Roman Poshtar" #property link "https://www.mql5.com/ru/users/romanuch" #property strict #property version "1.0" input int Candles= 10; input int x1 = 1; input int x2 = 1; input int x3 = 1; input int x4 = 1; int handle_In1S1; int handle_In2S1; int handle_In3S1; int handle_In4S1; double ind_In1S1[]; double ind_In2S1[]; double ind_In3S1[]; double ind_In4S1[]; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ int OnInit() { handle_In1S1=iMA(Symbol(),PERIOD_CURRENT,1,0,MODE_SMA,PRICE_CLOSE); //--- if the handle is not created if(handle_In1S1==INVALID_HANDLE) { return(INIT_FAILED); } //--- handle_In2S1=iMA(Symbol(),PERIOD_CURRENT,100,0,MODE_SMA,PRICE_CLOSE); //--- if the handle is not created if(handle_In2S1==INVALID_HANDLE) { return(INIT_FAILED); } //--- handle_In3S1=iMACD(Symbol(),PERIOD_CURRENT,12,26,9,PRICE_CLOSE); //--- if the handle is not created if(handle_In3S1==INVALID_HANDLE) { return(INIT_FAILED); } //--- handle_In4S1=iCCI(Symbol(),PERIOD_CURRENT,14,PRICE_CLOSE); //--- if the handle is not created if(handle_In4S1==INVALID_HANDLE) { return(INIT_FAILED); } //--- return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { //--- get data from the three buffers of the i-Regr indicator ArraySetAsSeries(ind_In1S1,true); if(!iGetArray(handle_In1S1,0,0,1010,ind_In1S1)) { return; } //--- //--- get data from the three buffers of the i-Regr indicator ArraySetAsSeries(ind_In2S1,true); if(!iGetArray(handle_In2S1,0,0,1010,ind_In2S1)) { return; } //--- //--- get data from the three buffers of the i-Regr indicator ArraySetAsSeries(ind_In3S1,true); if(!iGetArray(handle_In3S1,0,0,1010,ind_In3S1)) { return; } //--- //--- get data from the three buffers of the i-Regr indicator ArraySetAsSeries(ind_In4S1,true); if(!iGetArray(handle_In4S1,0,0,1010,ind_In4S1)) { return; } //--- perceptron1(); } //+------------------------------------------------------------------+ //| The PERCEPRRON - a perceiving and recognizing function | //+------------------------------------------------------------------+ double perceptron1() { double w1 = x1 - 10.0; double w2 = x2 - 10.0; double w3 = x3 - 10.0; double w4 = x4 - 10.0; double a1 = (((ind_In1S1[0]-ind_In1S1[Candles])/Point())/Candles); double a2 = (((ind_In2S1[0]-ind_In2S1[Candles])/Point())/Candles); double a3 = ((ind_In3S1[0]-ind_In3S1[Candles])/Candles); double a4 = ((ind_In4S1[0]-ind_In4S1[Candles])/Candles); Print("a1 = ", a1); Print("a2 = ", a2); Print("a3 = ", a3); Print("a4 = ", a4); Print("Perceptron = ", (w1 * a1 + w2 * a2 + w3 * a3 + w4 * a4)); Print(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"); return (w1 * a1 + w2 * a2 + w3 * a3 + w4 * a4); }
日志数据:
a1 - MA1 指标与 Candles 参数指定数量蜡烛的倾角。它可以取正数值和负数值。
a2 - MA100 指标与 Candles 参数指定数量蜡烛的倾角。它可以取正数值和负数值。
a3 - MACD 指标与 Candles 参数指定数量蜡烛的倾角。它可以取正数值和负数值。
a4 - CCI 指标与 Candles 参数指定数量蜡烛的倾角。它可以取正数值和负数值。
- 传递指标与过去的零点、或过去的最后一个交叉点的倾角。
#property copyright "2023, Roman Poshtar" #property link "https://www.mql5.com/ru/users/romanuch" #property strict #property version "1.0" input int x1 = 1; input int x2 = 1; input int x3 = 1; input int x4 = 1; int handle_In1S1; int handle_In2S1; int handle_In3S1; int handle_In4S1; double ind_In1S1[]; double ind_In2S1[]; double ind_In3S1[]; double ind_In4S1[]; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ int OnInit() { handle_In1S1=iMA(Symbol(),PERIOD_CURRENT,1,0,MODE_SMA,PRICE_CLOSE); //--- if the handle is not created if(handle_In1S1==INVALID_HANDLE) { return(INIT_FAILED); } //--- handle_In2S1=iMA(Symbol(),PERIOD_CURRENT,100,0,MODE_SMA,PRICE_CLOSE); //--- if the handle is not created if(handle_In2S1==INVALID_HANDLE) { return(INIT_FAILED); } //--- handle_In3S1=iMACD(Symbol(),PERIOD_CURRENT,12,26,9,PRICE_CLOSE); //--- if the handle is not created if(handle_In3S1==INVALID_HANDLE) { return(INIT_FAILED); } //--- handle_In4S1=iCCI(Symbol(),PERIOD_CURRENT,14,PRICE_CLOSE); //--- if the handle is not created if(handle_In4S1==INVALID_HANDLE) { return(INIT_FAILED); } //--- return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { //--- get data from the three buffers of the i-Regr indicator ArraySetAsSeries(ind_In1S1,true); if(!iGetArray(handle_In1S1,0,0,1010,ind_In1S1)) { return; } //--- //--- get data from the three buffers of the i-Regr indicator ArraySetAsSeries(ind_In2S1,true); if(!iGetArray(handle_In2S1,0,0,1010,ind_In2S1)) { return; } //--- //--- get data from the three buffers of the i-Regr indicator ArraySetAsSeries(ind_In3S1,true); if(!iGetArray(handle_In3S1,0,0,1010,ind_In3S1)) { return; } //--- //--- get data from the three buffers of the i-Regr indicator ArraySetAsSeries(ind_In4S1,true); if(!iGetArray(handle_In4S1,0,0,1010,ind_In4S1)) { return; } //--- perceptron1(); } //+------------------------------------------------------------------+ //| The PERCEPRRON - a perceiving and recognizing function | //+------------------------------------------------------------------+ double perceptron1() { int c1=0; int c2=0; int c3=0; double w1 = x1 - 10.0; double w2 = x2 - 10.0; double w3 = x3 - 10.0; double w4 = x4 - 10.0; for(int i=0; i<=1000; i++) { if(ind_In1S1[0]>ind_In2S1[0]) { if(ind_In1S1[i]<ind_In2S1[i]) { c1=i; break; } } if(ind_In1S1[0]<ind_In2S1[0]) { if(ind_In1S1[i]>ind_In2S1[i]) { c1=i; break; } } } double a1 = (((ind_In1S1[0]-ind_In1S1[c1])/Point())/c1); double a2 = (((ind_In2S1[0]-ind_In2S1[c1])/Point())/c1); for(int i=0; i<=1000; i++) { if(ind_In3S1[0]>0) { if(ind_In3S1[i]<0) { c2=i; break; } } if(ind_In3S1[0]<0) { if(ind_In3S1[i]>0) { c2=i; break; } } } double a3 = ((ind_In3S1[0]-ind_In3S1[c2])/c2); for(int i=0; i<=1000; i++) { if(ind_In4S1[0]>0) { if(ind_In4S1[i]<0) { c3=i; break; } } if(ind_In4S1[0]<0) { if(ind_In4S1[i]>0) { c3=i; break; } } } double a4 = ((ind_In4S1[0]-ind_In4S1[c3])/c3); Print("a1 = ", a1); Print("a2 = ", a2); Print("a3 = ", a3); Print("a4 = ", a4); Print("Perceptron = ", (w1 * a1 + w2 * a2 + w3 * a3 + w4 * a4)); Print(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"); return (w1 * a1 + w2 * a2 + w3 * a3 + w4 * a4); }
日志数据:
a1 - MA1 指标与 MA1 和 MA100 指标最后一个交叉点开始的斜角。它可以取正数值和负数值。
a2 - MA100 指标与 MA1 和 MA100 指标最后一个交叉点开始的斜角。它可以取正数值和负数值。
a3 - MACD 指标与最后一个零值交叉点开始的斜角。它可以取正数值和负数值。
a4 - CCI 指标与最后一个零值交叉点开始的斜角。它可以取正数值和负数值。
传递组合值至感知器的示例:
- MA1 和 MA100 指标值的组合传递。
#property copyright "2023, Roman Poshtar" #property link "https://www.mql5.com/ru/users/romanuch" #property strict #property version "1.0" input int Candles= 10; input int x1 = 1; input int x2 = 1; input int x3 = 1; input int x4 = 1; input int x5 = 1; input int x6 = 1; input int x7 = 1; int handle_In1S1; int handle_In2S1; double ind_In1S1[]; double ind_In2S1[]; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ int OnInit() { handle_In1S1=iMA(Symbol(),PERIOD_CURRENT,1,0,MODE_SMA,PRICE_CLOSE); //--- if the handle is not created if(handle_In1S1==INVALID_HANDLE) { return(INIT_FAILED); } //--- handle_In2S1=iMA(Symbol(),PERIOD_CURRENT,100,0,MODE_SMA,PRICE_CLOSE); //--- if the handle is not created if(handle_In2S1==INVALID_HANDLE) { return(INIT_FAILED); } //--- return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { //--- get data from the three buffers of the i-Regr indicator ArraySetAsSeries(ind_In1S1,true); if(!iGetArray(handle_In1S1,0,0,1010,ind_In1S1)) { return; } //--- //--- get data from the three buffers of the i-Regr indicator ArraySetAsSeries(ind_In2S1,true); if(!iGetArray(handle_In2S1,0,0,1010,ind_In2S1)) { return; } //--- perceptron1(); } //+------------------------------------------------------------------+ //| The PERCEPRRON - a perceiving and recognizing function | //+------------------------------------------------------------------+ double perceptron1() { int c1=0; double sum1 = 0; double sum2 = 0; double w1 = x1 - 10.0; double w2 = x2 - 10.0; double w3 = x3 - 10.0; double w4 = x4 - 10.0; double w5 = x5 - 10.0; double w6 = x6 - 10.0; double w7 = x7 - 10.0; double a1 = ((ind_In1S1[0]-ind_In2S1[0])/Point()); for(int i=0; i<=Candles; i++) { sum1+=ind_In1S1[i]-ind_In2S1[i]; } double a2 = sum1; for(int i=0; i<=1000; i++) { if(ind_In1S1[0]>ind_In2S1[0]) { if(ind_In1S1[i]<ind_In2S1[i]) { break; }; sum2+=(ind_In1S1[i]-ind_In2S1[i]); } if(ind_In1S1[0]<ind_In2S1[0]) { if(ind_In1S1[i]>ind_In2S1[i]) { break; }; sum2+=(ind_In1S1[i]-ind_In2S1[i]); } } double a3 = sum2; double a4 = (((ind_In1S1[0]-ind_In1S1[Candles])/Point())/Candles); double a5 = (((ind_In2S1[0]-ind_In2S1[Candles])/Point())/Candles); for(int i=0; i<=1000; i++) { if(ind_In1S1[0]>ind_In2S1[0]) { if(ind_In1S1[i]<ind_In2S1[i]) { c1=i; break; } } if(ind_In1S1[0]<ind_In2S1[0]) { if(ind_In1S1[i]>ind_In2S1[i]) { c1=i; break; } } } double a6 = (((ind_In1S1[0]-ind_In1S1[c1])/Point())/c1); double a7 = (((ind_In2S1[0]-ind_In2S1[c1])/Point())/c1); Print("a1 = ", a1); Print("a2 = ", a2); Print("a3 = ", a3); Print("a4 = ", a4); Print("a5 = ", a5); Print("a6 = ", a6); Print("a7 = ", a7); Print("Perceptron = ", (w1 * a1 + w2 * a2 + w3 * a3 + w4 * a4 + w5 * a5 + w6 * a6 + w7 * a7)); Print(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"); return (w1 * a1 + w2 * a2 + w3 * a3 + w4 * a4 + w5 * a5 + w6 * a6 + w7 * a7); }
日志数据:
a1 - 当前蜡烛上 MA1 和 MA100 之间的距离。它可以取正数值和负数值。
a2 - 累积指标 MA1 和 MA100 之间 Candles 参数指定数量蜡烛的差值。它可以取正数值和负数值。
a3 - 累积从 MA1 和 MA100 指标最后一个交叉点开始的差值。它可以取正数值和负数值。
a4 - MA1 指标与 Candles 参数指定数量蜡烛的倾角。它可以取正数值和负数值。
a5 - MA100 指标与 Candles 参数指定数量蜡烛的倾角。它可以取正数值和负数值。
a6 - MA1 指标与最后一个交叉点的倾角。它可以取正数值和负数值。
a7 - MA100 指标与最后一个交叉点的斜角。它可以取正数值和负数值。
智能系统
于此,我们将开发两个 EA。例如,我们将采用指标之间距离值。第一个是为了优化和选择参数而实现的。第二个旨在据第一个获得的结果进行交易。我在之前的文章中曾研究过这种方式。这种方法有助于在交易中整理和使用所有可用的优化结果。例如,我们在优化过程中获得了 50 个优良的结果。正如您也许想象的那样,在 50 个图表上安装 EA 很不方便。因此,我们将在第二个 EA 的帮助下同时使用所有结果。
在我的文章《神经网络实验(第 3 部分):实际应用》中了解有关该方法的更多信息。
我将在下面提供第一个 EA 的主代码进行优化,并讲述我们传递给感知器的内容:
开仓的主要代码。
//SELL++++++++++++++++++++++++++++++++++++++++++++++++ if((perceptron1()<-Param) && (CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_SELL, EAComment)==0) && (SpreadS1<=MaxSpread)) { OpenSell(symbolS1.Name(), LotsXSell, TP, SL, EAComment); } //BUY++++++++++++++++++++++++++++++++++++++++++++++++ if((perceptron1()>Param) && (CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_BUY, EAComment)==0) && (SpreadS1<=MaxSpread)) { OpenBuy(symbolS1.Name(), LotsXBuy, TP, SL, EAComment); }
感知器代码。
- a1 是当前蜡烛上的 MA1 指标与 Candles 参数中指定数量蜡烛之间的距离。
- a2 是当前蜡烛上的 MA100 指标与 Candles 参数中指定数量蜡烛之间的距离。
- a3 是当前蜡烛上的 CCI 指标与 Candles 参数中指定数量蜡烛之间的距离。
- a4 是当前蜡烛上的 StdDev 指标与 Candles 参数中指定数量蜡烛之间的距离。
在本例中,Candles 参数未优化,其值为 8。
//+------------------------------------------------------------------+ //| The PERCEPRRON - a perceiving and recognizing function | //+------------------------------------------------------------------+ double perceptron1() { double w1 = x1 - 10.0; double w2 = x2 - 10.0; double w3 = x3 - 10.0; double w4 = x4 - 10.0; double a1 = ((ind_In1S1[0]-ind_In1S1[Candles])/PointS1); double a2 = ((ind_In2S1[0]-ind_In2S1[Candles])/PointS1); double a3 = (ind_In3S1[0]-ind_In3S1[Candles]); double a4 = (ind_In4S1[0]-ind_In4S1[Candles]); return (w1 * a1 + w2 * a2 + w3 * a3 + w4 * a4); }
在此,我将提供优化和测试的所有参数,以免在文本中重复它们:
- 外汇市场
- EURUSD;
- 时间帧: H1;
- 指标: MA 1 SMA CLOSE, MA 200 SMA CLOSE, CCI 42, StdDev 60。
- 止损和止盈,400 和 830;
- 优化和测试模式“1 分钟 OHLC”和“最大盈利”。我们的 EA 最初据 M1 开盘价运行。在此,我们将采用“最大盈利”模式作为实验;
- 优化范围:1 年。从 2021.10.10 到 2022.10.10。1 年不是某种准则。您可以自行尝试或多或少
- 正向测试范围为 1 年。2022.10.10 至 2023.10.10;
- 在前向测试中,同时使用前 50 个最佳优化结果;
- 初始存款 10000;
- 杠杆 1:500。
下面的屏幕截图中提供了优化设置:
优化结果如下图所示:
优化完成后,使用 Excel 生成 CSV 格式的文件。我要提醒您,我们用了前 50 个最佳结果。将生成的文件粘贴到第二个 EA 的代码中进行测试。它在代码中如下所示。
string EURUSD[][8]= { {"Profit","Trades","x1","x2","x3","x4","Param"}, {"266.45","239","2","1","9","8","5000"}, {"266.45","239","2","1","9","13","5000"}, {"266.45","239","2","1","9","11","5000"}, {"266.45","239","2","1","9","10","5000"}, {"266.45","239","2","1","9","8","5000"}, {"266.45","239","2","1","9","12","5000"}, {"266.45","239","2","1","9","20","5000"}, {"266.45","239","2","1","9","14","5000"}, {"266.45","239","2","1","9","2","5000"}, {"266.45","239","2","1","9","3","5000"}, {"259.69","239","0","0","12","17","5500"}, {"259.69","239","0","0","12","8","5500"}, {"259.69","239","0","0","12","1","5500"}, {"259.69","239","0","0","12","9","5500"}, {"259.69","239","0","0","12","16","5500"}, {"259.69","239","0","0","12","18","5500"}, {"259.69","239","0","0","12","11","5500"}, {"259.69","239","0","0","12","7","5500"}, {"259.69","239","0","0","12","15","5500"}, {"259.69","239","0","0","12","8","5500"}, {"259.69","239","0","0","12","9","5500"}, {"259.69","239","0","0","12","17","5500"}, {"259.69","239","0","0","12","6","5500"}, {"259.69","239","0","0","12","15","5500"}, {"259.69","239","0","0","12","4","5500"}, {"259.69","239","0","0","12","7","5500"}, {"259.69","239","0","0","12","11","5500"}, {"259.69","239","0","0","12","14","5500"}, {"259.69","239","0","0","12","1","5500"}, {"259.69","239","0","0","12","5","5500"}, {"259.69","239","0","0","12","3","5500"}, {"259.69","239","0","0","12","0","5500"}, {"259.69","239","0","0","12","12","5500"}, {"259.69","239","0","0","12","16","5500"}, {"259.69","239","0","0","12","8","5500"}, {"259.69","239","0","0","12","10","5500"}, {"259.69","239","0","0","12","16","5500"}, {"259.69","239","0","0","12","18","5500"}, {"259.69","239","0","0","12","13","5500"}, {"259.69","239","0","0","12","9","5500"}, {"259.69","239","0","0","12","12","5500"}, {"259.69","239","0","0","12","11","5500"}, {"259.69","239","0","0","12","7","5500"}, {"259.69","239","0","0","12","15","5500"}, {"259.69","239","0","0","12","14","5500"}, {"259.69","239","0","0","12","3","5500"}, {"259.69","239","0","0","12","19","5500"}, {"259.69","239","0","0","12","0","5500"}, {"259.69","239","0","0","12","17","5500"}, {"259.69","239","0","0","12","2","5500"} };
我还提供了第二个交易 EA 的代码。正如您所见,我们在循环中遍历了优化期间获得的所有值,并将它们与感知器执行的当前结果进行了比较。如果数值匹配,则相应开立买入或卖出仓位。同时开仓数量限制由 MaxSeries 参数和 CalculateSeries 函数控制,该函数按照注释计算仓位。
for(int i=1; i<=(ArraySize(EURUSD)/8)-1; i++) { comm=(EURUSD[i][0]+EURUSD[i][1]); x1=(int)StringToInteger(EURUSD[i][2]); x2=(int)StringToInteger(EURUSD[i][3]); x3=(int)StringToInteger(EURUSD[i][4]); x4=(int)StringToInteger(EURUSD[i][5]); Param=(int)StringToInteger(EURUSD[i][6]); //SELL++++++++++++++++++++++++++++++++++++++++++++++++ if((NewOpen==true) && (CalculateSeries(Magic)<MaxSeries) && (perceptron1()<-Param) && (CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_SELL, EAComment+" En_"+comm)==0) && (SpreadS1<=MaxSpread)) { OpenSell(symbolS1.Name(), LotsXSell, TP, SL, EAComment+" En_"+comm); } //BUY++++++++++++++++++++++++++++++++++++++++++++++++ if((NewOpen==true) && (CalculateSeries(Magic)<MaxSeries) && (perceptron1()>Param) && (CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_BUY, EAComment+" En_"+comm)==0) && (SpreadS1<=MaxSpread)) { OpenBuy(symbolS1.Name(), LotsXBuy, TP, SL, EAComment+" En_"+comm); } }
//+------------------------------------------------------------------+ //| Calculate Positions | //+------------------------------------------------------------------+ int CalculateSeries(ulong mag) { int total=0; string com=""; for(int i=PositionsTotal()-1; i>=0; i--) { if(position.SelectByIndex(i)) { if(position.Magic()==mag) { if(com!=position.Comment()) { com=position.Comment(); total++; } } } } //--- return(total); }
反向测试结果:
正向测试结果:
结束语
附件中的文件清单:
- Distance 1, Distance 2, Distance 3 — 传递距离至感知器的 EA 示例;
- Accumulation 1, Accumulation 2 — 传递积累至感知器的 EA 示例;
- Angle 1, Angle 2 — 传递指标倾角至感知器的 EA 示例;
- Combo 1 — 传递组合指标数据至感知器的 EA 示例;
- Perceptron–opt — 优化 EA;
- Perceptron – trade — 优化交易参数的 EA。
正如从前向测试结果所见,我们传递指标的方式效果很好。针对前六个月,EA 非常自信地将余额推高。上面,我提供了各种传递指标的例子。您也许有兴趣测试它们。这次做了很多工作,但有些事情需要始终努力。
如果您有任何问题,随时在论坛或私信中与我联系。我将永远乐意为您提供帮助。
本文由MetaQuotes Ltd译自俄文
原文地址: https://www.mql5.com/ru/articles/13598