Announcement

Collapse
No announcement yet.

Problem with multi timeframe intervals custom efs

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

  • gem2004
    replied
    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.

    Leave a comment:


  • gem2004
    replied
    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.

    Leave a comment:


  • ACM
    replied
    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

    Leave a comment:


  • gem2004
    replied
    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.

    Leave a comment:


  • ACM
    replied
    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.

    Leave a comment:


  • gem2004
    replied
    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.

    Leave a comment:


  • ACM
    replied
    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.

    Leave a comment:


  • gem2004
    started a topic Problem with multi timeframe intervals custom efs

    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
Working...
X