/// <summary>
        /// Start the process of analysing the strategy from source code
        /// </summary>
        /// <param name="startDate">start date of back-testing</param>
        /// <param name="endDate">end date of back-testing</param>
        /// <param name="monthsInTerm">length of forward contract in months</param>
        /// <param name="fxCode">source code for a strategy</param>
        /// <returns>Profit Index over time</returns>
        public IEnumerable<DateIndex> Execute(DateTime startDate, DateTime endDate, int monthsInTerm, string fxCode)
        {
            // these objects are created for each execution
            // it is to support multi-threading
            var fxParser = new StrategyLanguageParser();
            var modelTransformer = new ASTToModelTransform.AstTreeToModelTransformer();
            var calculationEngine = new ProfitCalculationEngine(_currencyDataSource);
            var strategyRunTime = new StrategyInterpreter(_currencyDataSource);

            // parse the source code into abstract syntax tree
            var strategyAstNode = fxParser.Parse(fxCode);

            // transform the abstract syntax tree to the model
            var strategyModel = modelTransformer.Transform(strategyAstNode);

            // execute the model
            strategyRunTime.Clear();
            strategyRunTime.Execute(strategyModel, startDate, endDate);
            
            // calculate profit based on the position records
            calculationEngine.Evaluate( 
                strategyRunTime.PositionSetTable.Values.SelectMany(v => v.Positions).ToList(),
                startDate,endDate,
                new PeriodicTimeDefinition(monthsInTerm, PeriodicType.Month));

            return calculationEngine.IndexOverTime.Select(
                i => new DateIndex(){
                    Date = i.Time,
                    Index = i.Value
                });
        }
        public void ExecutionTimeTest()
        {
            TradingStrategy tradingStratgy = ConstructTradingStrategy();

            FXEntities.FXEntities fxEntities = new FXEntities.FXEntities();
            CurrencyDataSource currencyDataSource = new CurrencyDataSource(fxEntities);
            currencyDataSource.PreLoad();
            StrategyInterpreter target = new StrategyInterpreter(fxEntities, currencyDataSource);
            DateTime startExecutionTime;
            DateTime endExecutionTime;
            DateTime startDate = new DateTime(2000, 1, 1);
            List<List<double>> results = new List<List<double>>();
            StringBuilder output = new StringBuilder();
            for (int j = 0; j < 10; j++)
            {
                results.Add(new List<double>());
                output.AppendLine("Run no.: " + j);
                for (int i = 0; i < 11; i++)
                {
                    startExecutionTime = DateTime.Now;
                    target.Execute(tradingStratgy, startDate, startDate.AddYears(i + 1));
                    endExecutionTime = DateTime.Now;
                    results[j].Add((endExecutionTime - startExecutionTime).TotalMilliseconds);
                    output.AppendLine(String.Format("Execution time: {0}ms, Number of positionRecord: {1} ",
                        (endExecutionTime - startExecutionTime).TotalMilliseconds,
                        target.PositionSetTable.Sum(p => p.Value.Positions.SelectMany(pos => pos.PositionRecords).Count()
                        )
                        ));
                    target.Clear();

                    //results.Add(endExecutionTime - startExecutionTime);
                }
                output.AppendLine();
            }

            output.AppendLine("Average: ");
            for (int i = 0; i < 10; i++)
            {
                output.AppendLine( (i+1) + " Year: \t" + results.Select(r => r.ElementAt(i)).Average());
            }


            using (StreamWriter writer = new StreamWriter(@"D:\Documents\Study Materials\Master Thesis\Main Thesis\executionTime.txt"))
            {
                
                //for (int i = 1; i <= 10; i++)
                //{
                //    output += String.Format(results[i - 1].Milliseconds + " ms \n");
                //}

                writer.WriteLine(output);
            }

            
        }
        public void ExecuteTest()
        {
            StrategyInterpreter target = new StrategyInterpreter();
            TradingStrategy tradingStrategy = ConstructTradingStrategy();
                 
            DateTime startDate = new DateTime(2000,1,7);
            DateTime endDate = new DateTime(2000,2,25);
            target.Execute(tradingStrategy, startDate, endDate);

            PositionSetRuntime longPositions = target.PositionSetTable["LongPositions"];
            Assert.IsTrue(longPositions.Positions.Any( p => p.CurrencyInPosition.Name == "USD"));
            Assert.IsTrue(longPositions.Positions.Any( p => p.CurrencyInPosition.Name == "GBP"));
            Assert.IsTrue(longPositions.Positions.Any( p => p.CurrencyInPosition.Name == "NOK"));

            target.Clear();

            target.Execute(tradingStrategy, startDate, new DateTime(2000,3,10));
            longPositions = target.PositionSetTable["LongPositions"];
            Assert.IsTrue(longPositions.Positions.Any(p => p.CurrencyInPosition.Name == "USD"));
            Assert.IsTrue(longPositions.Positions.Any(p => p.CurrencyInPosition.Name == "GBP"));
            Assert.IsTrue(longPositions.Positions.Any(p => p.CurrencyInPosition.Name == "NZD"));

            target.Clear();

            target.Execute(tradingStrategy, startDate, new DateTime(2000, 4, 14));
            longPositions = target.PositionSetTable["LongPositions"];
            Assert.IsTrue(longPositions.Positions.Any(p => p.CurrencyInPosition.Name == "USD"));
            Assert.IsTrue(longPositions.Positions.Any(p => p.CurrencyInPosition.Name == "NOK"));
            Assert.IsTrue(longPositions.Positions.Any(p => p.CurrencyInPosition.Name == "NZD"));

        }
        public void TransformerTest()
        {
            StrategyLanguageParser fxParser = new StrategyLanguageParser();
            TradingStrategyAstNode strategyAst = fxParser.Parse(ExampleCode);
            AstTreeToModelTransformer transformer = new AstTreeToModelTransformer();
            TradingStrategy strategy = transformer.Transform(strategyAst);
            Assert.IsTrue(strategy.TradingRules.Count > 0);

            StrategyInterpreter strategyRunTime = new StrategyInterpreter();
            DateTime startDate = new DateTime(2000, 1, 7);
            DateTime endDate = new DateTime(2000, 2, 25);

            Assert.IsTrue(strategy.ConstantVariableDefinitions.Count == 3);

            strategyRunTime.Execute(strategy, startDate, endDate);

            PositionSetRuntime longPositions = strategyRunTime.PositionSetTable["LongPositions"];
            Assert.IsTrue(longPositions.Positions.Any(p => p.CurrencyInPosition.Name == "USD"));
            Assert.IsTrue(longPositions.Positions.Any(p => p.CurrencyInPosition.Name == "GBP"));
            Assert.IsTrue(longPositions.Positions.Any(p => p.CurrencyInPosition.Name == "NOK"));

            strategyRunTime.Clear();

            strategyRunTime.Execute(strategy, startDate, new DateTime(2000, 3, 10));
            longPositions = strategyRunTime.PositionSetTable["LongPositions"];
            Assert.IsTrue(longPositions.Positions.Any(p => p.CurrencyInPosition.Name == "USD"));
            Assert.IsTrue(longPositions.Positions.Any(p => p.CurrencyInPosition.Name == "GBP"));
            Assert.IsTrue(longPositions.Positions.Any(p => p.CurrencyInPosition.Name == "NZD"));

            strategyRunTime.Clear();

            strategyRunTime.Execute(strategy, startDate, new DateTime(2000, 4, 14));
            longPositions = strategyRunTime.PositionSetTable["LongPositions"];
            Assert.IsTrue(longPositions.Positions.Any(p => p.CurrencyInPosition.Name == "USD"));
            Assert.IsTrue(longPositions.Positions.Any(p => p.CurrencyInPosition.Name == "NOK"));
            Assert.IsTrue(longPositions.Positions.Any(p => p.CurrencyInPosition.Name == "NZD"));
        }