Características del lenguaje mql5, sutilezas y técnicas - página 208

 
mktr8591:

Al parecer, he entendido mal la situación del comercio.

Tal y como me lo imaginaba: la orden pendiente de límite fue ejecutada por varias operaciones. Todo este tiempo se colgaba en los pedidos en vivo y el campo ORDER_TIME_SETUP no era una constante. Después de la última operación entró en la historia. En ese momento, ORDER_TIME_SETUP se convirtió en una constante.

¿O no lo era?

ORDER_TIME_SETUP es siempre una constante. Cuando entró en el historial - ORDER_TIME_DONE apareció.

 
fxsaber:

ORDER_TIME_SETUP es siempre una constante. Cuando se golpea en la historia - ORDER_TIME_DONE apareció.

Aquí estoy fijando el límite retrasado. Entonces lo cambio a mano y con el script y ORDER_TIME_SETUP cambia.

¿Qué estoy haciendo mal?

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

Aquí estoy poniendo un limitador retardado. Entonces lo cambio manualmente y el script y ORDER_TIME_SETUP cambian.

¿Qué estoy haciendo mal?

Esto no cambia el tiempo establecido.

 

De hecho lo he hecho. Pero no podía recordarlo en absoluto. Creo que es un error.


fxsaber:

No sé qué pasará con la ejecución parcial repetida.

Ahora sé - en este corredor (me inclino por un error en su software) no va a cambiar más.

 
// Возвращает снепшот котирования символа.
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 veces es útil saber con qué frecuencia se emiten las tics.

 

Una transacción CloseBy genera dos operaciones. El swap de la primera (primera posición en CloseBy) transacción contiene la suma de los swaps de ambas posiciones. El intercambio de la segunda operación es cero.

Si el cierre parcial de la posición se hace a través de CloseBy, entonces la parte restante de la posición abierta es privada de swap - se pone a cero.


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


Resultado.


Por lo tanto, es muy posible que haya un gran intercambio en la posición más pequeña que nunca haya pasado por una refinanciación. Y un intercambio cero para una posición grande que se ha volcado.

 

Calcular el número de vuelcos (no es la opción más rápida).

#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


Ejemplo de uso.

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

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


Resultado.

#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 transacción CloseBy genera dos operaciones. El swap de la primera (primera posición en CloseBy) transacción contiene la suma de los swaps de ambas posiciones. El intercambio de la segunda operación es cero.

Si el cierre parcial de una posición se hace a través de CloseBy, la parte restante de la posición abierta se priva de swap - se pone a cero.

...

Por lo tanto, es muy posible que haya un gran intercambio en una posición mínima que nunca haya pasado por un rollover. Y un swap cero en una posición grande que se ha renovado.

¡Increíble!

¿Se debe al redondeo (para no perder o añadir un céntimo)?

¿O se trata de una operación poco utilizada, por lo que no importa?

 
Andrey Khatimlianskii #:

¡Increíble!

¿Se debe al redondeo (para no perder o añadir un céntimo)?

Definitivamente no, ya que los cierres parciales (OrderClose no los OrderLots completos) drenarán el swap en consecuencia.

¿O se trata de una operación poco utilizada, por lo que no importa?

No creo que se haya pensado mucho en los escenarios.