例えば、以下のやり方で指値注文のオーダー管理をした場合・・・
-----
(注文関数)
Ticket = OrderSend(Symbol(), OP_BUYSTOP, ロット数, 指値, スリッページ, 0, 0, コメント, マジックナンバー, 有効期限, チャートの矢印色);
return (Ticket);
(注文が通ったか確認する関数)
ordersuccess = OrderSelect(Ticket, SELECT_BY_TICKET);
if (ordersuccess){
if (OrderMagicNumber() == マジックナンバー && OrderType() == OP_BUY) return (true);
else return (false);
}
-----
このような形で、指値注文が刺さったかどうかをチケット番号(上記のTicketには同じ値が入ります)で検索するコードを組んだ場合、オアンダ以外の業者であればこのコーディングで正常に機能します。
しかし、ここでオアンダを使った場合に落とし穴が。。。
指値注文が刺さった場合、オアンダのチケット管理方法ではチケット番号が引き継がれません。
刺さった後のオーダーは別のチケット番号として管理されます。
つまり、上記のコード(赤太字部分)において、Orderselectでチケット番号を検索しても既にアクティブなチケットでなくなっているわけです。
もちろんMQLの仕様として「チケット番号は引き継がれなくてはならない」というルールは無いので、この管理方法が悪いと言っているわけではないのですが、デファクトとしてチケット番号は引き継がれるのがスタンダードのため、オアンダを利用する際には注意が必要ですということです。
#しかも困ったことに、デモ口座だと普通に引き継がれるから、デモ口座テストでは検出できないんですよね・・・リアル口座運用して初めて「ふざけんな!!」ってなるパターンです。
とうことで、こんな感じでいちいち注文が入ったか確認する必要があります。
#売買を1関数にまとめることも可能ですが、めんどくさいので買い注文に限定したコードです。
複数ポジションを管理する場合、もう少し複雑になります。
-----
int TicketOfEnteredBuyStopOrder(int MagicNumber)
//買い指値オーダーの刺さったチケット番号を返却。ない場合は-1を返却。
{
int Ticket = -1;
bool ordersuccess = false;
for (int i = 0; i < OrdersTotal(); i++){
ordersuccess = OrderSelect(i, SELECT_BY_POS);
if (ordersuccess){
if (OrderMagicNumber() == MagicNumber && OrderType() == OP_BUY){
Ticket = OrderTicket();
break;
}
}
}
return (Ticket);
}
-----
アルパリ破綻に伴って他のブローカーで同一のEA動作を検証している方も多いかと思いますが、デファクトを仕様と誤認すると思わぬ落とし穴があったりするので皆様も気をつけましょう。。。
以上です。
チケット番号引き継がれないんですね。
なるほど。。
リアルとデモで違うとはびっくりです。
ブログ更新楽しみにしています。
コメントありがとうございます。励みになります。
ご参考になったのであれば光栄です。
ブローカー毎に微妙な差分があるので、運用テストをどこまでやるかはいつも悩まされます。。。