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); } } //+------------------------------------------------------------------+
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))...
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))...
À 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
- www.mql5.com
Voici le code de l'oscillateur, qui, dans toute sa simplicité, ne produit pas de résultat.
- 2010.02.23
- MetaQuotes Software Corp.
- www.mql5.com
À 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 0Et voici le graphique du solde avec les valeurs assignées pour la période de test
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)
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
?
- Applications de trading gratuites
- Plus de 8 000 signaux à copier
- Actualités économiques pour explorer les marchés financiers
Vous acceptez la politique du site Web et les conditions d'utilisation
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 ?