最終更新: 2026年6月
SMA(Simple Moving Average / 単純移動平均線)は、すべての移動平均線の出発点となる最も基本的な指標だ。「過去N本のローソク足の終値の平均値を結んだ線」というシンプルな定義だが、この単純さが「多くのトレーダーが共通して参照するライン」としての市場的意味を生む。
EMA(指数平滑移動平均)の方が直近の動きへの反応が早いため、EAでは「SMAよりEMAを使う方がよい」という意見もある。しかし筆者の検証では、SMAにはEMAにはない「均等ウェイト」という特性から来るメリットがあり、用途によって明確に使い分けるべきだという結論に至っている。
Claudeと会話しながらインジケータが作れるhedgrow-fxはこちら
SMAの計算式——均等ウェイトの持つ意味
SMA(N) = (Close[0] + Close[1] + Close[2] + ... + Close[N-1]) / N
すべての価格に等しいウェイト(1/N)をかけて平均する。この均等ウェイトが「過去のある時点の価格と直近の価格が同じ重みで扱われる」ことを意味する。
具体例(SMA5の計算):
Day1終値: 100円、Day2: 102円、Day3: 101円、Day4: 103円、Day5: 104円
SMA(5) = (100 + 102 + 101 + 103 + 104) / 5 = 102円
SMAとEMAの根本的な違い
| 特性 | SMA | EMA | |------|-----|-----| | ウェイト | 全期間均等(1/N) | 直近に指数的ウェイト | | 価格変化への反応 | 遅い(平滑) | 早い(敏感) | | ダマし | 少ない | 多め | | シグナル発生 | 遅い | 早い | | 計算のわかりやすさ | 直感的 | やや複雑 |
EMAの直近ウェイト係数はα = 2 / (N + 1)で計算される。N=20のEMAなら、最新の終値に約9.5%のウェイト、前日の終値には約8.6%のウェイト、というように指数的に減衰する。
SMAでN=20なら全日程均等に5%(1/20)のウェイトだ。
MQL5でのSMA実装
input int SMAPeriod = 200; // SMA期間
input ENUM_APPLIED_PRICE SMAPrice = PRICE_CLOSE;
int SMAHandle;
double SMABuffer[];
int OnInit()
{
SMAHandle = iMA(_Symbol, _Period, SMAPeriod, 0, MODE_SMA, SMAPrice);
if(SMAHandle == INVALID_HANDLE)
{
Print("SMAハンドル取得失敗");
return INIT_FAILED;
}
ArraySetAsSeries(SMABuffer, true);
return INIT_SUCCEEDED;
}
// SMA値の取得
double GetSMA(int shift = 0)
{
if(CopyBuffer(SMAHandle, 0, 0, 5 + shift, SMABuffer) < (5 + shift))
return 0.0;
return NormalizeDouble(SMABuffer[shift], _Digits);
}
// 価格とSMAの位置関係でフィルタリング
bool IsBullishTrend()
{
double close = iClose(_Symbol, _Period, 0);
double sma = GetSMA(0);
return (close > sma); // 価格がSMAより上 = 上昇バイアス
}
bool IsBearishTrend()
{
double close = iClose(_Symbol, _Period, 0);
double sma = GetSMA(0);
return (close < sma); // 価格がSMAより下 = 下降バイアス
}
// SMAの傾きで方向を判定
bool IsSMASloping(bool upward)
{
double sma0 = GetSMA(0);
double sma5 = GetSMA(5); // 5本前と比較
if(upward) return (sma0 > sma5); // 右上がり
else return (sma0 < sma5); // 右下がり
}
void OnDeinit(const int reason)
{
IndicatorRelease(SMAHandle);
}
iMA関数でMODE_SMAを指定することでSMAになる。MODE_EMAにするとEMA、MODE_WMAにするとWMA(加重移動平均)になる。同じ関数で切り替えられるため、SMA・EMA・WMAの比較バックテストが容易にできる。
EA設計でのSMA活用パターン
パターン1: SMA200 方向フィルター(最頻用途)
SMA200(200期間移動平均)は「長期的なトレンド方向」の判断に広く使われる。
input int LongTermSMAPeriod = 200;
// SMA200の上側でのみ買い許可、下側でのみ売り許可
bool AllowBuy()
{
return IsBullishTrend(); // 価格 > SMA200
}
bool AllowSell()
{
return IsBearishTrend(); // 価格 < SMA200
}
この設計では、長期トレンドと逆行するエントリーを自動的に除外できる。デイトレードEAにSMA200フィルターを追加すると、「大きなトレンドに逆らったエントリー」による連続損失を防止できる可能性がある。
パターン2: SMAクロス戦略
input int FastSMAPeriod = 20;
input int SlowSMAPeriod = 50;
int FastSMAHandle, SlowSMAHandle;
double FastSMABuffer[], SlowSMABuffer[];
// ゴールデンクロス/デッドクロスの検出
int CheckSMACross()
{
double fast0 = FastSMABuffer[0];
double fast1 = FastSMABuffer[1];
double slow0 = SlowSMABuffer[0];
double slow1 = SlowSMABuffer[1];
// ゴールデンクロス: 短期が長期を上抜け
if(fast1 < slow1 && fast0 >= slow0) return 1;
// デッドクロス: 短期が長期を下抜け
if(fast1 > slow1 && fast0 <= slow0) return -1;
return 0;
}
SMAクロスはシンプルだが、強いトレンド相場では有効であり、レンジ相場ではダマしが多い。ADXフィルターとの組み合わせが推奨される。
パターン3: パーフェクトオーダー確認
3本の移動平均線が「短期 > 中期 > 長期」(買い)または「短期 < 中期 < 長期」(売り)の順序に並ぶ「パーフェクトオーダー」は、強いトレンドの存在を示す。
input int SMAFast = 20;
input int SMAMedium = 50;
input int SMASlow = 200;
bool IsPerfectOrderBull()
{
double fast = GetSMAByPeriod(SMAFast);
double medium = GetSMAByPeriod(SMAMedium);
double slow = GetSMAByPeriod(SMASlow);
return (fast > medium && medium > slow);
}
bool IsPerfectOrderBear()
{
double fast = GetSMAByPeriod(SMAFast);
double medium = GetSMAByPeriod(SMAMedium);
double slow = GetSMAByPeriod(SMASlow);
return (fast < medium && medium < slow);
}
グランビルの法則とSMA——EA設計への応用
グランビルの法則は、価格とSMAの位置関係から8つのエントリーパターンを定義したものだ。EAで実装する場合、特に以下の2パターンが機械的に定義しやすい:
パターン1(押し目買い): SMAが上向きで、価格がSMAを一時的に下抜けた後に反転上昇する局面
bool IsGranvillePattern1()
{
bool smaUpsloping = IsSMASloping(true); // SMAが右上がり
bool wasBelowSMA = (iClose(_Symbol, _Period, 1) < GetSMA(1)); // 前バーはSMA下
bool nowAboveSMA = (iClose(_Symbol, _Period, 0) > GetSMA(0)); // 現バーはSMA上
return (smaUpsloping && wasBelowSMA && nowAboveSMA);
}
パターン5(ダウトレンド戻り売り): SMAが下向きで、価格がSMAに近づいた後に反転下落する局面
SMAのEAバックテストで注意すべき点
期間の選択と自己実現効果: SMA20・SMA50・SMA100・SMA200は多くのトレーダーが共通して参照する「ラウンドナンバーSMA」だ。これらのラインで実際に反応が起きやすいのは、「多くの参加者が同じラインを見て売買する」という自己実現の側面がある。EAでSMAを使う場合は、一般的なラウンドナンバーを基準に検証することを推奨する。
ゴールデンクロスのタイムラグ: SMAはEMAより遅行するため、強いトレンドの初期を捉えにくい。ゴールデンクロス発生時にはすでにトレンドの中盤以降になっているケースがある。SMAクロスをエントリートリガーに使う場合は、これを認識した上でRRレシオ設計が必要だ。
ウィペリング(頻繁なクロス): レンジ相場ではSMAの傾きが小さくなり、ゴールデンクロスとデッドクロスが短期間に繰り返す「ウィペリング」が発生しやすい。ADXフィルター(ADX≥25)でトレンド相場を確認してからクロスシグナルを有効化する設計が重要だ。
Claudeと会話しながらインジケータが作れるhedgrow-fxはこちら
よくある質問(FAQ)
Q: EAにSMAとEMAのどちらを使うべきですか? A: 用途によります。「長期トレンドの方向フィルター」にはSMA200のような長期SMAが安定しています。「エントリータイミングの精度」を重視するなら、EMAの方が反応が早くシグナル精度が上がるケースがあります。両方を同じパラメーターでバックテストして比較することを推奨します。
Q: SMAの一般的な期間設定を教えてください。 A: よく使われる期間はSMA20(約1ヶ月・短期)、SMA50(中期)、SMA100(長期)、SMA200(超長期・約1年)です。これらはラウンドナンバーであり、多くのトレーダーが参照するため市場的意味があります。
Q: グランビルの法則をEAで完全に実装できますか? A: 8つのパターンのうち、機械的に定義できるものは実装できます。ただし「SMAに価格が近づいた」という条件の定義(何pips以内、何%以内など)がパラメーターになるため、バックテストでの検証が必要です。一部のパターンはローソク足パターンとの組み合わせが前提のため、より複雑な実装になります。
Q: SMAをMQL5のOnInit()で計算できますか? A: iMA関数でハンドルを取得し、CopyBuffer()でデータを取り出す設計が標準です。OnInit()でハンドルを取得し、OnTick()またはOnBar()でCopyBuffer()を呼ぶのが正しい実装順序です。OnInit()内でCopyBuffer()を呼ぶと、初期化タイミングでデータが揃っていない可能性があります。
Q: SMAの傾きを数値として取得するにはどうすればよいですか?
A: (SMABuffer[0] - SMABuffer[N]) / N で1本あたりの変化量を計算できます。この値が正なら右上がり、負なら右下がりです。さらに/ _Pointでpips単位の傾きに換算できます。
著者情報
本記事は金融工学・アルゴリズム取引の実務経験を持つライターが執筆しています。
免責事項: 本記事はFXの教育・情報提供を目的としており、投資勧誘を行うものではありません。FX取引には元本割れリスクがあります。バックテスト結果は将来の運用成果を保証しません。実際の取引は自己責任で行ってください。
