2016年5月9日月曜日

[MQL超入門] その020 本格的にEAを作ってみよう。その1 テクニカル指標を使用する

いよいよテクニカル指標を使って本格的にEAを作ってみましょう。
本格的に、と言ってもまずはシンプルに、移動平均線に対して終値が上抜ければ買い、下抜ければ売る、という戦略にします。1ポジションのみで両建てなし、いわゆるドテン注文です。
とりあえず時間軸を1時間、25本での単純移動平均として作りましょう。

始めに断っておきますが、この戦略が有効だという意味では全くありません。
あくまでテクニカル指標を使ったEAを作る例としているだけです。

それでは前に作った簡単EAと同様に、[テスト]フォルダの下に[EA_MA]という名前のEAを新たに作成しましょう。

新しいEAの作成方法はこちら
[MQL超入門] その014 とりあえずやってみよう!簡単EA作成1

そして、次の変更を加えます。
//+------------------------------------------------------------------+
//|                                                        EA_MA.mq4 |
//|                        Copyright 2016, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2016, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00"
#property strict

#include <Custom/TradingWrapper.mqh>

input int MagicNumber = 37858261; //マジックナンバー 他のEAと当らない値を使用する。
input int MaxPosition = 1;        //最大ポジション数
input double SpreadFilter = 2;    //最大スプレット値(PIPS)

input double Lot = 0.02;          //売買ロット
input uint Slippage = 2;          //許容スリップページ(pips)
input uint StopLoss = 200;        //ストップロス
input uint TakeProfit = 200;      //利益確定

input int MaPeriod = 25;                              //移動平均の期間
input ENUM_MA_METHOD MaMethod = MODE_SMA;             //移動平均線の種類
input ENUM_APPLIED_PRICE AppliedPrice = PRICE_CLOSE;  //移動平均を計算する価格の種類

// トレード補助クラス
CTradingWrapper m_wrapper(Symbol(), MagicNumber, MaxPosition, SpreadFilter);

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
{
//---
   
//---
   return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
//---
   
}
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
{
//---
   string symbol = Symbol();
   static ENUM_TIMEFRAMES target = PERIOD_H1;
   static datetime before = 0;

   // 1時間の確定足でのみ動作
   datetime current = iTime(symbol, target, 0);
   if( before == current )
   {
      return ;
   }
   before = current;

   m_wrapper.RefreshPositions();

   // 1つ前と2つ前の足の終値を取得する
   double close1 = iClose( symbol, target, 1 );
   double close2 = iClose( symbol, target, 2 );
   
   // 1つ前と2つ前の移動平均の値を取得する
   double ma1 = iMA( symbol, target, MaPeriod, 0, MaMethod, AppliedPrice, 1 );
   double ma2 = iMA( symbol, target, MaPeriod, 0, MaMethod, AppliedPrice, 2 );
   
   int orderCmd = OP_NONE;
   if ( close1 > ma1 && close2 < ma2 )
   {
      // 終値が移動平均線を上抜けたら買う
      orderCmd = OP_BUY;
   }
   else if ( close1 < ma1 && close2 > ma2 )
   {
      // 終値が移動平均線を下抜けたら売る
      orderCmd = OP_SELL;
   }
   
   if ( orderCmd != OP_NONE )
   {
      bool hasPosition = ( m_wrapper.GetPositionCount() > 0 );
      if ( hasPosition )
      {
         // ポジションを保持していれば決済する
         m_wrapper.CloseOrder( 0, Slippage );
      }

      m_wrapper.RefreshPositions();
      
      // 注文する
      m_wrapper.SendOrder( orderCmd, Lot, 0, Slippage, StopLoss, TakeProfit );
   }   
}
//+------------------------------------------------------------------+
今までの説明で、内容も大体理解できるのではないかと思いますが、前の説明と重複する部分を除いて説明していきます。

input int MaPeriod = 25;                              //移動平均の期間
input ENUM_MA_METHOD MaMethod = MODE_SMA;             //移動平均線の種類
input ENUM_APPLIED_PRICE AppliedPrice = PRICE_CLOSE;  //移動平均を計算する価格の種類
使用する移動平均線の条件です。入力パラメータとして宣言しています。

   // 1つ前と2つ前の足の終値を取得する
   double close1 = iClose( symbol, target, 1 );
   double close2 = iClose( symbol, target, 2 );
ここでまず終値を取得しています。
標準で用意されている、終値を取得するiClose()関数を使用しています。
iClose()関数の引数は以下のとおりです。
・string symbol
  終値を取得する通過ペア名。
・int timeframe
  終値を取得する時間軸。時間軸は、以下のように定義されています。
  ENUM_TIMEFRAMES列挙型
・int shift
  終値を取得する足の位置。(0~)

最後の引数は0から始まる足の位置を指定しますが、数字が小さいほど新しい足を表すため0が最新の足になります。
ここで最新の足とは、現在形成中の足のことですので、取得される値が変わる事があります。
既に確定済みの値を使用したい場合、1が確定済みの最新の足ということになります。
このコードでは1つ前と2つ前なので、確定済みの最新2本の終値を取得しています。

なお、チャートの価格を取得する関数は、iClose()の他にもiOpen()、iHigh()、iLow()があります。
名前から分かると思いますが、それぞれ始値、高値、安値を取得する関数です。使い方はiClose()と変わりません。

   // 1つ前と2つ前の移動平均の値を取得する
   double ma1 = iMA( symbol, target, MaPeriod, 0, MaMethod, AppliedPrice, 1 );
   double ma2 = iMA( symbol, target, MaPeriod, 0, MaMethod, AppliedPrice, 2 );
ここでは移動平均の値を取得しています。
標準で用意されている、移動平均を計算するiMA()関数を使用しています。
iMA()関数の引数は以下のとおりです。
・string symbol
  移動平均を計算する通過ペア名。
・int timeframe
  移動平均を計算する時間軸。時間軸は、以下のように定義されています。
  ENUM_TIMEFRAMES列挙型
・int period
  移動平均の期間。
・int ma_shift
  移動平均線をシフトする本数。
・ENUM_MA_METHOD ma_method
  移動平均線の種類。種類は、以下のように定義されています。
  ENUM_MA_METHOD列挙型
・ENUM_APPLIED_PRICE applied_price
  移動平均を計算する価格の種類。種類は、以下のように定義されています。
  ENUM_APPLIED_PRICE列挙型
・int shift
  移動平均の値を取得する足の位置。(0~)

終値と同じように1つ前と2つ前の位置の移動平均を取得しています。
また引数として渡す条件が、入力パラメータとなっています。

なお、標準で用意されているテクニカル指標を取得する関数も、iMA()の他にもたくさん存在します。以下を参考にしてください。
テクニカル指標関数

   int orderCmd = OP_NONE;
   if ( close1 > ma1 && close2 < ma2 )
   {
      // 終値が移動平均線を上抜けたら買う
      orderCmd = OP_BUY;
   }
   else if ( close1 < ma1 && close2 > ma2 )
   {
      // 終値が移動平均線を下抜けたら売る
      orderCmd = OP_SELL;
   }
ここはコメントにも書いてあるので分かると思いますが、上抜けた場合と下抜けた場合に、それぞれの注文の方向を決めています。
close1とclose2が1つ前と2つ前の終値、ma1とma2が1つ前と2つ前の移動平均線の値なので、直近のclose1がma1を超えていて、その前のclose2がma2未満の場合、上抜けたと判断しています。
下抜けはその反対ですね。

後はorderCmdに代入された注文種別によって取引を行っています。この辺は簡単EAとほとんど変わりませんので分かるかと思います。

コンパイルが通ったら、バックテストをしてみましょう。

赤い線が移動平均線で、上抜けと下抜けで売買していることが確認できます。
成績は見てもらえば分かるので載せませんが、まぁずいぶん負けてますw

こんな単純な戦略だけで勝てたら誰も苦労しないという話ですよね。実際は独自の複雑なインジケータなども組み合わせながら戦略を立てるかと思います。
なので次は、独自のインジケータを使ったEAを作ってみたいと思います。

次の回へ

「MT4でFXを勝ち抜く研究をするブログ」で公開している無料インジケータは、こちらの一覧から。
インジケータ一覧

Twitterもよろしくお願いします。
https://twitter.com/mt4program

ブログランキングにご協力よろしくお願いします。m(._.)m
にほんブログ村 為替ブログ MetaTraderへ
にほんブログ村

お約束ですが、本ブログは、投資に対する利益を約束する物ではありません。最終的には自己責任によるご判断よろしくお願いいたします。