Caractéristiques du langage mql5, subtilités et techniques - page 208

 
mktr8591:

Apparemment, j'ai mal compris la situation des échanges.

La façon dont je l'ai imaginé : l'ordre limite en attente a été exécuté par plusieurs transactions. Pendant tout ce temps, il était suspendu dans des commandes en direct et le champ ORDER_TIME_SETUP n'était pas une constante. Après le dernier échange, il est entré dans l'histoire. À ce moment-là, ORDER_TIME_SETUP est devenu une constante.

Ou pas ?

ORDER_TIME_SETUP est toujours une constante. Quand il est entré dans l'historique - ORDER_TIME_DONE est apparu.

 
fxsaber:

ORDER_TIME_SETUP est toujours une constante. Lorsqu'il a été touché dans l'historique - ORDER_TIME_DONE est apparu.

Me voici maintenant en train de fixer la limite retardée. Ensuite, je le modifie à la main et par script et ORDER_TIME_SETUP change.

Qu'est-ce que je fais de mal ?

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

Me voici maintenant en train de régler un limiteur retardé. Ensuite, je le modifie manuellement et le script et ORDER_TIME_SETUP changent.

Qu'est-ce que je fais de mal ?

Cela ne modifie pas l'heure programmée.

 
mktr8591:

Vous avez publié des articles sur des cas similaires dans le passé :

https://www.mql5.com/ru/forum/170952/page170#comment_15824249

https://www.mql5.com/ru/forum/170952/page172#comment_15829154

En effet, je l'ai fait. Mais je ne m'en souvenais pas du tout. Je pense que c'est un bug.


fxsaber:

Je ne sais pas ce qui va se passer avec l'exécution partielle répétée.

Maintenant, je sais qu'avec ce courtier (je penche pour un bug dans leur logiciel), il ne changera plus.

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

Il est parfois utile de savoir à quelle fréquence les tics sont diffusés.

 

Une transaction CloseBy génère deux transactions. Le swap de la première transaction (première position dans CloseBy) contient la somme des swaps des deux positions. Le swap de la deuxième transaction est de zéro.

Si la fermeture partielle de la position est effectuée via CloseBy, la partie restante de la position ouverte est privée de swap - elle est mise à zéro.


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


Résultat.


Il peut donc y avoir un énorme swap sur la plus petite position qui n'a jamais fait l'objet d'un rollover. Et zéro swap pour une position importante qui a roulé.

 

Calculer le nombre de tonneaux (ce n'est pas l'option la plus rapide).

#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


Exemple d'utilisation.

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

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


Résultat.

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

Une transaction CloseBy génère deux transactions. Le swap de la première transaction (première position dans CloseBy) contient la somme des swaps des deux positions. Le swap de la deuxième transaction est de zéro.

Si la fermeture partielle d'une position est effectuée via CloseBy, la partie restante de la position ouverte est privée de swap - mise à zéro.

...

Il peut donc y avoir un énorme swap sur une position minimale qui n'a jamais fait l'objet d'un rollover. Et zéro swap sur une position importante qui a roulé.

Incroyable !

Est-ce à cause des arrondis (pour ne pas perdre ou ajouter un centime) ?

Ou s'agit-il d'une opération rarement utilisée, donc sans importance ?

 
Andrey Khatimlianskii #:

Incroyable !

Est-ce à cause des arrondis (pour ne pas perdre ou ajouter un centime) ?

Certainement pas, car les fermetures partielles (OrderClose et non les OrderLots complets) videront le swap en conséquence.

Ou s'agit-il d'une opération rarement utilisée, donc sans importance ?

Je ne pense pas que l'on ait beaucoup réfléchi aux scénarios.