diff --git a/MarketDataLib/Generator/MGSHMomentum/HedgeManager.cs b/MarketDataLib/Generator/MGSHMomentum/HedgeManager.cs index e58c56b..384a02b 100644 --- a/MarketDataLib/Generator/MGSHMomentum/HedgeManager.cs +++ b/MarketDataLib/Generator/MGSHMomentum/HedgeManager.cs @@ -95,6 +95,134 @@ namespace MarketData.Generator.MGSHMomentum return false; } + /// + /// Mainains and adjusts the stop limits for teh hedge position + /// + /// + /// + /// + /// + public StopLimit EvaluateStopPriceHedge(DateTime analysisDate, MGSHPosition position, MGSHConfiguration configuration) + { + DateGenerator dateGenerator=new DateGenerator(); + Price currentPrice=GBPriceCache.GetInstance().GetPrice(position.Symbol,analysisDate); + double trailingStop=position.InitialStopLimit+Math.Floor((currentPrice.Low-position.PurchasePrice)/position.R)*position.R; + double trailingStopScaled=trailingStop; + double daysHeld=Math.Abs(dateGenerator.DaysBetweenActual(position.PurchaseDate,analysisDate)); + + if(Utility.IsEpoch(position.LastStopAdjustment)) // we've never adjusted the stop price + { + BollingerBandElementsByDate bollingerBandElementsByDate = GetBollingerBandElementsByDate(analysisDate); + if(null == bollingerBandElementsByDate)return null; + trailingStopScaled=GetHedgeStopLimitWithScalingAverageTrueRange(analysisDate,currentPrice,position,trailingStop, configuration.StopLimitScalingVolatilityDays, configuration.HedgeATRMultiplier); + trailingStop=Math.Max(trailingStop,trailingStopScaled); + if(trailingStop >= currentPrice.Low || trailingStop >= currentPrice.Close) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("The calculated trailing stop for {0} of {1} would be higher than the Low/Close of {2}.", + position.Symbol, + Utility.FormatCurrency(trailingStop), + Utility.FormatCurrency(currentPrice.Low))); + return null; + } + if(Numerics.Round(trailingStop) <= (Numerics.Round(position.TrailingStopLimit))) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("The calculated trailing stop for {0} of {1} would be less than or equal to the existing stop limit of {2}.", + position.Symbol, + Utility.FormatCurrency(trailingStop), + Utility.FormatCurrency(position.TrailingStopLimit))); + return null; + } + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("****************************** A D J U S T S T O P L I M I T ************************")); + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Adjusting StopLimit on {0} after {1} days for {2} from {3} to {4}. Purchase Price: {5} Current Price:{6} Spread:{7} Shares:{8}", + analysisDate.ToShortDateString(), + daysHeld, + position.Symbol, + Utility.FormatCurrency(position.TrailingStopLimit), + Utility.FormatCurrency(trailingStop), + Utility.FormatCurrency(position.PurchasePrice), + Utility.FormatCurrency(currentPrice.Close), + Utility.FormatPercent((currentPrice.Close-trailingStop)/trailingStop), + Utility.FormatNumber(position.Shares,2))); + + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("*****************************************************************************************")); + StopLimit newStopLimit=new StopLimit + { + StopLimitId=position.Symbol + Utility.DateTimeToStringYYYYMMDDMMSSTT(position.PurchaseDate), + Symbol=position.Symbol, + AnalysisDate=analysisDate, + PreviousStop=0.00==position.TrailingStopLimit?position.InitialStopLimit:position.TrailingStopLimit, + NewStop=trailingStop, + CurrentPriceLow=currentPrice.Low, + CurrentPriceClose=currentPrice.Close, + PriceTrendIndicatorSlope=0.00 + }; + position.TrailingStopLimit=trailingStop; + position.LastStopAdjustment=analysisDate; + return newStopLimit; + } + else // we have already made prior stop adjustments + { + int daysSinceLastStopAdjustment=Math.Abs(dateGenerator.DaysBetweenActual(position.LastStopAdjustment,analysisDate)); + if(daysSinceLastStopAdjustment>=configuration.HedgeMinDaysBetweenStopAdjustments) + { + trailingStopScaled=GetHedgeStopLimitWithScalingAverageTrueRange(analysisDate,currentPrice,position,trailingStop,daysSinceLastStopAdjustment,configuration.HedgeATRMultiplier); + trailingStop=Math.Max(trailingStop,trailingStopScaled); + if(trailingStop>=currentPrice.Low||trailingStop>=currentPrice.Close) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("The calculated trailing stop for {0} of {1} would be higher than the Low/Close of {2}.",position.Symbol,Utility.FormatCurrency(trailingStop),Utility.FormatCurrency(currentPrice.Low))); + return null; + } + if(Numerics.Round(position.TrailingStopLimit) < Numerics.Round(trailingStop)) // round the stop limits to fractionals don't look like differences + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("****************************** A D J U S T S T O P L I M I T ************************")); + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Adjusting StopLimit on {0} after {1} days for {2} from {3} to {4}. Purchase Price: {5} Current Price:{6} Spread:{7} Shares:{8}", + analysisDate.ToShortDateString(), + daysHeld, + position.Symbol, + Utility.FormatCurrency(position.TrailingStopLimit), + Utility.FormatCurrency(trailingStop), + Utility.FormatCurrency(position.PurchasePrice), + Utility.FormatCurrency(currentPrice.Close), + Utility.FormatPercent((currentPrice.Close-trailingStop)/trailingStop), + Utility.FormatNumber(position.Shares,2))); + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("****************************************************************************************")); + StopLimit newStopLimit=new StopLimit + { + StopLimitId=position.Symbol + Utility.DateTimeToStringYYYYMMDDMMSSTT(position.PurchaseDate), + Symbol=position.Symbol, + AnalysisDate=analysisDate, + PreviousStop=0.00==position.TrailingStopLimit?position.InitialStopLimit:position.TrailingStopLimit, + NewStop=trailingStop, + CurrentPriceLow=currentPrice.Low, + CurrentPriceClose=currentPrice.Close, + PriceTrendIndicatorSlope=0.00 + }; + position.TrailingStopLimit=trailingStop; + position.LastStopAdjustment=analysisDate; + return newStopLimit; + } + else + { + double currentTrailingStopLimit=Numerics.Round(position.TrailingStopLimit); + double suggestedTrailingStopLimit=Numerics.Round(trailingStop); + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Not Adjusting Stop Limit for {0} because the new trailing stop limit would be less than or equal to the current trailing stop limit. Current Trailing Stop Limit:{1}, Calculated Trailing Stop Limit:{2}.", + position.Symbol, + Utility.FormatCurrency(currentTrailingStopLimit), + Utility.FormatCurrency(suggestedTrailingStopLimit))); + return null; + } + } + else + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("The trailing stop for {0} was adjusted {1} days ago. HedgeMinDaysBetweenStopAdjustments is {2}", + position.Symbol, + daysSinceLastStopAdjustment, + configuration.HedgeMinDaysBetweenStopAdjustments)); + return null; + } + } + } + private int GetCloseLessL(DateTime analysisDate,BollingerBandElementsByDate bollingerBandElementsByDate, int days) { int count=0; @@ -195,176 +323,55 @@ namespace MarketData.Generator.MGSHMomentum return (lowLessLP1 >= days) && (closeLessLP1 >= days); } - private bool CloseGreaterSMAN(DateTime analysisDate, BollingerBandElementsByDate bollingerBandElementsByDate, int days) - { - DateGenerator dateGenerator = new DateGenerator(); - List dates = dateGenerator.GenerateHistoricalDates(analysisDate, days + 1); - dates.RemoveAt(0); - foreach (DateTime date in dates) + private bool CloseGreaterSMAN(DateTime analysisDate, BollingerBandElementsByDate bollingerBandElementsByDate, int days) { - BollingerBandElement bollingerBandElement = bollingerBandElementsByDate[date]; - if (bollingerBandElement.Close > bollingerBandElement.SMAN) return true; - } - return false; - } - - - /// - /// This is used to trigger an adjustment to the stop price. - /// - /// - /// - /// - public bool IsLowerBandBreakIndicator(DateTime analysisDate, MGSHPosition position) - { - BollingerBandElementsByDate bollingerBandElementsByDate = GetBollingerBandElementsByDate(analysisDate); - if (null == bollingerBandElementsByDate) return false; - BollingerBandElement bollingerBandElement = bollingerBandElementsByDate[analysisDate]; - - if (bollingerBandElement.High > bollingerBandElement.K) - { - Display(String.Format("+++ [1] Upper band break detected for {0} on {1} Purchase Date:{2} Purchase Price:{3} Price Close:{4} Price High:{5} Price High(hF):{6} KL1:{7}", - HedgeShortSymbol, - analysisDate.ToShortDateString(), - position.PurchaseDate.ToShortDateString(), - Utility.FormatCurrency(position.PurchasePrice), - Utility.FormatCurrency(bollingerBandElement.Close), - Utility.FormatCurrency(bollingerBandElement.High), - Utility.FormatCurrency(bollingerBandElement.High), - Utility.FormatCurrency(bollingerBandElement.K) - )); - return true; - } - return false; - } - - public StopLimit EvaluateStopPriceHedge(DateTime analysisDate, MGSHPosition position, int hedgeStopLimitScalingVolatilityDays, int hedgeMinDaysBetweenStopAdjustments) - { - DateGenerator dateGenerator=new DateGenerator(); - Price currentPrice=GBPriceCache.GetInstance().GetPrice(position.Symbol,analysisDate); - double trailingStop=position.InitialStopLimit+Math.Floor((currentPrice.Low-position.PurchasePrice)/position.R)*position.R; - double trailingStopScaled=trailingStop; - double daysHeld=Math.Abs(dateGenerator.DaysBetweenActual(position.PurchaseDate,analysisDate)); - - if(Utility.IsEpoch(position.LastStopAdjustment)) // we've never adjusted the stop price + DateGenerator dateGenerator = new DateGenerator(); + List dates = dateGenerator.GenerateHistoricalDates(analysisDate, days + 1); + dates.RemoveAt(0); + foreach (DateTime date in dates) { - BollingerBandElementsByDate bollingerBandElementsByDate = GetBollingerBandElementsByDate(analysisDate); - if(null == bollingerBandElementsByDate)return null; - trailingStopScaled=GetHedgeStopLimitWithScalingAverageTrueRange(analysisDate,currentPrice,position,trailingStop, hedgeStopLimitScalingVolatilityDays); - trailingStop=Math.Max(trailingStop,trailingStopScaled); - if(trailingStop>=currentPrice.Low||trailingStop>=currentPrice.Close) - { - MDTrace.WriteLine(LogLevel.DEBUG,String.Format("The calculated trailing stop for {0} of {1} would be higher than the Low/Close of {2}.", - position.Symbol, - Utility.FormatCurrency(trailingStop), - Utility.FormatCurrency(currentPrice.Low))); - return null; - } - if(Numerics.Round(trailingStop).Equals(Numerics.Round(position.TrailingStopLimit))) - { - MDTrace.WriteLine(LogLevel.DEBUG,String.Format("The calculated trailing stop for {0} of {1} would be the same as the existing stop limit of {2}.", - position.Symbol, - Utility.FormatCurrency(trailingStop), - Utility.FormatCurrency(position.TrailingStopLimit))); - return null; - } - MDTrace.WriteLine(LogLevel.DEBUG,String.Format("****************************** A D J U S T S T O P L I M I T ************************")); - MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Adjusting StopLimit on {0} after {1} days for {2} from {3} to {4}. Purchase Price: {5} Current Price:{6} Spread:{7} Shares:{8}", - analysisDate.ToShortDateString(), - daysHeld, - position.Symbol, - Utility.FormatCurrency(position.TrailingStopLimit), - Utility.FormatCurrency(trailingStop), - Utility.FormatCurrency(position.PurchasePrice), - Utility.FormatCurrency(currentPrice.Close), - Utility.FormatPercent((currentPrice.Close-trailingStop)/trailingStop), - Utility.FormatNumber(position.Shares,2))); - - MDTrace.WriteLine(LogLevel.DEBUG,String.Format("*****************************************************************************************")); - StopLimit newStopLimit=new StopLimit - { - StopLimitId=position.Symbol + Utility.DateTimeToStringYYYYMMDDMMSSTT(position.PurchaseDate), - Symbol=position.Symbol, - AnalysisDate=analysisDate, - PreviousStop=0.00==position.TrailingStopLimit?position.InitialStopLimit:position.TrailingStopLimit, - NewStop=trailingStop, - CurrentPriceLow=currentPrice.Low, - CurrentPriceClose=currentPrice.Close, - PriceTrendIndicatorSlope=0.00 - }; - position.TrailingStopLimit=trailingStop; - position.LastStopAdjustment=analysisDate; - return newStopLimit; - - } - else // we have already made prior stop adjustments - { - int daysSinceLastStopAdjustment=Math.Abs(dateGenerator.DaysBetweenActual(position.LastStopAdjustment,analysisDate)); - if(daysSinceLastStopAdjustment>=hedgeMinDaysBetweenStopAdjustments) - { - trailingStopScaled=GetHedgeStopLimitWithScalingAverageTrueRange(analysisDate,currentPrice,position,trailingStop,daysSinceLastStopAdjustment); - trailingStop=Math.Max(trailingStop,trailingStopScaled); - if(trailingStop>=currentPrice.Low||trailingStop>=currentPrice.Close) - { - MDTrace.WriteLine(LogLevel.DEBUG,String.Format("The calculated trailing stop for {0} of {1} would be higher than the Low/Close of {2}.",position.Symbol,Utility.FormatCurrency(trailingStop),Utility.FormatCurrency(currentPrice.Low))); - return null; - } - if(Numerics.Round(position.TrailingStopLimit) < Numerics.Round(trailingStop)) // round the stop limits to fractionals don't look like differences - { - MDTrace.WriteLine(LogLevel.DEBUG,String.Format("****************************** A D J U S T S T O P L I M I T ************************")); - MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Adjusting StopLimit on {0} after {1} days for {2} from {3} to {4}. Purchase Price: {5} Current Price:{6} Spread:{7} Shares:{8}", - analysisDate.ToShortDateString(), - daysHeld, - position.Symbol, - Utility.FormatCurrency(position.TrailingStopLimit), - Utility.FormatCurrency(trailingStop), - Utility.FormatCurrency(position.PurchasePrice), - Utility.FormatCurrency(currentPrice.Close), - Utility.FormatPercent((currentPrice.Close-trailingStop)/trailingStop), - Utility.FormatNumber(position.Shares,2))); - MDTrace.WriteLine(LogLevel.DEBUG,String.Format("****************************************************************************************")); - StopLimit newStopLimit=new StopLimit - { - Symbol=position.Symbol, - AnalysisDate=analysisDate, - PreviousStop=0.00==position.TrailingStopLimit?position.InitialStopLimit:position.TrailingStopLimit, - NewStop=trailingStop, - CurrentPriceLow=currentPrice.Low, - CurrentPriceClose=currentPrice.Close, - PriceTrendIndicatorSlope=0.00 - }; - position.TrailingStopLimit=trailingStop; - position.LastStopAdjustment=analysisDate; - return newStopLimit; - } - else - { - double currentTrailingStopLimit=Numerics.Round(position.TrailingStopLimit); - double suggestedTrailingStopLimit=Numerics.Round(trailingStop); - MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Not Adjusting Stop Limit for {0} because the new trailing stop limit would be less than or equal to the current trailing stop limit. Current Trailing Stop Limit:{1}, Calculated Trailing Stop Limit:{2}.", - position.Symbol, - Utility.FormatCurrency(currentTrailingStopLimit), - Utility.FormatCurrency(suggestedTrailingStopLimit))); - return null; - } - } - else - { - MDTrace.WriteLine(LogLevel.DEBUG,String.Format("The trailing stop for {0} was adjusted {1} days ago. MinDaysBetweenStopAdjustments is {2}", - position.Symbol, - daysSinceLastStopAdjustment, - hedgeMinDaysBetweenStopAdjustments)); - return null; - } + BollingerBandElement bollingerBandElement = bollingerBandElementsByDate[date]; + if (bollingerBandElement.Close > bollingerBandElement.SMAN) return true; } + return false; } - private double GetHedgeStopLimitWithScalingAverageTrueRange(DateTime analysisDate,Price currentPrice,MGSHPosition position,double stopLimitNonScaled, int stopLimitScalingVolatilityDays) + + /// + /// This is used to trigger an adjustment to the stop price. + /// + /// + /// + /// + public bool IsLowerBandBreakIndicator(DateTime analysisDate, MGSHPosition position) + { + BollingerBandElementsByDate bollingerBandElementsByDate = GetBollingerBandElementsByDate(analysisDate); + if (null == bollingerBandElementsByDate) return false; + BollingerBandElement bollingerBandElement = bollingerBandElementsByDate[analysisDate]; + + if (bollingerBandElement.High > bollingerBandElement.K) + { + Display(String.Format("+++ [1] Upper band break detected for {0} on {1} Purchase Date:{2} Purchase Price:{3} Price Close:{4} Price High:{5} Price High(hF):{6} KL1:{7}", + HedgeShortSymbol, + analysisDate.ToShortDateString(), + position.PurchaseDate.ToShortDateString(), + Utility.FormatCurrency(position.PurchasePrice), + Utility.FormatCurrency(bollingerBandElement.Close), + Utility.FormatCurrency(bollingerBandElement.High), + Utility.FormatCurrency(bollingerBandElement.High), + Utility.FormatCurrency(bollingerBandElement.K) + )); + return true; + } + return false; + } + + private double GetHedgeStopLimitWithScalingAverageTrueRange(DateTime analysisDate,Price currentPrice,MGSHPosition position,double stopLimitNonScaled, int stopLimitScalingVolatilityDays, double hedgeATRMultiplier) { MDTrace.WriteLine(LogLevel.DEBUG,String.Format("GetHedgeStopLimitWithScalingAverageTrueRange: Symbol:{0}",position.Symbol)); double volatility=double.NaN; - volatility=VolatilityGenerator.CalculateVolatility(position.Symbol,analysisDate,stopLimitScalingVolatilityDays, 1.00); + volatility=VolatilityGenerator.CalculateVolatility(position.Symbol,analysisDate,stopLimitScalingVolatilityDays, hedgeATRMultiplier); 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,analysisDate.ToShortDateString())); diff --git a/MarketDataLib/Generator/MGSHMomentum/MGSHBacktest.cs b/MarketDataLib/Generator/MGSHMomentum/MGSHBacktest.cs index dc56128..29c92f9 100644 --- a/MarketDataLib/Generator/MGSHMomentum/MGSHBacktest.cs +++ b/MarketDataLib/Generator/MGSHMomentum/MGSHBacktest.cs @@ -747,17 +747,36 @@ namespace MarketData.Generator.MGSHMomentum position.CurrentPrice = position.TrailingStopLimit; position.Comment = "Closed due to trailing stop."; HedgeCashBalance+=position.MarketValue; - if(HedgeCashBalance>Configuration.HedgeInitialCash) + +// This tries to maintain a 10% margin in the hedge cash + double hedgeCashMarginPercentDecimal=.10; + double hedgeCashTreshholdAmount=Configuration.HedgeInitialCash*(1.00+hedgeCashMarginPercentDecimal); + if(HedgeCashBalance > hedgeCashTreshholdAmount) { - CashBalance+=HedgeCashBalance-Configuration.HedgeInitialCash; // if we made gains on the hedge and the hedge cash would grow then put proceeds above the initial hedge cash in regualr cash - HedgeCashBalance=Configuration.HedgeInitialCash; // For example, let hedge proceeeds help the portfolio invest + DisplayBalance(); + MDTrace.WriteLine(LogLevel.DEBUG,$"The hedge cash balance would be {Utility.FormatCurrency(HedgeCashBalance)}, setting HedgeCashBalance to {Utility.FormatCurrency(hedgeCashTreshholdAmount)} and adding {Utility.FormatCurrency((HedgeCashBalance-hedgeCashTreshholdAmount))} to CashBalance."); + CashBalance += (HedgeCashBalance-hedgeCashTreshholdAmount); + HedgeCashBalance = hedgeCashTreshholdAmount; + DisplayBalance(); } + if(HedgeCashBalance<0.00) + { + HedgeCashBalance=0.00; + } + + //if(HedgeCashBalance>Configuration.HedgeInitialCash) + //{ + // CashBalance+=HedgeCashBalance-Configuration.HedgeInitialCash; // if we made gains on the hedge and the hedge cash would grow then put proceeds above the initial hedge cash in regualr cash + // HedgeCashBalance=Configuration.HedgeInitialCash; // For example, let hedge proceeeds help the portfolio invest + //} + + AllPositions.Add(position); closedPositions.Add(position); } else if(hedgeManager.IsLowerBandBreakIndicator(analysisDate, position)) { - StopLimit stopLimit = hedgeManager.EvaluateStopPriceHedge(analysisDate, position,Configuration.StopLimitScalingVolatilityDays,Configuration.HedgeMinDaysBetweenStopAdjustments); + StopLimit stopLimit = hedgeManager.EvaluateStopPriceHedge(analysisDate, position,Configuration); if(null != stopLimit) { StopLimits.Add(stopLimit); @@ -1363,6 +1382,7 @@ namespace MarketData.Generator.MGSHMomentum Cycle=sessionParams.Cycle; CashBalance=sessionParams.CashBalance; NonTradeableCash=sessionParams.NonTradeableCash; + HedgeCashBalance=sessionParams.HedgeCashBalance; return sessionParams; } catch(Exception exception) @@ -1389,6 +1409,7 @@ namespace MarketData.Generator.MGSHMomentum sessionParams.PricingExceptions=PricingExceptions; sessionParams.CashBalance=CashBalance; sessionParams.NonTradeableCash=NonTradeableCash; + sessionParams.HedgeCashBalance=HedgeCashBalance; sessionManager.SaveSession(sessionParams,PathSessionFileName); } @@ -1412,6 +1433,7 @@ namespace MarketData.Generator.MGSHMomentum sessionParams.PricingExceptions=PricingExceptions; sessionParams.CashBalance=CashBalance; sessionParams.NonTradeableCash=NonTradeableCash; + sessionParams.HedgeCashBalance=HedgeCashBalance; return sessionManager.SaveSession(sessionParams,backupFileName); } } diff --git a/MarketDataLib/Generator/MGSHMomentum/MGSHConfiguration.cs b/MarketDataLib/Generator/MGSHMomentum/MGSHConfiguration.cs index 1d059ae..16d98d7 100644 --- a/MarketDataLib/Generator/MGSHMomentum/MGSHConfiguration.cs +++ b/MarketDataLib/Generator/MGSHMomentum/MGSHConfiguration.cs @@ -12,7 +12,7 @@ namespace MarketData.Generator.MGSHMomentum public int MaxPositions{get;set;} public String NoTradeSymbols{get;set;} public String NoTradeFinancialSymbols{get;set;} - public double InitialCash{get;set;} + public double InitialCash{get;set;} // There is no defaullt for this value. It is supplied to the model at launch time. // Stop Limit Functionality public bool UseStopLimits{get;set;} @@ -28,9 +28,10 @@ namespace MarketData.Generator.MGSHMomentum public String HedgeShortSymbol{get;set;} public double HedgeRiskPercentDecimal{get;set;} public int HedgeMinDaysBetweenStopAdjustments; - public double HedgeInitialCash{get;set;} + public double HedgeInitialCash{get;set;} // There is no default for this value. It is supplied to the model at launch time public int HedgeCloseAboveSMANDays{get;set;} public int HedgeBandBreakCheckDays{get;set;} + public double HedgeATRMultiplier{get;set;} // Manage buying and selling public bool KeepSlotPositions{get;set;} // if this setting is true then we never sell slot positions, allowing the trailing stop to eventually invoke a sell. @@ -120,6 +121,7 @@ namespace MarketData.Generator.MGSHMomentum HedgeMinDaysBetweenStopAdjustments=1; // We use a single day for hedge positions HedgeCloseAboveSMANDays=10; // Part of open hedge indicator if Close is not above Bollinger SMAN for this many days then reject HedgeBandBreakCheckDays=3; // Number of days that low and close must be <= LP1 in order to open hedge. If >= number of days then reject + HedgeATRMultiplier=1.00; // 1.00 produces best results for the hedging stops. The default ATR multiplier in the code Volatility Calculator is 3 which gives a good spread when adjusting stop prices. // Manage buying and selling KeepSlotPositions=true; // The default is true to retain legacy functionality @@ -207,6 +209,7 @@ namespace MarketData.Generator.MGSHMomentum nvpCollection.Add(new NVP("HedgeInitialCash",HedgeInitialCash.ToString())); nvpCollection.Add(new NVP("HedgeCloseAboveSMANDays",HedgeCloseAboveSMANDays.ToString())); nvpCollection.Add(new NVP("HedgeBandBreakCheckDays",HedgeBandBreakCheckDays.ToString())); + nvpCollection.Add(new NVP("HedgeATRMultiplier",HedgeATRMultiplier.ToString())); nvpCollection.Add(new NVP("MaxPricingExceptions",MaxPricingExceptions.ToString())); @@ -281,6 +284,7 @@ namespace MarketData.Generator.MGSHMomentum mgConfiguration.HedgeInitialCash = nvpDictionary["HedgeInitialCash"].Get(); mgConfiguration.HedgeCloseAboveSMANDays = nvpDictionary["HedgeCloseAboveSMANDays"].Get(); mgConfiguration.HedgeBandBreakCheckDays = nvpDictionary["HedgeBandBreakCheckDays"].Get(); + mgConfiguration.HedgeATRMultiplier = nvpDictionary["HedgeATRMultiplier"].Get(); } else { @@ -350,6 +354,7 @@ namespace MarketData.Generator.MGSHMomentum MDTrace.WriteLine(LogLevel.DEBUG, String.Format("HedgeInitialCash,{0}", HedgeInitialCash)); MDTrace.WriteLine(LogLevel.DEBUG, String.Format("HedgeCloseAboveSMANDays,{0}", HedgeCloseAboveSMANDays)); MDTrace.WriteLine(LogLevel.DEBUG, String.Format("HedgeBandBreakCheckDays,{0}", HedgeBandBreakCheckDays)); + MDTrace.WriteLine(LogLevel.DEBUG, String.Format("HedgeATRMultiplier,{0}", HedgeATRMultiplier)); } } }