Features of the mql5 language, subtleties and tricks - page 208

 
mktr8591:

Apparently, I misunderstood the trading situation.

The way I pictured it: the pending limit order was executed by several trades. All this time it was hanging in live orders and the ORDER_TIME_SETUP field was not a constant. After the last trade it entered the history. At that moment, ORDER_TIME_SETUP became a constant.

Or it was not?

ORDER_TIME_SETUP is always a constant. When it got into the history - ORDER_TIME_DONE appeared.

 
fxsaber:

ORDER_TIME_SETUP is always a constant. When hit in history - ORDER_TIME_DONE appeared.

Here I am now setting the delayed limit. Then I change it by hand and script and ORDER_TIME_SETUP changes.

What am I doing wrong?

 
Особенности языка mql5, тонкости и приёмы работы
Особенности языка mql5, тонкости и приёмы работы
  • 2020.04.09
  • www.mql5.com
В данной теме будут обсуждаться недокументированные приёмы работы с языком mql5, примеры решения тех, или иных задач...
 
mktr8591:

Here I am now setting a delayed limiter. Then I change it manually and by script and ORDER_TIME_SETUP changes.

What am I doing wrong?

It does not change the set time.

 

Indeed I have. But I couldn't remember it at all. I think it's a bug.


fxsaber:

I don't know what will happen with the repeated partial execution.

Now I know - at this broker (I'm leaning towards a bug in their software) it won't change any more.

 
// Возвращает снепшот котирования символа.
int QuotesSnapshot( const string Symb = NULL, const datetime From = 0 )
{    
  int Snapshot = INT_MAX;

  MqlTick Ticks[];
  
#define  DAY (24 * 3600)  
  const int Size = CopyTicksRange(Symb, Ticks, COPY_TICKS_INFO, From ? From * 1000 : SymbolInfoInteger(Symb, SYMBOL_TIME) / DAY * DAY * 1000);
#undef  DAY  
  
  for (int i = 1; i < Size; i++)
  {
    const int Interval = (int)(Ticks[i].time_msc - Ticks[i - 1].time_msc);
    
    if (Interval < Snapshot)
      Snapshot = Interval;
  }
  
  return(Snapshot);
}

Sometimes it is useful to know how often tics are broadcast.

 

A CloseBy transaction generates two trades. Swap of the first (first position in CloseBy) transaction contains the sum of swaps of both positions. Swap of the second trade is zero.

If partial closing of the position is done via CloseBy, then remaining part of the open position is deprived of swap - it is zeroed.


// Демонстрация работы со свопами во время частичного закрытия через CloseBy.

#define  REPORT_TESTER             // В тестере будут автоматически записываться отчеты
#define  REPORT_BROWSER            // Создание отчета с запуском браузера - требует разрешения DLL.
#include <Report.mqh> // https://www.mql5.com/ru/code/18801

#define  Ask SymbolInfoDouble(_Symbol, SYMBOL_ASK)

void OnTick()
{
  static bool FirstRun = true;
  
  if (FirstRun)
  {
    if (!OrderSelect(0, SELECT_BY_POS))
      FirstRun = OrderSend(_Symbol, OP_BUY, 100, Ask, 0, 0, 0);
    else if (OrderSwap())
    {
      const TICKET_TYPE Ticket = OrderTicket();
      
//      FirstRun = !(OrderCloseBy(OrderSend(_Symbol, OP_SELL, 0.01, OrderClosePrice(),0, 0, 0), Ticket) &&
      FirstRun = !(OrderCloseBy(Ticket, OrderSend(_Symbol, OP_SELL, 0.01, OrderClosePrice(),0, 0, 0)) &&
                   OrderSelect(0, SELECT_BY_POS) && OrderClose(OrderTicket(), OrderLots(), OrderClosePrice(), 0));      
    }    
  }    
}


Result.


So there may well be a huge swap on the smallest position that has never gone through a rollover. And zero swap for a large position that has rolled over.

 

Calculating the number of rollovers (not the fastest option).

#define  DAY  (24 * 3600)
#define  WEEK (DAY * 7)

// Возврящает количество "четвергов" между двумя датами.
int GetAmountWeekDay( const datetime Begin, const datetime End, const int DayWeek = -1 )
{
  const datetime OffsetTime = (DayWeek - WEDNESDAY) * DAY;
  
  return((DayWeek != -1) ? (int)((End - OffsetTime) / WEEK - (Begin - OffsetTime) / WEEK) : 0);
}

// Возврящает количество рабочих дней между двумя датами.
int GetAmountWorkingDays( const datetime Begin, const datetime End )
{
  const int Res = (int)(End / DAY - Begin / DAY);
  
  return(Res ? Res - GetAmountWeekDay(Begin, End, SATURDAY) - GetAmountWeekDay(Begin, End, SUNDAY) : 0);
}

// Возвращает количество ролловеров (включая тройные) между двумя датами.
int GetRolloverAmounts( datetime TimeOpen, datetime TimeClose,
                        datetime RolloverTime = 0, const int Rollover3Days = WEDNESDAY )
{
  RolloverTime = RolloverTime % DAY;
  
  TimeOpen -= RolloverTime;
  TimeClose -= RolloverTime;
  
  const int Res = GetAmountWorkingDays(TimeOpen, TimeClose);
  
  return(Res ? Res + (GetAmountWeekDay(TimeOpen, TimeClose, Rollover3Days) << 1) : 0);
}

#undef  WEEK
#undef  DAY


Example of use.

// Сравниваем реальные и вычисленные значения свопов.

#include <MT4Orders.mqh>

input datetime inRolloverTime = 0; // Время ролловера
input int inCount = 100; // Маскимальное количество распечаток

// Вычисляет своп закрытой позиции.
double CalcOrderSwap( const datetime RolloverTime = 0 )
{
  return(((OrderType() <= OP_SELL) &&
          (SymbolInfoInteger(OrderSymbol(), SYMBOL_SWAP_MODE) == SYMBOL_SWAP_MODE_POINTS))
             // https://www.mql5.com/ru/forum/170952/page208#comment_24667438
           ? GetRolloverAmounts(OrderOpenTime(), OrderCloseTime(), RolloverTime,
             (int)SymbolInfoInteger(OrderSymbol(), SYMBOL_SWAP_ROLLOVER3DAYS)) *
             SymbolInfoDouble(OrderSymbol(), OrderType() ? SYMBOL_SWAP_SHORT : SYMBOL_SWAP_LONG) *
             SymbolInfoDouble(OrderSymbol(), SYMBOL_TRADE_TICK_VALUE) *
             OrderLots()
           : 0);
}

#define  TOSTRING(A) " " + #A + " = " + (string)(A)

void OnStart()
{  
  for (int i = OrdersHistoryTotal() - 1, Count = 0; (i >= 0) && (Count < inCount); i--)
    if (OrderSelect(i, SELECT_BY_POS, MODE_HISTORY) && OrderSwap())
    {
      OrderPrint();
      Print((string)Count++ + TOSTRING(OrderSwap()) + TOSTRING(CalcOrderSwap(inRolloverTime)) + "\n");
    }
}


Result.

#2122237 2021.09.09 23:09:15.512 sell 0.18 GBPCAD 1.75119 0.00000 1.75286 2021.09.10 04:27:40.506 1.75286 -0.84 -0.80 -20.07 7;[0] 7
97 OrderSwap() = -0.8 CalcOrderSwap(inRolloverTime) = -0.8048844238618312
 
fxsaber #:

A CloseBy transaction generates two trades. Swap of the first (first position in CloseBy) transaction contains the sum of swaps of both positions. Swap of the second trade is zero.

If partial closing of a position is done via CloseBy, remaining part of the open position is deprived of swap - zeroed.

...

So there may well be a huge swap on a minimum position that has never gone through a rollover. And zero swap on a large position that has rolled over.

Amazing!

Is it because of rounding (so as not to lose or add a cent)?

Or is it just a rarely used operation, so it doesn't matter?

 
Andrey Khatimlianskii #:

Amazing!

Is it because of rounding (so as not to lose or add a cent)?

Definitely not, as partial closures (OrderClose not full OrderLots) will drain the swap accordingly.

Or is it just a rarely used operation, so doesn't matter?

I don't think much thought has gone into the scenarios.