0

I am struggling to understand the NCalc and I have few questions.

1) If I have an expression like "if(CLOSE<2.3,ROC(OPEN),HIGH)" and ROC is a custom function. Does the result of "ROC(OPEN)" is available when the condition "CLOSE<2.3" is being evaluated?

2) How do I override the "If" statement? For the case below, I would like to perform a conditional check on each element in "listOpen". If the condition evaluated TRUE then I need to return the value at index where the condition was evaluated true from "listROC" otherwise return the value at the same index from listHigh.

example :

List<double> listResult =  new List<double>();
for(int index = 0; index< listClose.count;index++)
{
    if(listClose[index]<2.3)
         listResult.Add(listROC[index]);
    else
         listResult.Add(listHigh[index]);

}

return listResult;

This is sample code I am trying to get the expression evaluated. I am stuck at overriding/defining a custom if statement.

    private List<double> listOpen = new List<double>();
    private List<double> listClose = new List<double>();
    private List<double> listHigh = new List<double>();
    public void PrepareData()
    {
        for (int index = 0; index < 10; index++)
        {
            Random rnd = new Random();
            double open = rnd.NextDouble() * (2.5 - 2.0) + 2.0;
            listOpen.Add(open);
            double close = rnd.NextDouble() * (2.5 - 2.0) + 2.0;
            listClose.Add(close);
            double high = rnd.NextDouble() * (2.5 - 2.0) + 2.0;
            listHigh.Add(high);

        }
    }
    private void EvaluateExpression()
    {
        PrepareData();

        Expression ex = new Expression("if(CLOSE<2.3,ROC(OPEN),HIGH)");
        ex.EvaluateFunction += delegate(string name, FunctionArgs args)
        {
            if (name == "ROC")
            {
                List<double> listROC = new List<double>();
                string argument = args.Parameters[0].Evaluate().ToString();
                List<double> listParam = new List<double>();
                switch (argument)
                {
                    case "OPEN":
                        listParam = listOpen;
                        break;
                    case "CLOSE":
                        listParam = listClose;
                        break;
                    case "HIGH":
                        listParam = listHigh;
                        break;
                }
                foreach (double dbl in listParam)
                {
                    double result = dbl * 2;
                    listROC.Add(result);
                }
                args.Result = listROC;
            }
            if (name == "if")
            {
               //Override the if function
            }
        };

        object ob = ex.Evaluate();
    }

Any help is much appreciated.

Daniel Mann
  • 57,011
  • 13
  • 100
  • 120
balan
  • 179
  • 1
  • 5
  • 11

2 Answers2

0

cant make out what ou are trying to achieve, maybe if you can explain more would be able to help you better. you cant override "if", incase you dont want if behaviour to be like whats inbuilt use some other word like IF() or Filter() in expression

Brijesh Mishra
  • 2,738
  • 1
  • 21
  • 36
0

My understanding is:

1) The expressions are parsed all together, but then evaluated according to depth. So the if predicate CLOSE<2.3 will be evaluated for truth, then if true ROC(OPEN) will be evaluated. This would be an issue if you try to use parameters before they've been declared -- as in the case if you wrote a custom MAP(arg_array, callback([i])), it would parse callback([i]) expecting the parameter [i] to be present from the beginning of evaluation.

2) As long as you handle the function name and set a result, it should override whatever native handling that would have occurred. I made the mistake of making a convenience handler that always set the result (or threw an exception if it didn't recognize the function) which threw exceptions on unrecognized if statements. You could always define your own if statement with IF (case-sensitive) as well.


But I think your problem is that CLOSE and OPEN are supposed to be static values, and so should be escaped as strings like 'CLOSE' and 'OPEN' instead. Or declared as parameters and handled accordingly. https://ncalc.codeplex.com/wikipage?title=parameters

drzaus
  • 24,171
  • 16
  • 142
  • 201