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

 
Jeka77769:

Здравствуйте!  В описании написано: "Соответственно, OrderSelect в режиме SELECT_BY_TICKET в MT5 в редких случаях (в тестере) может выбрать не то, что задумывалось в MT4. "     Можете подробно написать в каких именно случаях? 

Когда тикеты позиции/сделки/ордера совпадают.

 
Еще пример (описание) кроссплатформенного кода

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

Советники: eaBreakeven

fxsaber, 2018.01.11 08:13

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

input int    Breakeven           = 15;           //Breakeven in points
input int    Distance            = 5;            //Breakeven distance in points from open price of position
input int    MagicNumber         = 16112017;     //Magic number
input bool   EnableSound         = true;         //Enable/disable playing sound when breakeven set
input string SoundFile           = "alert1.wav"; //Sound file name

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;
  
  //--- Move stop-loss at breakven price + Distance, if position profit greater than Breakeven points  
  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 is negative, then disable breakeven function
  if (Breakeven >= 0)      
  //Loop for positions
    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/ru/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-советник, тем проще его сконвертировать в MT5. И размер/сложность оригинального советника не имеет никакого значения при конвертации.

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

Советники: Three Point Arbitrage

fxsaber, 2018.01.20 09:58

#define MT4_TICKET_TYPE  // Обязываем OrderSend и OrderTicket возвращать значение такого же типа, как в MT4 - int.
#include <MT4Orders.mqh> // https://www.mql5.com/ru/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"
 
Если появляется Алерт, посмотрите, а не запущен ли на счете (по невнимательности) один и тот же советник дважды. Например, один на локальной машине, а другой - VPS.

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

Особенности языка mql5, тонкости и приёмы работы

fxsaber, 2018.02.06 07:41

OnTradeTransaction позволяет написать неторговый советник (Сервис), отслеживающий наличие запущенного на счете торгового "клона"-советника.
 

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

Особенности языка mql5, тонкости и приёмы работы

fxsaber, 2018.02.08 08:16

В MT5 у позиций нет комиссии (в отличие от MT4). Из-за этого есть свои особенности

  • В MT5 комиссия за открытие позиции, как и за закрытие позиции списывается сразу с баланса.
  • По этой причине Equity до закрытия всех позиций не показывает, чему будет равен Balance после закрытия.
  • Это значит, что рассчитать безубыток просто не получится в 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 выражение

ProfitWithCommission += OrderProfit() + OrderSwap() + OrderCommission(); // Вычисляем текущий профит с учетом комиссии

теряет смысл в MT5. Но это не так. На самом деле когда Вы закроете позицию, то Balance изменится именно на эту величину, а не станет тем, что показывало перед этим Equity. Грубо говоря, значение Equity в MT5 врет, с точки зрения этого понятия в MT4.

Учитывайте эту особенность MT5. Библиотека в данном случае точнее. И рассчитать тот же безубыток не составит труда.

 

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

Особенности языка mql5, тонкости и приёмы работы

fxsaber, 2018.02.08 10:06

На неттинге элементарно потерять комментарий открытой позиции. Для этого достаточно совершить любую сделку без комментария по символу позиции.

Библиотека не потеряет комментарий в описанном случае - OrderComment() будет выдавать комментарий, который был при открытии позиции.

 
// Список изменений:
// 13.02.2018
//   Add: Добавлено логирование ошибочного выполнения MT5-OrderSend.
//   Fix: Теперь "невидимы" только закрывающие MT5-ордера (SL/TP/SO, partial/full close).
//   Fix: Механизм определения SL/TP закрытых позиций после OrderClose скорректирован - работает, если позволяет StopLevel.
 

Здесь подробно описана некоторая особенность работы MT5. Библиотека отрабатывала эту ситуацию правильно уже давно. Но ругалась (Алерт), что ситуация нестандартная.

Теперь ругаться не будет

// Список изменений:
// 15.02.2018
//   Fix: Проверка синхронизации 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 все совсем не в порядке. Пример, показывающий проблему

// Пример неправильного считывания торгового окружения на каждом тике
// Скрипт эмулирует два тика ТС, которая должна открыть одну позицию, если ее нет.

#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);    
}

// Эмуляция прихода двух Tick-событий
void OnStart()
{
  ExampleOnTick(); 
  
  Sleep(10); // Между двумя тиками ~10 мс.
  
  ExampleOnTick();
}

Как думаете, если запустить этот скрипт на символе без позиций, что будет в итоге?

Правильный ответ: будет открыта одна или две позиции.

Эта проблема обходится, если писать в MQL4-style хотя бы частично. Чтобы в этом убедиться, достаточно GetAmountPositions сделать в MQL4-style (закомментирован в исходнике), убрав MQL5-style.

Будьте особенно бдительны с MQL5-style.