FX自動売買基礎と応用

ストキャスティクスをメインウィンドウに表示する自動売買の作成方法


パラメーターとバッファーを追加


この記事では、通常はサブウィンドウで表示されるオシレーター系指標のストキャスティクスを、メインウィンドウに表示する方法を解説します。

今回は、ストキャスティクスの20%と80%のところに水平線でレベルラインを描画し、20%ラインより下でゴールデンクロスした場合に買いサインを、80%ラインより上でデッドクロスした場合に売りサインを表示する仕様とします。

まずファイルの新規作成で「カスタムインディケータ」を選択し、ファイル名を「MainChartStoch」としてパラメーターを六つ追加します。

  • 一つ目は名前を「PERIOD_K」、タイプを「int」、初期値を「5」、
  • 二つ目は名前を「PERIOD_D」、タイプを「int」、初期値を「3」、
  • 三つ目は名前を「SLOWING」、タイプを「int」、初期値を「3」、
  • 四つ目は名前を「UPPER」、タイプを「double」、初期値を「80.0」、
  • 五つ目は名前を「LOWER」、タイプを「double」、初期値を「20.0」、
  • 六つ目は名前を「GAP」、タイプを「double」、初期値を「5.0」とします。

UPPERとLOWERはレベルライン用のパラメーター、GAPはローソク足とクロスサインとの距離を設定するパラメーターです。

パラメーターを六つ追加

「カスタムインディケータのイベントハンドラ」の画面では「OnChartEvent」にチェックを入れ次へ進み、「カスタムインディケータの描画プロパティ」画面のプロット欄でバッファーを四つ登録します。

  • 一つ目はメインライン用でラベルを「STOCH_M」、タイプを「Line」、カラーを「LightSeaGreen」、
  • 二つ目はシグナルライン用でラベルを「STOCH_S」、タイプを「Line」、カラーを「Red」、
  • 三つ目は矢印サインのアップ用でラベルを「UP」、タイプを「Arrow」、カラーを「Red」、
  • 四つ目は矢印サインのダウン用でラベルを「DN」、タイプを「Arrow」、カラーを「DodgerBlue」とします。

追加後に「完了」をクリックすれば、ひな形の完成です。

バッファーを四つ登録


「価格欄」と「移動平均の種別」を追加


ファイルが開いたら、上部のプロパティを修正します。

「STOCH_S」のスタイル(style)のところをデフォルトのストキャスティクスに合わせて、「STYLE_SOLID(実線)」から「STYLE_DOT(破線)」に変えておきます。また、売買サインを見やすくしたいので「UP」と「DN」の太さ(width)のところを「1」から「2」に変更しましょう。


//--- plot STOCH_S
#property indicator_label2  "STOCH_S"
#property indicator_type2   DRAW_LINE
#property indicator_color2  clrRed
#property indicator_style2  STYLE_DOT
#property indicator_width2  1
//--- plot UP
#property indicator_label3  "UP"
#property indicator_type3   DRAW_ARROW
#property indicator_color3  clrRed
#property indicator_style3  STYLE_SOLID
#property indicator_width3  2
//--- plot DN
#property indicator_label4  "DN"
#property indicator_type4   DRAW_ARROW
#property indicator_color4  clrDodgerBlue
#property indicator_style4  STYLE_SOLID
#property indicator_width4  2

そして「//--- input parameters」の「input int SLOWING=3;」の下に「価格欄」と「移動平均の種別」のパラメーターを追加します。各パラメーターが何であるかを分かりやすくするために「//」でコメントも入れておきましょう。


input int      PERIOD_K = 5;              // %K 期間
input int      PERIOD_D = 3;              // %D 期間
input int      SLOWING = 3;               // スローイング
input ENUM_STO_PRICE PRICE = STO_LOWHIGH; // 価格欄
input ENUM_MA_METHOD METHOD = MODE_SMA;   // 移動平均の種別
input double   UPPER = 80.0;              // 上限レベル
input double   LOWER = 20.0;              // 下限レベル
input double   GAP = 5.0;                 //  バーからサインの距離 [pips]

続いて、ストキャスティクスのゴールデンクロス・デッドクロス発生時に表示する矢印のタイプを「SetIndexArrow」で指定します。

OnInit関数配下にある「PlotIndexSetInteger(2,PLOT_ARROW,159);」「PlotIndexSetInteger(3,PLOT_ARROW,159);」の2行を次のように書き換えましょう。今回は「233(上向きの普通の矢印)」と「234(下向きの普通の矢印)」を使います。


SetIndexArrow(2, 233);
SetIndexArrow(3, 234);


ストキャスティクスを表示する関数を作る


次に、ストキャスティクスをメインウィンドウに表示するための処理を記述していきます。

今回は「DrawStoch()」という関数を作ってストキャスティクスを表示させるようにしましょう。OnCalculate関数の配下で「DrawStoch();」を呼び出すようにします。


int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
{
//---
   DrawStoch();
//--- return value of prev_calculated for next call
   return(rates_total);
}

そしてOnChartEvent関数の配下に次のif文を加え、ティックが配信されたときとチャートが変化したときにDrawStoch()を実行するようにします。


if (id == CHARTEVENT_CHART_CHANGE) DrawStoch();


DrawStoch()の処理を記述


「ChartEvent function」の下に「Draw function」を設けて、DrawStoch()の処理を書いていきます。

まずは表示する範囲の定義です。チャートの左端のバーを表す「CHART_FIRST_VISIBLE_BAR」から、チャート幅全体のバーの本数を表す「CHART_WIDTH_IN_BARS」を引くことで、右端を求めることができます。もし、その計算結果がマイナスとなってしまった場合は値を「0」にしましょう。


void DrawStoch()
{
   int barF = (int)ChartGetInteger(0, CHART_FIRST_VISIBLE_BAR);
   int barR = barF - (int)ChartGetInteger(0, CHART_WIDTH_IN_BARS);
   if (barR < 0) barR = 0;

メインチャートにストキャスティクスを表示する場合は、メインチャートの一番下を「0%」、一番上を「100%」にする変換が必要となるので、「ChartGetDouble」でチャートの上下の価格を取得し、1%あたりのピッチ価格を算出します。


double max = ChartGetDouble(0, CHART_PRICE_MAX);
double min = ChartGetDouble(0, CHART_PRICE_MIN);
double pitch = (max - min) / 100;

そしてfor文でバーの左端から右端まで計算します。求めたピッチ価格を利用して、メインバッファーとシグナルバッファーを算出しましょう。下限+ピッチ価格×ストキャスティックスの値で求めることが可能です。


for (int i = barF; i >= barR; i--) {
   STOCH_MBuffer[i] = min + pitch * iStochastic(NULL, 0, PERIOD_K, PERIOD_D, SLOWING, METHOD,  PRICE, MODE_MAIN, i);
   STOCH_SBuffer[i] = min + pitch * iStochastic(NULL, 0, PERIOD_K, PERIOD_D, SLOWING, METHOD,  PRICE, MODE_SIGNAL, i);
}

なお、バッファ用の配列が定義される前に実行するとエラーが出るので、「int barF = (int)ChartGetInteger(0, CHART_FIRST_VISIBLE_BAR);」の上に次の一文を加えておきます。


if (ArraySize(STOCH_MBuffer) == 0) return;

これでコンパイルしてチャートにセットすると、メインウィンドウにストキャスティクスが表示されます。サブウィンドウに表示されているものと同じ形となっていることが分かります。

メインウィンドウにストキャスティクスが表示


20%と80%のレベルに水平線を表示


続いて、メインウィンドウにストキャスティクスのレベルラインを水平線で描画します。水平線のサンプルコードは、MQL4リファレンスからコピーして使いましょう。

MQL4リファレンスの目次にある「Constants, Enumerations and Structures」→「Objects Constants」→「Object Types」をクリックするとオブジェクトの一覧が表示されるので、その中から「OBJ_HLINE」を選択し、あらかじめ用意されている「Create the horizontal line」のコードをコピーしてファイル下部に貼り付けます。

「//--- if the price is not set, set it at the current Bid price level」から「ResetLastError();」までの5行と、「Print(__FUNCTION__,」「": failed to create a horizontal line! Error code = ", GetLastError());」の2行は不要なので削除してください。

また、「// line color」の色を「Red」から「Silver」に、「// line style」のスタイルを「SOLID」から「DOT」に、「// in the background」のバックを「false」から「true」に変更します。


//+------------------------------------------------------------------+
//| Create the horizontal line                                       |
//+------------------------------------------------------------------+
bool HLineCreate(const long            chart_ID = 0,      // chart's ID
                 const string          name = "HLine",    // line name
                 const int             sub_window = 0,    // subwindow index
                 double                price = 0,         // line price
                 const color           clr = clrSilver,      // line color
                 const ENUM_LINE_STYLE style = STYLE_DOT, // line style
                 const int             width = 1,         // line width
                 const bool            back = true,      // in the background
                 const bool            selection = false,  // highlight to move
                 const bool            hidden = true,     // hidden in the object list
                 const long            z_order = 0)       // priority for mouse click
{
//--- create a horizontal line
   if(!ObjectCreate(chart_ID, name, OBJ_HLINE, sub_window, 0, price)) {
      return(false);
   }
//--- set line color
   ObjectSetInteger(chart_ID, name, OBJPROP_COLOR, clr);
//--- set line display style
   ObjectSetInteger(chart_ID, name, OBJPROP_STYLE, style);
//--- set line width
   ObjectSetInteger(chart_ID, name, OBJPROP_WIDTH, width);
//--- display in the foreground (false) or background (true)
   ObjectSetInteger(chart_ID, name, OBJPROP_BACK, back);
//--- enable (true) or disable (false) the mode of moving the line by mouse
//--- when creating a graphical object using ObjectCreate function, the object cannot be
//--- highlighted and moved by default. Inside this method, selection parameter
//--- is true by default making it possible to highlight and move the object
   ObjectSetInteger(chart_ID, name, OBJPROP_SELECTABLE, selection);
   ObjectSetInteger(chart_ID, name, OBJPROP_SELECTED, selection);
//--- hide (true) or display (false) graphical object name in the object list
   ObjectSetInteger(chart_ID, name, OBJPROP_HIDDEN, hidden);
//--- set the priority for receiving the event of a mouse click in the chart
   ObjectSetInteger(chart_ID, name, OBJPROP_ZORDER, z_order);
//--- successful execution
   return(true);
}

このHLineCreateを使ってレベルラインを表示します。まずは水平線を表示するところの価格を、次の計算式で求めます。DrawStoch()の「double pitch = (max - min) / 100;」の下に追記しましょう。


double upper = min + pitch * UPPER;
double lower = min + pitch * LOWER;

求めた「upper」と「lower」を用いて、水平線を表示します。上下のレンジが変わった場合などに水平線を消して再描画するように「ObjectsDeleteAll」も実行しておきます。


ObjectsDeleteAll(0, "Stoch_");
HLineCreate(0, "Stoch_upper", 0, upper);
HLineCreate(0, "Stoch_lower", 0, lower);

また、チャートからインジケーターを外したときにも削除しなければならないので、OnDeinit関数も定義しておきましょう。「Custom indicator initialization function」の下に「Custom indicator deinitialization function」を設けて、下記コードを加えます。


void OnDeinit(const int reason)
{
   ObjectsDeleteAll(0, "Stoch_");
}

これでコンパイルすると、チャートのメインウィンドウの20%と80%のレベルに水平線が引かれます。

チャートのメインウィンドウの20%と80%のレベルに水平線


買いサインと売りサインを表示


最後に、条件を作って買いサインと売りサインを表示するようにします。まずDrawStoch()の「if (barR < 0) barR = 0;」の下で、ローソク足との距離を設定する「gap」を次のように定義しましょう。


double gap = GAP * _Point * 10;

そして、買いサインはメインラインがシグナルラインを上回り、かつ一本前ではメインラインがシグナルライン以下、かつ一本前の値は「lower」以下という条件にします。

同様に、売りサインはメインラインがシグナルラインを下回り、かつ一本前ではメインラインがシグナルライン以上、かつ一本前の値は「upper」以上という条件にします。

下記コードを「STOCH_SBuffer[i] = min + pitch * iStochastic(NULL, 0, PERIOD_K, PERIOD_D, SLOWING, METHOD, PRICE, MODE_SIGNAL, i);」の下に加えましょう。


if (STOCH_MBuffer[i] > STOCH_SBuffer[i] && STOCH_MBuffer[i + 1] <= STOCH_SBuffer[i+ 1] && STOCH_SBuffer[i+ 1] <= lower)
   UPBuffer[i] = Low[i] - gap;
else UPBuffer[i] = EMPTY_VALUE;

if (STOCH_MBuffer[i] < STOCH_SBuffer[i] && STOCH_MBuffer[i + 1] >= STOCH_SBuffer[i+ 1] && STOCH_SBuffer[i+ 1] >= upper)
   DNBuffer[i] = High[i] + gap;
else DNBuffer[i] = EMPTY_VALUE;

これでコンパイルすると、チャート上に買いサインとなる上向きの矢印と、売りサインとなる下向きの矢印が表示されることが分かります。

買いサインとなる上向きの矢印と、売りサインとなる下向きの矢印が表示


ソースコード


今回、作成したソースコードは下記の通りです。


//+------------------------------------------------------------------+
//|                                               MainChartStoch.mq4 |
//|                        Copyright 2022, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2022, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00"
#property strict
#property indicator_chart_window
#property indicator_buffers 4
#property indicator_plots   4
//--- plot STOCH_M
#property indicator_label1  "STOCH_M"
#property indicator_type1   DRAW_LINE
#property indicator_color1  clrLightSeaGreen
#property indicator_style1  STYLE_SOLID
#property indicator_width1  1
//--- plot STOCH_S
#property indicator_label2  "STOCH_S"
#property indicator_type2   DRAW_LINE
#property indicator_color2  clrRed
#property indicator_style2  STYLE_DOT
#property indicator_width2  1
//--- plot UP
#property indicator_label3  "UP"
#property indicator_type3   DRAW_ARROW
#property indicator_color3  clrRed
#property indicator_style3  STYLE_SOLID
#property indicator_width3  2
//--- plot DN
#property indicator_label4  "DN"
#property indicator_type4   DRAW_ARROW
#property indicator_color4  clrDodgerBlue
#property indicator_style4  STYLE_SOLID
#property indicator_width4  2
//--- input parameters
input int      PERIOD_K = 5;              // %K 期間
input int      PERIOD_D = 3;              // %D 期間
input int      SLOWING = 3;               // スローイング
input ENUM_STO_PRICE PRICE = STO_LOWHIGH; // 価格欄
input ENUM_MA_METHOD METHOD = MODE_SMA;   // 移動平均の種別
input double   UPPER = 80.0;              // 上限レベル
input double   LOWER = 20.0;              // 下限レベル
input double   GAP = 5.0;                 //  バーからサインの距離 [pips]
//--- indicator buffers
double         STOCH_MBuffer[];
double         STOCH_SBuffer[];
double         UPBuffer[];
double         DNBuffer[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
{
//--- indicator buffers mapping
   SetIndexBuffer(0, STOCH_MBuffer);
   SetIndexBuffer(1, STOCH_SBuffer);
   SetIndexBuffer(2, UPBuffer);
   SetIndexBuffer(3, DNBuffer);
//--- setting a code from the Wingdings charset as the property of PLOT_ARROW
   SetIndexArrow(2, 233);
   SetIndexArrow(3, 234);

//---
   return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                         |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
   ObjectsDeleteAll(0, "Stoch_");
}
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
{
//---
   DrawStoch();
//--- return value of prev_calculated for next call
   return(rates_total);
}
//+------------------------------------------------------------------+
//| ChartEvent function                                              |
//+------------------------------------------------------------------+
void OnChartEvent(const int id,
                  const long &lparam,
                  const double &dparam,
                  const string &sparam)
{
//---
   if (id == CHARTEVENT_CHART_CHANGE) DrawStoch();
}
//+------------------------------------------------------------------+
//| Draw function                                              |
//+------------------------------------------------------------------+
void DrawStoch()
{
   if (ArraySize(STOCH_MBuffer) == 0) return;

   int barF = (int)ChartGetInteger(0, CHART_FIRST_VISIBLE_BAR);
   int barR = barF - (int)ChartGetInteger(0, CHART_WIDTH_IN_BARS);
   if (barR < 0) barR = 0;

   double gap = GAP * _Point * 10;

   double max = ChartGetDouble(0, CHART_PRICE_MAX);
   double min = ChartGetDouble(0, CHART_PRICE_MIN);
   double pitch = (max - min) / 100;

   double upper = min + pitch * UPPER;
   double lower = min + pitch * LOWER;

   ObjectsDeleteAll(0, "Stoch_");

   HLineCreate(0, "Stoch_upper", 0, upper);
   HLineCreate(0, "Stoch_lower", 0, lower);

   for (int i = barF; i >= barR; i--) {
      STOCH_MBuffer[i] = min + pitch * iStochastic(NULL, 0, PERIOD_K, PERIOD_D, SLOWING, METHOD,  PRICE, MODE_MAIN, i);
      STOCH_SBuffer[i] = min + pitch * iStochastic(NULL, 0, PERIOD_K, PERIOD_D, SLOWING, METHOD,  PRICE, MODE_SIGNAL, i);

      if (STOCH_MBuffer[i] > STOCH_SBuffer[i] && STOCH_MBuffer[i + 1] <= STOCH_SBuffer[i + 1] && STOCH_SBuffer[i + 1] <= lower)
         UPBuffer[i] = Low[i] - gap;
      else UPBuffer[i] = EMPTY_VALUE;

      if (STOCH_MBuffer[i] < STOCH_SBuffer[i] && STOCH_MBuffer[i + 1] >= STOCH_SBuffer[i + 1] && STOCH_SBuffer[i + 1] >= upper)
         DNBuffer[i] = High[i] + gap;
      else DNBuffer[i] = EMPTY_VALUE;
   }
}
//+------------------------------------------------------------------+
//| Create the horizontal line                                       |
//+------------------------------------------------------------------+
bool HLineCreate(const long            chart_ID = 0,      // chart's ID
                 const string          name = "HLine",    // line name
                 const int             sub_window = 0,    // subwindow index
                 double                price = 0,         // line price
                 const color           clr = clrSilver,      // line color
                 const ENUM_LINE_STYLE style = STYLE_DOT, // line style
                 const int             width = 1,         // line width
                 const bool            back = true,      // in the background
                 const bool            selection = false,  // highlight to move
                 const bool            hidden = true,     // hidden in the object list
                 const long            z_order = 0)       // priority for mouse click
{
//--- create a horizontal line
   if(!ObjectCreate(chart_ID, name, OBJ_HLINE, sub_window, 0, price)) {
      return(false);
   }
//--- set line color
   ObjectSetInteger(chart_ID, name, OBJPROP_COLOR, clr);
//--- set line display style
   ObjectSetInteger(chart_ID, name, OBJPROP_STYLE, style);
//--- set line width
   ObjectSetInteger(chart_ID, name, OBJPROP_WIDTH, width);
//--- display in the foreground (false) or background (true)
   ObjectSetInteger(chart_ID, name, OBJPROP_BACK, back);
//--- enable (true) or disable (false) the mode of moving the line by mouse
//--- when creating a graphical object using ObjectCreate function, the object cannot be
//--- highlighted and moved by default. Inside this method, selection parameter
//--- is true by default making it possible to highlight and move the object
   ObjectSetInteger(chart_ID, name, OBJPROP_SELECTABLE, selection);
   ObjectSetInteger(chart_ID, name, OBJPROP_SELECTED, selection);
//--- hide (true) or display (false) graphical object name in the object list
   ObjectSetInteger(chart_ID, name, OBJPROP_HIDDEN, hidden);
//--- set the priority for receiving the event of a mouse click in the chart
   ObjectSetInteger(chart_ID, name, OBJPROP_ZORDER, z_order);
//--- successful execution
   return(true);
}


本記事の監修者・HT FX


2013年にFXを開始し、その後専業トレーダーへ。2014年からMT4/MT5のカスタムインジケーターの開発に取り組む。ブログでは100本を超えるインジケーターを無料公開。投資スタイルは自作の秒足インジケーターを利用したスキャルピング。

EA(自動売買)を学びたい方へオススメコンテンツ

EA運用の注意点

OANDAではEA(自動売買)を稼働するプラットフォームMT4/MT5の基本的な使い方について、画像や動画付きで詳しく解説しています。MT4/MT5のインストールからEAの設定方法までを詳しく解説しているので、初心者の方でもスムーズにEA運用を始めることが可能です。またOANDAの口座をお持ちであれば、独自開発したオリジナルインジケーターを無料で利用することもできます。EA運用をお考えであれば、ぜひ口座開設をご検討ください。


本ホームページに掲載されている事項は、投資判断の参考となる情報の提供を目的としたものであり、投資の勧誘を目的としたものではありません。投資方針、投資タイミング等は、ご自身の責任において判断してください。本サービスの情報に基づいて行った取引のいかなる損失についても、当社は一切の責を負いかねますのでご了承ください。また、当社は、当該情報の正確性および完全性を保証または約束するものでなく、今後、予告なしに内容を変更または廃止する場合があります。なお、当該情報の欠落・誤謬等につきましてもその責を負いかねますのでご了承ください。

この記事をシェアする

ホーム » FX自動売買基礎と応用 » ストキャスティクスをメインウィンドウに表示する自動売買の作成方法