移動平均を使った戦略
移動平均は時系列データに対して平均的な挙動を表すことができる方法で、様々な分野で使われています。ここでは、株・FXなどに特化した移動平均方法を記載します。
移動平均とは
移動平均(Moving Average, MA)とは、時系列データにおいて、平均的な変化をとらえるような方法です。Rolling mean(ローリング平均)などとも言われます。直近のデータに重きを置くような指数平滑移動平均(Exponential moving average, exponential smoothing)などもあります。
この平均線を利用してMoving Average Convergence Divergence, MACDやTriple Exponetial Average, TRIXなどインジケーターを算出することができます。
単純移動平均(Simple Moving Average, SMA)
\(k\)期間における単純移動平均を考えてみます。時刻\(t\)における価格を\(p_t\)と表現します。
$$ SMA_k = \frac{p_{n-k+1}+p_{n-k+2} + \cdots + p_n}{k} $$
単純に、価格を平均しているだけですね。Pythonだと次のように簡単に計算できます。
prices.rolling(window=period).mean()
pricesはpandas.Series()です。Rolling()を使うと簡単に移動平均を計算することができます。
例えば以下のようなドル円のOHLCVデータがあったとします。
data.head(10)
open high low close tick_volume
time
2023-06-01 00:00:00 139.425 139.425 139.356 139.395 53
2023-06-01 00:10:00 139.375 139.387 139.328 139.350 89
2023-06-01 00:20:00 139.350 139.382 139.350 139.363 54
2023-06-01 00:30:00 139.368 139.368 139.318 139.331 161
2023-06-01 00:40:00 139.331 139.332 139.303 139.328 81
2023-06-01 00:50:00 139.328 139.354 139.328 139.354 139
2023-06-01 01:00:00 139.364 139.404 139.318 139.321 491
2023-06-01 01:10:00 139.321 139.338 139.238 139.258 1000
2023-06-01 01:20:00 139.254 139.279 139.190 139.265 668
2023-06-01 01:30:00 139.264 139.281 139.231 139.258 541
このデータに対して移動平均を計算してみます。ここでは、期間を5とします(この場合だと50分の移動平均線になる)。
data.close.rolling(window=5).mean()
time
2023-06-01 00:00:00 NaN
2023-06-01 00:10:00 NaN
2023-06-01 00:20:00 NaN
2023-06-01 00:30:00 NaN
2023-06-01 00:40:00 139.3534
2023-06-01 00:50:00 139.3452
2023-06-01 01:00:00 139.3394
2023-06-01 01:10:00 139.3184
2023-06-01 01:20:00 139.3052
2023-06-01 01:30:00 139.2912
最初の部分は計算されないのでNaNになります。実際に2023-06-01 00:40:00を確認すると、
sum([139.395, 139.35 , 139.363, 139.331, 139.328]) / 5.0 = 139.3534
5つの期間の平均となっています。クローズ値とk=14の移動平均値をプロットすると以下の図のようになります。

MQL5での計算
MT5ではデフォルトで移動平均が使えますが、EAで利用する際に、どのようになっているかみてみます。
double SimpleMA(const int position,const int period,const double &price[])
{
double result=0.0;
//--- check period
if(period>0 && period<=(position+1))
{
for(int i=0; i<period; i++)
result+=price[position-i];
result/=period;
}
return(result);
}
MQLではfor文を利用して価格の移動平均を取るようにしています。配列の特定のインデックスにおける移動平均をとります。
指数平滑移動平均
指数平滑移動平均(Exponential Moving Average, EMA)は、直近のデータに重みをつけて平均を取る方法です。
$$ EMA_t = \alpha p_t + (1 – \alpha) EMA_{t-1} $$
ここで、\(EMA_0 = p_0\)です。\(\alpha\)は2/(期間+1)とされることが多いです。直近の価格にアルファ分の重みを掛けているのが特徴です。
Pythonでは次のように計算します。
def calculate_ema(prices, period=14, alpha=None):
if alpha is None:
alpha = 2 / (period + 1)
ema = prices.ewm(alpha=alpha, adjust=False).mean()
return ema
Pandasにはewm()というメソッドが用意されています。adjust=Falseとした場合が上式の計算方法で、Trueの場合は、再帰的ではなく指数重み付き平均を直接計算します。具体的な式を確認したい場合は公式ドキュメントを確認してください。
先ほどのデータに対してEMA(5)を計算してみます。
time
2023-06-01 00:00:00 139.395000
2023-06-01 00:10:00 139.368000
2023-06-01 00:20:00 139.365632
2023-06-01 00:30:00 139.351246
2023-06-01 00:40:00 139.342322
2023-06-01 00:50:00 139.346589
2023-06-01 01:00:00 139.337529
2023-06-01 01:10:00 139.309943
2023-06-01 01:20:00 139.294562
2023-06-01 01:30:00 139.282160
ローリングウィンドウとは異なり、5点がNanになっていない点が注意です。これは前の値を使って計算を行っているためです。SMAの値と異なっていることがわかります。
Adaptive Moving Average
適応型移動平均は、ノイズに対して反応が低いように設計された移動平均です。EMAの場合では、急な価格変動が起こってしまうと、そのような影響を強く受けてしまいます。平均を取る上ではノイズとなりますので、影響度を低くするようにEMAのアルファを設計します。
- Efficiency ratio
現在のマーケットの状態を評価するためにS/N比を計算します。KaufmanはEfficiency Ration (ER)という考え方を導入してます。
$$ ER_t = \frac{Signal_t}{Noise_t} $$
シグナルはある期間に対して絶対値をとります。
$$ Signal_t = |p_t – p_{t-k}| $$
一方、ノイズは絶対差分の総和になります。
$$ Noise_t = \sum_{i}^{N} |p_i – p_{i-1}| $$
強いトレンドがあるとERは1に収束します。スムージングの係数であるα(smoothing constant, SC)に対して、短期(fast SC=2/(2+1)=0.6667)と長期(slow SC=2/(30+1)=0.06452)の影響を考えます。この変化をscaled smoothing constant, SSCと呼びます。
$$ SSC_t = ER_t (fast SC – slow SC) + slow SC $$
すなわち、
$$ SSC_t = 0.60215 ER_t + 0.006425 $$
となります。これをEMAのαとしたものがAdaptive MAです。最終的な式は以下のようになります。
$$ AMA_t = p_t (SSC_t^2) + (1 – SSC_t^2) * AMA_{t-1} $$
解説記事: https://www.metatrader5.com/en/terminal/help/indicators/trend_indicators/ama
他にもフラクタルを使ってアルファを調整する方法もあります。
インディケーターとしてのMA
次に、AMAを利用したシグナルについて記載します。レンジ相場ではなくトレンドがある場合に有効かと思います。2023年に強い上昇トレンドがあった日経平均先物をみてみます。
Buyシグナル
- ローソク足が移動平均線を上向きに交差(openからcloseでMA線を交差)(強いシグナル)
- close値がMA線を下回るが、次のローソク足でclose値が上回る場合(弱いシグナル)
Sellシグナル
基本はBuyシグナルの逆をすれば良いです。
ローソク足が移動平均線を下に交差したときは強い買いシグナルになります。
日経平均での検証
ローソク足のOpenからCloseにかけてMA線を交差しているため買いです。売るタイミングは、移動平均線を下回った時です。次の買いにおいても移動平均線を上回ったためopenでエントリーしています。

詳細なシグナルはMQL5に記載されています。
https://www.mql5.com/ja/docs/standardlibrary/expertclasses/csignal/signal_ama
これらのロジックをMQL5及びPythonでEAに実装した場合の記事も書いていけたらと思います。







