English Русский 中文 Español Deutsch Português 한국어 Français Italiano Türkçe
初心者のためのクイックスタート、あるいはショートガイド

初心者のためのクイックスタート、あるいはショートガイド

MetaTrader 5 | 2 10月 2015, 17:22
4 687 0
Dmitriy Parfenovich
Dmitriy Parfenovich

はじめに

読者の皆さんこんにちは!この記事では、Expert Advisorsの作成やインディケーターの使い方などの基本的なコツを簡単に素早く掴めるように説明していきたいと思います。初心者対象で難しいサンプルの紹介は行いません。ですので、この記事はExpert Advisorのプログラムをすでに理解している人たちには退屈で有益ではないかもしれません。


Expert Advisorとその構造

Expert AdvisorMQL言語で書かれたプログラムで、トレードを行うか横に据え置くかを特定します。

基本的にはEAは多くのブロックで構成することができますが、簡単に理解できるよう、MetaEditorで作成されたとてもシンプルな例をお見せします。

EA全体はそれぞれ受け持つ動作がある4つのパートに分けることができます。

EAのメインブロック

図 1. EAのメインブロック

  1. パラメータのブロックターミナルがEAを正しく処理するための情報を含むブロック。もっとも一般的なパラメータはEAのバージョン、開発者名、簡単な説明です。
  2. OnInit()ブロックはEAがターミナルにロードされるとコントロールできるようになります。EAの初期化に関する様々なデータを含みます - 変数の宣言や配列、インディケーターハンドルの取得など。これは、このブロックにはトレーディングに直接関係する関数は含まれていないということです。
  3. OnDeinit()ブロック OnInit()ブロックの逆の役割を果たします。EAがオペレーションを完了した時に呼びだされます(EA/ターミナルのシャットダウンやEAの初期化の失敗)。このブロックの主な役割の1つが必要のなくなったEAが占めるメモリスペースの解除です、言い換えると、変数、配列、インディケーターハンドル等の削除プロセスを記述します。
  4. OnTick() Blockはシンボルの新しい情報をサーバーから受信するたびに呼び出されます。トレードをするための状況とトレード自体の関数を指定します。

MetaEditorのデフォルトで生成されたドキュメントの例

図 2. MetaEditorのデフォルトで生成されたドキュメントの例

上の例を用いて説明したいと思います。まず”空の”Expert Advisorがあります。後で埋めていくことになるExpert Advisorのテンプレートのようなものです。

次のことが分かります:

  • 最初の5行(1行目から5行目)はEAの名前 (ファイル名)、EAの製作者名とそのWebサイトを含むコメントを表しています。ここには何を書いても良いです。このテキストはどこでも見られませんし、スキップすることも可能です。ここに含まれる情報は開発者のみを対象としています;
  • 次の3行(6行目から8行目)はパラメータブロックになります。ここの情報はEAをターミナルで開始した時に見ることができます;
  • 次に来るのがOnInit()関数です (12行目から19行目)。これはOnInit()ブロックです。この関数はパラメータを取得しませんが、初期化コードを返します(返さないかもしれませんが); the initialization code;
  • OnDeinit(const int reason) 関数が次に来ます(22行目から26行目)。これがOnDeinit()ブロックです。EAのシャットダウンの理由を特定するパラメータです。
    EAの初期化が失敗した場合、この関数が関連するコードを受け取ります;
  • 最後の関数はOnTick()(30行目から34行目)です。これはOnTick() ブロックの中に記述されいます。このブロックはEAの”頭脳”と呼ぶこともでき、トレードに関するすべての関数から成るブロックです。

前述のとおり、この構造は何倍も複雑になることもあり、今回のように簡単に全体を把握することができないものもあります。これが十分でないと感じるならば、自分のブロックを追加することができるのです。


インディケーターとその処理方法

インディケーターは MQLで書かれた小さなプログラムで、プライスチャートやその下の別のウインドウに表示され、マーケットのテクニカル分析を行うために使用されます。

すべてのインディケータは2つのタイプに分類できます:トレンドフォロー型のインディケーターオシレーターです。

トレンドフォロー型のインディケーターは、ルールとして、プライスチャート内に描画され、トレンドの方向を特定するのに使われ、オシレーターはプライスチャートの下にあり、エントリーポイントを判断するのに役立ちます。

ほとんどのインディケーターは、最低1つのバッファ(インディケーターバッファ)を持ち、ある時点での自身の読み取りデータを格納しています。EAと同じように、インディケーターも計算するためのシンボルとタイムフレームを持っています。

インディケーターバッファは、最後の要素が現在値(running value)である列と考えることができます。

移動平均インディケーターの例

図 3. 移動平均インディケーターの例

インディケーターバッファは、最初の要素(インデックスが0)が右端の足のデータを持ち、次の要素が(インデックスが1) 右から2番目の足のデータを持ち・・・という配列です。このような要素の構成はタイムシリーズと呼ばれます。

次の例を見てみましょう:通貨ペアはEUR/USDでタイムフレームは1時間だとしましょう。
まず最初に、EAにインディケーターを追加してそのハンドルを取得します。

ハンドルは固有のポインタで、インディケーターがプログラムのどこにあっても処理することを可能にします。

int iMA_handle; 
iMA_handle=iMA("EURUSD",PERIOD_H1,10,0,MODE_SMA,PRICE_CLOSE);
もう少し詳しく見てみましょう。
最初の行ではインディケーターハンドルを格納する変数を定義しています。2行目ではインディケーターを呼び出し(ここでは移動平均インディケーター)そのパラメータを指定し、後で使うためにハンドルを変数に保存しています。
”iMA(" と入力すると、MetaEditorでは、その行の上にツールチップが表示され。コンマで区切られたインディケーターのパラメータが表示されます。

移動平均インディケーターのパラメータを表示するツールチップの例

図 4. 移動平均インディケーターのパラメータを表示するツールチップの例

左から順に以下のパラメータが表示されているのが分かるはずです:

  1. シンボル名(ツールチップでは太字で表示)はテキストパラメータで、通貨ペア(シンボル)です;
  2. タイムフレーム
  3. インディケーターの期間(ここでは平均的な期間);
  4. チャートシフトN本進める/戻す。チャートシフトが正の数の場合は、N本進め、負の場合はN本戻します;
  5. 平均方法;
  6. 適用されたプライス あるいは異なるインディケーターのハンドル

それぞれのインディケーターには独自の変数と型があります;見たことのないインディケーターに出会った場合は、ビルトインのコンテキストヘルプで情報を得ることができます。例えば、iMAと入力しF1を押すと、その特定のインディケーターのヘルプウインドウが表れ、詳しいプロパティを見ることができます。

F1を押して詳しい説明を見るためのヘルプウインドウを呼び出す例

図 5. F1を押して詳しい説明を見るためのヘルプウインドウを呼び出す例

コードを書いてEAをターミナルで開始すると(プライスチャートの右上にEAが表れると)、そのインディケーターはチャート上から消えるのが分かると思います。これはエラーではありません - そうなるべきものです。それが表れるためには、もう1行必要になります:

ChartIndicatorAdd(ChartID(),0,iMA_handle);

これが何をしているのかを見てみましょう。ChartIndicatorAddコマンドの上にカーソルを置いて、F1を押しコマンドの目的に関するヘルプインフォメーションを読んでみましょう。そこにはこう書かれています:

特定のハンドルを持つインディケーターを特定のチャートウインドウに追加する。

2つ目の0に等しいパラメータはサブウインドウの数です。サブウインドウには大抵、プライスチャートの下にオシレーターがあります。覚えていますか?それは大量かもしれません。インディケーターをサブウインドウに表示するには、既に存在しているサブウインドウの数よりも1多い、サブウインドウの数を指定するだけで良いです。つまり最後のサブウインドウの数+1ということです。

次のようにコードを変更しました:

ChartIndicatorAdd(ChartID(),1,iMA_handle);

これで、インディケーターはプライスチャートの下のサブウインドウに表示されます。

それでは、インディケーターからデータを取り出してみましょう。そのためには、動的な配列を宣言し 、便宜的に配列のインデックスをタイムシリーズとして配置し、インディケーターの値をこの配列にコピーします。

double iMA_buf[];
ArraySetAsSeries(iMA_buf,true);
CopyBuffer(iMA_handle,0,0,3,iMA_buf);

上記の例では、移動平均インディケーターとして宣言したダブル型の動的な配列 iMA_buf[]はプライスに基づいており、プライスは分数を持っていることが示されています。

次の行では配列のインデックス化の設定を行っています。インデックスの小さいほど古い値を、大きなインデックスは新しい値を格納しています。これは、すべてのインディケーターのインディケーターバッファはタイムシリーズとしてインデックスされているため、混乱を防ぐのに便利です。

最後の行はiMA_buf[]の配列にインディケーターの値をコピーするための行です。これで、これらのデータが使えるようになりました。


オーダー、トレードとポジション

オーダーから始めましょう。

  • オーダーはトレードサーバーによって受け取られるトレードのリクエストです。リクエストが無効な場合、拒否されます。

    トレードリクエストを満たす難しさを避けるための、標準ライブラリを使用した簡単な方法を後ほど解説します。オーダーには2つのタイプがあります:マーケット(即座に実行されます)と指値です。

    マーケットオーダーとは特定の投資対象を市場価格で、あるボリュームで売買するということです。指値注文は、投資対象がある条件を満たしたときに実行される命令を表します。指値注文にはそれを取り消される一定の期間があります。

  • トレードとは実行された注文(トレードを実行する命令)の結果を表します。すべてのトレードは、ある1つの注文に基づきますが、1つの注文は複数のトレードによって行うことができます。例えば、10ロットの買い注文は、連続する複数のトレードによって実行することができます。トレードはトレード履歴に保存され、変更することはできません。トレードはターミナルの”過去データ”タブに表示されます。

  • ポジション実行中の注文の結果を表します。1つの通貨ペアに対し、ロングかショート、いずれかのポジションを開くことができます。

分かりやすくするために、例を使って説明させてください:1ロットのロングのポジションを開きました、現在のマーケット価格で1ロットの注文を出したということです。リクエストが正しければ、サーバーに送られ処理されます。処理が終了次第、ポジションとオーダーパラメータがターミナルの”トレード”タブに表示されます。もう1つ、1ロットのロングポジションを取ることを決めたとします。注文の処理が終了しても”トレード”タブには2つのトレードは表れませんが、1つのポジションのサイズが2ロットになります。つまり、ポジションとは複数の注文の実行の結果であるということです。

それでは、実際にみてみましょう。リクエストをするためには、次のストラクチャフィールドを埋めていかなければいけません:

struct MqlTradeRequest
{
ENUM_TRADE_REQUEST_ACTIONS action; // Type of action
ulong magic; // Expert Advisor ID (magic number)
ulong order; // Order ticket
string symbol; // Trade instrument
double volume; // Requested trade size in lots
double price; // Price 
double stoplimit; // StopLimit level of the order
double sl; // Stop Loss level of the order
double tp; // Take Profit level of the order
ulong deviation; // Maximum allowed deviation from the requested price
ENUM_ORDER_TYPE type; // Order type
ENUM_ORDER_TYPE_FILLING type_filling; // Order type by execution
ENUM_ORDER_TYPE_TIME type_time; // Order type by duration
datetime expiration; // Order expiration time (for orders of the ORDER_TIME_SPECIFIED type)
string comment; // Comment to the order
};

様々なオーダーがあるため、それぞれのオーダーのタイプによって、必須パラメータがあります。これらのフィールドについては長く説明ません。この問題に関しては、Webサイトで多くの情報を提供しているからです。あるオーダーの必須のパラメータが、指定されていなかったり、不正だった場合、リクエストは失敗します。

上のストラクチャは、それを埋める段階になった時に生じる問題を見やすくするためのものです。


ストップロスとテイクプロフィット

ストップロスとテイクプロフィットは ”代替策”として出される特別注文です。つまり、ミスやvExpert Advisorによって開かれたポジションに損失がある場合、ストップロス注文は、そのロスを好みのレベルに設定できます。

テイクプロフィットも同じですが、限定するのは損失ではなく利益であるということです。ポジションと閉じる心配をしなくてすむようになるかもしれません。あるプライスレベルになると、ポジションは閉じられます。言い換えれば、これらの注文は”保険”だということです。マーケットで損失を出すか、利益をあげるか。

このタイプの注文はそれだけで出すことはできません -すでに持っているポジションに対して変更するだけです。


標準ライブラリの使用

ついに、標準ライブラリまできました。このライブラリはターミナルに付属していることから-標準ライブラリと呼ばれます。EAのプログラミングを容易にする関数と複雑な処理を請け負う関数で構成されています。

トレードライブラリ(トレードクラスをご参照ください)は次のパスに置かれています:Include\Trade\ #includeディレクティブを使用して追加することも可能です。
例:

#include <Trade\Trade.mqh>
#include <Trade\PositionInfo.mqh>

上記のクラスは基本的なものと言えます。Expert Advisorの多数はこの2つのクラスを使ってプログラミングされるからです。それらをライブラリと呼びます:

  • 1つ目はオーダーを出したり、変更したりするためのものです。
  • 2つ目は、すでに存在するポジションの情報を取得するのに使われます。

他のライブラリが有用なこともあります:
#include <Trade\OrderInfo.mqh>
オーダーに関する関数を含みます。例えば、ストラテジーに指値注文の使用が必要な場合。

正しく知識を利用しなければならない様々なパラメータを含むトレードリクエストストラクチャを覚えていますか?
ここでは、ライブラリを使ったトレードリクエストのサンプルを見ていきます:
CTrade m_Trade;
m_Trade.Sell(lot,symbol_name,price,sl,tp,comment);

合計6つのパラメータがあります。そのうち1つが必須です(オーダーのサイズ-1つ目のパラメータです)。
1つずつ見てみましょう:

  • lotオーダーのサイズ;
  • symbol_nameオーダーを出すシンボル(通貨ペア)(指定が無ければ、EAを使用中の通貨ペア)
  • price オープンプライス(アクティブなオーダーを出す関数であるため、そのプライスが特定できない場合はチャートから自動的に直接取得されます);
  • slプライスが有利でなければ、オーダーを閉じるプライス(ストラテジーがストップロスを使用しない場合、省略可)
  • slプライスが望む希方向へ動けばはオーダーを閉じるプライス。(ストラテジーがテイクプロフィットを使用しない場合、省略可)
  • commentオーダーに関するコメント、オーダーを出した理由等。

ポジションを閉じる方法は多くあります:

  1. ポジションをすべて閉じる

    CPositionInfo m_Position;
    m_Position.Select(symbol_name);
    m_Trade.PositionClose(symbol_name);
  2. 反対に同じサイズの注文を出すことによって注文を閉じる

    CTrade m_Trade;
    m_Trade.Buy(lot,symbol_name,price,sl,tp,comment);
  3. より複雑な方法をを使い、すべてのポジションの中から、さらに閉じるための特定のパラメータ (通貨ペア、型、マジックナンバー、ポジション識別子など)を持つポジションを探し出す。上の例は初心者には難しすぎるので、ここでは出しません。


全てを1つに

新しく得た知識を1つのExpert Advisorに注ぎ込むには良いタイミングでしょう。

//+------------------------------------------------------------------+
//|                                           fast-start-example.mq5 |
//|                        Copyright 2012, MetaQuotes Software Corp. |
//|                                              https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2012, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00"
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
#include <Trade\Trade.mqh>                                         //include the library for execution of trades
#include <Trade\PositionInfo.mqh>                                  //include the library for obtaining information on positions

int               iMA_handle;                              //variable for storing the indicator handle
double            iMA_buf[];                               //dynamic array for storing indicator values
double            Close_buf[];                             //dynamic array for storing the closing price of each bar

string            my_symbol;                               //variable for storing the symbol
ENUM_TIMEFRAMES   my_timeframe;                             //variable for storing the time frame

CTrade            m_Trade;                                 //structure for execution of trades
CPositionInfo     m_Position;                              //structure for obtaining information of positions
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int OnInit()
  {
   my_symbol=Symbol();                                      //save the current chart symbol for further operation of the EA on this very symbol
   my_timeframe=PERIOD_CURRENT;                              //save the current time frame of the chart for further operation of the EA on this very time frame
   iMA_handle=iMA(my_symbol,my_timeframe,40,0,MODE_SMA,PRICE_CLOSE);  //apply the indicator and get its handle
   if(iMA_handle==INVALID_HANDLE)                            //check the availability of the indicator handle
   {
      Print("Failed to get the indicator handle");              //if the handle is not obtained, print the relevant error message into the log file
      return(-1);                                           //complete handling the error
   }
   ChartIndicatorAdd(ChartID(),0,iMA_handle);                  //add the indicator to the price chart
   ArraySetAsSeries(iMA_buf,true);                            //set iMA_buf array indexing as time series
   ArraySetAsSeries(Close_buf,true);                          //set Close_buf array indexing as time series
   return(0);                                               //return 0, initialization complete
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
   IndicatorRelease(iMA_handle);                             //deletes the indicator handle and deallocates the memory space it occupies
   ArrayFree(iMA_buf);                                      //free the dynamic array iMA_buf of data
   ArrayFree(Close_buf);                                    //free the dynamic array Close_buf of data
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
   int err1=0;                                             //variable for storing the results of working with the indicator buffer
   int err2=0;                                             //variable for storing the results of working with the price chart
   
   err1=CopyBuffer(iMA_handle,0,1,2,iMA_buf);               //copy data from the indicator array into the dynamic array iMA_buf for further work with them
   err2=CopyClose(my_symbol,my_timeframe,1,2,Close_buf);    //copy the price chart data into the dynamic array Close_buf for further work with them
   if(err1<0 || err2<0)                                    //in case of errors
   {
      Print("Failed to copy data from the indicator buffer or price chart buffer");  //then print the relevant error message into the log file
      return;                                                               //and exit the function
   }

   if(iMA_buf[1]>Close_buf[1] && iMA_buf[0]<Close_buf[0])   //if the indicator values were greater than the closing price and became smaller
     {
      if(m_Position.Select(my_symbol))                     //if the position for this symbol already exists
        {
         if(m_Position.PositionType()==POSITION_TYPE_SELL) m_Trade.PositionClose(my_symbol);  //and this is a Sell position, then close it
         if(m_Position.PositionType()==POSITION_TYPE_BUY) return;                              //or else, if this is a Buy position, then exit
        }
      m_Trade.Buy(0.1,my_symbol);                          //if we got here, it means there is no position; then we open it
     }
   if(iMA_buf[1]<Close_buf[1] && iMA_buf[0]>Close_buf[0])  //if the indicator values were less than the closing price and became greater
     {
      if(m_Position.Select(my_symbol))                     //if the position for this symbol already exists
        {
         if(m_Position.PositionType()==POSITION_TYPE_BUY) m_Trade.PositionClose(my_symbol);   //and this is a Buy position, then close it
         if(m_Position.PositionType()==POSITION_TYPE_SELL) return;                             //or else, if this is a Sell position, then exit
        }
      m_Trade.Sell(0.1,my_symbol);                         //if we got here, it means there is no position; then we open it
     }
  }
//+------------------------------------------------------------------+

このExpert Advisorを以下のパラメータでテストしましょう:

  • 通貨ペア- EURUSD
  • タイムフレーム - H1;
  • トレードモード”オープニングプライスオンリー”。

1つ目の足(0番目の足は現在アクティブな足)から、インディケーター値と閉じるプライスを使用するため、チャートは再描画されません。”オープニングプライスオンリー”のトレードモードを使用できるということです。これはテストの質には影響しませんが、テストを早く行うことができます。

過去のデータを使ったクイックテストの結果です。

Expert Advisorのテスト結果

図. 6. Expert Advisorのテスト結果

ドローダウンを見逃すことはできません。しかし、この記事の目的は、最少のドローダウンで大きな利益を上げる”スーパーなExpert Advisor”のプログラミングではありません。基本的な知識を持つだけでどれほど簡単にEA を作ることができるのかを示すことです。
100行未満のコードのExpert Advisorを作ることができました。


まとめ

この記事ではEAのプログラミングにおける重要な基本事項をカバーしています。MetaEditor 5のビルトインのヘルプメニューから様々な関数に関する情報や、注文やポジションに基本的な考え方、内蔵されている標準ライブラリの使用などの情報を得る方法を学びました。

MetaQuotes Ltdによってロシア語から翻訳されました。
元の記事: https://www.mql5.com/ru/articles/496

添付されたファイル |

この著者による他の記事

プライスヒストグラム(マーケット特性)とMQL5への導入 プライスヒストグラム(マーケット特性)とMQL5への導入
「マーケットプロファイル」は非常に優秀な思索家、 ピーター・スタイドルマイヤー氏によって展開されました。氏は全く異なるモデルセットに導く『水平的な』また『垂直的な』マーケットの動きに関する情報の別の解釈の仕方を提案しました。潜在するマーケットの拍動、または均衡と不均衡の周期と呼ばれる基本パターンがある、と仮定したのです。本記事では、プライスヒストグラムについて考察していきたいと思います。それは、マーケットプロファイルの最も単純なモデルです。また、その MQL5への導入について述べていきたいと思います。
オーダーストラテジー多目的Expert Advisor オーダーストラテジー多目的Expert Advisor
この記事では、未処理のオーダーを有効に活用するストラテジーや、それを表すためのメタ言語やそれに基づき動作する多目的ExpertAdvisorを中心に見ていきます。
データの交換方法:10分で書くMQL5のためのDLL データの交換方法:10分で書くMQL5のためのDLL
シンプルなDLLを書く方法や異なるシステム バインディングの特殊機能は何かを覚えている開発者はあまりいないと思います。いくつか例を挙げながら、10分でDLLを書く手順を網羅するとともに、バインディング実装の技術的詳細もいくらか説明していきたいと思います。異なるタイプの変数(数値、配列、ストリングなど)に置き換えた例を取り上げ、ビジュアル スタジオでDLLを作成する手順を段階的にお見せしていきます。それに加え、カスタムDLLのクラッシュからクライアント端末を保護する方法についてもご説明します。
MQL5でのトレードオペレーション - 簡単です MQL5でのトレードオペレーション - 簡単です
ほとんどすべてのトレーダーは利益をあげるためにマーケットに参加しますが、中にはそのプロセス自体を楽しむトレーダーもいます。しかし、手動のトレードだけが、エキサイティングな体験をさせてくれるわけではありません。自動トレードシステムの開発も非常に興味深いものです。トレードロボットの作成は面白いミステリー小説を読むのと同じくらい面白いものです。