Exemplo n.º 1
0
        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;
        }
Exemplo n.º 3
0
        // Sortino calculation from here: http://www.redrockcapital.com/Sortino__A__Sharper__Ratio_Red_Rock_Capital.pdf
        //The main reason we wrote this article is because in both literature and trading software packages,
        //we have seen the Sortino ratio, and in particular the target downside deviation, calculated
        //incorrectly more often than not. Most often, we see the target downside deviation calculated
        //by “throwing away all the positive returns and take the standard deviation of negative returns”.
        //We hope that by reading this article, you can see how this is incorrect
        // George: a little problem to me, but left it like this: underPerfFromTarget is distance from Zero, while in StDev, it was distance from Avg.
        public static StrategyResult CreateStrategyResultFromPV(List<DailyData> p_pv, string p_htmlNoteFromStrategy, string p_errorMessage, string p_debugMessage)
        {
            //IEnumerable<string> chartDataToSend = pv.Select(row => row.Date.Year + "-" + row.Date.Month + "-" + row.Date.Day + "-" + String.Format("{0:0.00}", row.ClosePrice));
            IEnumerable<string> chartDataToSend = p_pv.Select(row => row.Date.Year + "-" + row.Date.Month + "-" + row.Date.Day + "," + String.Format("{0:0.00}", row.ClosePrice >= 0 ? row.ClosePrice : 0.0));    // postprocess: TradingViewChart cannot accept negative numbers

            DateTime startDate = p_pv[0].Date;
            DateTime endDate = p_pv[p_pv.Count() - 1].Date;


            int nTradingDays = p_pv.Count();
            double nYears = nTradingDays / 252.0;   //https://www.google.co.uk/webhp?sourceid=chrome-instant&ion=1&espv=2&ie=UTF-8#q=how%20many%20trading%20days%20in%20a%20year

            double pvStart = p_pv[0].ClosePrice;
            double pvEnd = p_pv[p_pv.Count() - 1].ClosePrice;
            double totalGainPct = pvEnd/pvStart - 1.0;
            double cagr = Math.Pow(totalGainPct + 1, 1.0 / nYears) - 1.0;

            var dailyReturns = new double[p_pv.Count() - 1];
            for (int i = 0; i < p_pv.Count() - 1; i++)
            {
                dailyReturns[i] = p_pv[i + 1].ClosePrice / p_pv[i].ClosePrice - 1.0;
            }
            double avgReturn = dailyReturns.Average();
            double dailyStdDev = Math.Sqrt(dailyReturns.Sum(r => (r - avgReturn) * (r - avgReturn)) / ((double)dailyReturns.Count() - 1.0));    //http://www.styleadvisor.com/content/standard-deviation, "Morningstar uses the sample standard deviation method: divide by n-1
            double annualizedStDev = dailyStdDev * Math.Sqrt(252.0);    //http://en.wikipedia.org/wiki/Trading_day, http://www.styleadvisor.com/content/annualized-standard-deviation

            double annualizedSharpeRatio = cagr / annualizedStDev;

            
            double sortinoDailyTargetReturn = 0.0;       // assume investor is happy with any positive return
            double sortinoAnnualizedTargetReturn = Math.Pow(sortinoDailyTargetReturn, 252.0);       // maybe around annual 3-6% is expected by investor
            double dailyTargetDownsideDeviation = 0.0;
            for (int i = 0; i < dailyReturns.Length; i++)
            {
                double underPerfFromTarget = dailyReturns[i] - sortinoDailyTargetReturn;
                if (underPerfFromTarget < 0.0)
                    dailyTargetDownsideDeviation += underPerfFromTarget * underPerfFromTarget;
            }
            dailyTargetDownsideDeviation = Math.Sqrt(dailyTargetDownsideDeviation / (double)dailyReturns.Length);   // see Sortino PDF for explanation why we use the 0 samples too for the Average
            double annualizedDailyTargetDownsideDeviation = dailyTargetDownsideDeviation * Math.Sqrt(252.0); //http://en.wikipedia.org/wiki/Trading_day, http://www.styleadvisor.com/content/annualized-standard-deviation
            //double dailySortinoRatio = (avgReturn - sortinoDailyTargetReturn) / dailyTargetDownsideDeviation;   // daily gave too small values
            double annualizedSortinoRatio = (cagr - sortinoAnnualizedTargetReturn) / annualizedDailyTargetDownsideDeviation;   // 

            var drawdowns = new double[p_pv.Count()];
            double maxPv = Double.NegativeInfinity;
            double maxDD = Double.PositiveInfinity;
            double quadraticMeanDD = 0.0;
            for (int i = 0; i < p_pv.Count(); i++)
            {
                if (p_pv[i].ClosePrice > maxPv)
                    maxPv = p_pv[i].ClosePrice;
                double dd = p_pv[i].ClosePrice / maxPv - 1.0;
                drawdowns[i] = dd;
                quadraticMeanDD += dd * dd;
                if (dd < maxDD)
                    maxDD = drawdowns[i];
            }

            double ulcerInd = Math.Sqrt(quadraticMeanDD / (double)nTradingDays);

            int maxTradingDaysInDD = 0;
            int daysInDD = 0;
            for (int i = 0; i < drawdowns.Count(); i++)
            {
                if (drawdowns[i] < 0.0)
                    daysInDD++;
                else
                {
                    if (daysInDD > maxTradingDaysInDD)
                        maxTradingDaysInDD = daysInDD;
                    daysInDD = 0;
                }
            }
            if (daysInDD > maxTradingDaysInDD) // if the current DD is the longest one, then we have to check at the end
                maxTradingDaysInDD = daysInDD;

            int winnersCount = dailyReturns.Count(r => r > 0.0);
            int losersCount = dailyReturns.Count(r => r < 0.0);

            //double profitDaysPerAllDays = (double)dailyReturns.Count(r => r > 0.0) / dailyReturns.Count();
            //double losingDaysPerAllDays = (double)dailyReturns.Count(r => r < 0.0) / dailyReturns.Count();


            StrategyResult strategyResult = new StrategyResult()
            {
                startDateStr = startDate.ToString("yyyy-MM-dd"),
                rebalanceFrequencyStr = "Daily",
                benchmarkStr = "SPX",

                endDateStr = endDate.ToString("yyyy-MM-dd"),
                pvStartValue = pvStart,
                pvEndValue = pvEnd,
                totalGainPct = totalGainPct,
                cagr = cagr,
                annualizedStDev = annualizedStDev,
                sharpeRatio = annualizedSharpeRatio,
                sortinoRatio = annualizedSortinoRatio,
                maxDD = maxDD,
                ulcerInd = ulcerInd,
                maxTradingDaysInDD = maxTradingDaysInDD,
                winnersStr = String.Format("({0}/{1})  {2:0.00}%", winnersCount, dailyReturns.Count(), 100.0 * (double)winnersCount / dailyReturns.Count()),
                losersStr = String.Format("({0}/{1})  {2:0.00}%", losersCount, dailyReturns.Count(), 100.0 * (double)losersCount / dailyReturns.Count()),

                benchmarkCagr = 0,
                benchmarkMaxDD = 0,
                benchmarkCorrelation = 0,

                pvCash = 0.0,
                nPositions = 0,
                holdingsListStr = "NotApplicable",

                chartData = chartDataToSend.ToList(),

                htmlNoteFromStrategy = p_htmlNoteFromStrategy,
                errorMessage = p_errorMessage,
                debugMessage = p_debugMessage
            };

            return strategyResult;
        }
Exemplo n.º 4
0
        // Sortino calculation from here: http://www.redrockcapital.com/Sortino__A__Sharper__Ratio_Red_Rock_Capital.pdf
        //The main reason we wrote this article is because in both literature and trading software packages,
        //we have seen the Sortino ratio, and in particular the target downside deviation, calculated
        //incorrectly more often than not. Most often, we see the target downside deviation calculated
        //by “throwing away all the positive returns and take the standard deviation of negative returns”.
        //We hope that by reading this article, you can see how this is incorrect
        // George: a little problem to me, but left it like this: underPerfFromTarget is distance from Zero, while in StDev, it was distance from Avg.
        public static StrategyResult CreateStrategyResultFromPV(List <DailyData> p_pv, string p_htmlNoteFromStrategy, string p_errorMessage, string p_debugMessage)
        {
            //IEnumerable<string> chartDataToSend = pv.Select(row => row.Date.Year + "-" + row.Date.Month + "-" + row.Date.Day + "-" + String.Format("{0:0.00}", row.ClosePrice));
            IEnumerable <string> chartDataToSend = p_pv.Select(row => row.Date.Year + "-" + row.Date.Month + "-" + row.Date.Day + "," + String.Format("{0:0.00}", row.ClosePrice >= 0 ? row.ClosePrice : 0.0));    // postprocess: TradingViewChart cannot accept negative numbers

            DateTime startDate = p_pv[0].Date;
            DateTime endDate   = p_pv[p_pv.Count() - 1].Date;


            int    nTradingDays = p_pv.Count();
            double nYears       = nTradingDays / 252.0; //https://www.google.co.uk/webhp?sourceid=chrome-instant&ion=1&espv=2&ie=UTF-8#q=how%20many%20trading%20days%20in%20a%20year

            double pvStart      = p_pv[0].ClosePrice;
            double pvEnd        = p_pv[p_pv.Count() - 1].ClosePrice;
            double totalGainPct = pvEnd / pvStart - 1.0;
            double cagr         = Math.Pow(totalGainPct + 1, 1.0 / nYears) - 1.0;

            var dailyReturns = new double[p_pv.Count() - 1];

            for (int i = 0; i < p_pv.Count() - 1; i++)
            {
                dailyReturns[i] = p_pv[i + 1].ClosePrice / p_pv[i].ClosePrice - 1.0;
            }
            double avgReturn       = dailyReturns.Average();
            double dailyStdDev     = Math.Sqrt(dailyReturns.Sum(r => (r - avgReturn) * (r - avgReturn)) / ((double)dailyReturns.Count() - 1.0)); //http://www.styleadvisor.com/content/standard-deviation, "Morningstar uses the sample standard deviation method: divide by n-1
            double annualizedStDev = dailyStdDev * Math.Sqrt(252.0);                                                                             //http://en.wikipedia.org/wiki/Trading_day, http://www.styleadvisor.com/content/annualized-standard-deviation

            double annualizedSharpeRatio = cagr / annualizedStDev;


            double sortinoDailyTargetReturn      = 0.0;                                       // assume investor is happy with any positive return
            double sortinoAnnualizedTargetReturn = Math.Pow(sortinoDailyTargetReturn, 252.0); // maybe around annual 3-6% is expected by investor
            double dailyTargetDownsideDeviation  = 0.0;

            for (int i = 0; i < dailyReturns.Length; i++)
            {
                double underPerfFromTarget = dailyReturns[i] - sortinoDailyTargetReturn;
                if (underPerfFromTarget < 0.0)
                {
                    dailyTargetDownsideDeviation += underPerfFromTarget * underPerfFromTarget;
                }
            }
            dailyTargetDownsideDeviation = Math.Sqrt(dailyTargetDownsideDeviation / (double)dailyReturns.Length);            // see Sortino PDF for explanation why we use the 0 samples too for the Average
            double annualizedDailyTargetDownsideDeviation = dailyTargetDownsideDeviation * Math.Sqrt(252.0);                 //http://en.wikipedia.org/wiki/Trading_day, http://www.styleadvisor.com/content/annualized-standard-deviation
            //double dailySortinoRatio = (avgReturn - sortinoDailyTargetReturn) / dailyTargetDownsideDeviation;   // daily gave too small values
            double annualizedSortinoRatio = (cagr - sortinoAnnualizedTargetReturn) / annualizedDailyTargetDownsideDeviation; //

            var    drawdowns       = new double[p_pv.Count()];
            double maxPv           = Double.NegativeInfinity;
            double maxDD           = Double.PositiveInfinity;
            double quadraticMeanDD = 0.0;

            for (int i = 0; i < p_pv.Count(); i++)
            {
                if (p_pv[i].ClosePrice > maxPv)
                {
                    maxPv = p_pv[i].ClosePrice;
                }
                double dd = p_pv[i].ClosePrice / maxPv - 1.0;
                drawdowns[i]     = dd;
                quadraticMeanDD += dd * dd;
                if (dd < maxDD)
                {
                    maxDD = drawdowns[i];
                }
            }

            double ulcerInd = Math.Sqrt(quadraticMeanDD / (double)nTradingDays);

            int maxTradingDaysInDD = 0;
            int daysInDD           = 0;

            for (int i = 0; i < drawdowns.Count(); i++)
            {
                if (drawdowns[i] < 0.0)
                {
                    daysInDD++;
                }
                else
                {
                    if (daysInDD > maxTradingDaysInDD)
                    {
                        maxTradingDaysInDD = daysInDD;
                    }
                    daysInDD = 0;
                }
            }
            if (daysInDD > maxTradingDaysInDD) // if the current DD is the longest one, then we have to check at the end
            {
                maxTradingDaysInDD = daysInDD;
            }

            int winnersCount = dailyReturns.Count(r => r > 0.0);
            int losersCount  = dailyReturns.Count(r => r < 0.0);

            //double profitDaysPerAllDays = (double)dailyReturns.Count(r => r > 0.0) / dailyReturns.Count();
            //double losingDaysPerAllDays = (double)dailyReturns.Count(r => r < 0.0) / dailyReturns.Count();


            StrategyResult strategyResult = new StrategyResult()
            {
                startDateStr          = startDate.ToString("yyyy-MM-dd"),
                rebalanceFrequencyStr = "Daily",
                benchmarkStr          = "SPX",

                endDateStr         = endDate.ToString("yyyy-MM-dd"),
                pvStartValue       = pvStart,
                pvEndValue         = pvEnd,
                totalGainPct       = totalGainPct,
                cagr               = cagr,
                annualizedStDev    = annualizedStDev,
                sharpeRatio        = annualizedSharpeRatio,
                sortinoRatio       = annualizedSortinoRatio,
                maxDD              = maxDD,
                ulcerInd           = ulcerInd,
                maxTradingDaysInDD = maxTradingDaysInDD,
                winnersStr         = String.Format("({0}/{1})  {2:0.00}%", winnersCount, dailyReturns.Count(), 100.0 * (double)winnersCount / dailyReturns.Count()),
                losersStr          = String.Format("({0}/{1})  {2:0.00}%", losersCount, dailyReturns.Count(), 100.0 * (double)losersCount / dailyReturns.Count()),

                benchmarkCagr        = 0,
                benchmarkMaxDD       = 0,
                benchmarkCorrelation = 0,

                pvCash          = 0.0,
                nPositions      = 0,
                holdingsListStr = "NotApplicable",

                chartData = chartDataToSend.ToList(),

                htmlNoteFromStrategy = p_htmlNoteFromStrategy,
                errorMessage         = p_errorMessage,
                debugMessage         = p_debugMessage
            };

            return(strategyResult);
        }