基于预测的统计套利(基础篇)
📘

基于预测的统计套利(基础篇)

第 1/3 篇

用统计套利做跨品种预测

统计套利不靠方向猜顶底,而是抓两个高相关品种价差的均值回归。MT5 上这类系统通常先算协整关系,再在 z-score 偏离阈值时反向建仓,外汇与贵金属配对(如 XAUUSD 与 XAGUSD)在高波动期价差扩张,回归概率倾向随流动性恢复而上升,但杠杆品种回撤可能超 20%,属高风险操作。 原文作者 Javier Santiago Gaston De Iriarte Cabrera 于 2024 年 11 月 19 日发布该思路,社区展示阅读量 1361,说明这类非方向性策略在零售圈有稳定关注。 落地时先在 MT5 符号列表里挑相关系数 >0.8 的品种对,用内置相关系数工具验证 90 天窗口,再决定阈值。别把正态当圣经——价差在事件驱动下会长期偏离,需加波动率过滤。

「统计套利底层的三个统计量」

统计套利不靠方向判断吃饭,它赚的是相关金融工具之间价格低效回归的钱。模型要成立,先得啃下相关性、协整、皮尔逊系数这三块基石,否则配对标的选出来也是假关联。 相关性只回答一件事:两个证券价格变动贴得多紧。正相关的俩标的通常同向走,负相关的反过来。但光看相关性有个坑——它不保证关系稳定,一段行情里同涨同跌,下一段可能就拆伙。 协整比相关性更刁钻。它检验的是若干时间序列的线性组合能否长期保持平稳。白话讲:两只票各自乱走,但它们的价差受某条均衡线拽着,偏向了就会被拉回。配对交易的核心假设就立在这,标的历史上黏在一起才值得盯。 皮尔逊系数给相关性加了把尺:值域锁死在 -1 到 1,1 是完全同向往,−1 是完全反向,0 是没线性关系。实战里若两资产绝对值偏高,且你判断它会回长期均值,才算露出交易口子。外汇与贵金属跨品种统计套利属高风险,突发政策或流动性断裂会让均衡暂时失效。 真正跑这套的人靠算法和高频系统扫数据、抓偏离、自动下单。模型假设价格终将收敛历史均值,但经济冲击或情绪踩踏能撕开最稳的关系,所以人工重判不可省。

◍ 用生活场景拆开相关性与协整

相关性只是描述两件事是否同步发生。你和你朋友总在周六去同一家影院,这就是正相关:你出现,他大概率也在;若为负相关,你去了他反而不去;相关性为 0 则两者毫无同步痕迹。 协整比相关性更硬核,它管的是长期约束。把两个泳者用绳子拴住,短期各自乱游、距离时远时近,但绳长限定了他们不会彻底散开——这就是协整:变量短期可背离,长期必回到共同均衡。外汇与贵金属跨品种价差交易常依赖这种约束,但杠杆环境下短期背离就可能触发强平,属高风险操作。 皮尔逊相关系数给相关性一个数值刻度。接近 +1 是同涨同跌,接近 -1 是反向,0 是无线性关联。实测温度与冷饮销量会得到显著正系数,这类线性度量在 MT5 里用 iPearson 类函数即可批量算跨品种历史样本,用于筛候选配对。

用相关系数筛掉噪声货币对

想找出真正值得盯的联动品种,先得把弱相关和伪协整的过滤掉。一段 Python 脚本直连 MT5 终端,拉取名称含 EUR/USD 或结尾为 USD 的日线品种,取最近 365 根 D1 收盘,做两两 Pearson 相关系数与协整检验。 门槛设得狠一点:相关系数绝对值大于 0.8 才算强相关,协整 p 值小于 0.05 才算统计显著。跑完一轮,从全市场 EUR/USD 系里筛出 54 对同时满足两项条件的组合。 几个典型结果有:EURUSD 与 USDHRK 相关系数 -0.9972、p 值 0.0000;GBPUSD 与 GBXUSD 相关系数 0.9998、p 值 0.0000;AUDUSD 与 USDCNH 相关系数 -0.8074、p 值 0.0390。外汇与贵金属杠杆高、点差跳变频繁,这类数字仅代表历史样本的统计倾向,实盘须以 MT5 重新验算。 下方是脚本原文,复制进本地 Python 环境(需装 MetaTrader5、pandas、scipy、statsmodels)即可复跑,改 symbols 过滤规则就能换自己的观察池。

MQL5 / C++
class="kw">import MetaTrader5 as mt5
class="kw">import pandas as pd
from scipy.stats class="kw">import pearsonr
from statsmodels.tsa.stattools class="kw">import coint
class="kw">import numpy as np
# Connect with MetaTrader class="num">5
if not mt5.initialize():
    print("Failed to initialize MT5")
    mt5.shutdown()
# Get the list of symbols
symbols = mt5.symbols_get()
symbols = [s.name for s in symbols if s.name.startswith(&class="macro">#x27;EUR&class="macro">#x27;) or s.name.startswith(&class="macro">#x27;USD&class="macro">#x27;) or s.name.endswith(&class="macro">#x27;USD&class="macro">#x27;)]  # Filtrar símbolos por ejemplo
# Download historical data and save in dictionary
data = {}
for symbol in symbols:
    rates = mt5.copy_rates_from_pos(symbol, mt5.TIMEFRAME_D1, class="num">0, class="num">365)  # Último año, diario
    if rates is not None:
        df = pd.DataFrame(rates)
        df[&class="macro">#x27;time&class="macro">#x27;] = pd.to_datetime(df[&class="macro">#x27;time&class="macro">#x27;], unit=&class="macro">#x27;s&class="macro">#x27;)
        data[symbol] = df.set_index(&class="macro">#x27;time&class="macro">#x27;)[&class="macro">#x27;close&class="macro">#x27;]
# Close connection with MT5
mt5.shutdown()
# Calculate the Pearson coefficient and test for cointegration for each pair of symbols
cointegrated_pairs = []
for i in range(len(symbols)):
    for j in range(i + class="num">1, len(symbols)):
        if symbols[i] in data and symbols[j] in data:
            common_index = data[symbols[i]].index.intersection(data[symbols[j]].index)
            if len(common_index) > class="num">30:  # Asegurarse de que hay suficientes puntos de datos
                corr, _ = pearsonr(data[symbols[i]][common_index], data[symbols[j]][common_index])
                if abs(corr) > class="num">0.8:  # Correlación fuerte
                    score, p_value, _ = coint(data[symbols[i]][common_index], data[symbols[j]][common_index])
                    if p_value < class="num">0.05:  # P-valor menor que class="num">0.05
                        cointegrated_pairs.append((symbols[i], symbols[j], corr, p_value))
# Filter and show only cointegrated pairs with p-value less than class="num">0.05
print(f&class="macro">#x27;Total pairs with strong correlation and cointegration: {len(cointegrated_pairs)}&class="macro">#x27;)
for sym1, sym2, corr, p_val in cointegrated_pairs:
    print(f&class="macro">#x27;{sym1} - {sym2}: Correlación={corr:.4f}, P-valor de Cointegración={p_val:.4f}&class="macro">#x27;)

「跨品种协整配对的实际读数」

下面这组跨市场配对,是把 Pearson 相关系数与协整 P 值同时跑出来的结果。P 值小于 0.05 通常意味着两序列在样本期内存在统计上显著的长期均衡关系,但外汇与贵金属本身杠杆高、跳空频繁,协整随时可能被宏观事件打断,实盘只能当作概率参考。 EURJPY 与 USDTRY 的相关性达到 0.9564,协整 P 值 0.0102;EURCZK 与 USDCLP 相关性 0.9655,P 值仅 0.0001。这类高相关且低 P 值的组合,在 MT5 里适合做价差回归类的观察,而不是单向押注。 也有反向案例值得记:EURJPY 与 EURMXN 相关性 -0.8785(P 值 0.0172),EURNZD 与 NZDUSD 相关性 -0.8505(P 值 0.0455)。负向配对在价差拉大到历史带宽外时,倾向触发均值回归,但必须带止损。 USDBGN-USDHRK 与 USDHRK-USDDKK 的相关系数分别 0.9944 和 0.9954,P 值都是 0.0000,基本是钉住汇率的镜像;这种组合在真实交易里几乎没有价差空间,列出只是提醒你别被高相关误导成可套利机会。

◍ 把跨品种皮尔逊相关做成副图指标

想在 MT5 副窗里直接看两个品种的相关强度,可以把皮尔逊相关系数写成自定义指标。下面这段初始化只开一个缓冲、画红线,短名自动拼成「主图品种 & GBPUSD」,加载后一眼能认出配对。 参数上默认取 GBPUSD 作第二品种、回看 100 根 K 线算相关。BarsBack 设太小,相关系数会被近期噪声明暗摆动带偏;外汇与贵金属跨品种相关本就随宏观切换,属高风险观察量,数值只代表历史窗口内的线性耦合,不代表未来必然延续。 OnCalculate 里先卡 rates_total < BarsBack 直接返 0,避免样本不足算出 nonsense;随后把两个价格序列各扩到 BarsBack 长度,准备拷历史收盘价。这套骨架你拷进 MetaEditor 就能编译,把 Symbol2 换成 XAUUSD 便能量黄金与美指代理品种的相关漂移。

MQL5 / C++
class="macro">#class="kw">property copyright "Javier S. Gastón de Iriarte Cabrera"
class="macro">#class="kw">property link      "[MQL5官方文档]
class="macro">#class="kw">property version   "class="num">1.00"
class="macro">#class="kw">property indicator_separate_window
class="macro">#class="kw">property indicator_buffers class="num">1
class="macro">#class="kw">property indicator_color1 Red
input class="type">class="kw">string Symbol2 = "GBPUSD";      class=class="str">"cmt">// Second financial instrument
input class="type">int BarsBack = class="num">100;             class=class="str">"cmt">// Number of bars to include in correlation calculation
class="type">class="kw">double CorrelationBuffer[];
class="type">int OnInit()
  {
   SetIndexBuffer(class="num">0, CorrelationBuffer, INDICATOR_DATA);
   PlotIndexSetInteger(class="num">0, PLOT_DRAW_TYPE, DRAW_LINE);
   PlotIndexSetString(class="num">0, PLOT_LABEL, "Pearson Correlation");
   IndicatorSetString(INDICATOR_SHORTNAME, "Pearson Correlation(" + Symbol() + " & " + Symbol2 + ")");
   class="kw">return INIT_SUCCEEDED;
  }
class="type">int OnCalculate(class="kw">const class="type">int rates_total,
                class="kw">const class="type">int prev_calculated,
                class="kw">const class="type">class="kw">datetime &time[],
                class="kw">const class="type">class="kw">double &open[],
                class="kw">const class="type">class="kw">double &high[],
                class="kw">const class="type">class="kw">double &low[],
                class="kw">const class="type">class="kw">double &close[],
                class="kw">const class="type">long &tick_volume[],
                class="kw">const class="type">long &volume[],
                class="kw">const class="type">int &spread[])
  {
   if (rates_total < BarsBack) class="kw">return class="num">0; class=class="str">"cmt">// Ensure enough bars are present
   class="type">class="kw">double prices1[], prices2[];
   ArrayResize(prices1, BarsBack);
   ArrayResize(prices2, BarsBack);
   class=class="str">"cmt">// Copy historical data for primary symbol

常见问题

可作为辅助参考,但外汇贵金属波动受事件驱动,协整关系会断裂,先用历史数据验证再上实盘。
相关系数只看同涨同跌,协整看长期价差回归;相关高可能短期漂移,协整稳才能做配对。
小布可在品种页直接给出相关系数副图与协整读数,帮你筛掉噪声对,省去手动跑数据。
经验上绝对值低于0.6的多数对噪声偏大,回测中价差回归概率明显下降,建议先排除。
像两只绑着橡皮筋的狗,各自乱跑但总被拉回,价差长期稳定就是协整,可类比看盘。