ブログタイトルを「FX自動売買システム開発部」から「autoFX」に変更しました!

信頼できる注文変更関数

本記事で公開しているライブラリーは公開当時のままで、古くなっております。最新版のライブラリーはメルマガ登録いただくことでダウンロードできます。

注文変更はトレイリングストップで活躍する

注文時から利食いや損切り等の価格を変更する、MQL4の標準関数にOrderModify()があります。

このくだり、OrderSend()、OrderClose()及びOrderDelete()と一緒なので以下割愛です。OrderModify()が失敗した時を考慮した注文変更関数を紹介します。

//+------------------------------------------------------------------+
//|【関数】信頼できる注文変更                                        |
//|                                                                  |
//|【引数】 IN OUT  引数名             説明                          |
//|        --------------------------------------------------------- |
//|         ○      aTicket            チケット番号                  |
//|         ○      aPrice             待機注文の新しい仕掛け価格    |
//|         ○      aStoploss          損切り価格                    |
//|         ○      aTakeprofit        利食い価格                    |
//|         ○      aExpiration        待機注文の有効期限            |
//|         △      aArrow_color       チャート上の矢印の色          |
//|                                                                  |
//|【戻値】true :正常終了                                           |
//|        false:異常終了                                           |
//|                                                                  |
//|【備考】△:既定値あり                                            |
//+------------------------------------------------------------------+
bool orderModifyReliable(int aTicket, double aPrice, double aStoploss, 
     double aTakeprofit, datetime aExpiration, color aArrow_color = CLR_NONE)
{
  bool result = false;

  int startTime = GetTickCount();

  Print("Attempted orderModifyReliable(#" + aTicket + ", " + aPrice + ", SL:"+ aStoploss + ", 
  TP:" + aTakeprofit + ", Expiration:" + TimeToStr(aExpiration) + ", ArrowColor:" + aArrow_color + ")");

  bool selected = OrderSelect(aTicket, SELECT_BY_TICKET, MODE_TRADES);

  string symbol = OrderSymbol();
  int    type   = OrderType();

  double digits = MarketInfo(symbol, MODE_DIGITS);

  double price      = NormalizeDouble(OrderOpenPrice(), digits);
  double stoploss   = NormalizeDouble(OrderStopLoss(), digits);
  double takeprofit = NormalizeDouble(OrderTakeProfit(), digits);

  aPrice      = NormalizeDouble(aPrice,      digits);
  aStoploss   = NormalizeDouble(aStoploss,   digits);
  aTakeprofit = NormalizeDouble(aTakeprofit, digits);

  double stopLevel   = MarketInfo(symbol, MODE_STOPLEVEL) * MarketInfo(symbol, MODE_POINT);
  double freezeLevel = MarketInfo(symbol, MODE_FREEZELEVEL) * MarketInfo(symbol, MODE_POINT);

  while(true){
    if(IsStopped()){
      Print("Trading is stopped!");
      return(-1);
    }

    if(GetTickCount() - startTime > MAX_RETRY_TIME * MILLISEC_2_SEC){
      Print("Retry attempts maxed at " + MAX_RETRY_TIME + "sec");
      return(-1);
    }

    double ask = NormalizeDouble(MarketInfo(symbol, MODE_ASK), digits);
    double bid = NormalizeDouble(MarketInfo(symbol, MODE_BID), digits);

    // 仕掛け/損切り/利食いがストップレベル未満かフリーズレベル以下の場合、エラー
    if(type == OP_BUY){
      if(MathAbs(bid - aStoploss) < stopLevel){
        Print("StopLevel: SL was too close to brokers min distance (" + stopLevel + ")");
        return(-1);
      }else if(MathAbs(aTakeprofit - bid) < stopLevel){
        Print("StopLevel: TP was too close to brokers min distance (" + stopLevel + ")");
        return(-1);
      }else if(MathAbs(bid - aStoploss) <= freezeLevel){
        Print("FreezeLevel: SL was too close to brokers min distance (" + stopLevel + ")");
        return(-1);
      }else if(MathAbs(aTakeprofit - bid) <= freezeLevel){
        Print("FreezeLevel: TP was too close to brokers min distance (" + stopLevel + ")");
        return(-1);
      }
    }else if(type == OP_SELL){
      if(MathAbs(aStoploss - ask) < stopLevel){
        Print("StopLevel: SL was too close to brokers min distance (" + stopLevel + ")");
        return(-1);
      }else if(MathAbs(ask - aTakeprofit) < stopLevel){
        Print("StopLevel: TP was too close to brokers min distance (" + stopLevel + ")");
        return(-1);
      }else if(MathAbs(aStoploss - ask) <= freezeLevel){
        Print("FreezeLevel: SL was too close to brokers min distance (" + stopLevel + ")");
        return(-1);
      }else if(MathAbs(ask - aTakeprofit) <= freezeLevel){
        Print("FreezeLevel: TP was too close to brokers min distance (" + stopLevel + ")");
        return(-1);
      }
    }else if(type == OP_BUYLIMIT){
      if(MathAbs(ask - aPrice) < stopLevel && (aPrice != 0.0 && aPrice != price)){
        Print("StopLevel: OpenPrice was too close to brokers min distance (" + stopLevel + ")");
        return(-1);
      }else if(MathAbs(aPrice - aStoploss) < stopLevel && 
	    ((aPrice != 0.0 && aPrice != price) || (aStoploss != 0.0 && aStoploss != stoploss))){
        Print("StopLevel: SL was too close to brokers min distance (" + stopLevel + ")");
        return(-1);
      }else if(MathAbs(aTakeprofit - aPrice) < stopLevel && 
	    ((aPrice != 0.0 && aPrice != price) || (aTakeprofit != 0.0 && aTakeprofit != takeprofit))){
        Print("StopLevel: TP was too close to brokers min distance (" + stopLevel + ")");
        return(-1);
      }else if(MathAbs(ask - aPrice) <= freezeLevel && (aPrice != 0.0 && aPrice != price)){
        Print("FreezeLevel: OpenPrice was too close to brokers min distance (" + stopLevel + ")");
        return(-1);
      }
    }else if(type == OP_SELLLIMIT){
      if(MathAbs(aPrice - bid) < stopLevel && (aPrice != 0.0 && aPrice != price)){
        Print("StopLevel: OpenPrice was too close to brokers min distance (" + stopLevel + ")");
        return(-1);
      }else if(MathAbs(aStoploss - aPrice) < stopLevel && 
	    ((aPrice != 0.0 && aPrice != price) || (aStoploss != 0.0 && aStoploss != stoploss))){
        Print("StopLevel: SL was too close to brokers min distance (" + stopLevel + ")");
        return(-1);
      }else if(MathAbs(aPrice - aTakeprofit) < stopLevel && 
	    ((aPrice != 0.0 && aPrice != price) || (aTakeprofit != 0.0 && aTakeprofit != takeprofit))){
        Print("StopLevel: TP was too close to brokers min distance (" + stopLevel + ")");
        return(-1);
      }else if(MathAbs(aPrice - bid) <= freezeLevel && (aPrice != 0.0 && aPrice != price)){
        Print("FreezeLevel: OpenPrice was too close to brokers min distance (" + stopLevel + ")");
        return(-1);
      }
    }else if(type == OP_BUYSTOP){
      if(MathAbs(aPrice - ask) < stopLevel && (aPrice != 0.0 && aPrice != price)){
        Print("StopLevel: OpenPrice was too close to brokers min distance (" + stopLevel + ")");
        return(-1);
      }else if(MathAbs(aPrice - aStoploss) < stopLevel && 
	    ((aPrice != 0.0 && aPrice != price) || (aStoploss != 0.0 && aStoploss != stoploss))){
        Print("StopLevel: SL was too close to brokers min distance (" + stopLevel + ")");
        return(-1);
      }else if(MathAbs(aTakeprofit - aPrice) < stopLevel && 
	    ((aPrice != 0.0 && aPrice != price) || (aTakeprofit != 0.0 && aTakeprofit != takeprofit))){
        Print("StopLevel: TP was too close to brokers min distance (" + stopLevel + ")");
        return(-1);
      }else if(MathAbs(aPrice - ask) <= freezeLevel && (aPrice != 0.0 && aPrice != price)){
        Print("FreezeLevel: OpenPrice was too close to brokers min distance (" + stopLevel + ")");
        return(-1);
      }
    }else if(type == OP_SELLSTOP){
      if(MathAbs(bid - aPrice) < stopLevel && (aPrice != 0.0 && aPrice != price)){
        Print("StopLevel: OpenPrice was too close to brokers min distance (" + stopLevel + ")");
        return(-1);
      }else if(MathAbs(aStoploss - aPrice) < stopLevel && 
	    ((aPrice != 0.0 && aPrice != price) || (aStoploss != 0.0 && aStoploss != stoploss))){
        Print("StopLevel: SL was too close to brokers min distance (" + stopLevel + ")");
        return(-1);
      }else if(MathAbs(aPrice - aTakeprofit) < stopLevel && 
	    ((aPrice != 0.0 && aPrice != price) || (aTakeprofit != 0.0 && aTakeprofit != takeprofit))){
        Print("StopLevel: TP was too close to brokers min distance (" + stopLevel + ")");
        return(-1);
      }else if(MathAbs(bid - aPrice) <= freezeLevel && (aPrice != 0.0 && aPrice != price)){
        Print("FreezeLevel: OpenPrice was too close to brokers min distance (" + stopLevel + ")");
        return(-1);
      }
    }

    if(IsTradeContextBusy()){
      Print("Must wait for trade context");
    }else{
      result = OrderModify(aTicket, aPrice, aStoploss, aTakeprofit, aExpiration, aArrow_color);

      if(result){
        Print("Success! Ticket #", aTicket, " order modified, details follow");
        selected = OrderSelect(aTicket, SELECT_BY_TICKET, MODE_TRADES);
        OrderPrint();
        return(result);
      }

      int err = GetLastError();

      // 一時的エラーの場合はリトライするが、恒常的エラーの場合は処理中断(リトライしてもエラーになるため)
      if(err == ERR_NO_ERROR || 
         err == ERR_COMMON_ERROR ||
         err == ERR_SERVER_BUSY ||
         err == ERR_NO_CONNECTION ||
         err == ERR_TRADE_TIMEOUT ||
         err == ERR_INVALID_PRICE ||
         err == ERR_PRICE_CHANGED ||
         err == ERR_OFF_QUOTES ||
         err == ERR_BROKER_BUSY ||
         err == ERR_REQUOTE ||
         err == ERR_TRADE_CONTEXT_BUSY){
        Print("Temporary Error: " + err + " " + ErrorDescription(err) + ". waiting");
      }else{
        Print("Permanent Error: " + err + " " + ErrorDescription(err) + ". giving up");
        return(result);
      }

      // 最適化とバックテスト時はリトライは不要
      if(IsOptimization() || IsTesting()){
        return(result);
      }
    }

    Sleep(SLEEP_TIME * MILLISEC_2_SEC);
  }

  return(result);
}

orderSendReliable()と殆ど同じ作りですね。違いは待機注文の時だけ有効になるaPriceの考慮(オープンポジションの変更の場合、aPrice=0.0になりますので、その点の考慮)があるぐらいでしょうか。

サンプルEA

関数だけではイメージが沸きづらいと思いますので、サンプルEAを載せておきます。

「信頼できる注文変更関数」のSample.mq4
サイズ: 4.0KB
バージョン: 1.0
公開:2019年10月16日

MQL4プログラミングの最新記事8件

>完全放ったらかしEA 「AutoEndlessCatchRange」

完全放ったらかしEA 「AutoEndlessCatchRange」

「本業が忙しい!」「でも資産運用したい!」そんなあなたに最適なEAです。兼業トレーダーの方はチャートを毎日みて分析してトレードする時間はなかなか確保できないものです。トレードは本EAに任せて、本業やプライベートの時間をもっと増やしませんか?元々は自分自身のために開発したEAですので、手抜き無しのガチものです。

CTR IMG