ライブラリ: MT4Orders - ページ 19

 
Jeka77769:

MT5 の SELECT_BY_TICKET モードでの OrderSelect は、(テスターでは)まれに MT4 で意図したものと異なるものを選択することがあります。「具体的にどのようなケースか詳しく教えてください。

ポジション/取引/注文チケットが一致する場合。

 
クロス・プラットフォーム・コードのもう一つの例(説明

取引、自動取引システム、取引戦略のテストに関するフォーラム

エキスパートアドバイザー: eaBreakeven

fxsaber, 2018.01.11 08:13.

#include <MT4Orders.mqh>     //https://www.mql5.com/ja/code/16006
#include <Price_Compare.mqh> //https://www.mql5.com/ja/code/16169

input int    Breakeven           = 15;           //損益分岐点
input int    Distance            = 5;            //ポジションのオープン価格からのブレイクイーブンの距離。
input int    MagicNumber         = 16112017;     //マジックナンバー
input bool   EnableSound         = true;         //ブレークイーブンが設定されたときにサウンドを再生するかどうかを設定する。
input string SoundFile           = "alert1.wav"; //サウンドファイル名

void OnTick()
{
  DoBreakeven();
}

double GetNewStopLoss()
{
  const double point = SymbolInfoDouble(OrderSymbol(), SYMBOL_POINT);  
  const double stop_level = SymbolInfoInteger(OrderSymbol(), SYMBOL_TRADE_STOPS_LEVEL) * point;
  
  const double price_open = OrderOpenPrice();
  const double latest_price = OrderClosePrice();  
  const double stoploss = OrderStopLoss();

  double new_stoploss = 0;
  
  //--- 損益分岐点より利益が大きい場合、損切りは損益分岐点価格+距離で移動する。 
  return(((OrderType() == OP_BUY)  && (CP(latest_price - price_open, point) >= Breakeven * point) &&
                                      (CP(new_stoploss = price_open + Distance * point, point) > stoploss) &&
                                      (CP(latest_price - new_stoploss, point) > stop_level)) ||
         ((OrderType() == OP_SELL) && (CP(price_open - latest_price, point) >= Breakeven * point) &&
                                      ((CP(new_stoploss = price_open - Distance * point, point) < stoploss) || !stoploss) &&
                                      (CP(new_stoploss - latest_price, point) > stop_level))
         ? NormalizeDouble(new_stoploss, (int)SymbolInfoInteger(OrderSymbol(), SYMBOL_DIGITS)) : 0);
}

void DoBreakeven()
{
//ブレークイーブンが負の場合、ブレークイーブン機能を無効にする。
  if (Breakeven >= 0)      
  //ポジションのループ
    for (int i = OrdersTotal() - 1; i >= 0; i--)
      if (OrderSelect(i, SELECT_BY_POS) && (OrderType() <= OP_SELL) && (!MagicNumber || (OrderMagicNumber() == MagicNumber)))
      {
        const double new_stoploss = GetNewStopLoss();
        
        if (new_stoploss)      
        {
          if (!OrderModify(OrderTicket(), OrderOpenPrice(), new_stoploss, OrderTakeProfit(), OrderExpiration()))
            Print(GetLastError());
          else if(EnableSound)
            PlaySound(SoundFile);
        }
      }
}
 

取引、自動取引システム、取引戦略のテストに関するフォーラム

保留中の注文の数量を変更するには?

fxsaber, 2018.01.19 16:34

#include <MT4Orders.mqh> //https://www.mql5.com/ja/code/16006

// 保留中の注文の数量を変更します。Async = true - 注文を送信する非同期モード。
bool OrderChangeLots( const long Ticket, const double Lots, const bool Async = false )
{
  return(OrderSelect(Ticket, SELECT_BY_TICKET) && (Lots != OrderLots()) && (Async
         ? (OrderDeleteAsync(Ticket) &&
            OrderSendAsync(OrderSymbol(), OrderType(), Lots, OrderOpenPrice(), 0, OrderStopLoss(), OrderTakeProfit(), OrderComment(), OrderMagicNumber(), OrderExpiration()))
         : (OrderDelete(Ticket) &&
            (OrderSend(OrderSymbol(), OrderType(), Lots, OrderOpenPrice(), 0, OrderStopLoss(), OrderTakeProfit(), OrderComment(), OrderMagicNumber(), OrderExpiration()) != -1))));
}

void OnStart()
{
  for (int i = OrdersTotal() - 1; i >= 0; i--)
    if (OrderSelect(i, SELECT_BY_POS) && (OrderType() >= OP_BUYLIMIT))
      OrderChangeLots(OrderTicket(), OrderLots() + 1, true);
}
 
MT4のExpert Advisorがより良く書かれていればいるほど、それをMT5に変換するのは簡単です。また、元のEAのサイズ/複雑さは、変換時には重要ではありません。

取引、自動取引システム、取引戦略のテストに関するフォーラム。

エキスパートアドバイザー:3点アービトラージ

fxsaber, 2018.01.20 09:58

#define  MT4_TICKET_TYPE  // OrderSendとOrderTicketがMT4と同じ型(int)の値を返すようにします。
#include <MT4Orders.mqh> //https://www.mql5.com/ja/code/16006

#define MODE_MARGINREQUIRED 0

//https://www.mql5.com/ru/forum/170952/page9#comment_4134898
// 1ロットの購入に必要な自由資金の額
double MarketInfo( const string Symb, const int )
{
  MqlTick Tick;
  double MarginInit, MarginMain;

  return((SymbolInfoTick(Symb, Tick) && SymbolInfoMarginRate(Symb, ORDER_TYPE_BUY, MarginInit, MarginMain)) ? MarginInit * Tick.ask *
          SymbolInfoDouble(Symb, SYMBOL_TRADE_TICK_VALUE) / (SymbolInfoDouble(Symb, SYMBOL_TRADE_TICK_SIZE) * AccountInfoInteger(ACCOUNT_LEVERAGE)) : 0);
}

int DayOfWeek( void )
{
  MqlDateTime sTime = {0};

  TimeToStruct(TimeCurrent(), sTime);

  return(sTime.day_of_week);
}

int Hour( void )
{
  return((int)((TimeCurrent() % (24 * 3600)) / 3600));
}

#include "ThreePoint.mq4"
 
OnTradeTransactionを 使用すると、アカウント上で実行されているトレーディング「クローン」アドバイザーの存在を追跡する非トレーディングアドバイザー(サービス)を記述することができます。
 

ポジションを決済する ときの手数料も残高から即座に差し引かれます。

  • このため、すべてのポジションを決済する前のEquityには、決済後の残高が表示されません。
  • つまり、MT5 では単純に損益分岐点を計算することはできません。
  • MT4Orders には、ポジションに対する手数料が残っています。このため、次のような状況が発生します。

    #include <MT4Orders.mqh>
    
    #define  PRINT(A) Print(#A + " = " + (string)(A))
    
    void OnStart()
    {
      double ProfitWithoutCommission = 0;
      double ProfitWithCommission = 0;  
      
      for (int i = OrdersTotal(); i >= 0; i--)
        if (OrderSelect(i, SELECT_BY_POS))
        {
          OrderPrint();
          
          ProfitWithoutCommission += OrderProfit() + OrderSwap(); // 手数料を考慮せずに現在の利益を計算する
          
          ProfitWithCommission += OrderProfit() + OrderSwap() + OrderCommission(); // 手数料を考慮した現在の利益を計算する
        }
            
      PRINT(AccountInfoDouble(ACCOUNT_EQUITY) - AccountInfoDouble(ACCOUNT_BALANCE));
      
      PRINT(ProfitWithoutCommission);
      PRINT(ProfitWithCommission);  
    }


    結果

    #895889 2018.02.08 09:08:26 sell 1.00 EURUSD 1.22807 0.00000 0.00000 1.22877 -6.14 0.00 -70.00 0
    AccountInfoDouble(ACCOUNT_EQUITY)-AccountInfoDouble(ACCOUNT_BALANCE) = -70.0
    ProfitWithoutCommission = -70.0
    ProfitWithCommission = -76.14


    ご覧のように、Equity と Balance の差は手数料の分だけ異なります。そして、古典的な MT4 の表現が MT5 では意味を失うように見えるかもしれません。

    ProfitWithCommission += OrderProfit() + OrderSwap() + OrderCommission(); // 手数料を考慮した現在の利益を計算する

    はMT5では意味を失うと思われるかもしれません。しかし、そうではありません。実際、ポジションを決済すると、Equityが以前に示していた金額ではなく、Balanceがこの金額だけ変化します。大雑把に言えば、MT4のこの概念から見れば、MT5のEquityの値は偽りです。

    MT5のこの特殊性を考慮してください。この場合、ライブラリはより正確です。そして、同じ損益分岐点を計算するのは簡単でしょう。

     

    オープンポジションの コメントを失うことは初歩的なことです。これを行うには、ポジションシンボルのコメントなしで任意の取引を行うだけで十分です。

    OrderComment()はポジションがオープンされたときにあったコメントを生成します。

     
    // 変更リスト:
    // 13.02.2018
    // 追加: MT5-OrderSendエラーロギングを追加しました。
    // 修正: MT5のクローズ注文(SL/TP/SO、パーシャル/フルクローズ)のみが「不可視」になりました。
    // 修正:OrderClose後にクローズしたポジションのSL/TPを決定するメカニズムが修正されました。
     

    MT5操作のいくつかの特殊性について詳しく説明します。ライブラリは長い間 この状況を正しく 動作させていた。しかし、この状況は標準外であると悪態(アラート)をついていました。

    今は悪態をつきません。

    // 変更リスト:
    // 15.02.2018
    // 修正: MT5-OrderSendの同期チェックが、ECN/STP実装の特殊性を考慮するようになりました。


    テストとして、複雑なデモ口座FXOpen-MT5でこのスクリプトを実行できます。

    #include <Debug.mqh> //https://c.mql5.com/3/173/Debug.mqh
    #include <MT4Orders.mqh>
    
    #define Bid (SymbolInfoDouble(_Symbol, SYMBOL_BID))
    #define Ask (SymbolInfoDouble(_Symbol, SYMBOL_ASK))
    
    void OnStart()
    {
      _P(OrderCloseBy(_P(OrderSend(_Symbol, OP_BUY, 1, Ask, 0, 0, 0)), _P(OrderSend(_Symbol, OP_SELL, 1, Bid, 0, 0, 0))));
    }


    結果

    void OnStart(), Line = 9: OrderSend(_Symbol,OP_SELL,1,Bid,0,0,0) = 897247
    void OnStart(), Line = 9: OrderSend(_Symbol,OP_BUY,1,Ask,0,0,0) = 897248
    void OnStart(), Line = 9: OrderCloseBy(_P(OrderSend(_Symbol,OP_BUY,1,Ask,0,0,0)),_P(OrderSend(_Symbol,OP_SELL,1,Bid,0,0,0))) = true
    ファイル:
    Debug.mqh  1 kb
     

    取引、自動取引システム、取引戦略のテストに関するフォーラム

    ブルートフォース注文のサイクルの組織化

    fxsaber, 2018.02.16 09:40

    MT5が全然うまくいかない。問題を示す例

    // 各ティックにおける取引環境の不正確な読み取り例
    // スクリプトはTSの2ティックをエミュレートする。
    
    #include <Trade/Trade.mqh>
    
    // 文字ごとのポジション数を返す
    int GetAmountPositions( const string Symb )
    {
      int Res = 0;
      
      // このMQL5コードにはエラーがあります。
      for (int i = PositionsTotal() - 1; i >= 0; i--)
        if (PositionGetSymbol(i) == Symb)
          Res++;
    
    /*
    // MT4では、このコードはエラーなしで実行される
      for (int i = OrdersTotal() - 1; i >= 0; i--)
        if (OrderSelect(i, SELECT_BY_POS) && (OrderType() <= OP_SELL) && (OrderSymbol() == Symb))
          Res++;
    */      
      return(Res);
    }
    
    // OnTick の例
    void ExampleOnTick()
    {
      static CTrade Trade;
      
      // ポジションがない場合、オープン
      if (!GetAmountPositions(_Symbol))
        Trade.Buy(1);    
    }
    
    // 2つのティックイベントの到着のエミュレーション
    void OnStart()
    {
      ExampleOnTick(); 
      
      Sleep(10); // 2つのティックの間 ~10 ms.
      
      ExampleOnTick();
    }

    ポジションのないシンボルでこのスクリプトを実行した場合、最終的にどうなると思いますか?

    正解は、1つか2つのポジションが オープンされます。

    この問題は、少なくとも部分的にMQL4スタイルで記述すれば回避できます。それを確実にするには、GetAmountPositionsをMQL4スタイル(ソースコードではコメントアウト)で作り、MQL5スタイルを削除すれば十分だ。

    MQL5スタイルには特に注意してほしい。