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); } } //+------------------------------------------------------------------+
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))...
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))...
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
- www.mql5.com
Qui sotto c'è il codice dell'oscillatore, che in tutta la sua semplicità non produce un risultato.
- 2010.02.23
- MetaQuotes Software Corp.
- www.mql5.com
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
. Ilfatto 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
diEquity non viene visualizzato sull'indicatore, anche se i valori mutevoli vengono scritti nell'array Indicator?
Ecco ilcodice 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 0Ed ecco il grafico del saldo con i valori assegnati per il periodo di 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)
Controlliamo il valore di Equity sul grafico dell'indicatore al 2011.01.14 22:00
Secondoil 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
?
- App di trading gratuite
- Oltre 8.000 segnali per il copy trading
- Notizie economiche per esplorare i mercati finanziari
Accetti la politica del sito e le condizioni d’uso
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?