在任何市场中获得优势(第四部分):CBOE欧元和黄金波动率指数(基础篇)
📘

在任何市场中获得优势(第四部分):CBOE欧元和黄金波动率指数(基础篇)

第 1/3 篇

◍ 替代数据到底能不能给你交易优势

在大数据环境下,公开可用的数据集规模已达数亿级别,理论上每一个都可能提升对金融市场的预测精度,但实际能被策略消化的只是极少数。外汇与贵金属属高杠杆高风险品种,盲目堆数据反而容易过拟合,先把数据源的「有效边界」想清楚再谈接入。 本系列的目的不是推销某个神奇指标,而是带交易者逐一检视那些被宣传为「另类 alpha」的数据集。以 CBOE 的欧元波动率指数与黄金波动率指数为切口,我们会拆解它们在不同波动率 regime 下对 EUR 相关货币对、XAUUSD 的可能边际贡献,而不是预设结论。 你在 MT5 里打开 EURUSD 与 XAUUSD 的日线,叠加 VIX 类波动率曲线,先肉眼确认相关性断裂的时段——这比直接跑回测更省时间,也能避免被表面显著性误导。

XAUEUR与波动率指数的实战关联

XAUEUR 跟踪以欧元计价的黄金价格,其定价基准主要来自 LBMA 的全球协议价,而美国 CBOE 提供的欧元、黄金波动率指数可反映这两类市场的情绪温度。把这两个指数拉进 MT5 的窗口叠加,能直观看到欧系货币与贵金属的波动是否同步放大。 波动市里有机会也有坑:价格跳空可能让止损单来不及触发,短时间内亏掉大笔本金的概率明显上升;反过来,若方向做对,相对平静市更可能在短周期内打到利润目标。外汇与贵金属属高风险品种,仓位须自行约束。 老手在波动市通常比平静市更快落袋,也有人先等价格被夹在支撑阻力之间,突破才动手,赌区间释放后的单向推力。正常市突破常迅速泄力漂移,波动市突破则常伴同侧剧震,平均回报更高,但假突破剧烈反杀是这类手法绕不开的损耗点。

「从 FRED 到 MT5:XAUEUR 预测因子的拼装路径」

我们直接用圣路易斯联储的 FRED Python 接口拉取 CBOE 的欧元、黄金波动率日线序列,原始数据带缺失值且官方没给说明,统一做了均值填充。同时在 MT5 里用自写 MQL5 脚本抓了 XAUEUR 约 4000 行日线 OHLC。 把 CBOE 替代数据和 MT5 报价做相关性检验,两者与 XAUEUR 收盘的相关性都基本贴着 0;但两个 CBOE 序列之间相关性约 0.4,这种正相关倾向说明它们可能受共同参与者或联动机制影响。 合并后样本约 3000 行,散点图上看好像存在一条高波动阈值线,越过之后价格水平倾向抬升——但小样本很可能只是假模式,不能当真。我们用 3D 散点(两 CBOE 为 xy、收盘为 z)复看,上涨簇仍在;再用 t-SNE 把 6 维数据压到 2 维,图里浮出 4 个聚类,且有点序列依赖的味道。 自相关图全是强拖尾,部分自相关只有少数滞后项扛住大部分解释力,意味着这批序列可能能用移动平均模型建模。之后我们组了 3 套预测因子:纯 MT5 OHLC、纯 CBOE、两者合并,用三个相同深度网络做 5 折时间序列交叉验证(不打乱),合并组预测未来收盘的误差最低。 进一步用 ALE 和 SHAP 看全局重要性,两种方法都没把 CBOE 替代集排除掉。调参分两步:先 500 次随机搜索,再用 L-BFGS-B 精修连续参数;验证集上定制模型胜默认网络,但测试集最佳仍是随机搜索款,说明没明显过拟合。最后把最优模型转 ONNX 塞进 MT5 自写程序,另写 Python 脚本通过共享 CSV 把最新 FRED 数据喂给终端。外汇与贵金属波动剧烈,这类跨源建模只作概率参考,实盘前务必在 MT5 用历史数据复跑验证。

◍ MT5里一键导出行情CSV

做价格行为分析前,先得把裸数据拿到手。下面这段脚本能直接拖进MT5图表,按你指定的条数把当前品种的OHLC和RSI拉出来,写成逗号分隔的CSV,方便后续用Python或Excel啃。 脚本只有一个输入参数 size,默认 100000,代表要抓多少根K线。注意这个量级在主流货币对上可能覆盖数年数据,文件会比较大,实盘前建议先填个 5000 试跑。 核心逻辑是先 iRSI 挂一个20周期收盘价RSI句柄,CopyBuffer 把数值塞进数组,再倒序循环用 iTime/iOpen 等函数逐根写文件。循环从 i=size 写到 0,首行写表头,之后才是真实行情。 外汇和贵金属杠杆高、跳空频繁,导出的历史数据不代表未来波动,回测结论仅作概率参考。

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">//+------------------------------------------------------------------+
class=class="str">"cmt">//| Script Inputs                                                              |
class=class="str">"cmt">//+------------------------------------------------------------------+
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">//| Global variables                                                          |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">int rsi_handler;
class="type">class="kw">double rsi_buffer[];
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| On start function                                                         |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">void OnStart()
  {
class=class="str">"cmt">//--- Load indicator
   rsi_handler = iRSI(_Symbol,PERIOD_CURRENT,class="num">20,PRICE_CLOSE);
   CopyBuffer(rsi_handler,class="num">0,class="num">0,size,rsi_buffer);
   ArraySetAsSeries(rsi_buffer,true);
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),

把K线高低收写进文件的关键三行

这段片段是向文件逐根写入当前品种、当前周期K线数据的收尾部分,核心只靠三个内置函数取数。 iHigh(Symbol(),PERIOD_CURRENT,i) 取第 i 根 K 线最高价,iLow 取最低价,iClose 取收盘价;Symbol() 和 PERIOD_CURRENT 保证跟随图表品种与周期,不写死。 循环结束后用 FileClose(file_handle) 关闭句柄,否则 MT5 里文件会一直被占用,重跑脚本可能报 5004 句柄错误。外汇与贵金属波动剧烈,用真实账户前先在策略测试器跑一遍文件输出,确认 csv 里每根 bar 的 HLC 数量与图表一致。

MQL5 / C++
iHigh(Symbol(),PERIOD_CURRENT,i),
 iLow(Symbol(),PERIOD_CURRENT,i),
 iClose(Symbol(),PERIOD_CURRENT,i)
 );
 }
 }
class=class="str">"cmt">//--- Close the file
 FileClose(file_handle);
}
class=class="str">"cmt">//+------------------------------------------------------------------+

「把 MT5 导出的 XAUEUR 和恐慌指数对齐成监督样本」

从 MT5 导出的 OHLC csv 只是原材料。要喂给监督学习,得先把它和 CBOE 的 EVZCLS(欧元波动率)、GVZCLS(黄金波动率)按交易日对齐——这两个序列得从 FRED 拿,免费账号申请后填进 api_key 即可,没有隐藏费用。 代码里把 csv 从 96911 行起切片,是因为前面那段是 MT5 导出的非交易时段空行,直接 set_index('Time') 转成 datetime 后才能和 FRED 按索引做内连接。只保留两边都有记录的日期,避免未来函数式的错位。 标签定义很直接:look_ahead=20,用 20 根 K 线后的 Close 做回归目标,再生成一个 Binary Target——后价高于现价记 1,否则 0,仅用于后面看分布。XAUEUR 这类贵金属交叉盘波动受汇率与避险情绪双重牵引,样本对齐后做训练,对外汇和贵金属交易均属高风险尝试,回测结果只代表历史概率倾向。 最后把 Open/High/Low/Close 和两只波动率做成 predictors 列表,和 Target 分开,方便后面三组因子集做横向对比。

MQL5 / C++
class="macro">#Import the libraries we need
class="kw">import pandas as="as" pd
class="kw">import numpy as="as" np
class="kw">import matplotlib.pyplot as="as" plt
class="kw">import seaborn as="as" sns
class="kw">import statsmodels
from statsmodels.graphics.tsaplots class="kw">import plot_acf,plot_pacf
from fredapi class="kw">import Fred
from class="type">class="kw">datetime class="kw">import class="type">class="kw">datetime
class="kw">import time
class="macro">#Display library versions
print(f"Pandas version {pd.__version__}")
print(f"Numpy version {np.__version__}")
print(f"Seaborn version {sns.__version__}")
print(f"Statsmodels version {statsmodels.__version__}")
class="macro">#Read in the data
xau_eur = pd.read_csv("Market Data XAUEUR.csv")
xau_eur = xau_eur.loc[class="num">96911:,:]
xau_eur.set_index("Time",inplace=True)
xau_eur.index = pd.to_datetime(xau_eur.index)
class="macro">#Fetch FRED data
fred = Fred(api_key=&class="macro">#x27;ENTER YOUR API KEY HERE&class="macro">#x27;)
fred_euro_data = pd.DataFrame(fred.get_series(&class="macro">#x27;EVZCLS&class="macro">#x27;),columns=["EVZCLS"])
fred_gold_data = pd.DataFrame(fred.get_series(&class="macro">#x27;GVZCLS&class="macro">#x27;),columns=["GVZCLS"])
class="macro">#Fill in any missing values with the column mean
fred_euro_data = fred_euro_data.fillna(fred_euro_data.mean())
fred_gold_data = fred_gold_data.fillna(fred_gold_data.mean())
class="macro">#Merge the data
merged_data = pd.merge(xau_eur,fred_euro_data,left_index=True,right_index=True)
merged_data = pd.merge(merged_data,fred_gold_data,left_index=True,right_index=True)
merged_data
class="macro">#Let us label the data
look_ahead = class="num">20
class="macro">#Define the labels
merged_data["Target"] = merged_data["Close"].shift(-look_ahead)
merged_data["Binary Target"] = np.nan
merged_data.loc[merged_data["Target"] > merged_data["Close"],"Binary Target"] = class="num">1
merged_data.loc[merged_data["Target"] <= merged_data["Close"],"Binary Target"] = class="num">0
merged_data.dropna(inplace=True)
merged_data
class="macro">#Let us define the predictors and target
ohlc_predictors = ["Open","High","Low","Close"]
fred_predictors = ["EVZCLS","GVZCLS"]
predictors = ohlc_predictors + fred_predictors
target = "Target"
binary_target = "Binary Target"

常见问题

可能带来边际优势,但需和价格行为结合验证;单独用波动率指数预测易失效,建议回测后再上实盘。
恐慌抬升期黄金波动率指数走高,XAUEUR常出现单边加速;可用日线级数据对齐观察背离信号。
小布可自动拉取品种页做因子对齐与背离提示,省去手动拼 CSV 和写脚本的时间。
按日期主键左连接,缺失日用前值填充;导出时保留高开低收字段,方便后续监督学习。
打开文件句柄、用 iHigh/iLow/iClose 取数组、FileWrite 按行落盘;这三行漏一个就导不出。