从Python到MQL5:量子启发式交易系统的探索之旅·综合运用
📘

从Python到MQL5:量子启发式交易系统的探索之旅·综合运用

第 3/3 篇

量子模拟系统在 MT5 里的落地与边界

把量子计算思路搬进交易,核心不是真去跑量子硬件,而是在 MQL5 里用确定性演化模拟一套量子电路。作者从 Python 原型切到 MQL5 实现后,在模拟与真实环境都拿到了稳定的命中率,高波动段尤其比传统模型抗压。 但要注意,这只是一套量子『模拟』系统。市场状态、数据质量都会直接干扰输出,作者本人也在讨论区提醒:附带 set #2 是优化跑出来的失败参数,别直接挂。正确做法是你自己跑优化找适配参数。 外汇和贵金属本身高杠杆高风险,这类受量子启发的 EA 只算算法探索,实盘前务必在策略测试器用历史数据复核,别把回测满意当保本凭证。 下面这段是状态向量演化的核心函数,决定了特征怎么转成量子幅值: [CODE] double SimulatePureQuantumCircuit(double &features[]) { const int num_states = (int)MathPow(2.0, (double)NUM_QUBITS); // 1. 创建并初始化状态向量(确定性演化) double state[]; ArrayResize(state, num_states); ArrayInitialize(state, 0.0); state[0] = 1.0; // 状态 |000...0> double next_state[]; ArrayResize(next_state, num_states); // --- [演变:Ry旋转阀] --- for(int qubit = 0; qubit < NUM_QUBITS; qubit++) { const int feature_idx = qubit % ArraySize(features); const double angle = MathMax(MathMin(features[feature_idx] * M_PI, M_PI), -M_PI); const double cos_a = MathCos(angle / 2.0); const double sin_a = MathSin(angle / 2.0); ArrayCopy(next_state, state); for(int i = 0; i < num_states; i++) { if((i & (1 << qubit)) == 0) { const int i1 = i | (1 << qubit); next_state[i] = cos_a * state[i] - sin_a * state[i1]; next_state[i1] = sin_a * state[i] + cos_a * state[i1]; } } ArrayCopy(state, next_state); 逐行拆解:第 3 行按量子比特数算总状态数 2^N;第 7–10 行把状态向量清零并把初态置为 |000...0>;第 14 行把特征索引对特征数组取模,避免越界;第 15 行把特征值乘 π 并夹在 ±π 内当旋转角;第 16–17 行算 Ry 门的半角余弦正弦;第 20–29 行对每个量子比特做受控旋转,把幅值在基态间重新分配;最后一行把本轮结果写回主状态供下一比特继续演化。

MQL5 / C++
class="type">class="kw">double SimulatePureQuantumCircuit(class="type">class="kw">double &features[])
{
  const class="type">int num_states = (class="type">int)MathPow(class="num">2.0, (class="type">class="kw">double)NUM_QUBITS);
  
  class=class="str">"cmt">// class="num">1. 创建并初始化状态向量(确定性演化)
  class="type">class="kw">double state[];  
  ArrayResize(state, num_states);
  ArrayInitialize(state, class="num">0.0);
  state[class="num">0] = class="num">1.0; class=class="str">"cmt">// 状态 |class="num">000...class="num">0>
  class="type">class="kw">double next_state[];
  ArrayResize(next_state, num_states);
  class=class="str">"cmt">// --- [演变:Ry旋转阀] ---
  for(class="type">int qubit = class="num">0; qubit < NUM_QUBITS; qubit++)
  {
    const class="type">int feature_idx = qubit % ArraySize(features);
    const class="type">class="kw">double angle = MathMax(MathMin(features[feature_idx] * M_PI, M_PI), -M_PI);
    const class="type">class="kw">double cos_a = MathCos(angle / class="num">2.0);
    const class="type">class="kw">double sin_a = MathSin(angle / class="num">2.0);
    ArrayCopy(next_state, state);
    for(class="type">int i = class="num">0; i < num_states; i++)
    {
      if((i & (class="num">1 << qubit)) == class="num">0)
      {
        const class="type">int i1 = i | (class="num">1 << qubit);
        next_state[i]  = cos_a * state[i] - sin_a * state[i1];
        next_state[i1] = sin_a * state[i] + cos_a * state[i1];
      }
    }
    ArrayCopy(state, next_state);

「纠缠门与振幅平方取概率」

这段逻辑在模拟两比特间的纠缠相位门:当特征 i 与 j 的乘积把相位推过 π/4 时,凡是在状态位图里同时置位 i 和 j 的基态振幅直接翻负号。NUM_QUBITS 设成 3,状态向量长度就是 2^3=8,外层双重循环跑完最多触发 C(3,2)=3 次纠缠判断。 相位计算用 M_PI/2.0 乘特征积,阈值卡在 M_PI/4.0;越过阈值才进最里层按位与筛查。这种条件翻转不改变概率模长,只动相对符号,属于典型干涉操控,不是凭空造信号。 取概率那步很直白:exact_probs[i] = state[i] * state[i],振幅平方即 Born 规则下的理论概率,不经过任何采样近似。MIN_CONFIDENCE 默认 0.1 只用于上游过滤平移信号,本段把精确概率直接喂给 GetWeightedVote 做加权投票。 CountBits 用 n &= (n-1) 清最低置位来计数,比逐位移位快;GetWeightedVote 里 state_value 映射成 (2*num_ones/NUM_QUBITS)-1,把 0~3 个置位线性拉伸到 -1~1 区间。外汇贵金属波动大,这类量子启发模型仅作概率参考,实盘前务必在 MT5 策略测试器跑多品种回测。

MQL5 / C++
for(class="type">int i = class="num">0; i < NUM_QUBITS - class="num">1; i++)
{
   for(class="type">int j = i + class="num">1; j < NUM_QUBITS; j++)
   {
      const class="type">class="kw">double phase = M_PI / class="num">2.0 * (features[i] * features[j]);
      if(MathAbs(phase) > M_PI / class="num">4.0)
      {
         for(class="type">int k = class="num">0; k < num_states; k++)
         {
            if(((k & (class="num">1 << i)) != class="num">0) && ((k & (class="num">1 << j)) != class="num">0))
               state[k] = -state[k];
         }
      }
   }
}
class=class="str">"cmt">// --- [真实概率的计算] ---
class="type">class="kw">double exact_probs[];
ArrayResize(exact_probs, num_states);
for(class="type">int i = class="num">0; i < num_states; i++)
{
   class=class="str">"cmt">// 振幅的平方即为根据波尔定理计算出的纯理论概率
   exact_probs[i] = state[i] * state[i];
}
class=class="str">"cmt">// class="num">2. 直接将理想概率传递给投票权重计算
const class="type">class="kw">double prediction = GetWeightedVote(exact_probs);

class="kw">return prediction;
}
class=class="str">"cmt">// 全局设置(请根据您的交易系统进行调整)
class="macro">#define NUM_QUBITS class="num">3         class=class="str">"cmt">// 量子比特数(状态向量大小 = class="num">2^NUM_QUBITS)
class="macro">#define MIN_CONFIDENCE class="num">0.1   class=class="str">"cmt">// 过滤平移信号的最低置信度阈值
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| 快速计算已设置的位(布莱恩·柯尼汉的方法)      |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">int CountBits(class="type">int n)
{
   class="type">int count = class="num">0;
   while(n > class="num">0)
   {
      n &= (n - class="num">1);
      count++;
   }
   class="kw">return count;
}
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| 期望值(Expectation Value)的计算         |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">class="kw">double GetWeightedVote(const class="type">class="kw">double &state_probs[])
{
   class="type">class="kw">double expected_value = class="num">0.0;
   class="type">class="kw">double total_weight = class="num">0.0;
   const class="type">int size = ArraySize(state_probs);
   for(class="type">int i = class="num">0; i < size; i++)
   {
      const class="type">class="kw">double vote_weight = state_probs[i];
      if(vote_weight <= class="num">0.000001) class="kw">continue;
      const class="type">int num_ones = CountBits(i);
      const class="type">class="kw">double state_value = (class="num">2.0 * (class="type">class="kw">double)num_ones / (class="type">class="kw">double)NUM_QUBITS) - class="num">1.0;

◍ 复数量子态的编码与归一化落地

这段 MQL5 片段把‘投票加权’和‘复数量子电路模拟’拼在同一节里,核心是两件事:先用权重把多个状态值揉成一个有界预测,再用 complex 类型在 MT5 里真跑一个多 qubit 态向量。 expected_value += state_value * vote_weight 这一步就是按票权累加,total_weight 做分母前先判 <=0.0001 直接 return 0.0,避免除零把 EA 卡死;final_prediction 夹在 [-1.0, 1.0] 之间,意味着模型输出天生被限幅,不会给出离谱极值。 下面 SimulateQuantumCircuitComplex 用 num_states = 2^NUM_QUBITS 算出态数,比如 NUM_QUBITS=3 就是 8 个基态。state[0].real=1.0 把系统钉在 |000> 基态,其余振幅清零,这是确定性复路模拟的标准初值。 特征编码段把 features_matrix[][0] 当 Ry 角、[][1] 当 Rz 角,统一 clamp 到 [-M_PI, M_PI];cos(theta/2)、sin(theta/2) 配欧拉指数 e^(i*phi) 写进 complex,next_state 做原子缓冲。开 MT5 把 NUM_QUBITS 调到 4,观察 ArrayResize 后 state 长度变 16,能直接验证振幅展开成本。外汇与贵金属行情受杠杆与跳空影响,这类信号仅作概率参考,实盘前务必在策略测试器跑历史回测。

MQL5 / C++
expected_value += state_value * vote_weight;
total_weight += vote_weight;
}
if(total_weight <= class="num">0.0001) class="kw">return class="num">0.0;

class="type">class="kw">double final_prediction = expected_value / total_weight;
if(final_prediction > class="num">1.0)  final_prediction = class="num">1.0;
if(final_prediction < -class="num">1.0) final_prediction = -class="num">1.0;
class="kw">return final_prediction;
}
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| 确定性复量子电路模拟器            |
class=class="str">"cmt">//| features[][class="num">0] - 振幅参数,features[][class="num">1] - 相位   |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">class="kw">double SimulateQuantumCircuitComplex(class="type">class="kw">double &features_matrix[][]){
   const class="type">int num_states = (class="type">int)MathPow(class="num">2.0, (class="type">class="kw">double)NUM_QUBITS);
   const class="type">int num_features = ArrayRange(features_matrix, class="num">0);
   
   if(num_features == class="num">0)
   {
      Print("错误:特征矩阵为空!");
      class="kw">return class="num">0.0;
   }
   class=class="str">"cmt">// 基于内置类型 complex 的量子态向量
   complex state[];  
   ArrayResize(state, num_states);
   
   class=class="str">"cmt">// 将系统初始化为严格状态 |class="num">000...class="num">0>
   for(class="type">int i = class="num">0; i < num_states; i++)
   {
      state[i].real = class="num">0.0;
      state[i].imag = class="num">0.0;
   }
   state[class="num">0].real = class="num">1.0; class=class="str">"cmt">// 基态振幅为1
   class=class="str">"cmt">// 用于向量原子(同时)更新的临时缓冲区
   complex next_state[];
   ArrayResize(next_state, num_states);
   class=class="str">"cmt">// --- class="num">1. 特征的综合编码(U-Gate:Ry + Rz) ---
   for(class="type">int qubit = class="num">0; qubit < NUM_QUBITS; qubit++)
   {
      const class="type">int feat_idx = qubit % num_features;
      
      class=class="str">"cmt">// 将输入角度限制在 [-PI; PI] 范围内
      const class="type">class="kw">double theta = MathMax(MathMin(features_matrix[feat_idx][class="num">0] * M_PI, M_PI), -M_PI); class=class="str">"cmt">// 适用于 Ry
      const class="type">class="kw">double phi   = MathMax(MathMin(features_matrix[feat_idx][class="num">1] * M_PI, M_PI), -M_PI); class=class="str">"cmt">// 对于 Rz
      const class="type">class="kw">double cos_t = MathCos(theta / class="num">2.0);
      const class="type">class="kw">double sin_t = MathSin(theta / class="num">2.0);
      
      class=class="str">"cmt">// 相位移的欧拉指数:e^(i*phi) = cos(phi) + i*sin(phi)
      complex e_phase;
      e_phase.real = MathCos(phi);
      e_phase.imag = MathSin(phi);
      ArrayCopy(next_state, state);
      for(class="type">int i = class="num">0; i < num_states; i++)
      {

单比特旋转与纠缠门的状态演进

这段逻辑把量子态的演进拆成两步:先对每个 qubit 施加受控旋转(Rx 类门),再做两两之间的纠缠相位混淆。旋转部分只处理目标位为 0 的基态索引 i,用位运算 (i & (1 << qubit)) == 0 跳过已置位的分支,避免重复计算。 旋转矩阵 U(theta, phi) 的实部直接用 cos(theta/2) 与 sin(theta/2) 线性组合 state[i] 与 state[i1],虚部同理;相位偏移 e^(i*phi) 通过 MQL5 的 complex 原生乘法 temp_i1 * e_phase 施加到目标位为 1 的分量上,比手写欧拉展开更不易出错。 纠缠阶段用双层循环遍历 i<j 的 qubit 对,cross_phase 取 M_PI/2.0 乘以两个特征矩阵槽位的乘积,构造一个 cz_gate 复数(cos 为实、sin 为虚)。仅当基态 k 中 i 与 j 两位同时为 1((k & (1<<i))!=0 且 (k & (1<<j))!=0)时才把 state[k] 乘以该门,相当于受控相位门。 在 MT5 里把 NUM_QUBITS 设成 4、num_features 设成 2 跑这套,能看到 16 个基态里只有同时满足双 1 的 4 个索引(3、7、11、15)相位被扭动,其余保持原幅——外汇与贵金属市场高杠杆高风险,这类特征纠缠仅作非线性状态编码实验,不预示任何方向。

MQL5 / C++
if((i & (class="num">1 << qubit)) == class="num">0)
{
   const class="type">int i1 = i | (class="num">1 << qubit);
   
   class=class="str">"cmt">// 旋转风门的复矩阵 U(theta, phi):
   class=class="str">"cmt">// [   cos(theta/class="num">2)      ,  -sin(theta/class="num">2)           ]
   class=class="str">"cmt">// [ sin(theta/class="num">2)*e^(i*phi),   cos(theta/class="num">2)*e^(i*phi) ]
   
   class=class="str">"cmt">// 目标位 = class="num">0 的计算
   next_state[i].real = cos_t * state[i].real - sin_t * state[i1].real;
   next_state[i].imag = cos_t * state[i].imag - sin_t * state[i1].imag;
   class=class="str">"cmt">// 目标位 = class="num">1 的计算(考虑相位偏移 e^i*phi)
   complex temp_i1;
   temp_i1.real = sin_t * state[i].real + cos_t * state[i1].real;
   temp_i1.imag = sin_t * state[i].imag + cos_t * state[i1].imag;
   
   class=class="str">"cmt">// 通过 MQL5 原生复数乘法实现相位偏移
   next_state[i1] = temp_i1 * e_phase;
   }
}
ArrayCopy(state, next_state);
class=class="str">"cmt">// --- class="num">2. 诚实的综合量子纠缠(Controlled-Phase Gate) ---
for(class="type">int i = class="num">0; i < NUM_QUBITS - class="num">1; i++)
{
   for(class="type">int j = i + class="num">1; j < NUM_QUBITS; j++)
   {
      const class="type">int idx_i = i % num_features;
      const class="type">int idx_j = j % num_features;
      
      class=class="str">"cmt">// 将两个相互关联的参数的复数相位相互混淆
      const class="type">class="kw">double cross_phase = M_PI / class="num">2.0 * (features_matrix[idx_i][class="num">0] * features_matrix[idx_j][class="num">1]);
      
      complex cz_gate;
      cz_gate.real = MathCos(cross_phase);
      cz_gate.imag = MathSin(cross_phase);
      for(class="type">int k = class="num">0; k < num_states; k++)
      {
         class=class="str">"cmt">// 如果两个量子比特都处于1态,则平滑地旋转它们的总复相位
         if(((k & (class="num">1 << i)) != class="num">0) && ((k & (class="num">1 << j)) != class="num">0))
         {
            state[k] = state[k] * cz_gate;
         }
      }
   }
}

「把工具请下神坛」

上面这段收尾代码把量子态的实部虚部平方相加,就是波恩定律说的观测概率 P =ψ²,循环里逐状态算完 exact_probs 数组,再交给 GetWeightedVote 出加权预测值。

当 MathAbs(prediction) 低于 MIN_CONFIDENCE 时直接 return 0.0,意味着从这套量子链视角看,价格处于盘整或方向不明的区间,此时任何多空信号都该搁置。 外汇与贵金属杠杆高、跳空频繁,这类 AIGC 辅助判定只提供概率倾向,不能替代仓位风控;开 MT5 把 MIN_CONFIDENCE 从默认改到 0.15 试一周,你会看到触发空仓的次数明显多于趋势市。 工具就是工具,跑出来的 confidence 只是帮你过滤噪声,真要下单还得看实时盘口与止损位置。

MQL5 / C++
class=class="str">"cmt">// --- class="num">3. 精确理论概率的计算(确定性步骤) ---
class="type">class="kw">double exact_probs[];
ArrayResize(exact_probs, num_states);

for(class="type">int i = class="num">0; i < num_states; i++)
{
   class=class="str">"cmt">// 根据波恩定律,概率 P = |ψ|² = 实部² + 虚部²
   exact_probs[i] = (state[i].real * state[i].real) + (state[i].imag * state[i].imag);
}
class=class="str">"cmt">// --- class="num">4. 获取最终预测 ---
const class="type">class="kw">double prediction = GetWeightedVote(exact_probs);
const class="type">class="kw">double confidence = MathAbs(prediction);
if(confidence < MIN_CONFIDENCE)
{
   class="kw">return class="num">0.0; class=class="str">"cmt">// 从量子链的角度来看,市场处于盘整/不明朗状态
}
class="kw">return prediction;
}

常见问题

目前看多数场景是概率增强的思路验证,实盘仍需严控仓位;建议先用历史数据跑通振幅平方取概率的逻辑再上模拟盘。
每步旋转后做归一化除法,把实部虚部平方和开根当分母;数值接近0时加极小epsilon防止除零。
可以,小布能按你给的振幅与纠缠参数自动跑历史检验,并在状态归一化失败或概率异常时推送提醒。
从30°、45°、60°三档分别试,对比旋转后振幅分布偏移;45°附近通常纠缠效应最直观。
高波动下振幅平方会放大噪声,建议加波动率过滤并降杠杆;外汇贵金属均属高风险,须设硬止损。