/// <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 TransformerTest2()
        {
            string exampleCode = @"

global variables{
	define reEntryExRatePercent as 0.05;
	define noOfLongPosition as 3;
	define noOfShortPosition as 3;
}

define Portfolio{
	set BaseCurrency to 'EUR';
	LongPositions: Position<Long>[3];
}

rule reallocation executes on every Friday{
for all position in Portfolio.LongPositions{
	if position.Currency is not in Top3Currencies:
		Close position;
}

for all currency in Top3Currencies{
	if currency is not in Currency of Portfolio.LongPositions:
		Open Portfolio.LongPositions with currency;
}
}";


            StrategyLanguageParser fxParser = new StrategyLanguageParser();
            TradingStrategyAstNode strategyAst = fxParser.Parse(exampleCode);
            AstTreeToModelTransformer transformer = new AstTreeToModelTransformer();
            TradingStrategy strategy = transformer.Transform(strategyAst);
            //Assert.IsTrue(strategy.TradingRules.Count == 1);

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

            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"));
        }
        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"));
        }