Download MetaTrader 5

Problem encountered in porting CCFp.mq4 to MT5, need expert advice.

To add comments, please log in or register
XuWei Li
2796
XuWei Li  

I'm trying to port CCFp.mq4 from https://www.mql5.com/en/articles/1464 to MT5.

 

The problem blocks my road is this tricky function.

//+------------------------------------------------------------------+
//|  Subroutines                                                     |
//+------------------------------------------------------------------+
double ma(string sym, int per, int Mode, int Price, int i)
  {
   double res = 0;
   int k = 1;
   int ma_shift = 0;
   int tf = 0;
   switch(Period())
     {
       case 1:     res += iMA(sym, tf, per*k, ma_shift, Mode, Price, i); 
                   k += 5;
       case 5:     res += iMA(sym, tf, per*k, ma_shift, Mode, Price, i); 
                   k += 3;
       case 15:    res += iMA(sym, tf, per*k, ma_shift, Mode, Price, i); 
                   k += 2;
       case 30:    res += iMA(sym, tf, per*k, ma_shift, Mode, Price, i); 
                   k += 2;
       case 60:    res += iMA(sym, tf, per*k, ma_shift, Mode, Price, i); 
                   k += 4;
       case 240:   res += iMA(sym, tf, per*k, ma_shift, Mode, Price, i); 
                   k += 6;
       case 1440:  res += iMA(sym, tf, per*k, ma_shift, Mode, Price, i); 
                   k += 4;
       case 10080: res += iMA(sym, tf, per*k, ma_shift, Mode, Price, i); 
                   k +=4;
       case 43200: res += iMA(sym, tf, per*k, ma_shift, Mode, Price, i); 
     } 
   return(res);
  }  

 If you know how switch work, you will know how tricky it was.

 I'm trying to port it to MT5 as

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
double MAres(string sym, int per, ENUM_MA_METHOD Mode, ENUM_APPLIED_PRICE price, int i) {
   double res = 0;
   int k = 1;
   int ma_shift = 0;
   ENUM_TIMEFRAMES tf = PERIOD_CURRENT;
   int mah_1=INVALID_HANDLE, mah_5=INVALID_HANDLE, mah_15=INVALID_HANDLE, mah_30=INVALID_HANDLE,
   mah_60=INVALID_HANDLE, mah_240=INVALID_HANDLE, mah_1440=INVALID_HANDLE, mah_10080=INVALID_HANDLE, mah_43200=INVALID_HANDLE;
   double mab_1[], mab_5[], mab_15[], mab_30[], mab_60[], mab_240[], mab_1440[], mab_10080[], mab_43200[];
   ArraySetAsSeries(mab_1,true);
   ArraySetAsSeries(mab_5,true);
   ArraySetAsSeries(mab_15,true);
   ArraySetAsSeries(mab_30,true);
   ArraySetAsSeries(mab_60,true);
   ArraySetAsSeries(mab_240,true);
   ArraySetAsSeries(mab_1440,true);
   ArraySetAsSeries(mab_10080,true);
   ArraySetAsSeries(mab_43200,true);
   switch(Period())
     {
       case PERIOD_M1:
         mah_1 = iMA(sym, tf, per*k, 0, Mode, price);
         if(mah_1 != INVALID_HANDLE) {
           if(CopyBuffer(mah_1, 0, i, 1, mab_1)==1 && mab_1[0]!=EMPTY_VALUE) {
             res += mab_1[0];
           }
           else {
             Print("Getdata failed. Error ", GetLastError());
           }
           
           if(!IndicatorRelease(mah_1)) {
             Print("IndicatorRelease() failed. Error ", GetLastError());
           }
           else {
             mah_1 = INVALID_HANDLE;
           }
         }
         k += 5;
       case PERIOD_M5:
         mah_5 = iMA(sym, tf, per*k, 0, Mode, price);
         if(mah_5 != INVALID_HANDLE) {
           if(CopyBuffer(mah_5, 0, i, 1, mab_5)==1 && mab_5[0]!=EMPTY_VALUE) {
             res += mab_5[0];
           }
           else {
             Print("Getdata failed. Error ", GetLastError());
           }
           if(!IndicatorRelease(mah_5)) {
             Print("IndicatorRelease() failed. Error ", GetLastError());
           }
           else {
             mah_5 = INVALID_HANDLE;
           }
         }
              k += 3;
       case PERIOD_M15:
         mah_15 = iMA(sym, tf, per*k, 0, Mode, price);
         if(mah_15 != INVALID_HANDLE) {
           if(CopyBuffer(mah_15, 0, i, 1, mab_15)==1 && mab_15[0]!=EMPTY_VALUE) {
             res += mab_15[0];
           }
           else {
             Print("Getdata failed. Error ", GetLastError());
             Print("i=",i," ",sym," tf: ",tf," period: ", per*k, " handle: ", mah_15);
           }
           if(!IndicatorRelease(mah_15)) {
             Print("IndicatorRelease() failed. Error ", GetLastError());
           }
           else {
             mah_15 = INVALID_HANDLE;
           }
         }
              k += 2;
       case PERIOD_M30:
         mah_30 = iMA(sym, tf, per*k, 0, Mode, price);
         if(mah_30 != INVALID_HANDLE) {
           if(CopyBuffer(mah_30, 0, i, 1, mab_30)==1 && mab_30[0]!=EMPTY_VALUE) {
             res += mab_30[0];
           }
           else {
             Print("Getdata failed. Error ", GetLastError());
           }
           if(!IndicatorRelease(mah_30)) {
             Print("IndicatorRelease() failed. Error ", GetLastError());
           }
           else {
             mah_30 = INVALID_HANDLE;
           }
         }
              k += 2;
       case PERIOD_H1:
         mah_60 = iMA(sym, tf, per*k, 0, Mode, price);
         if(mah_60 != INVALID_HANDLE) {
           if(CopyBuffer(mah_60, 0, i, 1, mab_60)==1 && mab_60[0]!=EMPTY_VALUE) {
             res += mab_60[0];
           }
           else {
             Print("Getdata failed. Error ", GetLastError());
           }
           if(!IndicatorRelease(mah_60)) {
             Print("IndicatorRelease() failed. Error ", GetLastError());
           }
           else {
             mah_60 = INVALID_HANDLE;
           }
         }
              k += 4;
       case PERIOD_H4:
         mah_240 = iMA(sym, tf, per*k, 0, Mode, price);
         if(mah_240 != INVALID_HANDLE) {
           if(CopyBuffer(mah_240, 0, i, 1, mab_240)==1 && mab_240[0]!=EMPTY_VALUE) {
             res += mab_240[0];
           }
           else {
             Print("Getdata failed. Error ", GetLastError());
           }
           if(!IndicatorRelease(mah_240)) {
             Print("IndicatorRelease() failed. Error ", GetLastError());
           }
           else {
             mah_240 = INVALID_HANDLE;
           }
         }
              k += 6;
       case PERIOD_D1:
         mah_1440 = iMA(sym, tf, per*k, 0, Mode, price);
         if(mah_1440 != INVALID_HANDLE) {
           if(CopyBuffer(mah_1440, 0, i, 1, mab_1440)==1 && mab_1440[0]!=EMPTY_VALUE) {
             res += mab_1440[0];
           }
           else {
             Print("Getdata failed. Error ", GetLastError());
           }
           if(!IndicatorRelease(mah_1440)) {
             Print("IndicatorRelease() failed. Error ", GetLastError());
           }
           else {
             mah_1440 = INVALID_HANDLE;
           }
         }
              k += 4;
       case PERIOD_W1:
         mah_10080 = iMA(sym, tf, per*k, 0, Mode, price);
         if(mah_10080 != INVALID_HANDLE) {
           if(CopyBuffer(mah_10080, 0, i, 1, mab_10080)==1 && mab_10080[0]!=EMPTY_VALUE) {
             res += mab_10080[0];
           }
           else {
             Print("Getdata failed. Error ", GetLastError());
           }
           if(!IndicatorRelease(mah_10080)) {
             Print("IndicatorRelease() failed. Error ", GetLastError());
           }
           else {
             mah_10080 = INVALID_HANDLE;
           }
         }
              k +=4;
       case PERIOD_MN1:
         mah_43200 = iMA(sym, tf, per*k, 0, Mode, price);
         if(mah_43200 != INVALID_HANDLE) {
           if(CopyBuffer(mah_43200, 0, i, 1, mab_43200)==1 && mab_43200[0]!=EMPTY_VALUE) {
             res += mab_43200[0];
           }
           else {
             Print("Getdata failed. Error ", GetLastError());
           }
           if(!IndicatorRelease(mah_43200)) {
             Print("IndicatorRelease() failed. Error ", GetLastError());
           }
           else {
             mah_43200 = INVALID_HANDLE;
           }
         }
     } 
     /*
     ArrayFree(mab_1);
     ArrayFree(mab_5);
     ArrayFree(mab_15);
     ArrayFree(mab_30);
     ArrayFree(mab_60);
     ArrayFree(mab_240);
     ArrayFree(mab_1440);
     ArrayFree(mab_10080);
     ArrayFree(mab_43200);
     */
     //Print(GetLastError());
     //Print(i, " ", rates_total, " ", objMA.Main(0));
     if(GetLastError()>0) {
        res = 0;
        Print(sym);
        Print(GetLastError());
        ResetLastError();
     }
   return(res);
}

 Or as

//+------------------------------------------------------------------+
//|  Subroutines                                                     |
//+------------------------------------------------------------------+
double ma(string sym, int per, ENUM_MA_METHOD Mode, ENUM_APPLIED_PRICE price, int i, int rates_total)
  {
   double res = 0;
   int k = 1;
   int ma_shift = 0;
   ENUM_TIMEFRAMES tf = PERIOD_CURRENT;
   CiMA objMA;
   switch(Period())
     {
       case PERIOD_M1:
              objMA.Create(sym,tf,per*k,0,Mode,price);
              objMA.BufferResize(i+1);
              objMA.Refresh(-1);
              res += objMA.Main(i);
              k += 5;
       case PERIOD_M5:
              objMA.Create(sym,tf,per*k,0,Mode,price);
              objMA.BufferResize(i+1);
              objMA.Refresh(-1);
              res += objMA.Main(i);
              k += 3;
       case PERIOD_M15:
              objMA.Create(sym,tf,per*k,0,Mode,price);
              objMA.BufferResize(i+1);
              objMA.Refresh(-1);
              res += objMA.Main(i);
              k += 2;
       case PERIOD_M30:
              objMA.Create(sym,tf,per*k,0,Mode,price);
              objMA.BufferResize(i+1);
              objMA.Refresh(-1);
              res += objMA.Main(i);
              k += 2;
       case PERIOD_H1:
              objMA.Create(sym,tf,per*k,0,Mode,price);
              objMA.BufferResize(i+1);
              objMA.Refresh(-1);
              res += objMA.Main(i);
              k += 4;
       case PERIOD_H4:
              objMA.Create(sym,tf,per*k,0,Mode,price);
              objMA.BufferResize(i+1);
              objMA.Refresh(-1);
              res += objMA.Main(i);
              k += 6;
       case PERIOD_D1:
              objMA.Create(sym,tf,per*k,0,Mode,price);
              objMA.BufferResize(i+1);
              objMA.Refresh(-1);
              res += objMA.Main(i);
              k += 4;
       case PERIOD_W1:
              objMA.Create(sym,tf,per*k,0,Mode,price);
              objMA.BufferResize(i+1);
              objMA.Refresh(-1);
              res += objMA.Main(i);
              k +=4;
       case PERIOD_MN1:
              objMA.Create(sym,tf,per*k,0,Mode,price);
              objMA.BufferResize(i+1);
              objMA.Refresh(-1);
              res += objMA.Main(i);
     } 
     //Print(GetLastError());
     //Print(i, " ", rates_total, " ", objMA.Main(0));
     if(GetLastError()>0) {
        res = 0;
        Print(objMA.Symbol());
        Print(GetLastError());
        ResetLastError();
     }
   return(res);
  } 

 

 Neither is lucky.  Error code 4806 is always showing up as it can't get the MA value.

Why implement a simple iMA turn to be so complex in MT5?

Am I doing something wrong? 

Theoretical Basis of Building Cluster Indicators for FOREX - MQL4 Articles
  • www.mql5.com
Theoretical Basis of Building Cluster Indicators for FOREX - MQL4 Articles: features of automated forex trading and strategy tester
Files:
CCFp.mq4 18 kb
CCFp_MT5.mq5 29 kb
Alexander Piechotta
7182
Alexander Piechotta  
Помогите перейти на MetaTrader 5 без потерь
  • www.mql5.com
За время существования MT4 были созданы хорошие индикаторы.
XuWei Li
2796
XuWei Li  

Hi, FinGeR,

 Thanks for your advise. I had also check Graff's solution before.

But his solution is changing the original logic to achieve. This solution surely is working, however, already not the same as the original.

 

   switch(_Period)
     {
       case PERIOD_M1:  k += 5; break;
       case PERIOD_M5:  k += 3; break;
       case PERIOD_M15: k += 2; break;
       case PERIOD_M30: k += 2; break;
       case PERIOD_H1:  k += 4; break;
       case PERIOD_H4:  k += 6; break;
       case PERIOD_D1:  k += 4; break;
       case PERIOD_W1:  k += 4; break;       
     } 
   
hwd_EURUSDf=iMA("EURUSD",0,Fast*k,shift,smootMode,price);
hwd_GBPUSDf=iMA("GBPUSD",0,Fast*k,shift,smootMode,price);
hwd_AUDUSDf=iMA("AUDUSD",0,Fast*k,shift,smootMode,price);
//hwd_NZDUSDf=iMA(Symbol(),0,Fast,shift,smootMode,price);
hwd_CADUSDf=iMA("USDCAD",0,Fast*k,shift,smootMode,price);
hwd_CHFUSDf=iMA("USDCHF",0,Fast*k,shift,smootMode,price);
hwd_JPYUSDf=iMA("USDJPY",0,Fast*k,shift,smootMode,price);

// Slow
hwd_EURUSDs=iMA("EURUSD",0,Slow*k,shift,smootMode,price);
hwd_GBPUSDs=iMA("GBPUSD",0,Slow*k,shift,smootMode,price);
hwd_AUDUSDs=iMA("AUDUSD",0,Slow*k,shift,smootMode,price);
//hwd_NZDUSDs=iMA(Symbol(),0,Slow,shift,smootMode,price);
hwd_CADUSDs=iMA("USDCAD",0,Slow*k,shift,smootMode,price);
hwd_CHFUSDs=iMA("USDCHF",0,Slow*k,shift,smootMode,price);
hwd_JPYUSDs=iMA("USDJPY",0,Slow*k,shift,smootMode,price);

 He was using stable handlers which not as the original logic.

 

//+------------------------------------------------------------------+
//|  Subroutines                                                     |
//+------------------------------------------------------------------+
double ma(string sym, int per, int Mode, int Price, int i)
  {
   double res = 0;
   int k = 1;
   int ma_shift = 0;
   int tf = 0;
   switch(Period())
     {
       case 1:     res += iMA(sym, tf, per*k, ma_shift, Mode, Price, i); 
                   k += 5;
       case 5:     res += iMA(sym, tf, per*k, ma_shift, Mode, Price, i); 
                   k += 3;
       case 15:    res += iMA(sym, tf, per*k, ma_shift, Mode, Price, i); 
                   k += 2;
       case 30:    res += iMA(sym, tf, per*k, ma_shift, Mode, Price, i); 
                   k += 2;
       case 60:    res += iMA(sym, tf, per*k, ma_shift, Mode, Price, i); 
                   k += 4;
       case 240:   res += iMA(sym, tf, per*k, ma_shift, Mode, Price, i); 
                   k += 6;
       case 1440:  res += iMA(sym, tf, per*k, ma_shift, Mode, Price, i); 
                   k += 4;
       case 10080: res += iMA(sym, tf, per*k, ma_shift, Mode, Price, i); 
                   k +=4;
       case 43200: res += iMA(sym, tf, per*k, ma_shift, Mode, Price, i); 
     } 
   return(res);
  }  

 

However you need to think how "Switch" work before understanding.

The original accumulate the upper timeframes' values, which make the script can't solidify the MAs handles.

Was the stable handles which need to make 8 * 9 = 72 handles the only solution?

Why my dynamic handles solution can't work, I still don't know why. Is this my only fault or it's the bug of the MT5?

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
double MAres(string sym, int per, ENUM_MA_METHOD Mode, ENUM_APPLIED_PRICE price, int i) {
   double res = 0;
   int k = 1;
   int ma_shift = 0;
   ENUM_TIMEFRAMES tf = PERIOD_CURRENT;
   int mah_1=INVALID_HANDLE, mah_5=INVALID_HANDLE, mah_15=INVALID_HANDLE, mah_30=INVALID_HANDLE,
   mah_60=INVALID_HANDLE, mah_240=INVALID_HANDLE, mah_1440=INVALID_HANDLE, mah_10080=INVALID_HANDLE, mah_43200=INVALID_HANDLE;
   double mab_1[], mab_5[], mab_15[], mab_30[], mab_60[], mab_240[], mab_1440[], mab_10080[], mab_43200[];
   ArraySetAsSeries(mab_1,true);
   ArraySetAsSeries(mab_5,true);
   ArraySetAsSeries(mab_15,true);
   ArraySetAsSeries(mab_30,true);
   ArraySetAsSeries(mab_60,true);
   ArraySetAsSeries(mab_240,true);
   ArraySetAsSeries(mab_1440,true);
   ArraySetAsSeries(mab_10080,true);
   ArraySetAsSeries(mab_43200,true);
   switch(Period())
     {
       case PERIOD_M1:
         mah_1 = iMA(sym, tf, per*k, 0, Mode, price);
         if(mah_1 != INVALID_HANDLE) {
           if(CopyBuffer(mah_1, 0, i, 1, mab_1)==1 && mab_1[0]!=EMPTY_VALUE) {
             res += mab_1[0];
           }
           else {
             Print("Getdata failed. Error ", GetLastError());
           }
           
           if(!IndicatorRelease(mah_1)) {
             Print("IndicatorRelease() failed. Error ", GetLastError());
           }
           else {
             mah_1 = INVALID_HANDLE;
           }
         }
         k += 5;
       case PERIOD_M5:
         mah_5 = iMA(sym, tf, per*k, 0, Mode, price);
         if(mah_5 != INVALID_HANDLE) {
           if(CopyBuffer(mah_5, 0, i, 1, mab_5)==1 && mab_5[0]!=EMPTY_VALUE) {
             res += mab_5[0];
           }
           else {
             Print("Getdata failed. Error ", GetLastError());
           }
           if(!IndicatorRelease(mah_5)) {
             Print("IndicatorRelease() failed. Error ", GetLastError());
           }
           else {
             mah_5 = INVALID_HANDLE;
           }
         }
              k += 3;
       case PERIOD_M15:
         mah_15 = iMA(sym, tf, per*k, 0, Mode, price);
         if(mah_15 != INVALID_HANDLE) {
           if(CopyBuffer(mah_15, 0, i, 1, mab_15)==1 && mab_15[0]!=EMPTY_VALUE) {
             res += mab_15[0];
           }
           else {
             Print("Getdata failed. Error ", GetLastError());
             Print("i=",i," ",sym," tf: ",tf," period: ", per*k, " handle: ", mah_15);
           }
           if(!IndicatorRelease(mah_15)) {
             Print("IndicatorRelease() failed. Error ", GetLastError());
           }
           else {
             mah_15 = INVALID_HANDLE;
           }
         }
              k += 2;
       case PERIOD_M30:
         mah_30 = iMA(sym, tf, per*k, 0, Mode, price);
         if(mah_30 != INVALID_HANDLE) {
           if(CopyBuffer(mah_30, 0, i, 1, mab_30)==1 && mab_30[0]!=EMPTY_VALUE) {
             res += mab_30[0];
           }
           else {
             Print("Getdata failed. Error ", GetLastError());
           }
           if(!IndicatorRelease(mah_30)) {
             Print("IndicatorRelease() failed. Error ", GetLastError());
           }
           else {
             mah_30 = INVALID_HANDLE;
           }
         }
              k += 2;
       case PERIOD_H1:
         mah_60 = iMA(sym, tf, per*k, 0, Mode, price);
         if(mah_60 != INVALID_HANDLE) {
           if(CopyBuffer(mah_60, 0, i, 1, mab_60)==1 && mab_60[0]!=EMPTY_VALUE) {
             res += mab_60[0];
           }
           else {
             Print("Getdata failed. Error ", GetLastError());
           }
           if(!IndicatorRelease(mah_60)) {
             Print("IndicatorRelease() failed. Error ", GetLastError());
           }
           else {
             mah_60 = INVALID_HANDLE;
           }
         }
              k += 4;
       case PERIOD_H4:
         mah_240 = iMA(sym, tf, per*k, 0, Mode, price);
         if(mah_240 != INVALID_HANDLE) {
           if(CopyBuffer(mah_240, 0, i, 1, mab_240)==1 && mab_240[0]!=EMPTY_VALUE) {
             res += mab_240[0];
           }
           else {
             Print("Getdata failed. Error ", GetLastError());
           }
           if(!IndicatorRelease(mah_240)) {
             Print("IndicatorRelease() failed. Error ", GetLastError());
           }
           else {
             mah_240 = INVALID_HANDLE;
           }
         }
              k += 6;
       case PERIOD_D1:
         mah_1440 = iMA(sym, tf, per*k, 0, Mode, price);
         if(mah_1440 != INVALID_HANDLE) {
           if(CopyBuffer(mah_1440, 0, i, 1, mab_1440)==1 && mab_1440[0]!=EMPTY_VALUE) {
             res += mab_1440[0];
           }
           else {
             Print("Getdata failed. Error ", GetLastError());
           }
           if(!IndicatorRelease(mah_1440)) {
             Print("IndicatorRelease() failed. Error ", GetLastError());
           }
           else {
             mah_1440 = INVALID_HANDLE;
           }
         }
              k += 4;
       case PERIOD_W1:
         mah_10080 = iMA(sym, tf, per*k, 0, Mode, price);
         if(mah_10080 != INVALID_HANDLE) {
           if(CopyBuffer(mah_10080, 0, i, 1, mab_10080)==1 && mab_10080[0]!=EMPTY_VALUE) {
             res += mab_10080[0];
           }
           else {
             Print("Getdata failed. Error ", GetLastError());
           }
           if(!IndicatorRelease(mah_10080)) {
             Print("IndicatorRelease() failed. Error ", GetLastError());
           }
           else {
             mah_10080 = INVALID_HANDLE;
           }
         }
              k +=4;
       case PERIOD_MN1:
         mah_43200 = iMA(sym, tf, per*k, 0, Mode, price);
         if(mah_43200 != INVALID_HANDLE) {
           if(CopyBuffer(mah_43200, 0, i, 1, mab_43200)==1 && mab_43200[0]!=EMPTY_VALUE) {
             res += mab_43200[0];
           }
           else {
             Print("Getdata failed. Error ", GetLastError());
           }
           if(!IndicatorRelease(mah_43200)) {
             Print("IndicatorRelease() failed. Error ", GetLastError());
           }
           else {
             mah_43200 = INVALID_HANDLE;
           }
         }
     } 
     /*
     ArrayFree(mab_1);
     ArrayFree(mab_5);
     ArrayFree(mab_15);
     ArrayFree(mab_30);
     ArrayFree(mab_60);
     ArrayFree(mab_240);
     ArrayFree(mab_1440);
     ArrayFree(mab_10080);
     ArrayFree(mab_43200);
     */
     //Print(GetLastError());
     //Print(i, " ", rates_total, " ", objMA.Main(0));
     if(GetLastError()>0) {
        res = 0;
        Print(sym);
        Print(GetLastError());
        ResetLastError();
     }
   return(res);
}

 

 

 

Chris Mellard
141
Chris Mellard  

I've isolated the issues you're encountering down to error codes 4806, saying the indicator is not ready for use.

Seems any handles need placing in the OnInit section of the indicator, you cannot create them dynamically on the fly in OnCalculate and expect them to be ready to use. Seems like a big step backwards with MQL5 to me compared to MQL4 but this is the only way I've discovered to work around these issues.

I have seen slight exceptions to the above rule when not using the debugger where indicators do work when created on the fly, but given I need to rely heavily on the debugger to ensure the indicators run as expected I'm forced to create static handles in the OnInit.

I cheated and cut corners as I only use this indicator in automated trading on slower timescales H1+ so I didn't bother with the M1->M30 handles which drastically cut down the number of static handles I needed.

Be interested to hear if anyone has discovered a smart way of guaranteeing data back from handles referenced within OnCalculate.

Stanislav Korotky
23351
Stanislav Korotky  
Chris Mellard:

Be interested to hear if anyone has discovered a smart way of guaranteeing data back from handles referenced within OnCalculate.

If you know beforehand which indicator instances you need, than create them in OnInit and use in OnCalculate.

If you don't know parameters and want assign them dynamically, create in OnCalculate ad-hoc and then use also in OnCalculate.

But in both cases you should wait until sub-indicators are initialized and BarsCalculated returns required number of bars for all and any. Until then you should skip calculations and keep your indicator window empty (or show "please wait" message).

To add comments, please log in or register