チケットの管理と重要性【自作EA】(MQL4)

チケットの管理の重要性

自作EAを作成する上で一番重要なのはチケット番号の管理です。
なぜなら、チケット番号を管理しないと同じ時間に大量のエントリーをしていたりします。これに気づかずに本番環境で運用してしまうとあっという間に余剰証拠金がなくなり、エントリーができなくなり、証拠金維持率がそこを尽きてお陀仏です(笑)
下記の画像のようになります。


上記の画像のように大量に同じ時間にエントリーしてしまいます。画像では10ポジションですが実際には200ポジションあります。下記の画像。上記の画像と同じバックテスト時のものです。

でバックテスト時のグラフが下記の画像になります。

地獄へ真っ逆さまです(笑)
これは極端な例ではなく実際に有り得ます。なのでチケットの管理はEAを作る上では非常に大切です。

チケット管理のやり方

これはサンプルによって管理の仕方が変わっています。時間単位でエントリーを制限していたり、OrdersTotal()関数でポジション数を管理していたり、チケット番号で管理していたりします。

時間単位で管理してみる

例えばローソク足1本に付き1エントリーに制限する場合は宣言済み変数Time[]を使います。

//現在のバーの形成開始時刻
Time[0];
//グローバル変数
datetime CurrentTimeStamp;
bool TicketTimeMgr= true;  //ローソク足ごとにエントリーのスイッチ(オン)
int OnTick(){
   int BarShift = 0;
   bool NewBar =false;

   if(TicketTimeMgr){
      BarShift =1;
    //現在のバー開始時刻と比較して開始時刻が違ければ
      if(CurrentTimeStamp != Time[0]){
         //現在のバーの開始時刻をグローバル変数に代入
         CurrentTimeStamp = Time[0];
         //エントリーをできるようにする
         NewBar = true;
      }else{
         //エントリーできなくする
         NewBar = false;
      }
   }else{
      NewBar = true;
      BarShift = 0;
   }
   //ローソク足ごとにエントリー
   if(NewBar){
      //---エントリー処理や決済処理をを記述する。
   }
}

この処理を記述してやればエントリーの制限ができます。
ただ根本的な解決にはなっていないのでちゃんとエントリー条件やチケットの管理状態をチェックしましょう。

ポジションの数で管理する

この方法はMetaQuotes社のサンプルにある管理方法です。
コードは下記

int CalculateCurrentOrders( void ) {

    // ローカル変数宣言
    int buys=0;  // 買ポジション数
    int sells=0; // 売ポジション数
    int icount;
    int OrderTotal = OrdersTotal(); //待機中&ポジション保有中の合計を返す
    //ポジションの合計が0なら処理終了
    if(OrderTotal < 1){return(0);}

    // 実際に保有しているポジションを検索
    for ( icount = 0 ; icount < OrderTotal ; icount++) {

        // 実際に現在保有しているポジションを選択する
        if( OrderSelect(icount,SELECT_BY_POS,MODE_TRADES) == false) {
            break; // 選択に失敗したら処理終了
        }
        // 現在、開いている通貨ペアと注文時に指定した通貨ペアがあっているか調べる
        // &
        // 注文時に指定したマジックナンバーとEAのマジックナンバーが同じものか調べる
        if( OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber) {
            // 買ポジションを保有していた場合
            if(OrderType()==OP_BUY) {  
                buys++;                // buysに+1する
            }
            // 売ポジションを保有していた場合
            if(OrderType()==OP_SELL) { 
                sells++;                // sellsに+1する
            }
        }
    }
    // 関数戻り値を設定
    if( buys > 0) {    // 買いポジションが1つでもあればそれを返す。
        return(buys);  
    } else {           // 買いポジションがなければ、0又は売りポジション数を返す。
       return(-sells); 
    }
}

int OnTick(){    
    // 現在保有中のポジションがなければ
    if ( CalculateCurrentOrders() ==0) {
        //エントリー処理
        Buy_Entry();                  
        Sell_Entey();
    } else {
        // ポジション保有していれば
        // クローズ処理を行う
        Buy_Settlement();         
        Sell_Settlement();
    }
    return(0);
}

ポジションがあればポジション数を返してエントリーをできなくしています。で決済関数を呼び出しています。

チケットで管理する

この方法は単純です。ポジションがある場合はチケット番号(自然数)が変数(チケット)に格納されています。

int Ticket = OrderSend(symbol,...);
//チケットの中身(仮)下記のコメント
//  Ticket = 12345;
//  Ticket = チケット番号(自然数)

注文エラーの場合は-1が返ります。

int Ticket = OrderSend(symbol,...);
//チケットの中身(仮)下記のコメント
//  Ticket = -1;
//  Ticket = エラー番号

でチケットを0で初期化すると上記のどちらにも属さないので、エラーでもなくポジションを持っているワケでもないのです。
なのでまずチケットを0で初期化

//グローバル変数
int Ticket = 0;

//entry
Ticket = OrderSend(symbol,...);
//Ticket = 12345;

//exit
OrderClose(Ticket,...);
//ポジションを決済後チケットを0に戻す
Ticket = 0;

今回は以上です。お読み頂きありがとうございました。

シェアする

  • このエントリーをはてなブックマークに追加

フォローする