Free cookie consent management tool by TermsFeed Policy Generator

source: branches/sluengo/HeuristicLab.Problems.TradeRules/Interpreter.cs @ 14697

Last change on this file since 14697 was 9499, checked in by sluengo, 11 years ago
File size: 29.3 KB
Line 
1using System;
2using System.Collections.Generic;
3using System.Linq;
4using System.Text;
5using HeuristicLab.Common;
6using HeuristicLab.Core;
7using HeuristicLab.Data;
8using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
9using HeuristicLab.Parameters;
10using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
11using HeuristicLab.Problems.DataAnalysis.Symbolic;
12using HeuristicLab.Problems.DataAnalysis;
13using System.Threading;
14
15namespace HeuristicLab.Problems.TradeRules
16{
17    [StorableClass]
18    [Item("Interpreter", "Represents a grammar for Trading Problems")]
19    public sealed class Interpreter : ParameterizedNamedItem, ITradeRulesExpresionTree
20    {
21        private const string CheckExpressionsWithIntervalArithmeticParameterName = "CheckExpressionsWithIntervalArithmetic";
22        private const string EvaluatedSolutionsParameterName = "EvaluatedSolutions";
23        private int initialTraining;
24        private int initialTest;
25
26        [ThreadStatic]
27        private static Dictionary<ISymbolicExpressionTreeNode, double> signalCache;
28        [ThreadStatic]
29        private static Dictionary<ISymbolicExpressionTreeNode, double> firstEMACache;
30        [ThreadStatic]
31        private static Dictionary<ISymbolicExpressionTreeNode, double> secondEMACache;
32        [ThreadStatic]
33        private static Dictionary<ISymbolicExpressionTreeNode, double> RSIPositiveCache;
34        [ThreadStatic]
35        private static Dictionary<ISymbolicExpressionTreeNode, double> RSINegativeCache;
36        [ThreadStatic]
37        private static Dictionary<ISymbolicExpressionTreeNode, double> RSICache;
38        [ThreadStatic]
39        private static Dictionary<ISymbolicExpressionTreeNode, double> RSIOutputCache;
40
41        #region private classes
42        //This class manipulate the instructions of the stack
43        private class InterpreterState
44        {
45            private double[] argumentStack;
46            private int argumentStackPointer;
47            private Instruction[] code;
48            private int pc;
49            public int ProgramCounter
50            {
51                get { return pc; }
52                set { pc = value; }
53            }
54            internal InterpreterState(Instruction[] code, int argumentStackSize)
55            {
56                this.code = code;
57                this.pc = 0;
58                if (argumentStackSize > 0)
59                {
60                    this.argumentStack = new double[argumentStackSize];
61                }
62                this.argumentStackPointer = 0;
63            }
64
65            internal void Reset()
66            {
67                this.pc = 0;
68                this.argumentStackPointer = 0;
69            }
70
71            internal Instruction NextInstruction()
72            {
73                return code[pc++];
74            }
75            private void Push(double val)
76            {
77                argumentStack[argumentStackPointer++] = val;
78            }
79            private double Pop()
80            {
81                return argumentStack[--argumentStackPointer];
82            }
83
84            internal void CreateStackFrame(double[] argValues)
85            {
86                // push in reverse order to make indexing easier
87                for (int i = argValues.Length - 1; i >= 0; i--)
88                {
89                    argumentStack[argumentStackPointer++] = argValues[i];
90                }
91                Push(argValues.Length);
92            }
93
94            internal void RemoveStackFrame()
95            {
96                int size = (int)Pop();
97                argumentStackPointer -= size;
98            }
99
100            internal double GetStackFrameValue(ushort index)
101            {
102                // layout of stack:
103                // [0]   <- argumentStackPointer
104                // [StackFrameSize = N + 1]
105                // [Arg0] <- argumentStackPointer - 2 - 0
106                // [Arg1] <- argumentStackPointer - 2 - 1
107                // [...]
108                // [ArgN] <- argumentStackPointer - 2 - N
109                // <Begin of stack frame>
110                return argumentStack[argumentStackPointer - index - 2];
111            }
112        }
113
114        //Operation codes
115        private class OpCodes
116        {
117            public const byte Add = 1;
118            public const byte Sub = 2;
119            public const byte Mul = 3;
120
121            public const byte GT = 5;
122            public const byte LT = 6;
123
124            public const byte AND = 7;
125            public const byte OR = 8;
126            public const byte NOT = 9;
127            public const byte BOOLEAN = 10;
128
129            public const byte Average = 11;
130            public const byte MACD = 12;
131
132            public const byte Variable = 13;
133            public const byte ConstantInt = 16;
134            public const byte BoolConstant = 15;
135            public const byte Max = 17;
136            public const byte Min = 18;
137            public const byte Lag = 19;
138            public const byte RSI = 20;
139        }
140        #endregion
141
142        #region IStatefulItem
143        public void InitializeState()
144        {
145            EvaluatedSolutions.Value = 0;
146        }
147
148        public void ClearState()
149        {
150        }
151        #endregion
152
153        private Dictionary<Type, byte> symbolToOpcode = new Dictionary<Type, byte>() {
154      { typeof(Addition), OpCodes.Add },
155      { typeof(Subtraction), OpCodes.Sub },
156      { typeof(Multiplication), OpCodes.Mul },
157      { typeof(BoolConstant), OpCodes.BoolConstant },
158      { typeof(ConstantInt), OpCodes.ConstantInt },
159      { typeof(GreaterThan), OpCodes.GT },
160      { typeof(LessThan), OpCodes.LT },
161      { typeof(And), OpCodes.AND },
162      { typeof(Or), OpCodes.OR },
163      { typeof(Not), OpCodes.NOT},
164      { typeof(AverageTrade), OpCodes.Average},
165      { typeof(MACD), OpCodes.MACD},
166      { typeof(RSI), OpCodes.RSI},
167      { typeof(Max), OpCodes.Max},
168      { typeof(Min), OpCodes.Min},
169      { typeof(Lag), OpCodes.Lag},
170      { typeof(HeuristicLab.Problems.DataAnalysis.Symbolic.Variable), OpCodes.Variable },
171    };
172
173        public override bool CanChangeName
174        {
175            get { return false; }
176        }
177        public override bool CanChangeDescription
178        {
179            get { return false; }
180        }
181
182        #region parameter properties
183        public IValueParameter<BoolValue> CheckExpressionsWithIntervalArithmeticParameter
184        {
185            get { return (IValueParameter<BoolValue>)Parameters[CheckExpressionsWithIntervalArithmeticParameterName]; }
186        }
187
188        public IValueParameter<IntValue> EvaluatedSolutionsParameter
189        {
190            get { return (IValueParameter<IntValue>)Parameters[EvaluatedSolutionsParameterName]; }
191        }
192        #endregion
193
194        #region properties
195        public BoolValue CheckExpressionsWithIntervalArithmetic
196        {
197            get { return CheckExpressionsWithIntervalArithmeticParameter.Value; }
198            set { CheckExpressionsWithIntervalArithmeticParameter.Value = value; }
199        }
200
201        public IntValue EvaluatedSolutions
202        {
203            get { return EvaluatedSolutionsParameter.Value; }
204            set { EvaluatedSolutionsParameter.Value = value; }
205        }
206        #endregion
207
208        private double Evaluate(Dataset dataset, ref int row, InterpreterState state)
209        {
210            Instruction currentInstr = state.NextInstruction();
211
212            switch (currentInstr.opCode)
213            {
214                case OpCodes.Add:
215                    {
216                        double s = Evaluate(dataset, ref row, state);
217                        for (int i = 1; i < currentInstr.nArguments; i++)
218                        {
219                            s += Evaluate(dataset, ref row, state);
220                        }
221                        return s;
222                    }
223                case OpCodes.Sub:
224                    {
225                        double s = Evaluate(dataset, ref row, state);
226                        for (int i = 1; i < currentInstr.nArguments; i++)
227                        {
228                            s -= Evaluate(dataset, ref row, state);
229                        }
230                        if (currentInstr.nArguments == 1) s = -s;
231                        return s;
232                    }
233                case OpCodes.Mul:
234                    {
235                        double p = Evaluate(dataset, ref row, state);
236                        for (int i = 1; i < currentInstr.nArguments; i++)
237                        {
238                            p *= Evaluate(dataset, ref row, state);
239                        }
240                        return p;
241                    }
242                case OpCodes.Average:
243                    {
244                        double sum = Evaluate(dataset, ref row, state);
245                        int integerValue = (int)Math.Floor(sum);
246                        if (integerValue > 100) integerValue = 100;
247                        if (row < integerValue)
248                        {
249                            string variableName = dataset.GetValue(row, 3);
250                            double inferiorValue = Convert.ToDouble(variableName);
251                            return inferiorValue / (row + 1);
252                        }
253                        else
254                        {
255                            string variableName = dataset.GetValue(row, 3);
256                            double meanValue1 = Convert.ToDouble(variableName);
257                            string variableName2 = dataset.GetValue((row - integerValue), 3);
258                            double meanValue2 = Convert.ToDouble(variableName2);
259                            return (meanValue1 - meanValue2) / integerValue;
260                        }
261                    }
262                case OpCodes.AND:
263                    {
264                        double result = Evaluate(dataset, ref row, state);
265                        double result2 = Evaluate(dataset, ref row, state);
266                        double total = result + result2;
267                        return total < 2.0 ? -1.0 : 1.0;
268                    }
269                case OpCodes.OR:
270                    {
271                        double result = Evaluate(dataset, ref row, state);
272                        double result2 = Evaluate(dataset, ref row, state);
273                        double total = result + result2;
274                        return total > -2.0 ? 1.0 : -1.0;
275                    }
276                case OpCodes.NOT:
277                    {
278                        return Evaluate(dataset, ref row, state) > -1.0 ? -1.0 : 1.0;
279                    }
280
281                case OpCodes.BOOLEAN:
282                    {
283                        var booleanTreeNode = currentInstr.dynamicNode as BoolConstantTreeNode;
284                        return booleanTreeNode.Value;
285                    }
286                case OpCodes.GT:
287                    {
288                        double x = Evaluate(dataset, ref row, state);
289                        double y = Evaluate(dataset, ref row, state);
290                        if (x > y) return 1.0;
291                        else return -1.0;
292                    }
293                case OpCodes.LT:
294                    {
295                        double x = Evaluate(dataset, ref row, state);
296                        double y = Evaluate(dataset, ref row, state);
297                        if (x < y) return 1.0;
298                        else return -1.0;
299                    }
300                case OpCodes.Variable:
301                    {
302                        if (row < 0 || row >= dataset.Rows)
303                            return double.NaN;
304                        var variableTreeNode = (VariableTreeNode)currentInstr.dynamicNode;
305                        return ((IList<double>)currentInstr.iArg0)[row] * variableTreeNode.Weight;
306                    }
307                case OpCodes.BoolConstant:
308                    {
309                        var boolConstTreeNode = currentInstr.dynamicNode as BoolConstantTreeNode;
310                        return boolConstTreeNode.Value;
311                    }
312                case OpCodes.ConstantInt:
313                    {
314                        var constIntTreeNode = currentInstr.dynamicNode as ConstantIntTreeNode;
315                        return constIntTreeNode.Value;
316                    }
317                case OpCodes.Max:
318                    {
319                        int n = (int)Evaluate(dataset, ref row, state);
320                        double max = Double.NegativeInfinity;
321                        int i = Math.Min(n, row);
322                        while (i >= 0)
323                        {
324                            int position = row - i;
325                            string variableName = dataset.GetValue(position, 2);
326                            double intValue = Convert.ToDouble(variableName);
327                            if (intValue > max) max = intValue;
328                            i--;
329                        }
330                        return max;
331                    }
332                case OpCodes.Min:
333                    {
334                        int n = (int)Evaluate(dataset, ref row, state);
335                        double min = Double.NegativeInfinity;
336                        int i = Math.Min(n, row);
337                        while (i >= 0)
338                        {
339                            int position = row - i;
340                            string variableName = dataset.GetValue(position, 2);
341                            double intValue = Convert.ToDouble(variableName);
342                            if (intValue < min) min = intValue;
343                            i--;
344                        }
345                        return min;
346                    }
347                case OpCodes.Lag:
348                    {
349                        int n = (int)Evaluate(dataset, ref row, state);
350                        if (n > row) return 0;
351                        int position = row - n;
352                        string variableName = dataset.GetValue(position, 2);
353                        double intValue = Convert.ToDouble(variableName);
354                        return intValue;
355                    }
356                case OpCodes.MACD:
357                    {
358                        //Taking the number of the days for each EMA
359                        double firstEMA = Evaluate(dataset, ref row, state);
360                        double secondEMA = Evaluate(dataset, ref row, state);
361                        double signal = Evaluate(dataset, ref row, state);
362                        //Initiation of the variables
363                        double firstElementEMA = -1000000;
364                        double secondElementEMA = -100000;
365                        double signalValue = -100000;
366                        double macd = 0;
367
368                        //Check if this MACD has previous values and retrieve them
369                        if (firstEMACache.ContainsKey(currentInstr.dynamicNode)) firstElementEMA = firstEMACache[currentInstr.dynamicNode];
370                        if (secondEMACache.ContainsKey(currentInstr.dynamicNode)) secondElementEMA = secondEMACache[currentInstr.dynamicNode];
371                        if (signalCache.ContainsKey(currentInstr.dynamicNode)) signalValue = signalCache[currentInstr.dynamicNode];
372
373               
374                        //Calculating the factor for each EMA
375                        double factor = 2.0 / (firstEMA + 1.0);
376                        double factor2 = 2.0 / (secondEMA + 1.0);
377                        double factor3 = 2.0 / (signal + 1.0);
378
379                            //Calculate the first value in the training for the two EMAs and the signal.
380                            if (row == initialTest)
381                            {
382                                double [] meanValues = dataset.GetDoubleValues("\"Close\"", Enumerable.Range(0, row+1)).ToArray();
383                                firstElementEMA = meanValues[0];
384                                secondElementEMA = meanValues[0];
385                                double max = (Math.Max(firstEMA, secondEMA)-1);//The first macd happens when the longest EMA has its first value. We need -1 because row begin in 0.
386                                for (int i = 1; i < meanValues.Length; i++)
387                                {
388                                    firstElementEMA = (meanValues[i] * factor) + ((1 - factor) * firstElementEMA);
389                                    secondElementEMA = (meanValues[i] * factor2) + ((1 - factor2) * secondElementEMA);
390                                    if (i == max) signalValue = firstElementEMA - secondElementEMA;//First signal equals to macd.
391                                    else if (i > max)//Calculation for the next signals
392                                    {
393                                        macd = firstElementEMA - secondElementEMA;
394                                        signalValue = macd * factor3 + (1 - factor3) * signalValue;
395                                    }
396                                }
397                            }
398                            else  //The rest of the rows are calculating with the standard EMA formula
399                            {
400                                //Retrieve the dataset values
401                                string variableName = dataset.GetValue(row, 2);
402                                double meanValue1 = Convert.ToDouble(variableName);
403
404                                //Calculating EMA
405                                firstElementEMA = meanValue1 * factor + (1 - factor) * firstElementEMA;
406                                secondElementEMA = meanValue1 * factor2 + (1 - factor2) * secondElementEMA;
407
408                                //Calculating signal
409                                macd = firstElementEMA - secondElementEMA;
410                                signalValue = macd * factor3 + (1 - factor3) * signalValue;
411                            }
412                           
413                            //Save the values for the next iteration
414                            firstEMACache[currentInstr.dynamicNode] = firstElementEMA;
415                            secondEMACache[currentInstr.dynamicNode] = secondElementEMA;
416                            signalCache[currentInstr.dynamicNode] = signalValue;
417                           
418                        return macd > signalValue ? 1.0 : -1.0;
419                    }
420                case OpCodes.RSI:
421                    {
422                        //Taking the number of the days for EMA
423                        double numberOfDays = Evaluate(dataset, ref row, state);
424                        double upThreshold = Evaluate(dataset, ref row, state);
425                        double downThreshold = Evaluate(dataset, ref row, state);
426
427                        double positiveEMA = 0;
428                        double negativeEMA = 0;
429                        double yesterdayRSI = double.NegativeInfinity;
430                        double todayRSI = double.NegativeInfinity;
431                        double outputRSI = double.NegativeInfinity;
432                        //Retrieve EMA values
433                        if (RSIPositiveCache.ContainsKey(currentInstr.dynamicNode)) positiveEMA = RSIPositiveCache[currentInstr.dynamicNode];
434                        if (RSINegativeCache.ContainsKey(currentInstr.dynamicNode)) negativeEMA = RSINegativeCache[currentInstr.dynamicNode];
435                        if (RSICache.ContainsKey(currentInstr.dynamicNode)) yesterdayRSI = RSICache[currentInstr.dynamicNode];
436                        if (RSIOutputCache.ContainsKey(currentInstr.dynamicNode)) outputRSI = RSIOutputCache[currentInstr.dynamicNode];
437
438       
439                            //Calculate the factor for the EMA
440                            double factor = 1.0 / numberOfDays;
441
442                            if (row == initialTest)
443                            {
444                                double[] closeValues = dataset.GetDoubleValues("\"Close\"", Enumerable.Range(0, (row + 1))).ToArray();
445                                outputRSI = -1.0;
446                                for (int i = 1; i <= row; i++)
447                                {
448                                    if (numberOfDays >= i)
449                                    {
450                                        if ((closeValues[i] - closeValues[i - 1]) > 0) positiveEMA = ((closeValues[i] - closeValues[i - 1]) + positiveEMA);
451                                        else negativeEMA = Math.Abs(closeValues[i] - closeValues[i - 1]) + negativeEMA;
452                                        if (numberOfDays == i)
453                                        {
454                                            positiveEMA = positiveEMA / numberOfDays;
455                                            negativeEMA = negativeEMA / numberOfDays;
456                                            yesterdayRSI = 100 - (100 / (1 + (positiveEMA / negativeEMA)));
457                                        }
458                                    }
459                                    else
460                                    {
461                                        if ((closeValues[i] - closeValues[i - 1]) > 0)
462                                        {
463                                            positiveEMA = (closeValues[i] - closeValues[i - 1]) * factor + (1 - factor) * positiveEMA;
464                                            negativeEMA = 0 * factor + (1 - factor) * negativeEMA;
465                                        }
466                                        else
467                                        {
468                                            positiveEMA = 0 * factor + (1 - factor) * positiveEMA;
469                                            negativeEMA = Math.Abs(closeValues[i] - closeValues[i - 1]) * factor + (1 - factor) * negativeEMA;
470                                        }
471
472                                        todayRSI = 100 - (100 / (1 + (positiveEMA / negativeEMA)));
473
474                                        if ((yesterdayRSI < downThreshold) && (todayRSI > downThreshold)) outputRSI = 1.0;
475                                        else if ((yesterdayRSI > upThreshold) && (todayRSI < upThreshold)) outputRSI = -1.0;
476                                        yesterdayRSI = todayRSI;
477                                    }
478                                }
479                            }
480                            else
481                            {
482                                string todayCloseString = dataset.GetValue(row, 2);
483                                string yesterdayCloseString = dataset.GetValue((row - 1), 2);
484                                double todayClose = Convert.ToDouble(todayCloseString);
485                                double yesterdayClose = Convert.ToDouble(yesterdayCloseString);
486
487                                //Calculating EMA
488                                if ((todayClose - yesterdayClose) > 0)
489                                {
490                                    positiveEMA = (todayClose - yesterdayClose) * factor + (1 - factor) * positiveEMA;
491                                    negativeEMA = 0 * factor + (1 - factor) * negativeEMA;
492                                }
493                                else
494                                {
495                                    positiveEMA = 0 * factor + (1 - factor) * positiveEMA;
496                                    negativeEMA = Math.Abs(todayClose - yesterdayClose) * factor + (1 - factor) * negativeEMA;
497                                }
498                                todayRSI = 100 - (100 / (1 + (positiveEMA / negativeEMA)));
499                                if ((yesterdayRSI < downThreshold) && (todayRSI > downThreshold)) outputRSI = 1.0;
500                                else if ((yesterdayRSI > upThreshold) && (todayRSI < upThreshold)) outputRSI = -1.0;
501                            }
502
503                            //Save positive and negative EMA for the next iteration
504                            RSIPositiveCache[currentInstr.dynamicNode] = positiveEMA;
505                            RSINegativeCache[currentInstr.dynamicNode] = negativeEMA;
506                            RSICache[currentInstr.dynamicNode] = todayRSI;
507                            RSIOutputCache[currentInstr.dynamicNode] = outputRSI;
508                           
509                       
510                        return outputRSI;
511                    }
512
513                default: throw new NotSupportedException();
514            }
515        }
516
517        private byte MapSymbolToOpCode(ISymbolicExpressionTreeNode treeNode)
518        {
519            if (symbolToOpcode.ContainsKey(treeNode.Symbol.GetType()))
520                return symbolToOpcode[treeNode.Symbol.GetType()];
521            else
522                throw new NotSupportedException("Symbol: " + treeNode.Symbol);
523        }
524
525        // skips a whole branch
526        private void SkipInstructions(InterpreterState state)
527        {
528            int i = 1;
529            while (i > 0)
530            {
531                i += state.NextInstruction().nArguments;
532                i--;
533            }
534        }
535        [StorableConstructor]
536        private Interpreter(bool deserializing) : base(deserializing) { }
537        private Interpreter(Interpreter original, Cloner cloner) : base(original, cloner) { }
538        public override IDeepCloneable Clone(Cloner cloner)
539        {
540            return new Interpreter(this, cloner);
541        }
542
543        public Interpreter()
544            : base("SymbolicDataAnalysisExpressionTreeInterpreter", "Interpreter for symbolic expression trees including automatically defined functions.")
545        {
546            Parameters.Add(new ValueParameter<BoolValue>(CheckExpressionsWithIntervalArithmeticParameterName, "Switch that determines if the interpreter checks the validity of expressions with interval arithmetic before evaluating the expression.", new BoolValue(false)));
547            Parameters.Add(new ValueParameter<IntValue>(EvaluatedSolutionsParameterName, "A counter for the total number of solutions the interpreter has evaluated", new IntValue(0)));
548        }
549
550        [StorableHook(HookType.AfterDeserialization)]
551        private void AfterDeserialization()
552        {
553            if (!Parameters.ContainsKey(EvaluatedSolutionsParameterName))
554                Parameters.Add(new ValueParameter<IntValue>(EvaluatedSolutionsParameterName, "A counter for the total number of solutions the interpreter has evaluated", new IntValue(0)));
555        }
556        public void setInitialTraining(int initialTraining)
557        {
558            this.initialTraining = initialTraining;
559        }
560
561        public void setInitialTest(int initialTest)
562        {
563            this.initialTest = initialTest;
564        }
565
566        public void clearVariables()
567        {
568            if (signalCache != null) signalCache.Clear();
569            if (firstEMACache != null) firstEMACache.Clear();
570            if (secondEMACache != null) secondEMACache.Clear();
571            if (RSIPositiveCache != null) RSIPositiveCache.Clear();
572            if (RSINegativeCache != null) RSINegativeCache.Clear();
573            if (RSICache != null) RSICache.Clear();
574            if (RSIOutputCache != null) RSIOutputCache.Clear();
575        }
576
577        //Take the symbolic expression values of the tree
578        public IEnumerable<double> GetSymbolicExpressionTreeValues(ISymbolicExpressionTree tree, Dataset dataset, IEnumerable<int> rows)
579        {
580            if (CheckExpressionsWithIntervalArithmetic.Value)
581                throw new NotSupportedException("Interval arithmetic is not yet supported in the symbolic data analysis interpreter.");
582            EvaluatedSolutions.Value++; // increment the evaluated solutions counter
583            var compiler = new SymbolicExpressionTreeCompiler();
584            Instruction[] code = compiler.Compile(tree, MapSymbolToOpCode);//Take the type of symbol
585            int necessaryArgStackSize = 0;
586            for (int i = 0; i < code.Length; i++)
587            {
588                Instruction instr = code[i];
589                if (instr.opCode == OpCodes.Variable)
590                {
591                    var variableTreeNode = instr.dynamicNode as VariableTreeNode;
592                    instr.iArg0 = dataset.GetReadOnlyDoubleValues(variableTreeNode.VariableName);
593                    code[i] = instr;
594                }
595            }
596
597            if (signalCache == null) signalCache = new Dictionary<ISymbolicExpressionTreeNode, double>();
598            if (firstEMACache == null) firstEMACache = new Dictionary<ISymbolicExpressionTreeNode, double>();
599            if (secondEMACache == null) secondEMACache = new Dictionary<ISymbolicExpressionTreeNode, double>();
600            if (RSIPositiveCache == null) RSIPositiveCache = new Dictionary<ISymbolicExpressionTreeNode, double>();
601            if (RSINegativeCache == null) RSINegativeCache = new Dictionary<ISymbolicExpressionTreeNode, double>();
602            if (RSICache == null) RSICache = new Dictionary<ISymbolicExpressionTreeNode, double>();
603            if (RSIOutputCache == null) RSIOutputCache = new Dictionary<ISymbolicExpressionTreeNode, double>();
604
605            var state = new InterpreterState(code, necessaryArgStackSize);
606            //Evaluate each row of the datase
607            foreach (var rowEnum in rows)
608            {
609                int row = rowEnum;
610                state.Reset();
611                if (row < initialTest) yield return -1;
612                else yield return Evaluate(dataset, ref row, state);
613            }
614        }
615    }
616
617}
618
Note: See TracBrowser for help on using the repository browser.