2016年1月15日金曜日

[MT4インジケータ]TickEMA EMAの反応を取引の活発さによって変動する。


・図1 EMA(21)赤 と TickEMA(緑)

MQL超入門でTick更新回数をサブチャートに出すと何か見えないか?ということで作ってみましたが、応用してみたいと思います。

MQL超入門のTick更新回数インジケータを作成するシリーズ
http://mt4program.blogspot.com/2016/01/mql-009.html
http://mt4program.blogspot.com/2016/01/mql-010-tick.html
http://mt4program.blogspot.jp/2016/01/mql-011.html
http://mt4program.blogspot.com/2016/01/mql-012.html

移動平均の計算において、ある特定時間ごとの値から算出します。
たとえば、EMAですと次の式です。

EMA[i]=Price * α + (1-α) * EMA[i-1]

ここでのPriceはEMA算出元となる価格です。たとえばクローズ値です。

EMAはとても優秀だと思いますが、たとえばTickの更新回数が1000回の時間と100回の時間では重みが違うのではないでしょうか?上記計算式ではその部分は考慮されていないため全く同じ影響力があります。
そこで、MQL超入門で作成したTickVolumeインジケータのコードを利用して、TickVolumeを考慮して重みが変化するEMAを作ってみました。計算式は下記の通りです。

α=基準α*Tick更新回数/Tick更新回数の平均値
EMA[i]=Price * α + (1-α) * EMA[i-1]

※ただしαは0~1までの間とする。

これを適用したのが図1のチャートです。赤がMT4に標準でついているEMA(21)、緑がTickEMA(21)です。
図1では綺麗に出た場合の例ですが、活発さを伴って上昇していく場合は緑のラインが赤を追い越します。活発さが無い場合は、逆に赤のラインが追い越します。

ただし活発さを伴わずだらだらと一方方向に移動するときもあるため、信頼性に欠けるというだけでクロスしたから取引のシグナルとは限らないように思われます。
ちなみにインジケータに[加速方向のみの場合True]というパラメータがありますが、これをTrueにすると活発さを伴って価格が移動した場合にのみα値が変化するようになります。この場合次のようになります。

・図2 EMA(21)赤 と TickEMA(緑) 加速方向のみTrue時


さて、シグナルに使えるかを検証するためバックテストで試してみましょう。バックデータはAlpariです。

EURUSD1Hベースにて最大48時間ポジション保持、EMA(21)とTickEMA(21)のラインクロスで単純売買の結果です。損切・利確なしです。確定足でのラインクロス時に反対方向のポジションは全決済しています。

まずは、加速方向のみはTrueを設定して確認してみましょう。

・図3 EURUSD1H 2011-2015 加速方向のみTrue

まぁマイナスに沈みますね。ただ、PF0.98と移動平均のラインクロス売買にしてはかなりの好成績とも言えます。

ちなみに、加速方向のみをFalseにした場合はこちら

・図4 EURUSD1H 2011-2015 加速方向のみFalse

一昨年までは、ほぼ横ばい、去年は大きくマイナスといった感じです。
こちらはPF0.97で同じくラインクロスとしてはかなりの好成績のように思えます。

お互い少し工夫をするといろいろできそうな雰囲気です。例えば、図3のEAに4時間足でのEMAとTickEMAの位置も判断材料として加えてみましょう。

・図5 図3のEAに4時間足も見るように変更
プラスになりました。
やはり、少し工夫すると使えそうな予感がします。

EAのフィルタとして取引時間(例えば深夜帯はボラが低いから取引しない)等のフィルタを使用するより、活発さというデータがせっかくMT4で公開されていますので、是非有効活用していきたいです。

あ、蛇足ですが、本記事がMT4開発日記記念の200記事目になりました。皆様ご愛読ありがとうございます^^
・・・・・とはいっても、現在は100PV/1Dを割ってまして初心者ブロガーの域を全く超えていません。内容がマニアックすぎるのかなぁ?^^;;;

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

ソースコードはこちらから

2016年1月14日木曜日

[MQL超入門] その012 本格的にインジケータを作ってみよう。その4 平滑化をかけてみる。

さて、Tick更新回数インジケータ作成の流れを、考え方も含めて説明してきましたが、今回が最後となります。

過去記事はこちらから
http://mt4program.blogspot.com/2016/01/mql-009.html
http://mt4program.blogspot.com/2016/01/mql-010-tick.html
http://mt4program.blogspot.jp/2016/01/mql-011.html

こちらも効果から見ていきましょう。

・図12.01 Tick更新回数 平滑化有り無しの効果

上が平滑化あり、下が平滑化なしです。
どうですか?効果は一目かと思います。

平滑化ですが、私は線形加重移動平均の4期間を主に使用します。遅延量が1本とわかりやすいためです。このあたりのお話しは過去のシリーズをご覧ください。

移動平均の遅延利用シリーズ
http://mt4program.blogspot.jp/2015/10/blog-post_33.html
http://mt4program.blogspot.jp/2015/10/mama_8.html

移動平均は遅れている
http://mt4program.blogspot.jp/2015/10/blog-post_83.html

ここでは、線形加重移動平均ってなに?というところは除外させていただきます。

ソースコードですが、もうここまでお読みいただいた皆様でしたら、読み解くことが可能かと思います。解説は特にしませんので、ぜひ皆さま何をやっているのか見てみてください。
//+------------------------------------------------------------------+
//|                                                   TickVolume.mq4 |
//|                                         Copyright 2016, Daisuke. |
//|                                   http://mt4program.blogspot.jp/ |
//+------------------------------------------------------------------+
#property copyright "Copyright 2016, Daisuke"
#property link      "http://mt4program.blogspot.jp/"
#property version   "1.00"
#property strict
#property indicator_separate_window

//インジケータで使用するバッファの数を指定する。
#property indicator_buffers 2

//描画する線の情報を指定する。
#property indicator_label1  "TickVolume"
#property indicator_type1   DRAW_LINE
#property indicator_color1  clrAqua
#property indicator_style1  STYLE_SOLID
#property indicator_width1  1

#property indicator_label2  "TickAverage"
#property indicator_type2   DRAW_LINE
#property indicator_color2  clrIndianRed
#property indicator_style2  STYLE_SOLID
#property indicator_width2  1

input int SmoothPeriod = 4;   // ボリューム値平滑化期間
input int AveragePeriod = 100; //単純移動平均期間

// 表示バッファ
double tickVolume[];
double tickAverage[];

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   SetIndexBuffer(0,tickVolume);
   SetIndexBuffer(1,tickAverage);
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| 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[])
  {
//---
   for( int i = rates_total - prev_calculated - 1; i >= 0; i-- )
   {
      // 線形加重移動平均にて平滑化を行う。
      int count = 0 ;
      double smoothVolume = 0;
      for( int j = 0; j < SmoothPeriod && (i + j) < rates_total; j++ )
      {
         int weight = SmoothPeriod - j;
         count += weight;
         smoothVolume += (double)tick_volume[i + j] * weight;
      }
      if( count > 0 )
      {
         tickVolume[i] = smoothVolume / count;
      }
      
      // 単純平均を求める。
      double average = 0 ;
      count = 0 ;

      for( int j = 0; j < AveragePeriod && (i + j) < rates_total; j++ )
      {
         count++;
         average += tickVolume[i + j];
      }
      if( count > 0 )
      {
         average = average / count;
      }
      tickAverage[i] = average;
   }
//--- return value of prev_calculated for next call
   return(rates_total - 1);
  }
//+------------------------------------------------------------------+

・・・・と思ったら、前回ふくめて+=演算子の説明していませんでした。
[a += 3]は[a = a + 3]の省略形です。同じように[-=][*=][/=]演算子があります。その意味では、[average = average / count;]は[average /= count;]と書き換え可能ですね。コードに統一性がないって言われそう^^;;;;すみません。

次回は、途中説明をかっ飛ばした関数とOnCalculateを中心に解説したいと思います。

次の回へ


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

2016年1月13日水曜日

[MQL超入門] その011 本格的にインジケータを作ってみよう。その3 移動平均を追加してみよう。

昨日の続きでです。

[MQL超入門] その010 本格的にインジケータを作ってみよう。その2 TICKの更新回数を描画する。
http://mt4program.blogspot.jp/2016/01/mql-010-tick.html


今日もいきなり結果から行きたいと思います。

・図011.01 TICK更新回数に単純移動平均を追加する。

赤い線が100本平均、青い線が現在値です。
TICK値は15分足が面白いと考えています。眺めていると何か使えそうな指標が見えてくるかもしれません。基本的には更新回数のピークアウト時に方向転換が発生する可能性が高いですし、平均以下のTICKの場合、あるきまった方向にだらだらと移動する習性があるように見受けられます。これは参加者が少ない場合は方向性に逆らいたくないという心境など心理面が解析としてあらわれいるのではないでしょうか?

平均値を入れることで一挙に何かが見えてくるような感じがしてきませんか?

さて、コードを見てみましょう。

//+------------------------------------------------------------------+
//|                                                   TickVolume.mq4 |
//|                                         Copyright 2016, Daisuke. |
//|                                   http://mt4program.blogspot.jp/ |
//+------------------------------------------------------------------+
#property copyright "Copyright 2016, Daisuke"
#property link      "http://mt4program.blogspot.jp/"
#property version   "1.00"
#property strict
#property indicator_separate_window

//インジケータで使用するバッファの数を指定する。
#property indicator_buffers 2

//描画する線の情報を指定する。
#property indicator_label1  "TickVolume"
#property indicator_type1   DRAW_LINE
#property indicator_color1  clrAqua
#property indicator_style1  STYLE_SOLID
#property indicator_width1  1

#property indicator_label2  "TickAverage"
#property indicator_type2   DRAW_LINE
#property indicator_color2  clrIndianRed
#property indicator_style2  STYLE_SOLID
#property indicator_width2  1

input int AveragePeriod = 100; //移動平均期間

// 表示バッファ
double tickVolume[];
double tickAverage[];

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   SetIndexBuffer(0,tickVolume);
   SetIndexBuffer(1,tickAverage);
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| 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[])
  {
//---
   for( int i = rates_total - prev_calculated - 1; i >= 0; i-- )
   {
      tickVolume[i] = (double)tick_volume[i];
      
      // 単純平均を求める。
      double average = 0 ;
      int count = 0 ;

      for( int j = 0; j < AveragePeriod && (i + j) < rates_total; j++ )
      {
         count++;
         average += tickVolume[i + j];
      }
      if( count > 0 )
      {
         average = average / count;
      }
      tickAverage[i] = average;
   }
//--- return value of prev_calculated for next call
   return(rates_total - 1);
  }
//+------------------------------------------------------------------+

全く新しい記述として追加されているのは、次の一文です。
input int AveragePeriod = 100; //移動平均期間
これは、インジケータの入力パラメータを指定しています。
移動平均期間というint型の入力パラメータを指定しています。

なお、input構文は、最後にコメントをつけると入力画面にてコメントが表示できます。
詳しくはこちらをご覧ください。
[MT4プログラミング]小ネタ 入力パラメータの説明を置き換える。
http://mt4program.blogspot.jp/2015/11/mt4_10.html

ここ以外の構文は、その10までで説明した内容となります。現在値と平均値が同じ色だと見えにくいため線の色を変えています。
移動平均を求める処理は、足して割るという単純なものです。

さて、これで基本完成なのですが、もし私が使うインジケータでしたら、あと一工夫します。
TICK更新回数の現在値ですが、細かい変動が多く少し平滑化効果を入れたい気がしませんか?そこで、次回では、現在値に平滑化効果を入れてみたいと思います。

次の回へ


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

2016年1月12日火曜日

[MQL超入門] その010 本格的にインジケータを作ってみよう。その2 TICKの更新回数を描画する。

前回の続きです。

[MQL超入門] その009 本格的にインジケータを作ってみよう。その1 セパレート型インジケータ作成
http://mt4program.blogspot.com/2016/01/mql-009.html

前回、チャートとは別に表示するセパレート型インジケータの基本形ができました。
そこに実際の処理を埋め込みしていきたいと思います。

今回はすでに処理を組み入れたプログラムを見ながら解説します。ですので、先に結果から。このようなチャートが描画されます。なんとなく、価格が大きく動いているときに飛び出ている感じですよね。

・図010.01 価格の更新回数を描画する。


//+------------------------------------------------------------------+
//|                                                   TickVolume.mq4 |
//|                                         Copyright 2016, Daisuke. |
//|                                   http://mt4program.blogspot.jp/ |
//+------------------------------------------------------------------+
#property copyright "Copyright 2016, Daisuke"
#property link      "http://mt4program.blogspot.jp/"
#property version   "1.00"
#property strict
#property indicator_separate_window

//インジケータで使用するバッファの数を指定する。
#property indicator_buffers 1

//描画する線の情報を指定する。
#property indicator_label1  "TickVolume"
#property indicator_type1   DRAW_LINE
#property indicator_color1  clrAqua
#property indicator_style1  STYLE_SOLID
#property indicator_width1  1

// 表示バッファ
double tickVolume[];

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   SetIndexBuffer(0,tickVolume);
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| 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[])
  {
//---
   for( int i = rates_total - prev_calculated - 1; i >= 0; i-- )
   {
      tickVolume[i] = (double)tick_volume[i];
   }
//--- return value of prev_calculated for next call
   return(rates_total - 1);
  }
//+------------------------------------------------------------------+

赤字の部分が、今回追加した部分です。一つずつ説明したいと思います。
#property indicator_buffers 1
まず、この一文です。これは、インジケータ内で使用するバッファと呼ばれる物の数を指定しています。ここでは、インジケータ内で描画したい線の数を指定します。
(※正確ではありませんが、超入門ということで、まずは、線の数を指定するということで理解していただければと思います。)
#property indicator_label1  "TickVolume"
#property indicator_type1   DRAW_LINE
#property indicator_color1  clrAqua
#property indicator_style1  STYLE_SOLID
#property indicator_width1  1
ここは、インジケータ内で描画する線の形式を指定しています。

indicator_label1の1の部分は1番目の・・という意味を示しています。もし線が二つ以上ある場合は、ここが2,3...と番号を指定した分だけ増えた内容を定義します。それぞれの意味は次の通りです。
[indicator_label?]は、線の名前を指定します。自由な文字列を入力可能です。
[indicator_type?]は、線の種別を指定します。DRAW_LINEは直線という意味です。
[indicator_color?]は、線の色を指定ます。clrAquaは水色です。
[indicator_style?]は、線の見た目を指定します。STYLE_SOLIDは実線という意味です。
[indicator_width?]は、線の太さを指定します。整数値を指定可能です。

どのような値が指定可能かは、別の機会にということで、次に移ります。
double tickVolume[];
ここで、double型の配列を定義します。このように{}で囲われていない場所に書かれた変数をグローバル変数と呼びます。
インジケータでは、最低線の数分だけ、このdoubleで定義したグローバル変数を定義する必要があります。それぞれ違う名前を付ける必要があります。
ここでは、Tickの更新回数を表示する変数としてtickVolumeという名前のdouble配列を定義しました。
   SetIndexBuffer(0,tickVolume);
OnInit()と書かれた{}内に記載されている上記の文ですが、これは、「このdoubleの配列をチャートの描画に使いますよ」という宣言になります。先ほど定義した[tickVolume]を指定します。初めに0という数字も一緒に記載されていますが、「1番目に描画する線として指定します。」という意味になります。ここで0と指定したものが、[indicator_type1]と指定したものと一致します。
OnInit()は、インジケータが起動する最初に呼び出される処理を記載する場所です。

少々面倒な話になるのですが、MQLの元となっているC言語では配列の一番最初の要素は0と指定します。MQLもこのルールに従ってプログラム内では1番目の要素のことを0と指定します。
   for( int i = rates_total - prev_calculated - 1; i >= 0; i-- )
   {
      tickVolume[i] = (double)tick_volume[i];
   }
さて、次の部分は、実際の処理です。[OnCalculate]という{}の中に含まれています。[OnCalculate]はTickの更新があるたび呼び出される処理です。ここに具体的にチャートを描画する処理を記述していくことになります。

for文の内容を、もう少し詳しく、解説します。
まず[rates_total]という変数には、バーの本数が入っています。[prev_calculated]という変数には、すでに処理済みのバー本数が入っています。(※こちらも、この説明ではあまり正確ではありませんが、超入門ということでお許しを・・・・。)
つまり[rates_total - prev_calculated]は未処理のバー本数を示しています。
先ほど説明した通り、C言語の流儀に従って、配列の指定は0から始まりますので、-1として数字調整をしています。例えば、全部でバーの数が10本あるとすると、配列で指定する数字は0~9までとなります。そのため最大値-1を初期値としています。

あと、今回[i--]という文が出てきます。これは[i=i-1]と同じ意味です。省略形です。

もう一点、インジケータのデフォルトでは、配列の0番目の要素が、チャート右端のデータ(最新のデータ)になります。このforループでは、過去のデータから先に値を生成するために、大きい数字から小さい数字へループさせながら計算しています。

forの中ではグローバル変数として定義した[tickVolume]のi番目に[tick_volume]のi番目の値を入れています。[tick_volume]はMT4が自動的にバーごとの更新回数を入れてくれる変数としてとりあえず覚えておきましょう。
   return(rates_total - 1);
[return]を話そうと思うと、今まで避けていた関数という考え方を学習する必要が出てきます。ここではとりあえず、このように書くということだけで、次に進みましょう。

さて、実行してみましょう!図010.01のようなチャートが表示された成功です。

うーん。これだけだと、基準値が無いため活発なのかどうか判別がつきませんよね。そこで、基準値として平均値を表示するように変更したいと思います。
続きはまた明日!

次の回へ


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