MT5でOrderSendを正しく動作させる方法 - ページ 9

 
prostotrader:
https://www.mql5.com/ru/forum/97557/page4#comment_2891988
Документация по MQL5: Программы MQL5 / Выполнение программ
Документация по MQL5: Программы MQL5 / Выполнение программ
  • www.mql5.com
Программы MQL5 / Выполнение программ - справочник по языку алгоритмического/автоматического трейдинга для MetaTrader 5
 
fxsaber:

申し訳ありませんが、あなたのスクリプトに対応する気はありません。

によって追加されました。

しかし、そこから抜け出す方法がある。

OrderrSend()関数は同期式であるため、注文を受けた後、我々は

OnTradeTransaction()で履歴が同期されていることを確認する。

//+------------------------------------------------------------------+
// Expert TradeTransaction function                                  |
//+------------------------------------------------------------------+
void OnTradeTransaction(const MqlTradeTransaction &trans,
                        const MqlTradeRequest &request,
                        const MqlTradeResult &result)
  {
    switch(trans.type)
     {
      case TRADE_TRANSACTION_ORDER_UPDATE:
         switch(trans.order_state)
           {
            case ORDER_STATE_PLACED:
               if(order_ticket==trans.order)
                 {
                  Print(__FUNCTION__," Order plased done. Ticket = ",trans.order);
                  if(order_ticket>0)
                    {
                     if(OrderSelect(order_ticket))
                       {
                        //Ордер синхронизирован с историей
                       }
                     else
                       {
                        Print(__FUNCTION__," Order not select! Ticket = ",trans.order);
                       }
                    }
                  else
                    {
                     Print(__FUNCTION__," Wrong order ticket = ",trans.order);
                    }
                 }
               break;
           }
         break;
     }
  }

そして、ダンスは禁止!

 
prostotrader:

踊らない!?

トレーディング、自動売買システム、ストラテジーテストに関するフォーラム

MT5でOrderSendを正しく動作させる方法

fxsaber さん 2016.11.10 10:00

これはスクリプトであり、Event-overはありえない ことに注意してください。逃げ道は馬鹿なスリープしかない。

このスクリプトをSBで書き換えても、何も変わりません。

 
fxsaber:
Sleepで いくらでも捻じ曲げられる...。
 
prostotrader:
Sleepを好きなようにいじることができる...。

以前、他の人がすでに提案 し、声を上げていたことをなぜ繰り返すのか。

スレッドにはOnTradeTransactionで起こりうる問題点が全て書かれています。特に、複数のExpert Advisorを同時に操作することに関するものである。

人々が松葉杖をついているのは、ドキュメントを熟知していない、機能の使い方がわからないということではありません。

OnTradeとOnTradeTransactionは、まさにこの目的のために開発されました。開始当初は、アカウントで複数のExpert Advisorを同時に扱うのはバカバカしいと開発者は考えていた。

まあ、それは間違いだったんですけどね。

Expert Advisorに次のような関数を書いてみて ください。

  1. i = 0.
  2. シンボル[i]でポジションをオープンします。
  3. i++ >= 5 ならば終了する。
  4. スリッページがない場合はステップ2に戻り、スリッページがある場合は終了します。
 
fxsaber:

以前、他の人がすでに提案 し、声を上げていたことをなぜ繰り返すのか。

スレッドにはOnTradeTransactionで起こりうる問題点が全て書かれています。特に、複数のExpert Advisorを同時に操作することに関するものである。

人々が松葉杖をついているのは、ドキュメントを熟知していない、機能の使い方がわからないということではありません。

OnTradeとOnTradeTransactionは、まさにこの目的のために開発されました。開始当初は、アカウントで複数のExpert Advisorを同時に扱うのはバカバカしいと開発者は考えていた。

まあ、それは間違いだったんですけどね。

Expert Advisorに次のような関数を書いてみて ください。

  1. i = 0.
  2. シンボル[i]でポジションをオープンします。
  3. i++ >= 5 ならば終了する。
  4. スリッページがない場合はステップ2に戻り、スリッページがある場合は終了します。

現在、41のExpert Advisorが実際の口座(1つの端末)で稼働しており、取引日中にまとめて稼働しています。

2000件の注文のオープンポジションとクローズポジションを設定してくれていますが、全く問題がありません。

追加

持っている機能については、「必要なもの」ではなく、「持っているもの」を基準にすべきです。

開発者は、可能であれば、その意向を汲んで、バグを修正する。

のユーザーは、(非常にゆっくりではありますが)。

OederSend()もそのうち対応するんじゃないでしょうか。

 
prostotrader:

私のリアル口座(1つのターミナル)では、1日の取引で41のExpert Advisorが一斉に稼働しています。

2000件の注文、オープンポジション、クローズポジションを設定してくれますが、全く問題ありません。

こういうのを話題逸らしって言うんだよ。

最も単純なロジックであっても、それが実現したとき。

トレーディング、自動売買システム、トレーディング戦略のテストに関するフォーラム

MT5でOrderSendを正しく動作させる方法

fxsaber さん 2016.11.15 13:30

EAに以下のような関数を書いてみて ください。

  1. i = 0.
  2. シンボル[i]のポジションをオープンします。
  3. i++ >= 5 ならば終了する。
  4. 新しいポジションにスリッページがなければステップ2に戻り、スリッページがあれば終了します。
誰かがすぐにトレードしてくれる。
// MQL4&5-code

#property strict

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

void Func( const string &Symbols[] )
{
  const int Total = ArraySize(Symbols);
  
  for (int i = 0; i < Total; i++)
  {
    const double Price = SymbolInfoDouble(Symbols[i], SYMBOL_ASK);
    const int digits = (int)SymbolInfoInteger(Symbols[i], SYMBOL_DIGITS);
    
    if (!OrderSelect(OrderSend(Symbols[i], OP_BUY, 1, Price, 100, 0, 0, DoubleToString(Price, digits)), SELECT_BY_TICKET) ||
        (NormalizeDouble(Price - OrderOpenPrice(), digits) != 0)) // если не получилось открыть или есть проскальзывание - выходим
      break;
  }
}

void OnStart() // OnTick
{
  const string Symbols[] = {"EURUSD", "GBPUSD", "AUDUSD", "USDCAD", "USDJPY"};
  
  Func(Symbols);
}

そして、開発者からのマナを待つ人がいる。
 

どう捻じ曲げるかは自由であることは既に述べたとおりです(誰にでもその権利はあります)。

 
prostotrader:

私はすでに、あなたが好きなように捻じ曲げるのは自由であると言いました(誰にでもその権利はあります)。

昔の話ですが、この人、よく覚えていますよ、このfxsaberは 不思議な力を発揮しました。

彼のコードは今でもMT4のコードベースに保存されており、WinInetでサイトを読み込むためのコード

は、今でも多くのプログラマーに使われているのですが...。

ということで、変態ではないようです・・・。

 
ライブラリからOrderSendSyncを 抜き出すと、以下のようになります。
uint OrderSend_MaxPause = 1000000; // максимальное время на синхронизацию в мкс.

const bool IsTester = (::MQLInfoInteger(MQL_TESTER) || ::MQLInfoInteger(MQL_OPTIMIZATION) ||
                       ::MQLInfoInteger(MQL_VISUAL_MODE) || ::MQLInfoInteger(MQL_FRAME_MODE));
                      
                      

bool Waiting( const bool FlagInit = false )
{
  static ulong StartTime = 0;

  if (FlagInit)
    StartTime = ::GetMicrosecondCount();

  const bool Res = (::GetMicrosecondCount() - StartTime < OrderSend_MaxPause);

  if (Res)
    ::Sleep(0);

  return(Res);
}

bool EqualPrices( const double Price1, const double Price2, const int digits)
{
  return(::NormalizeDouble(Price1 - Price2, digits) == 0);
}

#define WHILE(A) while (!(Res = (A)) && Waiting())

bool OrderSendSync( const MqlTradeRequest &Request, MqlTradeResult &Result )
{
  bool Res = ::OrderSend(Request, Result);

  if (Res && !IsTester && (Result.retcode < TRADE_RETCODE_ERROR) && (OrderSend_MaxPause > 0))
  {
    Res = (Result.retcode == TRADE_RETCODE_DONE);
    Waiting(true);

    if (Request.action == TRADE_ACTION_DEAL)
    {
      WHILE(::HistoryOrderSelect(Result.order))
        ;

      Res = Res && (((ENUM_ORDER_STATE)::HistoryOrderGetInteger(Result.order, ORDER_STATE) == ORDER_STATE_FILLED) ||
                    ((ENUM_ORDER_STATE)::HistoryOrderGetInteger(Result.order, ORDER_STATE) == ORDER_STATE_PARTIAL));

      if (Res)
        WHILE(::HistoryDealSelect(Result.deal))
          ;
    }
    else if (Request.action == TRADE_ACTION_PENDING)
    {
      if (Res)
        WHILE(::OrderSelect(Result.order))
          ;
      else
      {
        WHILE(::HistoryOrderSelect(Result.order))
          ;

        Res = false;
      }
    }
    else if (Request.action == TRADE_ACTION_SLTP)
    {
      if (Res)
      {
        bool EqualSL = false;
        bool EqualTP = false;

        const int digits = (int)::SymbolInfoInteger(Request.symbol, SYMBOL_DIGITS);

        if ((Request.position == 0) ? ::PositionSelect(Request.symbol) : ::PositionSelectByTicket(Request.position))
        {
          EqualSL = EqualPrices(::PositionGetDouble(POSITION_SL), Request.sl, digits);
          EqualTP = EqualPrices(::PositionGetDouble(POSITION_TP), Request.tp, digits);
        }

        WHILE((EqualSL && EqualTP))
          if ((Request.position == 0) ? ::PositionSelect(Request.symbol) : ::PositionSelectByTicket(Request.position))
          {
            EqualSL = EqualPrices(::PositionGetDouble(POSITION_SL), Request.sl, digits);
            EqualTP = EqualPrices(::PositionGetDouble(POSITION_TP), Request.tp, digits);
          }
      }
    }
    else if (Request.action == TRADE_ACTION_MODIFY)
    {
      if (Res)
      {
        bool EqualSL = false;
        bool EqualTP = false;

        const int digits = (int)::SymbolInfoInteger(Request.symbol, SYMBOL_DIGITS);

        if (::OrderSelect(Result.order))
        {
          EqualSL = EqualPrices(::OrderGetDouble(ORDER_SL), Request.sl, digits);
          EqualTP = EqualPrices(::OrderGetDouble(ORDER_TP), Request.tp, digits);
        }

        WHILE((EqualSL && EqualTP))
          if (::OrderSelect(Result.order))
          {
            EqualSL = EqualPrices(::OrderGetDouble(ORDER_SL), Request.sl, digits);
            EqualTP = EqualPrices(::OrderGetDouble(ORDER_TP), Request.tp, digits);
          }
      }
    }
    else if (Request.action == TRADE_ACTION_REMOVE)
      if (Res)
        WHILE(::HistoryOrderSelect(Result.order))
          ;
  }

  return(Res);
}

#undef WHILE
コードの考え方は明確であるべきです。何か見落としているかもしれません。動作に不具合は感じない。