static List <DailyData> DoBacktestBasic(IList <List <DailyData> > p_allQuotes, string p_bullishTicker, string p_bearishTicker, string p_strategyName, string p_rebalancingFrequency, ref string p_noteToUserCheckData, ref string p_htmlNoteFromStrategy)
        {
            var bullishQoutes = p_allQuotes[0];    // URE, XIV, FAS, ZIV
            var bearishQoutes = p_allQuotes[1];    // SRS, VXX, FAZ, VXZ

            List <DailyData> pv = StrategiesCommon.DetermineBacktestPeriodCheckDataCorrectness(bullishQoutes, bearishQoutes, ref p_noteToUserCheckData);


            if (String.Equals(p_strategyName, "LETFDiscrepancy2", StringComparison.InvariantCultureIgnoreCase))
            {
                DoBacktestInTheTimeInterval_RebalanceToNeutral(bullishQoutes, bearishQoutes, p_rebalancingFrequency, pv, ref p_htmlNoteFromStrategy);
            }
            else if (String.Equals(p_strategyName, "LETFDiscrepancy3", StringComparison.InvariantCultureIgnoreCase))
            {
                DoBacktestInTheTimeInterval_AddToTheWinningSideWithLeverage(bullishQoutes, bearishQoutes, p_rebalancingFrequency, pv, ref p_htmlNoteFromStrategy);
            }
            else
            {
            }

            return(pv);
        }
        public static async Task <string> GenerateQuickTesterResponse(GeneralStrategyParameters p_generalParams, string p_strategyName, string p_params)
        {
            Stopwatch stopWatchTotalResponse = Stopwatch.StartNew();

            if (p_strategyName != "LETFDiscrepancy1" && p_strategyName != "LETFDiscrepancy2" && p_strategyName != "LETFDiscrepancy3")
            {
                return(null);
            }

            string strategyParams = p_params;
            int    ind            = -1;

            string etfPairs = null;

            if (strategyParams.StartsWith("ETFPairs=", StringComparison.InvariantCultureIgnoreCase))
            {
                strategyParams = strategyParams.Substring("ETFPairs=".Length);
                ind            = strategyParams.IndexOf('&');
                if (ind == -1)
                {
                    return(@"{ ""errorMessage"":  ""Error: uriQuery.IndexOf('&') 2. Uri: " + strategyParams + @""" }");
                }
                etfPairs       = strategyParams.Substring(0, ind);
                strategyParams = strategyParams.Substring(ind + 1);
            }

            string rebalancingFrequency = null;

            if (strategyParams.StartsWith("rebalancingFrequency=", StringComparison.InvariantCultureIgnoreCase))
            {
                strategyParams = strategyParams.Substring("rebalancingFrequency=".Length);
                ind            = strategyParams.IndexOf('&');
                if (ind == -1)
                {
                    ind = strategyParams.Length;
                }
                rebalancingFrequency = strategyParams.Substring(0, ind);
                if (ind < strategyParams.Length)
                {
                    strategyParams = strategyParams.Substring(ind + 1);
                }
                else
                {
                    strategyParams = "";
                }
            }

            ind = etfPairs.IndexOf('-');
            if (ind == -1)
            {
                return(@"{ ""errorMessage"":  ""Error: cannot find tickers in : " + etfPairs + @""" }");
            }

            string bullishTicker = etfPairs.Substring(0, ind);
            string bearishTicker = etfPairs.Substring(ind + 1);

            // startDates
            // URE: Feb 2, 2007
            // SRS: Feb 1, 2007
            // XIV: Nov 30, 2010
            // VXX: Jan 30, 2009
            // FAS: Nov 19, 2008
            // FAZ: Nov 19, 2008
            Stopwatch stopWatch        = Stopwatch.StartNew();
            var       getAllQuotesTask = StrategiesCommon.GetHistoricalAndRealtimesQuotesAsync(p_generalParams, (new string[] { bullishTicker, bearishTicker }).ToList());

            // Control returns here before GetHistoricalQuotesAsync() returns.  // ... Prompt the user.
            Console.WriteLine("Please wait patiently while I do SQL and realtime price queries.");
            var getAllQuotesData = await getAllQuotesTask;

            stopWatch.Stop();


            string htmlNoteFromStrategy = "", noteToUserCheckData = "", noteToUserBacktest = "", debugMessage = "", errorMessage = "";

            List <DailyData> pv = null;

            if (String.Equals(p_strategyName, "LETFDiscrepancy1", StringComparison.InvariantCultureIgnoreCase))
            {
                pv = DoBacktestExample(getAllQuotesData.Item1, bullishTicker, bearishTicker, rebalancingFrequency);
            }
            else
            {
                pv = DoBacktestBasic(getAllQuotesData.Item1, bullishTicker, bearishTicker, p_strategyName, rebalancingFrequency, ref noteToUserCheckData, ref htmlNoteFromStrategy);
            }


            stopWatchTotalResponse.Stop();
            StrategyResult strategyResult = StrategiesCommon.CreateStrategyResultFromPV(pv,
                                                                                        htmlNoteFromStrategy + ". " + noteToUserCheckData + "***" + noteToUserBacktest, errorMessage,
                                                                                        debugMessage + String.Format("SQL query time: {0:000}ms", getAllQuotesData.Item2.TotalMilliseconds) + String.Format(", RT query time: {0:000}ms", getAllQuotesData.Item3.TotalMilliseconds) + String.Format(", All query time: {0:000}ms", stopWatch.Elapsed.TotalMilliseconds) + String.Format(", TotalC#Response: {0:000}ms", stopWatchTotalResponse.Elapsed.TotalMilliseconds));
            string jsonReturn = JsonConvert.SerializeObject(strategyResult);

            return(jsonReturn);
            //{
            //  "Name": "Apple",
            //  "Expiry": "2008-12-28T00:00:00",
            //  "Sizes": [
            //    "Small"
            //  ]
            //}

            //returnStr = "[" + String.Join(Environment.NewLine,
            //    (await Tools.GetHistoricalQuotesAsync(new[] {
            //        new QuoteRequest { Ticker = "VXX", nQuotes = 2, StartDate = new DateTime(2011,1,1), NonAdjusted = true },
            //        new QuoteRequest { Ticker = "SPY", nQuotes = 3 }
            //    }, HQCommon.AssetType.Stock))
            //    .Select(row => String.Join(",", row))) + "]";

            //returnStr = returnStr.Replace(" 00:00:00", "");
            //returnStr = returnStr.Replace("\n", ",");

            //return @"[{""Symbol"":""VXX""},{""Symbol"":""^VIX"",""LastUtc"":""2015-01-08T19:25:48"",""Last"":17.45,""UtcTimeType"":""LastChangedTime""}]";
        }
        public static async Task<string> GenerateQuickTesterResponse(GeneralStrategyParameters p_generalParams, string p_strategyName, string p_params)
        {
            Stopwatch stopWatchTotalResponse = Stopwatch.StartNew();

            if (p_strategyName != "VXX_SPY_Controversial")
                return null;

            string strategyParams = p_params;
            int ind = -1;

            string spyMinPctMoveStr = null;
            if (strategyParams.StartsWith("SpyMinPctMove=", StringComparison.InvariantCultureIgnoreCase))
            {
                strategyParams = strategyParams.Substring("SpyMinPctMove=".Length);
                ind = strategyParams.IndexOf('&');
                if (ind == -1)
                {
                    ind = strategyParams.Length;
                }
                spyMinPctMoveStr = strategyParams.Substring(0, ind);
                if (ind < strategyParams.Length)
                    strategyParams = strategyParams.Substring(ind + 1);
                else
                    strategyParams = "";
            }
            string vxxMinPctMoveStr = null;
            if (strategyParams.StartsWith("VxxMinPctMove=", StringComparison.InvariantCultureIgnoreCase))
            {
                strategyParams = strategyParams.Substring("VxxMinPctMove=".Length);
                ind = strategyParams.IndexOf('&');
                if (ind == -1)
                {
                    ind = strategyParams.Length;
                }
                vxxMinPctMoveStr = strategyParams.Substring(0, ind);
                if (ind < strategyParams.Length)
                    strategyParams = strategyParams.Substring(ind + 1);
                else
                    strategyParams = "";
            }
            string longOrShortTrade = null;
            if (strategyParams.StartsWith("LongOrShortTrade=", StringComparison.InvariantCultureIgnoreCase))
            {
                strategyParams = strategyParams.Substring("LongOrShortTrade=".Length);
                ind = strategyParams.IndexOf('&');
                if (ind == -1)
                {
                    ind = strategyParams.Length;
                }
                longOrShortTrade = strategyParams.Substring(0, ind);
                if (ind < strategyParams.Length)
                    strategyParams = strategyParams.Substring(ind + 1);
                else
                    strategyParams = "";
            }

            double spyMinPctMove;
            bool isParseSuccess = Double.TryParse(spyMinPctMoveStr, out spyMinPctMove);
            if (!isParseSuccess)
            {
                throw new Exception("Error: spyMinPctMoveStr as " + spyMinPctMoveStr + " cannot be converted to number.");
            }

            double vxxMinPctMove;
            isParseSuccess = Double.TryParse(vxxMinPctMoveStr, out vxxMinPctMove);
            if (!isParseSuccess)
            {
                throw new Exception("Error: vxxMinPctMoveStr as " + vxxMinPctMoveStr + " cannot be converted to number.");
            }


            Stopwatch stopWatch = Stopwatch.StartNew();
            var getAllQuotesTask = StrategiesCommon.GetHistoricalAndRealtimesQuotesAsync(p_generalParams, (new string[] { "VXX", "SPY" }).ToList());
            // Control returns here before GetHistoricalQuotesAsync() returns.  // ... Prompt the user.
            Console.WriteLine("Please wait patiently while I do SQL and realtime price queries.");
            var getAllQuotesData = await getAllQuotesTask;
            stopWatch.Stop();

            var vxxQoutes = getAllQuotesData.Item1[0];
            var spyQoutes = getAllQuotesData.Item1[1];

            string noteToUserCheckData = "", noteToUserBacktest = "", debugMessage = "", errorMessage = "";
            List<DailyData> pv = StrategiesCommon.DetermineBacktestPeriodCheckDataCorrectness(vxxQoutes, spyQoutes, ref noteToUserCheckData);


            if (String.Equals(p_strategyName, "VXX_SPY_Controversial", StringComparison.InvariantCultureIgnoreCase))
            {
                DoBacktestInTheTimeInterval_VXX_SPY_Controversial(vxxQoutes, spyQoutes, spyMinPctMove, vxxMinPctMove, longOrShortTrade, pv, ref noteToUserBacktest);
            }
            //else if (String.Equals(p_strategyName, "LETFDiscrepancy3", StringComparison.InvariantCultureIgnoreCase))
            //{
            //    //DoBacktestInTheTimeInterval_AddToTheWinningSideWithLeverage(bullishQoutes, bearishQoutes, p_rebalancingFrequency, pv, ref noteToUserBacktest);
            //}
            else
            {

            }

            stopWatchTotalResponse.Stop();
            StrategyResult strategyResult = StrategiesCommon.CreateStrategyResultFromPV(pv,
               noteToUserCheckData + "***" + noteToUserBacktest, errorMessage,
               debugMessage + String.Format("SQL query time: {0:000}ms", getAllQuotesData.Item2.TotalMilliseconds) + String.Format(", RT query time: {0:000}ms", getAllQuotesData.Item3.TotalMilliseconds) + String.Format(", All query time: {0:000}ms", stopWatch.Elapsed.TotalMilliseconds) + String.Format(", TotalC#Response: {0:000}ms", stopWatchTotalResponse.Elapsed.TotalMilliseconds));
            string jsonReturn = JsonConvert.SerializeObject(strategyResult);
            return jsonReturn;
        }