Announcement

Collapse
No announcement yet.

GetSeries help needed!

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

  • GetSeries help needed!

    So in general it's more effiecient to return the values unless using a different interval than what is on the chart.

    Now back to series questions.
    This is a different script than previous.
    I'm building a series xVT (using efsInternal) but getting some errors/problems.

    1) I want to paint the bars different colors based on there value. and I'm using a global var sType which is being set in the UDF but is null when I try to access in main().

    2) I tried painting the bars inside the UDF called by efsInternal but that didn't work either.

    3) Also, sma(nLen, xVT) is producing NaN for values.

    Would appreciate any guidance on these three issues.



    PHP Code:
    /*************************************************
    PJ's trend indicator
    *************************************************/
    debugClear();

    function 
    preMain() {
        
        
    setPriceStudy(false);
        
    setStudyTitle("Trendy2");
        
    setCursorLabelName("Trendy"0);
        
    setDefaultBarFgColor(Color.blue0);
        
    setPlotType(PLOTTYPE_HISTOGRAM,0);
        
    setDefaultBarThickness(6,0);
        
    setCursorLabelName("MA"1);
        
    setDefaultBarFgColor(Color.blue1);    
        
    addBand(0PS_SOLID1Color.RGB(128,128,128), "zl");
    //    setComputeOnClose();
    }
    var 
    H,H1,L,L1,BL,BH,vSZ,vSum,ratio,prcnt,vG,vB,vUS,vLS;
    var 
    vT null;
    var 
    vT1 null;
    var 
    sType null;
    var 
    rnd=100;
    bInit=false;
    var 
    nLen=5;
    function 
    main() {

        if (
    bInit == false) {

            
    xO=open();
            
    xH=high();
            
    xL=low();
            
    xC=close();
            
    xVT efsInternal("fGetVT",xO,xH,xL,xC);
            
    xMA sma(nLenxVT);
            
    bInit=true;
        }

        
    nVT xVT.getValue(0);
        
    nMA xMA.getValue(0);
        
    //debugPrint(sType+" ");                //  not working sType is null    
        //debugPrintln(nVT+" "+nMA);            //  nMA returning NaN
    /*
        if (sType=="inside" || sType=="outside") {
            setBarFgColor(Color.grey, 0);
        } else {
            if (close(0)<open(0)) {
                setBarFgColor(Color.red, 0);
            }else {
                setBarFgColor(Color.green, 0);
            }
        }
        
        if (Math.abs(nVT)>.85 ) {
            setBarBgColor(Color.yellow, 0);
        }else{
            setBarBgColor(Color.white, 0);
        }
    */
        
    return new Array(getSeries(xVT), getSeries(xMA));
    }


    function 
    fGetVT(_xO_xH_xL_xC) {
        if ( 
    _xO==null || _xH==null || _xL==null || _xC==null ) return;

        
    vT1 vT;       // used only for inside bars
        
    vG=0;           // Gap size
        
    vB=0;           // Body size
        
    vUS=0;          // Upper shadow
        
    vLS=0;          // Lower shadow


        
    H  Math.round(_xH.getValue(0)*rnd)/rnd;
        
    H1 Math.round(_xH.getValue(-1)*rnd)/rnd;
        
    L  Math.round(_xL.getValue(0)*rnd)/rnd;
        
    L1 Math.round(_xL.getValue(-1)*rnd)/rnd;
        
    BL=Math.min_xC.getValue(0), _xO.getValue(0) );
        
    BL Math.round(BL*rnd)/rnd;
        
    BH=Math.max_xC.getValue(0), _xO.getValue(0) );
        
    BH Math.round(BH*rnd)/rnd;
        
        if (
    H<=H1) {
            if (
    L>=L1){
                
    _sT "inside";
            } else {    
    // lower hi and lower lo
                
    _sT "dntrend";
            }
        } else if (
    H>H1) {        
            if (
    L>=L1){ // higher hi & higher lo
                
    _sT "uptrend";
            } else {    
    // H>H1 & L<L1
                
    _sT "outside";
            }
        }    
        
    sType _sT;

        
    vSZ=(H-L);
        
    ratio=vSZ/(H1-L1);                //  computes the ratio of currnet bar vs previous

        
    switch (sType) {
            case 
    "inside" :
                
    vT=vT1;
                break;

            case 
    "uptrend" :
                
    //ut      GAP            
                
    if (L>H1) {  
                    
    vG=L-H1;
                } else {
                    
    vG=0;
                }

                
    //ut      LOWER SHADOW        
                
    if (L<BL) {
                    
    // a gap up with a lower shadow (ie Hanging Man) could be a reversal sign   
                    // but for Trendy purposes it's a higher hi so count everything above prev H
                    
    if (L>=H1) {    // the whole bar is above prev H
                        
    vLS=BL-L;
                    } else {        
    // only count the part > prev H
                        
    vLS=BL-H1;
                    }
                }
                
                
    //ut      the BODY        
                
    if (BL>H1) {        
                    
    vB=BH-BL;
                } else {            
    // only count the body > H1
                    
    vB=BH-H1;
                }
                
                
    //ut      UPPER SHADOW        
                
    if (H>BH) {
                    
    // upper shadows are higher hi but could be a Shooting Star, Hanging Man or Doji, So,
                    // if trend is ending, for shadow > H1 only add 1/2 value and < H1 subtract 1/2 value            
                    
    if (BH>=H1) {
                        
    vUS=(H-BH)/2;  // bottom of shadow > prev H use +1/2 * shadow
                    
    } else {        
                        
    vUS=(BH-H)/2;  // bottom of shadow < prev H use -1/2 * shadow 
                    
    }
                }
               
                
    // Compute Trendy for uptrend
                
    vSum = (vG+vB+vUS+vLS);
                
    prcnt vSum/vSZ;
                
    vT ratio prcnt;
                break;
                
            case 
    "dntrend" :
            
    //  values should be negative

                //dt      GAP     
                
    if (H<L1) {  
                    
    vG=H-L1;
                } else {
                    
    vG=0;
                }

                
    //dt      UPPER SHADOW        
                
    if (H>BH) {
                    
    // the upper shadow is "within" the downtrend, count everything < prev L
                    
    if (H<=L1) {    // the whole bar is < prev L    
                        
    vUS=BH-H;
                    } else {        
    // only count the part < prev L
                        
    if (BH<L1) {
                            
    vUS=BH-L1;
                        } else {
                            
    vUS=0;
                        }
                    }
                } else {
                    
    vUS=0;
                }
                
                
    //dt      the BODY                    
                
    if (BH<L1) {        // get body size below prev L
                    
    vB=BL-BH;
                } else {            
    // only count the body < L1      
                    
    if (BL<L1) {
                        
    vB=BL-L1;
                    } else {
                        
    vB=0;       // none of the body is < prev L
                    
    }
                }
                
                
    //dt      LOWER SHADOW       
                
    if (L<BL) {
                    
    // could be a Doji or a Hammer, if lower shadow below prev bar add -1/2 value
                    // and if within the the prev BAR add +1/2 value (to reduce negative amt) 
                    
    if (BL<=L1) {
                        
    vLS=(L-BL)/2;   // top of shadow < prev L add -1/2 * shadow
                    
    } else {            // sType requires L<L1
                        
    vLS=(L1-L)/2;   // top of shadow > prev L add +1/2 * shadow (part below)
                    
    }
                } else{
                    
    vLS=0;
                }
             
                
    // Compute Trendy for downtrend            
                
    vSum = (vG+vB+vUS+vLS);
                
    prcnt vSum/vSZ;
                
    vT ratio prcnt;
                break;            
              
            case 
    "outside" :
            
    //  The outside bar may be an engulfing pattern so set Trendy to match the direction
                
    vT=0;
                
    // should an outside bar be part of the trend?
                
    break;
            default :
                
    // should never be here
                
    debugPrintln("Trendy has bad data");
        }
        
        if (
    sType=="inside" || sType=="outside") {
            
    setBarFgColor(Color.grey0);
        } else {
            if (
    _xC.getValue(0) < _xO.getValue(0)) {
                
    setBarFgColor(Color.red0);
            }else {
                
    setBarFgColor(Color.green0);
            }
        }
        
        if (
    Math.abs(vT)>.85 ) {
            
    setBarBgColor(Color.yellow0);
        }else{
            
    setBarBgColor(Color.white0);
        }        

    return (
    vT);


  • #2
    I wondered why your global variables were not updated in main().
    The following test script tells me that strings cannot be returned by efsInternal() calls nor will they be updated in main() when modified in the UDF called via efsInternal().

    It seems that when you use efsInternal() to call a function, global varibles don't update outside of the called function so they will remain null in main().
    Also a function called via efsInternal() will not return string values, only number values.

    PHP Code:
    debugClear();
    var 
    bInit false;
    var 
    xVT null;
    var 
    tst null;
    function 
    main(){

        if(
    bInit == false){
            
    bInit true;
            
    //xVT = efsInternal("Testsym");//all global variables in Testsym() will be null, ie: tst
        
    }
        
    //var jj = xVT.getValue(0);//returns an error " xVT has no properties" since efsInternal only returns numbers and not text
        //debugPrintln(jj);
        
    Testsym();
        
    debugPrintln(tst);
        return 
    tst;//xVT;//xVT returns "none" since efsInternal only returns numbers and not text
    }
    function 
    Testsym() {
        if(
    high(0) > high(-1)) tst "H";
        else 
    tst "?";
        
    //debugPrintln(tst);

        
    return tst;
    }

    //it seems that when you use efsInternal() to call a function global varibles don't 
    //update outside of the called function so they will remain null in main().
    //also a function called via efsInternal() will not return string values, only number values. 
    I changed many things in your script as I tested different approaches. I tried to comment why I did so.

    I believe the following script does what you intended.

    3) Also, sma(nLen, xVT) is producing NaN for values.
    The reason that the sma returned null values is that the script had three division calculations that did not check for a denominator of value 0 which returned infinity. See lines 115, 162, & 219 of the script below.



    PHP Code:
    //http://forum.esignal.com/showthread.php?s=&threadid=35856
    /*************************************************
    PJ's trend indicator
    *************************************************/
    debugClear();

    function 
    preMain() {
        
        
    setPriceStudy(false);
        
    setStudyTitle("Trendy2");
        
    setCursorLabelName("Trendy"0);
        
    setDefaultBarFgColor(Color.blue0);
        
    setPlotType(PLOTTYPE_HISTOGRAM,0);
        
    setDefaultBarThickness(6,0);
        
    setCursorLabelName("MA"1);
        
    setDefaultBarFgColor(Color.blue1);    
        
    addBand(0PS_SOLID1Color.RGB(128,128,128), "zl");
    //    setComputeOnClose();//DON'T use when using efsInternal() calls.  They are incompatible. See:
    //http://kb.esignalcentral.com/display/2/index.aspx?c=12&cpc=ULwO0A442oKs512Q04X5j0UupP4SveI6dt2WJi7&cid=4&cat=&catURL=&r=0.923184454441071
    }
    var  
    H,H1,L,L1,BL,BH,vSZ,vSum,ratio,prcnt,vG,vB,vUS,vLS;
    var 
    vT null;
    var 
    vT1 null;
    var 
    xVT_vT null;
    var 
    xVT_sT null;
    var 
    sType null;
    var 
    rnd=100;
    bInit=false;
    var 
    nLen=5;
    function 
    main() {
        var 
    nVT,nMA,n_sT;//....declare all varibles as global or local
        
    if (!bInit) {
            
    xVT efsInternal("fGetVT");//....no parameters are needed since all values are included in fGetVT()
            
    xVT_vT getSeries(xVT,0);//....retrieves the series from the first item in the fGetVT() return statement
            
    xVT_sT getSeries(xVT,1);//....retrieves the series from the second item in the fGetVT() return statement
            
    xMA sma(nLenxVT_vT);//....must use the variable that retrieved the first item in the fGetVT() return statement
            
    bInit=true;
        }

        
    nVT xVT_vT.getValue(0); //....returns the series from fGetVT()
        
    nMA xMA.getValue(0);
        var 
    n_sT xVT_sT.getValue(0);//....efsInternal() will not return strings
        
    if (n_sT == 1sType "inside";//....converted _sT in fGetVT() to your text descriptions
        
    if (n_sT == 2sType "uptrend";
        if (
    n_sT == 3sType "dntrend";
        if (
    n_sT == 4sType "outside";

        if (
    sType=="inside" || sType=="outside") {//....works fine in main()
            
    setBarFgColor(Color.grey0);
        } else {
            if (
    close(0)<open(0)) {
                
    setBarFgColor(Color.red0);
            }else {
                
    setBarFgColor(Color.green0);
            }
        }
        
        if (
    Math.abs(nVT)>.85 ) {//....works fine in main()
            
    setBarBgColor(Color.yellow0);
        }else{
            
    setBarBgColor(Color.white0);
        }

        if (
    Math.abs(nVT)>.85 ) {//....works fine in main()
            
    setBarBgColor(Color.yellow0);
        }else{
            
    setBarBgColor(Color.white0);
        }        
        return new Array(
    nVTnMA,sType);//....you can remove the "sType", I just used it as a test
    }

    var 
    bInit1 false;//....created these varibles because open(), etc are not used in main()
    var xO,xH,xL,xC;//....created these varibles because open(), etc are not used in main()
    function fGetVT() {//,,,,,,,,
        
    var _sT;//....all variables need to be defined as local or global
        
    if(!bInit1){//,,,,,,,,
            
    xO=open();//only used in fGetVT()
            
    xH=high();
            
    xL=low();
            
    xC=close();
            
    bInit1 true;
        }
    //    if ( xO==null || xH==null || xL==null || xC==null ) return;
        
    vT1 vT;       // used only for inside bars
        
    vG=0;           // Gap size
        
    vB=0;           // Body size
        
    vUS=0;          // Upper shadow
        
    vLS=0;          // Lower shadow


        
    H  Math.round(xH.getValue(0)*rnd)/rnd;
        
    H1 Math.round(xH.getValue(-1)*rnd)/rnd;
        
    L  Math.round(xL.getValue(0)*rnd)/rnd;
        
    L1 Math.round(xL.getValue(-1)*rnd)/rnd;
        
    BL=Math.minxC.getValue(0), xO.getValue(0) );
        
    BL Math.round(BL*rnd)/rnd;
        
    BH=Math.maxxC.getValue(0), xO.getValue(0) );
        
    BH Math.round(BH*rnd)/rnd;
        
        if (
    H<=H1) {
            if (
    L>=L1){//....changed _sT to a number so efsInternal() can call it
                
    _sT 1;//"inside";
            
    } else {    // lower hi and lower lo
                
    _sT 3;//"dntrend";
            
    }
        } else if (
    H>H1) {        
            if (
    L>=L1){ // higher hi & higher lo
                
    _sT 2;//"uptrend";
            
    } else {    // H>H1 & L<L1
                
    _sT 4;//"outside";
            
    }
        }else 
    _sT 0//....added the else statement to always have a value for _sT

        
    vSZ=(H-L);
        if(
    H1-L1 != 0ratio=vSZ/(H1-L1);//....since (H1-L1) will be a denominator you must check for a 0 value //  computes the ratio of currnet bar vs previous
        
    else ratio 1;   //....CHANGE TO WHATEVER DEFAULT VALUE YOU FIND IS BEST

        
    switch (_sT) {//....changed sType to _sT to separate it in main()
            
    case ://"inside" :
                
    vT=vT1;
                break;

            case 
    ://"uptrend" :
                //ut      GAP            
                
    if (L>H1) {  
                    
    vG=L-H1;
                } else {
                    
    vG=0;
                }

                
    //ut      LOWER SHADOW        
                
    if (L<BL) {
                    
    // a gap up with a lower shadow (ie Hanging Man) could be a reversal sign   
                    // but for Trendy purposes it's a higher hi so count everything above prev H
                    
    if (L>=H1) {    // the whole bar is above prev H
                        
    vLS=BL-L1;
                    } else {        
    // only count the part > prev H
                        
    vLS=BL-H1;
                    }
                }
                
                
    //ut      the BODY        
                
    if (BL>H1) {        
                    
    vB=BH-BL;
                } else {            
    // only count the body > H1
                    
    vB=BH-H1;
                }
                
                
    //ut      UPPER SHADOW        
                
    if (H>BH) {
                    
    // upper shadows are higher hi but could be a Shooting Star, Hanging Man or Doji, So,
                    // if trend is ending, for shadow > H1 only add 1/2 value and < H1 subtract 1/2 value            
                    
    if (BH>=H1) {
                        
    vUS=(H-BH)/2;  // bottom of shadow > prev H use +1/2 * shadow
                    
    } else {        
                        
    vUS=(BH-H)/2;  // bottom of shadow < prev H use -1/2 * shadow 
                    
    }
                }
               
                
    // Compute Trendy for uptrend
                
    vSum = (vG+vB+vUS+vLS);
                if(
    vSZ != 0prcnt vSum/vSZ;//....since (H1-L1) will be a denominator you must check for a 0 value //  computes the ratio of currnet bar vs previous
                
    else vSZ 0;//....CHANGE TO WHATEVER DEFAULT VALUE YOU FIND IS BEST
                
    vT ratio prcnt;
                break;
                
            case 
    ://"dntrend" :
            //  values should be negative

                //dt      GAP     
                
    if (H<L1) {  
                    
    vG=H-L1;
                } else {
                    
    vG=0;
                }

                
    //dt      UPPER SHADOW        
                
    if (H>BH) {
                    
    // the upper shadow is "within" the downtrend, count everything < prev L
                    
    if (H<=L1) {    // the whole bar is < prev L    
                        
    vUS=BH-H;
                    } else {        
    // only count the part < prev L
                        
    if (BH<L1) {
                            
    vUS=BH-L1;
                        } else {
                            
    vUS=0;
                        }
                    }
                } else {
                    
    vUS=0;
                }
                
                
    //dt      the BODY                    
                
    if (BH<L1) {        // get body size below prev L
                    
    vB=BL-BH;
                } else {            
    // only count the body < L1      
                    
    if (BL<L1) {
                        
    vB=BL-L1;
                    } else {
                        
    vB=0;       // none of the body is < prev L
                    
    }
                }
                
                
    //dt      LOWER SHADOW       
                
    if (L<BL) {
                    
    // could be a Doji or a Hammer, if lower shadow below prev bar add -1/2 value
                    // and if within the the prev BAR add +1/2 value (to reduce negative amt) 
                    
    if (BL<=L1) {
                        
    vLS=(L-BL)/2;   // top of shadow < prev L add -1/2 * shadow
                    
    } else {            // _sT requires L<L1
                        
    vLS=(L1-L)/2;   // top of shadow > prev L add +1/2 * shadow (part below)
                    
    }
                } else{
                    
    vLS=0;
                }
             
                
    // Compute Trendy for downtrend            
                
    vSum = (vG+vB+vUS+vLS);
                if(
    vSZ != 0prcnt vSum/vSZ;//....since (H1-L1) will be a denominator you must check for a 0 value //  computes the ratio of currnet bar vs previous
                
    else vSZ 0;//....CHANGE TO WHATEVER DEFAULT VALUE YOU FIND IS BEST
                
    vT ratio prcnt;
                break;            
              
            case 
    ://"outside" :
            //  The outside bar may be an engulfing pattern so set Trendy to match the direction
                
    vT=0;
                
    // should an outside bar be part of the trend?
                
    break;
            default :
                
    // should never be here
                
    debugPrintln("Trendy has bad data");
        }

        return new Array(
    vT,_sT);//....added _sT as an integer so efsInternal could call it

    If any of my conclusions are wrong I welcome comments.

    Wayne
    Last edited by waynecd; 03-27-2011, 04:34 PM.

    Comment


    • #3
      Wow - really great comments. Thanks for all the work Wayne. While working thru the details some things were not readily apparent to me.

      RE your first comment in main(). Are you suggesting changing all the variables? I thought it was appropriate to have some global and some local. In any event I’m guessing all the variables in my first global var as well as vT and vT1 should probably be declared locally in the UDF. Even though you declared the OHLC series below main() – they are global also since they are not in the UDF. Your comment suggests they too could be local to the UDF.

      But perhaps most compelling was your observations on the undocumented features of efsInternal. I wonder if the problem might be trying to return both numbers and text. i.e. efsInternal could return text or numbers but not both (just a thought). I’m surprised about the globals not being available outside the UDF called by efsInternal. I think I tried using setGlobal once to try and overcome the problem and that failed also. The only example I found in the KB on returning an array didn’t mention anything about mixed types but it makes sense that an array should all be the same type.

      When reading the KB note on getSeries I hadn’t grasped the significance of using efsInternal to create the series then using getSeries to retrieve the 2 elements of the return array. The example is assigning each series to a global variable but I suppose it doesn’t matter if it is a local to main() only.

      Comment


      • #4
        Yw.
        RE your first comment in main(). Are you suggesting changing all the variables? I thought it was appropriate to have some global and some local. In any event I’m guessing all the variables in my first global var as well as vT and vT1 should probably be declared locally in the UDF. Even though you declared the OHLC series below main() – they are global also since they are not in the UDF. Your comment suggests they too could be local to the UDF.
        No, as you state, variables that don't require a global scope should be declared as local, otherwise declared as global. The original script had some variables that were not declared so I added the comment when I declared those variables.

        Regarding the "var xO,xH,xL,xC;", as I understand it they should be declared as global because each is assigned a series which should be done only once, thus I placed them within the "bInit1" statement. They must be global to survive outside of bInit1.

        Variables declared outside of functions are global. I just place global variables that apply to a specific UDF outside of that UDF so I know where they belong.

        But perhaps most compelling was your observations on the undocumented features of efsInternal. I wonder if the problem might be trying to return both numbers and text. i.e. efsInternal could return text or numbers but not both (just a thought). I’m surprised about the globals not being available outside the UDF called by efsInternal. I think I tried using setGlobal once to try and overcome the problem and that failed also. The only example I found in the KB on returning an array didn’t mention anything about mixed types but it makes sense that an array should all be the same type.
        I came to my conclusions based on test scripts. I found that a UDF called via efsInternal will not return a string even if it is the only thing returned by the UDF. I did not try to do it via get/setGlobalValue() though I believe it should work.

        When reading the KB note on getSeries I hadn’t grasped the significance of using efsInternal to create the series then using getSeries to retrieve the 2 elements of the return array. The example is assigning each series to a global variable but I suppose it doesn’t matter if it is a local to main() only.
        It depends how and where you will use the variable. When in doubt I always test both ways (as local and as global), if all works well as local I leave it as a local variable to reduce overhead in the global namespace.

        Wayne
        Last edited by waynecd; 03-29-2011, 04:04 PM.

        Comment

        Working...
        X