基礎から学ぶシステムトレード
シストレブログ人気ランキング  

シストレ徹底攻略シストレマスターへの道ワールド・トレーディング・エッジ基礎から学ぶシステムトレードシストレニュースシストレツールシストレナビTOPへ

 

著書のご紹介

2010年08月17日(火)

MQL5でカスタム指標プログラム(2) [MetaTrader5]

OnCalculate()関数の引数の意味がわかったところで、今回は、簡単なカスタム指標プログラムを作ってみましょう。

といっても終値をラインで結んでいくという超簡単なものです。(実用性はありません^^;)

MQL5のプログラムは次のように書けます。


#property indicator_chart_window
#property indicator_buffers 1
#property indicator_plots 1
//--- plot Close
#property indicator_label1 "Close"
#property indicator_type1 DRAW_LINE
#property indicator_color1 Red
#property indicator_style1 STYLE_SOLID
#property indicator_width1 2
//--- indicator buffers
double BufClose[];

int OnInit()
{
SetIndexBuffer(0, BufClose, INDICATOR_DATA);
return(0);
}

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=0; i<rates_total; i++)
{
BufClose[i] = Close[i];
}

return(rates_total);
}

順番に説明していきます。

#property indicator_chart_window

これは、指標をチャートウィンドウに表示するための指定ですね。MQL4と同じです。
#property indicator_buffers 1
#property indicator_plots 1

これは、指標バッファの数を指定する命令です。MQL4では、indicator_buffersだけでしたが、MQL5では、indicator_plotsで、実際に表示させる指標の数も指定するようになりました。
#property indicator_label1  "Close"
#property indicator_type1 DRAW_LINE
#property indicator_color1 Red
#property indicator_style1 STYLE_SOLID
#property indicator_width1 2

では、指標の表示スタイルを設定しています。indicator_color1indicator_style1indicator_width1などはMQL4と同じですが、MQL5では、indicator_label1indicator_type1で指標のラベルや指標の種類も指定できるようになりました。
double BufClose[]; 

これが指標バッファ用の配列で、MQL4と同じく外部変数として宣言します。

次にOnInit()関数で、
SetIndexBuffer(0, BufClose, INDICATOR_DATA); 

のように、BufClose[]という配列を指標バッファに割り当てます。この仕組みもMQL4と同じですが、この関数の引数がひとつ増えて、最後にINDICATOR_DATAを指定するようになりました。

MQL5では、指標バッファに格納されるのが指標の値だけでなく、指標の色も格納できるようになったので、どちらを格納するかを区別するための指定です。

最後にOnCalculate()中に、指標バッファに割り当てられた配列BufClose[]の各要素に、表示させたい指標の値を代入すれば完成です。

簡単には、チャート上のすべてのバーに対応する指標値を代入すればよいので、
for(int i=0; i<rates_total; i++)
{
BufClose[i] = Close[i];
}

と書けます。つまり、BufClose[0]からBufClose[rates_total-1]までにそれぞれのバーの終値を代入したことになります。

但し、前回説明したように、BufClose[rates_total-1]が最新のバーの指標値だということに注意してください。

このプログラムをコンパイルして、適当なチャートにアタッチすると、下のチャートのように終値を結んだ指標が表示されます。

画像(450x337)・拡大画像(800x600)

ただ、このままでは、OnCalculate()を呼び出すたびにチャート上のすべての指標値を書き直すことになるので、2回目以降は最新のバーのみ書き直すようにすると無駄な処理を減らすことができます。

そのために、次のようにプログラムを追加します。

int limit = prev_calculated;
if(prev_calculated > 0) limit--;

for(int i=limit; i<rates_total; i++)
{
BufClose[i] = Close[i];
}

指標値を代入するインデックスを0からではなく、limitから始めます。limit には、prev_calculatedを代入しておきます。

prev_calculated は、チャートにアタッチした直後は、0となっており、その後は前回計算したバーの総数が代入されます。

なので、prev_calculatedが0の場合は、limitも0のままで、0からrates_total-1までのバーの指標を表示します。

2回目以降は、prev_calculatedの値が0より大きいので limitを1だけ減らしておきます。これで、limit=rates_total-1 となるので、常に最新のバーの指標値を更新することができます。

このあたりのプログラムは色々な書き方があり、MQL4と同様、初心者向けに説明するのは難しいところです。

説明の仕方を考えながら、次回に続きます・・・

Posted at 13時13分 パーマリンク


2010年08月09日(月)

MQL5でカスタム指標プログラム(1) [MetaTrader5]

今回は、MQL5でカスタム指標プログラムを作ってみましょう。と言っても、色々と準備する必要があるので、何回かに分けて説明します。

まずは、メタエディターのFileメニューのNewから「Custom Indicator」を選んで、新規プログラムを作成してみましょう。

#property indicator_chart_window
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
//--- indicator buffers mapping
//---
return(0);
}
//+------------------------------------------------------------------+
//| 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[])
{
//---
//--- return value of prev_calculated for next call
return(rates_total);
}
//+------------------------------------------------------------------+

このプログラム中では、OnInit()OnCalculate()という2つの関数が定義されています。どちらもMQL4にはなかったものです。

OnInit()という関数は、MQL4におけるinit()と同じ働きをするもので、プログラムをチャートにアタッチして最初に実行される関数です。

OnCalculate()は、MQL4におけるstart()と同じ働きをするもので、価格が変化して指標計算が必要になったときに実行される関数です。

ただ、OnCalculate()関数には引数がたくさんあってちょっと驚くかもしれません。

引数の名前から判断すると、time[]、open[]、high[]、low[]、close[]、volume[] は、MQL4におけるTime[]、Open[]、High[]、Low[]、Close[]、Volume[]
と同じものだと推測できます。

つまり、MQL5のカスタム指標プログラムでは、チャート上のバーの4本値は、関数の引数で与えられるということなのです。

引数の変数名は変えられるので、もし、MQL4と同じように使いたければ、次のように引数を大文字から始めるようにすればいいでしょう。
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[])

ここで、関数の引数にそれぞれ「const」とついていますが、今の時点では特に気にする必要はありません。4本値などの値がプログラム中で勝手に変更できないようなおなじまいだと思ってください。

これでOnCalculate()関数中で Open[]、High[]、Low[]、Close[]の4本値の配列を利用できるようになったので、MQL4と同じようなプログラムが書けるかというと、・・・もう少し調べた方がいいところがあります。

とりあえず、次のようなプログラムを書いて適当なチャートにアタッチしてみましょう。
#property indicator_separate_window

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[])
{
Print("rates_total = ", rates_total);
Print("prev_calculated = ", prev_calculated);
Print("Close[0] = ", Close[0]);
Print("Close[rates_total-1] = ", Close[rates_total-1]);

return(rates_total);
}

これは何のためのプログラムかというと、OnCalculate()の引数である、「rates_total」と「prev_calculated」の値、および、Close[]などの配列がどういう順番で格納されているかを確認するためです。

このプログラムを適当なチャートにアタッチすると、指標は何も表示されませんが、ToolboxウィンドウのExperts タブの画面に、Print()関数で指定した変数の値が表示されます。

MT5では、Expertsタブの内容を内蔵のビューアで参照することができるようになっています。

Expertsタブの画面で右クリックすると、サブメニューが現れるので、そこで「Viewer」を選ぶと下の図のように出力結果が参照できます。

画像(450x210)・拡大画像(773x362)

ここで探したいキーワードや、ログの日付などを指定して右上の「Request」ボタンを押すと、表示される内容を絞ることもできます。

これを見ると、「rates_total」は、新しいバーができるまで値は変わらないので、チャート上のバーの総数だと推測できます。

また「prev_calculated」は、最初は0ですが、次から rates_total と同じ値になっています。

このことから、これらの変数は、MQL4における BarsIndicatorCounted()と同じような働きをしていることがわかります。(正確には全く同じではないのですが、詳しくは別の機会に。)

さて、rates_total がチャート上のバーの総数だとすると、それぞれのバーの終値は、Close[0]からCLose[rates_total-1]で表されることが推測できると思います。

ただ、ここで注意することは、Close[]のインデックスがどういう順番で振られているかということです。

MQL4の場合、Close[0]は最新のバーの終値、Close[1]は1本前のバーの終値というように、最新のバーから過去にさかのぼる形でインデックスが振られていました。

ところが、MQL5の場合、Close[0]は毎回同じ値を示しているのに、Close[rates_total-1]は毎回変化していることから、Close[rates_total-1]が最新のバーの終値だということがわかります。

すると、Close[0]は、チャートを最初までさかのぼればわかると思いますが、チャートの最初の(一番古い)バーの終値だということになります。

つまり、インデックスの振り方が全く逆になっているわけです。

これは、MQL4のプログラムに慣れた人からすると、かなり混乱することだと思います。このままだと、MQL4のプログラムをMQL5に移植するのもかなり大変です。

そこで、MQL4のように新しい方から古い方に向かってインデックスを振るような配列(時系列配列)に変換するための関数が用意されています。(これはMQL4の頃からあります)

ArraySetAsSeries(Close, true);

のように最初の引数に配列の名前、2番目に「true」と代入することで、Close[]の配列を時系列配列に変えてくれます。

これをOnCalculate()関数の最初に書いておくと、MQL4のようにClose[0]が最新のバーの終値となります。

このようにMQL5では、通常の配列と時系列配列が混在するので、配列の扱いに注意する必要があります。

長くなったので、続きはまた次回。

Posted at 15時28分 パーマリンク


2010年08月03日(火)

MQL5でよく出てくる構造体 [MetaTrader5]

今回はプログラミングの基礎に戻ってデータ型と構造体の話です。

C言語やMQL4では、

int a;
double b;

のように書くと、a、bという変数をそれぞれ、int(整数)型、double(実数)型として宣言したことになり、その後、そのプログラム中で使えるようになります。

MQL4の場合、データ型といっても、int、double、string、bool、color、datetime の6種類しかなかったので、覚えるのもそんなに苦ではなかったと思います。

MQL5でも同じデータ型は使えますが、さらに増えたものもあります。

特に整数を表す型が、char、short、int、long、uchar、ushort、uint、ulongの8種類と増えています。

また実数はdouble、float の2種類に増え、さらにenumという列挙型が追加されています。

ただ、これらのデータ型をすべて使いこなさなくてはいけないというわけではなく、特に数値の表現範囲や精度にこだわらなければ、整数はint実数はdoubleと覚えておけば大丈夫です。

ところで、前回、Bid、Ask を調べた際に
MqlTick tick;

のようなコードが出てきました。

これをそのまま読むと、tickという変数をMqlTick 型として宣言したという意味になります。

しかし、MQL5には、「MqlTick」 というデータ型はありません。

では、これは何かというと、「構造体」というデータ構造として定義されたデータ型の一種なのです。

そもそも「構造体」という考え方はC言語にあるもので、複数のデータをまとめて一つのデータとして扱うためのものです。

ただ、複数のデータと言っても色々なバリエーションがあるので、それぞれの構造体を区別するために名前が付いています。

MQL5で予め定義されている構造体の一つが、「MqlTick」 であり、次のように定義されています。

struct MqlTick
{
datetime time;
double bid;
double ask;
double last;
ulong volume;
};
構造体の定義はこれだけなのですが、ここで、
MqlTick tick;

としてtickという変数を宣言すると、tickには、datetime型のデータ1つ、double型のデータ3つ、ulong型のデータ1つの計5つのデータがまとめて格納されることになるのです。

そして、それぞれのデータはどのようにして区別するかというと、各データにはtime、bid、ask などの名前(メンバ名)が付いているので、tick.bid、tick.ask のように、変数名とメンバ名を「.」でつないで表します。

但し、この構造体変数は宣言するだけでBid、Askの値が代入されるわけではなく、SymbolInfoTick()という関数を介すことで実際のBid、Ask値が代入されます。

この関数は2つの引数を取り、最初の引数がシンボル名、二つ目の引数がMqlTick型の変数です。
MqlTick tick; 
SymbolInfoTick(_Symbol, tick);

のようにSymbolInfoTick()関数を呼ぶことで、tick という変数に最新のティックの情報を返します。

最後にMqlTick型のデータを使ってBid、Askの値を表示させるプログラムは以下のようになります。
void OnStart() 
{
MqlTick tick;
SymbolInfoTick(_Symbol, tick);
double Bid = tick.bid;
double Ask = tick.ask;
Print("Bid=", Bid);
Print("Ask=", Ask);
}

このような構造体の考え方は、この後も、チャートの四本値やトレード関数などに頻繁に出てきますので、扱い方を覚えておくとよいでしょう。

Posted at 12時09分 パーマリンク


過去の記事へ

ページのトップへ ページのトップへ

Sponsor AD

シストレナビモバイル

シストレナビモバイル
ケータイでバーコードを読み取りアクセス(詳細はこちら

プロフィール

豊嶋久道

2003年よりFX取引を始め、システムトレードの道へ。最近ではFXオプション取引も含めたトレーディングシステムの研究を行っている。システムトレードを基礎から正しく理解するための情報を発信する予定。

活動状況・Website

ToyolabFX
Toyolab FX-手ぶらで為替取引
FXトレーディング研究所。
FXメタトレーダー入門
FXメタトレーダー入門
最先端システムトレードソフト使いこなし術。
FXメタトレーダー実践プログラミング
FXメタトレーダー実践プログラミング
システム開発過程を段階的に学ぶ。

2010/8

1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31        

PHOTO

ランダムウォークとランダムトレード(5)

ランダムウォークとランダムトレード(5)

カテゴリーリスト

最近の記事

スポンサードリンク

検索


当サイトコメントについて

当コメントは情報提供のみを目的として作成されたものであり、投資に関してはご自身でご判断くださいますようお願い致します。また、当資料は著作物であり著作権法により保護されております。無断で全文または一部を転載することはできません。

RSS1.0

[Login]


powered by a-blog
Copyright (C) 2008 PhiConcept,Inc. All rights reserved.