Announcement

Collapse
No announcement yet.

Problem with multi timeframe intervals custom efs

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Problem with multi timeframe intervals custom efs

    Have been using a custom made efs with multiple timeframe intervals, with the great help that the forum and the knowledge base provide.

    The problem that I face is that when it is loaded on a chart the first 300 historic bars differ substantially from the values that were shown when the same bars were run live. Despite all my efforts I cannot make them identical. So obviously I am missing something or doing it incorrectly.

    I have created the following simplified version that incorporates the points that I wish to have included.

    Any assistance will be highly appreciated, thanking you in advance.
    Attached Files

  • #2
    gem2004
    The issue you are seeing is due to the fact that when running in real time you are calculating nRSIDiffAAA, nRSIDiffBBB and nRSIDiffCCC at BARSTATE_NEWBAR (for each interval) i.e. on the first tick of each corresponding bar using the values at the opening of those bars which is going to give you a different result than when you reload the chart and all of those same bars are now completed
    Here is a very basic sample script that illustrates your issue

    Click image for larger version

Name:	Script Editor_16-08-30_06-24-16.png
Views:	1
Size:	10.7 KB
ID:	243021

    Run it on a chart and you will see that the value being returned in real time is essentially that of the Open of each bar even though I am retrieving the Close (because on the first tick of a bar the Close is the same as the Open).
    If you let it run for some bars and then reload the script (or refresh the chart) you will see that all those "real time" values will change because they now return the value of the Close of the completed historical bars
    Alex


    Originally posted by gem2004 View Post
    Have been using a custom made efs with multiple timeframe intervals, with the great help that the forum and the knowledge base provide.

    The problem that I face is that when it is loaded on a chart the first 300 historic bars differ substantially from the values that were shown when the same bars were run live. Despite all my efforts I cannot make them identical. So obviously I am missing something or doing it incorrectly.

    I have created the following simplified version that incorporates the points that I wish to have included.

    Any assistance will be highly appreciated, thanking you in advance.

    Comment


    • #3
      Thank you Alex for your prompt clarification. For over a decade now you have been of great help.

      I do see the point you make.

      If I understand it well, if I modify the studies that are inside the multiple efsInternals that I use, like RSI, MACD etc to work with the open instead of the close of the bar, then both the historic and the live bars would be identical.

      By the way, I also tried using setComputeOnClose() but with multi timeframe intervals the live bars lag a few bars and I could not find a workaround to make them print on a bar the moment it closes.

      Comment


      • #4
        gem2004

        ...if I modify the studies that are inside the multiple efsInternals that I use, like RSI, MACD etc to work with the open instead of the close of the bar, then both the historic and the live bars would be identical.
        Based on a summary glance of your code it seems to me that they would. It should not be difficult for you to verify it yourself

        On a separate but related topic I see that you are passing the interval series object as the last parameter of each of your efsInternal() calls but then you are also passing the interval series object to each rsi() function within each called function
        That is somewhat redundant since if you call a function (or a separate efs) using an efsInternal() (or efsExternal()) call and within that call you pass the interval (or symbol) series object as the last parameter the function you are calling will run in the context of the interval (or symbol) that is being passed to that function.
        In other words the following code (note that this is just a very basic example to illustrate the concept)

        PHP Code:
        function main(){
            var  
        efsInternal("calc",inv(30));
            return 
        x;
        }
        function 
        calc(){
            return 
        rsi(14);

        will return the same result as the following (which is what you are essentially doing)

        PHP Code:
        function main(){
            var  
        efsInternal("calc",inv(30));
            return 
        x;
        }
        function 
        calc(interval){
            return 
        rsi(14,interval);

        or the following

        PHP Code:
        function main(){
            var  
        rsi(14,inv(30));
            return 
        x;

        even though in the first code example I am not actually passing the interval to the rsi() function. As I said that is because the entire calc() function in that example runs in the context of the interval I am passing to it as the last parameter of the efsInternal() call
        You can see more examples on the use of efsInternal() in this and this thread
        Alex


        Originally posted by gem2004 View Post
        Thank you Alex for your prompt clarification. For over a decade now you have been of great help.

        I do see the point you make.

        If I understand it well, if I modify the studies that are inside the multiple efsInternals that I use, like RSI, MACD etc to work with the open instead of the close of the bar, then both the historic and the live bars would be identical.

        By the way, I also tried using setComputeOnClose() but with multi timeframe intervals the live bars lag a few bars and I could not find a workaround to make them print on a bar the moment it closes.

        Comment


        • #5
          Alex, thank you once again for the elucidations. Each line you write saves me hours of trial and error.

          Will work on your suggestions and I am sure that I will get to where I want to go eventually.

          Comment


          • #6
            gem2004
            FWIW here are a few additional considerations on how to streamline/simplify your script taking better advantage of the functionality of EFS2

            1) In each of the routines you calculate an RSI and use its values to populate an array which you then use to calculate its average. As an example here is your AAARoutine [Note that I am assuming that you set the rsi() function to use the Open and that you implemented the change I suggested earlier whereby the whole routine is running in the context of the interval being passed to it by the efsInternal() call. Also note that I omitted showing the declaration of global variables as that is not the point I am trying to make here]

            PHP Code:
            function AAARoutine() {

                if (
            bInitAAA == false) {
                    
            xStudyRSI rsi(14open());
                    
            bInitAAA true;
                }

                
            nRSIVal xStudyRSI.getValue(0);
                if (
            nRSIVal == null) return;

                
            nMALength 3;
                var 
            nBarStateAAA getBarState();
                if (
            nBarStateAAA == BARSTATE_NEWBAR) {
                    
            vMAArray.unshift(nRSIVal);
                }
                
            vMAArray[0] = nRSIVal;
                if (
            vMAArray[nMALength 1] != null) {
                    var 
            vSum 0;
                    for (
            0<= nMALength 1i++) {
                        
            vSum += vMAArray[i];
                    }
                    
            nRSIAAA vSum nMALength 15;
                } else return;

                if (
            nRSIAAA 0) {
                    
            nRSIAAA 0;
                } else if (
            nRSIAAA 100) {
                    
            nRSIAAA 100;
                }

                return 
            nRSIAAA;

            The whole routine could be significantly simplified using the functionality provided by EFS2. Here is how the same function could be written

            PHP Code:
            function AAARoutine() {
                if (
            bInitAAA == false) {
                    
            xStudyRSI sma(3rsi(14open()));
                    
            bInitAAA true;
                }
                return 
            xStudyRSI.getValue(0);

            2) In the main function you call the three routines and then for each you calculate the difference between its current and previous values. As an example here is the relevant code for one of these

            PHP Code:
            ...
            if (
            xStudyAAA == nullxStudyAAA efsInternal("AAARoutine"inv(nInvA));//here you call the function
            ...
            // AAA
                
            if (getBarStateInterval(nInvA "") == BARSTATE_NEWBAR) {
                    
            nRSIAAA xStudyAAA.getValue(0);
                    
            nRSIPrevAAA xStudyAAA.getValue(-1);
                    if (
            nRSIAAA == null || nRSIPrevAAA == null) return;
                    
            nRSIDiffAAA nRSIAAA nRSIPrevAAA;
                } 
            In essence what you are doing is calculating a 1 period Momentum of the average of an RSI. Again this could be greatly simplified in either of the following ways using the EFS2 functionality

            a) You wrap the efsIntenal() call in the mom() function and set its length to 1

            PHP Code:
            ...
            if (
            xStudyAAA == nullxStudyAAA mom(1efsInternal("AAARoutine"inv(nInvA)));
            ... 
            In this case xStudyAAA.getValue(0) will return the same value as your nRSIDiffAAA

            b) Alternatively you can calculate the Momentum in the separate function itself e.g

            PHP Code:
            function AAARoutine() {
                
                if (
            bInitAAA == false) {
                    
            xStudyRSI mom(1,sma(3,rsi(14,open())));
                    
            bInitAAA true;
                }

                return 
            xStudyRSI.getValue(0);

            Also in this case the value returned by the efsInternal() call in main ie xStudyAAA.getValue(0) will return the same value as your nRSIDiffAAA

            3) Lastly your three routines (I am referring to the separate functions) are exactly the same which is redundant.
            You can just use one separate function and call that multiple times using different efsInternal() calls. Each time it is called the separate function will run in the context of the parameters it is being passed ie as if it were a completely different function.

            Following is your efs rewritten based on all of the above

            PHP Code:
            var bInit false;

            var 
            xStudyAAA null;
            var 
            xStudyBBB null;
            var 
            xStudyCCC null;

            function 
            preMain() {

                
            setStudyTitle("Multi_Intervals");
                
            setPriceStudy(false);
                
            setShowCursorLabel(true);
                
            setShowTitleParameters(false);

                
            setCursorLabelName("Multi"0);
                
            setDefaultBarThickness(30);
                
            setDefaultBarStyle(PS_SOLID0);
                
            setPlotType(PLOTTYPE_LINE0);
            }

            function 
            main() {

                if (
            bInit == false) {

                    if (
            isWatchList()) return;
                    if (!
            isIntraday()) return;
                    if (
            getCurrentBarCount() <= 100) return;

                    var 
            nInterval getInterval();
                    var 
            nTFCoeff nInterval;

                    var 
            nInvA nTFCoeff;//does not need to be a global variable
                    
            var nInvB nTFCoeff;//as above
                    
            var nInvC nTFCoeff;//as above

                    
            if (xStudyAAA == nullxStudyAAA mom(1efsInternal("AAARoutine"inv(nInvA)));
                    if (
            xStudyBBB == nullxStudyBBB mom(1efsInternal("AAARoutine"inv(nInvB)));
                    if (
            xStudyCCC == nullxStudyCCC mom(1efsInternal("AAARoutine"inv(nInvC)));
                    
            /*alternatively you can use the following and calculate the Momenhtum in the separate function itself
                    if (xStudyAAA == null) xStudyAAA = efsInternal("AAARoutine", inv(nInvA));
                    if (xStudyBBB == null) xStudyBBB = efsInternal("AAARoutine", inv(nInvB));
                    if (xStudyCCC == null) xStudyCCC = efsInternal("AAARoutine", inv(nInvC));*/
                    
                    
            bInit true;
                }
                
            //add some null checks for xStudyAAA.getValue(0), etc here
                
            var nSumOfDiffDoubled = (xStudyAAA.getValue(0) + xStudyBBB.getValue(0) + xStudyCCC.getValue(0)) * 2;

                return 
            nSumOfDiffDoubled;
            }

            var 
            bInitAAA false;
            var 
            xStudyRSI null;

            function 
            AAARoutine() {
                
                if (
            bInitAAA == false) {
                    
            xStudyRSI sma(3,rsi(14,open()));
                    
            /*if you use the alternative method in the main function then use the following
                    xStudyRSI = mom(1, sma(3,rsi(14,open())));*/
                    
            bInitAAA true;
                }
                
            //add null check for xStudyRSI.getValue(0) here
                
            return xStudyRSI.getValue(0);

            Having said all this it becomes obvious at this point that you do not even need an external function and can do all your calculations in main.
            Here is how the efs will look

            PHP Code:
            var bInit false;

            var 
            xStudyAAA null;
            var 
            xStudyBBB null;
            var 
            xStudyCCC null;

            function 
            preMain() {

                
            setStudyTitle("Multi_Intervals");
                
            setPriceStudy(false);
                
            setShowCursorLabel(true);
                
            setShowTitleParameters(false);

                
            setCursorLabelName("Multi"0);
                
            setDefaultBarThickness(30);
                
            setDefaultBarStyle(PS_SOLID0);
                
            setPlotType(PLOTTYPE_LINE0);
            }

            function 
            main() {

                if (
            bInit == false) {

                    if (
            isWatchList()) return;
                    if (!
            isIntraday()) return;
                    if (
            getCurrentBarCount() <= 100) return;

                    var 
            nInterval getInterval();
                    var 
            nTFCoeff nInterval;

                    var 
            nInvA nTFCoeff;//does not need to be a global variable
                    
            var nInvB nTFCoeff;//as above
                    
            var nInvC nTFCoeff;//as above

                    
            if (xStudyAAA == nullxStudyAAA mom(1,sma(3,rsi(14,open(inv(nInvA)))));
                    if (
            xStudyBBB == nullxStudyBBB mom(1,sma(3,rsi(14,open(inv(nInvB)))));
                    if (
            xStudyCCC == nullxStudyCCC mom(1,sma(3,rsi(14,open(inv(nInvC)))));
                    
                    
            bInit true;
                }
                
            //add some null checks for xStudyAAA.getValue(0), etc here
                
            var nSumOfDiffDoubled = (xStudyAAA.getValue(0) + xStudyBBB.getValue(0) + xStudyCCC.getValue(0)) * 2;

                return 
            nSumOfDiffDoubled;

            Enclosed below is an image showing the results of your original script modified to use the Open (top sub-chart) and the two variants proposed. As you can see the results are identical
            Alex

            Click image for larger version

Name:	Chart_16-09-03_10-05-39.png
Views:	1
Size:	50.6 KB
ID:	243031

            Comment


            • #7
              Thank you Alex for your extensive reply and suggestions.

              You are the man !

              Will be trying to apply the points you made to the efs that I use with multi intervals, will test them when the markets are open and will revert.

              Comment


              • #8
                Alex you have been of great help and thank you for it.

                Indeed using the “open” produces identical historical and live bars.

                There is of course the disadvantage that on larger time frames the efs is lagging a lot from real time price fluctuations.

                Is there any way at all that the efs can be tweaked to work with “close” instead of “open” and produce identical historical and live bars?

                Or is it a rule that when using multi timeframe intervals the historic bars will differ from the live ones?

                Could maybe something be done to the eSignal engine to resolve this?

                Thank you in advance.

                Comment

                Working...
                X