Tutte le domande dei nuovi arrivati su MQL4 e MQL5, aiuto e discussione su algoritmi e codici - pagina 522

 
PolarSeaman:

Che colpo di scena!)))

Ordine 1 (da# no, a# 2) -- > Ordine2 (da# 1, a# 3) -- >Ordine3 (da# 2, a# no)

Da qui si può trovare tutta la catena.

Guardiamo il commento aperto e se c'è da#XXX, significa che è stato precedentemente chiuso parzialmente - cerca il ticket XXX dal commento e cercalo nella storia. Guarda lì commento - se c'è da#YYY - significa che è stato parzialmente chiuso anche prima - guarda il biglietto YYY dal commento e cercalo nella storia. Guarda il commento - se c'è da#ZZZZ - significa che è stato parzialmente chiuso anche prima - ripeti la ricerca. Se non c'è from#..., allora è il primo di tutta la catena.

 
Artyom Trishkin:

Ordine 1 (da# no, a# 2) -- > Ordine2 (da# 1, a# 3) -- > Ordine3 (da# 2, a# no)

Da qui si può trovare tutta la catena.

Guardiamo il commento aperto e se c'è da#XXX, significa che è stato precedentemente chiuso parzialmente - cerca il ticket XXX dal commento e cercalo nella storia. Guarda lì commento - se c'è da#YYY - significa che è stato parzialmente chiuso anche prima - guarda il biglietto YYY dal commento e cercalo nella storia. Guarda il commento - se c'è da#ZZZZ - significa che è stato parzialmente chiuso anche prima - ripeti la ricerca. Se non c'è from#..., allora è il primo di tutta la catena.

Grazie, ci può essere un ordine nella direzione opposta, che anche io taglierò. Ho paura di confondermi. Penso che sarebbe più facile usare l'ordine Profit di una certa data, naturalmente, se siamo in grado di scoprire quando la posizione è stata aperta, perché la data cambia quando la posizione è parzialmente chiusa

 
Artyom Trishkin:

Ordine 1 (da# no, a# 2) -- > Ordine2 (da# 1, a# 3) -- > Ordine3 (da# 2, a# no)

Da qui si può trovare tutta la catena.

Guarda il commento aperto e se c'è da#XXX, significa che è stato parzialmente chiuso in precedenza - cerca il biglietto XXX dal commento e cercalo nella storia. Visualizza il commento lì - se c'è da#YYYY - quindi è stato parzialmente chiuso anche prima - visualizza il biglietto YYYY dal commento e cercalo nella storia. Guarda il commento - se c'è da#ZZZZ - significa che è stato parzialmente chiuso anche prima - ripeti la ricerca. Se non c'è from#..., allora è il primo di tutta la catena.

Artyom sai che questo non è sempre il caso. E per non tracciare una catena per non interrogare il terminale tre volte - la storia tutta la stessa è guidata in array e strutture proprie. Non è diverso dal mantenere il proprio database, tranne che per i passi extra

Il terminale e le sue API sono il livello più basso possibile. E per implementare la logica del robot, è logico fare la contabilità nei suoi termini (commercio, catena, gruppo, transazione - ognuno la chiama in modo diverso). È solo ragionevole tenerlo separato e non cercare di ricostruirlo ad ogni starnuto (tick/bar).

 
Maxim Kuznetsov:

Sai che non è sempre così, Artyom. E così non c'è bisogno di chiedere al terminale tre volte quando si segue la catena - la storia è ancora guidata nei propri array e strutture. Non è diverso dal mantenere il proprio database, tranne che per i passi extra

Il terminale e le sue API sono il livello più basso possibile. E per la realizzazione della logica dei robot, è logico tenere i conti nei suoi termini (commercio, catena, gruppo, transazione - ognuno la chiama in modo diverso). È solo ragionevole tenerlo separato e non cercare di ricostruirlo ad ogni starnuto (tick/bar).

Ho fatto tutto da molto tempo - non leggo la storia ogni volta - ma è sempre aggiornata, e posso trovare facilmente e molto rapidamente tutto ciò di cui ho bisogno. Ma per consigliare a qualcuno di fare lo stesso, ho bisogno di almeno un paio di articoli. E così ho scritto la logica per trovare tutta la catena.

 
PolarSeaman:

Grazie, potrebbe esserci un ordine nella direzione opposta, che anche io distruggerò. Ho paura di confondermi. Penso che sarebbe più facile usare la funzione Profit per chiudere una posizione a partire da una certa data, naturalmente se si può scoprire quando la posizione è stata aperta, perché in una chiusura parziale la data cambia

Per cercare una catena, è sufficiente conoscere il biglietto dell'ordine, l'intera catena di cui volete sapere - passate il biglietto come parametro alla funzione di ricerca, e l'output - un array riempito o un array di strutture con tutti i dati di ogni ordine dell'intera catena.

 
Artyom Trishkin:

Una matrice riempita o una matrice di strutture con tutti i dati di ogni ordine dell'intera catena.

Non so nemmeno approssimativamente quello che hai appena detto.

Almeno mostratemi un esempio di come dovrebbe essere.

 
PolarSeaman:

Non so nemmeno approssimativamente quello che hai appena detto.

Almeno dammi un esempio di come dovrebbe essere.

Risolvo il problema nel modo seguente: cerco le catene per storia. Bene, perché la storia sia inequivocabilmente disponibile, uso due varianti:

  1. Se senza DLL, allora nella descrizione del programma in 24 grassetto )))) specifico che la cronologia dell'account deve essere sempre caricata per intero (scheda Cronologia account della finestra Terminale, menu contestuale - Tutta la cronologia).
  2. Con DLL - Expert Advisor mantiene aggiornata la scheda "Storia del conto", indipendentemente da qualsiasi azione dell'utente.

Funzioni per determinare l'ordine padre, se l'ordine corrente non è quello primario:

int GetSignOfPartialOrCloseByClose()
{
   string comment = OrderComment();
   if (comment == "")
      return 0;
   
   // Ордер образовался вследствии частичного закрытия
   int fromStart = StringFind(comment, "from #");
   if (fromStart >= 0)
      return GetTicketByPartialClose(comment, fromStart, OrderType(), OrderOpenTime());
   
   // Ордер образовался вследствии встречного закрытия
   if (StringFind(comment, "partial close") >= 0)
   {
      datetime openTime = OrderOpenTime();
      int type = OrderType();
      for (int i = OrdersHistoryTotal() - 1; i >= 0; i--)
      {
         if (!OrderSelect(i, SELECT_BY_POS, MODE_HISTORY))
            continue;
            
         if (OrderOpenTime() != openTime)
            continue;
            
         if (OrderType() != type)
            continue;
            
         if (StringFind(OrderComment(), "partial close") < 0)
            continue;
            
         return OrderTicket();
      }
   }
   
   return 0;
}


int GetTicketByPartialClose(string comment, int fromStart, int orderType, datetime openTime)
{
   string sTicket = StringSubstr(comment, fromStart + 6);
   int iTicket = (int)StringToInteger(sTicket);
   int type = OrderType();
   if (!OrderSelect(iTicket, SELECT_BY_TICKET))
      return 0;
      
   if (OrderType() == type)                                                                        // Дочерний ордер указывает на родителя - уходим
      return iTicket;
      
   // Дочерний ордер указывает на противоположный ордер. Необходимо искать родительский
   for (int i = OrdersHistoryTotal() - 1; i >= 0; i--)
   {
      if (!OrderSelect(i, SELECT_BY_POS, MODE_HISTORY))
         continue;
         
      if (OrderType() != orderType || OrderOpenTime() != openTime)
         continue;
         
      int iFind = StringFind(OrderComment(), "close hedge by #");
      if (iFind < 0)
         continue;
         
      sTicket = StringSubstr(OrderComment(), iFind + 16);
      int iNewTicket = (int)StringToInteger(sTicket);
      if (iNewTicket != iTicket)
         continue;
         
      return OrderTicket();
   }
   
   return 0;
}

Facile da usare:

   for (int i = OrdersTotal() - 1; i >= 0; i--)
   {
      if (!OrderSelect(i, SELECT_BY_POS))
         continue;

      ....         

      int nFromTicket = GetSignOfPartialOrCloseByClose();                // Обязательно последней строкой в теле цикла, т. к. может измениться текущий выбранный ордер
   }


 
Ihor Herasko:

L'errore più grossolano qui è specificare il valore 100 invece di ticket nell'argomento OrderDelete().

Il prossimo errore non è così grossolano, ma è legato al fatto che viene controllato il valore calcolato dello Stop Loss e non il suo valore reale.

Anche il tipo di ordine non viene controllato. Cosa succede se abbiamo scelto un ordine a mercato? Come cancellarlo? Il simbolo dell'ordine non è stato controllato.

Prendendo in considerazione questi errori, otteniamo il codice di cancellazione dell'ordine pendente quando il prezzo raggiunge il suo Stop Loss:

Inoltre, nel tuo codice, lo Stop Loss viene controllato immediatamente dopo l'apertura dell'ordine. Sembra che dopo aver aperto un ordine pendente, questo codice non venga più eseguito. Cioè, è necessario separare i rami di esecuzione. Uno è responsabile di stabilire l'ordine e il secondo è responsabile del suo accompagnamento.

Grazie per la tua risposta dettagliata!

Seguendo i vostri consigli, ho separato i rami e tutto funziona.

Poi ho affrontato il problema dell'apertura simultanea di 10-15 ordini in sospeso, ho risolto questo problema aggiungendolo dopo il tuo codice:

if (OrdersTotal ()>0) return;

Sono sicuro che c'è un modo migliore.

Con il tuo codice, potresti spiegare cosa significa 1; i >=0; --i?

for (int i = OrdersTotal() - 1; i >= 0; --i)
 

Per favore, aiutatemi a capire come scrivere un indicatore. Ho disegnato un tale manichino, come fare una lunghezza dell'indicatore da disegnare a punti di dimensione sopra il Bid corrente, a partire dal momento in cui l'indicatore è posto sul grafico? Forse l'errore è che sto spostando questo array nella direzione sbagliata?

So che è "canonico", senza alcun prev_calcolato ecc., ma mi serve così


#property copyright "Copyright 2018, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00"
#property indicator_chart_window
#property indicator_buffers 1
#property indicator_plots 1
//---- plot 
#property indicator_label1  "myInd"
#property indicator_type1   DRAW_LINE
#property indicator_color1  Blue
#property indicator_style1  STYLE_SOLID
#property indicator_width1  1

double buff[], Bid;
input int lenght = 50, size = 5;
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping

   ArrayResize(buff, 50);
   ArrayInitialize(buff, 0);
   SetIndexBuffer(0, buff, INDICATOR_DATA);
   //--- установим метку для отображения в DataWindow
   PlotIndexSetString(0,PLOT_LABEL,"myInd");   
//--- установим имя для показа в отдельном подокне и во всплывающей подсказке
   IndicatorSetString(INDICATOR_SHORTNAME,"myInd");
//--- укажем точность отображения значений индикатора
   IndicatorSetInteger(INDICATOR_DIGITS, _Point);
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
  {
//---
   Bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
   for(int i = lenght-1; i>0; i--){
      buff[i] = buff[i-1];
   }
   buff[0] = Bid+size;
   


   
//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+
 
Roman Sharanov:

Per favore, aiutatemi a capire come scrivere un indicatore. Ho disegnato un tale manichino, come fare una lunghezza dell'indicatore da disegnare a punti di dimensione sopra il Bid corrente, a partire dal momento in cui l'indicatore è posto sul grafico? Forse l'errore è che sto spostando questo array nella direzione sbagliata?

So che è "canonico", senza prev_calcolato e cose del genere.


C'è un documento ufficiale - è esattamente come il tuo.

1. dovreste impostare la serializzazione di tutti gli array che usate dentro OnCalculate.

2. Prima di entrare nel ciclo, mettete buff[length]=Bid+size; - otterrete circa quello che volete. Una linea curva e alla fine una "visiera" a Bid+size

3. Guarda i limiti dell'array. Naturalmente, rates_total è difficilmente < lunghezza, ma non si può sbagliare :-)

4.
buff[i] = buff[i+1]; // если тайм-серия (а вы подразумеваете их) то +
Motivazione: