移動平均を使った戦略

2023年6月25日MQL,Python

移動平均は時系列データに対して平均的な挙動を表すことができる方法で、様々な分野で使われています。ここでは、株・FXなどに特化した移動平均方法を記載します。

移動平均とは

移動平均(Moving Average, MA)とは、時系列データにおいて、平均的な変化をとらえるような方法です。Rolling mean(ローリング平均)などとも言われます。直近のデータに重きを置くような指数平滑移動平均(Exponential moving average, exponential smoothing)などもあります。

この平均線を利用してMoving Average Convergence Divergence, MACDTriple 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の移動平均値をプロットすると以下の図のようになります。

画像に alt 属性が指定されていません。ファイル名: 20230624_usdjpy_sma14.png

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に実装した場合の記事も書いていけたらと思います。

MQL,Python

Posted by fortunefox5