Free cookie consent management tool by TermsFeed Policy Generator

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

Last change on this file since 9454 was 9386, checked in by sluengo, 11 years ago
File size: 29.4 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 Constant = 14;
134            public const byte ConstantInt = 16;
135            public const byte BoolConstant = 15;
136            public const byte Max = 17;
137            public const byte Min = 18;
138            public const byte Lag = 19;
139            public const byte RSI = 20;
140        }
141        #endregion
142
143        #region IStatefulItem
144        public void InitializeState()
145        {
146            EvaluatedSolutions.Value = 0;
147        }
148
149        public void ClearState()
150        {
151        }
152        #endregion
153
154        private Dictionary<Type, byte> symbolToOpcode = new Dictionary<Type, byte>() {
155      { typeof(Addition), OpCodes.Add },
156      { typeof(Subtraction), OpCodes.Sub },
157      { typeof(Multiplication), OpCodes.Mul },
158      { typeof(Constant), OpCodes.Constant },
159      { typeof(BoolConstant), OpCodes.BoolConstant },
160      { typeof(ConstantInt), OpCodes.ConstantInt },
161      { typeof(GreaterThan), OpCodes.GT },
162      { typeof(LessThan), OpCodes.LT },
163      { typeof(And), OpCodes.AND },
164      { typeof(Or), OpCodes.OR },
165      { typeof(Not), OpCodes.NOT},
166      { typeof(AverageTrade), OpCodes.Average},
167      { typeof(MACD), OpCodes.MACD},
168      { typeof(RSI), OpCodes.RSI},
169      { typeof(Max), OpCodes.Max},
170      { typeof(Min), OpCodes.Min},
171      { typeof(Lag), OpCodes.Lag},
172      { typeof(HeuristicLab.Problems.DataAnalysis.Symbolic.Variable), OpCodes.Variable },
173    };
174
175        public override bool CanChangeName
176        {
177            get { return false; }
178        }
179        public override bool CanChangeDescription
180        {
181            get { return false; }
182        }
183
184        #region parameter properties
185        public IValueParameter<BoolValue> CheckExpressionsWithIntervalArithmeticParameter
186        {
187            get { return (IValueParameter<BoolValue>)Parameters[CheckExpressionsWithIntervalArithmeticParameterName]; }
188        }
189
190        public IValueParameter<IntValue> EvaluatedSolutionsParameter
191        {
192            get { return (IValueParameter<IntValue>)Parameters[EvaluatedSolutionsParameterName]; }
193        }
194        #endregion
195
196        #region properties
197        public BoolValue CheckExpressionsWithIntervalArithmetic
198        {
199            get { return CheckExpressionsWithIntervalArithmeticParameter.Value; }
200            set { CheckExpressionsWithIntervalArithmeticParameter.Value = value; }
201        }
202
203        public IntValue EvaluatedSolutions
204        {
205            get { return EvaluatedSolutionsParameter.Value; }
206            set { EvaluatedSolutionsParameter.Value = value; }
207        }
208        #endregion
209
210        private double Evaluate(Dataset dataset, ref int row, InterpreterState state)
211        {
212            Instruction currentInstr = state.NextInstruction();
213
214            switch (currentInstr.opCode)
215            {
216                case OpCodes.Add:
217                    {
218                        double s = Evaluate(dataset, ref row, state);
219                        for (int i = 1; i < currentInstr.nArguments; i++)
220                        {
221                            s += Evaluate(dataset, ref row, state);
222                        }
223                        return s;
224                    }
225                case OpCodes.Sub:
226                    {
227                        double s = Evaluate(dataset, ref row, state);
228                        for (int i = 1; i < currentInstr.nArguments; i++)
229                        {
230                            s -= Evaluate(dataset, ref row, state);
231                        }
232                        if (currentInstr.nArguments == 1) s = -s;
233                        return s;
234                    }
235                case OpCodes.Mul:
236                    {
237                        double p = Evaluate(dataset, ref row, state);
238                        for (int i = 1; i < currentInstr.nArguments; i++)
239                        {
240                            p *= Evaluate(dataset, ref row, state);
241                        }
242                        return p;
243                    }
244                case OpCodes.Average:
245                    {
246                        double sum = Evaluate(dataset, ref row, state);
247                        int integerValue = (int)Math.Floor(sum);
248                        if (integerValue > 100) integerValue = 100;
249                        if (row < integerValue)
250                        {
251                            string variableName = dataset.GetValue(row, 3);
252                            double inferiorValue = Convert.ToDouble(variableName);
253                            return inferiorValue / (row + 1);
254                        }
255                        else
256                        {
257                            string variableName = dataset.GetValue(row, 3);
258                            double meanValue1 = Convert.ToDouble(variableName);
259                            string variableName2 = dataset.GetValue((row - integerValue), 3);
260                            double meanValue2 = Convert.ToDouble(variableName2);
261                            return (meanValue1 - meanValue2) / integerValue;
262                        }
263                    }
264                case OpCodes.AND:
265                    {
266                        double result = Evaluate(dataset, ref row, state);
267                        double result2 = Evaluate(dataset, ref row, state);
268                        double total = result + result2;
269                        return total < 2.0 ? -1.0 : 1.0;
270                    }
271                case OpCodes.OR:
272                    {
273                        double result = Evaluate(dataset, ref row, state);
274                        double result2 = Evaluate(dataset, ref row, state);
275                        double total = result + result2;
276                        return total > -2.0 ? 1.0 : -1.0;
277                    }
278                case OpCodes.NOT:
279                    {
280                        return Evaluate(dataset, ref row, state) > -1.0 ? -1.0 : 1.0;
281                    }
282
283                case OpCodes.BOOLEAN:
284                    {
285                        var booleanTreeNode = currentInstr.dynamicNode as BoolConstantTreeNode;
286                        return booleanTreeNode.Value;
287                    }
288                case OpCodes.GT:
289                    {
290                        double x = Evaluate(dataset, ref row, state);
291                        double y = Evaluate(dataset, ref row, state);
292                        if (x > y) return 1.0;
293                        else return -1.0;
294                    }
295                case OpCodes.LT:
296                    {
297                        double x = Evaluate(dataset, ref row, state);
298                        double y = Evaluate(dataset, ref row, state);
299                        if (x < y) return 1.0;
300                        else return -1.0;
301                    }
302                case OpCodes.Variable:
303                    {
304                        if (row < 0 || row >= dataset.Rows)
305                            return double.NaN;
306                        var variableTreeNode = (VariableTreeNode)currentInstr.dynamicNode;
307                        return ((IList<double>)currentInstr.iArg0)[row] * variableTreeNode.Weight;
308                    }
309                case OpCodes.Constant:
310                    {
311                        var constTreeNode = currentInstr.dynamicNode as ConstantTreeNode;
312                        return constTreeNode.Value;
313                    }
314                case OpCodes.BoolConstant:
315                    {
316                        var boolConstTreeNode = currentInstr.dynamicNode as BoolConstantTreeNode;
317                        return boolConstTreeNode.Value;
318                    }
319                case OpCodes.ConstantInt:
320                    {
321                        var constIntTreeNode = currentInstr.dynamicNode as ConstantIntTreeNode;
322                        return constIntTreeNode.Value;
323                    }
324                case OpCodes.Max:
325                    {
326                        int n = (int)Evaluate(dataset, ref row, state);
327                        double max = Double.NegativeInfinity;
328                        int i = Math.Min(n, row);
329                        while (i >= 0)
330                        {
331                            int position = row - i;
332                            string variableName = dataset.GetValue(position, 2);
333                            double intValue = Convert.ToDouble(variableName);
334                            if (intValue > max) max = intValue;
335                            i--;
336                        }
337                        return max;
338                    }
339                case OpCodes.Min:
340                    {
341                        int n = (int)Evaluate(dataset, ref row, state);
342                        double min = Double.NegativeInfinity;
343                        int i = Math.Min(n, row);
344                        while (i >= 0)
345                        {
346                            int position = row - i;
347                            string variableName = dataset.GetValue(position, 2);
348                            double intValue = Convert.ToDouble(variableName);
349                            if (intValue < min) min = intValue;
350                            i--;
351                        }
352                        return min;
353                    }
354                case OpCodes.Lag:
355                    {
356                        int n = (int)Evaluate(dataset, ref row, state);
357                        if (n > row) return 0;
358                        int position = row - n;
359                        string variableName = dataset.GetValue(position, 2);
360                        double intValue = Convert.ToDouble(variableName);
361                        return intValue;
362                    }
363                case OpCodes.MACD:
364                    {
365                        //Taking the number of the days for each EMA
366                        double firstEMA = Evaluate(dataset, ref row, state);
367                        double secondEMA = Evaluate(dataset, ref row, state);
368                        double signal = Evaluate(dataset, ref row, state);
369                        //Initiation of the variables
370                        double firstElementEMA = -1000000;
371                        double secondElementEMA = -100000;
372                        double signalValue = -100000;
373                        double macd = 0;
374
375                        //Check if this MACD has previous values and retrieve them
376                        if (firstEMACache.ContainsKey(currentInstr.dynamicNode)) firstElementEMA = firstEMACache[currentInstr.dynamicNode];
377                        if (secondEMACache.ContainsKey(currentInstr.dynamicNode)) secondElementEMA = secondEMACache[currentInstr.dynamicNode];
378                        if (signalCache.ContainsKey(currentInstr.dynamicNode)) signalValue = signalCache[currentInstr.dynamicNode];
379
380               
381                        //Calculating the factor for each EMA
382                        double factor = 2.0 / (firstEMA + 1.0);
383                        double factor2 = 2.0 / (secondEMA + 1.0);
384                        double factor3 = 2.0 / (signal + 1.0);
385
386                            //Calculate the first value in the training for the two EMAs and the signal.
387                            if (row == initialTest)
388                            {
389                                double [] meanValues = dataset.GetDoubleValues("\"Close\"", Enumerable.Range(0, row+1)).ToArray();
390                                firstElementEMA = meanValues[0];
391                                secondElementEMA = meanValues[0];
392                                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.
393                                for (int i = 1; i < meanValues.Length; i++)
394                                {
395                                    firstElementEMA = (meanValues[i] * factor) + ((1 - factor) * firstElementEMA);
396                                    secondElementEMA = (meanValues[i] * factor2) + ((1 - factor2) * secondElementEMA);
397                                    if (i == max) signalValue = firstElementEMA - secondElementEMA;//First signal equals to macd.
398                                    else if (i > max)//Calculation for the next signals
399                                    {
400                                        macd = firstElementEMA - secondElementEMA;
401                                        signalValue = macd * factor3 + (1 - factor3) * signalValue;
402                                    }
403                                }
404                            }
405                            else  //The rest of the rows are calculating with the standard EMA formula
406                            {
407                                //Retrieve the dataset values
408                                string variableName = dataset.GetValue(row, 2);
409                                double meanValue1 = Convert.ToDouble(variableName);
410
411                                //Calculating EMA
412                                firstElementEMA = meanValue1 * factor + (1 - factor) * firstElementEMA;
413                                secondElementEMA = meanValue1 * factor2 + (1 - factor2) * secondElementEMA;
414
415                                //Calculating signal
416                                macd = firstElementEMA - secondElementEMA;
417                                signalValue = macd * factor3 + (1 - factor3) * signalValue;
418                            }
419                           
420                            //Save the values for the next iteration
421                            firstEMACache[currentInstr.dynamicNode] = firstElementEMA;
422                            secondEMACache[currentInstr.dynamicNode] = secondElementEMA;
423                            signalCache[currentInstr.dynamicNode] = signalValue;
424                           
425                        return macd > signalValue ? 1.0 : -1.0;
426                    }
427                case OpCodes.RSI:
428                    {
429                        //Taking the number of the days for EMA
430                        double numberOfDays = Evaluate(dataset, ref row, state);
431
432                        double positiveEMA = 0;
433                        double negativeEMA = 0;
434                        double yesterdayRSI = double.NegativeInfinity;
435                        double todayRSI = double.NegativeInfinity;
436                        double outputRSI = double.NegativeInfinity;
437                        //Retrieve EMA values
438                        if (RSIPositiveCache.ContainsKey(currentInstr.dynamicNode)) positiveEMA = RSIPositiveCache[currentInstr.dynamicNode];
439                        if (RSINegativeCache.ContainsKey(currentInstr.dynamicNode)) negativeEMA = RSINegativeCache[currentInstr.dynamicNode];
440                        if (RSICache.ContainsKey(currentInstr.dynamicNode)) yesterdayRSI = RSICache[currentInstr.dynamicNode];
441                        if (RSIOutputCache.ContainsKey(currentInstr.dynamicNode)) outputRSI = RSIOutputCache[currentInstr.dynamicNode];
442
443       
444                            //Calculate the factor for the EMA
445                            double factor = 1.0 / numberOfDays;
446
447                            if (row == initialTest)
448                            {
449                                double[] closeValues = dataset.GetDoubleValues("\"Close\"", Enumerable.Range(0, (row + 1))).ToArray();
450                                outputRSI = -1.0;
451                                for (int i = 1; i <= row; i++)
452                                {
453                                    if (numberOfDays >= i)
454                                    {
455                                        if ((closeValues[i] - closeValues[i - 1]) > 0) positiveEMA = ((closeValues[i] - closeValues[i - 1]) + positiveEMA);
456                                        else negativeEMA = Math.Abs(closeValues[i] - closeValues[i - 1]) + negativeEMA;
457                                        if (numberOfDays == i)
458                                        {
459                                            positiveEMA = positiveEMA / numberOfDays;
460                                            negativeEMA = negativeEMA / numberOfDays;
461                                            yesterdayRSI = 100 - (100 / (1 + (positiveEMA / negativeEMA)));
462                                        }
463                                    }
464                                    else
465                                    {
466                                        if ((closeValues[i] - closeValues[i - 1]) > 0)
467                                        {
468                                            positiveEMA = (closeValues[i] - closeValues[i - 1]) * factor + (1 - factor) * positiveEMA;
469                                            negativeEMA = 0 * factor + (1 - factor) * negativeEMA;
470                                        }
471                                        else
472                                        {
473                                            positiveEMA = 0 * factor + (1 - factor) * positiveEMA;
474                                            negativeEMA = Math.Abs(closeValues[i] - closeValues[i - 1]) * factor + (1 - factor) * negativeEMA;
475                                        }
476
477                                        todayRSI = 100 - (100 / (1 + (positiveEMA / negativeEMA)));
478
479                                        if ((yesterdayRSI < 30) && (todayRSI > 30)) outputRSI = 1.0;
480                                        else if ((yesterdayRSI > 70) && (todayRSI < 70)) outputRSI = -1.0;
481                                        yesterdayRSI = todayRSI;
482                                    }
483                                }
484                            }
485                            else
486                            {
487                                string todayCloseString = dataset.GetValue(row, 2);
488                                string yesterdayCloseString = dataset.GetValue((row - 1), 2);
489                                double todayClose = Convert.ToDouble(todayCloseString);
490                                double yesterdayClose = Convert.ToDouble(yesterdayCloseString);
491
492                                //Calculating EMA
493                                if ((todayClose - yesterdayClose) > 0)
494                                {
495                                    positiveEMA = (todayClose - yesterdayClose) * factor + (1 - factor) * positiveEMA;
496                                    negativeEMA = 0 * factor + (1 - factor) * negativeEMA;
497                                }
498                                else
499                                {
500                                    positiveEMA = 0 * factor + (1 - factor) * positiveEMA;
501                                    negativeEMA = Math.Abs(todayClose - yesterdayClose) * factor + (1 - factor) * negativeEMA;
502                                }
503                                todayRSI = 100 - (100 / (1 + (positiveEMA / negativeEMA)));
504                                if ((yesterdayRSI < 30) && (todayRSI > 30)) outputRSI = 1.0;
505                                else if ((yesterdayRSI > 70) && (todayRSI < 70)) outputRSI = -1.0;
506                            }
507
508                            //Save positive and negative EMA for the next iteration
509                            RSIPositiveCache[currentInstr.dynamicNode] = positiveEMA;
510                            RSINegativeCache[currentInstr.dynamicNode] = negativeEMA;
511                            RSICache[currentInstr.dynamicNode] = todayRSI;
512                            RSIOutputCache[currentInstr.dynamicNode] = outputRSI;
513                           
514                       
515                        return outputRSI;
516                    }
517
518                default: throw new NotSupportedException();
519            }
520        }
521
522        private byte MapSymbolToOpCode(ISymbolicExpressionTreeNode treeNode)
523        {
524            if (symbolToOpcode.ContainsKey(treeNode.Symbol.GetType()))
525                return symbolToOpcode[treeNode.Symbol.GetType()];
526            else
527                throw new NotSupportedException("Symbol: " + treeNode.Symbol);
528        }
529
530        // skips a whole branch
531        private void SkipInstructions(InterpreterState state)
532        {
533            int i = 1;
534            while (i > 0)
535            {
536                i += state.NextInstruction().nArguments;
537                i--;
538            }
539        }
540        [StorableConstructor]
541        private Interpreter(bool deserializing) : base(deserializing) { }
542        private Interpreter(Interpreter original, Cloner cloner) : base(original, cloner) { }
543        public override IDeepCloneable Clone(Cloner cloner)
544        {
545            return new Interpreter(this, cloner);
546        }
547
548        public Interpreter()
549            : base("SymbolicDataAnalysisExpressionTreeInterpreter", "Interpreter for symbolic expression trees including automatically defined functions.")
550        {
551            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)));
552            Parameters.Add(new ValueParameter<IntValue>(EvaluatedSolutionsParameterName, "A counter for the total number of solutions the interpreter has evaluated", new IntValue(0)));
553        }
554
555        [StorableHook(HookType.AfterDeserialization)]
556        private void AfterDeserialization()
557        {
558            if (!Parameters.ContainsKey(EvaluatedSolutionsParameterName))
559                Parameters.Add(new ValueParameter<IntValue>(EvaluatedSolutionsParameterName, "A counter for the total number of solutions the interpreter has evaluated", new IntValue(0)));
560        }
561        public void setInitialTraining(int initialTraining)
562        {
563            this.initialTraining = initialTraining;
564        }
565
566        public void setInitialTest(int initialTest)
567        {
568            this.initialTest = initialTest;
569        }
570
571        public void clearVariables()
572        {
573            if (signalCache != null) signalCache.Clear();
574            if (firstEMACache != null) firstEMACache.Clear();
575            if (secondEMACache != null) secondEMACache.Clear();
576            if (RSIPositiveCache != null) RSIPositiveCache.Clear();
577            if (RSINegativeCache != null) RSINegativeCache.Clear();
578            if (RSICache != null) RSICache.Clear();
579            if (RSIOutputCache != null) RSIOutputCache.Clear();
580        }
581
582        //Take the symbolic expression values of the tree
583        public IEnumerable<double> GetSymbolicExpressionTreeValues(ISymbolicExpressionTree tree, Dataset dataset, IEnumerable<int> rows)
584        {
585            if (CheckExpressionsWithIntervalArithmetic.Value)
586                throw new NotSupportedException("Interval arithmetic is not yet supported in the symbolic data analysis interpreter.");
587            EvaluatedSolutions.Value++; // increment the evaluated solutions counter
588            var compiler = new SymbolicExpressionTreeCompiler();
589            Instruction[] code = compiler.Compile(tree, MapSymbolToOpCode);//Take the type of symbol
590            int necessaryArgStackSize = 0;
591            for (int i = 0; i < code.Length; i++)
592            {
593                Instruction instr = code[i];
594                if (instr.opCode == OpCodes.Variable)
595                {
596                    var variableTreeNode = instr.dynamicNode as VariableTreeNode;
597                    instr.iArg0 = dataset.GetReadOnlyDoubleValues(variableTreeNode.VariableName);
598                    code[i] = instr;
599                }
600            }
601
602            if (signalCache == null) signalCache = new Dictionary<ISymbolicExpressionTreeNode, double>();
603            if (firstEMACache == null) firstEMACache = new Dictionary<ISymbolicExpressionTreeNode, double>();
604            if (secondEMACache == null) secondEMACache = new Dictionary<ISymbolicExpressionTreeNode, double>();
605            if (RSIPositiveCache == null) RSIPositiveCache = new Dictionary<ISymbolicExpressionTreeNode, double>();
606            if (RSINegativeCache == null) RSINegativeCache = new Dictionary<ISymbolicExpressionTreeNode, double>();
607            if (RSICache == null) RSICache = new Dictionary<ISymbolicExpressionTreeNode, double>();
608            if (RSIOutputCache == null) RSIOutputCache = new Dictionary<ISymbolicExpressionTreeNode, double>();
609
610
611            var state = new InterpreterState(code, necessaryArgStackSize);
612            //Evaluate each row of the datase
613            foreach (var rowEnum in rows)
614            {
615                int row = rowEnum;
616                state.Reset();
617                if (row < initialTest) yield return -1;
618                else yield return Evaluate(dataset, ref row, state);
619            }
620        }
621    }
622
623}
624
Note: See TracBrowser for help on using the repository browser.