去年年底结束的国际大赛的第一名为Better所夺得,他采用的就是神经网络原理的EA,这使得用神经网络方法做EA成为不少人关注的焦点。这里翻译一篇采用神经网络做EA的不错的示例文章,当然附有源码是吸引人的地方,不过也许作者提出了研究神经网络EA的一些思考更为值得注意。
作者提出了∶
1。“如果有飞机,为什么还要教人类去飞?”
意思是研究是经网络不必从零起步。MT4里已有了不错的“遗传算法”
文中介绍了如何利用MT4已有的“遗传算法”
2。大家都说做单子最重要的是“顺势而为”,但更需要解决的是∶
“一个基于趋势的交易系统是不能成功交易在盘整(sideways trends),
也不能识别市场的回调(setbacks)和逆转(reversals.,反向走势)!”
这可是抓到不少人心中的“痒处”,有多少人不是到了该逆势时没转向而产生亏损呢?
3。训练神经网络需要用多长的历史数据,提出了并不是用的历史数据越长越好,另外也不是训练的间隔越短越好,文中提出了什么情况下有需再训练它。
等等。。
(ATS)自动的(智能的,采用神经网络的)交易系统的问题表述如下
如果我们有一个(BTS, basic trading system),同时需要用创建一个神经网络系统并教会它做BTS所不能做的事,按这个思路就是要创建这样一个交易系统∶它由互相补充(配合)的两部分组成,BTS和NN(神经网络)。
呃,英语说,我们不需要再去发现“新大陆”,它们是已经存在的东西!进一步说,如果我们已经有了汽车,那为什么还要教人如何跑得快?如果有飞机,为什么还要教人类去飞?
一旦有一个趋势交易系统的ATS,我们仅需要教会这个神经网络如何逆势(反趋势)交易的策略。这一点是非常必要的,因为一个基于趋势的交易系统是不能成功交易在盘整(sideways trends),也不能识别市场的回调(setbacks)和逆转(reversals.,反向走势)!当然,你可以采用两个ATS,一个基于“趋势”,一个基于“反趋势”(逆向),然后把它们挂到同一图表上。另一个办法是,你能教会神经网络如何与你现有的系统“互补地”协调工作!
为实现这个目标,我们设计了一个两层的神经网络,下层有两个感知机(perceptrons)上层有一个感知机。
这个神经网络的能输出下列三种状态之一
进场做多
进场做空 实际上,第三种状态是就把控制权交给BTS,反之前两种状态是交易信号由神经网络给出。
神经网络的“教育”分成三步骤,每一步骤“教育”一个感知机,在任何一步骤,这个优化了的BTS必须存在为的是“感知机们”知道它自己能做什么。 感知机们分别的“教育”由遗传算法来承担,由于这样的算法的缺乏,换句话说,搜索到的这样的算法有限,限制了“输入”(参数变量)的数量(借助这样算法得到的参数变量的值),然而,每一步骤的“教育”是密切配合补充的。(因此效果还是不错),这样这个神经网络不会太大,整个的优化也不会耗费太多的时间。
为了不使我们自己也被搞糊涂了,我们将已经测试通过的ATS的输入(参数变量)记录上(”通过”("pass")的步骤号(stage number).,输入s(参数变量)的标识符将和stage number(步骤号)一致(等同)。
这样,我们开始对这个NN进行优化和“教育”的准备。设置初始保证金为$100万(以便于在优化期间不产生人为的补充保证金的通知)。Input(参数变量)是按“余额”进行优化,设置EA的Strategy Tester的测试的属性tab为"Testing" 。开始运行遗传算法。
在这个EA的开仓量 "lots".的值设为0.1 lot。
从这个ATS算法明确地有效开始,实施优化,所采用复盘模型是∶“仅用开盘价(以最快速的方法分析刚形成的柱线)”。
优化步骤1,BTS的优化
设置为 1 为这input(参数变量)“为通过”(the input "pass")。我们仅仅优化步骤1相关的那些inputs(参数变量),即,尾标为 1 的参数变量,于是,我们仅仅测试优化有关的inputs而不测试其他的变量参数
tp1,BTS的所取的止盈值(TakeProfit)。在step 1,优化的值的范围在10到100,
sl1,BTS的所取的止损值(StopLoss)。在step 1,优化的值的范围在10到100 。
p1,用于BTS的CCI的周期值。在step 1 ,优化的值的范围在 3到100
下面是BTS优化的结果
步骤 2 ,“教育负责“开空仓”(short positions)的感知机
根据步骤的步骤号,设置(input,参数变量) 的"pass"的值为 2。
不测试那些已经测试过的优化了的以前步骤的inputs.(变量参数)。以防万一,保存以前步骤获得的inputs(变量参数值)到一个文件中去
根据我们的规则,必须是测试那些是在尾标为 2的inputs(变量参数)。
x12, x22, x32, x42 是识别并开空仓的感知机的权重,它们的值在step 1时被优化在范围0 to 200
tp2 (TakeProfit) 是感知机所开的仓的止盈值,它们的值在step 1时被优化在范围10 to 100。
sl2 (StopLos) 在 step 1它是感知机所开的仓的止损值,被优化值的范围在 10 to 100
p2 感知机所分析的价格差的周期值 (iiCCI()函数的一个参数∶period - Averaging period for calculation),在step 1 它的值所优化的范围在3 to 100
现在,开始用遗传算法来优化“教育”NN(让它“学习”市场),获得的结果如下∶
步骤 3 “教育”负责开多仓的感知机(“学习”市场)。
设置值 3 (根据步骤的步骤号)说明这些input(变量参数)已经“通过”(the input "pass")
同样,不测试,那些已经测试过的优化了的,以前步骤的inputs.(变量参数值),以防万一,保存以前步骤获得的inputs.(变量参数值) 到一个文件中去
根据我们的规则,优化测试的inputs(变量参数值)必须是尾标为3的那些变量参数。
x13, x23, x33, x43是识别多仓的感知机的权重,它们的值在step 1时被优化时得到的范围在0 to 200
tp 3 (TakeProfit) 是感知机所开的仓的“止盈值”,它的值在step 1时被优化时的范围是在10 to 100。
sl3 (StopLoss) 是感知机所开的仓的“止盈值”,它们的值在step 1时被优化为范围是10 to 100。
p3 --感知机所分析的价差的周期值。它在步骤 1 优化时得到的值的范围是 3 to 100 。
启动采用遗传算法的优化来“教育”NN,所获得的结果如下∶
步骤 4 (最终步骤) “教育”第一层,即“教育”在上层的感知机。
Set the value 4 (according to the stage number) for the input "pass".
根据步骤的步骤号,设置值4 为输入通过(for the input "pass")
不测试那些在之前步骤已经测试过的优化了的“输入” (inputs) (意思是∶已经在之前步骤优化过的变量的参数值就不再优化它们了)。以防万一,将之前步骤获得的这些变量的参数值存到一个文件中去。
根据我们的规则,只测试优化标识符最后位是4的那些inputs(变量的参数值)
x14, x24, x34, x44 是第一层感知机参数的权重值。在步骤 1 时它们被优化的值的范围在0 to 200 。
p4 被感知机分析的价差的值的周期。在步骤 1 它的值的范围被优化在 3 to 100 。
采用遗传算法来优化,启动“教育”来教它“学习”。所获得结果如下∶
这就是全部,神经网络已经被“教育”了。
这个ATS有一个不能被优化的input(参数) mn-- Magic Number.(魔法号)它是一个交易系统它所开的仓位的识别符,为的是不和手动开仓或其他ATSes开的仓位混淆。这个Magic Number的值必须是唯一的并且和这个特别的EA尚未开仓的magic numbers不一致。
P.S.
出于保证有一些安全保险的考虑,初始保证金的金额设置是考虑为绝对最大回落的两倍
这个EA的源代码没有优化。
如果你需要置换嵌入另一个交易系统算法的BTS,你必须修改BTS功能的内部。
以便于不输入优化时的初值,终值和步长,你可采用已备好的combo.set文件,把它放置到MT4的 \tester 目录并加载这个EA的属性(properties)到Strategy Tester。
这个EA的再优化可在周末进行,即周六和周日,但仅在前面一周的结果是不盈利的。亏损的出现意味着市场已经改变,于是需要重新优化,若是仍然获利意味着这个ATS不需要重新优化,它对市场目前的模型的识别继续有效! 源码: //+------------------------------------------------------------------+
//| Combo_Right.mq4 |
//|| Copyright 2010, fx68com@gmail.com||
//|| http://www.fx68.com ||
//+------------------------------------------------------------------+
#property copyright "Copyright 2010, fx68com@gmail.com"
#property link "http://www.fx68.com" //---- input parameters
extern double tp1 = 50;
extern double sl1 = 50;
extern int p1 = 10;
extern int x12 = 100;
extern int x22 = 100;
extern int x32 = 100;
extern int x42 = 100;
extern double tp2 = 50;
extern double sl2 = 50;
extern int p2 = 20;
extern int x13 = 100;
extern int x23 = 100;
extern int x33 = 100;
extern int x43 = 100;
extern double tp3 = 50;
extern double sl3 = 50;
extern int p3 = 20;
extern int x14 = 100;
extern int x24 = 100;
extern int x34 = 100;
extern int x44 = 100;
extern int p4 = 20;
extern int pass = 1;
extern double lots = 0.1;
extern int mn = 888;
static int prevtime = 0;
static double sl = 10;
static double tp = 10; //+------------------------------------------------------------------+
//| expert start function |
//+------------------------------------------------------------------+
int start()
{
if (Time[0] == prevtime) return(0);
prevtime = Time[0];
if (! IsTradEAllowed()) {
again();
return(0);
}
//----
int total = OrdersTotal();
for (int i = 0; i < total; i++) {
OrderSelect(i, SELECT_BY_POS, MODE_TRADES);
if (OrderSymbol() == Symbol() && OrderMagicNumber() == mn) {
return(0);
}
}
sl = sl1;
tp = tp1;
int ticket = -1;
RefreshRates();
if (Supervisor() > 0) {
ticket = OrderSend(Symbol(), OP_BUY, lots, NormalizeDouble(Ask,Digits), 1, NormalizeDouble(Bid - sl * Point,Digits), NormalizeDouble(Bid + tp * Point,Digits), WindowExpertName(), mn, 0, Blue);
if (ticket < 0) {
again();
}
} else {
ticket = OrderSend(Symbol(), OP_SELL, lots, NormalizeDouble(Bid,Digits), 1, NormalizeDouble(Ask + sl * Point,Digits),NormalizeDouble(Ask - tp * Point,Digits), WindowExpertName(), mn, 0, Red);
if (ticket < 0) {
again();
}
}
//-- Exit --
return(0);
}
//+--------------------------- getLots ----------------------------------+
double Supervisor() {
if (pass == 4) {
if (perceptron3() > 0) {
if (perceptron2() > 0) {
sl = sl3;
tp = tp3;
return(1);
}
} else {
if (perceptron1() < 0) {
sl = sl2;
tp = tp2;
return(-1);
}
}
return(basicTradingSystem());
}
if (pass == 3) {
if (perceptron2() > 0) {
sl = sl3;
tp = tp3;
return(1);
} else {
return(basicTradingSystem());
}
} if (pass == 2) {
if (perceptron1() < 0) {
sl = sl2;
tp = tp2;
return(-1);
} else {
return(basicTradingSystem());
} }
return(basicTradingSystem());
} double perceptron1() {
double w1 = x12 - 100;
double w2 = x22 - 100;
double w3 = x32 - 100;
double w4 = x42 - 100;
double a1 = Close[0] - Open[p2];
double a2 = Open[p2] - Open[p2 * 2];
double a3 = Open[p2 * 2] - Open[p2 * 3];
double a4 = Open[p2 * 3] - Open[p2 * 4];
return(w1 * a1 + w2 * a2 + w3 * a3 + w4 * a4);
} double perceptron2() {
double w1 = x13 - 100;
double w2 = x23 - 100;
double w3 = x33 - 100;
double w4 = x43 - 100;
double a1 = Close[0] - Open[p3];
double a2 = Open[p3] - Open[p3 * 2];
double a3 = Open[p3 * 2] - Open[p3 * 3];
double a4 = Open[p3 * 3] - Open[p3 * 4];
return(w1 * a1 + w2 * a2 + w3 * a3 + w4 * a4);
} double perceptron3() {
double w1 = x14 - 100;
double w2 = x24 - 100;
double w3 = x34 - 100;
double w4 = x44 - 100;
double a1 = Close[0] - Open[p4];
double a2 = Open[p4] - Open[p4 * 2];
double a3 = Open[p4 * 2] - Open[p4 * 3];
double a4 = Open[p4 * 3] - Open[p4 * 4];
return(w1 * a1 + w2 * a2 + w3 * a3 + w4 * a4);
} double basicTradingSystem() {
return(iCCI(Symbol(), 0, p1, PRICE_OPEN, 0));
} void again() {
prevtime = Time[1];
Sleep(30000);
}
必胜注:关注神经网络应用的朋友越来越多,我们收集了这篇文章供大家参考。但是这篇文章的做法似乎只是系统测试优化的简化版,分步测试,减少了组合的次数,但几步最优的组合在一起未必结果最优。当然他这个EA是把信号分别发出,1-4的部分之间相对独立,这样测试也是可以的,也就基本等同于全部一次性测试。如果不是这种结构的话,就会失去很多有利的参数组合。真正的神经网络应该是交互式的自动获取有利参数。另外,设置步骤写的不够清楚,似乎这样更明确: 训练方法:
1 打开智能交易测试界面,选择Combo_Right,单击“智能交易属性”按钮,将起始资金设置为1000000(为了避免中途没钱,所以资金设置大一点)。
2 切换到“输入参数”选项卡,单击“加载”按钮,将combo.set里的参数加载到EA中。
3 在参数“tp1”、“sl1”和“p1”前打上勾,将“pass”参数设置为1,单击“确定”按钮退出。
4 在智能交易测试界面,选择“优化”复选项,然后选择一个商品,复盘模型设置为“仅用开盘价”(这个EA只对每根K线的收盘价进行分析,因此选用“每个即时价位”结果是一样的,而花的时间要多得多,所以没有必要),选择起始日期(俺推荐先试试2个月的长度),时间周期任意吧,作者给的图是一小时,因此我测试的时候也是用的一小时。选择好以后,单击“开始”按钮。 5 优化完毕,将最优结果备份,然后单击“智能交易属性”按钮,切换到“输入参数”选项卡,将“tp1”、“sl1”和“p1”前面的勾去掉,并将刚才的最优结果输入到“赋值”一栏。
6 在所有尾号为“2”的参数前打上勾,将“pass”参数设置为2,单击“确定”按钮退出,单击“开始”按钮。
7 优化完毕,将最优结果备份,然后单击“智能交易属性”按钮,切换到“输入参数”选项卡,将所有尾号为“2”的参数前面的勾去掉,并将刚才的最优结果输入到“赋值”一栏。
8 在所有尾号为“3”的参数前打上勾,将“pass”参数设置为3,单击“确定”按钮退出,单击“开始”按钮。
9 优化完毕,将最优结果备份,然后单击“智能交易属性”按钮,切换到“输入参数”选项卡,将所有尾号为“3”的参数前面的勾去掉,并将刚才的最优结果输入到“赋值”一栏。
10 在所有尾号为“4”的参数前打上勾,将“pass”参数设置为4,单击“确定”按钮退出,单击“开始”按钮。
11 优化完毕,将最优结果备份,然后单击“智能交易属性”按钮,切换到“输入参数”选项卡,将所有尾号为“4”的参数前面的勾去掉,并将刚才的最优结果输入到“赋值”一栏。
12 单击“保存”按钮,将最优参数保存为一个文件。
训练完毕,现在你手里有了针对某个特定货币、某个特定时间周期在某个时间段的最优参数,然而,这只是根据历史数据进行的最优化,至于实测的效果,则要挂着观察了。实测时,“pass”参数一定要设置为4! |