Indicator:
//+------------------------------------------------------------------+ //| Test_Indicator.mq5 | //| Copyright © 2019, Vladimir Karputov | //| http://wmua.ru/slesar/ | //+------------------------------------------------------------------+ #property copyright "Copyright © 2019, Vladimir Karputov" #property link "http://wmua.ru/slesar/" #property version "1.00" #property indicator_separate_window #property indicator_buffers 1 #property indicator_plots 1 //--- plot BarNumber #property indicator_label1 "BarNumber" #property indicator_type1 DRAW_LINE #property indicator_color1 clrLimeGreen #property indicator_style1 STYLE_SOLID #property indicator_width1 1 //--- input parameters //--- indicator buffers double BarNumberBuffer[]; //+------------------------------------------------------------------+ //| Custom indicator initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- indicator buffers mapping SetIndexBuffer(0,BarNumberBuffer,INDICATOR_DATA); //--- set the accuracy of values to be displayed in the Data Window IndicatorSetInteger(INDICATOR_DIGITS,0); //--- return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| 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 limit=prev_calculated-1; if(prev_calculated==0) limit=0; for(int i=limit; i<rates_total; i++) { BarNumberBuffer[i]=i; } //--- return value of prev_calculated for next call return(rates_total); } //+------------------------------------------------------------------+
EA:
//+------------------------------------------------------------------+ //| Test_EA.mq5 | //| Copyright © 2019, Vladimir Karputov | //| http://wmua.ru/slesar/ | //+------------------------------------------------------------------+ #property copyright "Copyright © 2019, Vladimir Karputov" #property link "http://wmua.ru/slesar/" #property version "1.00" //--- input parameters //--- int handle_iCustom; // variable for storing the handle of the iCustom indicator //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- create handle of the indicator iCustom handle_iCustom=iCustom(Symbol(),Period(),"Test_Indicator"); //--- if the handle is not created if(handle_iCustom==INVALID_HANDLE) { //--- tell about the failure and output the error code PrintFormat("Failed to create handle of the iCustom indicator for the symbol %s/%s, error code %d", Symbol(), EnumToString(Period()), GetLastError()); //--- the indicator is stopped early return(INIT_FAILED); } //--- return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { //--- } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { //--- double buffers[]; ArraySetAsSeries(buffers,true); int start_pos=0,count=3; if(!iGetArray(handle_iCustom,0,start_pos,count,buffers)) return; //--- string text=""; for(int i=0; i<count; i++) text=text+"bar #"+IntegerToString(i)+": "+DoubleToString(buffers[i],0)+"\n"; Comment(text); } //+------------------------------------------------------------------+ //| Get value of buffers | //+------------------------------------------------------------------+ bool iGetArray(const int handle,const int buffer,const int start_pos, const int count,double &arr_buffer[]) { bool result=true; if(!ArrayIsDynamic(arr_buffer)) { PrintFormat("ERROR! EA: %s, FUNCTION: %s, this a no dynamic array!",__FILE__,__FUNCTION__); return(false); } ArrayFree(arr_buffer); //--- reset error code ResetLastError(); //--- fill a part of the iBands array with values from the indicator buffer int copied=CopyBuffer(handle,buffer,start_pos,count,arr_buffer); if(copied!=count) { //--- if the copying fails, tell the error code PrintFormat("ERROR! EA: %s, FUNCTION: %s, amount to copy: %d, copied: %d, error code %d", __FILE__,__FUNCTION__,count,copied,GetLastError()); //--- quit with zero result - it means that the indicator is considered as not calculated return(false); } return(result); } //+------------------------------------------------------------------+
Hi all,
I'm trying to make an EA and backtest it, but I'm having problems with the buffers in my EA. I know that in my custom indicator the values are getting set correctly in the buffers there as I have debugged through that and checked. However in my EA when I use CopyBuffer(), I am not getting the correct values. All I am getting is some random values . I even tried to figure this out using the most simplistic code of an indicator and an EA, which really do nothing but set buffer values in the indicator and copy the buffer values in the EA. So my question is how do I actually get buffer arrays from a custom indicator. Here's the code from my simplistic example as I think if I get the answer for this code, then I will be able to figure it out for my actual more complicated EA:
Attached is also an image of what I'm seeing when I debug if that helps at all. Test[2] always seems to be 0 for some reason. Any feedback is appreciated. Thank you.(updated) I came across almost the same situation as you.
The same Indicator and the same EA, exactly the same settings, run the same test multiple times, there is a high probability of getting randomly incorrect results.
If I initialize the output value of indicators with a value of zero in advance, most of the false test results are all zero and a few are correct.
I now believe that the iCustom() function of MT5/MQL5 is itself faulty.
Since the probability of errors in the optimization series of the same test is much higher than the probability of errors in the individual test, my unreliable guess is:
It may be related to the simultaneous invocation of historical data in multiple test processes.
I tried to completely port the algorithm in my custom indicator into EA, using the CopyRates() function called conditionally in OnTick() to compute the "indicator" value.
- www.mql5.com
Before blaming the iCustom function, you first need to start with yourself: if your code is written carelessly, with system errors, then iCustom is not to blame. How much experience do I have that everyone who screams “iCustom is bad” actually writes their code like “chicken paw” (they write a disgusting code).
This is for information.
Let me remind you that this is a MQL5 technical forum and if you have a question, ask it. Provide a code. Describe the test conditions. Describe the result.
Indicator:
EA:
I came across almost the same situation as you.
The same Indicator and the same EA, exactly the same settings, run the same test multiple times, there is a high probability of getting randomly incorrect results.
If I initialize the output value of indicators with a value of zero in advance, most of the false test results are all zero and a few are correct.
I now believe that the iCustom() function of MT5/MQL5 is itself faulty.
Since the probability of errors in the optimization series of the same test is much higher than the probability of errors in the individual test, my unreliable guess is:
It may be related to the simultaneous invocation of historical data in multiple test processes.
I tried to completely port the algorithm in my custom indicator into EA, using the CopyRates() function called conditionally in OnTick() to compute the "indicator" value.
Thanks for the response, Vladimir. I tried out your code and it worked. I'll have to take a closer look after work hopefully if I have time.
Please note: first I apply to arrays ArraySetAsSeries
double buffers[]; ArraySetAsSeries(buffers,true);
and copy only the last three bars
int start_pos=0,count=3; if(!iGetArray(handle_iCustom,0,start_pos,count,buffers)) return;
Nothing complicated. Everything is very simple!
- www.mql5.com
Hi all,
I'm trying to make an EA and backtest it, but I'm having problems with the buffers in my EA. I know that in my custom indicator the values are getting set correctly in the buffers there as I have debugged through that and checked. However in my EA when I use CopyBuffer(), I am not getting the correct values. All I am getting is some random values . I even tried to figure this out using the most simplistic code of an indicator and an EA, which really do nothing but set buffer values in the indicator and copy the buffer values in the EA. So my question is how do I actually get buffer arrays from a custom indicator. Here's the code from my simplistic example as I think if I get the answer for this code, then I will be able to figure it out for my actual more complicated EA:
Attached is also an image of what I'm seeing when I debug if that helps at all. Test[2] always seems to be 0 for some reason. Any feedback is appreciated. Thank you.error 1.
in your indicator:
TestBuffer[inserted] = inserted;
The index number of TestBuffer in you indicator should always be a bar number like 350188,depending on the history data your test running on,it should never be a number defined by you.
try:
TestBuffer[rates_total-1]=inserted;
error 2.
in your ea:
indicator call in OnInit() means your indicator will be called only once at the first bar.
no further accumulation of variable "inserted", only zero.
try putting CopyBuffer() into OnTick().
thus:
ticks flow, then calculation happens on corresponding bar. till the very last second of your test process.
3. not an error. only an option.
set your receiving array Test[] to timeseries if you want Test[0] to have the most recent indicator value:
ArraySetAsSeries(Test,true);
The order in which you can manipulate the data you extract from the indicator is entirely up to you.
4.
I modified your test indicator and ea to make them work.
You can try it and see if the output is what you need.
please observe the output number after " ------ ". it's the index number of the indicator buffer , a number you can not specify.
//+------------------------------------------------------------------+ //| TestIndicator.mq5 | //| Copyright 2019, MetaQuotes Software Corp. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2019, MetaQuotes Software Corp." #property link "https://www.mql5.com" #property version "1.00" #property indicator_chart_window #property indicator_buffers 1 double TestBuffer[]; int inserted = 0; //+------------------------------------------------------------------+ //| Custom indicator initialization function | //+------------------------------------------------------------------+ int OnInit() { SetIndexBuffer(0,TestBuffer,INDICATOR_DATA); IndicatorSetString(INDICATOR_SHORTNAME, "Testing"); return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Custom indicator iteration function | //+------------------------------------------------------------------+ int OnCalculate(const int rates_total, const int prev_calculated, const int begin, const double &price[]) { TestBuffer[rates_total-1] = inserted; Print(" ------ ",rates_total-1,": ",DoubleToString(TestBuffer[rates_total-1],0)); inserted++; return(rates_total); } //+------------------------------------------------------------------+
//+------------------------------------------------------------------+ //| TestEA.mq5 | //| Copyright 2019, MetaQuotes Software Corp. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2019, MetaQuotes Software Corp." #property link "https://www.mql5.com" #property version "1.00" #property tester_indicator "TestIndicator.ex5" double Test[]; int handle; int couter=2000; //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { // ArraySetAsSeries(Test,true); handle = iCustom(NULL, 0, "TestIndicator"); if ( handle==INVALID_HANDLE ) { Print("Failed to get IndicatorHandle!"); ExpertRemove(); } return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { IndicatorRelease(handle); } //+------------------------------------------------------------------+ void OnTick() { CopyBuffer(handle, 0, 0, 3, Test); for ( int i=0;i<3;i++ ) Print(i," ",DoubleToString(Test[i],0)); Print(""); couter--; if ( couter==0 ) TesterStop(); return; }
Wait for the next bar, than you habe 1 more
you count the existing bars in the chart
Please note: first I apply to arrays ArraySetAsSeries
and copy only the last three bars
Nothing complicated. Everything is very simple!
error 1.
in your indicator:
The index number of TestBuffer in you indicator should always be a bar number like 350188,depending on the history data your test running on,it should never be a number defined by you.
try:
error 2.
in your ea:
indicator call in OnInit() means your indicator will be called only once at the first bar.
no further accumulation of variable "inserted", only zero.
try putting CopyBuffer() into OnTick().
thus:
ticks flow, then calculation happens on corresponding bar. till the very last second of your test process.
3. not an error. only an option.
set your receiving array Test[] to timeseries if you want Test[0] to have the most recent indicator value:
The order in which you can manipulate the data you extract from the indicator is entirely up to you.
4.
I modified your test indicator and ea to make them work.
You can try it and see if the output is what you need.
please observe the output number after " ------ ". it's the index number of the indicator buffer , a number you can not specify.
Thanks for all the tips here. As for #2, that part was on purpose. I simply wanted to see the indicator buffers copy data correctly. I'll see if your updated code works for me. Thanks for taking the time to do that.
Wait for the next bar, than you habe 1 more
you count the existing bars in the chart
- no data at all
- all data are the same (not acceptable, I need the proper MA values)
- array out of range error messages
I thought I've finally fixed these issues but it turned out my solution isn't correct because sometimes the data can change in previous bars - which cannot happen with moving averages.
Here is my code:
double ExtBuffer[]; double dMABuffer[]; //+------------------------------------------------------------------+ //| Custom indicator initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- indicator buffers mapping SetIndexBuffer(0, ExtBuffer, INDICATOR_DATA); //--- indicator accuracy to be displayed IndicatorSetInteger(INDICATOR_DIGITS, _Digits); //---- indicator name to be displayed in DataWindow and subwindow IndicatorSetString(INDICATOR_SHORTNAME, "Trend"); //--- set index of the bar the drawing starts from //PlotIndexSetInteger(0, PLOT_DRAW_BEGIN, 10); PlotIndexSetInteger(0, PLOT_LINE_STYLE, STYLE_SOLID); //--- sets drawing line empty value PlotIndexSetDouble(0, PLOT_EMPTY_VALUE, 0.0); //--- iMAHandle = iMA(NULL, PERIOD_CURRENT, 10, 0, MODE_SMA, PRICE_CLOSE); if ( iMAHandle == INVALID_HANDLE ) { Print(__FUNCTION__, " MA handle invalid at init!"); return (INIT_FAILED); } ArraySetAsSeries(dMABuffer, true); } //+------------------------------------------------------------------+ //| 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 i, limit, j, j1 = 0, cnt = 0; bool bEnd = false; double d; //--- preliminary calculations if ( !prev_calculated ) { //--- set first data ExtBuffer[0] = Close[0]; limit = 1; } else limit = prev_calculated - 1; //--- the main loop of calculations for ( i = limit; i < rates_total && !IsStopped(); i++ ) { if ( i < rates_total - 10 ) { if ( CopyBuffer(iMAHandle, 0, i, 10, dMABuffer) < 0 ) //99% of time this is fine { //Print(__FUNCTION__, ", Error copying MA indicator buffer! "); return -1; } } else { if ( (cnt = CopyBuffer(iMAHandle, 0, i, rates_total - i, dMABuffer)) < 0 ) { Print(__FUNCTION__, ", Error copying MA indicator buffer! "); return -1; } if ( !bEnd ) { bEnd = true;j1 = 0; } } if ( !End ) d = dMABuffer[0] - dMABuffer[1]; if ( bEnd ) //no matter what I do, if this condition is met the buffer is filled with garbage. ; //Even if I explicitly check for the cnt variable to see how much data has been copied - it still doesn't work. } }
If I use this approach at the end
if ( (cnt = CopyBuffer(iMAHandle, 0, 0, rates_total - 1, dMABuffer)) < 0 )
- Free trading apps
- Over 8,000 signals for copying
- Economic news for exploring financial markets
You agree to website policy and terms of use
Hi all,
I'm trying to make an EA and backtest it, but I'm having problems with the buffers in my EA. I know that in my custom indicator the values are getting set correctly in the buffers there as I have debugged through that and checked. However in my EA when I use CopyBuffer(), I am not getting the correct values. All I am getting is some random values . I even tried to figure this out using the most simplistic code of an indicator and an EA, which really do nothing but set buffer values in the indicator and copy the buffer values in the EA. So my question is how do I actually get buffer arrays from a custom indicator. Here's the code from my simplistic example as I think if I get the answer for this code, then I will be able to figure it out for my actual more complicated EA:
Attached is also an image of what I'm seeing when I debug if that helps at all. Test[2] always seems to be 0 for some reason. Any feedback is appreciated. Thank you.