Привет всем!
День бьюсь над вопросом построения осциллятора Equity под графиком, к которому он привязан (так как график в Тестере лишен главного, а именно простоты сопоставления с изменением рынка, о чем писали, кстати, и другие).
Проблема же, как я понял, носит двухсторонний характер.
С одной стороны, в методе OnCalculate осциллятора метод определения Equity AccountInfoDouble(ACCOUNT_EQUITY) для каждого бара действовать отказывается.
С другой стороны, трудно понять, можно ли менять график осциллятора (а точнее буфер его данных) из кода OnTick эксперта, где метод AccountInfoDouble(ACCOUNT_EQUITY) работает.
Ниже привожу код осциллятора, который результата при всей своей простоте не дает.
Интуитивно понимаю, что вопрос должен решаться просто, но как - понять пока не могу.
Может быть, у кого-то есть на этот счет какие-то мысли?
AccountInfoDouble(ACCOUNT_EQUITY); возвращает текущее состояние эквити и не имеет истории. В вашем примере все ячейки буфера индикатора записываются одинаковым значением. Вот вам пример индикатора эквити, но он работает только с момента запуска на графике
//+------------------------------------------------------------------+ //| 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); } //+------------------------------------------------------------------+
Немного исправил индикатор так лучше будет
#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); } } //+------------------------------------------------------------------+
Сергей, спасибо!
Но неужели отсутствует возможность создать полноценный осциллятор Equity с учетом истории?
Ведь в OnTick эксперта все значения Equity за выбранный в тестере период выводятся самым простейшим образом
Print (AccountInfoDouble(ACCOUNT_EQUITY))...
Сергей, спасибо!
Но неужели отсутствует возможность создать полноценный осциллятор Equity с учетом истории?
Ведь в OnTick эксперта все значения Equity за выбранный в тестере период выводятся самым простейшим образом
Print (AccountInfoDouble(ACCOUNT_EQUITY))...
Судя по выводу меняющихся значений в Print (AccountInfoDouble(ACCOUNT_EQUITY)), изменения в Equity есть, так как текущее состояние Equity по истории эмулируется в методе OnCalculatde(...) индикатора и происходит это синхронно с обработкой в методе OnTick эксперта.
Так в чем же дело? Почему в выводе в журнал прибыль меняется, в то время, как в Индикаторе остается неизменной (в моем случае - 10000)?
Код - простейший (немного переписал):
//+------------------------------------------------------------------+ //| 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; }
В результате на истории в Индикаторе значение баланса является постоянным и = 10000 , хотя в выводе Print меняется, а в случае с динамикой не баланса, а цен, отображение происходит корректно.
К примеру, для последнего из баров тестируемого периода параметры таковы.
2011.01.19 19:27:27 Core 1 2011.01.14 22:00:00 Equity - OnCalculate - Cycle: AccountInfoDouble(ACCOUNT_EQUITY) = 9949.299999999999
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 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 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 Core 1 2011.01.14 22:00:00 Equity - OnCalculate: rates_total=6419
2011.01.19 19:27:27 Core 1 2011.01.14 22:00:00 Equity - OnCalculate: AccountInfoDouble(ACCOUNT_EQUITY)=9949.299999999999
2011.01.19 19:27:27 Core 1 2011.01.14 22:00:00 Equity - OnCalculate: HistoryDealsTotal()=12
- www.mql5.com
Ниже привожу код осциллятора, который результата при всей своей простоте не дает.
- 2010.02.23
- MetaQuotes Software Corp.
- www.mql5.com
Судя по выводу меняющихся значений в Print (AccountInfoDouble(ACCOUNT_EQUITY)), изменения в Equity есть, так как текущее состояние Equity по истории эмулируется в методе OnCalculatde(...) индикатора и происходит это синхронно с обработкой в методе OnTick эксперта.
Так в чем же дело? Почему в выводе в журнал прибыль меняется, в то время, как в Индикаторе остается неизменной (в моем случае - 10000)?
Вам достаточно закомментировать весь ненужный вывод и начать выводит значение prev_calculated, чтобы понять, что индикатор рассчитывается только в первый раз, а на следующих тиках цикл не работает
//---Блок контрольных показателей //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, если честно, то понял Вас мало. Вывод был нужен только для того, чтобы убедиться в том, что Equity внутри диапазона тестирования действительно меняется.
То, что до начала диапазона тестирования цикл в OnCalculated работает в отношении диапазона, а потом внутри диапазона тестирования каждый вызов OnCalculated содержит только по одному тику и проходу – понятно, но почему изменяющееся значение Equity не отображается на Индикаторе, хотя изменяющиеся значения в массив Индикатора записываются?
Вот - код сокращенной версии 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;
}
Вот - результаты в конце тестируемого периода, в которых видно, что Equity, которые мы записываем в массив значений индикатора, меняется и отличается от первоначального баланса, равного 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)
Проверяем значение Equity по графику индикатора по состоянию на 2011.01.14 22:00.
Согласно журналу по состоянию на 2011.01.14 22:00:00 оно должно быть равным 9949:
... 2011.01.14 22:00:00 Equity - OnCalculate: AccountInfoDouble(ACCOUNT_EQUITY)=9949.299999999999
А что мы видим на графике Индикатора?
- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Вы принимаете политику сайта и условия использования
Привет всем!
День бьюсь над вопросом построения осциллятора Equity под графиком, к которому он привязан (так как график в Тестере лишен главного, а именно простоты сопоставления с изменением рынка, о чем писали, кстати, и другие).
Проблема же, как я понял, носит двухсторонний характер.
С одной стороны, в методе OnCalculate осциллятора метод определения Equity AccountInfoDouble(ACCOUNT_EQUITY) для каждого бара действовать отказывается.
С другой стороны, трудно понять, можно ли менять график осциллятора (а точнее буфер его данных) из кода OnTick эксперта, где метод AccountInfoDouble(ACCOUNT_EQUITY) работает.
Ниже привожу код осциллятора, который результата при всей своей простоте не дает.
//+------------------------------------------------------------------+
//| 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;
}
Интуитивно понимаю, что вопрос должен решаться просто, но как - понять пока не могу.
Может быть, у кого-то есть на этот счет какие-то мысли?