Announcement

Collapse
No announcement yet.

call() and callFunction()

Collapse
This topic is closed.
X
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • call() and callFunction()

    The object of this thread is to explain the use of call() and callFunction() without resorting, where possible, to any programming jargon.
    I for one know that it took me a while to appreciate the differences between the two functions and to understand when one works (or does not) and why.
    Hopefully this will make life easier for others as it did for me.

    First of all create a folder in the Formulas folder in the eSignal directory and call it Test
    Then in that folder save the attached calledCCI.efs
    In this first example I am using CCI as a study because it has only two parameters thereby making these initial examples easier.

    Now copy the following formula in a new Formula Editor window and save it as callCCI.efs in the same Test directory

    PHP Code:
    function preMain() {
        
    setPriceStudy(false);
        
    setStudyTitle("callCCI");
        
    setCursorLabelName("CCI");  
    }
     
    function 
    main() {
        
        var 
    test null;
       
        
    test call("calledCCI.efs");
        
        if (
    test == null
        return;
        
        return 
    test;

    Create a new chart and load callCCI.efs and you should get the plot of the CCI based on the default parameters in the called efs.



    At this point copy the next formula in a new Formula Editor window and save it as callfunctionCCI.efs in the Test folder.

    PHP Code:
    function preMain() {
        
    setPriceStudy(false);
        
    setStudyTitle("callfunctionCCI");
        
    setCursorLabelName("CCI");    
    }
     
    function 
    main() {
        
        var 
    test null;
       
        
    test callFunction("calledCCI.efs","main");
        
        if (
    test == null
        return;

        return 
    test;

    Once you load this in a chart (or even run a Syntax check) you will get an error that says that there is an invalid parameter 1 in CCIStudy of calledCCI.efs.
    Theoretically the syntax is correct because we are calling "main" in the called efs as suggested and we know that passing parameters is optional as indicated by the Help files and shown with the prior call() function.

    The reason for this error is due to the different “use” call() and callFunction() make of the efs they are calling (in this case calledCCI.efs).

    In the following image highlighted in yellow is what call() "uses" of the called formula.
    As you can see the whole formula is highlighted in yellow which means that callCCI.efs is taking the parameters from preMain() in that formula and applying them to the CCIStudy in main().



    In the next image highlighted in yellow is what callFunction() “uses” of the called formula. Unlike what happens with call(), callFunction() ONLY uses the main() section of the efs.



    As you can see there are no valid parameters defined for CCIStudy in the main() section of the formula hence the error. It is true that they are defined in preMain() but callFunction() does not use that section of the formula so all it “sees” are the words “Length” and “Source” which are not valid parameters.

    There are two solutions to correct this error.

    The first solution is to keep the callfunctionCCI.efs as it is but add the parameters that the CCIStudy needs to run correctly.
    It is true that parameters are optional, but only if they exist in the main() section of the called efs in the first place.
    The correct callfunctionCCI.efs will therefore need to be as follows.

    PHP Code:
    function preMain() {
        
    setPriceStudy(false);
        
    setStudyTitle("callfunctionCCI");
        
    setCursorLabelName("CCI");   
    }
     
    function 
    main() {
        
        var 
    test null;
       
        
    test callFunction("calledCCI.efs","main",20,”Close”);
        
        if (
    test == null
        return;

        return 
    test;

    In the above iteration of the formula we are now passing the parameters to the CCIStudy in the order in which it expects to see them and the result is as follows.



    The other solution entails modifying calledCCI.efs in such a way that the parameters are defined in the main() section of the formula rather than in preMain() which we know callFunction() does not use.
    Here below is calledCCI.efs modified to be used with callFunction() without the need to pass parameters.

    PHP Code:
    var vCCI null;

    function 
    preMain() {
        
    setStudyTitle("calledCCI");
        
    setCursorLabelName("CCI"0);
        
    setDefaultBarFgColor(Color.blue0);
        
        var 
    fp1 = new FunctionParameter("Length"FunctionParameter.NUMBER);
        
    fp1.setLowerLimit(1);        
        
    fp1.setDefault(20); 
        
        var 
    fp2 = new FunctionParameter("Source"FunctionParameter.STRING);
        
    fp2.setName("Source");
        
    fp2.addOption("Close");
        
    fp2.addOption("High");
        
    fp2.addOption("Low");
        
    fp2.addOption("Open"); 
        
    fp2.setDefault("Close");     
    }

    function 
    main(LengthSource) {

        if(
    Length==null)Length=20;
        if(
    Source==null)Source="Close";
        
        if (
    vCCI == nullvCCI = new CCIStudy(LengthSource);
            
        return 
    vCCI.getValue(CCIStudy.CCI);

    Notice that we now have added parameters ie 20 and “Close” in the main() section of the efs which is the section of the formula that callFunction “uses”.



    If we now modify callfunctionCCI.efs back to the way we first wrote it ie as follows…

    PHP Code:
    function preMain() {
        
    setPriceStudy(false);
        
    setStudyTitle("callfunctionCCI");
        
    setCursorLabelName("CCI");
    }
     
    function 
    main() {
        
        var 
    test null;
       
        
    test callFunction("calledCCI.efs","main");
        
        if (
    test == null
        return; 

        return 
    test;

    …it will now work even without passing any parameters because those are now defined in the main() section of the calledCCI.efs.

    At this point we could pass different parameters if we wanted to plot a CCI with different values hence the notion that parameters to be passed are optional.
    Parameters can be passed also when using call() where they are always optional because call() uses all sections of the called formula.
    So while call() is somewhat more flexible in as much as it does not force us to pass parameters, it also has a bit more overhead than callFunction().

    It is important to remember that with either function you will then have to use Arrays() or ref() to retrieve historical values in the calling efs.

    In the next message I intend to cover calling formulas that have multiple returns (ie Arrays) and how to retrieve those values and pass back parameters using both call() and callFunction().

    Alex
    Attached Files

  • #2
    Part 2
    To view this thread in reverse order or in a printable version click here

    In the prior example we used the CCI as the called efs in order to limit the amount of variables involved with regards to both the parameters and the returned data.
    In this second part we are instead going to use a study that returns an Array (ie more than one plot) such as Stochastic, MACD, etc.

    The basic principles of how call() and callFunction() work remain unchanged as does the fact that the called efs(s) need to be structured in exactly the same way as explained in the first post in this thread if they are to be used with callFunction().

    In the Test folder save the attached calledStoch.efs. This will be the study we will be calling using callFunction() and to which we will be passing back parameters.
    Now copy the following formula in a new Formula Editor window and save it as callfunctionStoch.efs in the same Test directory

    PHP Code:
    function preMain() {
        
    setPriceStudy(false);
        
    setStudyTitle("callfunctionStoch");
        
    setCursorLabelName("%K",0); 
        
    setCursorLabelName(%D”,1);
        
    setDefaultBarFgColor(Color.blue,0);
        
    setDefaultBarFgColor(Color.red,1);
    }
     
    function 
    main() {
        
        var 
    test null;
       
        
    test callFunction("calledStoch.efs","main");
        
        if (
    test == null
        return;
        
        return 
    test;

    Other than the fact that we have added some statements in preMain() to name the Cursor label and to color the lines differently this script is essentially identical to the ones provided in the first message of this thread.

    Now create a new chart, load the callfunctionStoch.efs and you should get a chart similar to the one in the following image.



    SIDE NOTE
    As an aside notice that the bands are also being plotted even though they are neither in the return new Array() of the called efs nor are they defined in the calling efs. However if you open the calledStoch.efs you will see that the bands are defined in the main() section of that efs hence they are also called by callFunction(). If on the other hand we had placed the addBands() in preMain() of the called efs they would not appear.



    In the image above highlighted in yellow is the section callFunction() “uses” in the called efs. As you can see the bands are part of the called section. In the next image instead you can see that the bands are not included in the section used by the calling efs hence they do not get plotted.



    In this case the bands will not plot (see last screenshot in this post)
    The problem at this point is that we cannot separate the returned data points of the calledStoch.efs to use them for example to create some conditions. In other words if we wanted to evaluate a cross between %K and %D we cannot address the individual plots with the formula as it is now.

    However each element of an array can be individually addressed by using the array name followed by a value in square brackets that represents the position of the element in the array (starting from 0).
    For example in the return line of calledStoch.efs we have the following

    Return new Array(vStoch.getValue.StochStudy.FAST, vStoch.getValue.StochStudy.SLOW);

    So if we were to assign a name to this array – such as for example TEST - then we would have that

    TEST[0] is vStoch.getValue.StochStudy.FAST ie. the %K plot
    and
    TEST[1] is vStoch.getValue.StochStudy.SLOW ie. the %D plot.

    So if we now modify the calling efs to look as follows

    PHP Code:
    function preMain() {
        
    setPriceStudy(false);
        
    setStudyTitle("callfunctionStoch");
        
    setCursorLabelName("%K",0); 
        
    setCursorLabelName(%D”,1);
        
    setDefaultBarFgColor(Color.blue,0);
        
    setDefaultBarFgColor(Color.red,1);
    }
     
    function 
    main() {
        
        var 
    test null;
       
        
    test callFunction("calledStoch2.efs","main"); //we call the function
        
        
    if(test == null)
        return;
        
        var 
    vFast test[0]; //we create a variable and assign to it the first element of the array
               //called by callFunction()
        
    var vSlow test[1]; //same as above for the second element
        
        
    if(vFast == null || vSlow == null//we perform null checks on both the variables
        
    return;

        
        return new Array (
    vFast,vSlow); //notice that this is now an array also 

    we can access the individual elements of the return array of the efs that we are calling.
    In fact our return is now an array itself whereas before just by using return test; we could plot both %K and %D from the called efs.

    At this point we can apply our conditions using the appropriate variables. In the example below I will paint the background yellow if vFast is above vSlow

    PHP Code:
    function preMain() {
        
    setPriceStudy(false);
        
    setStudyTitle("callfunctionStoch");
        
    setCursorLabelName("%K",0); 
        
    setCursorLabelName("%D",1);
        
    setDefaultBarFgColor(Color.blue,0);
        
    setDefaultBarFgColor(Color.red,1);
    }
     
    function 
    main() {
        
        var 
    test null;
       
        
    test callFunction("calledStoch2.efs","main");
        
        if(
    test == null)
        return;
        
        var 
    vFast test[0];
        var 
    vSlow test[1];
        
        if(
    vFast == null || vSlow == null)
        return;
        
        if(
    vFast>vSlow)
        
    setBarBgColor(Color.yellow);
        
        
        return new Array (
    vFast,vSlow);

    The result is shown in the following image



    In closing a reminder that all the requirements for using call() or callFunction() such as passing parameters, etc remain the same as described in the first part of this brief guide.
    Hope this helps
    Alex
    Attached Files

    Comment

    Working...
    X