MT5 multi-indicator calculation order - page 2

 

I would suggest, that before tackling such a complex task, you first "play" a bit with a very simple EA and a simple indicator, so that you can understand the process.

Until you can understand the mechanics you are going to have a difficult time designing and implementing your project.

Start small, and then build on it.

 
Fernando Carreiro #:

No, that is not how it works. The indicators and EA work independently of each other and the EA has its own dedicated thread.

The EA can then read the data from the indicators via the CopyBuffer() function, at anytime it wishes when processing an event, for example during OnTick(), OnTimer(), OnChartEvent(), etc.

thanks again,

not sure if we are saying the same thing ?....what i meant was that the EA should be the central hub for all indicators (parallel signal flow...no cascaded indicators)...it queries indicator inputs through iCustom/CopyBuffer calls ......any additional indicator signal processing should happen inside EA's OnTick() ...not through cascading indicator signals to other indicators. Maybe the sketch was not accurate enough:

iCustom1 -------> CopyBuffer1----> EA onTick()

iCustom2 -------> CopyBuffer2---->  EA onTick()

iCustom3 -------> CopyBuffer3---->  EA onTick()

iCustomX -------> CopyBufferX---->  EA onTick()

regarding data synchronization: does a CopyBuffer call from the EA to the indicator initiate an OnCalculate() call on the indicator ? documentation regarding the indicator's OnCalculate() states:  "The function is called in the indicators when the Calculate event occurs for processing price data changes"..... not very clear if it does.

should I look into using somehting like "EventChartCustom" ?

the main issue i am trying to solve is to make sure that when the EA requests indicator data (to make trading decisions)...the indicator data is available and accurate...regardless of complixity of the indicator logic or indicator count.

 
chuckdavis #:

thanks again,

not sure if we are saying the same thing ?....what i meant was that the EA should be the central hub for all indicators (parallel signal flow...no cascaded indicators)...it queries indicator inputs through iCustom/CopyBuffer calls ......any additional indicator signal processing should happen inside EA's OnTick() ...not through cascading indicator signals to other indicators. Maybe the sketch was not accurate enough:

iCustom1 -------> CopyBuffer1----> EA onTick()

iCustom2 -------> CopyBuffer2---->  EA onTick()

iCustom3 -------> CopyBuffer3---->  EA onTick()

iCustomX -------> CopyBufferX---->  EA onTick()

regarding data synchronization: does a CopyBuffer call from the EA to the indicator initiate an OnCalculate() call on the indicator ? documentation regarding the indicator's OnCalculate() states:  "The function is called in the indicators when the Calculate event occurs for processing price data changes"..... not very clear if it does.

should I look into using somehting like "EventChartCustom" ?

the main issue i am trying to solve is to make sure that when the EA requests indicator data (to make trading decisions)...the indicator data is available and accurate...regardless of complixity of the indicator logic or indicator count.

Again no! Here is a pseudo code example ...

OnInit {

        handle1 = iCustom( "... 1 ..." )
        handle2 = iCustom( "... 2 ..." )
        handle3 = iCustom( "... 3 ..." )
}

OnTick {

        if ( NewBar ) {

                CopyBuffer( handle1 )
                CopyBuffer( handle2 )
                CopyBuffer( handle3 )
        }
}

However, I repeat, first make a simple indicator and a simple EA. Otherwise you are going to struggle to understand how it all integrates, and you will end up making a very badly designed (and implemented) project.

 
Fernando Carreiro #:

Again no! Here is a pseudo code example ...

However, I repeat, first make a simple indicator and a simple EA. Otherwise you are going to struggle to understand how it all integrates, and you will end up making a very badly designed (and implemented) project.

@Fernando Carreiro Thanks for your post on this interesting thread.


I am actually working on an indicator which uses Five Indicator classe(s) [Bold and highlighted with Blue Clr] to get input data. The code of OnInit() posted below. So far the indicator is working without any issue. However reading this thread made me cautious and rethink, if I am doing it correctly and will not cause serious issues in future. Your comment will be highly appreciated.

int OnInit() {

                SParamTPA                         paramTPAFast;
                paramTPAFast.showLine             = true;
                paramTPAFast.active               = true;
                paramTPAFast.earlySignal          = true;
                paramTPAFast.tpaPeriod            = 21;   		// PERIOD_M5, TPA Recommended period
                paramTPAFast.smoothFactor         = 4.00;
                paramTPAFast.displayArrow         = true;

                SParamTPA                         paramTPASlow;
                paramTPASlow.showLine             = true;
                paramTPASlow.active               = false;
                paramTPASlow.earlySignal          = false;
                paramTPASlow.tpaPeriod            = 21;                 // PERIOD_M30, Period(50) followed by Market Makers
                paramTPASlow.smoothFactor         = 4.00;
                paramTPASlow.displayArrow         = true;

                SParamHull                        paramHull;
                paramHull.maPeriod                = 32;
                paramHull.devisor                 = 2.50;
                paramHull.appliedPrice            = priceHA_CLOSE;

        //+-----Set TPA Fast, Mid, Slow and Hull Indicators---------------------------------------------------------------------------+
                cTPAFast = CiTPA(_Symbol,_Period,PERIOD_M5,paramTPAFast);
                cTPASlow = CiTPA(_Symbol,_Period,PERIOD_H1,paramTPASlow);

                gHullPeriod     = paramHull.maPeriod;
                cHull           = CiHull(_Symbol,_Period,paramHull);

        //+-----Set up Slope Threshold limits for trend indicators--------------------------------------------------------------------+
                thldHull    = PctDoji;
                thldTPAFast = 1*PctDoji;
                thldTPASlow = 2*PctDoji;

        //+-----Set up iMyATR indicator | For Reversal Bars, we keep SMA & getATR Period as 55 period---------------------------------+
                gSMAPeriod  = 55;
                cATRSlow    = CiMyATR(_Symbol,_Period,gSMAPeriod);

        //+-----Set up iMyATR indicator | For Tags or Touch to Key Price Level, we keep ATRFast Period as 13 period-------------------+
                cATRFast = CiMyATR(_Symbol,_Period,13);

        //+-----Set up indicator properties-------------------------------------------------------------------------------------------+
                IndicatorSetString(INDICATOR_SHORTNAME,"iRevBars");
                IndicatorSetInteger(INDICATOR_DIGITS,_Digits);

        //+-----Set up indicator buffer mapping---------------------------------------------------------------------------------------+
                SetIndexBuffer(_bCoP,bCoP,INDICATOR_DATA);                                    ArraySetAsSeries(bCoP,true);
                SetIndexBuffer(_bWRev,bWRev,INDICATOR_DATA);                                  ArraySetAsSeries(bWRev,true);
                SetIndexBuffer(_b3BC,b3BC,INDICATOR_DATA);                                    ArraySetAsSeries(b3BC,true);
                SetIndexBuffer(_bEGFRev,bEGFRev,INDICATOR_DATA);                              ArraySetAsSeries(bEGFRev,true);
                SetIndexBuffer(_bERev,bERev,INDICATOR_DATA);                                  ArraySetAsSeries(bERev,true);
                SetIndexBuffer(_bPiercing,bPiercing,INDICATOR_DATA);                          ArraySetAsSeries(bPiercing,true);
                SetIndexBuffer(_bTweezer,bTweezer,INDICATOR_DATA);                            ArraySetAsSeries(bTweezer,true);
                SetIndexBuffer(_bHarami,bHarami,INDICATOR_DATA);                              ArraySetAsSeries(bHarami,true);
                SetIndexBuffer(_bNinja,bNinja,INDICATOR_DATA);                                ArraySetAsSeries(bNinja,true);
                SetIndexBuffer(_bDoji,bDoji,INDICATOR_DATA);                                  ArraySetAsSeries(bDoji,true);

        //+-----Set up indicator buffer plots in DataWindow---------------------------------------------------------------------------+
        for(int bufferNo = _bCoP; bufferNo <= _bDoji; bufferNo++) {
            PlotIndexSetString(BNo[bufferNo],PLOT_LABEL,BName[bufferNo]);
            PlotIndexSetDouble(BNo[bufferNo],PLOT_EMPTY_VALUE,0.00);
            PlotIndexSetInteger(BNo[bufferNo],PLOT_SHOW_DATA,DataWindow);                     // 'true' Show in DataWindow
        }
        //+---------------------------------------------------------------------------------------------------------------------------+
        int barsLook = iBarShift(_Symbol,_Period,StringToTime("2024.01.01 00:00"),false);       // On weekends iBarShift return Zero
        gMaxBars = (barsLook != -1 || barsLook != 0) ? barsLook : gMaxBars;
        return(INIT_SUCCEEDED);
}

Regards

 
Anil Varma #:
@Fernando Carreiro Thanks for your post on this interesting thread.


I am actually working on an indicator which uses Five Indicator classe(s) [Bold and highlighted with Blue Clr] to get input data. The code of OnInit() posted below. So far the indicator is working without any issue. However reading this thread made me cautious and rethink, if I am doing it correctly and will not cause serious issues in future. Your comment will be highly appreciated.

Regards

so you have an indicator (master) that takes input data from 5 other indicators (classes) ...then the master indicator feeds to the EA?

blue objects are all custom classes from Cindicator? where are the iCustom and CopyBuffer calls implemented ?


thx

 
chuckdavis #:

so you have an indicator (master) that takes input data from 5 other indicators (classes) ...then the master indicator feeds to the EA?

blue objects are all custom classes from Cindicator? where are the iCustom and CopyBuffer calls implemented ?


thx

Posing here for the benefit of the Members.

Yes usually I create my own or customize prebuild indicators. I than create class to get its data and if needed I addon additional methods required to calculate something.

E.g. I have customized iHull indicator and its class. CopyBuffer() gives me value of Hull indicator. Now there are two more important features in iHull, i.e. its slope and ChangeOfTrend. In the object class I create three methods ...

1) getHull()

2) getTrend()

3) getCoT

This way I can use call to this class wherever I need iHull data. It could be EA, Indicator or another signal class or combination of them. CiHull class works as single point of information and if any changes required in Trend/CoT calculation, I just do that in the class.

 
@Anil Varma #: I am actually working on an indicator which uses Five Indicator classe(s) [Bold and highlighted with Blue Clr] to get input data. The code of OnInit() posted below. So far the indicator is working without any issue. However reading this thread made me cautious and rethink, if I am doing it correctly and will not cause serious issues in future. Your comment will be highly appreciated.

Regards

You are obtaining the handle for the indicator, but it is unclear if you are checking to see if it is valid.

It is clear, however, that you are not aborting the initialisation in the case when one or more of the handles are invalid.

 
chuckdavis #:

in order to keep things a bit organized in the code....do you think i can use objects/classes to encapsulate as much as possible ...or do i absolutely need to have all the fx calls sitting directly inside onTick()?

Classes would normally help with encapsulation and better organization, but it's a matter of the classes. I'm not a fan of the standard classes distributed along with the terminal.

All code in EA runs upon one of available events. Since you requested fast and reliable processing, I'd think that streamlined calculation in the special event for a new tick is a proper place.

 
chuckdavis #:

regarding data synchronization: does a CopyBuffer call from the EA to the indicator initiate an OnCalculate() call on the indicator ? documentation regarding the indicator's OnCalculate() states:  "The function is called in the indicators when the Calculate event occurs for processing price data changes"..... not very clear if it does.

should I look into using somehting like "EventChartCustom" ?

the main issue i am trying to solve is to make sure that when the EA requests indicator data (to make trading decisions)...the indicator data is available and accurate...regardless of complixity of the indicator logic or indicator count.

When a new tick arrives to the terminal, it's dispatched to all attached indicators via OnCalculate event and to all EAs via OnTick - in both cases it's about work symbol of the chart - if you need ticks from other symbols as well, it's a different long story.

If EA calls CopyBuffer on this exact tick, chances are that indicators are not yet re-calculated (they probably are during processing still, even microseconds) for this tick (it depends from many factors: how heavy is your calculations, how many MQL-programs work in parallel, how many free CPU cores are available at the moment), and hence EA could read updated buffers only on the next tick. On the other hand, for very fast market (with bulk incoming ticks) even if you place all calculations into your EA, heavy calculations may not catch the ticks, so some of them can be skipped.

Unfortunately, due to parallelism in the platform, you can't be 100% sure that "when the EA requests indicator data (to make trading decisions)...the indicator data is available and accurate". For example, even built-in Market Watch window and on chart's ask/bid lines can show short and fast discrepencies. Of cource, this is only important for really super-HFT trading strategies. In other cases, several microseconds or milliseconds do not spoil the game.

 
Fernando Carreiro #:

You are obtaining the handle for the indicator, but it is unclear if you are checking to see if it is valid.

It is clear, however, that you are not aborting the initialisation in the case when one or more of the handles are invalid.

Thanks Fernando

Yes it is valid point and I actually used to have a check if Class is valid or not. This is when I define class with *operator. However, I started getting pointer not deleted issues, though I actually deleted them. But somehow at some place I forgot to do that.

At suggestions from this forum, I changed class calling method without *operator and on exit the deconstructor() takes care of removing the class.

I have not tried but will do now, if I can still check if class is valid when declared without *operator.