Библиотеки: MT4Orders - страница 11

 
Aliaksandr Kryvanos:
Ясно, а можете натолкнуть на мысль как GetLastError()  заставить выводить и ошибки торгового сервера, я бы написал сам, если у Вас пока нет времени. Спасибо
По той же схеме, как реализована OrdersTotal. Скорее всего, напишу расширенный GetLastError. А также GetLastTradeRequest() и GetLastTradeResult().
 
fxsaber:
Скорее всего, напишу расширенный GetLastError. А также GetLastTradeRequest() и GetLastTradeResult().

Изучив GetLastError, сделал вывод, что дополнять его нецелесообразно.

После проверки будет доступно обновление

// Список изменений:
// 08.02.2017:
//   Add: Переменные MT4ORDERS::LastTradeRequest и MT4ORDERS::LastTradeResult содержат соответствующие данные MT5-OrderSend.

Теперь можно получать полностью все данные MT5-OrderSend.
 

 
// Скрипт позволяет быстро разобраться, как в MT5 формировать соответствующий MT4-аналогу MqlTradeRequest-запрос в MT5-OrderSend.

#define TOSTRING(A)  #A + " = " + (string)(A) + "\n"
#define TOSTRING2(A) #A + " = " + EnumToString(A) + " (" + (string)(A) + ")\n"

string ToString( const MqlTradeRequest &Request )
{
  return(TOSTRING2(Request.action) + TOSTRING(Request.magic) + TOSTRING(Request.order) +
         TOSTRING(Request.symbol) + TOSTRING(Request.volume) + TOSTRING(Request.price) +
         TOSTRING(Request.stoplimit) + TOSTRING(Request.sl) +  TOSTRING(Request.tp) +
         TOSTRING(Request.deviation) + TOSTRING2(Request.type) + TOSTRING2(Request.type_filling) +
         TOSTRING2(Request.type_time) + TOSTRING(Request.expiration) + TOSTRING(Request.comment) +
         TOSTRING(Request.position) + TOSTRING(Request.position_by));
}

string ToString( const MqlTradeResult &Result )
{
  return(TOSTRING(Result.retcode) + TOSTRING(Result.deal) + TOSTRING(Result.order) +
         TOSTRING(Result.volume) + TOSTRING(Result.price) + TOSTRING(Result.bid) +
         TOSTRING(Result.ask) + TOSTRING(Result.comment) + TOSTRING(Result.request_id) +
         TOSTRING(Result.retcode_external));
}

#include <MT4Orders.mqh>

#define PRINT(A) A; Print(#A + "\n" + ToString(MT4ORDERS::LastTradeRequest) + ToString(MT4ORDERS::LastTradeResult));

#define Point _Point
#define Bid (::SymbolInfoDouble(_Symbol, ::SYMBOL_BID))
#define Ask (::SymbolInfoDouble(_Symbol, ::SYMBOL_ASK))

void OnStart()
{
  Print(TOSTRING(AccountInfoString(ACCOUNT_SERVER)));
  
  // Открыли позицию
  const int TicketPosition = PRINT(OrderSend(NULL, OP_BUY, 1, Ask, 100, 0, 0, "My Position"))

  if (OrderSelect(TicketPosition, SELECT_BY_TICKET))
  {
    // Установили SL/TP
    PRINT(OrderModify(OrderTicket(), OrderOpenPrice(), Bid - 100 * Point, Bid + 100 * Point, 0))

    // Закрыли позицию
    PRINT(OrderClose(OrderTicket(), OrderLots(), Bid, 100))
  }

  // Установили отложенный ордер
  const int TicketOrder = PRINT(OrderSend(NULL, OP_BUYLIMIT, 1, Ask - 100 * Point, 100, 0, 0, "My Order"))

  if (OrderSelect(TicketOrder, SELECT_BY_TICKET))
  {
    // Удалили ордер
    PRINT(OrderDelete(OrderTicket()))
  }
}
 
Отлично работает, спасибо
 
Результат работы скрипта
AccountInfoString(ACCOUNT_SERVER) = FXOpen-MT5

OrderSend(NULL,OP_BUY,1,Ask,100,0,0,My Position)
Request.action = TRADE_ACTION_DEAL (1)
Request.magic = 0
Request.order = 0
Request.symbol = EURUSD
Request.volume = 1.0
Request.price = 1.06455
Request.stoplimit = 0.0
Request.sl = 0.0
Request.tp = 0.0
Request.deviation = 100
Request.type = ORDER_TYPE_BUY (0)
Request.type_filling = ORDER_FILLING_IOC (1)
Request.type_time = ORDER_TIME_GTC (0)
Request.expiration = 1970.01.01 00:00:00
Request.comment = My Position
Request.position = 0
Request.position_by = 0
Result.retcode = 10009
Result.deal = 9320
Result.order = 57775
Result.volume = 1.0
Result.price = 0.0
Result.bid = 0.0
Result.ask = 0.0
Result.comment = My Position
Result.request_id = 589
Result.retcode_external = 0

OrderModify(OrderTicket(),OrderOpenPrice(),OrderOpenPrice()-100*Point,OrderOpenPrice()+100*Point,0)
Request.action = TRADE_ACTION_SLTP (6)
Request.magic = 0
Request.order = 0
Request.symbol = EURUSD
Request.volume = 0.0
Request.price = 0.0
Request.stoplimit = 0.0
Request.sl = 1.06355
Request.tp = 1.06555
Request.deviation = 0
Request.type = ORDER_TYPE_BUY (0)
Request.type_filling = ORDER_FILLING_FOK (0)
Request.type_time = ORDER_TIME_GTC (0)
Request.expiration = 1970.01.01 00:00:00
Request.comment =
Request.position = 57775
Request.position_by = 0
Result.retcode = 10009
Result.deal = 0
Result.order = 0
Result.volume = 1.0
Result.price = 0.0
Result.bid = 0.0
Result.ask = 0.0
Result.comment = Request executed
Result.request_id = 590
Result.retcode_external = 0

OrderClose(OrderTicket(),OrderLots(),Bid,100)
Request.action = TRADE_ACTION_DEAL (1)
Request.magic = 0
Request.order = 0
Request.symbol = EURUSD
Request.volume = 1.0
Request.price = 1.0645
Request.stoplimit = 0.0
Request.sl = 0.0
Request.tp = 0.0
Request.deviation = 100
Request.type = ORDER_TYPE_SELL (1)
Request.type_filling = ORDER_FILLING_IOC (1)
Request.type_time = ORDER_TIME_GTC (0)
Request.expiration = 1970.01.01 00:00:00
Request.comment =
Request.position = 57775
Request.position_by = 0
Result.retcode = 10009
Result.deal = 9321
Result.order = 57776
Result.volume = 1.0
Result.price = 0.0
Result.bid = 0.0
Result.ask = 0.0
Result.comment = Request executed
Result.request_id = 591
Result.retcode_external = 0

OrderSend(NULL,OP_BUYLIMIT,1,Ask-100*Point,100,0,0,My Order)
Request.action = TRADE_ACTION_PENDING (5)
Request.magic = 0
Request.order = 0
Request.symbol = EURUSD
Request.volume = 1.0
Request.price = 1.06356
Request.stoplimit = 0.0
Request.sl = 0.0
Request.tp = 0.0
Request.deviation = 100
Request.type = ORDER_TYPE_BUY_LIMIT (2)
Request.type_filling = ORDER_FILLING_IOC (1)
Request.type_time = ORDER_TIME_GTC (0)
Request.expiration = 1970.01.01 00:00:00
Request.comment = My Order
Request.position = 0
Request.position_by = 0
Result.retcode = 10009
Result.deal = 0
Result.order = 57777
Result.volume = 1.0
Result.price = 1.06356
Result.bid = 0.0
Result.ask = 0.0
Result.comment = My Order
Result.request_id = 592
Result.retcode_external = 0

OrderDelete(OrderTicket())
Request.action = TRADE_ACTION_REMOVE (8)
Request.magic = 0
Request.order = 57777
Request.symbol =
Request.volume = 0.0
Request.price = 0.0
Request.stoplimit = 0.0
Request.sl = 0.0
Request.tp = 0.0
Request.deviation = 0
Request.type = ORDER_TYPE_BUY (0)
Request.type_filling = ORDER_FILLING_FOK (0)
Request.type_time = ORDER_TIME_GTC (0)
Request.expiration = 1970.01.01 00:00:00
Request.comment =
Request.position = 0
Request.position_by = 0
Result.retcode = 10009
Result.deal = 0
Result.order = 57777
Result.volume = 1.0
Result.price = 1.06356
Result.bid = 0.0
Result.ask = 0.0
Result.comment = My Order
Result.request_id = 593
Result.retcode_external = 0
Теперь легко разобраться, как правильно формировать соответствующие торговые запросы в MT5.
 
// Скрипт проверяет скоростные характеристики обработки основных типов торговых приказов MT5.

#define TOSTRING(A)  #A + " = " + (string)(A) + "\n"
#define TOSTRING2(A) #A + " = " + EnumToString(A) + " (" + (string)(A) + ")\n"

string ToString( const MqlTradeRequest &Request )
{
  return(TOSTRING2(Request.action) + TOSTRING(Request.magic) + TOSTRING(Request.order) +
         TOSTRING(Request.symbol) + TOSTRING(Request.volume) + TOSTRING(Request.price) +
         TOSTRING(Request.stoplimit) + TOSTRING(Request.sl) +  TOSTRING(Request.tp) +
         TOSTRING(Request.deviation) + TOSTRING2(Request.type) + TOSTRING2(Request.type_filling) +
         TOSTRING2(Request.type_time) + TOSTRING(Request.expiration) + TOSTRING(Request.comment) +
         TOSTRING(Request.position) + TOSTRING(Request.position_by));
}

string ToString( const MqlTradeResult &Result )
{
  return(TOSTRING(Result.retcode) + TOSTRING(Result.deal) + TOSTRING(Result.order) +
         TOSTRING(Result.volume) + TOSTRING(Result.price) + TOSTRING(Result.bid) +
         TOSTRING(Result.ask) + TOSTRING(Result.comment) + TOSTRING(Result.request_id) +
         TOSTRING(Result.retcode_external));
}

ENUM_DAY_OF_WEEK GetDayOfWeek( const datetime time )
{
  MqlDateTime sTime = {0};

  ::TimeToStruct(time, sTime);

  return((ENUM_DAY_OF_WEEK)sTime.day_of_week);
}

bool SessionTrade( const string Symb )
{
  datetime TimeNow = ::TimeTradeServer();

  const ENUM_DAY_OF_WEEK DayOfWeek = GetDayOfWeek(TimeNow);

  TimeNow %= 24 * 60 * 60;

  bool Res = false;
  datetime From, To;

  for (int i = 0; (!Res) && ::SymbolInfoSessionTrade(Symb, DayOfWeek, i, From, To); i++)
    Res = ((From <= TimeNow) && (TimeNow < To));

  return(Res);
}

bool SymbolTrade( const string Symb )
{
  MqlTick Tick;

  return(::SymbolInfoTick(Symb, Tick) ? ((Tick.bid != 0) && (Tick.ask != 0) && SessionTrade(Symb) &&
         ((ENUM_SYMBOL_TRADE_MODE)::SymbolInfoInteger(Symb, SYMBOL_TRADE_MODE) == SYMBOL_TRADE_MODE_FULL)) : false);
}

#define MT4ORDERS_BENCHMARK Alert(MT4ORDERS::LastTradeRequest.symbol + " " +       \
                                  (string)MT4ORDERS::LastTradeResult.order + " " + \
                                  MT4ORDERS::LastTradeResult.comment);             \
                            Print(ToString(MT4ORDERS::LastTradeRequest) +          \
                                  ToString(MT4ORDERS::LastTradeResult));

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


#define Point (SymbolInfoDouble(Symb, SYMBOL_POINT))
#define Bid (SymbolInfoDouble(Symb, SYMBOL_BID))
#define Ask (SymbolInfoDouble(Symb, SYMBOL_ASK))

void Benchmark( string Symb = NULL, uint LimitOffset = 1000 )
{
  if (Symb == NULL)
    Symb = _Symbol;

  if (SymbolTrade(Symb))
  {
    const bool DemoAccount = ((ENUM_ACCOUNT_TRADE_MODE)AccountInfoInteger(ACCOUNT_TRADE_MODE) == ACCOUNT_TRADE_MODE_DEMO);
    const double MinLot = SymbolInfoDouble(Symb, SYMBOL_VOLUME_MIN);

    const uint StopLevel = (uint)SymbolInfoInteger(Symb, SYMBOL_TRADE_STOPS_LEVEL);

    if (StopLevel != 0)
      LimitOffset = StopLevel;

    if (DemoAccount && OrderSelect(OrderSend(Symb, OP_BUY, MinLot, Ask, 100, 0, 0, __FUNCTION__ + "_Position"), SELECT_BY_TICKET))
    {
      OrderModify(OrderTicket(), OrderOpenPrice(), 0, Bid + LimitOffset * Point, 0);
      OrderClose(OrderTicket(), OrderLots(), Bid, 100);
    }

    double PriceMin = SymbolInfoDouble(Symb, SYMBOL_SESSION_PRICE_LIMIT_MIN);

    if (PriceMin < Point)
      PriceMin = MathMax(Ask - LimitOffset * Point, Point);

    if ((PriceMin < Ask) &&
        OrderSelect(OrderSend(Symb, OP_BUYLIMIT, MinLot, PriceMin, 100, 0, 0, __FUNCTION__ + "_Order"), SELECT_BY_TICKET) &&
        (!OrderDelete(OrderTicket())) && (!DemoAccount))
    {
      Alert("OrderDelete ERROR, Check Now!");

      ExpertRemove();
    }
  }
}
void OnStart()
{
  if ((ENUM_ACCOUNT_TRADE_MODE)AccountInfoInteger(ACCOUNT_TRADE_MODE) == ACCOUNT_TRADE_MODE_DEMO) // Закомментировать, если хочется проверить реал
  {
    Alert(TOSTRING(AccountInfoString(ACCOUNT_SERVER)));
    Alert(TOSTRING(TerminalInfoInteger(TERMINAL_PING_LAST)));

    while (!IsStopped())
      for (int i = SymbolsTotal(true) - 1; (i >= 0) && (!IsStopped()); i--)
        Benchmark(SymbolName(i, true));
  }
}

С помощью этого скрипта удалось найти проблемы с исполнением в MT5. Рекомендую проверять свою связку Терминал+Торговый Сервер и, в случае проблем, сообщать в Сервисдеск.

 

 
fxsaber:

С помощью этого скрипта удалось найти проблемы с исполнением в MT5. Рекомендую проверять свою связку Терминал+Торговый Сервер и, в случае проблем, сообщать в Сервисдеск.

Т.е. в билде 1533 уже выдается инфа по задержкам в result.comment?
 
Alexey Kozitsyn:
Т.е. в билде 1533 уже выдается инфа по задержкам в result.comment?

Нет, это библиотека делает.

Второе число - сколько времени уходит на синхронизацию истории ордеров (сделок) после выполнения OrderSend (через сколько приходит соответствующее событие в OnTradeTransaction).

На скрине этот показатель дошел до 28 мс - это крайне много.  СД и с этим вопросом разбираются.

Если MT5 будет проходить этот стресс-тест без вопросов, будет очень хорошо. Испытать свой MT5 может каждый.

 

Форум по трейдингу, автоматическим торговым системам и тестированию торговых стратегий

Скрипты: CloseAllPositions

fxsaber, 2017.03.30 14:11

// MQL4&5-code

#property script_show_inputs

#include <MT4Orders.mqh>

sinput int RTOTAL = 4;            // Число повторов при неудачных сделках
sinput int SLEEPTIME = 1;         // Время паузы между повторами в секундах
sinput int Deviation_ = 10;       // Отклонение цены
sinput bool exAllSymbols = false; // false - только текущий, true - все символы

#define _CS(A) ((!IsStopped()) && (A))

bool CloseAllPositions( const bool AllSymbols = true, const int Slippage = 0 )
{
  bool Res = true;
  
  MqlTick Tick;
  
  for (int i = OrdersTotal() - 1; _CS(i >= 0); i--)
    if (OrderSelect(i, SELECT_BY_POS) && (OrderType() <= OP_SELL) &&
        (AllSymbols ? true : (OrderSymbol() == Symbol())) && SymbolInfoTick(OrderSymbol(), Tick))
      Res &= OrderClose(OrderTicket(), OrderLots(), (OrderType() == OP_BUY) ? Tick.bid : Tick.ask, Slippage);
      
  return(Res);
}

void OnStart()
{
  for (int i = 0; _CS((i < RTOTAL) && (!CloseAllPositions(exAllSymbols, Deviation_))); i++)
    Sleep(SLEEPTIME * 1000);
}
Причина обращения: