重构经典策略(第五部分):基于USDZAR的多品种分析(基础篇)
📘

重构经典策略(第五部分):基于USDZAR的多品种分析(基础篇)

第 1/3 篇

把美元南非兰特当成多品种验证样本

USDZAR 这类高息差、宽振幅的货币对,常被用来检验经典策略在极端波动下的稳定性。在 MT5 中把同一套规则同时挂在 USDZAR、EURUSD、XAUUSD 上,能直观看出策略对点差和滑点的敏感度差异。 以 2024 年 USDZAR 的日线为例,年振幅约 18%,单日波动超过 1.5% 的交易日占比接近 30%,远高于 EURUSD 的 6%。这种环境会放大均线类信号的假突破概率,但也可能让突破后趋势延续更长。 外汇与贵金属交易带杠杆,USDZAR 流动性在伦敦时段外偏薄,滑点可能吞掉部分盈利,实盘前务必用 MT5 策略测试器跑至少三年tick数据。

「用 AI 给老策略做体检」

把人工智能塞进交易系统的方式多到数不清,但真要拿资金去试每一种,时间和试错成本都扛不住。 我们这次挑了一个在 MT5 多品种分析里流传较广的老策略,重新跑一遍逻辑,看 AI 模块能不能补上它原本的盲区。 你要做的不是盲信结论,而是拿着我们拆出的参数和代码,在 MT5 里自己复验一次——外汇和贵金属杠杆高、滑点诡异,任何策略回测漂亮都不代表实盘概率占优。

◍ 用相关性做一篮子品种分析

多品种策略的核心,是借一篮子交易标的之间的相关性来辅助判断。相关性度量的是两个变量的线性依赖程度,但它常被误读成两者存在因果或稳定关系——实际远非如此。 有经验的交易者会把对相关资产的基本认知,用于定调仓位方向、估算风险暴露,甚至当作离场参考。以 USDZAR 为例:美国是主要石油出口国,南非是全球最大黄金出口国,商品在两国 GDP 中占比都不小。 由此可推,若现货石油相对黄金走强,美元相对兰特偏强的可能性更高;反向运行则兰特偏强。外汇与贵金属杠杆高、波动剧烈,这类关联只是概率倾向,不能直接当单边信号。

两组输入下模型的训练与比对

为评估石油、黄金与 USDZAR 的关联,我们用 MQL5 脚本从 MT5 终端导出全部市场数据,分别用两组输入训练模型:一组是 USDZAR 的 OHLC 常规报价,另一组是石油与黄金价格组合。 从导出数据看,石油与 USDZAR 的相关性似乎强于黄金。因各序列量纲不同,训练前统一做了标准化与归一化。 我们做了 10 折交叉验证且未随机打乱,以便横向比较不同输入集的准确度。结果显示第一组(OHLC)可能误差最低,其最佳模型是线性回归;第二组最佳模型为 KNeighborsRegressor。 超参调优用随机搜索跑了 500 次迭代、覆盖 5 个参数。用预留验证集对比定制模型与默认模型误差以测过拟合,同训练集下定制模型在验证集上表现更优。最终模型导出为 ONNX 并嵌入 EA。外汇与贵金属波动剧烈,这类相关性结论仅代表样本内概率倾向,实盘需自担高风险。

「用脚本把品种历史撸成 CSV」

想做价格行为复盘或喂给 AIGC 模型,第一步是把 MT5 里的裸数据弄出来。手动导出太慢,直接挂个脚本到图表上更干脆:拖进去就跑,不用碰策略测试器。 脚本默认抓取当前品种、当前周期的数据,落盘路径在终端目录的 \MetaTrader 5\MQL5\Files 下,文件名带品种名,例如 "Market Data EURUSD.csv"。input 里的 size 默认 100000,代表往前数多少根 K 线——真要拉满十万根,注意小周期可能覆盖数年,文件会偏大。 代码核心是一个倒序 for 循环:从 size 跑到 0,先写表头 Time/Open/High/Low/Close,再用 iTime、iOpen 等系列函数按索引取每根 K 线字段。FILE_CSV 配合逗号分隔,Excel 或 Python 直接读。 外汇和贵金属杠杆高、跳空频繁,导出的历史不代表未来波动,拿来训练或统计时先剔掉异常 session。

MQL5 / C++
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//|                                                                 ProjectName |
class=class="str">"cmt">//|                     Copyright class="num">2020, CompanyName |
class=class="str">"cmt">//|                      http://www.companyname.net |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="macro">#class="kw">property copyright "Gamuchirai Zororo Ndawana"
class="macro">#class="kw">property link      "[MQL5官方文档]
class="macro">#class="kw">property version   "class="num">1.00"
class="macro">#class="kw">property script_show_inputs
class=class="str">"cmt">//---Amount of data requested
class="kw">input class="type">int size = class="num">100000; class=class="str">"cmt">//How much data should we fetch?
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//|                                                                  |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">void OnStart()
  {
class=class="str">"cmt">//---File name
   class="type">class="kw">string file_name = "Market Data " + Symbol() + ".csv";
class=class="str">"cmt">//---Write to file
   class="type">int file_handle=FileOpen(file_name,FILE_WRITE|FILE_ANSI|FILE_CSV,",");
   for(class="type">int i= size;i>=class="num">0;i--)
     {
      if(i == size)
        {
        FileWrite(file_handle,"Time","Open","High","Low","Close");
        }
      else
        {
         FileWrite(file_handle,iTime(Symbol(),PERIOD_CURRENT,i),
                                 iOpen(Symbol(),PERIOD_CURRENT,i),
                                 iHigh(Symbol(),PERIOD_CURRENT,i),
                                 iLow(Symbol(),PERIOD_CURRENT,i),
                                 iClose(Symbol(),PERIOD_CURRENT,i));
        }
     }
  }
class=class="str">"cmt">//+------------------------------------------------------------------+

◍ 用 Python 给 USDZAR 拼一套多源特征

原始数据是按时间倒序存的,时间戳从近往远排,直接喂给模型等于拿未来猜过去。先把三个 CSV 用 [::-1] 整体反转,让时序从远到近,预测目标才能落在前面没见过的窗口。 合并前必须统一用 Time 列做索引,pandas 的 merge(..., how="inner") 只保留三张表共有的日期,避免错位。内连接之后,USOIL、XAUUSD 与 USDZAR 的收盘价才在同一行对齐。 预测视界设成 look_ahead = 10,即拿当前行去标 10 根 K 线后的收盘价当回归目标;同时造一个二元标签:后市收盘价高于当下就记 1,否则记 0,方便后面画图看分界。 跑 merged_df.corr() 能看到,石油与 USDZAR 的相关性约 -0.4,黄金与该货币对只有约 0.1。相关性不等于因果——美元走弱时资金撤出美元转投黄金,这是两者反向的共同驱动,但散点图里红绿点混在一起,没有明显可分簇。外汇与贵金属杠杆高、跳空频繁,这类弱相关信号只能当概率参考。 下面这段是上面流程的可执行骨架,路径按你本机 market_data 目录改一下就能跑:

MQL5 / C++
class="macro">#Libraries
class="kw">import pandas as pd
class="kw">import numpy as np
class="kw">import seaborn as sns
class="macro">#Dollar VS Rand
USDZAR = pd.read_csv("/home/volatily/market_data/Market Data USDZAR.csv")
class="macro">#US Oil
USOIL = pd.read_csv("/home/volatily/market_data/Market Data US Oil.csv")
class="macro">#SA Gold
SAGOLD = pd.read_csv("/home/volatily/market_data/Market Data XAUUSD.csv")
USOIL
class="macro">#Format the data
USDZAR = USDZAR[::-class="num">1]
USOIL = USOIL[::-class="num">1]
SAGOLD = SAGOLD[::-class="num">1]
class="macro">#Set the indexes
USOIL = USOIL.set_index("Time")
SAGOLD = SAGOLD.set_index("Time")
USDZAR = USDZAR.set_index("Time")
class="macro">#Merge the dataframes
merged_df = pd.merge(USOIL,SAGOLD,how="inner",left_index=True,right_index=True,suffixes=(" US OIL"," SA GOLD"))
merged_df = pd.merge(merged_df,USDZAR,how="inner",left_index=True,right_index=True)
class="macro">#Define the forecast horizon
look_ahead = class="num">10
class="macro">#Label the data
merged_df["Target"] = merged_df["Close"].shift(-look_ahead)
merged_df["Binary Target"] = class="num">0
merged_df.loc[merged_df["Close"] < merged_df["Target"],"Binary Target"] = class="num">1
class="macro">#Drop empty rows
merged_df.dropna(inplace=True)
class="macro">#Let&class="macro">#x27;s observe the correlation levels
merged_df.corr()

常见问题

可以当压力测试样本,它的高波动能暴露老策略在极端行情下的过拟合问题,但结论只作参考,不能直接当通用信号。
先算目标品种间的相关系数矩阵,挑绝对值在0.6到0.85之间的组合,既能分散又能保留联动特征,再用脚本批量导出历史数据。
可以,小布能读取你的策略逻辑和多品种历史,自动标出在USDZAR这类高波动样本上失效的因子,并给出简化建议。
把两组模型跑在同一段样本外历史上,比最大回撤和信号翻转频率,翻转少且回撤小的那组更抗实盘。
用现成导出脚本一键落盘,再用Python读CSV拼多源特征,重点看量价背离和波动率突变这两个维度。