【MQL4】iStochastic関数の使い方を完全解説!ストキャスティクスを使ったEAサンプル付き

【中級編】MQLプログラムの読み方・書き方

ストキャスティクスは、相場の「買われすぎ」「売られすぎ」を判断するための代表的なオシレーター系インジケーターです。MQL4ではiStochastic関数を使うことで、EA(自動売買プログラム)やカスタムインジケーターの中からストキャスティクスの値を簡単に取得できます。

この記事では、iStochastic関数の書式・引数をひとつずつ丁寧に解説し、最後にストキャスティクスのクロスで売買する実践的なEAサンプルを紹介します。

ストキャスティクスとは?

ストキャスティクス(Stochastic Oscillator)は、一定期間の価格レンジの中で現在の価格がどの位置にあるかを0〜100の数値で示すテクニカル指標です。

3本のラインを理解しよう

ストキャスティクスには以下の3種類のラインがあります。

  • %K(Fast %K):直近の価格が一定期間の高値・安値レンジのどこに位置するかを示す、最も感度の高いライン
  • %D(Fast %D / Slow %K):%Kを移動平均で平滑化したライン。MetaTrader4のストキャスティクスではこれがメインラインになります
  • Slow %D(シグナルライン):%Dをさらに移動平均で平滑化したライン

80と20のレベルライン

一般的に、ストキャスティクスの値が80以上になると「買われすぎ」、20以下になると「売られすぎ」と判断します。この水準でのラインのクロスが売買シグナルとしてよく使われます。

iStochastic関数の書式と引数を完全解説

iStochastic関数の書式は以下のとおりです。

double iStochastic(
   string       symbol,        // ① 通貨ペア
   int          timeframe,     // ② 時間足
   int          Kperiod,       // ③ %K期間
   int          Dperiod,       // ④ %D期間
   int          slowing,       // ⑤ スローイング
   int          method,        // ⑥ 移動平均の種類
   int          price_field,   // ⑦ 価格フィールド
   int          mode,          // ⑧ 取得するライン
   int          shift          // ⑨ シフト(何本前のバーか)
);

引数が9つもあるので少し多く感じますが、一つずつ見ていきましょう。

① symbol(通貨ペア)

値を取得したい通貨ペアを文字列で指定します。現在のチャートの通貨ペアを使う場合はNULLまたはSymbol()と書きます。

② timeframe(時間足)

時間足を定数で指定します。現在のチャートの時間足を使う場合は0またはPERIOD_CURRENTと書きます。主な定数は以下のとおりです。

定数 時間足
PERIOD_M1 1分足
PERIOD_M5 5分足
PERIOD_M15 15分足
PERIOD_M30 30分足
PERIOD_H1 1時間足
PERIOD_H4 4時間足
PERIOD_D1 日足
PERIOD_W1 週足

③ Kperiod(%K期間)

%Kラインの計算に使う期間です。一般的には514がよく使われます。

④ Dperiod(%D期間)

%Kを平滑化して%Dを求める際の移動平均の期間です。一般的には3がよく使われます。

⑤ slowing(スローイング)

スローストキャスティクスのスローイング値です。1にするとファスト、3にするとスローストキャスティクスになります。通常は3を指定します。

⑥ method(移動平均の種類)

%Dラインの平滑化に使用する移動平均の種類を指定します。

定数 種類
MODE_SMA 単純移動平均(最も一般的)
MODE_EMA 指数移動平均
MODE_SMMA 平滑移動平均
MODE_LWMA 線形加重移動平均

⑦ price_field(価格フィールド)

ストキャスティクスの計算に使う価格の種類です。

説明
0 高値/安値(Low/High)を使用 ※一般的
1 終値(Close/Close)を使用

通常は0(高値/安値)を使います。

⑧ mode(取得するライン)

どのラインの値を取得するかを指定します。

定数 説明
MODE_MAIN(= 0) メインライン(%D)
MODE_SIGNAL(= 1) シグナルライン(Slow %D)

⑨ shift(シフト)

何本前のバーの値を取得するかを指定します。0で現在のバー、1で1本前のバー(確定済み)です。

基本的な使い方

まずはストキャスティクスの値を取得してチャートに表示するシンプルなコードを見てみましょう。

#property strict

void OnTick()
{
   // メインライン(%D)を取得 - 1本前の確定バー
   double stochMain = iStochastic(NULL, 0, 5, 3, 3, MODE_SMA, 0, MODE_MAIN, 1);

   // シグナルライン(Slow %D)を取得 - 1本前の確定バー
   double stochSignal = iStochastic(NULL, 0, 5, 3, 3, MODE_SMA, 0, MODE_SIGNAL, 1);

   // チャートに表示
   Comment("Stochastic Main: ", DoubleToString(stochMain, 2),
           "\nStochastic Signal: ", DoubleToString(stochSignal, 2));
}

このコードでは、期間5・3・3のスローストキャスティクス(SMA)のメインラインとシグナルラインの値を取得し、Comment関数でチャート左上に表示しています。shift=1を指定しているので、確定済みの1本前のバーの値を取得しています。

実践サンプルEA ― ストキャスティクスのクロスで売買

ここからは、ストキャスティクスのゴールデンクロス(買いシグナル)とデッドクロス(売りシグナル)で売買する実践的なEAを作ってみましょう。

売買ルール

  • 買いエントリー:ストキャスティクスが20以下のゾーンで、メインラインがシグナルラインを下から上にクロス(ゴールデンクロス)
  • 売りエントリー:ストキャスティクスが80以上のゾーンで、メインラインがシグナルラインを上から下にクロス(デッドクロス)
  • 既にポジションがある場合は新規エントリーしない

EAの完全なコード

//+------------------------------------------------------------------+
//|                                          StochasticCrossEA.mq4   |
//|                         ストキャスティクス クロスEA サンプル        |
//+------------------------------------------------------------------+
#property strict

// --- 入力パラメータ ---
input int    KPeriod      = 5;       // %K期間
input int    DPeriod      = 3;       // %D期間
input int    Slowing      = 3;       // スローイング
input double UpperLevel   = 80.0;    // 上限レベル(売られすぎ判定)
input double LowerLevel   = 20.0;    // 下限レベル(買われすぎ判定)
input double LotSize      = 0.1;     // ロットサイズ
input int    StopLoss     = 100;     // ストップロス(pips)
input int    TakeProfit   = 200;     // テイクプロフィット(pips)
input int    MagicNumber  = 12345;   // マジックナンバー

// --- 新バー判定用変数 ---
datetime lastBarTime = 0;

//+------------------------------------------------------------------+
//| Expert initialization function                                     |
//+------------------------------------------------------------------+
int OnInit()
{
   Print("StochasticCrossEA が初期化されました");
   return(INIT_SUCCEEDED);
}

//+------------------------------------------------------------------+
//| 新しいバーが生成されたか判定する関数                                  |
//+------------------------------------------------------------------+
bool IsNewBar()
{
   datetime currentBarTime = iTime(NULL, 0, 0);
   if(lastBarTime != currentBarTime)
   {
      lastBarTime = currentBarTime;
      return true;
   }
   return false;
}

//+------------------------------------------------------------------+
//| 現在のポジション数を取得する関数                                     |
//+------------------------------------------------------------------+
int CountPositions(int type)
{
   int count = 0;
   for(int i = OrdersTotal() - 1; i >= 0; i--)
   {
      if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
      {
         if(OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber)
         {
            if(OrderType() == type)
               count++;
         }
      }
   }
   return count;
}

//+------------------------------------------------------------------+
//| Expert tick function                                               |
//+------------------------------------------------------------------+
void OnTick()
{
   // 新しいバーが確定したときだけ処理
   if(!IsNewBar())
      return;

   // --- ストキャスティクスの値を取得 ---
   // 1本前(確定済み)のメインライン
   double mainCurr   = iStochastic(NULL, 0, KPeriod, DPeriod, Slowing,
                                    MODE_SMA, 0, MODE_MAIN, 1);
   // 1本前(確定済み)のシグナルライン
   double signalCurr = iStochastic(NULL, 0, KPeriod, DPeriod, Slowing,
                                    MODE_SMA, 0, MODE_SIGNAL, 1);
   // 2本前のメインライン
   double mainPrev   = iStochastic(NULL, 0, KPeriod, DPeriod, Slowing,
                                    MODE_SMA, 0, MODE_MAIN, 2);
   // 2本前のシグナルライン
   double signalPrev = iStochastic(NULL, 0, KPeriod, DPeriod, Slowing,
                                    MODE_SMA, 0, MODE_SIGNAL, 2);

   // --- ゴールデンクロス判定(買いシグナル) ---
   bool goldenCross = (mainPrev < signalPrev) && (mainCurr > signalCurr);

   // --- デッドクロス判定(売りシグナル) ---
   bool deadCross = (mainPrev > signalPrev) && (mainCurr < signalCurr);

   // --- 買いエントリー ---
   if(goldenCross && mainCurr < LowerLevel && CountPositions(OP_BUY) == 0)
   {
      double sl = NormalizeDouble(Ask - StopLoss * Point, Digits);
      double tp = NormalizeDouble(Ask + TakeProfit * Point, Digits);

      int ticket = OrderSend(Symbol(), OP_BUY, LotSize, Ask, 3, sl, tp,
                              "Stoch GoldenCross", MagicNumber, 0, clrBlue);
      if(ticket > 0)
         Print("買い注文成功: チケット=", ticket);
      else
         Print("買い注文失敗: エラー=", GetLastError());
   }

   // --- 売りエントリー ---
   if(deadCross && mainCurr > UpperLevel && CountPositions(OP_SELL) == 0)
   {
      double sl = NormalizeDouble(Bid + StopLoss * Point, Digits);
      double tp = NormalizeDouble(Bid - TakeProfit * Point, Digits);

      int ticket = OrderSend(Symbol(), OP_SELL, LotSize, Bid, 3, sl, tp,
                              "Stoch DeadCross", MagicNumber, 0, clrRed);
      if(ticket > 0)
         Print("売り注文成功: チケット=", ticket);
      else
         Print("売り注文失敗: エラー=", GetLastError());
   }

   // --- チャート表示 ---
   Comment("Main[1]: ", DoubleToString(mainCurr, 2),
           "  Signal[1]: ", DoubleToString(signalCurr, 2),
           "\nMain[2]: ", DoubleToString(mainPrev, 2),
           "  Signal[2]: ", DoubleToString(signalPrev, 2));
}

サンプルコードのポイント解説

ポイント1:新バー判定で無駄な処理を防ぐ

IsNewBar()関数を使い、新しいバーが確定したタイミングでのみ売買判定を行っています。OnTick()はティックごとに呼ばれるため、そのまま処理すると同じバーで何度もシグナルを検出してしまいます。新バー判定を入れることで、確定した値に基づく安定したシグナル検出ができます。

ポイント2:2本のバーでクロスを検出する

クロスの判定には、1本前(shift=1)2本前(shift=2)の値を比較しています。

// ゴールデンクロス:2本前は「メイン < シグナル」→ 1本前は「メイン > シグナル」
bool goldenCross = (mainPrev < signalPrev) && (mainCurr > signalCurr);

// デッドクロス:2本前は「メイン > シグナル」→ 1本前は「メイン < シグナル」
bool deadCross = (mainPrev > signalPrev) && (mainCurr < signalCurr);

shift=0(現在のバー)を使うと、バーが確定するまで値が変動し続けるため、誤ったシグナルが出る可能性があります。確定済みのshift=1とshift=2を使うのが安全です。

ポイント3:ゾーンフィルタでダマシを減らす

単純なクロスだけではダマシ(偽シグナル)が多くなります。そこで、買いはLowerLevel(20)以下のゾーン売りはUpperLevel(80)以上のゾーンでのみエントリーするフィルタを入れています。売られすぎ・買われすぎの極端な領域でのクロスに絞ることで、シグナルの精度を高めています。

カスタマイズのヒント

マルチタイムフレーム分析

iStochastic関数の第2引数(timeframe)を変えることで、異なる時間足のストキャスティクスを取得できます。例えば、日足のトレンド方向を確認してからエントリーするといった使い方が可能です。

// 日足のストキャスティクスを取得
double dailyMain = iStochastic(NULL, PERIOD_D1, 5, 3, 3, MODE_SMA, 0, MODE_MAIN, 1);

// 日足が50以上なら上昇傾向 → 買いのみエントリーする、など
if(dailyMain > 50.0 && goldenCross && mainCurr < LowerLevel)
{
   // 買いエントリー処理
}

他のインジケーターとの併用

ストキャスティクス単体よりも、移動平均線(iMA関数)やRSI(iRSI関数)など他のインジケーターと組み合わせることで、より信頼性の高い売買ルールを構築できます。例えば、移動平均線の上にいるときだけ買いシグナルを採用する、といったフィルタが考えられます。

ストラテジーテスターで最適化

KPeriod、DPeriod、Slowing、UpperLevel、LowerLevelなどのパラメータは、MetaTraderのストラテジーテスターで最適化できます。input変数として宣言しているので、テスターの最適化機能でベストな組み合わせを探してみましょう。ただし、過剰最適化(カーブフィッティング)には注意が必要です。

まとめ

この記事で学んだポイントを整理します。

  1. iStochastic関数は9つの引数を持ち、MQL4からストキャスティクスの値を取得できる関数です
  2. MODE_MAINでメインライン(%D)、MODE_SIGNALでシグナルライン(Slow %D)を取得します
  3. price_fieldは通常0(高値/安値ベース)を使い、1(終値ベース)との違いを理解しておきましょう
  4. クロス判定にはshift=1とshift=2の確定済みバーを使うのが安全です
  5. 80/20のゾーンフィルタやマルチタイムフレーム分析を組み合わせることで、ダマシを減らして精度を向上させることができます

ストキャスティクスはシンプルながら強力なオシレーター指標です。まずは今回のサンプルEAをストラテジーテスターで動かして、パラメータを変えながら挙動を確認してみてください。実際に手を動かすことで、iStochastic関数の使い方がしっかり身につくはずです!