文系人間のためのシステムトレーダー養成所 メタトレーダー講座
--------

スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。
2009-03-23

メタトレーダー講義第12回 初めてのインディケーター第三部

今回バーのことがたくさん出てきますが、バーの概念が難しいので、これより先に、補講のバーの方から先に目を通して頂いた方が良いかもしれません。
尚、海外ではローソク足ではなくバーチャートを使われていることが多いので、記述はすべてバーチャートを基準としたものになっています。
ローソク足とほとんど変わらないので読み進めて頂く際にバーとでてきたらローソク足と置き換えて考えて頂くと、ローソク足を普段使っている方はわかりやすいと思います。
それでは今回もよろしくお願いいたします。

この文章はCodersGuruさんのMQL4Lesson4の訳文です。(翻訳しての転載に本人の許可はとってあります)                              
                       MQL4講座                        
                       Coders'guru
                         www.forex-tsd.com                               
                             -12-
                   初めてのインディケーター
                    第三部


初めてのインディケーター第三部の講義によくいらっしゃいました。
前回の授業では、初めてのインディケーターのコードを1行1行学んでいき、dinit()関数まで到達しました。

前回の授業でどういう構造になっているかをしっかり理解されてこの講義に辿りつかれていることを願っています。

今日は、start()関数とその中身を勉強します。そしてついに、私たちは初めてのインディケーターをコンパイルし、起動させることになるでしょう。

準備はいいですか? コードを一行一行みていきましょう。

私たちのコード

//+------------------------------------------------------------------+
//| my_first_indicator.mq4 |
//| Codersguru |
//| http://www.forex-tsd.com |
//+------------------------------------------------------------------+
#property copyright "Codersguru"
#property link "http://www.forex-tsd.com"

#property indicator_separate_window
#property indicator_buffers 1
#property indicator_color1 Red

//---- buffers
double ExtMapBuffer1[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int init()
{

//---- indicators
SetIndexStyle(0,DRAW_LINE);
SetIndexBuffer(0,ExtMapBuffer1);
string shotr_name="Your first indicator is running!";
IndicatorShortName(short_name);


//----
return(1);
}
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function |
//+------------------------------------------------------------------+
int deinit()
{

//----

//----
return(0);
}
//+------------------------------------------------------------------+
//| Custom indicator iteration function |
//+------------------------------------------------------------------+
int start()
{
int
counted_bars=IndicatorCounted();
//----check for possible errors
  if (counted_bars<0) return(-1);
//----last counted bar will be recounted
  if(counted_bars>0) counted_bars--;

  int pos=Bars-counted_bars;
  
  double dHigh , dLow , dResult;
  Comment("hi! I'mhere on the main cart windows!");


//----maincaluculation loop
  while(pos>=0)
   {
      dHigh=High[pos];
      dLow=Low[pos];
      dResult=dHigh - dLow;
      ExtMapBuffer1[pos]=dResult ;
      pos--;
    }

return(0);
}
//+------------------------------------------------------------------+

____________________________________________________________________


int start()
 {...
  return(0);
 }

以前に言ったように、プログラミングの役割はstart()関数の大括弧の中であり、9割を占めます。
なぜならMQL4のなかでもっとも重要な特別関数だからです。

init()関数やdenit関数と対照的に、start()はターミナルクライアント(メタトレーダーのメイン画面)によって一回しか呼び出されません。しかし、メタトレーダーターミナルクライアントに新しいティックが届けられると、そのたびごとにstart()関数が呼び出されることになります。
start()関数はすべてのMQL4の特別関数と同じように整数値を返します。0の意味はエラーがないということで、何かの数字が出てくるとその意味は、何かエラーが生じたということになります。

____________________________________________________________________

int counted_bars=IndicatorCounted();

ここで私たちはcounted_barsをintegerタイプの変数と定めました。そして、IndicatorCounted()関数の返却値をcounted_bars変数に割り当てました。

int IndicatorCounted()

この関数は私たちのインディケーターが計算した足(バー)の総数をintegerタイプの値で返します。

貴方のインディケーターは最初にこの値を0と数えるでしょう。なぜなら、まだインディケーターはどのバーも算出していないからです。そしてその後、それはチャートに表示されるバー(ローソク足)の総数の-1になります。(後述のbars関数をごらんください。)
____________________________________________________________________
  if (counted_bars<0) return(-1);

一つ前の、IndicatorCounted()関数のコード文を使うことで、私たちはcounted_barsの数を取得しました。
この数はもしエラーが何も起こらなければ、0からそれ以上の数になります。もし0よりも小さい数がでてきたら、それはエラーが起こったことを示しており、start()関数をreturnステートメントを使うことによって終了させなければなりません。(上述のようにreturnに0以外の値が返されるとエラーとしてみなされます。)
____________________________________________________________________
 if (counted_bars<0) counted_bars--;

ここでcounted_barsが0以上であるか確かめます。
もし0以上であるのならば、その数から数字を1減らします。
これは何故かというと、最後のバーをもう一度数えなおしたいからです。

私たちはデクレメント演算子(第4回講義の演算子と式をご覧ください。)を使用して、counted_barsの値からを引きます。

メモ:counted_barの式を以下のようにかくこともできます。

counted_bars=counted_bars-1;
____________________________________________________________________

 int pos=Bars-counted_bars;

ここではposを私たちのループ計算(この講義のあとでのwhileループをご覧ください)が働くであろう回数の値を持つように宣言しています。。これはチャートのバーの総数からcounted_barsを減算することで得られ、バーの総数はBars()関数を使うことで取得します。
ここはBars()関数と、その兄弟について述べるいい機会だと思うのでそのことについて触れていきます。

MQL4の定義済み変数

Ask,Bid,Bars,Close,Open,High,Low,Time,VolumehはMQL4は定義済み変数と名付けていますが、関数です。何故これは関数なのか証明していきましょう。

変数の意味は、メモリーの空間という意味で、そのデータタイプをあなたが特定します。
関数の意味は、ある実行を行い、それによって得られた結果の値を返すことです。たとえばBarsはチャート上の足(バー)の数を集めて、その値を返します。 これは変数なのでしょうか?

また他の観点からも、これらは変数でないことを証明することができます。
もしあなたがこのコード文を記述しコンパイルすると:

Bars=1:

このようなエラー文がでてくるでしょう。'Bars'-unexpected token
これはなぜなら、変数ではないので、値を割り振ることができないからです。

他の証明。次のコード文は適応され、コンパイルでエラーは発生しません。

Alert(Bars(1));

設定値を変数に受け渡すことはできません。設定値は関数にのみ受け渡すことができます。

長々とすみませんでした。それではすべての関数について議論を進めていきましょう。

int Bars

この関数は現在のチャートの足の総数を数え、integerタイプの値としてそれを返します

double Ask

この関数は(エキスパートアドバイザーで使います)現在の通貨における最新の買値をdoubleタイプの値で返します。

double bid

この関数は(エキスパートアドバイザーで使います)現在の通貨における最新の売値をdoubleタイプの値で返します。

メモ:例えば、USD/JPY=98.27/98.31だとしたら、左の値がbidプライス(売値)で次の値がaskプライス(買値)となります。

double Open[]

この関数は指定されたバーの始値の値をdoubleタイプの変数で返します。
始値は、バーの期間(日足、週足、月足、一時間足等)での始値になります。
例: Open[0]は最新のバーの始値を返します。

double Close[]
この関数は指定されたバーの終値の値をdoubleタイプの変数で返します。
終値は、バーの期間での(日足、週足、月足、一時間足等)終値になります。
例: Close[0]は最新のバーの終値を返します。

double High[]

この関数は指定されたバーの高値の値をdoubleタイプの変数で返します。
高値は、バーの期間での高値になります。
例: High[0]は最新のバーの高値を返します。

double Low[]

この関数は指定されたバーの安値の値をdoubleタイプの変数で返します。
安値は、バーの期間での安値になります。
例: Low[0]は最新のバーの安値を返します。

double Volume[]

この関数はその期間内でのバーの出来高(取引された総量の平均)をdoubleタイプの変数で返します。
期間は普通、日足で考えられます。
例: Volume[0]は最新のバーの出来高を返します。

int Digits

この関数は小数点以下の桁数をintegerタイプの値を返します。(普通は4)

double point

この関数は通貨の足の最小単位をdoubleタイプの変数を返します。(普通は0.0001)

detetime time[]

この関数は指定した足の開始した時間の値をdatatimeの値を返します。
例: Time[0]は最新の足の始まった時間を戻します。

____________________________________________________________________

double dHigh, dLow, dResult;
私たちは後で使うことになる三つのdoubleタイプの変数を宣言しました。コンマで区切ることによって同じ行で三つの変数を宣言をしたこのやり方を覚えておいてください。

____________________________________________________________________

Comment("hi! I'mhere on the main cart windows!");


このコード文はComment関数をつかって、"Hi!I'm here on the main chart window"という文章をメインチャートの左上に表示させます(図1参照)
Comment関数には似たような関数が二つあります。

void Comment(...)

この関数は受け渡された値(どのようなデータタイプでも構いません)をチャートの左上の角に表示します(図1参照)

void Print(...)

この関数は受け渡された値(どのようなデータタイプでも構いません)をexpert logに表示します(図2参照)

void Alert(...)

この関数は受け渡された値(どのようなデータタイプでも構いません)をdialog boxに表示します(図3参照)
図1コメント
図1コメント
keikokuke.png
図2expert log
図3警告
図3dialog box

____________________________________________________________________
 while(pos>=0)
   {
      dHigh=High[pos];
      dLow=Low[pos];
      dResult=dHigh - dLow;
      ExtMapBuffer1[pos]=dResult ;
      pos--;
    }


さぁついに、私たちのインディケーターを描くための値を算出するためのループの記述をみていくことになりました。
私たちがExtMapBuffer1[]に割り当てた値はすべて、チャートに描かれます(なぜなら私たちはこの配列をSetIndexBuffer関数によって描かれるバッファーに割り当てたからです)

ループを記述する前に、私たちはループが行われるべき回数をチャート上のすべてのバーの総数からcounted_barsを引くことによって算出しなくてはなりません。
ループが実行されるべき回数のことをLoop変数とよび、今回の私たちの例ではpos変数と名付けています。

私たちはloop変数を算出された最新のバーとして使用しています。たとえばHigh[pos]はposバーの中での高値が返されるでしょう。

ループ本体では、dHigh変数にわりあてた最新のループ変数の高値をわりあてます。

また、dLow変数には最新のループ変数の安値をわりあてています。
dHighからdLowを引いた結果がdResult変数に割り当てられます。

それから、dResultを描画するバッファーの配列であるExtMapBuffer1[]に割り当てることでインディケーターラインを描きます。

ループの最後の行はデクレメント式で、ループ変数であるposからループが機能するたびに1をひきます。そしてこの変数が-1に達したら、このループは終了されます。
____________________________________________________________________

最後に私たちはインディケーターをコンパイルすることができます。F5をおすか、fileメニューのCompileを選択してください。
そうすると実行可能なファイルである"My_First_indicator.ex4"を発生させます。そしてそれはあなたのterminal clientから読み込むことができます。

インディケーターを読み込むために、まずF4をクリックしてterminal clientを呼び出してください。それから、NavigatorウィンドウでMy_First_indivatorを見つけて、それをチャートに取り付けてください。(図4参照)

メモ:このインディケーターはあまり使えないかもしれません。しかし、最高値と最安値の差はマーケットのボラティリティを知る上で助けになります。
図4
図4 My_First_Indicator

初めてのインディケーターは楽しんでいただけたでしょうか。また、次回は初めてのエキスパートアドバイザーを講義でとりあげるので準備をしておいてください。


Coders'Guru

今回もお疲れ様でした。 これでインディケーター作成に関する基礎知識は備わったと思いますので、書籍メタトレーダー入門を読むとより深い理解ができると思います。


今回も最後まで読んでくださいましてありがとうございました。



押していただけると大変嬉しいです。よろしくお願いします。手間のかからないようにクリックしても別窓で表示されるようにしてみました。
人気ブログランキングへ



theme : FXでシステムトレード
genre : 株式・投資・マネー

2009-03-23

メタトレーダー講義 補講1 Bars

ここではバーチャートとしての説明がされていますが、バーをローソク足と置き換えて考えられても何も問題はないので、ローソク足をお使いの方は、ローソク足と自分の中で置き換えて考えて頂けると幸いです。

この文章はCodersGuruさんのMQL4Lesson4の訳文です。(翻訳しての転載に本人の許可はとってあります)                      
                     MQL4講座             
                     Coders'guru
                       www.forex-tsd.com   
                          -補講1-
                           バー

足の数え方にかんするたくさんの質問をいただきました。
今回の補講ではバーについてのみ取り上げていきたいと思います。

バーってなに?

バーはチャート上にでてくる図形で、期間の長さでバーを決めることができます。

例:30分の期間でしたら、30分ごとにバーが描かれていきます。

一本のバーの中に、高値、安値、始値、終値の情報が入っています。

MQL4ではどのようにバーはインデックス化されるの?

MQL4では、バーのインデックス化を(最新のローソク足)から始めて1,2,3....というふうに数えていきます。
もし最新のバーを利用したいのならインデックスはに。
(最新のローソク足の)一つ前のバーを利用したいならインデックスをに。
インデックスが100なら100個前のバーを利用することになります。
インデックスの最後の値は、チャート上のバーの総数の数になります。

MQL4 バー総数関数

MQL4では、バーの数と一緒に機能する種類の関数があります。

int Bars

この関数は最新のチャートでのバーの数を返します。

タイムフレーム(期間)を変えるとこの数字は変わってくることを覚えておいてください。

int iBars(string symbol int timeframe)

この関数は、バー特定の期間の通貨ペアの数を返します。
貴方が30分の期間で取引をしていて、1時間の期間と同じ数のーが欲しかったら次の文を使います。
____________________________________________________________________________________________
iBars(NULL,PERIOD_H1);
____________________________________________________________________________________________
メモ:もし以下のように記述したら
____________________________________________________________________________________________
iBars(NULL,0);
____________________________________________________________________________________________
これはBars関数と同じ数の返却値になります。
NULLは現在の通貨ペアを指定することになっています。

int IndicatorCounted()

インディケーターを書く時に、どのようにして自分の欲しい数のバーを得ることができるかはこれでわかりましたね。
この数を用いて計算し、ラインを描写させます。

しかし、もし以前にバーを数えたか、それとも数えるのがこれが初めてかということを知ることは役に立ちます。なぜなら、もし、以前にバーを数えたことがあるなら、それらを再び数えたくはありませんし、新しく増えたバーを数えるだけで良いからです。

このような時はIndicatorCounted()関数をつかいます。これはインディケーターによって数えられたバーの数を返します。

最インディケーターの最初の起動時にこの数はゼロを示します。なぜなら、インディケーターはまだ、何のバーも数えていないからです。
そのあと、バーの総数から1を引いたのと同じ数になります。なぜなら、最後のバーはまだ数えられていないからです。(図1参照)
図2
図1



バーになにが起きているかを示す小さなプログラムを記述してみましょう。
//+------------------------------------------------------------------+
//| my_first_indicator.mq4 |
//| Codersguru |
//| http://www.forex-tsd.com |
//+------------------------------------------------------------------+
#property copyright "Codersguru"
#property link "http://www.forex-tsd.com"
#property indicator_chart_window

//+------------------------------------------------------------------+
//| 初期化関数                                  |
//+------------------------------------------------------------------+
int init()
{

//---- indicators

//----
return(1);
}
//+------------------------------------------------------------------+
//|後処理関数                                     |
//+------------------------------------------------------------------+
int deinit()
{

//----

//----
return(0);
}
//+------------------------------------------------------------------+
//| 指標処理関数                                |
//+------------------------------------------------------------------+
int start()
{
  Alert (
"counted_bars=" , IndicatorCounted());//数えられたバーの総数
  Alert("Bars=", Bars); //チャート上のバーの総数
  Alert("iBars=",iBars(NULL,O));//配列で考えたチャート上のバーの総数
  Alert("First Bar Open=", Open[Bars-1]); //最初のバーの始値
  Alert("Last Bar Open=",Open[0]);//最新のバーの始値

return(0);
}
//+------------------------------------------------------------------+


このプログラムが図1の結果を生み出します。

バーの数え方についてわかりましたでしょうか。


それでは。
Coders'Guru

お疲れ様でした。一応補足ですが、図1で
上から8番目の counted_bars=0 になっていて、
上から4番目の counted_bars=15830 になっているのは
起動時(16:55:02)にインディケーターはまだバーを数えていないからです。
次の時(16:55:08)は数えられているのでチャート上のバーの数-1(最新のバーは抜かすので)である15830の値がでてきます。
FirstBarOpenでは、あなたが開いているチャートの一番左(たくさんスクロールしてこれ以上いけないところです。)の始値の値になります。


今回は以上になります。


押していただけると大変嬉しいです。よろしくお願いします!手間のかからないようにクリックしても別窓で表示されるようにしてみました。
人気ブログランキングへ



theme : FXでシステムトレード
genre : 株式・投資・マネー

2009-03-29

メタトレーダー講義第13回 初めてのエキスパートアドバイザー

この文章はCodersGuruさんのMQL4Lesson4の訳文です。(翻訳しての転載に本人の許可はとってあります)  
                             MQL4講座          
                             Coders'guru         
                              www.forex-tsd.com/                   
                                  -13-

前回の講義では、初めてのインディケーターを作成しました。そのインディケーターはトレーダーとしてはそんなに役立つものではありませんでしたが、プログラマーとしてはとても役立つものでした。

一般的にインディケーターはマーケットの将来の値段を予想するのを試みるテクニカル分析において大変重要なものです。
しかし、私たちはインディケーターと共にチャートを観察して、自分の手を使って売り買いをし、手動で注文を調整します。貴方は画面の前に座っていないといけませんし、目を凝らし続けなければなりません。

もし貴方が疲れたり、お茶を飲みたくなったり、まとまった休日を取るような時、貴方は今から上げていく解決策の一つを考えなければなりません。

貴方はチャートを見てくれる誰かを雇って、5分おきに相場で何が起きているか携帯に連絡させることをするかもしれません。もしこの雇った人がプロなら、費用は貴方が稼いだPipsを要求するでしょう。そしてもし雇った人が初心者なら、その費用は貴方の資本金を要求するでしょう。

二つ目の解決策は貴方のトレードを自動化するプログラムを使うことです。
これがエキスパートアドバイザの存在意義になります。

エキスパートアドバイザーはMQL4に記述されたプログラムで、貴方の好きなインディケーターを使い、あなたのトレード方法で注文を自動で行ってくれます。
エキスパートアドバイザーは貴方のために買い注文も、売り注文も、注文の修正も行わせることができます。貴方はこれでお茶を飲むことも、雇った人に渡す給料を節約することも、貴方のアシスタントである妻に花束を持っていくこともできるようになります。

今日は、初めてのエキスパートアドバイザーを作成していきます。さぁ始めましょう。

最初の二つのステップ

ステップ1

もし貴方がメタエディターをまだ開いていませんでしたら、起動させてください。
メタエディターのFileメニューからNewをクリックしてください。(CTRL+Nのホットキーを使うか、スタンダードツールバーのNewアイコンをクリックすることでも起動できます。) そうすると、初めてのインディケーターを作成した時にも見た新しいプログラム操作ガイドが出てきます。(図1)

今回は、"Expert Advisor program"の項目をクリックして、次へを押してください。
expertad.png
図1-ステップ1の操作ガイド

ステップ2


次へをクリックすると、general properties操作ガイドが出てきます(図2)
この操作ガイドはあなたのエキスパートアドバイザーの属性を指定することができ、そして貴方がエキスパートアドバイザーで使うexternal(外部)変数を指定することができます。

このステップでは、以下の属性を指定できます。

   1-エキスパートアドバイザーの名前。今回はMy_First_EAを使用します。
   2-プログラムの著者名。貴方の名前を入力してください(サンプルでは私の名前を使ってます)
   3-あなたのウェブサイトへのリンク
   4-External(外部)変数のリスト
 
   以下が貴方が自分で作ったエキスパートアドバイザーを、Expert propertyウィンドウか
   らユーザーが変更することを可能にさせる外部変数のリストです。
   新しい変数を加えたかったら、Add ボタンをクリックしてください。クリックすると、新しい外部変数
   リストが登録されます。すべてのリストは三つの設定値をもちます。

   Name:この設定値をダブルクリックすると変数の名前(識別子)を指定できます。
   Type:この設定値をダブルクリックすると、変数のデータタイプを指定できます。
   Initial value:この設定値をダブルクリックすると、その変数の初期値を与えることができます。
   この設定値は任意なもので、何も設定しないで次に行くこともできます。

   今回のサンプルでは、三つの設定値を加えます。

   Varaible→Type→initial value
   ________________________________________
   TakeProfit→double→240
   Lots→double→0.1
   TrailingStop→double→30

Wizars.png
図2-ステップ2の操作ガイド

それでは完了ボタンをクリックして操作ガイドを閉じてください。メタエディターは操作ガイドによって作られたコードを貴方に提供し、My_First_EA.mq4MetaTrader4/expertsパスの所に保存することになります。

メモ:エキスパートアドバイザーをMetaTrader4/expertsのパスに入れなくてはなりません。またインディケーターはMetaTrader4/experts/indicatorsのパスに入れてください。そうでなければ起動しません。

以下が操作ガイドから得られるコードです。

//+------------------------------------------------------------------+
//| My_First_EA.mq4                    |
//| Coders Guru                    |
//| http://www.forex-tsd.com                  |
//+------------------------------------------------------------------+

#property copyright "Coders Guru"
#property link "http://www.forex-tsd.com"

//---- input parameters
extern double TakeProfit=240.0;
extern double Lots=0.1;
extern double TralingStop=30.0;
//+------------------------------------------------------------------+
//| expert initialization function                    |
//+------------------------------------------------------------------+

int init()
{
//----

//----

return(0);
}
//+------------------------------------------------------------------+
//| expert deinitialization function                    |
//+------------------------------------------------------------------+

int deinit()
{
//----

//----

return(0);
}
//+------------------------------------------------------------------+
//| expert start function                    |
//+------------------------------------------------------------------+

int start()
{
//----

//----

return(0);
}
//+------------------------------------------------------------------+

上記をみればわかるように、操作ガイドによって生み出されたコードは直接主要な関数を入力する手間を省き、あなたがコードを付け加えることができるテンプレートです。

さぁコードを付け加えていきましょう。

//+------------------------------------------------------------------+
//| My_First_EA.mq4 |
//| Coders Guru |
//| http://www.forex-tsd.com |
//+------------------------------------------------------------------+

#property copyright "Coders Guru"
#property link "http://www.forex-tsd.com"

//---- 埋め込まれた設定値
extern double TakeProfit=250.0;
extern double Lots=0.1;
extern double TrailingStop=35.0;
//+------------------------------------------------------------------+
//| expert initialization function                    |
//+------------------------------------------------------------------+

int init()
{
//----

//----

return(0);
}
//+------------------------------------------------------------------+
//| expert deinitialization function                   |
//+------------------------------------------------------------------+

int deinit()
{
//----

//----
return(0);
}
int Crossed (double line1 , double line2)
  {
   static int last_direction = 0;
   static int current_direction = 0;

   if(line1>line2)current_direction=1; //アップ
   if(line12; //ダウン

   if(current_direction !=last_direction) //変化
   {
      last_direction = current_direction;
      return(last_direction);
   }
   else
   {
     return (0);
   }
 }
//+------------------------------------------------------------------+
//| expert start function                     |
//+------------------------------------------------------------------+

int start()
 {
 int cnt, ticket, total;
 double shortEma,longEma;

 if(Bars<100)
 {
  Print("bars less than 100");
  return(0);
 }
 if(TakeProfit<10)
 {
  Print("TakeProfit less than 10");
  return(0); //check TakeProfit
  }

 shortEma=iMA(NULL,0,8,0,MODE_EMA,PRICE_CLOSE,0);
 longEma=iMA(NULL,0,13,0,MODE_EMA,PRICE_CLOSE,0);

 int isCrossed = Crossed(shortEma,longEma);

 total = OrdersTotal();
 if(total < 1)
  {
  if (isCrossed == 1)
   {
ticket=OrderSend(Symbol(),OP_BUY,Lots,Ask,3,0,Ask+TakeProfit*Point,
"My EA",12345,0,Green);
     if(ticket>0)
     {
     if(OrderSelect(ticket,SELECT_BY_TICKET,MODE_TRADES))
Print("BUY order operand : ",OrderOpenPrice());
     }
    else Print("Error opening BUY order : ",GetLastError());
     return(0);
     }
    if(isCrossed == 2)
    {

     ticket=OrderSend(Symbol(),OP_SELL,Lots,Bid,3,0,
     Bid-TakeProfit*Point,"My EA",12345,0,Red);
      if(ticket>0)
        {
        if(OrderSelect(ticket,SELECT_BY_TICKET,MODE_TRADES))
      Print("SELL order opened ; ",OrderOpenPrice());
        }
      else Print("Error opening Sell order : ",GetLastError());
       return(0);
       }
       return(0);
    }
     for(cnt=0;cnt<total;cnt++)
     {
     OrderSelect(cnt,SELECT_BY_POS,MODE_TRADES);
     if(OrderType()<=OP_SELL && OrderSymbol()==Symbol())
    {
    if(OrderType()==OP_BUY) //ロングポジションでエントリー
    {
    //手仕舞うか?
   if(isCrossed ==2)
      {
         OrderClose(OrderTicket(),OrderLots(),Ask,3,Violet);
  //手仕舞い
     return(0); //次へ
      }
    if(TrailingStop>0)
     {
     if(Bid-OrderOpenPrice()>Point*TrailingStop)
       {
       if(OrderStopLoss()<Bid-Point*TrailingStop)
        {
         OrderModify(OrderTicket(),OrderOpenPrice(),Bid-
          Point*TrailingStop,OrderTakeProfit(),0,Green);
         return(0);
         }
        }
       }
      }
     else//ショートポジションへ
      {
     //手仕舞うべきか
      if(isCrossed ==1)
      {
      OrderClose(OrderTicket(),OrderLots(),Ask,3,Violet);
  //手仕舞い
     return(0); //決済
      }
     //トレイリングストップのチェック
      if(TrailingStop>0)
       {
        if((OrderOpenPrice()-Ask)>(Point*TrailingStop))
        {
         if((OrderStopLoss()>(Ask+Point*TrailingStop)) ||
      (OrderStopLoss()==0))
             {

    OrderModify(OrderTicket(),OrderOpenPrice(),Ask+Point*TrailingStop,
     OrderTakeProfit(),0,Red);
            return(0);
             }
            }
           }
          }
         }
       }
 return(0);
 }
//+------------------------------------------------------------------+

メモ:コピー&ペーストはなさらないでください。メタエディターが停止してしまいます。コード文はファイルとしてありますので、必要な方はこちらの方からダウンロードしてください(無料登録する必要があります。)

怖い?

上述の160行の文に恐れないでください。私たちは一行一行のすべてのコードの意味を理解することができるようになります。これは簡単な課題であるということを約束します。

エキスパートアドバイザーを試してみよう。

エキスパートアドバイザーのコードを勉強する前に、これは利益を出せるものなのかどうか確認してみましょう。

メモ:このエキスパードアドバイザーはEURUSD4時間足で試してください。
それではF5を押してコンパイルをし、メタトレーダーを起動させましょう。

エキスパートアドバイザーは二つの方法でテストすることができます。

1-自動売買

自動売買では結果がより正確に出ますが、そのエキスパートアドバイザーが利益を出すかどうかを知るには数日(もしくは数カ月)かかります。

エキスパートアドバイザーが自動でトレードをできるように設定しなければなりません。
それを可能にするために、Tools→オプションをクリック(もしくはCTRL+Oのホットキーを使用)してください。そうするとオプションウィンドウが現れるはずです(図3)Expert Advisorsタブをクリックして以下のオプションを可能に設定してください。

Enable Expert Advisors
Allow Live trading

そしてOKをクリックしてください。
おぷと
図3-自動売買が可能になるように設定

次に、Navigatorタブ→ExpertAdvisorをクリックし、My_First_EAをダブルクリックしてください。そうするとエキスパートアドバイザーの名前の隣にスマイルのマークが表示されると思います。これは、エキスパートアドバイザーが働いており、トレードする用意ができていることをしめすマークです。
KIIRo.png
図4-エキスパートアドバイザーが自動売買モードになっています。

2-ストラテジーテスター
二番目のエキスパートアドバイザーのテスト方法は少し精度が落ちるかもしれませんが、時間をとりません。この方法がストラテジーテスターです。ストラテジーテスターについては、そのうち全て分かるようになります。Strategy Testerのタブからストラテジーテスターを起動させましょう。(図5)
ウィンドウが開いたら、以下の設定に変更してください。

Symbol:EURUSD(4hours)
Period:H4(4Hours)
Model:Open price only
これ
図5-ストラテジーテスターウィンドウ

さぁスタートボタンをクリックしてエキスパートアドバイザーをテストしてみましょう。

現在進行形のバー(ローソク足)と、二つのタブ(セッティングと操作履歴)から5つのタブになったことが確認できると思います。私たちが最も興味深いところはレポートです(図6)クリックして損益を確認してみましょう。
kekka.png
図6-ストラテジーテスターの検証結果

次の講義ではたくさんの説明ややることがあります。挑戦する準備は整いましたでしょうか。


それでは。


Coder'sGuru




本日もお疲れ様でした。コードの記述が大変でしたね!僕はコンパイルに失敗しまくりました(笑)それでも自動売買モードが動くとなんだか嬉しくなってきませんか?
皆さんの自動売買のきっかけになってくれたら幸いです。

本日も訪問頂き大変ありがとうございました。


押していただけると凄く励みになります。よろしくお願いします。
人気ブログランキングへ

theme : FXでシステムトレード
genre : 株式・投資・マネー

2009-03-31

MQL4講義 第14回 初めてのエキスパートアドバイザー第2部

皆さんおはようございます。FXboyです。
今回のコード文ですが、赤で表示した文が今までちゃんと表示されていなく、
わけわからないコードになっておりました。

時々「>」を書いた間近のコード文が管理画面の文章を書くところでは書いていても
ブログには表示されないというケースが存在します。
そういう時は仕方なくコードで>の代わりに>で書いたりしていますのでご了承ください。

今回ご指摘頂くことで修正箇所が見つかり大変ありがたく思っております。
もし何かおかしいな。っていうところがございましたら僕のミスであることがほとんどだと
思いますのでこれからもご指摘、ご教授頂けると嬉しいです。

コード文にミスがあったことで、プログラムがしっかり動かずお手間を取らせてしまった方が結構いらっしゃると思います。大変申し訳なく思っています。本当に失礼いたしました。ミスをなくすように努力しますので今後ともよろしくお願い致します。




この文章はCodersGuruさんのMQL4Lesson4の訳文です。(翻訳しての転載に本人の許可はとってあります)     
                         MQL4講座  
                         Coders'guru   
                           www.forex-tsd.com
                               -13-
                       初めてのエキスパートアドバイザー
                           第2部


初めてのエキスパートアドバイザー作成の第二回目の講義によくいらっしゃいました。
今回は、前回作られた操作ガイドによって作りだされたコードと、私たちが付け加えたコードを一行ずつ見ていくことにします。

コードを分析する用意はいいですか?さぁ始めましょう。

メモ:繰り返しますが、前回のエキスパートアドバイザーは教育のサンプルとして取り上げたもので、利益を追求するものではありません。

私たちのコード


//+------------------------------------------------------------------+
//| My_First_EA.mq4 |
//| Coders Guru |
//| http://www.forex-tsd.com |
//+------------------------------------------------------------------+

#property copyright "Coders Guru"
#property link "http://www.forex-tsd.com"

//---- 埋め込まれた設定値
extern double TakeProfit=250.0;
extern double Lots=0.1;
extern double TrailingStop=35.0;
//+------------------------------------------------------------------+
//| expert initialization function                    |
//+------------------------------------------------------------------+

int init()
{
//----

//----

return(0);
}
//+------------------------------------------------------------------+
//| expert deinitialization function                   |
//+------------------------------------------------------------------+

int deinit()
{
//----

//----
return(0);
}
int Crossed (double line1 , double line2)
  {
   static int last_direction = 0;
   static int current_direction = 0;

   if(line1>line2)current_direction=1; //アップ
   if(line1<line2)current_direction=2; //ダウン

   if(current_direction !=last_direction) //変化
   {
      last_direction = current_direction;
      return(last_direction);
   }
   else
   {
     return (0);
   }
 }
//+------------------------------------------------------------------+
//| expert start function                     |
//+------------------------------------------------------------------+

int start()
 {
 int cnt, ticket, total;
 double shortEma,longEma;

 if(Bars<100)
 {
  Print("bars less than 100");
  return(0);
 }
 if(TakeProfit<10)
 {
  Print("TakeProfit less than 10");
  return(0); //check TakeProfit
  }

 shortEma=iMA(NULL,0,8,0,MODE_EMA,PRICE_CLOSE,0);
 longEma=iMA(NULL,0,13,0,MODE_EMA,PRICE_CLOSE,0);

 int isCrossed = Crossed(shortEma,longEma);

 total = OrdersTotal();
 if(total < 1)
  {
  if (isCrossed == 1)
   {
ticket=OrderSend(Symbol(),OP_BUY,Lots,Ask,3,0,Ask+TakeProfit*Point,
"My EA",12345,0,Green);
     if(ticket>0)
     {
     if(OrderSelect(ticket,SELECT_BY_TICKET,MODE_TRADES))
Print("BUY order operand : ",OrderOpenPrice());
     }
    else Print("Error opening BUY order : ",GetLastError());
     return(0);
     }
    if(isCrossed == 2)
    {

     ticket=OrderSend(Symbol(),OP_SELL,Lots,Bid,3,0,
     Bid-TakeProfit*Point,"My EA",12345,0,Red);
      if(ticket>0)
        {
        if(OrderSelect(ticket,SELECT_BY_TICKET,MODE_TRADES))
      Print("SELL order opened ; ",OrderOpenPrice());
        }
      else Print("Error opening Sell order : ",GetLastError());
       return(0);
       }
       return(0);
    }
     for(cnt=0;cnt<total;cnt++)
     {
     OrderSelect(cnt,SELECT_BY_POS,MODE_TRADES);
     if(OrderType()<=OP_SELL && OrderSymbol()==Symbol())
    {
    if(OrderType()==OP_BUY) //ロングポジションでエントリー
    {
    //手仕舞うか?
     if(isCrossed ==2)
      {
         OrderClose(OrderTicket(),OrderLots(),Ask,3,Violet);
  //手仕舞い
     return(0); //次へ
      }
    if(TrailingStop>0)
     {
     if(Bid-OrderOpenPrice()>Point*TrailingStop)
       {
       if(OrderStopLoss()<Bid-Point*TrailingStop)
        {
         OrderModify(OrderTicket(),OrderOpenPrice(),Bid-
          Point*TrailingStop,OrderTakeProfit(),0,Green);
         return(0);
         }
        }
       }
      }
     else//ショートポジションへ
      {
     //手仕舞うべきか
      if(isCrossed ==1)
      {
      OrderClose(OrderTicket(),OrderLots(),Ask,3,Violet);
  //手仕舞い
     return(0); //決済
      }
     //トレイリングストップのチェック
      if(TrailingStop>0)
       {
        if((OrderOpenPrice()-Ask)>(Point*TrailingStop))
        {
         if((OrderStopLoss()>(Ask+Point*TrailingStop)) ||
      (OrderStopLoss()==0))
             {

    OrderModify(OrderTicket(),OrderOpenPrice(),Ask+Point*TrailingStop,
     OrderTakeProfit(),0,Red);
            return(0);
             }
            }
           }
          }
         }
       }
 return(0);
 }
//+------------------------------------------------------------------+

____________________________________________________________________
私たちのエキスパートアドバイザーの背後にあるアイディア

コードの解説に掘り下げていく前に、まず、私たちのエキスパートアドバイザーはどのようなアイディアで作られたものなのかを説明して行きたいと思います。どのエキスパートアドバイザーも、いつマーケットにエントリー注文をだして、いつイグジットするかを決めなくてはなりません。
エキスパートアドバイザーの背後にあるアイディアは、どのような状況の時にエントリーして、イグジットするかになります。私たちのエキスパートアドバイザーの後ろにあるアイディアはとても単純なものです。さぁ見ていきましょう。

私たちは二つの指数加重移動平均線を使っています。最初のEMA(指数加重移動平均線)は8日(短期EMA)のもので、二つ目のEMA(指数加重移動平均線)は13日(長期EMA)です。

メモ:これらの指数加重移動平均線を使うことや、その他の考えは、ただ講義を目的として使用しているもので、私がお勧めするものではありません。

エントリー(参入);

私たちのエキスパートアドバイザーがマーケットにエントリーする時は、短期EMA長期EMAとクロスした時になります。二つの線の方向が注文の種類を決定することになります。
もし短期EMA長期EMAにあれば買い注文(ロング)で入ります。
もし短期EMA長期EMAにあれば売り注文(ショート)で入ります。
常に買いか売りかの一つの注文が入ります。

エクジット(手仕舞い);

初めてのエキスパートアドバイザーは、買い注文でエントリーした時は短期EMA長期EMAを交差し、かつ短期EMA長期EMAにある時に手仕舞います。
また売り注文でエントリーした時は短期EMA長期EMAを交差し、かつ短期EMA長期EMAの上にある時に手仕舞います。

私たちの注文(買いでも売りでも)はTakeProfit,TrailingStopのポイントに達した時も自動で手仕舞われることになります。

修正

マーケットへのエントリーにエクジットに加えて、エキスパートアドバイザーにはトレイリングストップの概念でエクジットの値を変更し続けることができるという特質があります。

さぁ、私たちのコードを解読していきましょう。
____________________________________________________________________________________________
//---- input parameters
extern double TakeProfit=250.0;
extern double Lots=0.1;
extern double TrailingStop=35.0;

上記のコードは操作ガイドに三つの(extern)外部変数として宣言してくれと頼んだものです。(外部変数の値はユーザーがエキスパートアドバイザーのpropertyウィンドウで変更することができます)
三つの変数のデータタイプはdoubelです。私たちは初期設定値を決め初期化しました(ユーザーは三つの変数の値をpropertyウィンドウで変更することができますが、初期設定値のままにしていくことを推奨されています)

ここで三つの変数についての解説をするために立ち止まりましょう

ストップロス

これは注文が手仕舞われる時を貴方が指定する限界値です。これはマーケットが逆行した時の損失の最小化に対して役立ちます。
ストップロスの値は買い注文の時は常に通貨の売り値の下、売り注文の時は常に通貨の買値の上に設定されます。

TrailingStop

トレイリングストップは一定の水準の下(買い注文時)もしくは上(売り注文時)の値に置かれる種類のストップロスオーダーです。この値は変動値として調整されます。
この大変重要な概念についてはこの講義の後で取り上げていこうと思います。

TakeProfit

これは注文が手仕舞われる時を貴方が指定する限界値であるという点でストップロスと似ています。

しかし、二つの相違点があります。

   ・値を追っかけていかないこと。
   ・エクジットの値は通貨の値の下に置く代わりに上に置かなければならないこと(買い注文時)。

zu1.png
図1-ストップロス(逆指値注文)とTake profit(指値注文)
____________________________________________________________________
int Crossed (double line1 , double line2)
  {
   static int last_direction = 0;
   static int current_direction = 0;

   if(line1>line2)current_direction=1; //アップ
   if(line12; //ダウン

   if(current_direction !=last_direction) //変化
   {
      last_direction = current_direction;
      return(last_direction);
   }
   else
   {
     return (0);
   }
 }

以前にお話ししたように、私たちのエキスパートアドバイザーの背後にあるアイディアは短期EMAと長期EMAが交差するのを監視しています。そして交差する方向性を得ること(どちらのEMAが上もしくは下にあるか)で、注文の種類(売りエントリー、買いエントリー、買い手仕舞い、売り手仕舞い)が決定されます。

この目標を達成するために私たちはCrossed関数を作り出します。

Crossed関数は二つのdoubleの値を設定値として持ち、integerの値を返却値として返します。
最初の設定値は監視して欲しいと思う一つ目のラインの値(私たちの場合は短期EMAになります)になり、二つ目の設定値は二つ目の監視してほしいラインの値(長期EMA)になります。

Crossed関数は、二つのラインをCrossed関数が呼び出される度にその二つのラインの状態を記憶するstatic変数の方向を保存することによって監視します。

 ・最新の方向が保存された時に何も変わらなければの値を返します。
 ・方向が変化(ラインが交差)し、かつ最初のラインが二つ目のラインの上にある時はを返します。
 ・方向が変化(ラインが交差)し、かつ最初のラインが二つ目のラインの下にある時はを返します。

メモ:この関数は、いずれ貴方が自分でコードを書いていく時に、どのような二つのラインでも監視することができ、クロスすることを知らせてくれます。

どのように書いたか見ていきましょう。

int Crossed (double line1 , double line2)

上記のコードは関数の宣言です。設定値はdoubleのデータタイプと定め、返却値にはintegerタイプを返すCrossed関数を作り出したいというものです。

この関数を呼び出すとき、貴方は二つのdoubleの設定値を受け渡さなければなりません、そしてそれはintegerタイプの返却値として戻ってくることになります。

Crossed関数を使う前に宣言をしなければなりません。その関数を宣言する場所はどこでも構いません。私はstart()関数の上に置きましたが、それ以外のどの場所からでも宣言することができます。

static int last_direction = 0;
static int current_direction = 0;

ここでは私たちは二つのラインの動向と、最新の方向の値を保持するintegetタイプの二つのstatic変数を宣言しました。私たちはこれらのstatic変数(何回も呼び出されている間もその値を保存する特質をもつ変数)を使ってラインの方向が変化したかどうかをチェックしていきます。

私たちは0を初期値として初期化しました。なぜなら初めて関数を呼び出すときに働いてほしくないからです。(もしCrossed関数が最初の呼び出しで働くようにしたら、エキスパートアドバイザーが私たちがメタトレーダを開くと同時にエントリー注文をすることになってしまいます。)

if(current_direction !=last_direction)//変化

この行は、二つのstatic変数を、一つ前の関数の呼び出しと、現在の呼び出しとの間で変化があるかをチェックすることで比べるものです。
もしlast_directionとcurrent_directionの値が等しくなければ、方向は変化したということを意味します。

last direction = current direction;
return (last_direction);

そしてlast_directionとcurrent_directionが等しくない場合、last_directionの値をcurrent_directionの値を割りあてて変更しなければなりません。
そしてlast_directionの値を返却値として返します。この値はもし最初のラインが二つ目のラインの上にあればを返し、最初のラインが二つ目のラインの下にあればを返します。

else
  {
    return(0);
  }

もしそうでなければ(last_directionとcurrent_directionの値が等しいのならば)、ラインの動向は変わってないことになり、0の値を返却値として返します。

私たちのプログラムはこの関数をstart()関数の本体で呼び出し、返却値をそれに対応する適切な行動を決定するために使います。

次の講義ではどうやって関数を呼び出すのか、大変重要なtrading関数について私たちは知ることになります。

それでは。
Coders'Guru



本日もお疲れ様でした。
何か質問がありましたら聞いて下さいね。




押していただけると凄い励みになりますのでよろしくお願いします。 
人気ブログランキングへ


theme : FXでシステムトレード
genre : 株式・投資・マネー

2009-04-01

メタトレーダー補講第2回 トレーディング関数

今回は補講第2回ということで、トレーディング関数を扱います。

今までの記事の中で最も分量が多く、訳すのが疲れました。。(笑)

ですので読むのも結構大変だと思いますが、最初の3つ程のトレーディング関数の説明を読んでしまえば、後はほとんど同じパターンのトレーディング関数の記述になっていくので、そんなに難しくはないと思います。

記述はすべて、
関数名
シンタックス(データタイプ)
関数の解説
関数の取る設定値
例文
で行われており、必要に応じてメモが入る構成になっています。

それでは、今回もよろしくお願いします。

この文章はCodersGuruさんのMQL4Lesson4の訳文です。(翻訳しての転載に本人の許可はとってあります)                      
                     MQL4講座             
                     Coders'guru
                       www.forex-tsd.com   
                          -補講2-
                   トレーディング関数

今回の補講では、MQL4の25個のトレーディング関数の解説を行います。
私は初めてのエキスパートアドバイザー第3部の講義の前にこの補講を行うことに決めました。なぜなら、残りのコードを解読していく前に、これらの重要な関数を知ることが必要だからです。
____________________________________________________________________

OrderSend:

シンタックス:
int OrderSend(string symbol, int cmd, double volume, double price, int slippage, double stoploss,double, double takeprofit, string comment=NULL,int magic=0, detetime expriation=0,color allow_color=CLR_NONE)

敢えて日本語に訳すなら

注文執行(通貨ペア,売買執行種類(売り、買い、エントリー、エクジッド、指値等),Lot数,エントリ―時の価格,許容スリッページ,ストップロスの値,手仕舞いの指値の値,注文時のコメント,オーダー識別番号,手仕舞い時間,エントリー時のマークの色)

解説
このOrderSend関数は売り/買いのオープンオーダー(指定した値段になると実行される注文)か、決済注文に指定のために使います。

もしその注文が成功すれば注文番号が返却値として返され、失敗すればー1が返されます。
GetLastError関数を使ってより詳しいエラーの原因を知ることができます。

  メモ:注文番号はOrderSend関数によって返される固有の数字です。この関数
  は後で新規あるいは決済注文のリファレンスとして使うことができます。(たとえばOrderClose関
  数と注文番号を使用して、特定の注文を手仕舞うことができます)

  メモ:GetLastError関数は、あるコードが実行された後に最後に起こったエラー
  に対応する予約された数字が返されます。(例えばOrderSendが実行されたあとにGerLastError
  関数が呼び出され時、OrderSendが実行している間に起きたエラーナンバーが表示されます)

  GetLastEllorが呼び出されると、一つ前のエラーナンバーは0にリセットされます。

  stderror.mqhファイルにMQL4のエラーナンバーのすべてのリストが書かれていますのでよろしけ
  ればご覧ください。
  また特定のエラーナンバーに対するエラーの解説をstdlib.mqhファイルに定義されたErrorDescripti
  on関数を使うことによって得ることもできます。(どちらもexperts/includeフォルダの中に入ってま
  す)

設定値
OrderSend関数は設定値を11個持ちます。

string symbol
symbolとは貴方の取引する通貨ペアの名称のことです(例EURUSD USDJPY等)

  メモ:現在使用している通貨ペアを得るためにはSymbol()関数を使い、OrderS
  elecy()関数によって指定された、現在指定されている通貨ペアを得るためにはOrderSymbol関数
  を使用します。

int cmd;
貴方がどのような売買執行をしたいのかを指し示す整数値の数値です。以下の値がとれます。

定数            値       解説
OP_BUY          0        買いポジション  
OP_SELL          1        売りポジション
OP_BUYLIMIT       2        指値で買う
OP_SELLLIMIT      3        指値で売る
OP_BUYSTOP       4        逆指値で買う
OP_SELLSTOP      5        逆指値で売る

  メモ:整数値を定数値の代わりに式として使うことも可能です。
  例えば
  OrderSend(Symbol(),0,......)はOrderSend(Symbol(),OP_BUY....)と書くのと等しいです。
  しかし、コードを分かりやすい状態にするために、定数名で記述することをお勧めします。

double volume
貴方がトレードさせたいと思うロット数

double price:
ここでは価格の値段がいくらの時に売買を実行するかを指定します。
最新の買値や売値(bid ask)のデータを得るためにはBid関数もしくはASK関数を使います。

int slippage:
貴方が注文の際に定める許容スリッページの値。

  メモ:スリッページとは算出取引価格と実際の執行価格との間に生まれた差で
  す。
  スリッページは普通スプレッドの変化によるものと考えられています。

double stoploss:
損失を含んだときに手仕舞おうと思う値段。(逆指値手仕舞いの値段)

double takeprofit:
含み益の際に手仕舞おうと思っている値段。(逆指値手仕舞いの値段)

string comment:
指定したテキストのコメントを、貴方が注文した時に表示することができます。(図1参照)
初期値は、注文に対して何もコメントを割り振りませんという意味のNULLが設定されています。

  メモ:初期値が指定されている場合、貴方はコード文を記述しなくても大丈夫と
  いう意味です。何も記述しなければ、MQL4は初期値が設定されているものとして読み込みます。
  つまり、コメントを挿入するのであれば
  OrderSend(Symbol(),OP_BUY,Ask 3,ask-25*Point,Ask+25*Point,"My order comment",12345,
  0,Green);
  逆にしないのであれば
  OrderSend(Symbol(),OP_BUY,Ask 3,ask-25*Point,Ask+25*Poin
  t,12345
,0,Green);
  と記述するわけです。(赤で囲ったAsk+25*Point,12345の間に、順序的にコメントが入るわけです
  が、コメントを挿入する気がないのならば記述しなくていいわけです。そこにはNULLが初期値なの
  で自動的に挿入されたとしてMQL4は考えます)

int magic:
注文に対して割り振ったマジックナンバー

  メモ:マジックナンバーとは、貴方に注文の違いを区別できるようにさせるリファ
  レンスとして、注文に対して割り振った数字です。例えば貴方がエキスパートアドバイザーによって
  行ったオープン注文(指定した値段になると実行される注文)と、貴方が手動で行ったオープン注
  文等が例に挙げられます。

detetime expiration
貴方の未決の注文の有効期限がいつ切れるかを決めるものです。
初期値はで、これは有効期限等は無いことを示します。

  メモ:ここでいう時間とは、サーバーの時間で、日本時間ではありません。現在
  のサーバーの時間を得るためにはCurTime関数を使用し、日本時間(ローカル時間)を得たいなら
  LocalTime関数を使用します。

color arrow_color;
エントリー注文の時のマークの色の設定(図2)で、初期値はCLR_NONEです。意味は、チャート上にマークを何も描かない です。



int ticket;
if(iRSI(NULL,0,14,PRICE_CLOSE,0)<25)
{
ticket=OrderSend( (Symbol(),OP_BUY,Ask,3,ask-25*Point,Ask+25*Point,"Myorder#2,16384,0,Green);
  if(ticket<0)
   {
   Print("OrderSend failed with error#"GetLastError());
   return(0)
   }
  }
____________________________________________________________________
OrderModify

シンタックス
bool OrderModify(int ticket,double price,double stoploss,double takeprofit,datetime expiration,color arrow_color=CLR_NONE)

真か偽か 注文調整(注文番号, いくらで注文するか, ストップロスはいくらか, いくら益がでたら決済するか,タイムリミットはいつか,マークの色 )  

解説
OrderModify関数は、特定の注文もしくはまだ執行されていない注文の特性を変更し、新しい値に置き換えて、関数に受け渡すという働きをします。
もしも注文が変更するのに成功したらばtrueの値を返し、失敗すればfalseの値が返されます。
GetLastError関数を使うことによって、より詳細なエラーの原因がわかります。

設定値
設定値は6つあります。

int ticket:
貴方が調整(変更)したいチケット番号(注文番号)です。

  メモ:この数はOrderSend関数によって既に注文に割り当てられています。
  OrderTicket関数を使うことで、現在の注文のチケット番号を取得できます。

double price:
注文する時に指定する値段です。

  メモ:OrderOpenPrice関数を使うことで現在の注文のオープン価格(オープン
  注文で指定した価格)を取得できます。

double stoploss
損失が出た時に手仕舞おうと思っている値段です(逆指値決済の値です)

double takeprofit;
利益が出た時に手仕舞おう(指値決済の値です)

  メモ:OrderModify関数は、stoplossとtakeprofitの値を変えるために使われる
  ことが一般的です。これはトレイリングストップと呼ばれています。

detatime expiration:
未決の注文を何時に無効にするか。
特に時間を指定したくない時はを使ってください。

color arrow_color
マークの色。初期値の色はCLR_NONEで、何もマークをチャートに描かないことを表しています。



if(TrailingStop>0)
 {
 SelectOrder(12345,SELECT_BY_TICKET);
 if(BID-OrderOpenPrice()>Point*TrailingStop)
  {
   if(OrderStopLoss()     {
      OrderModify(OrderTicket(),Ask-10*Point,Ask-35*Point,OrderTakeProfit(),0,Blue);
      return(0);
     }
    }
   }
____________________________________________________________________
OrderClose

シンタックス
bool OrderClose(int ticket,double lots,double price,int slippage,color=CLR_NONE)


解説

OrderClose関数は特定の約定注文を(そのチケット番号を使って)手仕舞う時に使います。
もし注文の手仕舞いが行われればtrueを返し、行われなければfalseの値を返します。
GetLastError関数を使うことで、エラーの詳細を取得できます。

設定値
この関数は5つの設定値を持ちます。

int ticket:
貴方が手仕舞いおうとする注文のチケット番号です。

double lots:
貴方が手仕舞おうとするロット数です。

  メモ:OrderLots関数を使うことで、現在の注文のロット数を取得できます。

double price:
対象の注文を手仕舞う時に指定する値段です。
Bid関数やAsk関数を使うことで現在の買値、売値を取得できます。

int slippage:
注文のスリッページ許容値です。

color Color:
手仕舞い時のマークの色です。初期値はCLR_NONEであり、チャートにマークは描かれないことを意味しています。



if(iRSI(NULL,0,14,PRICE CLOSE,0)>75)
  {
  OrderClose(order id,1,Ask,3,Red);
  return(0);
  }
____________________________________________________________________
OrderSelect

シンタックス
bool OrderSelect(int index,int select,int pool=MODE_TRADES)

解説
OrderSelect関数は、新規注文もしくは未決済注文を、チケット番号又はインデックスによって選択する働きを持ちます。
もしも注文の選択に成功したらtrueの値を返し、失敗したらtrueの値を返します。
GetLastError関数を使うことでエラーの詳細を取得できます。

  メモ:設定値をとらないトレーディング関数の前には、OrderSelect関数を使わ
  なければなりません。
  OrderMagicNumber, OrderClosePrice, OrderCloseTime, OrderOpenPrice, OrderOpen,Time,
  OrderComment,OrderCommission, OrderExpiration, OrderLots, OrderPrint, OrderProfit,
  OrderStoploss,OrderSwap,OrderSymbol,OrderTakeProfit,OrderTicket, OrderType

設定値:
この関数はつの設定値を持ちます。

int index
貴方が選択したい注文のインデックスもしくはチケット番号。どちらにするかは次の設定値(select)次第です。

int select:
選択を実行するタイプ(インデックスか、注文番号か)
以下の二つの値のどちらかを取ります。
SELECT_BY_POS:注文の位置(インデックス)を使用します。
SELECT_BY_TICKET:注文のチケット番号を使用します。

int pool:
もしSELECT_BY_POSの選択タイプを使ったなら、どこの情報源から選択するかを決定しなくてはなりません。

MODE_TRADES:現在の注文から選択(エントリー注文、未決済注文用)これが初期設定値になります。
MODE_HISTORY:履歴から選択(手仕舞い注文、注文取り消し用)



if(OrderSelect(12470,SELECT BY TICKET)=true)
  {
  Print("order#12370 open price is",OrderOpenPrice());
  Print("order#12470 close price is ",OrderClosePrice());
  }
  else
   Print("OrderSelect failed error code is",GetLastError());
____________________________________________________________________
OrderDelete:

シンタックス
bool OrderDelete(int ticket)

解説
OrderDelete関数はまだ執行されていない注文を削除する時に使われます。
もし注文が正常に削除されたのならtrueの値を返し、失敗したらfalseの値を返します。
GetLastError関数を使うと、エラーの詳細が取得できます。

設定値

この関数は1つの設定値のみ持ちます。

int ticket
貴方が削除したい注文のチケット番号です。



if(Ask>var1)
  {
  OrderDelete(order_ticket);
  return(0);
  }

____________________________________________________________________
OrderCloseBy:

シンタックス
bool OrderCloseBy(int ticket,int opposite, color Color=CLR_NONE)

解説
OrderCloseBy関数は、特定の注文を反対売買を行うことによって手仕舞う時につかう関数です。
もし成功したらtrueの値を返し、失敗したらfalseの値を返します。
GetLastError関数を使えば、エラーに関する詳細を取得することができます。

設定値
この関数は3つの設定値を持ちます。

int ticket
貴方が手仕舞いたい注文のチケット番号です。

int opposite
貴方が反対方向でエントリーしようと思う注文のチケット番号です

color Color:
手仕舞いマークの色です。初期設定値はCLR_NONEで、マークをチャート場に描かないことを意味します。


if(RSI(NULL,0,14,PRICE_CLOSE,0)>75)
 {
 OrderCloseBy(order id,opposite id);
 return(0);
 }

____________________________________________________________________
OrderType
シンタックス
int OrderType()

解説
OrderType関数は、返却値として選択された注文の種類を返します。具体的にはOrderSend関数であるOP_BUY,OP_SELL,OP_BUYLIMIT,OP_SELLLIMIT,OP_BUYSTOP,OP_SELLSTOPのうちのどれかです。

設定値
この関数には設定値がありません。ただ整数値の選択された注文のデータタイプを返すだけです。
(返された整数値が0ならばOP_BUYが返されます。詳しくはOrderSend関数をご覧ください。)



int order_type;
 if(OrderSelect(12,SELECT_BY_POS)==true)
  {
  order_type=OrderType();
  }
  else
  Print("OrderSelect()returned error-",GetLastError());
____________________________________________________________________
History Total:

シンタックス
int HistoryTotal()

解説
HistoryTotal関数はメタトレーダーターミナルから読み込まれた口座の履歴を検索し、手仕舞い注文の数を返す。

  メモ:普通この関数はOrderSelect関数と一緒に使用し、履歴の中から特定の
  注文情報を取得します。

設定値

この関数はなんの設定値も持ちません。ただ整数値(履歴の中の手仕舞い注文の総数)を返します。
GetLastError関数を使うことでエラーの詳細の情報を取得することができます。



//取引履歴から情報を回収する行動を取る
  int i,hstTotal=HistoryTotal();
  for(i=0;i  {
  //---選択した結果のチェック
  if(OrderSelect(i,SELECT BY POS,MODE HISTORY)==false)
  {
  Print("Access to history failed with error(",GetLastError(),")");
  break;
  }
  //注文と一緒にする仕事
 }

____________________________________________________________________
OrderClosePrice:

シンタックス
double OrderClosePrice()

解説
OrderClosePrice関数は選択した注文の手仕舞った値段を返します。
注文は普通、OrderClosePrice関数を呼び出す前にOrderSelect関数によって選択されています。



if(OrderSelect(ticket,SELLECT BY POS)==true)
  Print("Close price for the order",ticket,"=",OrderClosePrice());
 else
  Orint("OrderSelect failed error code is "GetLastError());

____________________________________________________________________
OrderCloseTime;

シンタックス
datetime OrderCloseTime()

解説
OrderCloseTime関数は手仕舞った時間を返します。
0が返却値として返されたら、その指定した注文は手仕舞われていないか、もしくはすでに手仕舞われていて、履歴から回収されたかのどちらかになります。
OrderCloseTimeが呼び出される前に、OrderSelect関数によって注文が選択されていなければなりません。

設定値
この関数は何も設定値をもちません。そして返却値としてdatetimeのデータタイプ(指定された手仕舞い注文の時間)が返されます。



if(OrderSelect(10,SELECT_BY_POS,MODE_HISTORY)==true)
 {
 datetime ctm=OrderOpenTime();
 if(ctm>0)Print("Open time for the order 10",ctm);
 ctm=OrderCloseTime();
 if(ctm>0)Print("Close time for the order 10",ctm);
 }
 else
  Print("OrderSelect failed error code is ",GetLastError());
____________________________________________________________________
OrderComment;

シンタックス
string OrderComment()

解説
OrderComment関数は、選択した注文に対する文字列のコメントを返します。

  メモ:このコメントはOrderSend関数と一緒にエントリー注文に対して割り当てら
  れるか、もしくはサーバーによって割り当てられます。時々あなたのコメントの最後に、サーバーの
  コメントを添えることがあります。

OrderComment関数を呼び出す前に、OrderSelectによって注文を選択していなければなりません。

設定値
この関数は何も設定値をとりません。そしてstringのデータタイプ(選択された注文に対するコメントの文字列)を返します。



string comment;
if(OrderSelect(10,SELECT_BY_TICKET)==false)
 {
 Promt("OrderSelect failed error code is",GetLastError());
 return(0);
 }
 comment=OrderComment();
____________________________________________________________________
OrderCommission:

シンタックス
double OrderCommission()

解説
OrderCommission関数は選択された注文の手数料を返します。
OrderCommission関数を呼び出す前に、OrderSelect関数によって注文が選択されていなければなりません。

設定値
この関数は設定値をとらず、doubleのデータタイプ(選択された注文に対する手数料)を返します。



if(OrderSelect(10,SELECT_BY_POS)==true)
  Print("Commission for the order10",OrderCommission());
 else
  Print("OrderSelect failed error code is",GetLastError());
 ____________________________________________________________________
OrderExpiration:
シンタックス
datetime OrderExpiration()

解説
OrderExpiration関数は、任意のOrderSendで指定した未決注文の有効期限の終了の時間を返します。
OrderExpiration関数を呼び出す前に、OrderSelect関数によって注文が選択されていなければなりません。

設定値
この関数は設定値をとらず、datatimeのデータタイプ(選択された未決注文の有効期限終了の時間)を返します。



if(OrderSelect(10,SELECT_BY_TICKET)==true)
  Print("Order expiration for the order#10"is,OrderExpiration());
 else
  Print("OrderSelect failed error code is,",GetLastError());
 ____________________________________________________________________
OrderLots:

シンタックス
double OrderLots()


解説
OrderLots関数は、任意のOrderSend関数(のvolume設定値)で指定したロット数を返します。
OrderLots関数を呼び出す前に、OrderSelect関数によって注文が選択されていなければなりません。

設定値
この関数は設定値をとらず、doubleのデータタイプ(選択された注文のロット数)を返します。



if(OrderSelect(10,SELECT_BY_POS)==true)
  Print("lots for the order 10"is,OrderLots());
 else
  Print("OrderSelect failed error code is,",GetLastError());
 ____________________________________________________________________
OrderMagicNumber:

シンタックス
int OrderMagicNumber()

解説
OrderMagicNumber関数は、任意のOrderSend関数で指定した識別番号の数を返します。
OrderMagicNumber関数を呼び出す前に、OrderSelect関数によって注文が選択されていなければなりません。

設定値

この関数は設定値をとらず、integerのデータタイプ(選択された注文の識別番号)を返します。



if(OrderSelect(10,SELECT_BY_POS)==true)
  Print("Magic number for the order 10",OrderMagicNumber());
 else
  Print("OrderSelect failed error code is,",GetLastError());
 ____________________________________________________________________
OrderOpenPrice:

シンタックス
double OrderOpenPrice()

解説
OrderOpenPrice関数は、指定したオープン価格を返します。
OrderOpenPrice関数を呼び出す前に、OrderSelect関数によって注文が選択されていなければなりません。

設定値
この関数は設定値をとらず、doubleのデータタイプ(選択された注文のオープン価格)を返します。



if(OrderSelect(10,SELECT_BY_POS)==true)
  Print("open price for the order 10",OrderOpenPrice());
 else
  Print("OrderSelect failed error code is,",GetLastError());
 ____________________________________________________________________
OrderOpenTime:

シンタックス
datetime OrderOpenTime()


解説
OrderOpenTime関数は、指定した注文の執行時間を返します。
OrderOpenTime関数を呼び出す前に、OrderSelect関数によって注文が選択されていなければなりません。

設定値
この関数は設定値をとらず、datatimeのデータタイプ(選択された注文の執行時間)を返します。



if(OrderSelect(10,SELECT_BY_POS)==true)
  Print("open time for the order 10",OrderOpenTime());
 else
  Print("OrderSelect failed error code is,",GetLastError());
 ____________________________________________________________________
OrderProfit:

シンタックス
double OrderProfit()


解説
OrderProfit関数は、指定した注文の利益を返します。
OrderProfit関数を呼び出す前に、OrderSelect関数によって注文が選択されていなければなりません。

設定値
この関数は設定値をとらず、doubleのデータタイプ(選択された注文の利益)を返します。



if(OrderSelect(10,SELECT_BY_POS)==true)
  Print("profit for the order 10",OrderProfit());
 else
  Print("OrderSelect failed error code is,",GetLastError());
 ____________________________________________________________________
OrderPrint:

シンタックス

void OrderPrint()

解説
OrderPrint関数は、選択された注文の情報をexpert log fileに出力します。
OrderPrint関数を呼び出す前に、OrderSelect関数によって注文が選択されていなければなりません。

設定値
この関数は設定値をとらず、返却値も返しません(voidです)

  メモ:voidの意味は、何も返却値を返さないという意味で、以下のような変数を
  割り振ることはできません。
  int i =OrderPrint();//コンパイルをしてもエラーはでてきませんが、何も意味はありません。



if(OrderSelect(10,SELECT_BY_TICKET)==true)
  OrderPrint();
 else
  Print("OrderSelect failed error code is,",GetLastError());
 ____________________________________________________________________
OrderStopLoss:

シンタックス
double OrderStopLoss()

解説
OrderStopLoss関数は、任意のOrderModify関数で調整、もしくはOrderSend関数で指定したストップロスの値を返します。
OrderStopLoss関数を呼び出す前に、OrderSelect関数によって注文が選択されていなければなりません。

設定値
この関数は設定値をとらず、doubleのデータタイプ(選択された注文のストップロスの値)を返します。



if(OrderSelect(10,SELECT_BY_POS)==true)
  Print("stop loss value for the order 10",OrderStopLoss());
 else
  Print("OrderSelect failed error code is,",GetLastError());
 ____________________________________________________________________
OrdersTotal:

シンタックス
int OrdersTotal()

解説
OrdersTotal関数は、指定した値段になると実行される注文と未決注文の総数を返します。
もしの値が帰ってきたら、注文は何もなされていないことを表します。

設定値
この関数は設定値をとらず、integerのデータタイプ(指定した値段になると実行される注文と未決注文の総数)を返します。



int handle=FileOpen("OrderReport.csv",FILE_WRITE|FILE_CSV,"\t");
 if(handle<0)return(0);
  //ヘッダーに記述
 FileWrite(handle,"#","open price","open time","symbol","lots");
 int total=OrdersTotal();
  //オープンオーダーを記述
 for(int pos=0;pos<total;pos++)
  {
  if(OrderSelect(pos,SELECT_BY_POS)==false)continue;

FileWrite(hadle,OrderTicket(),OrderOpenPrice(),OrderOpenTime(),OrderSymbol(),OrderLots());
  }
  FileClose(handle);
 ____________________________________________________________________
OrderSwap:


シンタックス
double OrderSwap()

解説
OrderSwap関数は、指定した注文のスワップポイントを返します。
OrderSwap関数を呼び出す前に、OrderSelect関数によって注文が選択されていなければなりません。

  メモ:交換には、一つの通貨ともう一つの通貨を同じにするための為替の元金
  と利率が必要です。通貨スワップは、もともと為替管理の問題を避けるために行われたものです。

設定値
この関数は設定値をとらず、doubleデータタイプの返却値(選択した通貨のスワップポイント)を返します。


if(OrderSelect(order_id,SELECT_BY_TICKET)==true)
  Print("Swap for the order #",order_id,"",OrderSwap());
 else
  Print("OrderSelect failed error code is,",GetLastError());
 ____________________________________________________________________
OrderTakeProfit

シンタックス
double OrderTakeProfit()

解説
OrderTakeProfit関数は、任意のOrderSendで指定した、もしくはOrderModify関数で調整した注文の指値決済の値段を返します。
OrderTakeProfit関数を呼び出す前に、OrderSelect関数によって注文が選択されていなければなりません。

設定値
この関数は設定値をとらず、doubleのデータタイプ(選択された注文の通貨ペアの指値決済の値段)を返します。



if(OrderSelect(12,SELECT_BY_POS)==true)
  Print("order#",OrderTicket(),"profit",OrderTakeProfit());
 else
  Print("OrderSelect failed error code is,",GetLastError());
 ____________________________________________________________________
OrderTicket

シンタックス
int OrderTicket()


解説
OrderTicket関数は、指定した注文のチケット番号(注文番号)を返します。
OrderTicket関数を呼び出す前に、OrderSelect関数によって注文が選択されていなければなりません。

設定値
この関数は設定値をとらず、integerのデータタイプ(選択された注文のチケット番号)を返します。



if(OrderSelect(12,SELECT_BY_POS)==true)
  order=OrderTicket();
 else
  Print("OrderSelect failed error code is,",GetLastError());
 ____________________________________________________________________

OrderSymbol

シンタックス
string OrderSymbol()

解説
OrderSymbol関数は、指定した注文の通貨ペアの説明を文字列で返します。(EURUSD等)
OrderSymbol関数を呼び出す前に、OrderSelect関数によって注文が選択されていなければなりません。

設定値
この関数は設定値をとらず、stringのデータタイプ(選択された注文の通貨ペアの説明)を返します。



if(OrderSelect(12,SELECT_BY_POS)==true)
  Print("symbol of order#",OrderTicket(),"is",OrderSymbol());
 else
  Print("OrderSelect failed error code is,",GetLastError());
 ____________________________________________________________________

これでトレーディング関数のことがよくわかりましたでしょうか。

それでは。

Coder's Guru


以上です。長かったですね!今回もお疲れ様でした。

押していただけると大変励みになりますのでよろしくお願いします!
人気ブログランキングへ

theme : FXでシステムトレード
genre : 株式・投資・マネー

2009-04-06

メタトレーダー補講第2回 トレーディング関数

今回は補講第2回ということで、トレーディング関数を扱います。

今までの記事の中で最も分量が多く、訳すのが疲れました。。(笑)

ですので読むのも結構大変だと思いますが、最初の3つ程のトレーディング関数の説明を読んでしまえば、後はほとんど同じパターンのトレーディング関数の記述になっていくので、そんなに難しくはないと思います。

記述はすべて、
関数名
シンタックス(データタイプ)
関数の解説
関数の取る設定値
例文
で行われており、必要に応じてメモが入る構成になっています。

それでは、今回もよろしくお願いします。

この文章はCodersGuruさんのMQL4Lesson4の訳文です。(翻訳しての転載に本人の許可はとってあります)                      
                     MQL4講座             
                     Coders'guru
                       www.forex-tsd.com   
                          -補講2-
                   トレーディング関数

今回の補講では、MQL4の25個のトレーディング関数の解説を行います。
私は初めてのエキスパートアドバイザー第3部の講義の前にこの補講を行うことに決めました。なぜなら、残りのコードを解読していく前に、これらの重要な関数を知ることが必要だからです。
____________________________________________________________________

OrderSend:

シンタックス:
int OrderSend(string symbol, int cmd, double volume, double price, int slippage, double stoploss,double, double takeprofit, string comment=NULL,int magic=0, detetime expriation=0,color allow_color=CLR_NONE)

敢えて日本語に訳すなら

注文執行(通貨ペア,売買執行種類(売り、買い、エントリー、エクジッド、指値等),Lot数,エントリ―時の価格,許容スリッページ,ストップロスの値,手仕舞いの指値の値,注文時のコメント,オーダー識別番号,手仕舞い時間,エントリー時のマークの色)

解説
このOrderSend関数は売り/買いのオープンオーダー(指定した値段になると実行される注文)か、決済注文に指定のために使います。

もしその注文が成功すれば注文番号が返却値として返され、失敗すればー1が返されます。
GetLastError関数を使ってより詳しいエラーの原因を知ることができます。

  メモ:注文番号はOrderSend関数によって返される固有の数字です。この関数
  は後で新規あるいは決済注文のリファレンスとして使うことができます。(たとえばOrderClose関
  数と注文番号を使用して、特定の注文を手仕舞うことができます)

  メモ:GetLastError関数は、あるコードが実行された後に最後に起こったエラー
  に対応する予約された数字が返されます。(例えばOrderSendが実行されたあとにGerLastError
  関数が呼び出され時、OrderSendが実行している間に起きたエラーナンバーが表示されます)

  GetLastEllorが呼び出されると、一つ前のエラーナンバーは0にリセットされます。

  stderror.mqhファイルにMQL4のエラーナンバーのすべてのリストが書かれていますのでよろしけ
  ればご覧ください。
  また特定のエラーナンバーに対するエラーの解説をstdlib.mqhファイルに定義されたErrorDescripti
  on関数を使うことによって得ることもできます。(どちらもexperts/includeフォルダの中に入ってま
  す)

設定値
OrderSend関数は設定値を11個持ちます。

string symbol
symbolとは貴方の取引する通貨ペアの名称のことです(例EURUSD USDJPY等)

  メモ:現在使用している通貨ペアを得るためにはSymbol()関数を使い、OrderS
  elecy()関数によって指定された、現在指定されている通貨ペアを得るためにはOrderSymbol関数
  を使用します。

int cmd;
貴方がどのような売買執行をしたいのかを指し示す整数値の数値です。以下の値がとれます。

定数            値       解説
OP_BUY          0        買いポジション  
OP_SELL          1        売りポジション
OP_BUYLIMIT       2        指値で買う
OP_SELLLIMIT      3        指値で売る
OP_BUYSTOP       4        逆指値で買う
OP_SELLSTOP      5        逆指値で売る

  メモ:整数値を定数値の代わりに式として使うことも可能です。
  例えば
  OrderSend(Symbol(),0,......)はOrderSend(Symbol(),OP_BUY....)と書くのと等しいです。
  しかし、コードを分かりやすい状態にするために、定数名で記述することをお勧めします。

double volume
貴方がトレードさせたいと思うロット数

double price:
ここでは価格の値段がいくらの時に売買を実行するかを指定します。
最新の買値や売値(bid ask)のデータを得るためにはBid関数もしくはASK関数を使います。

int slippage:
貴方が注文の際に定める許容スリッページの値。

  メモ:スリッページとは算出取引価格と実際の執行価格との間に生まれた差で
  す。
  スリッページは普通スプレッドの変化によるものと考えられています。

double stoploss:
損失を含んだときに手仕舞おうと思う値段。(逆指値手仕舞いの値段)

double takeprofit:
含み益の際に手仕舞おうと思っている値段。(逆指値手仕舞いの値段)

string comment:
指定したテキストのコメントを、貴方が注文した時に表示することができます。(図1参照)
初期値は、注文に対して何もコメントを割り振りませんという意味のNULLが設定されています。

  メモ:初期値が指定されている場合、貴方はコード文を記述しなくても大丈夫と
  いう意味です。何も記述しなければ、MQL4は初期値が設定されているものとして読み込みます。
  つまり、コメントを挿入するのであれば
  OrderSend(Symbol(),OP_BUY,Ask 3,ask-25*Point,Ask+25*Point,"My order comment",12345,
  0,Green);
  逆にしないのであれば
  OrderSend(Symbol(),OP_BUY,Ask 3,ask-25*Point,Ask+25*Poin
  t,12345
,0,Green);
  と記述するわけです。(赤で囲ったAsk+25*Point,12345の間に、順序的にコメントが入るわけです
  が、コメントを挿入する気がないのならば記述しなくていいわけです。そこにはNULLが初期値なの
  で自動的に挿入されたとしてMQL4は考えます)

int magic:
注文に対して割り振ったマジックナンバー

  メモ:マジックナンバーとは、貴方に注文の違いを区別できるようにさせるリファ
  レンスとして、注文に対して割り振った数字です。例えば貴方がエキスパートアドバイザーによって
  行ったオープン注文(指定した値段になると実行される注文)と、貴方が手動で行ったオープン注
  文等が例に挙げられます。

detetime expiration
貴方の未決の注文の有効期限がいつ切れるかを決めるものです。
初期値はで、これは有効期限等は無いことを示します。

  メモ:ここでいう時間とは、サーバーの時間で、日本時間ではありません。現在
  のサーバーの時間を得るためにはCurTime関数を使用し、日本時間(ローカル時間)を得たいなら
  LocalTime関数を使用します。

color arrow_color;
エントリー注文の時のマークの色の設定(図2)で、初期値はCLR_NONEです。意味は、チャート上にマークを何も描かない です。



int ticket;
if(iRSI(NULL,0,14,PRICE_CLOSE,0)<25)
{
ticket=OrderSend( (Symbol(),OP_BUY,Ask,3,ask-25*Point,Ask+25*Point,"Myorder#2,16384,0,Green);
  if(ticket<0)
   {
   Print("OrderSend failed with error#"GetLastError());
   return(0)
   }
  }
____________________________________________________________________
OrderModify

シンタックス
bool OrderModify(int ticket,double price,double stoploss,double takeprofit,datetime expiration,color arrow_color=CLR_NONE)

真か偽か 注文調整(注文番号, いくらで注文するか, ストップロスはいくらか, いくら益がでたら決済するか,タイムリミットはいつか,マークの色 )  

解説
OrderModify関数は、特定の注文もしくはまだ執行されていない注文の特性を変更し、新しい値に置き換えて、関数に受け渡すという働きをします。
もしも注文が変更するのに成功したらばtrueの値を返し、失敗すればfalseの値が返されます。
GetLastError関数を使うことによって、より詳細なエラーの原因がわかります。

設定値
設定値は6つあります。

int ticket:
貴方が調整(変更)したいチケット番号(注文番号)です。

  メモ:この数はOrderSend関数によって既に注文に割り当てられています。
  OrderTicket関数を使うことで、現在の注文のチケット番号を取得できます。

double price:
注文する時に指定する値段です。

  メモ:OrderOpenPrice関数を使うことで現在の注文のオープン価格(オープン
  注文で指定した価格)を取得できます。

double stoploss
損失が出た時に手仕舞おうと思っている値段です(逆指値決済の値です)

double takeprofit;
利益が出た時に手仕舞おう(指値決済の値です)

  メモ:OrderModify関数は、stoplossとtakeprofitの値を変えるために使われる
  ことが一般的です。これはトレイリングストップと呼ばれています。

detatime expiration:
未決の注文を何時に無効にするか。
特に時間を指定したくない時はを使ってください。

color arrow_color
マークの色。初期値の色はCLR_NONEで、何もマークをチャートに描かないことを表しています。



if(TrailingStop>0)
 {
 SelectOrder(12345,SELECT_BY_TICKET);
 if(BID-OrderOpenPrice()>Point*TrailingStop)
  {
   if(OrderStopLoss()     {
      OrderModify(OrderTicket(),Ask-10*Point,Ask-35*Point,OrderTakeProfit(),0,Blue);
      return(0);
     }
    }
   }
____________________________________________________________________
OrderClose

シンタックス
bool OrderClose(int ticket,double lots,double price,int slippage,color=CLR_NONE)


解説

OrderClose関数は特定の約定注文を(そのチケット番号を使って)手仕舞う時に使います。
もし注文の手仕舞いが行われればtrueを返し、行われなければfalseの値を返します。
GetLastError関数を使うことで、エラーの詳細を取得できます。

設定値
この関数は5つの設定値を持ちます。

int ticket:
貴方が手仕舞いおうとする注文のチケット番号です。

double lots:
貴方が手仕舞おうとするロット数です。

  メモ:OrderLots関数を使うことで、現在の注文のロット数を取得できます。

double price:
対象の注文を手仕舞う時に指定する値段です。
Bid関数やAsk関数を使うことで現在の買値、売値を取得できます。

int slippage:
注文のスリッページ許容値です。

color Color:
手仕舞い時のマークの色です。初期値はCLR_NONEであり、チャートにマークは描かれないことを意味しています。



if(iRSI(NULL,0,14,PRICE CLOSE,0)>75)
  {
  OrderClose(order id,1,Ask,3,Red);
  return(0);
  }
____________________________________________________________________
OrderSelect

シンタックス
bool OrderSelect(int index,int select,int pool=MODE_TRADES)

解説
OrderSelect関数は、新規注文もしくは未決済注文を、チケット番号又はインデックスによって選択する働きを持ちます。
もしも注文の選択に成功したらtrueの値を返し、失敗したらfalseの値を返します。
GetLastError関数を使うことでエラーの詳細を取得できます。

  メモ:設定値をとらないトレーディング関数の前には、OrderSelect関数を使わ
  なければなりません。
  OrderMagicNumber, OrderClosePrice, OrderCloseTime, OrderOpenPrice, OrderOpen,Time,
  OrderComment,OrderCommission, OrderExpiration, OrderLots, OrderPrint, OrderProfit,
  OrderStoploss,OrderSwap,OrderSymbol,OrderTakeProfit,OrderTicket, OrderType

設定値:
この関数はつの設定値を持ちます。

int index
貴方が選択したい注文のインデックスもしくはチケット番号。どちらにするかは次の設定値(select)次第です。

int select:
選択を実行するタイプ(インデックスか、注文番号か)
以下の二つの値のどちらかを取ります。
SELECT_BY_POS:注文の位置(インデックス)を使用します。
SELECT_BY_TICKET:注文のチケット番号を使用します。

int pool:
もしSELECT_BY_POSの選択タイプを使ったなら、どこの情報源から選択するかを決定しなくてはなりません。

MODE_TRADES:現在の注文から選択(エントリー注文、未決済注文用)これが初期設定値になります。
MODE_HISTORY:履歴から選択(手仕舞い注文、注文取り消し用)



if(OrderSelect(12470,SELECT BY TICKET)=true)
  {
  Print("order#12370 open price is",OrderOpenPrice());
  Print("order#12470 close price is ",OrderClosePrice());
  }
  else
   Print("OrderSelect failed error code is",GetLastError());
____________________________________________________________________
OrderDelete:

シンタックス
bool OrderDelete(int ticket)

解説
OrderDelete関数はまだ執行されていない注文を削除する時に使われます。
もし注文が正常に削除されたのならtrueの値を返し、失敗したらfalseの値を返します。
GetLastError関数を使うと、エラーの詳細が取得できます。

設定値

この関数は1つの設定値のみ持ちます。

int ticket
貴方が削除したい注文のチケット番号です。



if(Ask>var1)
  {
  OrderDelete(order_ticket);
  return(0);
  }

____________________________________________________________________
OrderCloseBy:

シンタックス
bool OrderCloseBy(int ticket,int opposite, color Color=CLR_NONE)

解説
OrderCloseBy関数は、特定の注文を反対売買を行うことによって手仕舞う時につかう関数です。
もし成功したらtrueの値を返し、失敗したらfalseの値を返します。
GetLastError関数を使えば、エラーに関する詳細を取得することができます。

設定値
この関数は3つの設定値を持ちます。

int ticket
貴方が手仕舞いたい注文のチケット番号です。

int opposite
貴方が反対方向でエントリーしようと思う注文のチケット番号です

color Color:
手仕舞いマークの色です。初期設定値はCLR_NONEで、マークをチャート場に描かないことを意味します。


if(RSI(NULL,0,14,PRICE_CLOSE,0)>75)
 {
 OrderCloseBy(order id,opposite id);
 return(0);
 }

____________________________________________________________________
OrderType
シンタックス
int OrderType()

解説
OrderType関数は、返却値として選択された注文の種類を返します。具体的にはOrderSend関数であるOP_BUY,OP_SELL,OP_BUYLIMIT,OP_SELLLIMIT,OP_BUYSTOP,OP_SELLSTOPのうちのどれかです。

設定値
この関数には設定値がありません。ただ整数値の選択された注文のデータタイプを返すだけです。
(返された整数値が0ならばOP_BUYが返されます。詳しくはOrderSend関数をご覧ください。)



int order_type;
 if(OrderSelect(12,SELECT_BY_POS)==true)
  {
  order_type=OrderType();
  }
  else
  Print("OrderSelect()returned error-",GetLastError());
____________________________________________________________________
History Total:

シンタックス
int HistoryTotal()

解説
HistoryTotal関数はメタトレーダーターミナルから読み込まれた口座の履歴を検索し、手仕舞い注文の数を返す。

  メモ:普通この関数はOrderSelect関数と一緒に使用し、履歴の中から特定の
  注文情報を取得します。

設定値

この関数はなんの設定値も持ちません。ただ整数値(履歴の中の手仕舞い注文の総数)を返します。
GetLastError関数を使うことでエラーの詳細の情報を取得することができます。



//取引履歴から情報を回収する行動を取る
  int i,hstTotal=HistoryTotal();
  for(i=0;i  {
  //---選択した結果のチェック
  if(OrderSelect(i,SELECT BY POS,MODE HISTORY)==false)
  {
  Print("Access to history failed with error(",GetLastError(),")");
  break;
  }
  //注文と一緒にする仕事
 }

____________________________________________________________________
OrderClosePrice:

シンタックス
double OrderClosePrice()

解説
OrderClosePrice関数は選択した注文の手仕舞った値段を返します。
注文は普通、OrderClosePrice関数を呼び出す前にOrderSelect関数によって選択されています。



if(OrderSelect(ticket,SELLECT BY POS)==true)
  Print("Close price for the order",ticket,"=",OrderClosePrice());
 else
  Orint("OrderSelect failed error code is "GetLastError());

____________________________________________________________________
OrderCloseTime;

シンタックス
datetime OrderCloseTime()

解説
OrderCloseTime関数は手仕舞った時間を返します。
0が返却値として返されたら、その指定した注文は手仕舞われていないか、もしくはすでに手仕舞われていて、履歴から回収されたかのどちらかになります。
OrderCloseTimeが呼び出される前に、OrderSelect関数によって注文が選択されていなければなりません。

設定値
この関数は何も設定値をもちません。そして返却値としてdatetimeのデータタイプ(指定された手仕舞い注文の時間)が返されます。



if(OrderSelect(10,SELECT_BY_POS,MODE_HISTORY)==true)
 {
 datetime ctm=OrderOpenTime();
 if(ctm>0)Print("Open time for the order 10",ctm);
 ctm=OrderCloseTime();
 if(ctm>0)Print("Close time for the order 10",ctm);
 }
 else
  Print("OrderSelect failed error code is ",GetLastError());
____________________________________________________________________
OrderComment;

シンタックス
string OrderComment()

解説
OrderComment関数は、選択した注文に対する文字列のコメントを返します。

  メモ:このコメントはOrderSend関数と一緒にエントリー注文に対して割り当てら
  れるか、もしくはサーバーによって割り当てられます。時々あなたのコメントの最後に、サーバーの
  コメントを添えることがあります。

OrderComment関数を呼び出す前に、OrderSelectによって注文を選択していなければなりません。

設定値
この関数は何も設定値をとりません。そしてstringのデータタイプ(選択された注文に対するコメントの文字列)を返します。



string comment;
if(OrderSelect(10,SELECT_BY_TICKET)==false)
 {
 Promt("OrderSelect failed error code is",GetLastError());
 return(0);
 }
 comment=OrderComment();
____________________________________________________________________
OrderCommission:

シンタックス
double OrderCommission()

解説
OrderCommission関数は選択された注文の手数料を返します。
OrderCommission関数を呼び出す前に、OrderSelect関数によって注文が選択されていなければなりません。

設定値
この関数は設定値をとらず、doubleのデータタイプ(選択された注文に対する手数料)を返します。



if(OrderSelect(10,SELECT_BY_POS)==true)
  Print("Commission for the order10",OrderCommission());
 else
  Print("OrderSelect failed error code is",GetLastError());
 ____________________________________________________________________
OrderExpiration:
シンタックス
datetime OrderExpiration()

解説
OrderExpiration関数は、任意のOrderSendで指定した未決注文の有効期限の終了の時間を返します。
OrderExpiration関数を呼び出す前に、OrderSelect関数によって注文が選択されていなければなりません。

設定値
この関数は設定値をとらず、datatimeのデータタイプ(選択された未決注文の有効期限終了の時間)を返します。



if(OrderSelect(10,SELECT_BY_TICKET)==true)
  Print("Order expiration for the order#10"is,OrderExpiration());
 else
  Print("OrderSelect failed error code is,",GetLastError());
 ____________________________________________________________________
OrderLots:

シンタックス
double OrderLots()


解説
OrderLots関数は、任意のOrderSend関数(のvolume設定値)で指定したロット数を返します。
OrderLots関数を呼び出す前に、OrderSelect関数によって注文が選択されていなければなりません。

設定値
この関数は設定値をとらず、doubleのデータタイプ(選択された注文のロット数)を返します。



if(OrderSelect(10,SELECT_BY_POS)==true)
  Print("lots for the order 10"is,OrderLots());
 else
  Print("OrderSelect failed error code is,",GetLastError());
 ____________________________________________________________________
OrderMagicNumber:

シンタックス
int OrderMagicNumber()

解説
OrderMagicNumber関数は、任意のOrderSend関数で指定した識別番号の数を返します。
OrderMagicNumber関数を呼び出す前に、OrderSelect関数によって注文が選択されていなければなりません。

設定値

この関数は設定値をとらず、integerのデータタイプ(選択された注文の識別番号)を返します。



if(OrderSelect(10,SELECT_BY_POS)==true)
  Print("Magic number for the order 10",OrderMagicNumber());
 else
  Print("OrderSelect failed error code is,",GetLastError());
 ____________________________________________________________________
OrderOpenPrice:

シンタックス
double OrderOpenPrice()

解説
OrderOpenPrice関数は、指定したオープン価格を返します。
OrderOpenPrice関数を呼び出す前に、OrderSelect関数によって注文が選択されていなければなりません。

設定値
この関数は設定値をとらず、doubleのデータタイプ(選択された注文のオープン価格)を返します。



if(OrderSelect(10,SELECT_BY_POS)==true)
  Print("open price for the order 10",OrderOpenPrice());
 else
  Print("OrderSelect failed error code is,",GetLastError());
 ____________________________________________________________________
OrderOpenTime:

シンタックス
datetime OrderOpenTime()


解説
OrderOpenTime関数は、指定した注文の執行時間を返します。
OrderOpenTime関数を呼び出す前に、OrderSelect関数によって注文が選択されていなければなりません。

設定値
この関数は設定値をとらず、datatimeのデータタイプ(選択された注文の執行時間)を返します。



if(OrderSelect(10,SELECT_BY_POS)==true)
  Print("open time for the order 10",OrderOpenTime());
 else
  Print("OrderSelect failed error code is,",GetLastError());
 ____________________________________________________________________
OrderProfit:

シンタックス
double OrderProfit()


解説
OrderProfit関数は、指定した注文の利益を返します。
OrderProfit関数を呼び出す前に、OrderSelect関数によって注文が選択されていなければなりません。

設定値
この関数は設定値をとらず、doubleのデータタイプ(選択された注文の利益)を返します。



if(OrderSelect(10,SELECT_BY_POS)==true)
  Print("profit for the order 10",OrderProfit());
 else
  Print("OrderSelect failed error code is,",GetLastError());
 ____________________________________________________________________
OrderPrint:

シンタックス

void OrderPrint()

解説
OrderPrint関数は、選択された注文の情報をexpert log fileに出力します。
OrderPrint関数を呼び出す前に、OrderSelect関数によって注文が選択されていなければなりません。

設定値
この関数は設定値をとらず、返却値も返しません(voidです)

  メモ:voidの意味は、何も返却値を返さないという意味で、以下のような変数を
  割り振ることはできません。
  int i =OrderPrint();//コンパイルをしてもエラーはでてきませんが、何も意味はありません。



if(OrderSelect(10,SELECT_BY_TICKET)==true)
  OrderPrint();
 else
  Print("OrderSelect failed error code is,",GetLastError());
 ____________________________________________________________________
OrderStopLoss:

シンタックス
double OrderStopLoss()

解説
OrderStopLoss関数は、任意のOrderModify関数で調整、もしくはOrderSend関数で指定したストップロスの値を返します。
OrderStopLoss関数を呼び出す前に、OrderSelect関数によって注文が選択されていなければなりません。

設定値
この関数は設定値をとらず、doubleのデータタイプ(選択された注文のストップロスの値)を返します。



if(OrderSelect(10,SELECT_BY_POS)==true)
  Print("stop loss value for the order 10",OrderStopLoss());
 else
  Print("OrderSelect failed error code is,",GetLastError());
 ____________________________________________________________________
OrdersTotal:

シンタックス
int OrdersTotal()

解説
OrdersTotal関数は、指定した値段になると実行される注文と未決注文の総数を返します。
もしの値が帰ってきたら、注文は何もなされていないことを表します。

設定値
この関数は設定値をとらず、integerのデータタイプ(指定した値段になると実行される注文と未決注文の総数)を返します。



int handle=FileOpen("OrderReport.csv",FILE_WRITE|FILE_CSV,"\t");
 if(handle<0)return(0);
  //ヘッダーに記述
 FileWrite(handle,"#","open price","open time","symbol","lots");
 int total=OrdersTotal();
  //オープンオーダーを記述
 for(int pos=0;pos<total;pos++)
  {
  if(OrderSelect(pos,SELECT_BY_POS)==false)continue;

FileWrite(hadle,OrderTicket(),OrderOpenPrice(),OrderOpenTime(),OrderSymbol(),OrderLots());
  }
  FileClose(handle);
 ____________________________________________________________________
OrderSwap:


シンタックス
double OrderSwap()

解説
OrderSwap関数は、指定した注文のスワップポイントを返します。
OrderSwap関数を呼び出す前に、OrderSelect関数によって注文が選択されていなければなりません。

  メモ:交換には、一つの通貨ともう一つの通貨を同じにするための為替の元金
  と利率が必要です。通貨スワップは、もともと為替管理の問題を避けるために行われたものです。

設定値
この関数は設定値をとらず、doubleデータタイプの返却値(選択した通貨のスワップポイント)を返します。


if(OrderSelect(order_id,SELECT_BY_TICKET)==true)
  Print("Swap for the order #",order_id,"",OrderSwap());
 else
  Print("OrderSelect failed error code is,",GetLastError());
 ____________________________________________________________________
OrderTakeProfit

シンタックス
double OrderTakeProfit()

解説
OrderTakeProfit関数は、任意のOrderSendで指定した、もしくはOrderModify関数で調整した注文の指値決済の値段を返します。
OrderTakeProfit関数を呼び出す前に、OrderSelect関数によって注文が選択されていなければなりません。

設定値
この関数は設定値をとらず、doubleのデータタイプ(選択された注文の通貨ペアの指値決済の値段)を返します。



if(OrderSelect(12,SELECT_BY_POS)==true)
  Print("order#",OrderTicket(),"profit",OrderTakeProfit());
 else
  Print("OrderSelect failed error code is,",GetLastError());
 ____________________________________________________________________
OrderTicket

シンタックス
int OrderTicket()


解説
OrderTicket関数は、指定した注文のチケット番号(注文番号)を返します。
OrderTicket関数を呼び出す前に、OrderSelect関数によって注文が選択されていなければなりません。

設定値
この関数は設定値をとらず、integerのデータタイプ(選択された注文のチケット番号)を返します。



if(OrderSelect(12,SELECT_BY_POS)==true)
  order=OrderTicket();
 else
  Print("OrderSelect failed error code is,",GetLastError());
 ____________________________________________________________________

OrderSymbol

シンタックス
string OrderSymbol()

解説
OrderSymbol関数は、指定した注文の通貨ペアの説明を文字列で返します。(EURUSD等)
OrderSymbol関数を呼び出す前に、OrderSelect関数によって注文が選択されていなければなりません。

設定値
この関数は設定値をとらず、stringのデータタイプ(選択された注文の通貨ペアの説明)を返します。



if(OrderSelect(12,SELECT_BY_POS)==true)
  Print("symbol of order#",OrderTicket(),"is",OrderSymbol());
 else
  Print("OrderSelect failed error code is,",GetLastError());
 ____________________________________________________________________

これでトレーディング関数のことがよくわかりましたでしょうか。

それでは。

Coder's Guru


以上です。長かったですね!今回もお疲れ様でした。

押していただけると大変励みになりますのでよろしくお願いします!
人気ブログランキングへ

theme : FXでシステムトレード
genre : 株式・投資・マネー

2009-04-08

メタトレーダー講義第15回初めてのエキスパートアドバイザー第3部

この文章はCodersGuruさんのMQL4Lesson4の訳文です。(翻訳しての転載に本人の許可はとってあります)         
                      MQL4講座       
                     Coders'guru                               
                      www.forex-tsd.com                          
                           -15-
                 初めてのエキスパートアドバイザー
                   第3部


最近の二つの講義では、初めてのエキスパートアドバイザーを紹介し、その背後にあるアイディアを知りました。
また、第2回目の補講2では、今回の授業で使うことにもなるトレーディング関数について学びました。

今回は、エキスパートアドバイザーの残りのコードの解読の続きになります。
今回の我々の解読任務によって、貴方の疑問がきれいになくなることを期待しています。

私たちのコード

//+------------------------------------------------------------------+
//| My_First_EA.mq4 |
//| Coders Guru |
//| http://www.forex-tsd.com |
//+------------------------------------------------------------------+

#property copyright "Coders Guru"
#property link "http://www.forex-tsd.com"

//---- 埋め込まれた設定値
extern double TakeProfit=250.0;
extern double Lots=0.1;
extern double TrailingStop=35.0;
//+------------------------------------------------------------------+
//| expert initialization function                    |
//+------------------------------------------------------------------+

int init()
{
//----

//----

return(0);
}
//+------------------------------------------------------------------+
//| expert deinitialization function                   |
//+------------------------------------------------------------------+

int deinit()
{
//----

//----
return(0);
}
int Crossed (double line1 , double line2)
  {
   static int last_direction = 0;
   static int current_direction = 0;

   if(line1>line2)current_direction=1; //アップ
   if(line1<line2)current_direction=2; //ダウン

   if(current_direction !=last_direction) //変化
   {
      last_direction = current_direction;
      return(last_direction);
   }
   else
   {
     return (0);
   }
 }
//+------------------------------------------------------------------+
//| expert start function                     |
//+------------------------------------------------------------------+

int start()
 {
 int cnt, ticket, total;
 double shortEma,longEma;

 if(Bars<100)
 {
  Print("bars less than 100");
  return(0);
 }
 if(TakeProfit<10)
 {
  Print("TakeProfit less than 10");
  return(0); //check TakeProfit
  }

 shortEma=iMA(NULL,0,8,0,MODE_EMA,PRICE_CLOSE,0);
 longEma=iMA(NULL,0,13,0,MODE_EMA,PRICE_CLOSE,0);

 int isCrossed = Crossed(shortEma,longEma);

 total = OrdersTotal();
 if(total < 1)
  {
  if (isCrossed == 1)
   {
ticket=OrderSend(Symbol(),OP_BUY,Lots,Ask,3,0,Ask+TakeProfit*Point,
"My EA",12345,0,Green);
     if(ticket>0)
     {
     if(OrderSelect(ticket,SELECT_BY_TICKET,MODE_TRADES))
Print("BUY order operand : ",OrderOpenPrice());
     }
    else Print("Error opening BUY order : ",GetLastError());
     return(0);
     }
    if(isCrossed == 2)
    {

     ticket=OrderSend(Symbol(),OP_SELL,Lots,Bid,3,0,
     Bid-TakeProfit*Point,"My EA",12345,0,Red);
      if(ticket>0)
        {
        if(OrderSelect(ticket,SELECT_BY_TICKET,MODE_TRADES))
      Print("SELL order opened ; ",OrderOpenPrice());
        }
      else Print("Error opening Sell order : ",GetLastError());
       return(0);
       }
       return(0);
    }
     for(cnt=0;cnt<total;cnt++)
     {
     OrderSelect(cnt,SELECT_BY_POS,MODE_TRADES);
     if(OrderType()<=OP_SELL && OrderSymbol()==Symbol())
    {
    if(OrderType()==OP_BUY) //ロングポジションでエントリー
    {
    //手仕舞うか?
    if(isCrossed ==2)
      {
         OrderClose(OrderTicket(),OrderLots(),Ask,3,Violet);
  //手仕舞い
     return(0); //次へ
      }
    if(TrailingStop>0)
     {
     if(Bid-OrderOpenPrice()>Point*TrailingStop)
       {
       if(OrderStopLoss()<Bid-Point*TrailingStop)
        {
         OrderModify(OrderTicket(),OrderOpenPrice(),Bid-
          Point*TrailingStop,OrderTakeProfit(),0,Green);
         return(0);
         }
        }
       }
      }
     else//ショートポジションへ
      {
     //手仕舞うべきか
      if(isCrossed ==1)
      {
      OrderClose(OrderTicket(),OrderLots(),Ask,3,Violet);
  //手仕舞い
     return(0); //決済
      }
     //トレイリングストップのチェック
      if(TrailingStop>0)
       {
        if((OrderOpenPrice()-Ask)>(Point*TrailingStop))
        {
         if((OrderStopLoss()>(Ask+Point*TrailingStop)) ||
      (OrderStopLoss()==0))
             {

    OrderModify(OrderTicket(),OrderOpenPrice(),Ask+Point*TrailingStop,
     OrderTakeProfit(),0,Red);
            return(0);
             }
            }
           }
          }
         }
       }
 return(0);
 }
//+------------------------------------------------------------------+

____________________________________________________________________
int cnt, ticket, total;

この文では、3つのintegerタイプの変数を宣言しています。
一つの文を使うことで、3つの変数を宣言していますが、これは三つの変数(cnt,ticket,total)がどれも同じデータタイプなので可能になっています。(もしデータタイプが違っていたら、一つの文でまとめて宣言することはできません。)

メモ:複数の変数を一つの文で宣言するために、変数のデータタイプを示す宣言キーワードから文を始めて、識別子(変数名)をコンマで区切っていきます。
上のコード文を、3行に分けて書くことも可能です。下のようになります。
int cnt;
int ticket;
int total;

cnt変数はオープンオーダー(指定した値段になると実行される注文)のループ回数をチェックする変数として使用することになります。
ticket変数はOrderSend関数によって返されたチケット番号(注文番号)の値を入れる変数として使用することになります。
total変数は、すでに注文された総数の値を入れる変数として使用することになります。
____________________________________________________________________
double shortEma,longEma;

ここでは再び1行で、二つの変数を宣言しています。
この変数は短期EMAと長期EMAの値を入れる変数として使用することになります。
前回の部で説明したように、買いの状況なのか売りの状況なのか、手仕舞いの状況なのかという判断には、短期EMAと長期EMAの交差を使用しています。
____________________________________________________________________
if(Bars<100)
 {
  Print("bars less than 100");
  return(0);
 }

私たちは正常なチャートで働かせたいと思っています。正常なチャートは、100以上のバー(ローソク足)があることを想定しています。なぜなら、バーの数が不十分であると、EMAインディケーターが機能しないあるいは正常に動かないからです。

私たちはBars関数を使うことによって、チャート上に何本のバーがあるかを取得し、バーの数が100以下であるかそうでないかをチェックします。もし、バーの数が100より少なければ、二つのことをします。
エキスパートログに"bars less than 100"とメッセージを書くことで、何が問題なのかユーザーに伝えます。
その後、return(0)のコード文によってstart関数を終了します。

このようにして、チャート場のバーが100以下であったらばEA(エキスパートアドバーザー)を働かせることを終了させます。
図1
図1-エキスパートログ

____________________________________________________________________
if(TakeProfit<10)
 {
  Print("TakeProfit less than 10");
  return(0); //check TakeProfit
  }

私たちは、不十分なTakeProfit(獲得利益)の設定の状態でEA(エキスパートアドバイザー)を起動させたくもありません。
TakeProfit変数は、external(外部)変数ですので、ユーザーが初期設定値を、エキスパートアドバイザーのプロパティーウィンドウで変更することが可能です。
私たちはEAのユーザーを、ユーザーの誤った判断から守りたいと思います。
私たちはTakeProfit変数が10以下であることは悪い判断であると考えていますので、ユーザーがTakeProfit変数が10以下に指定したかそうでないかをチェックします。

もしも10以下であったなら、私たちは"TakeProfit less than 10"というメッセージを表示させることによって、何が問題であるかをユーザーにしらせます。そして、return(0)を返すことによってstart関数を終了させます。
____________________________________________________________________
 shortEma=iMA(NULL,0,8,0,MODE_EMA,PRICE_CLOSE,0);
 longEma=iMA(NULL,0,13,0,MODE_EMA,PRICE_CLOSE,0);

もしすべてが大丈夫なら、チャート上のバーの総数は100以上であり、TakeProfit変数は、ユーザーが10以上に指定しているということになります。

そこで私たちは今、現在のバーの短期と長期のEMAの値を算出したいと思います。
MQL4に埋め込まれている、移動平均線の値を算出するテクニカル指標関数であるiMAを使います。
私はここで数分立ち止まって、貴方にiMA関数の詳細を伝えなければなりません。

iMA

シンタックス
double iMA(sring,Symbol,int timeflame, int period,int ma_shift,int ma_method,int applied_price,int shift)

解説
iMa関数は移動平均線を算出し、その値を(doubleタイプで)返します。

  メモ:移動平均線とは、ある通貨の、ある時間足(日、時間、分)での、割り当てられた期間の平均
     値です。

設定値
この関数は7つの設定値を取ります。

string symbol:
貴方の取引での通貨ペアの指定(EURUSD,USDJPY等)です。
もしもチャートで使っている通貨ペアを指定したいのなら、設定値としてNULLを割り当ててください。
(例えばEURUSDに指定して、GBPJPYのチャートに起動させたら、チャートはGBPJPYを開いていてもEURUSDの移動平均線が表示されつづけることになります。)

int timeframe
移動平均線に使用する時間足の設定です。
以下の時間足が使えます。

定数        値    解説
PERIOD_M1    1     1分足
PERIOD_M5    5     5分足
PERIOD_M15   15    15分足
PERIOD_M30   30    30分足
PERIOD_H1    60    1時間足
PERIOD_M4    240   4時間足
PERIOD_D1    1440   日足
PERIOD_W1    10080  週間足
PERIOD_MN1   43200  月足
0          0     チャートで使われている時間足

もし使用されている時間足を使いたければ、を設定値としてお使い下さい。

  メモ:時間足の設定は、整数でも定数名ででも使うことができます。たとえば
     iMA(NULL,PERIOD_H4,8,0,MODE_EMA,PRICE_CLOSE,0);
     は
     iMA(NULL,0,8,0,MODE_EMA,PRICE_CLOSE,0);
     と等しいです。しかし、コードをはっきりさせるために、定数名を使用することをお勧めします。

int period:
移動平均線の算出に使う足はいくつかを設定するものです。

int ma_shift:
移動平均線をチャートの開始時から何本ずらしたいかを設定するものです。
0は移動なしを意味します(図2参照)
正の整数は右にシフトします(図3参照)
負の整数は左にシフトします(図4参照)

int ma_method;
移動平均線の算出に使いたい、移動平均線の種類を指定するものです。
以下の設定値を使うことができます。

定数       値   解説
MODE_SMA   0   単純移動平均線 
MODE_EMA   1   指数移動平均線
MODE_SMMA  2   平滑移動平均線
MODE_LWMA  3   線形加重移動平均線

int applied_price:
移動平均線を算出する際に使う値段をきめます。
以下の値を使用することができます。

定数          値    解説
PRICE_CLOSE     0   終値
PRICE_OPEN      1   始値
PRICE_HIGH      2   高値
PRICE_LOW      3   安値
PRICE_MEDIAN    4   高値と安値の平均値
PRICE_TYPICAL   5   高値と安値と終値の平均値
PRICE_WEIGHTED  6   高値、安値、終値、始値の平均値
図2
図2:ma_shift=0
図3
図3:ma_shift=10
図4
図4:ma_shift=-10
int shift:
現在のバー(ローソク足)から何本前の値を移動平均線の算出にしようするか。
が現在のバーを使用することを指定します。
(0にすると現在のバーが使われるので、移動平均線の値が次のバーがでるまで動き続けます。そうするとクロスしたり戻ったりという場面がでてきますので、僕としてはバーが算出されクロスが確定した状態が分かる1を設定することをお勧めします。1を設定すると最新のバーから一つ前のバーで移動平均線のクロスが確定していたらエントリーすることになります。)

____________________________________________________________________
shortEma=iMA(NULL,0,8,0,MODE_EMA,PRICE_CLOSE,0);
 longEma=iMA(NULL,0,13,0,MODE_EMA,PRICE_CLOSE,0);

さてこれで、上のコード文の意味が解りましたね。

私たちはShortEma変数の値を、
8日間で終値を使った、現在のバーでの指数移動平均。
というように設定したことになります。簡単に言うと8日指数移動平均線です。

LongEma変数の値は、
13日間で終値を使った、現在のバーでの指数移動平均。
というように割り振りました。簡単に言うと13日指数移動平均線です。

____________________________________________________________________
int isCrossed = Crossed(shortEma,longEma);

メモ:Crossed関数は二つのdoubleの値を設定値として持ち、integerの値を返却値として返します。
最初の設定値は監視して欲しいと思う一つ目のラインの値(私たちの場合は短期EMAになります)になり、二つ目の設定値は二つ目の監視してほしいラインの値(長期EMA)になります。
Crossed関数は、二つのラインをCrossed関数が呼び出される度にその二つのラインの状態を記憶するstatic変数の方向を保存することによって監視します。

 ・最新の方向が保存された時に何も変わらなければの値を返します。
 
・方向が変化(ラインが交差)し、かつ最初のラインが二つ目のラインの上にある時はを返します。

 ・方向が変化(ラインが交差)し、かつ最初のラインが二つ目のラインの下にある時はを返します。

ここでは、isCrossed変数をCrossed関数の値を入れる変数として宣言しました。これを使用してエントリーや手仕舞いの注文をします。
____________________________________________________________________

 total = OrdersTotal();
 if(total < 1)
  {
      ・・・・・・
  }

OrderTotalの返却値をtotal変数に割り振りました。

  メモ:OrderTotal関数は、オープン注文や未決注文の総数を返します。もしも0が返されれば、何も
     注文を発注していないことを表します。
     詳しくは補講第2回を読みなおしください。

その後、この数をチェックして、注文があるかないかを確認します。ifブロック内のコードは、total変数の値が既に入っている注文はないことを示す1より小さい値でなければ働きません。
____________________________________________________________________ 
if (isCrossed == 1)
   {
ticket=OrderSend(Symbol(),OP_BUY,Lots,Ask,3,0,Ask+TakeProfit*Point,
"My EA",12345,0,Green);
     if(ticket>0)
     {
     if(OrderSelect(ticket,SELECT_BY_TICKET,MODE_TRADES))
Print("BUY order operand : ",OrderOpenPrice());
     }
    else Print("Error opening BUY order : ",GetLastError());
     return(0);
     }

短期EMAと長期EMAがクロスして、短期EMAが長期EMAの上の状況になったら買いをいれます。
OrderSend関数を使うことによって買いエントリーの注文を入れます。

  メモ:OrderSend関数は売り/買いのオープンオーダー(指定した値段になると実行される注文)か、
     決済注文に指定のために使います。
     もしその注文が成功すればチケット(注文)番号が返却値として返され、失敗すれば-1が返さ
     れます。

  シンタックス:
int OrderSend(string symbol, int cmd, double volume, double price, int slippage, double stoploss,double, double takeprofit, string comment=NULL,int magic=0, detetime expriation=0,color allow_color=CLR_NONE)
補講2に詳しい記述がありますのでよろしければお読み直しください。

これらが、OrderSend関数で使った設定値です。

symbol:
私たちはSymbol関数を使って現在使用している通貨ペア名を取得し、OrderSend関数に受け渡しています。

cmd:
ここでは、買いポジションのエントリーをしたいのでOP_BUYをつかっています。

volume
ここでは外部変数であるLots変数(extern double Lots=0.1;)を指定することでユーザーが自由に変更できるようにしています。

price
ASK関数を使って、現在の買値を取得し、OrderSend関数に引き渡します。

slippage
最大許容スリッページの値は3としました。

stoploss
ここでは0を設定し、ストップロスの値は設定しないことを示しています。

takeprofit
ユーザーが与えた(初期設定はextern double TakeProfit=250.0;により250)TakeProfitの値とPoint関数の返却値を掛けたものにエントリーしたAskの値を足しています。


    メモ:Point関数は、現在使用されている通貨ペアのpip値です。
    例えば、もしあなたがEURUSDでトレードしていたならpip値は.0001になり、EURJPYならpip値は
    .01になります。
    ですので、OrderSendもしくはOrderModify関数と一緒に使用する前に、貴方のstoplossとtake
    profitの値のpip値を切り替えなくてはなりません。

comment
私たちは"My EA"の文字絵rつをコメントとして使用しました。

magic
マジックナンバーは12345と設定しました。

expiration
有効期限は設定していませんので0を使用しました。

arrow_color
エントリーのマークを緑にしました(なぜならお金は緑だからです。←Codersさんは日本人じゃありません)

OrderSend関数はもし注文に成功すればチケットナンバーを返します。ですので、私たちは以下のコード文を使うことで注文が成功したかどうかをチェックします。

 if(ticket>0)

OrderSelct関数をつかって、チケット番号によって注文を選択し、選択された注文のエントリーの値段を返すOrderOpenPrice関数の前にチケット番号を選択しておきます。

すべてがOKなら、OrderSendは特定のチケット番号(0以上の)を返します。そして、OrderSelect関数が成功すれば、それはユーザーに良いニュースを知らせるいい機会になります。彼に"BUY order opend"というメッセージとともにエントリー時の値段を表示して知らせてあげましょう。

  メモ:OrderSelectとOrderOpenPriceの詳細については補講第2回をご覧ください。

もしOrderSend関数が-1を返したら、それは、注文のエントリーが失敗したことを意味します。私たちはユーザーにこの悪い知らせを"Error opening BUY order:"に加えて、GetLastError関数から取得したエラー番号を表示させることによって知らせましょう。そしてこの状況の時は、return(0)を使ってこのstart関数を終了させなければなりません。


____________________________________________________________________
 if(isCrossed == 2)
    {

     ticket=OrderSend(Symbol(),OP_SELL,Lots,Bid,3,0,
     Bid-TakeProfit*Point,"My EA",12345,0,Red);
      if(ticket>0)
        {
        if(OrderSelect(ticket,SELECT_BY_TICKET,MODE_TRADES))
      Print("SELL order opened ; ",OrderOpenPrice());
        }
      else Print("Error opening Sell order : ",GetLastError());
       return(0);
       }

ここでは対照的な筋書きです。短期EMAと長期EMAがクロスして、長期EMAの下に短期EMAがある場合で、その時は売りを行います。

OrderSend関数を使って売り注文でエントリーします。OrderSend関数のBuy設定値とSell設定値との違いを予測してもらっても良いですか? そうです!貴方にプレゼントとして100pips差し上げたい!

今からあげる設定値は変わっていません。

symbol
volume
slippage
stoploss
comment
magic
expiration


これらの設定値は変わりました。

cmd
OP_SELLを使っています。エントリー時に売りから入りたいからです。

price
Bid関数をつかって現在の売りねをOrderSend関数に受け渡します。

takeprofit
ユーザーが定めたTakeProfit変数の値にPoint関数の返却値の値を掛けて、その計算結果を売値の結果から引きます。

arrow_color

ここでは赤色に売りでのエントリーのマークの色を指定しました。(なぜなら私たちはお金が好きで、お金は緑色ですが、売りポジションの時は別の色を使いたかったからです。)

私たちは簡単にOrderSend関数が呼び出されたあと上記の設定値によって何が起こったかを繰り返し説明することができます。

OrderSendがもし成功したならチケット番号を返します。
この数字が0より大きいかどうかをチェックすることでエラーがないことを確かめます。
OrderSelect関数をつかってOrderOpenPrice関数を使う前に注文を選択します。
全てが大丈夫だったら、ユーザーにこの良いニュースを("Sell Order Opend")に、エントリー時の値段を加えてメッセージを表示します。

そうでなければ、OrderSend関数は-1を返します。私たちはユーザーにこの悪い知らせを"Error opening SELL order:"と、エラー番号を加えて彼に伝え、return(0)を使ってstart関数を終了させます。
____________________________________________________________________ 
-ちょっとまって!(あなた)
-貴方が今説明した上記のifブロックのコードの最後の後に一行コードがあるよ!
-どちらにですか(私)
-ほら、これだよ。

 return(0);

そう!良く気付いたね。デモ今回はpipsをあげることはできないよ。
これらのブロックを注意深く見て。

if(total < 1)
  {
  if(isCrossed == 1)
    {
     ・・・・・
    }
    if(isCrossed == 2)
    {
      ・・・・・・
    }
       return(0); ←ここ!
    }

もし短期EMAが長期EMAが上向きにクロスしたら買い注文でエントリー。
もし短期EMAが長期EMAが下向きにクロスしたら売り注文でエントリー。

それではもしクロスをまだしてなかったらどうしますか?それがこのコード文の仕事です。
もしもクロスがなければ、私たちはstart関数を終了します。
(isCrossedの値が1でも2でもなかった時です)
____________________________________________________________________
さぁ私たちは今回で買い、売りポジションのエントリーをみてきました。

次の講義では、残りのコードをチェックして、ストラテジーテスターについて詳しく述べていきたいと思います。

今回の講義は楽しんでいただけたでしょうか。

Coder'sGuru



今回もお疲れ様でした。
長かった講義もあと3つで終了です。
全部読み終えたらなんか気持ちいいですね(笑)

何か質問がございましたらお願いいたします。


今回も最後までお読み頂きありがとうございました。


押していただけると凄い励みになりますのでよろしくお願いします。 

人気ブログランキングへ

theme : FXでシステムトレード
genre : 株式・投資・マネー

2009-04-13

メタトレーダー講義第16回 初めてのエキスパートアドバイザー第4回

ようやく到達しました。
初めてのエキスパートアドバイザーの終着章です。

MQL4の概念から学んでようやくここまでたどり着きましたね。お疲れ様でした。


ここで4月16日よりも前に初めてのエキスパートアドバイザーの講義をご覧頂いた方にお伝えしなければならないことがあるのですが・・
今回の記事をかいていて、僕らが書いていたコードにミスがあることがわかりました。

すいません。。
抜けたコードは
if(isCrossed ==2)
      {
         OrderClose(OrderTicket(),OrderLots(),Ask,3,Violet);
  //手仕舞い
     return(0); //次へ
      }

です。 下のコード文に修正場所を赤で入れておいたのでご覧ください。

そのコードがないことで、ドテン売買はしないようになっていました。付け加えたところ成績自体はおちてしまいましたが。。とにかく申し訳ありませんでした。

それでは始めますね。



この文章はCodersGuruさんのMQL4Lesson4の訳文です。(翻訳しての転載に本人の許可はとってあります)         
                      MQL4講座       
                     Coders'guru                               
                      www.forex-tsd.com                          
                           -16-
                 初めてのエキスパートアドバイザー
                   第4部


私たちは真実の探求への最終地点へと辿り着こうとしています。初めてのエキスパートアドバイザーの最後の部へと到達したことを大変うれしく思います。そうです!今回が最後のエキスパートアドバイバーの講義です。

貴方が簡潔ではありますが、重要なエキスパートアドバイザーの記述の仕方を発見する旅を楽しんでくれたことを願います。
それでは、最後のステップへ参りましょう。

私たちのコード

//+------------------------------------------------------------------+
//| My_First_EA.mq4 |
//| Coders Guru |
//| http://www.forex-tsd.com |
//+------------------------------------------------------------------+

#property copyright "Coders Guru"
#property link "http://www.forex-tsd.com"

//---- 埋め込まれた設定値
extern double TakeProfit=250.0;
extern double Lots=0.1;
extern double TrailingStop=35.0;
//+------------------------------------------------------------------+
//| expert initialization function                    |
//+------------------------------------------------------------------+

int init()
{
//----

//----

return(0);
}
//+------------------------------------------------------------------+
//| expert deinitialization function                   |
//+------------------------------------------------------------------+

int deinit()
{
//----

//----
return(0);
}
int Crossed (double line1 , double line2)
  {
   static int last_direction = 0;
   static int current_direction = 0;

   if(line1>line2)current_direction=1; //アップ
   if(line1<line2)current_direction=2; //ダウン

   if(current_direction !=last_direction) //変化
   {
      last_direction = current_direction;
      return(last_direction);
   }
   else
   {
     return (0);
   }
 }
//+------------------------------------------------------------------+
//| expert start function                     |
//+------------------------------------------------------------------+

int start()
 {
 int cnt, ticket, total;
 double shortEma,longEma;

 if(Bars<100)
 {
  Print("bars less than 100");
  return(0);
 }
 if(TakeProfit<10)
 {
  Print("TakeProfit less than 10");
  return(0); //check TakeProfit
  }

 shortEma=iMA(NULL,0,8,0,MODE_EMA,PRICE_CLOSE,0);
 longEma=iMA(NULL,0,13,0,MODE_EMA,PRICE_CLOSE,0);

 int isCrossed = Crossed(shortEma,longEma);

 total = OrdersTotal();
 if(total < 1)
  {
  if (isCrossed == 1)
   {
ticket=OrderSend(Symbol(),OP_BUY,Lots,Ask,3,0,Ask+TakeProfit*Point,
"My EA",12345,0,Green);
     if(ticket>0)
     {
     if(OrderSelect(ticket,SELECT_BY_TICKET,MODE_TRADES))
Print("BUY order operand : ",OrderOpenPrice());
     }
    else Print("Error opening BUY order : ",GetLastError());
     return(0);
     }
    if(isCrossed == 2)
    {

     ticket=OrderSend(Symbol(),OP_SELL,Lots,Bid,3,0,
     Bid-TakeProfit*Point,"My EA",12345,0,Red);
      if(ticket>0)
        {
        if(OrderSelect(ticket,SELECT_BY_TICKET,MODE_TRADES))
      Print("SELL order opened ; ",OrderOpenPrice());
        }
      else Print("Error opening Sell order : ",GetLastError());
       return(0);
       }
       return(0);
    }
     for(cnt=0;cnt<total;cnt++)
     {
     OrderSelect(cnt,SELECT_BY_POS,MODE_TRADES);
     if(OrderType()<=OP_SELL && OrderSymbol()==Symbol())
    {
    if(OrderType()==OP_BUY) //ロングポジションでエントリー
    {
    //手仕舞うか?
 
    if(isCrossed ==2)
      {
         OrderClose(OrderTicket(),OrderLots(),Ask,3,Violet);
  //手仕舞い
     return(0); //次へ
      }

    if(TrailingStop>0)
     {
     if(Bid-OrderOpenPrice()>Point*TrailingStop)
       {
       if(OrderStopLoss()<Bid-Point*TrailingStop)
        {
         OrderModify(OrderTicket(),OrderOpenPrice(),Bid-
          Point*TrailingStop,OrderTakeProfit(),0,Green);
         return(0);
         }
        }
       }
      }
     else//ショートポジションへ
      {
     //手仕舞うべきか
      if(isCrossed ==1)
      {
      OrderClose(OrderTicket(),OrderLots(),Ask,3,Violet);
  //手仕舞い
     return(0); //決済
      }
     //トレイリングストップのチェック
      if(TrailingStop>0)
       {
        if((OrderOpenPrice()-Ask)>(Point*TrailingStop))
        {
         if((OrderStopLoss()>(Ask+Point*TrailingStop)) ||
      (OrderStopLoss()==0))
             {

    OrderModify(OrderTicket(),OrderOpenPrice(),Ask+Point*TrailingStop,
     OrderTakeProfit(),0,Red);
            return(0);
             }
            }
           }
          }
         }
       }
 return(0);
 }
//+------------------------------------------------------------------+

____________________________________________________________________
前回の授業では、OrderTotal関数が1よりも小さければ、それはまだ何も注文が入っていないことを表すので、買いもしくは売りでのエントリー注文をしました。
私たちはこのコードを使いました。

if(total < 1)
  {
  if(isCrossed == 1)
    {
     ・・・・・
    }
    if(isCrossed == 2)
    {
      ・・・・・・
    }
      return(0);
  }

これはエントリー注文執行部分です。 今日は、調整手仕舞い注文部分を見ていきましょう。
____________________________________________________________________
 for(cnt=0;cnt<total;cnt++)
     {
     ........
     }
上記のコードは、forループを全てのエントリーされた注文が通過するようにしています。
cnt=0からループを始めます。そして既に執行された注文の総数になった時ループを終了します。
cntはループが繰り返されるたびに1ずつ増えていきます(cnt++)。ですので、cntは、すげての局面でのポジションの注文の値をとります。それぞれのポジションの指定にはOrderSelect関数を使用します。

今回の使命は上記のループの中ではどのようなことが起こっているかを学ぶことにあります。
____________________________________________________________________
OrderSelect(cnt,SELECT_BY_POS,MODE_TRADES);
     if(OrderType()<=OP_SELL && OrderSymbol()==Symbol())
    {
    ・・・・・
    }

OrderSelect関数はエントリー注文もしくは決済注文をチケットナンバーもしくはインデックスによって選択する時に使用します。

私たちはOrderSelect関数をOrderTypeとOrderSymbol関数を使う前に使用します。なぜならそれらの関数はOrderSelect関数を使わないと機能しないからです。

メモ:設定値をとらないトレーディング関数の前には、OrderSelect関数を使わ
  なければなりません。
  OrderMagicNumber, OrderClosePrice, OrderCloseTime, OrderOpenPrice, OrderOpen,Time,
  OrderComment,OrderCommission, OrderExpiration, OrderLots, OrderPrint, OrderProfit,
  OrderStoploss,OrderSwap,OrderSymbol,OrderTakeProfit,OrderTicket, OrderType


私たちはSELECT_BY_POSを使いました。これは注文をチケット番号ではなく、そのチケット(注文)のインデックス番号によって注文を選択するという意味です。

  メモ:最初の注文のインデックス番号は0で、2番目のインデックス番号はになります。

そして、MODE_TRADESを使いました。これは、履歴から選択するのではなく、現在のエントリー,未決済注文を選択するという意味です。

Ordertype関数は選択した注文の種類を以下の中から選んで返すものです。
OP_BUY,OP_SELL,OP_BUYLIMIT,OP_BUYSTOP,OP_SELLLIMIT,OP_SELLSTOP,

私たちは注文の種類をチェックしてOP_SELLと等しいか、もしくはそれより小さいか、或いはそうでないかを見つけます。これは二つの状況のどちらかを意味します。OP_SELLかOP_BUYです。(なぜならOP_SELLは1で、OP_BUYは0だからです。詳しくは補講2回目のOrderSendをご覧ください)
私たちは未決済注文に対しては働きかけたくないので、この二つの時のみ反応するようにしました。

また、私たちはエキスパートアドバイザーが注文したエントリー注文でのみ起動させたいと思っているため、現在のチャートの通貨の値を返すSymbol関数の返却値を使ってOrderSymbolの注文をチェックします。もしその値と等しいなら、それは今、注文がエキスパートアドバイザーによって取り付けられている注文と同じであることを意味します。

これからのすべてのコードは、注文の種類がOP_SELLかOP_BUY。そして、通貨ペアはOrderSymbolと同じものであるものでのみ働くようになります。

____________________________________________________________________
 if(OrderType()==OP_BUY) //ロングポジションでエントリー
    {
    ........
    }

私たちは二つの種類の注文でしか働かせないといいました。最初の種類はOP_BUYです。
上記のコードの意味は
ロングポジションでのエントリーはありますか?もしイエス!なら、このコードのブロックを実行してください。。
それでは、ロングポジションでのエントリー注文が約定していた場合どのようにするかを見ていきましょう。
____________________________________________________________________
if(isCrossed ==2)
 {
    OrderClose(OrderTicket(),OrderLots(),Bid,3,Violet);
    //手仕舞い
    return(0); //次へ
 }

短期EMAが長期EMAを上向きにクロスした時、買いのエントリー注文をいれます。
このポジションを短期EMAが長期EMAが逆向きの方向で(下向きに)クロスしたら手仕舞うのは合理的です。

ですので、isCrossedがもそし2になっていたら、逆方向でのクロスが起こったことを表しますので買いエントリー注文を手仕舞います。

OrderClose関数を手仕舞う為に使います。OrderClose関数は特定の注文をそのチケットによって手仕舞います(補講2回を読み直しください。)

私たちは選択した注文のチケット番号をOrderTicket関数によって取得し、OrderClose関数の最初の設定値としてその値を渡します。
OrderClose関数の二つ目のパラメーターはLots(ロット数)です。OrderLotsを使用して、選択した注文のロット数の値を取得します。
OrderClose関数の三つ目のパラメーターは手仕舞いの値段です。Bid関数を使用することで、選択した注文の買値を取得します。
4つ目のパラメーターはスリッページです。を使用しました。
5つ目のパラメーターは手仕舞いマークの色です。Violet(スミレ色)を使用しました。

Start関数を終了させる時にreturn(0)ステートメントを忘れないでくださいね。

____________________________________________________________________
 //トレイリングストップのチェック
    if(TrailingStop>0)
     {
     if(Bid-OrderOpenPrice()>Point*TrailingStop)
       {
       if(OrderStopLoss()<Bid-Point*TrailingStop)
        {
         OrderModify(OrderTicket(),OrderOpenPrice(),Bid-
          Point*TrailingStop,OrderTakeProfit(),0,Green);
         return(0);
         }
        }
       }

  メモ:まだ私たちはif(OrderType()==OP_BUY)のブロックの中にいます。

買いのエントリー注文のために、トレイリングストップの技術を追加しましょう。

最初に、ユーザーが適用可能なTrailingStop変数の値(0以上)を設定しているかどうかをチェックします。

それから、以下の条件の時にトレイリングストップの技術を買いエントリー注文に付け加えます。

私たちは、エントリー時の値段と、現在の買値価格とのが、設定したTrailingStop変数の値よりも大きい時に逆指値注文を調整します
そして
現在のストップロスの値は、現在の買値TrailingStop変数で設定した価格を付けひいた値よりも小さくなります。

OrderModify関数を使って臨むべき調整を行います。
以下はOrderModify関数と一緒に使用するパラメーターです。

ticket:現在の注文番号をOrderTicket関数をつかって取得します。

price:エントリーした時の値段をOrderOpenPrice関数を使って取得します。

stoploss:これが実際に働くものです!なぜなら、買いポジションを開いている間、現在の買値から、TrailingStopを引いた値を新しい逆指値の値段として、価格が動いている間セットし続けるからです。
これが私たちに利益を与えるために逆指値の値をひきずっていく方法になります。

  メモ:ストップロスは買い注文の時は常に現在の買値の下に位置し、売り注文でいる時は現在の売値の下に位置します。

takprofit:何も変えません。OrderTakeProfit関数をつかってその注文での現在の含み益の値を取得します。

expiration:私たちは有効期限を指定していませんので、0を使用します。

arrow_color:緑色でいきましょう。

最後に、start関数を終了させます。

____________________________________________________________________
 else//ショートポジションへ
      {
      ・・・・・
      }
  メモ:ここでelseに含まれている意味のコード。

  if(OrderType()==OP_BUY)
       {
       ・・・・・
       }

先ほどは買い注文での状況を学びました。
それでは、売り注文の時はどのように働くかを見ていきましょう。
既に注文されているのがショートポジションの時はどのようにしていくのかを見ていきましょう。

____________________________________________________________________
if(isCrossed ==1)
      {
      OrderClose(OrderTicket(),OrderLots(),Ask,3,Violet);
  //手仕舞い
     return(0); //次へ
      }

短期EMAが長期EMAを下向きにクロスした時、売りのエントリー注文をいれます。
このポジションを短期EMAが長期EMAが逆向きの方向で(上向きに)クロスしたらそれは手仕舞いするタイミングになります。isCrossed=1になったときがそのタイミングになります。

決済注文をいれるためにOrderClose関数を使用します。OrderClose関数の設定値は、買いでのエントリー時に、決済するために使用した手仕舞いの値段の設定値を、BidからAskに変更することを除いてすべて同じです。
そのあとstart関数を終了させます。

____________________________________________________________________
  //トレイリングストップのチェック
      if(TrailingStop>0)
       {
        if((OrderOpenPrice()-Ask)>(Point*TrailingStop))
        {
         if((OrderStopLoss()>(Ask+Point*TrailingStop)) ||
      (OrderStopLoss()==0))
             {

    OrderModify(OrderTicket(),OrderOpenPrice(),Ask+Point*TrailingStop,
     OrderTakeProfit(),0,Red);
            return(0);
             }
            }
           }

このコードのブロック(括弧で囲われた部分)では、トレイリングストップを、売りで開いているポジションのために、取り付けます。

最初に、ユーザーが適用可能なTrailingStop変数の値(0以上)を設定しているかどうかをチェックします。

それから、トレイリングストップを売りで開いているポジションを以下のようにして付け加えます。

私たちは、エントリー時の値段と、現在の売値価格とのが、設定したTrailingStop変数の値よりも大きい時に逆指値注文を調整します
そして
現在のストップロスの値は、現在の売値TrailingStop変数で設定した価格を付け加えた値よりも大きくなります。

私たちは望ましい変更を作り出すためにOrderModify関数を使用します。
そして先ほどの、買いでのエントリーポジションが入っている状況で使った設定値と、第三の設定値であるstoplossの値を除いてすべて同じものを使います。
私たちは新しい逆指値注文を、現在の売値にTrailingStop変数の値を足した値を指定していきます。

そして5つめの設定値であるマークの色は、Redにしましょう。

そして、start関数をreturn(0)を返すことによって終了させます。
____________________________________________________________________
 return(0);

この文はstart関数を終了させるためにどのようなケースでも使用します。例えば、新しいポジションを開くような状況ではない。すでに開いているポジションを調整したり手仕舞いしたりする必要はないなどです。覚えておいてください。

楽しんでいただけましたでしょうか。

Coders'Guru



以上で終わります。本当にお疲れ様でした。

何か皆さんのEAづくり等でのヒントとなるようなものが書けるようになりましたら書いていきたいと思いますのでよろしくお願いします。

最後まで読んで頂き大変ありがとうございました。



押していただけると凄い励みになりますのでよろしくお願いします。 

人気ブログランキングへ

theme : FXでシステムトレード
genre : 株式・投資・マネー

2009-05-11

ティック毎一回のみアラートを表示させる。

みなさんはあるインディケーターの条件を満たした時にアラートがなってくれたら良いなと考えたことはありませんか?
僕はそのためにメタトレーダーを始めたといっても過言ではありません。
今回はCodersGuruさんがAlertについて書かれていた記事を見つけたので翻訳してみました。

それではお楽しみください。
原文はhttp://www.metatrader.info/node/173です。


Alert Once Per Bar

やぁ兄弟。

Pink Floyedのアルバムで、"Brain Damage"という曲を聞いたことはありますか?聞く必要はありません! しかしMQL4のプログラミング脳で、Alertを一回だけ表示させるということは大変難しい挑戦になります。

1時間足で短期移動平均線が下から上に長期移動平均線を突き抜けた時、アラートを買い!と表示
させたい。素晴らしい!簡単? そうですね。しかし。。

上述した状況に出くわしたとき、まず一つのアラートが表示され、そして短期移動平均線が長期移動平均線の上にある間ずっとアラートが表示され続けます。

私は上述した状況の時、新しいティック(ローソク足)ごとにアラートを表示させたいと考えます。これが私がアラートを表示させる方法の記事を書いた理由です。

では、いつそれが新しいティック(ローソク足)だと言えるのでしょうか。

コードに、新しいティックだと告げるための二つの方法があります。
最初の方法は私が以前作成し、NewBar()と名付けた関数を使うことです。これは新しいティック(ローソク足)が届けられたらtrueを返し、そうでなければfalseを返します。

bool NewBar()
{
 static datetime lastbar ;
 datatime curbar = Time[0];
 if(lastbar!=curbar)
 {
  lastbar=curbar;
  return(true);
 }
 else
 {
   return(false);
 }
}

上記の関数は、最後の記憶されたティックの開始時間(ローソク足の始値が決まった時間)と、最新のティックの開始時間を比べます。もし、その時間が同じでないのならそれは新しいティックが届けられたことを意味し、trueの値を返します。そして、もし値が等しければ、そこには新しいティックは発見されなかったことを意味し、falseを返します。

この関数はもしあなたが一つの条件のみアラートを表示させたいのなら素晴らしいものになります。しかし、アラートを2つ以上の条件で表示させたい時があります。例えば以下の時に鳴らしたい場合

1-短期移動平均線が長期移動平均線を上に交差した時 買い!とアラートを表示させたい。

2-短期移動平均線が長期移動平均線を下に交差した時 売り!とアラーとを表示させたい。

3-二つ前のティックで短期移動平均線が長期移動平均線を上向きに交差した時、他のティックで買いが確認された!とアラートを表示させたい。

4-二つ前のティックで短期移動平均線が長期移動平均線を下向きに交差した時、他のティックで売りが確認にされた!とアラートを表示させたい。

私は4つのアラートが欲しいし、貴方はそれらを追いかけ続けなくてはなりません。そして、Alertはティック一本につき一回で良い!これがプログラミングのBrain Damageです :)!

それでは二つ目のタイプの新しいティックが届けられましたと報告する関数を見てみましょう。

static int LastAlert = 0;

if(LastAlert == 0 || LastAlert_1<Bars)
 {
    Alert(alert_msg);
    LastAlert=Bars;
 }

このコードは最後に保存されたバーの数と現在のバーの総数を比べているものです。もし、この総数が増えれば、それは新しいバーであるという意味を表します。私はこちらのコードの方をお勧めします。なぜなら、アラートよりもむしろ追跡する意味で使うからです。

アラートを一回だけ表示させるためのロジック。
このイメージ(10000語)。Alert一回関数の後ろにあるロジックをしるためにこのイメージをご覧ください(イメージはみれませんでした。原文はhttp://www.metatrader.info/node/173です。)

上のイメージでみれるように、このロジックはとても簡単です。

1-AlertOnce関数が呼び出された時、私たちはまず最初にこの関数が初めて呼び出されたものかをチェックします。そのようなとき、私たちはAlertのメッセージを表示させます。

2-もしそれは最初の呼び出しでなかった時、私たちは「最後のalertを発生させたローソク足は同じローソク足であるかどうか」をチェックします。これは新しいアラートにとって同じローソク足ですか?ということです。もしNoならアラートメッセージを表示させます。

イメージをコードに転換させましょう。

上記のイメージをコードに転換させる前に、新しい概念を付け加えたいと思います。Alertを表示させるための基準です。

私は4つのアラートを設定したいと思います。ですので、私はAlertを表示させる条件を加え、さらにそれぞれのアラートが一度限りで表示されるような関数を作りたいと思います。下に書いたコードがあなたの理解を進めるものになれば幸いです。

bool AlertOnce(string alert_msg, int ref)
{
static int LastAlert_1 = 0;
static int LastAlert_2 = 0;
static int LastAlert_3 = 0;
static int LastAlert_4 = 0;

switch(ref)
{
case 1:
if( LastAlert_1 == 0 || LastAlert_1 < Bars )
{
Alert(alert_msg);
LastAlert_1 = Bars;
return (1);
}
break;
case 2:
if( LastAlert_2 == 0 || LastAlert_2 < Bars )
{
Alert(alert_msg);
LastAlert_2 = Bars;
return (1);
}
break;
case 3:
if( LastAlert_3 == 0 || LastAlert_3 < Bars )
{
Alert(alert_msg);
LastAlert_3 = Bars;
return (1);
}
break;
case 4:
if( LastAlert_4 == 0 || LastAlert_4 < Bars )
{
Alert(alert_msg);
LastAlert_4 = Bars;
return (1);
}
break;
}
}

コードの説明
最初に私たちは4つのアラートの跡をつけました。ですので、私たちは
4つのstatic変数をそれぞれのアラートの値を保持させるために使用します。そして、switchキーワードをそれぞれのアラートに働くように使用します。こちらのほうが、すべてのアラームを設定するために4つの関数を使用するのよりも簡単だと思いませんか?

1-LastAlert_1(もしくは他の4つのアラートのうちの一つ)が0と等しい場合、それは私たちのalert_msgのアラートが初めて呼び出されたことを表し、LastAlert_1にチャートのローソク足の数字を割り当てます。

2-もしLastAlert_1がチャート上のローソク足より小さければ、私たちのalert_msgのアラートは新しいバーで行われた。

これだけです!    

どのように関数を呼び出すか:

これは簡単なことです。最初のアラートの種類(短期移動平均線が上向きにクロスした時に買う)を使用したい時は以下のようなコードを使ってください。

if (Cross(FMA ,SMA) == CROSS_UP)
AlertOnce ("We have to buy",1);

このアラートのリファレンス番号は1番だということを覚えておいてください。

これは便利だと思ってくださると幸いです。

Coders'Guru


翻訳は以上です。 
概念はわかりやすく説明されていたのですが、自分にはまだ疑問があって

1,関数はどこに保存したら良いのか
2.保存した関数をどうすれば読み込めるのか
3,時々わからない変数がでてくる

等があり僕の頭がBrain Damageになってしまいました。

自分で調べて作ってみたので次回、そのことについて触れてみたいと思います。


押していただけると大変励みになりますのでよろしくお願いします。 人気ブログランキングへ


theme : FXでシステムトレード
genre : 株式・投資・マネー

2009-05-11

アラート関数の作り方

前回CodersGuruさんのアラート関数を読み、自分でいろいろ試行錯誤した結果、アラート関数をつくり出すことに成功しました!
今回は僕が作ったアラート関数を紹介したいと思います。

アラート関数作成法

前科の疑問は
1,関数はどこに保存したら良いのか
2.保存した関数をどうすれば読み込めるのか
3,時々わからない変数が出てくる

というものでした。

前回の疑問の僕なりに出した答えはこちらです。
1,Libraryに保存します。
2,#import を使用したいコードの先頭で使用し、libraryに保存したコードを読み込みます。
3,分かりやすいアラートがならせるコードを探して応用する(こちらのBolliToucher.mq4 を参考にして作成しました。)

それでは関数を作っていきましょう。

ステップ1 Libraryに自作関数を保存する。

1,メタエディターのfile→Newをクリック。
2,Libraryをクリックして次へを選択。

Libra.png

3,NameにAlertOnceと入力→完了をクリック。

libra2.png


すると
//+------------------------------------------------------------------+
//| AlertOnce.mq4                    |
//| FXboy                      |
//| http://fxboyt.blog56.fc2.com/                  |
//+------------------------------------------------------------------+
#property copyright "FXboy"
#property link "http://fxboyt.blog56.fc2.com/"
//+------------------------------------------------------------------+
//| My function                      |
//+------------------------------------------------------------------+
// int MyCalculator(int value,int value2)
// {
// return(value+value2);
// }
//+------------------------------------------------------------------+

このようなものが出てきたと思います。(#propertyの2行はコードに関係ないので表示が違っていても全く問題ありません)

コメントで記述されているMyFunctionは例文だと思います。
MyFunction(私の関数)と書かれているのでここに自作関数を作るというのは間違いなさそうです。

それでは記述していきましょう。

//+------------------------------------------------------------------+
//| AlertOnce.mq4                    |
//| FXboy                      |
//| http://fxboyt.blog56.fc2.com/                  |
//+------------------------------------------------------------------+
#property copyright "FXboy"
#property link "http://fxboyt.blog56.fc2.com/"
#property library

extern bool Use_Sound=true;
//+------------------------------------------------------------------+
//| My function |
//+------------------------------------------------------------------+
void DoAlert()
{
if(!NewBar() || !Use_Sound)
return;
PlaySound("Alert2");
}

bool NewBar()
{
static datetime dt=0;
if(dt!=Time[0])
{
dt=Time[0];
return(true);
}
}
// int MyCalculator(int value,int value2)
// {
// return(value+value2);
// }
//+------------------------------------------------------------------+


記述する位置はどこでも良いのですがせっかくなのでMy functionと書かれている下から記述してみました。一番下の灰色のコメント部分は気になるようでしたら消しちゃってください。

このコードの概念としては前回の記事のCodersGuruさんのNewBarの判断の仕方と同じです。
ここではAlertではなく、音がなるだけですが、もしAlertになさりたければ、 PlaySound("Alert2");の部分をAlertに変更してください。

コードの解説は省きますが、
static変数は受け取った値を保持するという役割がある
! は「~でないなら」
|| は「もしくは」
NewBar関数を使ってDoAlert関数を機能させている。

ということを頭にいれておけばなんとなく理解できると思います。


先頭に#property libraryと記述しなければ、Start関数が無い(=何も動作をおこせない)じゃないかとコンパイラーが怒り出しますので注意してください。

以上で無事、アラート関数をつくり、保存することができました。

それでは次にこのアラート関数をどのようにして使うかを説明します。

ステップ2 アラート関数を呼び出す。
まずご自身のアラート関数を埋め込みたいと思われているインディケーターのコードをお開きください。
そしたらコードの先頭(init関数の始まる前)に

#import"AlertOnce.ex4"
bool NewBar();
void DoAlert();

を記述し、関数をよびだしてください(これで自分で作った関数が使えるようになります。)

あとはstart関数の中で自分がアラートを鳴らしたい場所にいれこんで頂ければ完了です。

参考までに僕が使用した例をのせておきます。

//+------------------------------------------------------------------+
//| TouchBB.mq4 |
//| FXboy |
//| http://fxboyt.blog56.fc2.com/ |
//+------------------------------------------------------------------+
#property copyright "FXboy"
#property link "http://fxboyt.blog56.fc2.com"

#property indicator_chart_window
#property indicator_buffers 3
#property indicator_color1 CLR_NONE
#property indicator_color2 Red
#property indicator_color3 Red
#import "AlertOnce.ex4"
bool NewBar();
void DoAlert();


double BufMA[];
double BufUpper[];
double BufLower[];


extern int BandsPeriod = 20;
extern double BandsDeviationsHigh = 2.0;
extern double BandsDeviationsLow =2.0;

//+------------------------------------------------------------------+
//|Custom indicator intialization function |
//+------------------------------------------------------------------+
int init()
{
SetIndexBuffer(0,BufMA);
SetIndexBuffer(1,BufUpper);
SetIndexBuffer(2,BufLower);



return(0);
}

//+------------------------------------------------------------------+
//|custom indicator interation function |
//+------------------------------------------------------------------+
int start()
{
int limit = Bars-IndicatorCounted();
if(limit == Bars) limit -= BandsPeriod-1;

for(int i=limit-1; i>=0; i--)
{
BufMA[i] = iMA(NULL,0,BandsPeriod,0,MODE_SMA,PRICE_CLOSE,i);

double sum=0.0;
for(int a=0; a {
double newres = Close[i+a]-BufMA[i];
sum += newres*newres;
}
double deviation = MathSqrt(sum/BandsPeriod);
BufUpper[i] = BufMA[i]+BandsDeviationsHigh*deviation;
BufLower[i] = BufMA[i]-BandsDeviationsLow*deviation;

if(i<2)
{

if(BufLower[i] + 50*Point>Bid) DoAlert() ;
if(BufUpper[i] - 50*Point<Bid) DoAlert();

}

}
return(0);
}
//+------------------------------------------------------------------+

このように使います。ロジックとしてはボリンジャーバンドにローソク足が触れる直前でサウンドを鳴らすというものです。

もしよろしければこちらにAlertOnce関数と、ボリンジャーバンドに価格が近付くとアラートがなるインディケーターを置いておきましたのでDLしてください。

TouchBBはMetaTrader-expert -indicatorのフォルダに
AlertOnceはMetaTrader-expert-librariesのフォルダに
いれてくださいね。

長くなってしまいましたが以上です。何か質問がありましたらシステムトレーダー交流所の方へお越しください。


最後までお付き合い頂きありがとうございました。

押していただけると大変励みになりますのでよろしくお願いします。 人気ブログランキングへ

theme : FXでシステムトレード
genre : 株式・投資・マネー

上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。