Librerie: Rapporto rapido MT4Ordini - pagina 5

 
Forester #:

Server: MetaQuotes-Demo Hedge
Trattare il ticket 99 a pagina due.

Un po' localizzato.

#include <MT4Orders.mqh>

void OnTick ()
{
  static int Count = 0;
  
  if (Count > 6)
    return;
  
  MqlTick Tick;
  SymbolInfoTick(_Symbol, Tick);
  
  const double Offset = 5 * _Point;
  bool Buy =  false;
  bool Sell =  false;

  for (uint i = OrdersTotal(); (bool)i--;)
    if (OrderSelect(i, SELECT_BY_POS))         
    {
      if(OrderMagicNumber())
        switch (OrderType())
        {
        case OP_BUY:
          OrderModify(OrderTicket(), OrderOpenPrice(), 0, Tick.bid + Offset, 0);
          Buy = true;
         
         break;
        case OP_SELL:
          OrderModify(OrderTicket(), OrderOpenPrice(), 0, Tick.ask - Offset, 0);
          Sell = true;
         
         break;
        case OP_BUYLIMIT:
          OrderModify(OrderTicket(), Tick.ask - Offset, 0, 0, 0);
          Buy = true;
         
         break;
        case OP_SELLLIMIT:          
          OrderModify(OrderTicket(), Tick.bid + Offset, 0, 0, 0);
          Sell = true;
         
         break;
        }
      else
        OrderDelete(OrderTicket());
    }

  if (!Buy)
    OrderSend(_Symbol, OP_BUYLIMIT, 1, Tick.ask - Offset, 0, 0, 0, NULL, ++Count);

  if (!Sell)
    OrderSend(_Symbol, OP_SELLLIMIT, 1, Tick.bid + Offset, 0, 0, 0, NULL, ++Count);
  
  OrderSend(_Symbol, OP_BUYLIMIT, 1,  Tick.ask - Offset, 0, Tick.ask - Offset, Tick.ask - Offset);
  Count++;
}

string TimeToString( const long Time )
{
  return((string)(datetime)(Time / 1000) + "." + IntegerToString(Time % 1000, 3, '0'));
}

void OnDeinit( const int )
{
  if (HistorySelect(0, INT_MAX))
    for (uint i = HistoryOrdersTotal(); (bool)i--;)
    {
      const ulong Ticket = HistoryOrderGetTicket(i);
      
      Print((string)i + ": " + (string)Ticket + " " + TimeToString(HistoryOrderGetInteger(Ticket, ORDER_TIME_DONE_MSC)));
    }
}


Non importa cosa stia facendo l'EA. La cosa principale è il codice evidenziato, che mostra semplicemente gli ordini MT5 della cronologia di trading: il luogo dell'ordine, il suo ticket e l'ora in cui è entrato nella cronologia.

11: 13 2023.05.29 23:54:39.425
10: 12 2023.05.29 00:04:25.870
 9: 11 2023.05.29 00:03:59.331
 8: 10 2023.05.29 00:03:59.430
 7: 9 2023.05.29 00:03:59.281
 6: 8 2023.05.29 00:03:59.281
 5: 7 2023.05.29 00:03:59.227
 4: 3 2023.05.29 00:03:59.331
 3: 6 2023.05.29 00:03:18.390
 2: 5 2023.05.29 00:03:18.390
 1: 4 2023.05.29 00:02:41.107
 0: 2 2023.05.29 00:02:41.107

Nella tabella della cronologia, gli ordini MT5 non sono ordinati per ticket o tempo. Non vedo perché segnalare questo comportamento di MQ-Tester agli sviluppatori. Dopo tutto, "i compiti sono eccessivi".

Pertanto, non standardizzerei MQ-Tester.

 
fxsaber #:

Un po' localizzato.


Non importa cosa faccia l'EA. La cosa principale è un codice dedicato che semplicemente estrae gli ordini MT5 dalla cronologia di trading: il luogo dell'ordine, il suo ticket e l'ora in cui è stato inserito nella cronologia.

Nella tabella della cronologia, gli ordini MT5 non sono ordinati per ticket o tempo. Non vedo perché segnalare questo comportamento di MQ-Tester agli sviluppatori. Dopo tutto, "i compiti sono eccessivi".

Pertanto, non standardizzerei MQ-Tester.

Penso che gli ordini limite abbiano una propria coda di trasferimento allo storico quando vengono chiusi. Non ad ogni tick.
Se non hanno bisogno di correggere i bug evidenti con i primi trade e swap di prova (che ho scontato un paio di settimane fa), allora è solo una funzione. La matrice di confusione è più importante....
 
A volte è bene saperlo.
// Durata massima del drawdown dal momento impostato.
int MaxLengthDD( datetime &BeginDD, datetime &EndDD, const datetime From = 0 )
{
  const int Total = OrdersHistoryTotal();
  
  double Profit = 0;
  double MaxProfit = 0;
  datetime Begin = 0;
  
  BeginDD = 0;
  EndDD = 0;
  
  for (int i = 0; i < Total; i++)
    if (OrderSelect(i, SELECT_BY_POS, MODE_HISTORY) && (OrderType() <= OP_SELL))
    {
      if (!Begin && (OrderOpenTime() > From))
        Begin = OrderOpenTime();
        
      Profit += OrderProfit() + OrderSwap() + OrderCommission();
      
      if ((Profit > MaxProfit) || (i == Total - 1))
      {
        MaxProfit = Profit;
        
        const datetime End = OrderCloseTime();        
        
        if (Begin && (End - Begin > EndDD - BeginDD))
        {
          BeginDD = Begin;
          EndDD = End;
        }
        
        if (Begin)
          Begin = End;
      }
    }
    
  return((int)(EndDD - BeginDD));
}

void PrintMaxLengthDD( const datetime &From[] )
{
  const int Size = ArraySize(From);
  
  datetime BeginDD, EndDD;
  
  for (int i = 0; i < Size; i++)
    Print("From " + TimeToString(From[i], TIME_DATE) + " MaxLengthDD = " + (string)(MaxLengthDD(BeginDD, EndDD, From[i]) / (25 * 3600)) + " days: " +
          (string)BeginDD + " - " + (string)EndDD);  
}
 

fxsaber #:
Иногда полезно знать.

Print("From " + TimeToString(From[i], TIME_DATE) + " MaxLengthDD = " + (string)(MaxLengthDD(BeginDD, EndDD, From[i]) / (25 * 3600)) + " days: " +
          (string)BeginDD + " - " + (string)EndDD);

È meglio non scrivere in modo così confezionato e frivolo (non solo qui, ma anche in altri sorgenti). L'ordine di calcolo di operandi con la stessa priorità non è fissato rigidamente: il compilatore può ottimizzarlo in base alle proprie considerazioni, quindi si possono ottenere effetti collaterali diversi. Se funziona ora, non significa che non smetterà di funzionare in seguito, perché l'implementazione interna del compilatore cambia continuamente.

 
Stanislav Korotky #:

È meglio non scrivere in modo così confezionato e frivolo (non solo qui, ma anche in altri sorgenti). L'ordine di calcolo di operandi con la stessa priorità non è fissato rigidamente: il compilatore può ottimizzarlo in base alle proprie considerazioni, quindi si possono ottenere effetti collaterali diversi. Se funziona ora, non significa che non smetterà di funzionare in seguito, perché l'implementazione interna del compilatore cambia continuamente.

Grazie per il consiglio! Purtroppo è difficile costringermi ad abbandonare lo stile "conciso" a favore di quello corretto. C'è molto codice "sbagliato" scritto e utilizzato.

 
fxsaber #:
// Durata massima del drawdown a partire da un determinato momento.
Dalla data di inizio dell'operazione?
Stanislav Korotky #:

È meglio non scrivere in modo così confezionato e frivolo (non solo qui, ma anche in altre fonti). L'ordine di calcolo di operandi con la stessa priorità non è fissato rigidamente - il compilatore può ottimizzarlo in base alle proprie considerazioni, quindi si possono ottenere effetti collaterali diversi. Se funziona ora, non significa che non smetterà di funzionare in seguito, perché l'implementazione interna del compilatore cambia continuamente.

Cosa c'è di sbagliato?

Io ho solo

/ (25 * 3600)
Non mi piace. Ci sono 24 ore in un giorno, non 25.
 

Forester #:
C даты начала форварда?

Chiunque.

Cosa c'è di sbagliato?

Non c'è un ordine univoco in cui viene formata la stringa per la stampa. Se si procede da destra a sinistra, il risultato sarà diverso da quello desiderato.

    Print("From " + TimeToString(From[i], TIME_DATE) + " MaxLengthDD = " + (string)(MaxLengthDD(BeginDD, EndDD, From[i]) / (25 * 3600)) + " days: " +
          (string)BeginDD + " - " + (string)EndDD);  


Vorrei che ci fosse un'ambiguità in questo caso.

int MaxLengthDD( const datetime &BeginDD, const datetime &EndDD, const datetime From = 0 )
 
fxsaber #:

Grazie per il valido consiglio! Purtroppo è difficile costringermi ad abbandonare lo stile "conciso" a favore di quello corretto. C'è molto codice "sbagliato" scritto e utilizzato.

Quasi sempre comprimo funzioni e altro codice in una sola riga se il codice è già stato lavorato/testato e non ho intenzione di tornarci sopra. Solo per risparmiare spazio.
Inoltre è più comodo leggere il codice senza scorrere avanti e indietro quando si può vedere tutto in una sola schermata. Soprattutto negli editor che evidenziano la parola evidenziata (purtroppo Metaeditor non è uno di questi).
 
Forester #:
Quasi sempre comprimo le funzioni e altro codice in una sola riga se il codice è stato lavorato/testato e non ho intenzione di ritornarci. Solo per risparmiare spazio.
Inoltre, è più comodo leggere il codice senza scorrere avanti e indietro quando si può vedere tutto in un'unica schermata. Soprattutto negli editor che evidenziano la parola evidenziata (purtroppo Metaeditor non è uno di questi).

Purtroppo, questa pratica può portare a errori molto difficili da vedere quando si cambia compilatore.

Tuttavia, ci sono situazioni in cui è sufficiente utilizzare l'ordine impostato nel compilatore. E non so come aggirare il problema in modo che non ci siano UB.

 
fxsaber #:

Da chiunque.

Le informazioni sul drawdown massimo lungo sono interessanti. L'ho fatta per l'intero array di stringhe. Non ho ancora aggiornato il codice sul sito.
Ma non è chiaro a cosa serva la data. Se facciamo un punto di divisione in test back/forward (come ho suggerito), allora dobbiamo calcolare le statistiche su di essi separatamente in 2 tabelle (i periodi di max drawdown saranno anche lì).
E solo per una data è in qualche modo troppo specifico e incomprensibile.