L'oscillatore di equità di MQL5 significa

 

Ciao a tutti!

Ho lottato per un giorno con il problema di costruire l'oscillatore Equity sotto il grafico a cui è attaccato (perché il grafico nel Tester manca della cosa principale, cioè la facilità di confronto con i cambiamenti del mercato, come altri hanno scritto, tra l'altro).

Il problema, per come la vedo io, è a due facce.

Da un lato, il metodo per determinare l'Equity AccountInfoDouble(ACCOUNT_EQUITY) per ogni barra nel metodo OnCalculate dell'oscillatore si rifiuta di funzionare.

D'altra parte, è difficile capire se il grafico dell'oscillatore (o piuttosto il suo buffer di dati) può essere cambiato dal codice OnTick dell'Expert Advisor dove funziona il metodo AccountInfoDouble(ACCOUNT_EQUITY).

Qui sotto c'è il codice dell'oscillatore che, per tutta la sua semplicità, non riesce a produrre risultati.

//+------------------------------------------------------------------+
//|                                                       Equity.mq5 |
//|                        Copyright 2010, MetaQuotes Software Corp. |
//|                                              http://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2010, MetaQuotes Software Corp."
#property link      "http://www.mql5.com"
#property version   "1.00"
#property indicator_separate_window
#property indicator_buffers 1
#property indicator_plots   1
//--- plot Label1
#property indicator_label1  "Label1"
#property indicator_type1   DRAW_LINE
#property indicator_color1  Red
#property indicator_style1  STYLE_SOLID
#property indicator_width1  1
//--- indicator buffers
double        Values[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit(){
   //--- indicator buffers mapping
   SetIndexBuffer(0,Values,INDICATOR_DATA);
   PlotIndexSetInteger(0, PLOT_DRAW_BEGIN, 100);
   PlotIndexSetDouble(0, PLOT_EMPTY_VALUE, EMPTY_VALUE);
   ArraySetAsSeries(Values, false);
   return(0);
  }
//+------------------------------------------------------------------+
//| 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[]){
   int toCount = (int)MathMin(rates_total, rates_total - prev_calculated + 1);
   for (int i = toCount - 2; i >= 0; --i){
      Values[i] = AccountInfoDouble(ACCOUNT_EQUITY);  
   }
   return rates_total;
}

Intuitivamente capisco che il problema deve essere risolto in modo semplice, ma non riesco a capire come.

Forse qualcuno ha qualche idea al riguardo?

 
DV2010:

Ciao a tutti!

Ho lottato per un giorno con il problema di costruire l'oscillatore Equity sotto il grafico a cui è attaccato (perché il grafico nel Tester manca della cosa principale, cioè la facilità di confronto con i cambiamenti del mercato, come altri hanno scritto, tra l'altro).

Il problema, per come la vedo io, è a due facce.

Da un lato, il metodo per determinare l'Equity AccountInfoDouble(ACCOUNT_EQUITY) per ogni barra nel metodo OnCalculate dell'oscillatore si rifiuta di funzionare.

D'altra parte, è difficile capire se il grafico dell'oscillatore (o piuttosto il suo buffer di dati) può essere cambiato dal codice OnTick dell'Expert Advisor dove funziona il metodo AccountInfoDouble(ACCOUNT_EQUITY).

Qui sotto c'è il codice dell'oscillatore che, per tutta la sua semplicità, non riesce a produrre risultati.


Intuitivamente capisco che il problema deve essere risolto in modo semplice, ma non riesco a capire come.

Forse qualcuno ha qualche idea su questo argomento?

AccountInfoDouble(ACCOUNT_EQUITY); restituisce lo stato attuale del capitale e non ha storia. Nel vostro esempio, tutte le celle del buffer dell'indicatore sono scritte con lo stesso valore. Ecco un esempio dell'indicatore azionario, ma funziona solo dal momento in cui viene lanciato sul grafico

//+------------------------------------------------------------------+
//|                                                       Equity.mq5 |
//|                                                    Сергей Грицай |
//|                                               sergey1294@list.ru |
//+------------------------------------------------------------------+
#property copyright "Сергей Грицай"
#property link      "sergey1294@list.ru"
#property version   "1.00"
#property indicator_separate_window
#property indicator_buffers 4
#property indicator_plots   1
//--- plot Label1
#property indicator_label1  "Label1"
#property indicator_type1   DRAW_CANDLES
#property indicator_color1  MediumAquamarine
#property indicator_style1  STYLE_SOLID
#property indicator_width1  1

double         Label1Buffer1[];
double         Label1Buffer2[];
double         Label1Buffer3[];
double         Label1Buffer4[];

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   SetIndexBuffer(0,Label1Buffer1,INDICATOR_DATA);
   SetIndexBuffer(1,Label1Buffer2,INDICATOR_DATA);
   SetIndexBuffer(2,Label1Buffer3,INDICATOR_DATA);
   SetIndexBuffer(3,Label1Buffer4,INDICATOR_DATA);

   ArraySetAsSeries(Label1Buffer1,true);
   ArraySetAsSeries(Label1Buffer2,true);
   ArraySetAsSeries(Label1Buffer3,true);
   ArraySetAsSeries(Label1Buffer4,true);
   
   ArrayInitialize(Label1Buffer1,0.0);
   ArrayInitialize(Label1Buffer2,0.0);
   ArrayInitialize(Label1Buffer3,0.0);
   ArrayInitialize(Label1Buffer4,0.0);
//---
   return(0);
  }
//+------------------------------------------------------------------+
//| 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[])
  {
//---
   Label1Buffer1[0]= AccountInfoDouble(ACCOUNT_EQUITY);
   Label1Buffer2[0]= AccountInfoDouble(ACCOUNT_EQUITY);
   Label1Buffer3[0]= AccountInfoDouble(ACCOUNT_EQUITY);
   Label1Buffer4[0]= AccountInfoDouble(ACCOUNT_EQUITY);
//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+
 

Sistemato un po' l'indicatore in modo che sia migliore

#property indicator_separate_window
#property indicator_buffers 4
#property indicator_plots   1
//--- plot Label1
#property indicator_label1  "Label1"
#property indicator_type1   DRAW_CANDLES
#property indicator_color1  MediumAquamarine
#property indicator_style1  STYLE_SOLID
#property indicator_width1  1

double         Label1Buffer1[];
double         Label1Buffer2[];
double         Label1Buffer3[];
double         Label1Buffer4[];

datetime Time[1];
datetime curbar[1];
datetime lastbar[1];
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   SetIndexBuffer(0,Label1Buffer1,INDICATOR_DATA);
   SetIndexBuffer(1,Label1Buffer2,INDICATOR_DATA);
   SetIndexBuffer(2,Label1Buffer3,INDICATOR_DATA);
   SetIndexBuffer(3,Label1Buffer4,INDICATOR_DATA);

   ArraySetAsSeries(Label1Buffer1,true);
   ArraySetAsSeries(Label1Buffer2,true);
   ArraySetAsSeries(Label1Buffer3,true);
   ArraySetAsSeries(Label1Buffer4,true);

   ArrayInitialize(Label1Buffer1,0.0);
   ArrayInitialize(Label1Buffer2,0.0);
   ArrayInitialize(Label1Buffer3,0.0);
   ArrayInitialize(Label1Buffer4,0.0);

//---
   return(0);
  }
//+------------------------------------------------------------------+
//| 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[])
  {
//---
   if(NewBar())
     {
      Label1Buffer1[0]= AccountInfoDouble(ACCOUNT_EQUITY);
      Label1Buffer2[0]= AccountInfoDouble(ACCOUNT_EQUITY);
      Label1Buffer3[0]= AccountInfoDouble(ACCOUNT_EQUITY);
      Label1Buffer4[0]= AccountInfoDouble(ACCOUNT_EQUITY);
     }
   if(AccountInfoDouble(ACCOUNT_EQUITY)>Label1Buffer2[0])Label1Buffer2[0]= AccountInfoDouble(ACCOUNT_EQUITY);
   if(AccountInfoDouble(ACCOUNT_EQUITY)<Label1Buffer3[0])Label1Buffer3[0]= AccountInfoDouble(ACCOUNT_EQUITY);
   Label1Buffer4[0]=AccountInfoDouble(ACCOUNT_EQUITY);
//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+
bool NewBar()
  {
   if(CopyTime(_Symbol,0,0,1,Time)<1)return(false);

   curbar[0]=Time[0];
   if(lastbar[0]!=curbar[0])
     {
      lastbar[0]=curbar[0];
      return(true);
     }
   else
     {
      return(false);
     }
  }
//+------------------------------------------------------------------+
 

Questo è più o meno il quadro che emerge

т

 

Sergey, grazie!

Ma è davvero possibile creare un robusto oscillatore Equity con la storia presa in considerazione?

L'Expert Advisor mostra tutti i valori di Equity per il periodo selezionato nel tester nel modo più semplice

Stampa(AccountInfoDouble(ACCOUNT_EQUITY))...

 
DV2010:

Sergey, grazie!

Ma è davvero possibile creare un robusto oscillatore Equity che tenga conto della storia?

L'Expert Advisor mostra tutti i valori di Equity per il periodo selezionato nel tester nel modo più semplice

Stampa(AccountInfoDouble(ACCOUNT_EQUITY))...

Si può, ma non è così facile. È necessario emulare il trading in base alla storia degli scambi. e ci possono essere anche problemi con la sincronizzazione dei dati su diversi strumenti. E non confondere l'indicatore con il tester. È il tester che emula il trading.
 

A giudicare dai valori che cambiano in Print(AccountInfoDouble(ACCOUNT_EQUITY)), ci sono cambiamenti in Equity perché lo stato attuale di Equity dalla storia è emulato nel metodo OnCalculatde(...) dell'indicatore e questo avviene sincronicamente con l'elaborazione nel metodo OnTick dell'EA.

Allora qual è il problema? Perché nell'uscita il profitto varia, mentre rimane invariato nell'indicatore (nel mio caso - 10000)?

Il codice è semplice (l'ho riscritto un po'):

//+------------------------------------------------------------------+
//|                                                       Equity.mq5 |
//|                        Copyright 2010, MetaQuotes Software Corp. |
//|                                              http://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2010, MetaQuotes Software Corp."
#property link      "http://www.mql5.com"
#property version   "1.00"
#property indicator_separate_window
#property indicator_buffers 1
#property indicator_plots   1
//--- plot Label1
#property indicator_label1  "Label1"
#property indicator_type1   DRAW_LINE
#property indicator_color1  Red
#property indicator_style1  STYLE_SOLID
#property indicator_width1  1
//--- indicator buffers
double Values[];


//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit(){
   //--- indicator buffers mapping
   SetIndexBuffer(0,Values,INDICATOR_DATA);
   PlotIndexSetInteger(0, PLOT_DRAW_BEGIN, 100);
   PlotIndexSetDouble(0, PLOT_EMPTY_VALUE, EMPTY_VALUE);
   ArraySetAsSeries(Values, false);
   return(0);
  }


//+------------------------------------------------------------------+
//| 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[]){


   //---Блок контрольных показателей
   HistorySelect(0,TimeCurrent());
   Print("Equity - OnCalculate: HistoryDealsTotal()=", HistoryDealsTotal());
   Print("Equity - OnCalculate: AccountInfoDouble(ACCOUNT_EQUITY)=", AccountInfoDouble(ACCOUNT_EQUITY));
   Print("Equity - OnCalculate: rates_total=", rates_total);
   Print("Equity - OnCalculate: prev_calculated=", prev_calculated);
   Print("Equity - OnCalculate: ArraySize(open)= ", ArraySize(open));
   Print("Equity - OnCalculate: ArraySize(Values)= ", ArraySize(Values));
   Print("Equity - OnCalculate: datetime(time[",ArraySize(time)-1,"])= ", datetime(time[ArraySize(time)-1]));  


   //---Блок заполнения Индикатора и журнала сообщений значениями
   for (int i = prev_calculated; i <= rates_total-1; ++i){
      //Путем сопоставления с выводом значений в Print() исследуются 2 варианта:
      // - Первый вариант - индикатор показывает динамику цен - правильно
      //Values[i] = open[i]; //То есть в соответствии с выводом в Print(...)
      // - Второй вариант - индикатор показывает динамику Equity - неправильно, так как объем остается постоянным
      Values[i] = AccountInfoDouble(ACCOUNT_EQUITY); //Хотя в выводе Print(...) он меняется 
      //---Блок проверки даты и показателей цены открытия и Equity в цикле заполнения в рамках диапазона тестирования:
      if(prev_calculated > 0){
         Print("Equity - OnCalculate - Cycle: datetime([",i,"])= ", datetime(time[i]));
         Print("Equity - OnCalculate - Cycle: ArraySize([",i,"])= ", open[i]);
         Print("Equity - OnCalculate - Cycle: AccountInfoDouble(ACCOUNT_EQUITY) = ", AccountInfoDouble(ACCOUNT_EQUITY));    
      }
   }
   return rates_total;
}


Come risultato il valore di equilibrio nell'indicatore è costante e = 10000, mentre nell'uscita Print cambia, e nel caso di dinamiche non di equilibrio ma di prezzi viene visualizzato correttamente.

Per esempio, per l'ultima delle barre del periodo testato i parametri sono i seguenti

2011.01.19 19:27:27 Core 1 2011.01.14 22:00:00 Equity - OnCalculate - Cycle: AccountInfoDouble(ACCOUNT_EQUITY) = 9949.29999999999999
2011.01.19 19:27:27 Core 1 2011.01.14 22:00:00 Equity - OnCalculate - Cycle: ArraySize([6418])= 1.33724
2011.01.19 19:27:27:27 Core 1 2011.01.14 22:00:00 Equity - OnCalculate - Cycle: datetime([6418])= 2011.01.14 22:00:00
2011.01.19 19:27:27 Core 1 2011.01.14 22:00:00 Equity - OnCalculate: datetime(time[6418])= 2011.01.14 22:00:00
2011.01.19 19:27:27:27 Core 1 2011.01.14 22:00:00 Equity - OnCalculate: ArraySize(Values)=6419
2011.01.19 19 19:27:27 Core 1 2011.01.14 22:00:00 Equity - OnCalculate: ArraySize(open)= 6419
2011.01.19 19 19:27:27 Core 1 2011.01.14 22:00:00 Equity - OnCalculate: prev_calculated=6418
2011.01.19 19:27:27:27 Core 1 2011.01.14 22:00:00 Equity - OnCalculate: rates_total=6419
2011.01.19 19:27:27:27 Core 1 2011.01.14 22:00:00 Equity - OnCalculate: AccountInfoDouble(ACCOUNT_EQUITY)=9949.29999999999999
2011.01.19 19:27:27 Core 1 2011.01.14 22:00:00 Equity - OnCalculate: HistoryDealsTotal()=12

Документация по MQL5: Общие функции / Print
Документация по MQL5: Общие функции / Print
  • www.mql5.com
Общие функции / Print - Документация по MQL5
File:
Equity.mq5  4 kb
 

È più bello così.

 
DV2010:

Qui sotto c'è il codice dell'oscillatore, che in tutta la sua semplicità non produce un risultato.

Inserite il codice correttamente in modo che sia evidenziato.
MQL5.community - Памятка пользователя
MQL5.community - Памятка пользователя
  • 2010.02.23
  • MetaQuotes Software Corp.
  • www.mql5.com
Вы недавно зарегистрировались и у вас возникли вопросы: Как вставить картинку в сообщение на форуме, как красиво оформить исходный код MQL5, где находятся ваши Личные сообщения? В этой статье мы подготовили для вас несколько практических советов, которые помогут быстрее освоиться на сайте MQL5.community и позволят в полной мере воспользоваться доступными функциональными возможностями.
 
DV2010:

A giudicare dai valori che cambiano in Print(AccountInfoDouble(ACCOUNT_EQUITY)), ci sono cambiamenti in Equity perché lo stato attuale di Equity dalla storia è emulato nel metodo OnCalculatde(...) dell'indicatore e questo avviene sincronicamente con l'elaborazione nel metodo OnTick dell'EA.

Allora qual è il problema? Perché nell'output il profitto varia, mentre nell'indicatore rimane costante (nel mio caso - 10000)?


È sufficiente commentare tutti gli output non necessari e iniziare ad emettere il valore prev_calculato, per capire che l'indicatore è calcolato solo per la prima volta, e il ciclo non funziona sui tick successivi

   //---Блок контрольных показателей
   //HistorySelect(0,TimeCurrent());
   //Print("Equity - OnCalculate: HistoryDealsTotal()=", HistoryDealsTotal());
   //Print("Equity - OnCalculate: AccountInfoDouble(ACCOUNT_EQUITY)=", AccountInfoDouble(ACCOUNT_EQUITY));
   //Print("Equity - OnCalculate: rates_total=", rates_total);
   //Print("Equity - OnCalculate: prev_calculated=", prev_calculated);
   //Print("Equity - OnCalculate: ArraySize(open)= ", ArraySize(open));
   //Print("Equity - OnCalculate: ArraySize(Values)= ", ArraySize(Values));
   //Print("Equity - OnCalculate: datetime(time[",ArraySize(time)-1,"])= ", datetime(time[ArraySize(time)-1]));  
   Print("prev_calculated=",prev_calculated,"   rates_total=",rates_total);
 

Rosh, ad essere sincero, non ti ho capito molto . L'uscita era necessaria solo per assicurarsi che Equity all'interno della gamma di test cambiasse

. Il

fatto che il ciclo in OnCalculated funziona rispetto all'intervallo prima dell'inizio dell'intervallo di test, e poi all'interno dell'intervallo di testogni chiamata di OnCalculated contiene solo un tick e un passaggio - è chiaro, ma perché il valore mutevole

di

Equity non viene visualizzato sull'indicatore, anche se i valori mutevoli vengono scritti nell'array Indicator?

Ecco il

codice della versione abbreviata di OnCalculated:

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[]){
   Print("prev_calculated=",prev_calculated,"   rates_total=",rates_total);
   Print("Equity - OnCalculate: AccountInfoDouble(ACCOUNT_EQUITY)=", AccountInfoDouble(ACCOUNT_EQUITY));
   for (int i = prev_calculated; i <= rates_total-1; ++i){
      Values[i] = AccountInfoDouble(ACCOUNT_EQUITY);
   }
   return rates_total;
}

Ecco i risultati alla fine del periodo di test dove possiamo vedere che Equity che scriviamo nell'array di valori dell'indicatore cambia e differisce dal saldo iniziale uguale a 10000:

2011.01.20 13:32:07     Core 1  OnTester result 0
2011.01.20 13:32:07     Core 1  2011.01.14 23:59:59   order performed sell 0.15 at 1.33829 [#13 sell 0.15 EURUSD at 1.33829]
2011.01.20 13:32:07     Core 1  2011.01.14 23:59:59   deal performed [#13 sell 0.15 EURUSD at 1.33829]
2011.01.20 13:32:07     Core 1  2011.01.14 23:59:59   deal #13 sell 0.15 EURUSD at 1.33829 done (based on order #13)
2011.01.20 13:32:07     Core 1  2011.01.14 23:59:59   position closed due end of test at 1.33829 [buy 0.15 EURUSD 1.33593]
2011.01.20 13:32:07     Core 1  2011.01.14 22:00:00   Equity - OnCalculate: AccountInfoDouble(ACCOUNT_EQUITY)=9949.299999999999
2011.01.20 13:32:07     Core 1  2011.01.14 22:00:00   prev_calculated=6418   rates_total=6419
2011.01.20 13:32:07     Core 1  2011.01.14 21:00:00   CTrade::PositionOpen: instant buy 0.15 EURUSD at 1.33593 [done at 0.00000]
2011.01.20 13:32:07     Core 1  2011.01.14 21:00:00   order performed buy 0.15 at 1.33593 [#12 buy 0.15 EURUSD at 1.33593]
2011.01.20 13:32:07     Core 1  2011.01.14 21:00:00   deal performed [#12 buy 0.15 EURUSD at 1.33593]
2011.01.20 13:32:07     Core 1  2011.01.14 21:00:00   deal #12 buy 0.15 EURUSD at 1.33593 done (based on order #12)
2011.01.20 13:32:07     Core 1  2011.01.14 21:00:00   instant buy 0.15 EURUSD at 1.33593 (1.33577 / 1.33593 / 1.33577)
Ed ecco il grafico del saldo con i valori assegnati per il periodo di test

Controlliamo il valore di Equity sul grafico dell'indicatore al 2011.01.14 22:00

Secondo

il log

al 2011

.01.14

22

:00:00

dovrebbe essere uguale a 9949:
... 2011.01.14 22:00:00   Equity - OnCalculate: AccountInfoDouble(ACCOUNT_EQUITY)=9949.299999999999

E cosa vediamo sul grafico dell'indicatore

?