From e50ac03b3312de95a36fab629ef9bbabe38cbf8d Mon Sep 17 00:00:00 2001 From: Sean Date: Sat, 22 Feb 2025 22:15:37 -0500 Subject: [PATCH] Add StopLimitATRMultiplier as a configurable parameter. Code cleanup. --- .../Generator/MGSHMomentum/MGSHActivePositions.cs | 10 ++++++++++ MarketDataLib/Generator/MGSHMomentum/MGSHBacktest.cs | 9 +++------ .../Generator/MGSHMomentum/MGSHConfiguration.cs | 9 +++++++++ 3 files changed, 22 insertions(+), 6 deletions(-) diff --git a/MarketDataLib/Generator/MGSHMomentum/MGSHActivePositions.cs b/MarketDataLib/Generator/MGSHMomentum/MGSHActivePositions.cs index 9f9b85c..5dd73de 100644 --- a/MarketDataLib/Generator/MGSHMomentum/MGSHActivePositions.cs +++ b/MarketDataLib/Generator/MGSHMomentum/MGSHActivePositions.cs @@ -11,6 +11,16 @@ namespace MarketData.Generator.MGSHMomentum { } + public int GetMaxSlotNumber() + { + List keys = new List(Keys); + if(0 == keys.Count) + { + return -1; // if there are no slots then return -1 + } + return keys.Max(); + } + public int GetCount() { int positionCount=0; diff --git a/MarketDataLib/Generator/MGSHMomentum/MGSHBacktest.cs b/MarketDataLib/Generator/MGSHMomentum/MGSHBacktest.cs index 7b26d7e..d289ab1 100644 --- a/MarketDataLib/Generator/MGSHMomentum/MGSHBacktest.cs +++ b/MarketDataLib/Generator/MGSHMomentum/MGSHBacktest.cs @@ -229,7 +229,7 @@ namespace MarketData.Generator.MGSHMomentum // **************************************************************** S T A T I S T I C S ****************************************************************** // ****************************************************************************************************************************************************** -// Calcualtes the expectation for the model ( Percent of Winning Trades * Average Gain)/(Percent Losing Trades * Average Loss) +// Calculates the expectation for the model ( Percent of Winning Trades * Average Gain)/(Percent Losing Trades * Average Loss) // The expectation should be above zero // Using the AllPositions collection ignored open positions and active hedge positions public static ModelStatistics GetModelStatistics(MGSHSessionParams sessionParams) @@ -298,6 +298,7 @@ namespace MarketData.Generator.MGSHMomentum DateTime minDate=combinedPositions.Min(x => x.PurchaseDate); DateTime maxDate=PricingDA.GetLatestDate(); double prevGainLoss=double.NaN; + LocalPriceCache.GetInstance().RemoveDate(maxDate); List historicalDates=dateGenerator.GenerateHistoricalDates(minDate,maxDate); foreach(DateTime currentDate in historicalDates) @@ -853,8 +854,6 @@ namespace MarketData.Generator.MGSHMomentum foreach(MGSHPosition position in positions) { Price price=GBPriceCache.GetInstance().GetPrice(position.Symbol,analysisDate); -// Incorporate Pricing Exceptions - if(null==price) { int exceptionCount=AddPricingException(position.Symbol); @@ -872,14 +871,12 @@ namespace MarketData.Generator.MGSHMomentum else MDTrace.WriteLine(LogLevel.DEBUG,String.Format("[UpdateStopLimitsForActivePositions] Cannot determine price for {0} on {1}",position.Symbol,analysisDate.ToShortDateString())); continue; } - // This is an older position for which we never set an initial stop. We will not adjust these if (double.IsNaN(position.R) || double.IsNaN(position.TrailingStopLimit) || double.IsNaN(position.InitialStopLimit)) { MDTrace.WriteLine(LogLevel.DEBUG, String.Format("[UpdateStopLimitsForActivePositions] Position {0} on {1} is legacy will not adjust stop limit.", position.Symbol, analysisDate.ToShortDateString())); continue; } - position.CurrentPrice = price.Close; RemovePricingException(position.Symbol); if (price.Low < position.TrailingStopLimit && !position.PurchaseDate.Equals(analysisDate)) @@ -1043,7 +1040,7 @@ namespace MarketData.Generator.MGSHMomentum { MDTrace.WriteLine(LogLevel.DEBUG,String.Format("GetStopLimitWithScalingAverageTrueRange: Symbol:{0}",position.Symbol)); double volatility=double.NaN; - volatility=VolatilityGenerator.CalculateVolatility(position.Symbol,tradeDate,Configuration.StopLimitScalingVolatilityDays); + volatility=VolatilityGenerator.CalculateVolatility(position.Symbol,tradeDate,Configuration.StopLimitScalingVolatilityDays, Configuration.StopLimitATRMultiplier); if(double.IsNaN(volatility)) { MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Unable to calculate AverageTrueRange for {0} on {1}. Using non-scaled stop limit.",position.Symbol,tradeDate.ToShortDateString())); diff --git a/MarketDataLib/Generator/MGSHMomentum/MGSHConfiguration.cs b/MarketDataLib/Generator/MGSHMomentum/MGSHConfiguration.cs index 40e2d7f..69840bc 100644 --- a/MarketDataLib/Generator/MGSHMomentum/MGSHConfiguration.cs +++ b/MarketDataLib/Generator/MGSHMomentum/MGSHConfiguration.cs @@ -22,6 +22,7 @@ namespace MarketData.Generator.MGSHMomentum public int MinDaysBetweenStopAdjustments{get;set;} public int MinDaysBetweenInitialStopAdjustment{get;set;} public int StopLimitPriceTrendDays{get;set;} + public double StopLimitATRMultiplier{get;set;} // Hedging Strategy public bool UseHedging{get;set;} @@ -121,6 +122,7 @@ namespace MarketData.Generator.MGSHMomentum MinDaysBetweenInitialStopAdjustment=30; // 30 Number of days that must elapse before attempting to adjust the stop limit. This is the best setting MinDaysBetweenStopAdjustments=30; // 30 Number of days between stop adjustments. This is after the initial stop is set... of course StopLimitPriceTrendDays=20; // The number of days for which we want to see upward trend before adjusting a subsequent stop limit + StopLimitATRMultiplier=3.00; // the ATR multiplier for setting stop limits on regular positions // Hedging Strategy UseHedging=false; // Flag to control the use of hedging strategy @@ -209,6 +211,7 @@ namespace MarketData.Generator.MGSHMomentum nvpCollection.Add(new NVP("MinDaysBetweenInitialStopAdjustment",MinDaysBetweenInitialStopAdjustment.ToString())); nvpCollection.Add(new NVP("MinDaysBetweenStopAdjustments",MinDaysBetweenStopAdjustments.ToString())); nvpCollection.Add(new NVP("StopLimitPriceTrendDays",StopLimitPriceTrendDays.ToString())); + nvpCollection.Add(new NVP("StopLimitATRMultiplier",StopLimitATRMultiplier.ToString())); nvpCollection.Add(new NVP("UseHedging",UseHedging.ToString())); nvpCollection.Add(new NVP("HedgeBenchmarkSymbol",HedgeBenchmarkSymbol.ToString())); @@ -279,6 +282,10 @@ namespace MarketData.Generator.MGSHMomentum mgConfiguration.MinDaysBetweenInitialStopAdjustment = nvpDictionary["MinDaysBetweenInitialStopAdjustment"].Get(); mgConfiguration.MinDaysBetweenStopAdjustments = nvpDictionary["MinDaysBetweenStopAdjustments"].Get(); mgConfiguration.StopLimitPriceTrendDays = nvpDictionary["StopLimitPriceTrendDays"].Get(); + if(nvpDictionary.ContainsKey("StopLimitATRMultiplier")) + { + mgConfiguration.StopLimitATRMultiplier = nvpDictionary["StopLimitATRMultiplier"].Get(); + } } else { @@ -361,9 +368,11 @@ namespace MarketData.Generator.MGSHMomentum MDTrace.WriteLine(LogLevel.DEBUG,String.Format("UseStopLimits,{0}",UseStopLimits)); MDTrace.WriteLine(LogLevel.DEBUG,String.Format("StopLimitRiskPercentDecimal,{0}",StopLimitRiskPercentDecimal)); MDTrace.WriteLine(LogLevel.DEBUG,String.Format("StopLimitScalingVolatilityDays,{0}",StopLimitScalingVolatilityDays)); + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("MinDaysBetweenInitialStopAdjustment,{0}",MinDaysBetweenInitialStopAdjustment)); MDTrace.WriteLine(LogLevel.DEBUG,String.Format("MinDaysBetweenStopAdjustments,{0}",MinDaysBetweenStopAdjustments)); MDTrace.WriteLine(LogLevel.DEBUG,String.Format("StopLimitPriceTrendDays,{0}",StopLimitPriceTrendDays)); + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("StopLimitATRMultiplier,{0}",StopLimitATRMultiplier)); MDTrace.WriteLine(LogLevel.DEBUG,String.Format("UseHedging,{0}",UseHedging)); MDTrace.WriteLine(LogLevel.DEBUG,String.Format("HedgeBenchmarkSymbol,{0}",HedgeBenchmarkSymbol));