Caratteristiche del linguaggio mql5, sottigliezze e tecniche - pagina 208

 
mktr8591:

A quanto pare, ho frainteso la situazione degli scambi.

Il modo in cui me lo sono immaginato: l'ordine limite pendente è stato eseguito da diversi trade. Per tutto questo tempo era sospeso negli ordini live e il campo ORDER_TIME_SETUP non era una costante. Dopo l'ultimo scambio è entrato nella storia. In quel momento, ORDER_TIME_SETUP è diventato una costante.

O non lo era?

ORDER_TIME_SETUP è sempre una costante. Quando è entrato nella storia - è apparso ORDER_TIME_DONE.

 
fxsaber:

ORDER_TIME_SETUP è sempre una costante. Quando è stato colpito dalla storia - è apparso ORDER_TIME_DONE.

Qui sto impostando il limite ritardato. Poi lo cambio a mano e con lo script e ORDER_TIME_SETUP cambia.

Cosa sto facendo di sbagliato?

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

Ecco che ora sto impostando un limitatore ritardato. Poi lo cambio manualmente e tramite script e ORDER_TIME_SETUP cambia.

Cosa sto facendo di sbagliato?

Questo non cambia il tempo impostato.

 

Infatti l'ho fatto. Ma non me lo ricordavo affatto. Penso che sia un bug.


fxsaber:

Non so cosa succederà con l'esecuzione parziale ripetuta.

Ora so che - a questo broker (propendo per un bug nel loro software) non cambierà più.

 
// Возвращает снепшот котирования символа.
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);
}

A volte è utile sapere quanto spesso vengono trasmessi i tic.

 

Una transazione CloseBy genera due operazioni. Lo swap della prima (prima posizione in CloseBy) transazione contiene la somma degli swap di entrambe le posizioni. Lo swap del secondo scambio è zero.

Se la chiusura parziale della posizione viene fatta tramite CloseBy, allora la parte rimanente della posizione aperta viene privata dello swap - viene azzerata.


// Демонстрация работы со свопами во время частичного закрытия через 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));      
    }    
  }    
}


Risultato.


Quindi potrebbe esserci un enorme swap sulla posizione minima, che non è mai passata attraverso un rollover. E zero swap per una grande posizione che ha rotolato.

 

Calcolo del numero di rollover (non è l'opzione più veloce).

#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


Esempio di utilizzo.

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

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


Risultato.

#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 #:

Una transazione CloseBy genera due operazioni. Lo swap della prima (prima posizione in CloseBy) transazione contiene la somma degli swap di entrambe le posizioni. Lo swap del secondo scambio è zero.

Se la chiusura parziale di una posizione viene fatta tramite CloseBy, la parte rimanente della posizione aperta viene privata dello swap - azzerata.

...

Quindi potrebbe esserci un enorme swap su una posizione minima che non è mai passata attraverso un rollover. E zero swap su una grande posizione che è rotolata.

Incredibile!

È a causa dell'arrotondamento (per non perdere o aggiungere un centesimo)?

O è solo un'operazione usata raramente, quindi non ha importanza?

 
Andrey Khatimlianskii #:

Incredibile!

È a causa dell'arrotondamento (per non perdere o aggiungere un centesimo)?

Decisamente no, poiché le chiusure parziali (OrderClose non OrderLots completi) prosciugheranno lo swap di conseguenza.

O è solo un'operazione usata raramente, quindi non ha importanza?

Non credo che si sia pensato molto agli scenari.

Motivazione: