2016年4月22日金曜日

[MQL超入門] その015 とりあえずやってみよう!簡単EA作成2

ではさっそく取引するコードを書いてみましょう。
・・と言いたいところですが、その前に1つお約束事があります。

本ブログ内のEA関係の記事は、注文クラスと呼んでいるクラスを使用しています。
「クラス」とは何かという説明はひとまず置いといて、EAを作成するのに必要なソースファイルがあるとだけ理解しておいてください。

ファイルの内容はこちらで公開しています。
http://mt4program.blogspot.jp/2016/04/mt4_57.html

必要なファイルは以下の2つです。
上記の記事のコードをそのままコピーし、Include/Customフォルダの下にそれぞれのファイル名で保存してください。
・TradingWrapper.mqh
・TradingDefines.mqh

準備ができたら、EAのコードを次のように変更します。
//+------------------------------------------------------------------+
//|                                                      Sample1.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 = 37858260; //マジックナンバー 他のEAと当らない値を使用する。
input int MaxPosition = 1;        //最大ポジション数
input double SpreadFilter = 2;    //最大スプレット値(PIPS)

// トレード補助クラス
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()
{
//---

}
//+------------------------------------------------------------------+

コードを変更したら、メタエディターの[コンパイル]ボタンをクリックしてみましょう。
・図015.01 コンパイルボタン

メタエディター左下の[エラー]欄に赤いびっくりマークのエラーが出た場合は、上記のファイル内容やファイル名、保存先が正しいか、または変更したコードが正しいかどうかを確認してください。

エラーが出なければ正しく準備が完了していることになりますので、先へ進みます。
ここまでではまだ取引は一切行われませんので、引き続き次のように実際に取引するコードを追加しましょう。
//+------------------------------------------------------------------+
//|                                                      Sample1.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 = 37858260; //マジックナンバー 他の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;      //利益確定

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

int counter = 0;
bool isBuy = true;

//+------------------------------------------------------------------+
//| 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;
   
   counter++;
   if ( counter < 5 )
   {
      // 5本に1回しか処理しない
      return;
   }   
   // カウンターをリセット
   counter = 0;

   m_wrapper.RefreshPositions();
   
   bool hasPosition = ( m_wrapper.GetPositionCount() > 0 );
   if ( !hasPosition )
   {
      // ポジションを保持していなければ注文する
      int orderCmd = ( isBuy ? OP_BUY : OP_SELL );
      m_wrapper.SendOrder( orderCmd, Lot, 0, Slippage, StopLoss, TakeProfit );

      // 売/買を反転      
      isBuy = !isBuy;
   }
   else
   {
      // ポジションを保持していれば決済する
      m_wrapper.CloseOrder( 0, Slippage );
   }
}
//+------------------------------------------------------------------+

先ほどと同様にコンパイルを行い、エラーが出ないことを確認してください。

内容としては、5時間ごとに、買い→決済→売り→決済→買い→・・・と取引を繰り返すだけです。
コードの説明は後ほどしたいと思いますので、まずは結果を見てみましょう。

長くなりましたので、続きは次回に。

次の回へ


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

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

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

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

2016年4月21日木曜日

[雑記]MQL超入門を更新しました

先ほど、久しぶりにMQL超入門の最新記事を追加しました。
これからはEA作成についてを取り上げていきます。
[MQL超入門] その014 とりあえずやってみよう!簡単EA作成1

それに伴い、MQL超入門の目次ページも作成しました。
MQL超入門 目次

ブログの左側に「MQL超入門 目次」のリンクを作りましたので、そこから見ると便利です。

また、各記事の最後に「次の回へ」というリンクを追加して続けて読めるようにしましたので、読みやすくなっていると思います。
初めて読まれる方も、読み直したい方も、ぜひ読んでみてください。


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

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

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

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

[MQL超入門] その014 とりあえずやってみよう!簡単EA作成1

これまででインジケータの作りかたを学びました。
今回からは、EAを作ってみましょう。

※インジケータ作成の時と繰り返しになりますが、リアル口座を運用しているMT4を使用する場合、ソフトウェアの作成に失敗すると、取引に影響が出ます。
そこで、プログラム開発用にMT4のデモ口座を作ることをお勧めします。

[雑記]MT4のデモ口座はどこがいい?
http://mt4program.blogspot.jp/2015/12/mt4.html
などから、プログラム開発用のデモ口座を開き、プログラムはデモ口座が動いているMT4上で作ることをお勧めします。

インジケータの時と同じで、EAもウィザードから追加します。
メタエディター上で下記の通りに操作してみてください。

ナビゲータ上で、[Experts]を選択して、マウスの右クリックから[新規ファイル(N)]を選択します。
・図014.01 EA 新規作成

MQL4ウィザードにて[エキスパートアドバイザ(テンプレート)]を選択した状態で、[次へ(N)]をクリックします。
・図014.02 MQLウィザード EA選択

名前の箇所に[Experts\テスト\Sample1]と入力して[次へ(N)]を押します。
今回はあらかじめExpertsの下に[テスト]フォルダを作成しておき、その中にSample1というEAを作成します。
・図014.03 MQLウィザード 名前の決定

チェックが全て外れている状態で、[次へ(N)]をクリックします。
・図014.04 MQLウィザード カスタムイベントハンドラの選択

チェックが全て外れている状態で、[完了]をクリックして終了です。
・図014.05 MQLウィザード テスターイベントハンドラの選択

そうすると次のようなファイルが出来上がります。
これがEAの最小限のひな形となります。
//+------------------------------------------------------------------+
//|                                                      Sample1.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
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
{
//---
   
//---
   return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
//---
   
}
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
{
//---
   
}
//+------------------------------------------------------------------+

もちろんこのままでは取引は何も行われませんので、次回からは実際に取引するコードを書いていきます。

次の回へ


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

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

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

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

2016年4月20日水曜日

[MT4インジケータ]TEMA傾き累積インジケータによるトレンドフォロー 追加考察 その2

少し時間が空きましたが、TEMA傾き累積インジケータを使った戦略の続きです。

前回の記事はこちら
TEMA傾き累積インジケータによるトレンドフォロー 追加考察

傾き量の変化が短期周期に惑わされずトレンド方向を表すことを目的として、閾値を使ってある程度細かい振幅は無視してしまうというのが前回までの話でした。

ある程度長期のトレンドの中にも短期周期の上下は必ず発生しますので、今回はこれを逆手にとって、閾値なしで方向がリセットされる場合と、閾値を使ってリセットされない場合で考えます。
閾値を使ってリセットされないという事は、トレンド方向としては継続していると考えられますが、その中で小さな反転の動きがあった場合、追加で売り買いのチャンスになるのではないでしょうか。

チャートで見てみるとこんな感じです。
インジケータの上が閾値あり、下が閾値なしです。
例えば赤い丸のあたりで、閾値ありではリセットされず、閾値なしでリセットされています。
チャートを見てもわずかな上昇が見えますので、ここで追撃する戦略を検証してみます。

まずは追撃なし1ポジションのみの結果から見てみます。

通貨ペアEURUSD (EUR/USD)
期間15分足(M15) 2011.01.03 00:00 - 2015.12.31 00:00 (2011.01.01 - 2015.12.31)
モデルコントロールポイント(おおまかな方法。結果はあまり信頼性はない)
パラメーターMagicNumber=55351234; Lot=0.1; SpreadFilter=5; MaxPosition=2; Slippage=5; CloseBarCount=110; CloseLimitBarCount=80; StopLoss=100; TakeProfit=400; FixProfit=40; MinProfit=2; Threashold=5; EnableDiff=2; PositionPeriod=5; PositionStdPeriod=21; PositionEmaAlfa=0.8; PositionSigma1=0.7; PositionSigma2=2; ScanPeriod=60;
テストバー数124772モデルティック数4393676モデリング品質n/a
不整合チャートエラー0
初期証拠金10000.00スプレッド現在値 (5)
純益2893.80総利益13229.10総損失-10335.30
プロフィットファクタ1.28期待利得7.84
絶対ドローダウン420.00最大ドローダウン1007.00 (9.07%)相対ドローダウン9.07% (1007.00)
総取引数369売りポジション(勝率%)188 (69.15%)買いポジション(勝率%)181 (68.51%)
勝率(%)254 (68.83%)負率 (%)115 (31.17%)
最大勝トレード400.00敗トレード-100.00
平均勝トレード52.08敗トレード-89.87
最大連勝(金額)12 (521.30)連敗(金額)4 (-400.00)
最大連勝(トレード数)688.70 (4)連敗(トレード数)-400.00 (4)
平均連勝3連敗1

次に追撃ありの結果です。
最大4ポジションの両建てなしで、リセットされた際には保持しているポジションは全決済します。

通貨ペアEURUSD (EUR/USD)
期間15分足(M15) 2011.01.03 00:00 - 2015.12.31 00:00 (2011.01.01 - 2015.12.31)
モデルコントロールポイント(おおまかな方法。結果はあまり信頼性はない)
パラメーターMagicNumber=55351234; Lot=0.1; SpreadFilter=5; MaxPosition=8; Slippage=5; CloseBarCount=110; CloseLimitBarCount=80; StopLoss=100; TakeProfit=400; FixProfit=40; MinProfit=2; Threashold=5; EnableDiff=2; PositionPeriod=5; PositionStdPeriod=21; PositionEmaAlfa=0.8; PositionSigma1=0.7; PositionSigma2=2; ScanPeriod=60;
テストバー数124772モデルティック数4393676モデリング品質n/a
不整合チャートエラー0
初期証拠金10000.00スプレッド現在値 (5)
純益11141.60総利益38457.90総損失-27316.30
プロフィットファクタ1.41期待利得11.57
絶対ドローダウン2433.40最大ドローダウン2779.00 (26.86%)相対ドローダウン26.86% (2779.00)
総取引数963売りポジション(勝率%)495 (66.67%)買いポジション(勝率%)468 (69.44%)
勝率(%)655 (68.02%)負率 (%)308 (31.98%)
最大勝トレード400.00敗トレード-100.00
平均勝トレード58.71敗トレード-88.69
最大連勝(金額)31 (1163.10)連敗(金額)10 (-1000.00)
最大連勝(トレード数)2897.50 (25)連敗(トレード数)-1000.00 (10)
平均連勝6連敗3

グラフはほぼ同じ形のまま、ポジション数が増えている分利益が飛躍的に増えています。
追撃することで利益が増えているので、売買のタイミングとしては効果的であると言えそうです。

単純な自動売買ではマイナスの動きのときにも追撃していてドローダウンも増えていますが、このあたりを考慮すれば十分使えるのではないでしょうか。

TEMAの傾き量インジケータの無料ダウンロードはこちらから
TEMAの傾き量でトレンドフォロー
TEMAの傾き量でトレンドフォロー

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

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

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

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

2016年4月19日火曜日

[MT4プログラミング]注文クラス修正版

ずいぶん久しぶりですが、注文クラスの修正版をまたアップしておきます。

前回のアップからなんと約1年ぶり!
といっても機能的な大きな変更はほとんどなく、関数の引数の初期値対応や細かなバグの修正といった感じです。

なのでアップする程でもなく細々と修正を加えてきましたが、もうだいぶ安定して動作しているし、(ふと思い出したので・・)アップしました。
//------------------------------------------------------------------
// 注文関係ラッパークラス
#property copyright "Copyright 2015,  Daisuke"
#property link      "http://mt4program.blogspot.jp/"
#property version   "1.40"
#property strict

#include <Arrays/ArrayInt.mqh>
#include <Custom/TradingDefines.mqh>
#include <stdlib.mqh>
#include <stderror.mqh>

//------------------------------------------------------------------
// 注文関係ラッパークラス
class CTradingWrapper
{
private:
   // マジックナンバー
   int m_magicNumber;
   
   // 最大ポジション数
   int m_maxPosition;
   
   // 最大スプレット
   double m_spreadFilter;
   
   // Pips倍率
   int m_pipsRate;
   
   // 対象通貨ペア
   string m_symbol;
   
   // 保有ポジション
   CArrayInt m_positions ;
   
   // タイムアウト値
   uint m_timeout;
   
   // 少数桁数
   int m_digit;
   
   // 取扱い最小値
   double m_point ;
   
   // デフォルトのコメント
   string m_defualtComment;
   
   // カウントダウン方式の場合true
   bool m_isCountdown;
public:
   //------------------------------------------------------------------
   // コンストラクタ
   CTradingWrapper(
      string symbol,       //対象通貨ペア
      int magicNumber,     //マジックナンバー
      int maxPosition,     //最大ポジション数
      double spreadFilter, //最大スプレット
      uint timeout,        //タイムアウト
      bool isCountdown,    // カウントダウン方式
      string defualtComment //デフォルトコメント
      );

   //------------------------------------------------------------------
   // デストラクタ
   ~CTradingWrapper();
   
   //------------------------------------------------------------------
   // 発注する
   // Return   発注成功時インデックス それ以外-1
   int SendOrder(
      int cmd,                //売買種別  
      double volume,          //売買ロット
      double price,           //価格
      uint slippage,          //許容スリッピング(Pips単位)
      uint stoploss,          //ストップロス(Pips単位)
      uint takeprofit,        //利確値(Pips単位)
      string comment,         //コメント
      datetime expiration,    //注文有効期限
      color arrowColor        //注文矢印の色
   );
   
   //------------------------------------------------------------------
   // 発注する
   // Return   発注成功時インデックス それ以外-1
   int SendOrderPrice(
      int cmd,                      //売買種別  
      double volume,                //売買ロット
      double price,                 //価格(成行き時は現在値を自動設定)
      uint slippage,                //許容スリッピング(Pips単位)
      double stoploss = 0,          //ストップロス(価格)
      double takeprofit = 0,        //利確値(価格)
      string comment = NULL,        //コメント
      datetime expiration = 0,      //注文有効期限
      color arrowColor = clrNONE    //注文矢印の色
   );
   
   //------------------------------------------------------------------
   // 成行き決済を行う。
   // Return   発注成功時ture それ以外false
   bool CloseOrder(
      int index,                    //決済するインデックス
      uint slippage,                //許容スリッピング
      color arrowColor = clrNONE    //注文矢印の色
   );
   
   //------------------------------------------------------------------
   // 全ポジションを成行き決済を行う。
   // Return   発注成功時ture それ以外false
   bool CloseOrderAll(
      uint slippage,                //許容スリッピング
      color arrowColor = clrNONE    //注文矢印の色
   );

   //------------------------------------------------------------------
   // 注文を変更する。
   // Return   発注成功時ture それ以外false
   bool ModifyOrder(
      int index,              //決済するインデックス
      uint stoploss,          //ストップロス(Pips単位)
      uint takeprofit,        //利確値(Pips単位)
      color arrowColor        //注文矢印の色
   );
   
   //------------------------------------------------------------------
   // 注文を変更する。
   // Return   発注成功時ture それ以外false
   bool CTradingWrapper::ModifyOrderPrice(
      int index,                 //決済するインデックス
      double stoploss,           //ストップロス(Pips単位)
      double takeprofit = 0,     //利確値(Pips単位)0は変更なし
      color arrowColor = clrNONE //注文矢印の色
   );

   //------------------------------------------------------------------
   // すべての注文を変更する。
   bool ModifyOrderAll(
      uint stoploss,          //ストップロス(Pips単位)
      uint takeprofit,        //利確値(Pips単位)
      color arrowColor        //注文矢印の色
   );
   
   //------------------------------------------------------------------
   // マジックナンバーを取得する。
   // Return   マジックナンバー
   int GetMagicNumber() { return m_magicNumber; };
   
   //------------------------------------------------------------------
   // 現在のポジション数を取得する。
   // Return   現在のポジション数を取得する。
   int GetPositionCount(){ return m_positions.Total(); };
   
   //------------------------------------------------------------------
   // 最大ポジション数を取得する。
   // Return   最大ポジション数を取得する。
   int GetMaxPosition(){ return m_maxPosition; };
   
   //------------------------------------------------------------------
   // 通貨ペアを取得する。
   // Return   最大ポジション数を取得する。
   string GetSymbol(){ return m_symbol; };
   
   //------------------------------------------------------------------
   // 指定番号のチケットを取得する。
   // Return   チケット番号 取得失敗時-1
   int GetTicket(
      int index         //インデックス
   );
   
   //------------------------------------------------------------------
   // 指定番号の売買種別 を取得する。
   // Return   売買種別 
   int GetOrderType(
      int index         //インデックス
   );
   
   //------------------------------------------------------------------
   // 指定番号の現在利益を取得する。
   // Return   現在利益(Pips)
   double GetOrderProfit(
      int index         //インデックス
   );
   
   //------------------------------------------------------------------
   // 指定番号の現在リミット値を取得する。
   // Return   リミット値
   double GetOrderLimit(
      int index         //インデックス
   );
   
   //------------------------------------------------------------------
   // 指定番号の現在リミット値を取得する。
   // Return   リミット値(Pips)
   double GetOrderLimitPips(
      int index         //インデックス
   );

   //------------------------------------------------------------------
   // 指定番号のオープン価格を取得する。。
   // Return   オープン値
   double GetOrderOpen(
      int index         //インデックス
   );
   
   
   //------------------------------------------------------------------
   // 指定番号の現在値を取得する。
   // Return   現在価格
   double GetOrderClose(
      int index         //インデックス
   );
   
   //------------------------------------------------------------------
   // 指定番号の取引開始時間 を取得する。
   // Return   取引開始時間 
   datetime GetOrderOpenTime(
      int index         //インデックス
   );

   //------------------------------------------------------------------
   // 1pipsあたりの値を取得する。
   // Return   1pipあたりの値
   double GetPipsValue() { return m_point * m_pipsRate; } ;

   //------------------------------------------------------------------
   // 指定pipsあたりの値を取得する。
   // Return   指定pipあたりの値
   double GetPipsValue(
      double pips    // 指定Pips
   ){ return pips * m_point * m_pipsRate; } ;
   
   //------------------------------------------------------------------
   // ポジションリストを更新する。
   void RefreshPositions();
   
private:

   //------------------------------------------------------------------
   // 設定パラメータが安全かどうか
   // Return 安全ture それ以外false
   bool IsSafeParameter();

};

//------------------------------------------------------------------
// コンストラクタ
CTradingWrapper::CTradingWrapper(
      string symbol,             //対象通貨ペア
      int magicNumber = 0,       //マジックナンバー
      int maxPosition = 3,       //最大ポジション数
      double spreadFilter = 5,   //最大スプレット
      uint timeout = 1000,       //タイムアウト(ms)
      bool isCountdown = false,  // カウントダウン方式
      string defualtComment=NULL //デフォルトコメント 
)
{
   m_symbol = symbol;
   m_magicNumber = magicNumber;
   m_maxPosition = maxPosition;
   m_timeout = timeout;
   m_positions.Resize(m_maxPosition);
   m_defualtComment = defualtComment;
   m_isCountdown = isCountdown;
   
   //Pips計算 小数点桁数が3or5の場合、Point()*10=1pips
   m_digit = (int)MarketInfo(m_symbol, MODE_DIGITS);
   m_point = (double)MarketInfo(m_symbol, MODE_POINT);

   m_pipsRate = m_digit == 3 || m_digit == 5 ? 10 : 1;
   
   for( int i = 0 ; i < OrdersTotal(); i++)
   {
      if( OrderSelect(i, SELECT_BY_POS) )
      {
         if( OrderMagicNumber() == m_magicNumber && OrderSymbol() == m_symbol)
         {
            m_positions.Add(OrderTicket());
         }
      }
   }
   m_spreadFilter = GetPipsValue(spreadFilter);
}

//------------------------------------------------------------------
// デストラクタ
CTradingWrapper::~CTradingWrapper()
{
}

//------------------------------------------------------------------
// 発注する
// Return   発注成功時インデックス それ以外-1
int CTradingWrapper::SendOrder(
      int cmd,                      //売買種別  
      double volume,                //売買ロット
      double price,                 //価格(成行き時は現在値を自動設定)
      uint slippage,                //許容スリッピング(Pips単位)
      uint stoploss = 0,            //ストップロス(Pips単位)
      uint takeprofit = 0,          //利確値(Pips単位)
      string comment = NULL,        //コメント
      datetime expiration = 0,      //注文有効期限
      color arrowColor = clrNONE    //注文矢印の色
)
{
   if( !this.IsSafeParameter() ) return -1;
   if( m_positions.Total() >= m_maxPosition ) return -1 ;

   if( comment == NULL ) comment = m_defualtComment;

   // 計算用 負数フラグ
   int flag = cmd == OP_BUY || cmd == OP_BUYLIMIT || cmd == OP_BUYSTOP ? 1 : -1;
   
   uint start = GetTickCount();
   while(!IsStopped())
   {
      if( (GetTickCount() - start ) > m_timeout ) return -1;

      double bid = MarketInfo(m_symbol, MODE_BID);
      double ask = MarketInfo(m_symbol, MODE_ASK);
      
      // スプレットが大きすぎる場合は取引しない。
      if( NormalizeDouble(MathAbs(ask - bid), m_digit) > m_spreadFilter )
      {
         Print("Order failed. spread over.");
         return -1;
      }

      if( cmd == OP_SELL ) price = bid;
      if( cmd == OP_BUY ) price = ask;

      double closeTarget = cmd == OP_BUY || cmd == OP_BUYLIMIT || cmd == OP_BUYSTOP ? ask : bid; 

      //pips値からストップロス値、利益確定値を取得する。   
      double stoplossValue = 0 ;
      double takeprofitValue = 0;
      if( stoploss != 0 )
      {
         stoplossValue = NormalizeDouble(closeTarget - this.GetPipsValue(stoploss) * flag, m_digit );
      }
      if( takeprofit != 0)
      {
         takeprofitValue = NormalizeDouble(closeTarget + this.GetPipsValue(takeprofit) * flag, m_digit );
      }

      if( IsTradeAllowed() )
      {
         if( AccountFreeMarginCheck(m_symbol, cmd, volume) < 0 )
         {
            int errorCode = GetLastError();
            Print("AccountFreeMarginCheck Error[",errorCode ,"]");
            return -1;
         }
         
         int tiket = -1;
         if( m_isCountdown )
         {
            tiket = ::OrderSend(m_symbol, cmd, volume, price,
               slippage * m_pipsRate, 0, 0, 
               comment, m_magicNumber, expiration, arrowColor);
         }
         else
         {
            tiket = ::OrderSend(m_symbol, cmd, volume, price,
               slippage * m_pipsRate, stoplossValue, takeprofitValue, 
               comment, m_magicNumber, expiration, arrowColor);
         }
            
         if( tiket >= 0 )
         {
            m_positions.Add(tiket);
            
            if( m_isCountdown )
            {
               ModifyOrder(m_positions.Total() - 1, stoploss, takeprofit);
            }
            
            return m_positions.Total() - 1;
         }
         else
         {
            int errorCode = GetLastError();
            
            // リトライしても仕方がないエラーの時は終了してしまう。
            if( errorCode == ERR_INVALID_PRICE ||
               errorCode == ERR_INVALID_STOPS ||
               errorCode == ERR_INVALID_TRADE_VOLUME ||
               errorCode == ERR_NOT_ENOUGH_MONEY )
            {
               return -1;
            }
         }
      }
      Sleep(100);
   }
   Print("SendOrder Timeout");
   return -1;
}

//------------------------------------------------------------------
// 発注する
// Return   発注成功時インデックス それ以外-1
int CTradingWrapper::SendOrderPrice(
      int cmd,                      //売買種別  
      double volume,                //売買ロット
      double price,                 //価格(成行き時は現在値を自動設定)
      uint slippage,                //許容スリッピング(Pips単位)
      double stoploss = 0,          //ストップロス(価格)
      double takeprofit = 0,        //利確値(価格)
      string comment = NULL,        //コメント
      datetime expiration = 0,      //注文有効期限
      color arrowColor = clrNONE    //注文矢印の色
)
{
   if( !this.IsSafeParameter() ) return -1;
   if( m_positions.Total() >= m_maxPosition ) return -1 ;

   if( comment == NULL ) comment = m_defualtComment;

   // 計算用 負数フラグ
   int flag = cmd == OP_BUY || cmd == OP_BUYLIMIT || cmd == OP_BUYSTOP ? 1 : -1;
   
   uint start = GetTickCount();
   while(!IsStopped())
   {
      if( (GetTickCount() - start ) > m_timeout ) return -1;

      double bid = MarketInfo(m_symbol, MODE_BID);
      double ask = MarketInfo(m_symbol, MODE_ASK);
      
      // スプレットが大きすぎる場合は取引しない。
      if( NormalizeDouble(MathAbs(ask - bid), m_digit) > m_spreadFilter ) return -1;

      //pips値からストップロス値、利益確定値を取得する。   
      double stoplossValue = NormalizeDouble(stoploss, m_digit) ;
      double takeprofitValue = NormalizeDouble(takeprofit, m_digit) ;

      if( cmd == OP_SELL )
      {
         price = bid;
         if( stoplossValue > 0 && price > stoplossValue) return -1;
         if( takeprofitValue > 0 && price < takeprofitValue) return -1;
      }
      if( cmd == OP_BUY )
      {
         price = ask;
         if( stoplossValue > 0 && price < stoplossValue) return -1;
         if( takeprofitValue > 0 && price > takeprofitValue) return -1;
      }

      double closeTarget = cmd == OP_BUY || cmd == OP_BUYLIMIT || cmd == OP_BUYSTOP ? ask : bid; 


      if( IsTradeAllowed() )
      {
         if( AccountFreeMarginCheck(m_symbol, cmd, volume) < 0 )
         {
            int errorCode = GetLastError();
            Print("AccountFreeMarginCheck Error[",errorCode ,"]");
            return -1;
         }
         
         int tiket = -1;
         if( m_isCountdown )
         {
            tiket = ::OrderSend(m_symbol, cmd, volume, price,
               slippage * m_pipsRate, 0, 0, 
               comment, m_magicNumber, expiration, arrowColor);
         }
         else
         {
            tiket = ::OrderSend(m_symbol, cmd, volume, price,
               slippage * m_pipsRate, stoplossValue, takeprofitValue, 
               comment, m_magicNumber, expiration, arrowColor);
         }
            
         if( tiket >= 0 )
         {
            m_positions.Add(tiket);
            
            if( m_isCountdown )
            {
               ModifyOrderPrice(m_positions.Total() - 1, stoploss, takeprofit);
            }
            
            return m_positions.Total() - 1;
         }
         else
         {
            int errorCode = GetLastError();
            
            // リトライしても仕方がないエラーの時は終了してしまう。
            if( errorCode == ERR_INVALID_PRICE ||
               errorCode == ERR_INVALID_STOPS ||
               errorCode == ERR_INVALID_TRADE_VOLUME ||
               errorCode == ERR_NOT_ENOUGH_MONEY )
            {
               return -1;
            }
         }
      }
      Sleep(100);
   }
   Print("SendOrder Timeout");
   return -1;
}

//------------------------------------------------------------------
// 成行き決済を行う。
// Return   発注成功時ture それ以外false
bool CTradingWrapper::CloseOrder(
   int index,                    //決済するインデックス
   uint slippage,                //許容スリッピング
   color arrowColor = clrNONE    //注文矢印の色
)
{
   uint start = GetTickCount();
   while(!IsStopped())
   {
      if( (GetTickCount() - start ) > m_timeout ) return false;

      if( IsTradeAllowed() )
      {
         // オーダーが選択できない状態(すでに存在しない)場合は、リストから削除して終了する。
         int targetTicket = m_positions.At(index);
         if( !OrderSelect(targetTicket, SELECT_BY_TICKET) ) 
         {
            m_positions.Delete(index);
            return false;
         }
      
         if( OrderClose(OrderTicket(),OrderLots(), OrderClosePrice(), slippage * m_pipsRate, arrowColor) )
         {
            m_positions.Delete(index);
            return true;
         }
         else
         {
            int errorCode = GetLastError();

            // リトライしても仕方がないエラーの時は終了してしまう。
            if( errorCode == ERR_INVALID_TICKET)
            {
               m_positions.Delete(index);
               return false;
            }
         }
      }
      Sleep(100);
   }
   
   Print("CloseOrder Timeout");

   return false;
}

//------------------------------------------------------------------
// 全ポジションを成行き決済を行う。
// Return   発注成功時ture それ以外false
bool CTradingWrapper::CloseOrderAll(
   uint slippage,                // 許容スリッピング
   color arrowColor = clrNONE    // 注文矢印の色
)
{
   RefreshPositions();
   bool result = true;
   for( int i = m_positions.Total() - 1; i >= 0; i--)
   {
      result &= this.CloseOrder(i, slippage, arrowColor);
   }

   return result;
}

//------------------------------------------------------------------
// 注文を変更する。
// Return   発注成功時ture それ以外false
bool CTradingWrapper::ModifyOrder(
   int index,                 //決済するインデックス
   uint stoploss,             //ストップロス(Pips単位)
   uint takeprofit = 0,       //利確値(Pips単位)0は変更なし
   color arrowColor = clrNONE //注文矢印の色
)
{
   uint start = GetTickCount();
   while(!IsStopped())
   {
      if( (GetTickCount() - start ) > m_timeout ) return false;

      if( IsTradeAllowed() )
      {
         // オーダーが選択できない状態(すでに存在しない)場合は、リストから削除して終了する。
         int targetTicket = m_positions.At(index);
         if( !OrderSelect(targetTicket, SELECT_BY_TICKET) ) 
         {
            m_positions.Delete(index);
            return false;
         }
         
         // 実際のポジション以外は無視
         int cmd = OrderType();
         if( cmd != OP_BUY && cmd != OP_SELL )
         {
            return false;
         }
   
         double bid = MarketInfo(m_symbol, MODE_BID);
         double ask = MarketInfo(m_symbol, MODE_ASK);

         // 計算用 負数フラグ
         int flag = cmd == OP_BUY  ? 1 : -1;

         double closeTarget = cmd == OP_BUY ? ask : bid; 
         //pips値からストップロス値、利益確定値を取得する。   
         double stoplossValue = 0 ;
         double takeprofitValue = 0;
         double nowStop = OrderStopLoss();

         if( stoploss != 0 )
         {
            stoplossValue = NormalizeDouble(closeTarget - this.GetPipsValue(stoploss) * flag, m_digit );
         }
         else
         {
            // 0の場合変更しない。
            if( nowStop > 0 ) stoplossValue = nowStop;
         }
         
         if( nowStop > 0 ) 
         {
            // 注文ストップ値は下方方向への変更は許可しない。
            if((cmd == OP_BUY && stoplossValue <= OrderStopLoss() ) ||
               (cmd == OP_SELL && stoplossValue >= OrderStopLoss() ) ) stoplossValue = nowStop ;
         }
            
         if( takeprofit != 0)
         {
            closeTarget = OrderOpenPrice();
            takeprofitValue = NormalizeDouble(closeTarget + this.GetPipsValue(takeprofit) * flag, m_digit );
         }
         else
         {
            // 0の場合変更しない。
            double profit = OrderTakeProfit();
            if( stoplossValue > 0 && profit > 0 ) takeprofitValue = profit;
         }
         
         // 変更がない場合はコマンドを実行しない。
         if( stoplossValue == 0 && takeprofitValue == 0 ) return true;

         if( OrderModify(targetTicket, OrderOpenPrice(), stoplossValue, takeprofitValue, 0, arrowColor ))
         {
            return true;
         }
         else
         {
            int errorCode = GetLastError();
            
            // 変更なしだった
            if( errorCode == ERR_NO_RESULT ) return true;
            
            // リトライしても仕方がないエラーの時は終了してしまう。
            if( errorCode == ERR_INVALID_PRICE ||
               errorCode == ERR_INVALID_STOPS ||
               errorCode == ERR_INVALID_TRADE_VOLUME ||
               errorCode == ERR_NOT_ENOUGH_MONEY)
            {
               return false;
            }
         }
      }
   }
   Print("ModifyOrder Timeout");
   return false;
}

//------------------------------------------------------------------
// 注文を変更する。
// Return   発注成功時ture それ以外false
bool CTradingWrapper::ModifyOrderPrice(
   int index,                 //決済するインデックス
   double stoploss,           //ストップロス
   double takeprofit = 0,     //利確値(Pips単位)0は変更なし
   color arrowColor = clrNONE //注文矢印の色
)
{
   uint start = GetTickCount();
   while(!IsStopped())
   {
      if( (GetTickCount() - start ) > m_timeout ) return false;

      if( IsTradeAllowed() )
      {
         // オーダーが選択できない状態(すでに存在しない)場合は、リストから削除して終了する。
         int targetTicket = m_positions.At(index);
         if( !OrderSelect(targetTicket, SELECT_BY_TICKET) ) 
         {
            m_positions.Delete(index);
            return false;
         }
         
         // 実際のポジション以外は無視
         int cmd = OrderType();
         if( cmd != OP_BUY && cmd != OP_SELL )
         {
            return false;
         }
   
         double bid = MarketInfo(m_symbol, MODE_BID);
         double ask = MarketInfo(m_symbol, MODE_ASK);

         // 計算用 負数フラグ
         int flag = cmd == OP_BUY  ? 1 : -1;

         double closeTarget = cmd == OP_BUY ? ask : bid; 
         //pips値からストップロス値、利益確定値を取得する。   
         double stoplossValue = NormalizeDouble(stoploss, m_digit );
         double takeprofitValue = NormalizeDouble(takeprofit, m_digit) ;
         double nowStop = OrderStopLoss();

         if( stoploss == 0 && nowStop > 0) stoplossValue = nowStop;
         if( nowStop > 0 ) 
         {
            // 注文ストップ値は下方方向への変更は許可しない。
            if((cmd == OP_BUY && stoplossValue <= nowStop ) ||
               (cmd == OP_SELL && stoplossValue >= nowStop ) ) stoplossValue = nowStop ;
         }
         double nowTakeProfit = OrderTakeProfit();
         if( takeprofit == 0 && nowTakeProfit > 0 ) takeprofitValue = nowTakeProfit; 
         
         if( cmd == OP_SELL )
         {
            if( stoplossValue > 0 && closeTarget > stoplossValue) return false;
            if( takeprofitValue > 0 && closeTarget < takeprofitValue) return false;
         }
         if( cmd == OP_BUY )
         {
            if( stoplossValue > 0 && closeTarget < stoplossValue) return false;
            if( takeprofitValue > 0 && closeTarget > takeprofitValue) return false;
         }
         
         // 変更がない場合はコマンドを実行しない。
         if( stoplossValue == nowStop && takeprofitValue == nowTakeProfit ) return true;

         if( OrderModify(targetTicket, OrderOpenPrice(), stoplossValue, takeprofitValue, 0, arrowColor ))
         {
            return true;
         }
         else
         {
            int errorCode = GetLastError();
           
            // 変更なしだった
            if( errorCode == ERR_NO_RESULT ) return true;
            
            // リトライしても仕方がないエラーの時は終了してしまう。
            if( errorCode == ERR_INVALID_PRICE ||
               errorCode == ERR_INVALID_STOPS ||
               errorCode == ERR_INVALID_TRADE_VOLUME ||
               errorCode == ERR_NOT_ENOUGH_MONEY)
            {
               return false;
            }
         }
      }
   }
   Print("ModifyOrder Timeout");
   return false;
}

//------------------------------------------------------------------
// すべての注文を変更する。
bool CTradingWrapper::ModifyOrderAll(
   uint stoploss,             //ストップロス(Pips単位)
   uint takeprofit = 0,       //利確値(Pips単位)
   color arrowColor = clrNONE //注文矢印の色
)
{
   RefreshPositions();
   bool result = true;
   for( int i = m_positions.Total() - 1; i >= 0; i--)
   {
      result &= this.ModifyOrder(i, stoploss, takeprofit, arrowColor);
   }

   return result;
}

//------------------------------------------------------------------
// 設定パラメータが安全かどうか
// Return 安全ture それ以外false
bool CTradingWrapper::IsSafeParameter()
{
   if( m_symbol == NULL ) return false;
   if( m_maxPosition == 0 ) return false; 
   return true;
}

//------------------------------------------------------------------
// ポジションリストを更新する。
void CTradingWrapper::RefreshPositions()
{
   m_positions.Clear();
   for( int i = 0 ; i < OrdersTotal(); i++)
   {
      if( OrderSelect(i, SELECT_BY_POS) )
      {
         if( OrderMagicNumber() == m_magicNumber && OrderSymbol() == m_symbol)
         {
            m_positions.Add(OrderTicket());
         }
      }
   }
}

//------------------------------------------------------------------
// 指定番号のチケットを取得する。
// Return   チケット番号 取得失敗時-1
int CTradingWrapper::GetTicket(
      int index         //インデックス
   )
{
   if(index < 0 || index >= m_positions.Total() ) return -1;
   return m_positions.At(index);
}

//------------------------------------------------------------------
// 指定番号の売買種別 を取得する。
// Return   売買種別 
int CTradingWrapper::GetOrderType(
      int index         //インデックス
   )
{
   int ticket = GetTicket(index);
   if( ticket < 0 ) return OP_NONE;
   if( OrderSelect(ticket, SELECT_BY_TICKET) ) return OrderType();
   
   return OP_NONE;
}

//------------------------------------------------------------------
// 指定番号の現在利益を取得する。
// Return   現在利益(Pips)
double CTradingWrapper::GetOrderProfit(
      int index         //インデックス
   )
{
   int ticket = GetTicket(index);
   if( ticket < 0 ) return 0;
   if( OrderSelect(ticket, SELECT_BY_TICKET) )
   {
      if( OrderType() == OP_BUY )
      {
         return (OrderClosePrice() - OrderOpenPrice()) / GetPipsValue();
      }
      else      
      {
         return (OrderOpenPrice() - OrderClosePrice()) / GetPipsValue();
      }
   }
   
   return 0;
}

//------------------------------------------------------------------
// 指定番号の現在リミット値を取得する。
// Return   リミット値
double CTradingWrapper::GetOrderLimit(
   int index         //インデックス
)
{
   int ticket = GetTicket(index);
   if( ticket < 0 ) return 0;
   if( OrderSelect(ticket, SELECT_BY_TICKET) )
   {
      return OrderStopLoss();
   }
   
   return 0;

}

//------------------------------------------------------------------
// 指定番号の現在リミット値を取得する。
// Return   リミット値
double CTradingWrapper::GetOrderLimitPips(
   int index         //インデックス
)
{
   int ticket = GetTicket(index);
   if( ticket < 0 ) return 0;
   if( OrderSelect(ticket, SELECT_BY_TICKET) )
   {
      if( OrderType() == OP_BUY )
      {
         return (OrderClosePrice() - OrderStopLoss()) / GetPipsValue();
      }
      else      
      {
         return (OrderStopLoss() - OrderClosePrice()) / GetPipsValue();
      }
   }
   
   return 0;
}


//------------------------------------------------------------------
// 指定番号の現在値を取得する。
// Return   現在価格
double CTradingWrapper::GetOrderClose(
   int index         //インデックス
)
{
   int ticket = GetTicket(index);
   if( ticket < 0 ) return 0;
   if( OrderSelect(ticket, SELECT_BY_TICKET) )
   {
      return OrderClosePrice();
   }
  
   return 0;
}

//------------------------------------------------------------------
// 指定番号のオープン価格を取得する。。
// Return   オープン値
double CTradingWrapper::GetOrderOpen(
   int index         //インデックス
)
{
   int ticket = GetTicket(index);
   if( ticket < 0 ) return 0;
   if( OrderSelect(ticket, SELECT_BY_TICKET) )
   {
      return OrderOpenPrice();
   }
   
   return 0;
}



//------------------------------------------------------------------
// 指定番号の取引開始時間 を取得する。
// Return   取引開始時間 
datetime CTradingWrapper::GetOrderOpenTime(
   int index         //インデックス
)
{
   int ticket = GetTicket(index);
   if( ticket < 0 ) return 0;
   if( OrderSelect(ticket, SELECT_BY_TICKET) )
   {
      return OrderOpenTime();
   }
   return 0;
}

そしてこの注文クラスですが、実は必要なファイルを公開していなかったためコンパイルが通らない状況でした!
公開し始めた頃からずっとこの状況であることに今気付きました・・すみません。

不足していたのは下記のインクルードファイルです。
#include <Custom/TradingDefines.mqh>
注文クラスで使用する定数値の定義ファイルで、このファイルがInclude/Customフォルダの下にTradingDefines.mqhというファイル名で保存されている必要があります。

ファイルの内容は以下の通りです。
//+------------------------------------------------------------------+
//|                                               TradingDefines.mqh |
//|                                         Copyright 2015,  Daisuke |
//|                                 http://mt4program.blogspot.jp/ |
//+------------------------------------------------------------------+
#property copyright "Copyright 2015,  Daisuke"
#property link      "http://mt4program.blogspot.jp/"
#property strict

//+------------------------------------------------------------------+
//| defines                                                          |
//+------------------------------------------------------------------+

//シグナルなし
#define OP_NONE (-1)

//全決済
#define OP_CLOSEALL (-2)

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

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

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

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

2016年4月18日月曜日

[雑記]シンプル イズ ベスト!?ゴールデンクロスとデッドクロスで自動売買

先日、FX初心者にこんな事を聞かれました。
「短期移動平均線と長期移動平均線のクロスで単純に売買すれば意外と勝てないんですか?」

答えはまぁ言うまでもないんですが・・

誰もが知っている超有名なシグナルであるゴールデンクロスとデッドクロス。
有名なのは価値があるからであり、
価値があるからこそ、シンプル イズ ベスト!?

なんて事は全く思っていませんが、実際にゴールデンクロスとデッドクロスをシグナルに自動売買したらどうなるのか、(思い知らせるためにも)やってみました。

使用したのは単純移動平均(SMA)の25日線と75日線で、
シンプルに1ポジションのみ、両建てなしです。

まずはUSDJPYの結果から。

通貨ペアUSDJPY (USD/JPY)
期間日足(D1) 2001.01.01 00:00 - 2015.12.31 00:00 (2001.01.01 - 2015.12.31)
モデルコントロールポイント(おおまかな方法。結果はあまり信頼性はない)
パラメーターMagicNumber=37858261; SpreadFilter=2; MaxPosition=1; Lot=0.02; Slippage=2; StopLoss=0; TakeProfit=0; ShortPeriod=25; LongPeriod=75;
テストバー数4418モデルティック数296949モデリング品質n/a
不整合チャートエラー0
初期証拠金10000.00スプレッド現在値 (4)
純益138.09総利益2082.32総損失-1944.23
プロフィットファクタ1.07期待利得2.09
絶対ドローダウン453.58最大ドローダウン706.25 (6.89%)相対ドローダウン6.89% (706.25)
総取引数66売りポジション(勝率%)33 (33.33%)買いポジション(勝率%)33 (33.33%)
勝率(%)22 (33.33%)負率 (%)44 (66.67%)
最大勝トレード367.12敗トレード-130.18
平均勝トレード94.65敗トレード-44.19
最大連勝(金額)4 (342.35)連敗(金額)6 (-166.94)
最大連勝(トレード数)463.98 (3)連敗(トレード数)-272.82 (3)
平均連勝1連敗3

まぁこうなりますよね。
むしろもっとダメダメになるかと思いましたが、意外にも最終的にはわずかですがプラスになっていて驚きました。
とはいえ、これで自動売買できるとはとても言えません。

では次にEURUSDの結果です。

通貨ペアEURUSD (EUR/USD)
期間日足(D1) 2001.01.01 00:00 - 2015.12.31 00:00 (2001.01.01 - 2015.12.31)
モデルコントロールポイント(おおまかな方法。結果はあまり信頼性はない)
パラメーターMagicNumber=37858261; SpreadFilter=2; MaxPosition=1; Lot=0.02; Slippage=2; StopLoss=0; TakeProfit=0; ShortPeriod=25; LongPeriod=75;
テストバー数4419モデルティック数296740モデリング品質n/a
不整合チャートエラー0
初期証拠金10000.00スプレッド現在値 (5)
純益1269.62総利益3176.72総損失-1907.10
プロフィットファクタ1.67期待利得20.81
絶対ドローダウン4.50最大ドローダウン761.52 (6.83%)相対ドローダウン6.83% (761.52)
総取引数61売りポジション(勝率%)31 (35.48%)買いポジション(勝率%)30 (53.33%)
勝率(%)27 (44.26%)負率 (%)34 (55.74%)
最大勝トレード466.10敗トレード-239.90
平均勝トレード117.66敗トレード-56.09
最大連勝(金額)4 (348.40)連敗(金額)4 (-101.08)
最大連勝(トレード数)494.86 (3)連敗(トレード数)-311.88 (2)
平均連勝2連敗2


こちらは意外にも右肩上がりっぽくなっています。
しかし取引回数があまりに少ない。
15年分のバックテストにしましたが、取引回数は15年で61回!1年に4回程度です。
これでは全くもって信頼できません。

とはいえ、EURUSDに限ってではありますが、トレンドを見る分にはそこそこ信頼できるのかもしれません。
短期の取引をする際にも、方向性に迷ったらこれをひとつの参考にするのもありかも知れませんね。

余談ですが、移動平均に関する記事を過去にいくつか書いています。
こちらをぜひ参考にしてみてください。


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

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

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

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