本随机震荡神经网络是以函数库的形式构建的, 用于MQL4开发的EA交易. 本函数库可以同时包含多个网络. 我曾经尝试让网络最大限度地独立, 但是我很快决定首先把一些功能放到外面进行管理以能够更好控制. 我就以这样的形式提供它. 这个网络的特点是, 它的大小能够根据情况动态改变. 网络可以通过基本(Primary)的训练然后在工作过程中还能得到训练. 在那时会有新的神经元产生, 也会有神经元调整或者死去. 针对每个类都会创建新的网络. 例如, 为了产生超买和超卖的信号, 您需要为第一种情况创建一个网络, 为第二种情况创建另外一个.
训练
网络的输入是规范化统一的向量. 输出是 [0..1] 的数字, 分别指示输入的向量是否属于此类型的网络. 同时, 如果在训练过程中, 网络没有以指定的可能性发现模式, 它会自动增加新的神经元用以记录. 如果是基本训练(Primary training), 我建议重复运行两到三次. 以便当时网络可以更好地学习发生的基本信息. 通常需要不超过5遍重复.
预测或者分类会更加准确
分类的目标是提交输入模式是否匹配网络的类型. 如果网络已经学会, 把与熊势趋势信号相反分类为牛势趋势, 则它的输出值必须接近为1. 我把这些工作留到将来, 要看EA的开发者在于它集成时的反馈再做决定.
操作网络的主要必需函数
CreateNet函数用于创建网络.
doubleCreateNet(stringNN,// 我们创建叫做 的网络intInputVectorSize,// 输入向量所需的神经元数量 doubleMinTV,// 神经元冲突的阈值doubleMaxTV,// 独立的阈值doubleMW,// 神经元衰弱的标准intNL);// 神经元的生命周期 (柱数), 如果为0, 就一直存在
为了方便起见, 我决定称它们为nets. 我想提醒您, 您可以使用全部的神经元集合. 每个网络的设置在其创建时指定, 直到被删除都不会改变.
独立阈值是用来决定在训练过程中是否产生新的神经元的. 通常它等于0.95. 如果指定了比较低的值 (较小的独立程度), 网络会尝试更新, 这样不需要很多神经元就能应对大量的变数. 在这种情况下, 预测的精确性会下降. 如果 MaxTV 的值高, 网络会为几乎每个向量都创建新的神经元, 这样网络会变得很大. 网络会不断更新, 因而神经元不会产生冲突 (模式彼此间不会类似). MinTV 就是为了此目的而实现的, 我通常把它设为 2. MaxTV, MinTV 和 MW 参数值定义一次就够了. 之后如有必要, 优化程序会找到更好的参数值.
强者生存!这里也使用了同样的原则. 权重低于 MW 数值的虚弱神经元会被抛弃. 这样的神经元通常含有有害的信息, 应该死去而不是用来产生奇怪的信号.
如有必要, 您可以杀死老的神经元以去除这些"陈规陋习". 为此您应该制定神经元的生命周期柱数 (NL). 当新的神经元创建时, 它的创建时间会记录下来, 在未来您可以通过此标记删除它. 所以当把任何类型的数据输入到网络时, 时间因素是必需的.
您可以使用DestroyNet函数来删除网络. 这非常简单. 不要忘记删除不必要的网络, 否则它们会一直占用计算机的内存直到MetaTrader被关闭.
intDestroyNet(stringNN);// 删除 网络, 返回剩余的网络数量
我没有实现网络名称独特性的检查, 您可以创建很多同名的网络. 这些网络会通过序列号加以区分.
stringNetName(inti);// 返回根据序列号取得的网络名称intGetNetsNumber();// 返回库中的网络总数intNetNumber(stringNetName);// 返回库中叫做 的网络的序列号
您应该使用TrainNet函数来训练网络.正确的答案可能是需要进行下单. 例如, 我们以 1 为买入信号, 而已 -1 为卖出信号. 但是因为买入和卖出是使用不同的网络, 所以在网络内不作考虑. 我们所需的是当前时间或者柱的创建时间.
doubleTrainNet(stringNetName,double& iX[],// InputVectorSize 大小的输入的规范化向量intT,// 正确答案datetimesT);// 向量创建的时间
在训练的过程中, 您可以决定网络识别了模式还是把它当成了新的类型. 为此可以使用SizeOfNet函数.
intSizeOfNet(stringNetName);// 返回高斯神经元的数量
您应该使用GetPredict函数读取回应. 它的参数与TrainNet一致. 如果您输入了与训练时同样的向量, 那么答案将是1.
doubleGetPredict(stringNetName,// 取得 [0..1] 的数值以判断输入向量是否属于此类double& iX[],datetimesT);
这些函数在网络的内部使用中是必需的. 可以如例子中那样使用它们.
voidShrink(stringNetName);voidWReset(stringNetName);voidAEqual(stringNetName);voidCW(stringNetName);voidKillWeaks(stringNetName);voidKillOlds(stringNetName,datetimesT);
使用实例
init()函数的代码实例
Print("已创建网络的编号: ",CreateNet("OverBought",24,0.2,0.95,0.001,Period()*60*1000));// 创建卖出信号的网络Print("已创建网络的编号: ",CreateNet("OverSold",24,0.2,0.95,0.001,Period()*60*1000));// 创建买入信号的网络//~~Print("开始初始训练 ...");for(intR =1; R
start()函数的代码实例
KillOlds("OverBought",iTime(Symbol(),,1));// 去掉老旧神经元PostTraining("OverBought",-1);// 在过程中继续训练Shrink("OverBought");// 更新网络AEqual("OverBought");// 把所有权重设为1CW("OverBought");// 计算权重KillWeaks("OverBought");// 去掉老旧神经元CW("OverBought");// 计算权重KillOlds("OverSold",iTime(Symbol(),,1));PostTraining("OverSold",1);// 在过程中继续训练AEqual("OverSold");// 把所有权重设为1Shrink("OverSold");// 更新网络CW("OverSold");// 计算权重KillWeaks("OverSold");// 去掉老旧神经元CW("OverSold");// 计算权重//--------------------------------------------------------------------doubleOverBought = Predict("OverBought");doubleOverSold = Predict("OverSold");Out = (OverBought - OverSold)/(OverBought+OverSold);
deinit()函数的代码实例
Print("Destroying net=>",Destroy ("OverBought"));// 删除我们增加的网络Print("Destroying net=>",Destroy ("OverSold"));// 删除我们增加的网络
已经成功检查了网络的工作能力. 好的结果依赖于创建输入向量的方法. 在训练过程中, 应该输入那些事先知道分类结果的向量数据, 认识到这点很重要. 简单来说, 如果网络是用于卖出信号的, 那么选择用来训练的柱应该确实是用于卖出信号的. 否则网络会收集相反的信号而您得不到想要的结果.
▼想了解更详细的信息,请扫码联系我们
▼
公众号
小编个人微信
领取专属 10元无门槛券
私享最新 技术干货