著書のご紹介
![]() |
▼高機能ソフトが切り開く! 「FXメタトレーダー入門」 うわさの高性能オールインワンFXソフトを徹底紹介。ようこそ“メタトレーダー”の世界へ! |
![]() |
▼MT4開発過程を段階的に学ぶ 「FXメタトレーダー実践プログラミング」 FXメタトレーダー入門の続編としてプログラミング機能をできるだけ多く紹介 |
2010年08月30日(月)
MQL5でEA(1) [MetaTrader5]
さて、今回からMQL5でEAを作成してみます。
「EA」は「Expert Advisor」の略で、日本語に直訳すれば「専門の相談員」となります。でも、これでは意味がわからないので、「EA」という言葉は普及しないかなと思っていたのですが、今ではメタトレーダーの自動売買プログラムという意味ですっかり定着したようです。
MQL5のEAも他のプログラム同様、MQL4とは互換性がないので、何回かにわけて説明していきます。
まず、メタエディターからFile - Newを選んでExpert Advisorを選択すると、以下のような新規プログラムが作成されます。
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
//---
//---
return(0);
}
//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
//---
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
//---
}
//+------------------------------------------------------------------+
ここで、OnInit()、OnDeinit()、OnTick()の3つの関数があります。OnInit()、OnDeinit()はカスタム指標プログラムで出てきたものと同じで、それぞれプログラムの最初と最後に呼ばれる関数です。
OnTick()というのは初めて出てきましたが、これは MQL4での start()と同じものです。ティック毎に実行される関数です。
今回はまず準備として、MQL4で定義済み変数としてすぐに使えたものをMQL5用に用意しておきましょう。
最初にBidとAskです。BidとAskはプログラム全体で使えるように外部変数として宣言しておきます。
そして、以前の記事のように構造体MqlTickとSymbolInfoTick()という関数を使って取得します。
ただ、これらを書く場所ですが、レートの更新はティック毎だけでなく、トレードの直前に行うこともあるので、RefreshRates()という関数(これはMQL4では組込み関数でした)を作って、そこに書いておくことにします。
以下のリストは、ティック毎にBid、Askを表示させるだけのEAです。
double Bid, Ask;
// 初期化関数
int OnInit()
{
return(0);
}
// 終了関数
void OnDeinit(const int reason)
{
}
// ティック関数
void OnTick()
{
if(!RefreshRates()) return;
Print("Bid=", Bid);
Print("Ask=", Ask);
}
// レートの更新
bool RefreshRates()
{
MqlTick tick;
if(!SymbolInfoTick(_Symbol, tick)) return(false);
Bid = tick.bid;
Ask = tick.ask;
return(true);
}
いくつかif文が出てきますが、これらは「念のため」といったところです。
SymbolInfoTick()は、正常にレートが取得できなかった場合にfalseを返すので、その場合RefreshRates()もfalseを返すようにしています。なお、
if(!SymbolInfoTick(_Symbol, tick)) return(false);
は、
if(SymbolInfoTick(_Symbol, tick) == false) return(false);
と同じ意味です。
同じく
if(!RefreshRates()) return;
も
if(RefreshRates() == false) return;
と同じ意味です。
ここで、return に戻り値がついていないのは、Ontick()がvoid(戻り値なし)として宣言されているからです。
RefreshRates()でレート更新ができなかった場合は、それ以降のプログラムをスキップしてOnTick()関数を終了します。
次にチャートの4本値です。カスタム指標プログラムでは、OnCalculate()関数の引数としてOpen[]、High[]、Low[]、Close[]などの配列が使えたのですが、EAの場合、そのままでは使えません。
EAで4本値を使う方法について、Close[]を例にとって説明します。
まずは、Close[]を外部変数として宣言します。
double Close[];
そして、OnInit()中に、
ArraySetAsSeries(Close, true);
と書き、Close[]を時系列配列(最新のデータがClose[0]、1本前のデータがClose[1]・・・)に設定します。
そして、RefreshRates()関数中に、CopyClose()という関数を使い、終値配列をClose[]配列にコピーします。このCopyClose()関数は、前回のCopyBuffer()関数と同じような使い方をします。
CopyClose(_Symbol, _Period, 0, count, Close)
と書くと、挿入したチャートの通貨ペア、タイムフレームにおける終値配列の最新の位置(0)からcount個分をClose[]配列にコピーします。
同様にOpen[]、Low[]、High[]の場合、CopyOpen()、CopyLow()、CopyHigh()という関数を使います。
以下のリストは、countを10とし、10個分の終値を表示させるプログラムです。
double Bid, Ask;
double Close[];
// 初期化関数
int OnInit()
{
ArraySetAsSeries(Close, true);
return(0);
}
// 終了関数
void OnDeinit(const int reason)
{
}
// ティック関数
void OnTick()
{
if(!RefreshRates()) return;
Print("Bid=", Bid);
Print("Ask=", Ask);
for(int i=0; i<10; i++) Print("Close[", i, "]=", Close[i]);
}
// レートの更新
bool RefreshRates()
{
MqlTick tick;
if(!SymbolInfoTick(_Symbol, tick)) return(false);
Bid = tick.bid;
Ask = tick.ask;
int count = 10;
if(CopyClose(_Symbol, _Period, 0, count, Close) < count) return(false);
return(true);
}
CopClose()もCopyBuffer()と同様、実際にコピーしたデータの個数を返すので、それがcountより少ない場合、エラーとしてfalseを返しています。
これで、プログラム中で終値をClose[0]、Close[1]などと参照することができるようになりました。
次回はトレードに関する関数について見ていきます。
Posted at 14時58分 パーマリンク
2010年08月24日(火)
MQL5でカスタム指標プログラム(3) [MetaTrader5]
カスタム指標プログラムでテクニカル指標を表示させる最も簡単な方法は、MQL5に既に組み込まれている関数を使うことです。
MQL5にも、MQL4のようによく使うテクニカル指標が組み込み関数として用意されています。例えば、移動平均線を算出する関数はiMA()です。
MQL4では、iMA()などの組み込みテクニカル指標関数は、その指標の値そのものが関数の戻り値だったので、
Buf[i] = iMA(NULL, 0, MAPeriod, 0, MODE_SMA, PRICE_CLOSE, i);
のように指標バッファ用の配列に直接代入するだけで利用することができました。
しかし、MQL5では、同じiMA()を使うにも、いくつかの手順を踏まなくてはいけません。
まずは、iMA()を利用して移動平均線を表示するMQL5プログラムを示します。
#property indicator_chart_window
#property indicator_buffers 1
#property indicator_plots 1
#property indicator_label1 "MA"
#property indicator_type1 DRAW_LINE
#property indicator_color1 Red
#property indicator_style1 STYLE_SOLID
#property indicator_width1 2
// パラメータ
input int MAPeriod = 20;
// 指標バッファ
double Buf[];
// テクニカル指標ハンドル
int hMA;
// 初期化関数
int OnInit()
{
// 指標バッファの割り当て
SetIndexBuffer(0, Buf, INDICATOR_DATA);
// テクニカル指標の初期化
hMA = iMA(NULL, 0, MAPeriod, 0, MODE_SMA, PRICE_CLOSE);
return(0);
}
// 終了関数
void OnDeinit(const int reason)
{
// テクニカル指標の解放
IndicatorRelease(hMA);
}
// 開始関数
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[])
{
// バッファのコピー
CopyBuffer(hMA, 0, 0, rates_total, Buf);
return(rates_total);
}
順に説明していきます。
// パラメータ
input int MAPeriod = 20;
これは、iMA()で利用する「移動平均の期間」を変えるための変数です。チャート挿入時に現れるプロパティ画面のInputsタブ(下図)で値を変えることができます。
このような用途の場合、MQL4では「extern」をつけて宣言していましたが、MQL5では「input」というキーワードに変わりました。
次に、問題のiMA()の使い方ですが、
// テクニカル指標ハンドル
int hMA;
に注目してください。
テクニカル指標ハンドルとは聞きなれない言葉ですが、MQL5では、外部変数として宣言したハンドルと呼ばれる変数を介してテクニカル指標を扱うようになっているのです。
プログラム中では、「hMA」という変数は以下の3箇所に出てきます。
OnInit()中
// テクニカル指標の初期化
hMA = iMA(NULL, 0, MAPeriod, 0, MODE_SMA, PRICE_CLOSE);
OnDeinit()中
// テクニカル指標の解放
IndicatorRelease(hMA);
OnCalculate()中
// バッファのコピー
CopyBuffer(hMA, 0, 0, rates_total, Buf);
手順としては、まず、OnInit()関数の中でiMA()を呼び出し、テクニカル指標の初期化を行います。
テクニカル指標の初期化とは、プログラム内部に移動平均用の配列を確保し、チャート全体の移動平均の値を格納しておくことです。
iMA()のパラメータはMQL4の場合とほぼ同じです。この例では、挿入したチャート上での終値に対する単純移動平均(SMA)を求めます。
但し、iMA()の戻り値は移動平均の値ではなく、このテクニカル指標を特定するための値(ハンドル)です。
つまり、MQL4のように各バーにおける移動平均の値をいちいちiMA()を呼び出して算出するのではなく、移動平均の値は内部の配列に自動的に算出されるわけです。
この移動平均の入っている配列をそのまま表示すれば簡単なのですが、残念ながらこれを直接表示させることはできず、表示用の指標バッファとして割り当てられた配列にコピーしてやる必要があるのです。
それが、OnCalculate()中のCopyBuffer()という関数で行っていることです。CopyBuffer()では、最初の引数にコピーしたいテクニカル指標のハンドル、2番目の引数にテクニカル指標のインデックス(移動平均の場合、指標は1本しかないので、0を指定)を代入します。
3番目と4番目の引数は変数の型によって意味が違ってくるのですが、両方intの場合、コピーしたいテクニカル指標の位置とコピーしたい個数を指定します。0, rates_total の場合、0の位置からrates_total個の指標データをコピーすることを意味します。
そして、5番目の引数はコピー先の配列名です。ここでは、SetIndexBuffer()で割り当てた「Buf」を指定します。
これで、rates_total個、つまりチャート上のすべての移動平均の値をBuf[]にコピーすることができたわけです。
最後にOnDeinit()(MQL4のdeinit()と同じ)中でIndicatorRelease(hMA)を呼んでいますが、これは、hMAで確保した配列を解放することを意味します。このプログラムが終了すれば、移動平均の配列は不要となるので、メモリの消費を防ぐために解放しておくのです。
以上が組み込みテクニカル指標関数の最も簡単な使い方です。コンパイルしてチャートに挿入すると次のように表示されます。
但し、このままでは、OnCalculate()を呼ぶ毎にチャート上のすべての移動平均の値をコピーします。新しいバーのために必要な分だけコピーするには、CopyBuffer()でコピーする個数を変えてやる必要があります。
ここで注意することは、Buf[]は、最も古いバーからインデックスが振られている配列なのに対して、hMAで確保されている内部配列は最新のバーから古い方にインデックスが振られている「時系列配列」だということです。
ですから、CopyBuffer()で、0からrates_total個というのは、最新のバーからrates_total個ということになります。そこで、rates_tatalをcountに変えると、最新のバーからcount個のデータをコピーすることになります。
プログラムは次のように追加・修正します。
int limit = prev_calculated;
if(prev_calculated > 0) limit--;
int count = rates_total-limit;
// バッファのコピー
if(CopyBuffer(hMA, 0, 0, count, Buf) < count) return(0);
前回の記事で説明したlimitという変数を使い、count=rates_total-limit とします。すると、最初はcount=rates_total となり、すべてのデータをコピーしますが、2回目からはcount=1となるので、最新のバーのみのコピーとなります。
なお、ここでif文になっているのは、CopyBuffer()の戻り値が実際にコピーできた指標データの個数になるのですが、それが指定したcountより少ない場合、エラーなので、return(0)として次回の実行時にコピーし直すためです。
簡単な方法と言いながら、ちょっと長くなってしまいました。配列のコピーについては、別の機会にも出てきますので、そのときにまた説明します。
Posted at 16時23分 パーマリンク
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_color1、indicator_style1、indicator_width1などはMQL4と同じですが、MQL5では、indicator_label1、indicator_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]が最新のバーの指標値だということに注意してください。
このプログラムをコンパイルして、適当なチャートにアタッチすると、下のチャートのように終値を結んだ指標が表示されます。
ただ、このままでは、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」を選ぶと下の図のように出力結果が参照できます。
ここで探したいキーワードや、ログの日付などを指定して右上の「Request」ボタンを押すと、表示される内容を絞ることもできます。
これを見ると、「rates_total」は、新しいバーができるまで値は変わらないので、チャート上のバーの総数だと推測できます。
また「prev_calculated」は、最初は0ですが、次から rates_total と同じ値になっています。
このことから、これらの変数は、MQL4における Bars と IndicatorCounted()と同じような働きをしていることがわかります。(正確には全く同じではないのですが、詳しくは別の機会に。)
さて、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分 パーマリンク
2010年07月27日(火)
MQL5でBid、Askはどう書くの? [MetaTrader5]
前回の記事では、MQL5には Bid、Askという変数が予め用意されていないということでした。
じゃあ、
double Bid, Ask;
のように直接宣言すればいいかと言うと、確かに宣言は必要ですが、それだけでは実際の売値、買値の値は Bid、Askには代入されません。
こういう場合、考えるだけでは解決できませんから、調べてみるしかありません。
まずは、MT5のメタエディターのHelpメニューに「MQL5のレファレンス」があります。またその下の「MQL5.community」からは、MetaQuotes社のMQL5のサイトを開くことができます。
MQL5のコミュニティはサンプルプログラムなど多数掲載されているので、ここを調べるのがてっとり早いでしょう。
メタエディターでは、画面下の「Toolboxウィンドウ」の「Articleタブ」と「Code Baseタブ」の画面に、MQL5コミュニティの記事一覧がリストアップされています。
ここから参考になりそうな記事を探してダブルクリックすると、その記事に直接ジャンプすることができます。
今回はその中で、
「Migrating from MQL4 to MQL5」
という記事を見てみましょう。
ここで、「Migrating」 は「移住」という意味ですが、プログラミング用語では、「移植」を意味します。つまり、「MQL4からMQL5への移植」ということですね。
この記事、実はかなりの大作です。印刷すると20〜30ページ近くになるんじゃないでしょうか。実際、MQL4とMQL5とはそれだけ違いがあるということなんです。
ここでは、当初の目的であった BidとAskだけ調べてみます。
幸い、BidとAskは、「3. Predefined Variables」の最初の方に記述があり、以下のように書かれています。
MqlTick last_tick;
SymbolInfoTick(_Symbol,last_tick);
double Ask=last_tick.ask;
MqlTick last_tick;
SymbolInfoTick(_Symbol,last_tick);
double Bid=last_tick.bid;
これを見てなるほどと、意味がわかる人は次に進んでいって構わないのですが、「MqlTick」って何?「SymbolInfoTick()っていう関数の意味は?」「.ask .bid ってくっついているけどこれは何?」と引っかかってしまうと、ちょっと時間がかかるかもしれません。
実は、これを説明するためには「構造体」という考え方を説明しなくてはならないのです。構造体はもともとC言語に導入されている機能ですが、MQL4では導入されていませんでした。ですから、MQL4しか知らない人にとっては初めての内容になるわけです。
構造体の説明は別の機会に説明することにして、今回はもう少し簡単に書ける方法として、
double Ask=SymbolInfoDouble(Symbol(), SYMBOL_ASK);という書き方を紹介しておきます。
double Bid=SymbolInfoDouble(Symbol(), SYMBOL_BID);
ここで、「SymbolInfoDouble()」という関数は、シンボル(FXでは通貨ペア)の情報のうち、double、つまり、実数の情報を取得する関数です。
「Symbol()」はMQL4と同様、プログラムをアタッチしたチャートのシンボル名を返す関数です。MQL5の場合、「_Symbol」と書くこともできます。
その次の「SYMBOL_ASK」、「SYMBOL_BID」がそれぞれ、AskとBidを意味する記号定数(MQL5では列挙型識別子というのですが、これも話すと長くなるので省略)です。
細かいことはさておき、MQL5でBidとAskを表示させるプログラムは以下のようになります。
void OnStart()
{
double Bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
double Ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
Print("Bid=", Bid);
Print("Ask=", Ask);
}
このスクリプトプログラムを適当なチャートにアタッチすると、その結果は、下図のように「Toolboxウインドウ」の「Expertsタブ」の画面に表示されます。
ちなみに ToolboxウィンドウはMT4ではTerminalウィンドウと呼んでいたものです。
次回は「構造体」あたりを説明しておいた方がいいかな。
Posted at 14時21分 パーマリンク
2010年07月20日(火)
MQL5スクリプトプログラム [MetaTrader5]
今回からMT5に搭載されているMQL5プログラムについて紹介していきます。
但し、更新のペースはゆっくりなので、急いでMQL5入門したい方は、以下のサイトなどをご利用ください。
「とあるMetaTraderの備忘秘録」のMQL5カテゴリー
http://d.hatena.ne.jp/fai_fx/archive?word=*[MQL5]
では今回は、プログラムをチャートにアタッチすると、1回だけ実行されるスクリプトプログラムについて見ていきます。
スクリプトのサンプルプログラムもMT5にインストールされていますが、このサンプルプログラムは、MQL5で導入された「クラス」という機能を使ったものが多いので、C言語、あるいはMQL4しか知らない人にとってはさっぱりわからないかと思います。
クラスという機能は、そもそもC言語を拡張した「C++」という言語に導入されているものです。これは、独自のデータ構造やそれに関連する関数を作っていく場合に効果を発揮しますが、とりあえず、初心者向けの説明は後回しにします。
「class」というキーワードが入っているプログラムについては、今回は飛ばしていただいて結構です。
では、実際に簡単なスクリプトプログラムを作ってみましょう。
MetaEditorの「File」メニューから「New」を選ぶと、下図のようなWizard画面が現れます。MQL4の場合とほとんど一緒です。
ここで「Script」を選択してプログラム名(ここでは「test」)を設定すると、次のようなプログラムの雛形が出来上がります。
このプログラムで、//から始まる行はコメント行、#から始まる行はプリプロセッサ命令といったところは、MQL4と同じです。
すると、OnStart()というのが関数のようですが、このOnStart()とは何でしょう?
MQL4の場合、プログラム中に必ず出てくる特殊関数は start()でした。プログラムはstart()関数からスタートするようになっていました。
MQL5のスクリプトプログラムでは、start()の代わりに、OnStart()という関数を使うように変わったのです。
但し、OnStart()を使うのはスクリプトプログラムだけで、カスタム指標プログラムやEAでは、別の関数を特別な関数として使うので注意してください。
詳しくは以下のMQL5のHELPサイトをご覧ください。
http://www.mql5.com/en/docs/runtime/running
では、スクリプトの簡単な例として、売値Bidと買値Askを表示させてみましょう。
MQL4の場合、
Print("Bid=", Bid);
Print("Ask=", Ask);と書けばよかったところですが、MQL5では、同じ書き方にすると、コンパイル時にエラーとなってしまいます。
エラーメッセージは
'Bid' - undeclared identifier
'Ask' - undeclared identifier
となります。つまり、BidとAskが宣言されていないという意味です。
実は、MQL4で BidやAskが宣言せずに使えたのは、予め宣言されていて自動的に値が代入される定義済み変数だったからです。
MQL5では Bid、Askは定義済み変数ではありません。では、別の変数名に代わったのかというと、そうでもありません。代わりの変数はないのです。
こうなってしまうと、何も参考資料がなければお手上げです。やっぱり、サンプルプログラムやMQL5のHELPを探していかなくてはなりません。
ということで、続きはまた次回。
Posted at 13時47分 パーマリンク
【 過去の記事へ 】





















