文系人間のためのシステムトレーダー養成所 メタトレーダー講義第16回 初めてのエキスパートアドバイザー第4回
--------

スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。
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 : 株式・投資・マネー

コメントの投稿

管理者にだけ表示を許可する

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