L'oscillateur d'équité de MQL5 signifie

 

Bonjour à tous !

Cela fait une journée que je me débats avec la question de la construction de l'oscillateur Equity sous le graphique auquel il est attaché (parce que le graphique dans le Tester manque de l'essentiel, à savoir la facilité de comparaison avec les changements du marché, comme d'autres l'ont écrit, d'ailleurs).

Le problème, tel que je le comprends, est à double sens.

D'une part, la méthode pour déterminer l'équité AccountInfoDouble(ACCOUNT_EQUITY) pour chaque barre dans la méthode OnCalculate de l'oscillateur refuse de fonctionner.

D'autre part, il est difficile de voir si le graphique de l'oscillateur (ou plutôt son tampon de données) peut être modifié à partir du code OnTick du Conseiller Expert où la méthode AccountInfoDouble(ACCOUNT_EQUITY) fonctionne.

Vous trouverez ci-dessous le code de l'oscillateur qui, malgré sa simplicité, ne donne pas de résultats.

//+------------------------------------------------------------------+
//|                                                       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;
}

Intuitivement, je comprends que le problème doit être résolu de manière simple, mais je n'arrive pas à trouver comment.

Peut-être quelqu'un a-t-il des idées à ce sujet ?

 
DV2010:

Bonjour à tous !

Cela fait une journée que je me débats avec la question de la construction de l'oscillateur Equity sous le graphique auquel il est attaché (parce que le graphique dans le Tester manque de l'essentiel, à savoir la facilité de comparaison avec les changements du marché, comme d'autres l'ont écrit, d'ailleurs).

Le problème, tel que je le comprends, est à double sens.

D'une part, la méthode pour déterminer l'équité AccountInfoDouble(ACCOUNT_EQUITY) pour chaque barre dans la méthode OnCalculate de l'oscillateur refuse de fonctionner.

D'autre part, il est difficile de voir si le graphique de l'oscillateur (ou plutôt son tampon de données) peut être modifié à partir du code OnTick du Conseiller Expert où la méthode AccountInfoDouble(ACCOUNT_EQUITY) fonctionne.

Vous trouverez ci-dessous le code de l'oscillateur qui, malgré sa simplicité, ne donne pas de résultats.


Intuitivement, je comprends que le problème doit être résolu de manière simple, mais je n'arrive pas à trouver comment.

Peut-être quelqu'un a-t-il des idées à ce sujet ?

AccountInfoDouble(ACCOUNT_EQUITY) ; renvoie l'état actuel des fonds propres et n'a pas d'historique. Dans votre exemple, toutes les cellules du tampon de l'indicateur sont écrites avec la même valeur. Voici un exemple de l'indicateur d'équité, mais il ne fonctionne qu'à partir du moment où il est lancé sur le graphique

//+------------------------------------------------------------------+
//|                                                       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);
  }
//+------------------------------------------------------------------+
 

J'ai corrigé un peu l'indicateur pour qu'il soit meilleur.

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

Voici à peu près l'image qui en ressort

т

 

Sergey, merci !

Mais est-il vraiment possible de créer un oscillateur d'actions robuste tenant compte de l'historique ?

Le conseiller expert affiche toutes les valeurs d'actions pour la période sélectionnée dans le testeur de la manière la plus simple qui soit.

Imprimer(AccountInfoDouble(ACCOUNT_EQUITY))...

 
DV2010:

Sergey, merci !

Mais est-il vraiment possible de créer un oscillateur d'actions robuste tenant compte de l'historique ?

Le conseiller expert affiche toutes les valeurs d'actions pour la période sélectionnée dans le testeur de la manière la plus simple qui soit.

Imprimer(AccountInfoDouble(ACCOUNT_EQUITY))...

Vous pouvez, mais ce n'est pas si facile. Vous devez émuler le trading par l'historique des transactions. et il peut également y avoir des problèmes de synchronisation des données sur différents instruments. Et ne confondez pas l'indicateur avec le testeur. C'est le testeur qui émule le commerce.
 

À en juger par les valeurs changeantes dans Print(AccountInfoDouble(ACCOUNT_EQUITY)), il y a des changements dans l'équité parce que l'état actuel de l'équité à partir de l'historique est émulé dans la méthode OnCalculatde(...) de l'indicateur et cela se produit de manière synchrone avec le traitement dans la méthode OnTick de l'EA.

Quel est donc le problème ? Pourquoi le bénéfice en sortie varie-t-il, alors qu'il reste inchangé dans l'indicateur (dans mon cas - 10000) ?

Le code est simple (je l'ai un peu réécrit) :

//+------------------------------------------------------------------+
//|                                                       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;
}


Par conséquent, la valeur de la balance dans l'indicateur est constante et = 10000, tandis que dans la sortie, Print change, et dans le cas de la dynamique non pas de la balance mais des prix, elle est affichée correctement.

Par exemple, pour la dernière des barres de la période testée, les paramètres sont les suivants

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 Équité - 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:27:27 Core 1 2011.01.14 22:00:00 Equity - OnCalculate : ArraySize(open)= 6419
2011.01.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_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
Dossiers :
Equity.mq5  4 kb
 

C'est plus joli comme ça.

 
DV2010:

Voici le code de l'oscillateur, qui, dans toute sa simplicité, ne produit pas de résultat.

Insérez le code correctement afin qu'il soit mis en évidence.
MQL5.community - Памятка пользователя
MQL5.community - Памятка пользователя
  • 2010.02.23
  • MetaQuotes Software Corp.
  • www.mql5.com
Вы недавно зарегистрировались и у вас возникли вопросы: Как вставить картинку в сообщение на форуме, как красиво оформить исходный код MQL5, где находятся ваши Личные сообщения? В этой статье мы подготовили для вас несколько практических советов, которые помогут быстрее освоиться на сайте MQL5.community и позволят в полной мере воспользоваться доступными функциональными возможностями.
 
DV2010:

À en juger par les valeurs changeantes dans Print(AccountInfoDouble(ACCOUNT_EQUITY)), il y a des changements dans l'équité parce que l'état actuel de l'équité à partir de l'historique est émulé dans la méthode OnCalculatde(...) de l'indicateur et cela se produit de manière synchrone avec le traitement dans la méthode OnTick de l'EA.

Quel est donc le problème ? Pourquoi le bénéfice varie-t-il dans la sortie, alors qu'il reste constant dans l'indicateur (dans mon cas - 10000) ?


Il suffit de commenter toutes les sorties inutiles et de commencer à sortir la valeur prev_calculated, pour comprendre que l'indicateur est calculé seulement pour la première fois, et que le cycle ne fonctionne pas sur les ticks suivants.

   //---Блок контрольных показателей
   //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, pour être honnête, je ne vous ai pas beaucoup compris . La sortie était seulement nécessaire pour s'assurer que l'équité à l'intérieur de la gamme de test change

.

Le fait que la boucle dans OnCalculated

fonctionne par rapport à la plage avant le début de la plage de test, et qu'ensuite, à l'intérieur de la plage de test,

chaque appel de OnCalculated ne contient qu'un tick et une passe - est clair, mais pourquoi la valeur changeante

de l'

équité n'est pas affichée sur l'indicateur, bien que les valeurs changeantes soient écrites dans le tableau de l'indicateur ?

Voici le code de la version abrégée de 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;
}

Voici les résultats à la fin de la période de test où nous pouvons voir que l'Equity que nous écrivons dans le tableau des valeurs de l'indicateur change et diffère du solde initial égal à 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)
Et voici le graphique du solde avec les valeurs assignées pour la période de test

Nous vérifions la valeur de l'Equity sur le graphique de l'indicateur à partir de 2011.01.14 22:00

Selon le journal

en date du 2011

.01.14

22

:00:00

, il devrait être égal à 9949 :
... 2011.01.14 22:00:00   Equity - OnCalculate: AccountInfoDouble(ACCOUNT_EQUITY)=9949.299999999999

Et que voyons-nous sur le graphique de l'indicateur

?