ARIMA外汇预测基础:用Python给EURUSD时间序列建模的入门全景(基础篇)
📈

ARIMA外汇预测基础:用Python给EURUSD时间序列建模的入门全景(基础篇)

(1/3)·从时间序列定义到ARIMA三参数,一篇补齐非季节性外汇预测的理论地基

进阶 第 1/3 篇

很多交易者把历史价格直接丢进任意模型就等信号,却分不清单变量和多变量预测的根本差异。ARIMA只吃自身滞后值,硬塞 exogenous 变量只会让残差悄悄失真。先搞懂平稳性和差分,才谈得上拿它碰 EURUSD 的分钟线。

「从时间序列预测切入ARIMA」

做价格行为分析的交易者,常把K线当成纯形态游戏,但EURUSD的小时图里藏着明显的自相关结构,这恰恰是时间序列模型能啃下的骨头。 所谓时间序列预测,核心是用历史观测值的顺序依赖关系外推未来,外汇与贵金属这类高波动品种,用错了滞后阶数就会把噪声当信号,杠杆市场高风险,模型输出只能当概率参考。 本系列以MetaTrader 5导出的EURUSD报价为样本,先讲清ARIMA的三个核心件:差分阶数d、自回归p、移动平均q,再落到Python里真跑一遍,而不是空谈理论。

时间序列预测的两个核心变量与分类

时间序列预测的本质,是用按时间排序的历史数据点去推断未来取值。任何能拿来做时序分析的数据,最少要有两个字段:一个是时间本身,作为自变量标记每条观测发生的时刻;另一个是目标变量,也就是你真正想往前推的数值,比如每日收盘价、每小时气温或每分钟访问量。 剥开花哨定义,落地时只分两种做法。单变量预测只用目标变量自身的历史去猜未来,例如拿股票收盘价推收盘价;多变量预测则引入其他输入特征共同建模。本文后续要用的 ARIMA 属于前者,它不依赖外部因子,只吃自己的历史。 对外汇与贵金属交易者而言,纯单变量模型在跳空、数据中断的行情里容易失真,这是高风险品种的客观约束,用 ARIMA 前先确认数据连续性。

◍ 拆开 ARIMA 的三个旋钮

ARIMA 全名是自回归积分移动平均,本质是用序列自己的滞后值和滞后误差去解释当下、外推未来。只要一段行情数据不是纯随机白噪声、带点可捕捉的规律且非季节性,就能塞进这个框架里跑预测。 模型由 (p, d, q) 三个阶数定义,每个数都是独立旋钮。p 是自回归阶数,决定拿多少期过去的 Y 当解释变量;q 是移动平均阶数,控制把几期过去的预测误差纳入方程。 d 最容易被忽略:它代表让序列变平稳所需的最少差分次数。平稳一般用「当期减前一期」实现,原序列已经平稳时 d=0,复杂些的可能要差两三次才压住趋势和周期。 在 MT5 里用 iMA 或自写差分函数先确认 d,再回头定 p、q,比盲目调参更省事。外汇与贵金属波动受事件驱动,ARIMA 仅刻画历史惯性,实盘高风险,信号失效概率不低。

「拆开ARIMA的三个字母」

ARIMA这个名字直接对应三块机制:AR、I、MA。把这三块拆开看,比盯着完整公式容易懂得多。 AR(p)是自回归部分,思路接近线性回归,但预测因子用的是序列自己的滞后值。当前值 y_t 由常数项、p个滞后项 y_{t-1}…y_{t-p} 乘上各自系数 φ,再加误差 ε_t 得到。系数 φ 大小直接反映某期滞后对现在的影响权重。 I(d)做差分。对一个观测值减去它的前期观测值,目的是消掉趋势和季节性,逼出平稳序列——均值和方差在一段时间内恒定。不平稳的序列喂给模型,拟合的往往是噪声而不是规律,这一步不能跳。 MA(q)看的是当前观测和过去预测误差的关系。模型用滞后误差项 ε_{t-1}…乘上 θ 参数,估算随机冲击的残留影响,对抓短期波动特别有用。外汇与贵金属价格受突发消息驱动明显,MA部分捕捉这类冲击的能力值得在MT5里实测验证。

用Python给EURUSD定ARIMA参数

ARIMA把自回归(AR)、差分(I)、移动平均(MA)拼在一起,真正卡人的地方是(p,d,q)三个阶数怎么取。参数选歪了,模型要么欠拟合要么过度差分,拿去推汇率下一步纯属碰运气。外汇和贵金属杠杆高,这类统计模型只给概率倾向,不能直接当入场指令。 AR阶数p看偏自相关函数(PACF)图。PACF剔掉了中间滞后项的干扰,只留序列和某一滞后项的纯相关;图里相关系数掉到接近0且不再显著的那个滞后阶,就是p的上限。跑EURUSD日线1000根bar的PACF,0阶之后全不显著,所以p=0。 d差分阶数靠ADF检验把关。原假设是序列非平稳,p值小于0.05才拒绝、认定平稳。EURUSD收盘价ADF的p值跑出来是0.3707,远大于0.05,说明本来就不平稳。做一阶差分后ACF快速衰减,二阶差分没明显更好,故d=1。 MA阶数q对应ACF图,看消掉平稳序列残留自相关要几个滞后误差项。同样样本下q最佳也是0。手动看图和auto_arima自动选参结果一致,说明这套原始方法在EURUSD日线上够用。 别把正态当圣经:ADF只验平稳性,不保证差分后分布适合交易,真要上MT5验证建议先小样本跑一遍再放大。

MQL5 / C++
pip install -r requirements.txt
# Importing required libraries
class="kw">import pandas as pd
class="kw">import numpy as np
class="kw">import MetaTrader5 as mt5
# Use auto_arima to automatically select best ARIMA parameters
class="kw">import seaborn as sns
class="kw">import matplotlib.pyplot as plt
class="kw">import warnings
class="kw">import os
# Suppress warning messages for cleaner output
warnings.filterwarnings("ignore")
# Set seaborn plot style for better visualization
sns.set_style("darkgrid")
# Getting(EUR/USD OHLC data) from MetaTrader5
mt5_exe_file = r"c:\Users\Omega Joctan\AppData\Roaming\Pepperstone MetaTrader class="num">5\terminal64.exe" # Change this to your MetaTrader5 path
if not mt5.initialize(mt5_exe_file):
    print("Failed to initialize Metatrader5, error = ",mt5.last_error)
    exit()
# select a symbol into the market watch
symbol = "EURUSD"
timeframe = mt5.TIMEFRAME_D1
if not mt5.symbol_select(symbol, True):
    print(f"Failed to select {symbol}, error = {mt5.last_error}")
    mt5.shutdown()
    exit()
rates = mt5.copy_rates_from_pos(symbol, timeframe, class="num">1, class="num">1000) # Get class="num">1000 bars historically
df = pd.DataFrame(rates)
print(df.head(class="num">5))
print(df.shape)
from statsmodels.graphics.tsaplots class="kw">import plot_pacf
class="kw">import matplotlib.pyplot as plt
plt.figure(figsize=(class="num">6,class="num">4))
plot_pacf(series.diff().dropna(), lags=class="num">5)
plt.title("Partial Autocorrelation Plot")
plt.xlabel(&class="macro">#x27;Lag&class="macro">#x27;)  # X-axis label
plt.ylabel(&class="macro">#x27;PACF&class="macro">#x27;)  # Y-axis label
plt.savefig("pacf plot.png")
plt.show()
plt.figure(figsize=(class="num">7,class="num">5))
sns.lineplot(df, x=df.index, y="Close")
plt.savefig("close prices.png")
from statsmodels.tsa.stattools class="kw">import adfuller
series = df["Close"]
result = adfuller(series)
print(f&class="macro">#x27;p-value: {result[class="num">1]}&class="macro">#x27;)
p-value: class="num">0.3707268514544181
# Original Series
fig, axes = plt.subplots(class="num">3, class="num">2, sharex=True, figsize=(class="num">9, class="num">9))
axes[class="num">0, class="num">0].plot(series); axes[class="num">0, class="num">0].set_title(&class="macro">#x27;Original Series&class="macro">#x27;)
plot_acf(series, ax=axes[class="num">0, class="num">1])
# 1st Differencing
axes[class="num">1, class="num">0].plot(series.diff().dropna()); axes[class="num">1, class="num">0].set_title(&class="macro">#x27;1st Order Differencing&class="macro">#x27;)
plot_acf(series.diff().dropna(), ax=axes[class="num">1, class="num">1])
# 2nd Differencing

◍ 用 Python 给价差序列定阶

把原始序列做一阶、二阶差分后分别画时序图和 ACF,能直观看出 d=1 或 d=2 哪个更接近平稳。对欧元兑美元这类高流动性品种,差分后用 ADF 检验,一阶差分 p-value 落到 0.0,二阶同样 0.0,说明一阶就已经能把单位根剔除干净。 接着看 PACF 截尾位置,lags 拉到 20,一阶差分后 PACF 在 lag=1 之后快速衰减,暗示 MA 项不用堆太高。用 auto_arima 跑非季节性逐步搜索,trace 打开后 AIC 对比一目了然:ARIMA(0,1,0) 无截距项 AIC=-35538.731 最优,比带截距的 (0,1,0) 还低一点,总拟合耗时 6.5 秒左右。 这套流程不依赖 MT5,但结论可以直接拿去对照 MT5 里自带的 ARIMA 类指标参数。外汇与贵金属杠杆高、价差跳变频繁,模型阶数只是概率意义上的最优,实盘前务必用历史数据重跑验证。

MQL5 / C++
axes[class="num">2, class="num">0].plot(series.diff().diff()); axes[class="num">2, class="num">0].set_title(&class="macro">#x27;2nd Order Differencing&class="macro">#x27;)
plot_acf(series.diff().diff().dropna(), ax=axes[class="num">2, class="num">1])
plt.savefig("acf plots.png")
plt.show()
result = adfuller(series.diff().dropna())
print(f&class="macro">#x27;p-value d=class="num">1: {result[class="num">1]}&class="macro">#x27;)
result = adfuller(series.diff().diff().dropna())
print(f&class="macro">#x27;p-value d=class="num">2: {result[class="num">1]}&class="macro">#x27;)
p-value d=class="num">1: class="num">0.0
p-value d=class="num">2: class="num">0.0
plt.figure(figsize=(class="num">7,class="num">5))
plot_pacf(series.diff().dropna(), lags=class="num">20)
plt.title("Partial Autocorrelation Plot")
plt.xlabel(&class="macro">#x27;Lag&class="macro">#x27;)  # X-axis label
plt.ylabel(&class="macro">#x27;PACF&class="macro">#x27;)  # Y-axis label
plt.savefig("pacf plot finding q.png")
plt.show()
from pmdarima.arima class="kw">import auto_arima
model = auto_arima(series, seasonal=False, trace=True)
print(model.summary())
Performing stepwise search to minimize aic
ARIMA(class="num">2,class="num">1,class="num">2)(class="num">0,class="num">0,class="num">0)[class="num">0] intercept  : AIC=-class="num">35532.282, Time=class="num">3.21 sec
ARIMA(class="num">0,class="num">1,class="num">0)(class="num">0,class="num">0,class="num">0)[class="num">0] intercept  : AIC=-class="num">35537.068, Time=class="num">0.49 sec
ARIMA(class="num">1,class="num">1,class="num">0)(class="num">0,class="num">0,class="num">0)[class="num">0] intercept  : AIC=-class="num">35537.492, Time=class="num">0.59 sec
ARIMA(class="num">0,class="num">1,class="num">1)(class="num">0,class="num">0,class="num">0)[class="num">0] intercept  : AIC=-class="num">35537.511, Time=class="num">0.74 sec
ARIMA(class="num">0,class="num">1,class="num">0)(class="num">0,class="num">0,class="num">0)[class="num">0]            : AIC=-class="num">35538.731, Time=class="num">0.25 sec
ARIMA(class="num">1,class="num">1,class="num">1)(class="num">0,class="num">0,class="num">0)[class="num">0] intercept  : AIC=-class="num">35535.683, Time=class="num">1.22 sec
Best model:  ARIMA(class="num">0,class="num">1,class="num">0)(class="num">0,class="num">0,class="num">0)[class="num">0]            
Total fit time: class="num">6.521 seconds
把平稳性诊断交给小布
这些诊断小布盯盘的 AIGC 已内置,打开对应品种页即可看到序列是否需差分以及建议的 d 阶,你专注参数调优而非重复跑脚本。

常见问题

标准ARIMA利用序列自身滞后值与滞后误差预测未来,属单变量范畴;若需引入外部变量应转向ARIMAX或SARIMA类扩展。
可以,小布盯盘的品种页内置了AIGC诊断,能给出差分阶数建议与残差平稳视图,省去手敲Python的环节。
线性回归类结构要求预测因子相互独立,价差序列常带趋势与异方差,差分至平稳可缓解自相关、提升拟合合理性,概率上更稳。
p为自回归滞后阶,d为使序列平稳的最小差分次数,q为移动平均误差阶;三者共同决定模型记忆长度与噪声修正力。
SARIMA在ARIMA基础上加入季节周期项,处理带周期性外汇波动;本篇基础篇先铺非季节性ARIMA,后续系列会展开。