用感知器给价格做独立预测
用感知器给价格做独立预测
感知器(Perceptron)属于最基础的机器学习结构,在 MT5 环境下可被改造成不依赖外部信号的独立价格预测模块。它通过对历史报价做线性加权,输出对下一根 K 线方向的倾向性判断。 对外汇与贵金属这类高波动品种,任何模型输出都只是概率倾向,实盘前必须在策略测试器里用真实点差回测。 本文后续将围绕这一自给自足的预测思路展开,读者可先在 MT5 新建一个空 EA,准备承接感知器的训练与推理逻辑。
◍ 用单层感知器给汇率把脉
感知器是 1957 年 Rosenblatt 提出的极简神经网络,单层结构就能吃进汇率、成交量、CPI 等多路输入,吐出一个货币对的价格预测信号。它靠监督学习在历史数据上调权重,本质是在找市场因子和未来价格之间的映射关系。 训练时把外汇历史行情和真实价喂进去,按预测误差反向修权重;跑预测时切到推理模式直接出信号。相比纯统计或时间序列,它能随新数据持续自适应,这是它在变动盘面里比老方法耐用的地方。 但单层感知器对外汇、贵金属这种高风险市场有明显短板:异常跳空或脏数据会带偏权重,且依赖大量有代表性的历史样本。若样本偏离当下结构,预测倾向失真,典型症状是过拟合——对旧数据敏感、对新行情麻木。 实践上可用 L1/L2 正则掐住权重膨胀,也可把它和 ARIMA、指数平滑拼着用:感知器抓长期倾向,短周期交给统计模型。模型别训一次用到老,定期用近期 tick 重训才贴近实盘。
「调参是感知器能不能用的命门」
感知器结构再简单,参数没调对也是白搭。隐藏层数和每层神经元数直接决定模型复杂度:层数或神经元太少,可能学不出外汇高低点分类边界;太多则倾向过拟合历史行情,实盘泛化能力掉队。 学习率设 0.1、动量 0.9、最大世代 1000、目标精度 90,是 MT5 里 NeuralNets 库跑 XOR 样例的常用起点。学习率过高权重容易发散,过低则训练时间拖到没法接受。 激活函数得按问题挑:隐藏层用 TANH、输出层用 SIGMOID 是一类组合;换 ReLU 或双曲正切结果会偏移。批量规模、优化器(SGD / Adam / RMSprop)、权重初始化法,也都要针对具体品种和周期试,不是抄一份就万能。 监管项(regularization)往误差函数里加惩罚项,能压住权重膨胀,减少预测在贵金属跳空时的盲散。外汇和贵金属杠杆高、波动突兀,模型过拟合后实盘亏损概率明显放大,调参务必留验证集。 下面这段 OnInit 是两层示例里较完整的一版,含输入 2、隐藏 3(TANH)、输出 1(TANH)的搭建与 XOR 测试: int OnInit() { // 定义输入、隐藏、输出层神经元数量 int n_inputs = 2; // 两个输入,对应 XOR 的两个比特 int n_hidden = 3; // 隐藏层 3 个神经元 int n_outputs = 1; // 输出层 1 个神经元 CNeuralNet ann; // 新建感知器对象 ann.AddLayer(n_inputs); // 加输入层 ann.AddLayer(n_hidden, CNeuralNet::TANH); // 加隐藏层,激活用 TANH ann.AddLayer(n_outputs, CNeuralNet::TANH); // 加输出层,激活用 TANH ann.SetLearningRate(0.1); // 学习率 0.1 ann.SetMomentum(0.9); // 动量 0.9,加速收敛 ann.SetMaxEpochs(1000); // 最多训 1000 代 ann.SetDesiredAccuracy(90); // 目标精度 90% double inputs[][2] = {{0,0}, {0,1}, {1,0}, {1,1}}; // 4 组输入 double targets[] = {0, 1, 1, 0}; // XOR 目标输出 ann.Train((double*)inputs, targets, 4); // 用 4 样本训练 double output; // 存输出 ann.Compute((double*)inputs[0], output); Print("0 XOR 0 = ", output); // 打印第 1 组结果 ann.Compute((double*)inputs[1], output); Print("0 XOR 1 = ", output); // 打印第 2 组 ann.Compute((double*)inputs[2], output); Print("1 XOR 0 = ", output); // 打印第 3 组 ann.Compute((double*)inputs[3], output); Print("1 XOR 1 = ", output); // 打印第 4 组 } 开 MT5 把这段塞进 EA 的 OnInit,跑完看日志里四个 XOR 输出是否接近 0/1/1/0。若偏差大,先动隐藏层神经元数或学习率,别急着换架构。
class="type">int OnInit() { class=class="str">"cmt">// set the number of neurons in the class="kw">input, hidden and output layers class="type">int n_inputs = class="num">2; class="type">int n_hidden = class="num">3; class="type">int n_outputs = class="num">1; class=class="str">"cmt">// create a perceptron object CNeuralNet ann; class=class="str">"cmt">// add layers ann.AddLayer(n_inputs); ann.AddLayer(n_hidden, CNeuralNet::TANH); ann.AddLayer(n_outputs, CNeuralNet::TANH); class=class="str">"cmt">// set learning parameters ann.SetLearningRate(class="num">0.1); ann.SetMomentum(class="num">0.9); ann.SetMaxEpochs(class="num">1000); ann.SetDesiredAccuracy(class="num">90); class=class="str">"cmt">// create arrays to store class="kw">input and target values class="type">class="kw">double inputs[][class="num">2] = {{class="num">0,class="num">0}, {class="num">0,class="num">1}, {class="num">1,class="num">0}, {class="num">1,class="num">1}}; class="type">class="kw">double targets[] = {class="num">0, class="num">1, class="num">1, class="num">0}; class=class="str">"cmt">// train the perceptron ann.Train((class="type">class="kw">double*)inputs, targets, class="num">4); class=class="str">"cmt">// test the perceptron class="type">class="kw">double output; ann.Compute((class="type">class="kw">double*)inputs[class="num">0], output); Print("class="num">0 XOR class="num">0 = ", output); ann.Compute((class="type">class="kw">double*)inputs[class="num">1], output); Print("class="num">0 XOR class="num">1 = ", output); ann.Compute((class="type">class="kw">double*)inputs[class="num">2], output); Print("class="num">1 XOR class="num">0 = ", output); ann.Compute((class="type">class="kw">double*)inputs[class="num">3], output); Print("class="num">1 XOR class="num">1 = ", output); }
用异或样本验证神经网络输出
把第 3 组输入指针强转成 double* 后交给 ann.Compute,网络会按已训练权重算出 output。这里喂的是 1 和 1 的异或样本,理论上 XOR 输出应趋近 0。 Print 直接把字符串 "1 XOR 1 = " 和 output 打印到 MT5 专家日志,你开终端按 Ctrl+E 加载 EA,就能在「专家」标签页看到实际数值与 0 的偏差。 若 output 落在 0.05 以内,说明前向传播与训练闭环没断;偏到 0.3 以上就要回头查 inputs[3] 的归一化是否和训练时一致。外汇与贵金属模型信号仅作概率参考,实盘波动风险高。
ann.Compute((class="type">class="kw">double*)inputs[class="num">3], output); Print("class="num">1 XOR class="num">1 = ", output);
◍ 给感知器喂指标与价格的取舍
做市场分析时,指标本质是提炼价格信息的数学方程。往感知器里送数据,最常用的是移动平均线、RSI、随机振荡器和 MACD 这几类。把收盘价叠加这些指标一起输入,模型既能借均线判趋势方向,又能用随机振荡器定位可能的切入区,预测维度比单看价格更立体。 但指标不是越多越灵。一股脑塞进十几个指标,冗余特征会拉高过拟合概率,模型在样本外普遍偏弱、泛化能力差。针对具体品种和周期,挑两三个信号最鲜明的指标反而更稳。 送进网络前得先洗数据。若某根 K 线的指标值缺失,要么用该序列均值补齐,要么直接剔掉那一行,否则训练容易跑偏。 隐藏层神经元数、激活函数、训练 epoch 数、mini-batch 大小,这几个参数直接决定模型学得怎么样。靠手动试错能调,也可上遗传算法或梯度优化去搜最优组合,MT5 里接 Python 脚本来跑这套参数搜索是可行的。
「用双均线间距训练单层感知器」
把周期 1 和 24 的两条指数移动平均线(收盘价应用)之间的距离,先归一化成点数,再喂给一个单层感知器。输入取蜡烛序号 1、4、7、10 上的四个距离值,输出两个节点分别代表开多和开空信号。这只是演示用的简化条件,不是可实盘照搬的规则。 回测框架固定在 EURUSD、H1、初始本金 10000、杠杆 1:500。止损 300 点、止盈 600 点(止盈设为止损两倍)。优化用「仅开盘价 + 快速遗传算法 + 最大复杂准则」模式,样本区间 2019.04.19–2022.04.19 共 3 年;前向验证取其后 1 年(2022.04.19–2023.04.19)。值得在 MT5 里亲自比对的是:「最大复杂准则」相较「最大盈利能力」给出的参数更不容易过拟合。 外汇与贵金属属高风险品种,上述前向结果仅代表历史样本表现,未来分布偏移时信号可能失效。打开 MT5 按这组输入窗口和归一化方式跑一遍优化,看前向前 5 名参数能否复现,比直接信任何结论更有用。
画得少,看得清
把感知器直接当价格预测器用,核心约束只有两条:历史样本必须和实盘场景同构,且权重数组要随品种特性重训。有读者拿 EURUSD H4 跑过一组对照——2020.1.1 至 2023.1.1 训练、2023.1.1 至 2023.5.1 前向测试,角度法在 1 月初延长趋势停顿里误触发,没反转却扛到止损把起始仓位打穿,扇形法整段零成交。 这类现象说明,单感知器对外汇高波动品种的前向泛化极不稳定,滚动重训(训练末日之后只跑一个月再平移窗口)比一次性训练更贴近真实市况,但会吃掉大量 MT5 优化算力。 打开 Perceptron_MA_4.mq5 把 GA 跑出来的权重手填进数组,先在某一个货币对上验证停顿误触发频率,比急着上多对象架构更实际。贵金属与外汇杠杆交易风险极高,任何历史吻合都不承诺未来复现。