public static async Task<string> GenerateQuickTesterResponse(GeneralStrategyParameters p_generalParams, string p_strategyName, Dictionary<string, StringValues> p_allParamsDict) { if (p_strategyName != "AdaptiveUberVxx") return null; Stopwatch stopWatchTotalResponse = Stopwatch.StartNew(); // if parameter is not present, then it is Unexpected, it will crash, and caller Catches it. Good. //string assetsStr = p_allParamsDict["Assets"][0]; // "MDY,ILF,FEZ,EEM,EPP,VNQ,TLT" Stopwatch stopWatch = Stopwatch.StartNew(); var getAllQuotesTask = StrategiesCommon.GetHistoricalAndRealtimesQuotesAsync(p_generalParams, (new string[] { "VXX", "SPY" }).ToList()); var getAllQuotesData = await getAllQuotesTask; stopWatch.Stop(); string warningToUser = "", noteToUserBacktest = "", debugMessage = "", errorMessage = ""; DateTime startDate, endDate; StrategiesCommon.DetermineBacktestPeriodCheckDataCorrectness(getAllQuotesData.Item1, new string[] { "VXX", "SPY" }, ref warningToUser, out startDate, out endDate); List<DailyData> pv = StrategiesCommon.DeepCopyQuoteRange(getAllQuotesData.Item1[0], startDate, endDate); var vxxQoutes = getAllQuotesData.Item1[0]; var spyQoutes = getAllQuotesData.Item1[1]; DoBacktestInTheTimeInterval_AdaptiveUberVxx(vxxQoutes, spyQoutes, 0.001, 0.001, "Long", pv, ref noteToUserBacktest); stopWatchTotalResponse.Stop(); StrategyResult strategyResult = StrategiesCommon.CreateStrategyResultFromPV(pv, warningToUser + "***" + 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; }
public static async Task<string> GenerateQuickTesterResponse(GeneralStrategyParameters p_generalParams, string p_strategyName, Dictionary<string, StringValues> p_allParamsDict) { if (p_strategyName != "VXX_SPY_Controversial") return null; Stopwatch stopWatchTotalResponse = Stopwatch.StartNew(); // if parameter is not present, then it is Unexpected, it will crash, and caller Catches it. Good. string spyMinPctMoveStr = p_allParamsDict["SpyMinPctMove"][0]; string vxxMinPctMoveStr = p_allParamsDict["VxxMinPctMove"][0]; string longOrShortTrade = p_allParamsDict["LongOrShortTrade"][0]; 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()); var getAllQuotesData = await getAllQuotesTask; stopWatch.Stop(); string warningToUser = "", noteToUserBacktest = "", debugMessage = "", errorMessage = ""; DateTime startDate, endDate; StrategiesCommon.DetermineBacktestPeriodCheckDataCorrectness(getAllQuotesData.Item1, new string[] { "VXX", "SPY" }, ref warningToUser, out startDate, out endDate); List<DailyData> pv = StrategiesCommon.DeepCopyQuoteRange(getAllQuotesData.Item1[0], startDate, endDate); var vxxQoutes = getAllQuotesData.Item1[0]; var spyQoutes = getAllQuotesData.Item1[1]; if (String.Equals(p_strategyName, "VXX_SPY_Controversial", StringComparison.CurrentCultureIgnoreCase)) { DoBacktestInTheTimeInterval_VXX_SPY_Controversial(vxxQoutes, spyQoutes, spyMinPctMove, vxxMinPctMove, longOrShortTrade, pv, ref noteToUserBacktest); } else { } stopWatchTotalResponse.Stop(); StrategyResult strategyResult = StrategiesCommon.CreateStrategyResultFromPV(pv, warningToUser + "***" + 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; }
public static async Task<string> GenerateQuickTesterResponse(GeneralStrategyParameters p_generalParams, string p_strategyName, Dictionary<string, StringValues> p_allParamsDict) { if (p_strategyName != "TotM") return null; Stopwatch stopWatchTotalResponse = Stopwatch.StartNew(); // if parameter is not present, then it is Unexpected, it will crash, and caller Catches it. Good. string bullishTradingInstrument = p_allParamsDict["BullishTradingInstrument"][0]; string dailyMarketDirectionMaskSummerTotM = p_allParamsDict["DailyMarketDirectionMaskSummerTotM"][0]; string dailyMarketDirectionMaskSummerTotMM = p_allParamsDict["DailyMarketDirectionMaskSummerTotMM"][0]; string dailyMarketDirectionMaskWinterTotM = p_allParamsDict["DailyMarketDirectionMaskWinterTotM"][0]; string dailyMarketDirectionMaskWinterTotMM = p_allParamsDict["DailyMarketDirectionMaskWinterTotMM"][0]; //bullishTradingInstrument = bullishTradingInstrument.Replace("%20", " "); int ind = bullishTradingInstrument.IndexOf(' '); // "long SPY", "long QQQ", "short VXX" StrongAssert.True(ind != -1 && ind != (bullishTradingInstrument.Length - 1), "bullishTradingInstrument parameter cannot be interpreted: " + bullishTradingInstrument); string stock = bullishTradingInstrument.Substring(ind + 1); string longOrShortOnBullish = bullishTradingInstrument.Substring(0, ind); Stopwatch stopWatch = Stopwatch.StartNew(); var getAllQuotesTask = StrategiesCommon.GetHistoricalAndRealtimesQuotesAsync(p_generalParams, (new string[] { stock }).ToList()); var getAllQuotesData = await getAllQuotesTask; stopWatch.Stop(); var stockQoutes = getAllQuotesData.Item1[0]; string warningToUser = "", noteToUserBacktest = "", debugMessage = "", errorMessage = ""; List<DailyData> pv = StrategiesCommon.DetermineBacktestPeriodCheckDataCorrectness(stockQoutes, ref warningToUser); DoBacktestInTheTimeInterval_TotM(stockQoutes, longOrShortOnBullish, dailyMarketDirectionMaskSummerTotM, dailyMarketDirectionMaskSummerTotMM, dailyMarketDirectionMaskWinterTotM, dailyMarketDirectionMaskWinterTotMM, pv, ref noteToUserBacktest); stopWatchTotalResponse.Stop(); StrategyResult strategyResult = StrategiesCommon.CreateStrategyResultFromPV(pv, //"Number of positions: <span> XXXX </span><br><br>test", //"Number of positions: <span> {{nPositions}} </span><br><br>test", "<b>Bullish</b> (Bearish) on days when mask is Up (Down).<br>" + warningToUser + ((!String.IsNullOrEmpty(warningToUser) && !String.IsNullOrEmpty(noteToUserBacktest)) ? "<br>" : "") + 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; }
public static async Task<Tuple<IList<List<DailyData>>, TimeSpan, TimeSpan>> GetHistoricalAndRealtimesQuotesAsync(GeneralStrategyParameters p_generalParams, List<string> p_tickers, CancellationToken p_canc = default(CancellationToken)) { //- SPY 300K CSV SQLqueryTime (local server), msecond times for (for Azure in-house datacenter, these will be less) //All data: Open, High, Low, Close, Volume : 886, 706, 1237, 761, 727, Avg = 863 //Only ClosePrice: 662, 680, 702, 820, 663, 692, Avg = 703 // if the Website is not local, but it is in the same Azure datacenter as the SQL center //SQL query time (All OHLCV data): msec: 612, 614, 667, 772, 632, 613, 665, 662, Avg = 654 //SQL query time (only Close data): msec: 623, 624, 704, 614, 615, 621, 621, 722, 636, Avg = 642 //Conclusion:downloading only Closeprice from SQL, we can save 100msec (LocalServer website (non-datacenter website)) or 15msec (Azure server website when SQL server is very close), still worth it ushort sqlReturnedColumns = QuoteRequest.TDC; // QuoteRequest.All or QuoteRequest.TDOHLCVS //var sqlReturnTask = GetHistQuotesAsync(p_tickers.Select(r => new QuoteRequest { Ticker = r, nQuotes = Int32.MaxValue, NonAdjusted = false, ReturnedColumns = sqlReturnedColumns }), HQCommon.AssetType.Stock, true); // Ascending date order: TRUE, better to order it at the SQL server than locally. SQL has indexers var sqlReturnTask = GetHistQuotesAsync(p_generalParams, p_tickers, sqlReturnedColumns); Task<Tuple<IList<double?>, TimeSpan>> realtimeReturnTask = null; if (p_generalParams.endDateUtc >= DateTime.UtcNow) realtimeReturnTask = GetRealtimesQuotesAsync(p_tickers); // Control returns here before GetHistoricalQuotesAsync() returns. // ... Prompt the user. Console.WriteLine("Please wait patiently while I do SQL and realtime price queries."); // Wait for the tasks to complete. // ... Display its results. //var combinedAsyncTasksResults = await Task.WhenAll(sqlReturnTask, realtimeReturnTask); this cannot be done now, because the return values are different if (realtimeReturnTask != null) await Task.WhenAll(sqlReturnTask, realtimeReturnTask); // otherwise, the next await will wait the historical data var sqlReturnData = await sqlReturnTask; //as they have all definitely finished, you could also use Task.Value, "However, I recommend using await because it's clearly correct, while Result can cause problems in other scenarios." Tuple<IList<double?>, TimeSpan> realtimeReturnData = null; if (realtimeReturnTask != null) realtimeReturnData = await realtimeReturnTask; //as they have all definitely finished, you could also use Task.Value, "However, I recommend using await because it's clearly correct, while Result can cause problems in other scenarios." var sqlReturn = sqlReturnData.Item1; List<List<DailyData>> returnQuotes = null; // sql query of "VXX.SQ" gives back tickers of VXX and also tickers of "VXX.SQ" int closePriceIndex = -1; if (sqlReturnedColumns == QuoteRequest.TDOHLCVS) closePriceIndex = 5; else if (sqlReturnedColumns == QuoteRequest.TDC) closePriceIndex = 2; else throw new NotImplementedException(); returnQuotes = p_tickers.Select(ticker => { string tickerWithoutDotSQ = ""; if (ticker.EndsWith(".SQ")) tickerWithoutDotSQ = ticker.Substring(0, ticker.Length - ".SQ".Length); return sqlReturn.Where(row => (string)row[0] == ticker || (string)row[0] == tickerWithoutDotSQ).Select( row => new DailyData() { Date = ((DateTime)row[1]), ClosePrice = (double)Convert.ToDecimal(row[closePriceIndex]) // row[2] is object(double) if it is a stock (because Adjustment multiplier), and object(float) if it is Indices. However Convert.ToDouble(row[2]) would convert 16.66 to 16.6599999 }).ToList(); }).ToList(); if (realtimeReturnData != null) { var todayDate = DateTime.UtcNow.Date; var realtimeReturn = realtimeReturnData.Item1; for (int i = 0; i < p_tickers.Count(); i++) { if (realtimeReturn[i] != null) { int todayInd = returnQuotes[i].FindLastIndex(r => r.Date == todayDate); if (todayInd == -1) // if it is missing { returnQuotes[i].Add(new DailyData() { Date = todayDate, ClosePrice = (double)realtimeReturn[i] }); } else // if it is already in the array, overwrite it { returnQuotes[i][todayInd].ClosePrice = (double)realtimeReturn[i]; } } } } return new Tuple<IList<List<DailyData>>, TimeSpan, TimeSpan>(returnQuotes, sqlReturnData.Item2, (realtimeReturnData != null) ? realtimeReturnData.Item2 : TimeSpan.Zero); }
//public static async Task<Tuple<IList<object[]>,TimeSpan>> GetHistQuotesAsync(IEnumerable<QuoteRequest> p_req, HQCommon.AssetType p_at, bool? p_isAscendingDates = null, CancellationToken p_canc = default(CancellationToken)) public static async Task<Tuple<List<object[]>, TimeSpan>> GetHistQuotesAsync(GeneralStrategyParameters p_generalParams, List<string> p_tickers, ushort p_sqlReturnedColumns) { List<string> stockTickers = p_tickers.Where(r => !r.StartsWith("^")).ToList(); List<string> indicesTickers = p_tickers.Where(r => r.StartsWith("^")).ToList(); TimeZoneInfo etZone = null; int requestNQuotes = Int32.MaxValue; DateTime? requestStartDateExcgLocal = null, requestEndDateExcgLocal = null; if (p_generalParams.startDateUtc != DateTime.MinValue) { ConvertUtcToExchangeLocal(p_generalParams.startDateUtc, ref etZone, ref requestStartDateExcgLocal); } if (p_generalParams.endDateUtc != DateTime.MaxValue) { ConvertUtcToExchangeLocal(p_generalParams.endDateUtc, ref etZone, ref requestEndDateExcgLocal); } Stopwatch stopWatch = Stopwatch.StartNew(); Task<IList<object[]>> stocksSqlReturnTask = null, indicesSqlReturnTask = null; IList<object[]> stocksSqlReturn = null, indicesSqlReturn = null; if (stockTickers.Count != 0) stocksSqlReturnTask = SqlTools.LoadHistoricalQuotesAsync(stockTickers.Select(r => new QuoteRequest { Ticker = r, nQuotes = requestNQuotes, StartDate = requestStartDateExcgLocal, EndDate = requestEndDateExcgLocal, NonAdjusted = false, ReturnedColumns = p_sqlReturnedColumns }), DbCommon.AssetType.Stock, true); // Ascending date order: TRUE, better to order it at the SQL server than locally. SQL has indexers if (indicesTickers.Count != 0) indicesSqlReturnTask = SqlTools.LoadHistoricalQuotesAsync(indicesTickers.Select(r => new QuoteRequest { Ticker = r, nQuotes = requestNQuotes, StartDate = requestStartDateExcgLocal, EndDate = requestEndDateExcgLocal, NonAdjusted = false, ReturnedColumns = p_sqlReturnedColumns }), DbCommon.AssetType.BenchmarkIndex, true); // Ascending date order: TRUE, better to order it at the SQL server than locally. SQL has indexers if (stockTickers.Count != 0) stocksSqlReturn = await stocksSqlReturnTask; if (indicesTickers.Count != 0) indicesSqlReturn = await indicesSqlReturnTask; stopWatch.Stop(); TimeSpan historicalQueryTimeSpan = stopWatch.Elapsed; List<object[]> sqlReturn = null; if (stocksSqlReturn != null) sqlReturn = stocksSqlReturn.ToList(); // the return is a List() already if you look deeper in the implementation if (indicesSqlReturn != null) { if (sqlReturn == null) sqlReturn = indicesSqlReturn.ToList(); else sqlReturn.AddRange(indicesSqlReturn.ToList()); } return new Tuple<List<object[]>, TimeSpan>(sqlReturn, historicalQueryTimeSpan); }
public static async Task<string> GenerateQuickTesterResponse(GeneralStrategyParameters p_generalParams, string p_strategyName, Dictionary<string, StringValues> p_allParamsDict) { if (p_strategyName != "LETFDiscrepancy1" && p_strategyName != "LETFDiscrepancy2" && p_strategyName != "LETFDiscrepancy3" && p_strategyName != "LETFDiscrepancy4") return null; Stopwatch stopWatchTotalResponse = Stopwatch.StartNew(); // if parameter is not present, then it is Unexpected, it will crash, and caller Catches it. Good. string etfPairs = p_allParamsDict["ETFPairs"][0]; string rebalancingFrequency = p_allParamsDict["RebalancingFrequency"][0]; string etf1 = p_allParamsDict["ETF1"][0]; string weightStr1 = p_allParamsDict["Weight1"][0]; string etf2 = p_allParamsDict["ETF2"][0]; string weightStr2 = p_allParamsDict["Weight2"][0]; double weight1 = Double.NaN; if (!Double.TryParse(weightStr1, out weight1)) return @"{ ""errorMessage"": ""Error: Weight1 cannot be converted to Number : " + weightStr1 + @""" }"; double weight2 = Double.NaN; if (!Double.TryParse(weightStr2, out weight2)) return @"{ ""errorMessage"": ""Error: Weight2 cannot be converted to Number : " + weightStr2 + @""" }"; int ind = etfPairs.IndexOf('-'); if (ind == -1) { return @"{ ""errorMessage"": ""Error: cannot find tickers in : " + etfPairs + @""" }"; } string etfPairs1 = etfPairs.Substring(0, ind); string etfPairs2 = etfPairs.Substring(ind + 1); string ticker1 = null, ticker2 = null; if (p_strategyName == "LETFDiscrepancy4") // in HarryLong strategy use these as tickers { ticker1 = etf1; ticker2 = etf2; }else { ticker1 = etfPairs1; ticker2 = etfPairs2; } int rebalancingTradingDays; if (!Int32.TryParse(rebalancingFrequency.TrimEnd(new char[] { 'd', 'D' }), out rebalancingTradingDays)) rebalancingTradingDays = Int32.MaxValue; //So we don't rebalance // 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 List<string> tickers = new List<string>(); if (!ticker1.Equals("Cash")) tickers.Add(ticker1); if (!ticker2.Equals("Cash")) tickers.Add(ticker2); Stopwatch stopWatch = Stopwatch.StartNew(); var getAllQuotesTask = StrategiesCommon.GetHistoricalAndRealtimesQuotesAsync(p_generalParams, tickers); Tuple<IList<List<DailyData>>, TimeSpan, TimeSpan> getAllQuotesData = await getAllQuotesTask; stopWatch.Stop(); IList<List<DailyData>> quotes12 = getAllQuotesData.Item1; List<DailyData> quotes1 = null, quotes2 = null; if (!ticker1.Equals("Cash")) { quotes1 = quotes12[0]; quotes12.RemoveAt(0); } if (!ticker2.Equals("Cash")) { quotes2 = quotes12[0]; quotes12.RemoveAt(0); } if (quotes1 == null) // it is Cash, set it according to the other, but use cash quotes1 = quotes2.Select(item => new DailyData() { Date = item.Date, ClosePrice = 100.0 }).ToList(); if (quotes2 == null) // it is Cash, set it according to the other, but use cash quotes2 = quotes1.Select(item => new DailyData() { Date = item.Date, ClosePrice = 100.0 }).ToList(); string htmlNoteFromStrategy = "", warningToUser = "", noteToUserBacktest = "", debugMessage = "", errorMessage = ""; List<DailyData> pv = null; if (String.Equals(p_strategyName, "LETFDiscrepancy1", StringComparison.CurrentCultureIgnoreCase)) { pv = quotes1; // only testing: PV = First of the ETF pair } else { DateTime startDate, endDate; StrategiesCommon.DetermineBacktestPeriodCheckDataCorrectness((new List<DailyData>[] { quotes1, quotes2 }).ToList(), new string[] { ticker1, ticker2 }, ref warningToUser, out startDate, out endDate); pv = StrategiesCommon.DeepCopyQuoteRange(quotes1, startDate, endDate); if (String.Equals(p_strategyName, "LETFDiscrepancy2", StringComparison.CurrentCultureIgnoreCase)) { DoBacktestInTheTimeInterval_RebalanceToNeutral(quotes1, quotes2, rebalancingTradingDays, pv, ref warningToUser); } else if (String.Equals(p_strategyName, "LETFDiscrepancy3", StringComparison.CurrentCultureIgnoreCase)) { DoBacktestInTheTimeInterval_AddToTheWinningSideWithLeverage(quotes1, quotes2, rebalancingTradingDays, pv, ref warningToUser); } else if (String.Equals(p_strategyName, "LETFDiscrepancy4", StringComparison.CurrentCultureIgnoreCase)) { DoBacktestInTheTimeInterval_HarryLong(quotes1, quotes2, weight1 / 100.0, weight2 / 100.0, rebalancingTradingDays, pv, ref warningToUser); } else { } } stopWatchTotalResponse.Stop(); StrategyResult strategyResult = StrategiesCommon.CreateStrategyResultFromPV(pv, htmlNoteFromStrategy + ". " + warningToUser + "***" + 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""}]"; }
private async Task<Tuple<string, string>> GenerateRtpResponse() { string jsonpCallback = null; string uriQuery = ""; try { uriQuery = this.HttpContext.Request.QueryString.ToString(); // "?s=VXX,XIV,^vix&f=ab&o=csv" from the URL http://localhost:58213/api/rtp?s=VXX,XIV,^vix&f=ab&o=csv if (uriQuery.Length > 8192) {//When you try to pass a string longer than 8192 charachters, a faultException will be thrown. There is a solution, but I don't want throw new Exception("Error caught by WebApi Get():: uriQuery is longer than 8192: we don't process that. Uri: " + uriQuery); } uriQuery = uriQuery.Substring(1); // remove '?' uriQuery = uriQuery.Replace("%20", " ").Replace("%5E", "^"); // de-coding from URL to normal things // QueryString paramsQs = new QueryString("?" + p_params); Dictionary<string, StringValues> allParamsDict = Microsoft.AspNetCore.WebUtilities.QueryHelpers.ParseQuery(uriQuery); // unlike ParseQueryString in System.Web, this returns a dictionary of type IDictionary<string, string[]>, so the value is an array of strings. This is how the dictionary handles multiple query string parameters with the same name. StringValues jsonpStrVal; if (allParamsDict.TryGetValue("jsonp", out jsonpStrVal)) // Strategy.ts.StartBacktest() doesn't fill this up, so 'jsonp' is not expected in query jsonpCallback = jsonpStrVal[0]; string startDateStr = allParamsDict["StartDate"][0]; // if parameter is not present, then it is Unexpected, it will crash, and caller Catches it. Good. string endDateStr = allParamsDict["EndDate"][0]; string strategyName = allParamsDict["strategy"][0]; DateTime startDate = DateTime.MinValue; if (startDateStr.Length != 0) { if (!DateTime.TryParse(startDateStr, out startDate)) throw new Exception("Error: startDateStr couldn't be converted: " + uriQuery); } DateTime endDate = DateTime.MaxValue; if (endDateStr.Length != 0) { if (!DateTime.TryParse(endDateStr, out endDate)) throw new Exception("Error: endDateStr couldn't be converted: " + uriQuery); } GeneralStrategyParameters generalParams = new GeneralStrategyParameters() { startDateUtc = startDate, endDateUtc = endDate }; string jsonString = (await AdaptiveUberVxx.GenerateQuickTesterResponse(generalParams, strategyName, allParamsDict)); if (jsonString == null) jsonString = (await TotM.GenerateQuickTesterResponse(generalParams, strategyName, allParamsDict)); if (jsonString == null) jsonString = await VXX_SPY_Controversial.GenerateQuickTesterResponse(generalParams, strategyName, allParamsDict); if (jsonString == null) jsonString = (await LEtfDistcrepancy.GenerateQuickTesterResponse(generalParams, strategyName, allParamsDict)); if (jsonString == null) jsonString = (await TAA.GenerateQuickTesterResponse(generalParams, strategyName, allParamsDict)); if (jsonString == null) throw new Exception("Strategy was not found in the WebApi: " + strategyName); string reply = ResponseBuilder(jsonpCallback, jsonString); //var jsonDownload = string.Empty; ////string queryString = @"?s=VXX,SVXY,UWM,TWM,^RUT&f=l"; // without JsonP, these tickers are streamed all the time //Utils.Logger.Info($"RealtimePrice.GenerateRtpResponse(). Sending '{this.HttpContext.Request.QueryString.ToString()}'"); //string reply = VirtualBrokerMessage.Send(this.HttpContext.Request.QueryString.ToString(), VirtualBrokerMessageID.GetRealtimePrice).Result; //Utils.Logger.Info($"RealtimePrice.GenerateRtpResponse(). Received '{reply}'"); return new Tuple<string, string>(reply, "application/json"); } catch (Exception e) { string errMsg = $"Error. Exception in QuickTester.GenerateRtpResponse() UriQuery: '{uriQuery}'"; Utils.Logger.Error(e, errMsg); string reply = ResponseBuilder(jsonpCallback, @"{ ""errorMessage"": """ + errMsg + @", Exception.Message: " + e.Message + @""" }"); return new Tuple<string, string>(reply, "application/json"); } }
public static async Task<string> GenerateQuickTesterResponse(GeneralStrategyParameters p_generalParams, string p_strategyName, Dictionary<string, StringValues> p_allParamsDict) { if (p_strategyName != "TAA") return null; Stopwatch stopWatchTotalResponse = Stopwatch.StartNew(); // if parameter is not present, then it is Unexpected, it will crash, and caller Catches it. Good. string assetsStr = p_allParamsDict["Assets"][0]; // "MDY,ILF,FEZ,EEM,EPP,VNQ,TLT" string assetsConstantLeverageStr = p_allParamsDict["AssetsConstantLeverage"][0]; // "1,1,1,-1,1.5,2,2" string rebalancingFrequencyStr = p_allParamsDict["RebalancingFrequency"][0]; // "Weekly,Fridays"; // "Daily, 2d"(trading days),"Weekly, Fridays", "Monthly, T+1"/"Monthly, T-1" (first/last trading day of the month), string pctChannelLookbackDaysStr = p_allParamsDict["PctChannelLookbackDays"][0]; // "30-60-120-252" string pctChannelPctLimitsStr = p_allParamsDict["PctChannelPctLimits"][0]; // "30-70" string pctChannelIsConditionalStr = p_allParamsDict["PctChannelIsConditional"][0]; // "Yes" string histVolLookbackDaysStr = p_allParamsDict["HistVolLookbackDays"][0]; // "20" string dynamicLeverageClmtParamsStr = p_allParamsDict["DynamicLeverageClmtParams"][0]; // "SMA(SPX,50d,200d); PR(XLU,VTI,20d)"; // SPX 50/200 crossover; PR=PriceRatio of XLU/VTI for 20 days string uberVxxEventsParamsStr = p_allParamsDict["UberVxxEventsParams"][0]; // "FOMC;Holidays" RebalancingPeriodicity rebalancingPeriodicity = RebalancingPeriodicity.Weekly; DayOfWeek weeklyRebalancingWeekDay = DayOfWeek.Friday; int[] pctChannelLookbackDays = pctChannelLookbackDaysStr.Split(new char[] { '-' }, StringSplitOptions.RemoveEmptyEntries).Select(r => Int32.Parse(r)).ToArray(); string[] pctChannelPctLimitsStr2 = pctChannelPctLimitsStr.Split(new char[] { '-' }, StringSplitOptions.RemoveEmptyEntries); double pctChannelPctLimitLower = Double.Parse(pctChannelPctLimitsStr2[0]) / 100.0; double pctChannelPctLimitUpper = Double.Parse(pctChannelPctLimitsStr2[1]) / 100.0; int histVolLookbackDays = Int32.Parse(histVolLookbackDaysStr); int clmt1_shorterDays = 50, clmt1_longerDays = 200, clmt2_utilsLookbackDays = 20; string[] tickers = assetsStr.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries); bool isNonActiveAssetsPlayedByCash = true; string cashSubstituteTicker = "SHY"; // "" List<string> tickersNeeded = tickers.ToList(); if (!String.IsNullOrEmpty(cashSubstituteTicker)) tickersNeeded.Add(cashSubstituteTicker); Stopwatch stopWatch = Stopwatch.StartNew(); var getAllQuotesTask = StrategiesCommon.GetHistoricalAndRealtimesQuotesAsync(p_generalParams, tickersNeeded); Tuple<IList<List<DailyData>>, TimeSpan, TimeSpan> getAllQuotesData = await getAllQuotesTask; stopWatch.Stop(); IList<List<DailyData>> quotes; List<DailyData> cashSubstituteQuotes = null; if (String.IsNullOrEmpty(cashSubstituteTicker)) quotes = getAllQuotesData.Item1; else { quotes = getAllQuotesData.Item1.ToList().GetRange(0, tickers.Length); cashSubstituteQuotes = getAllQuotesData.Item1[tickers.Length]; } string warningToUser = "", noteToUserBacktest = "", debugMessage = "", errorMessage = ""; List<DailyData> pv; DoBacktestInTheTimeInterval_TAA(quotes, tickers, rebalancingPeriodicity, weeklyRebalancingWeekDay, pctChannelLookbackDays, pctChannelPctLimitLower, pctChannelPctLimitUpper, histVolLookbackDays, clmt1_shorterDays, clmt1_longerDays, clmt2_utilsLookbackDays, isNonActiveAssetsPlayedByCash, cashSubstituteQuotes, ref warningToUser, ref noteToUserBacktest, ref errorMessage, ref debugMessage, out pv); stopWatchTotalResponse.Stop(); StrategyResult strategyResult = StrategiesCommon.CreateStrategyResultFromPV(pv, warningToUser + "***" + 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; }