From ac739d57f4ba023e0d86ebc527267f89bcabf7f1 Mon Sep 17 00:00:00 2001 From: Sean Date: Mon, 4 Aug 2025 22:21:48 -0400 Subject: [PATCH] Fix MGSHBacktest Edit/Close hedge positions. --- MarketDataLib/DataAccess/HolidayDA.cs | 8 +++---- .../Generator/MGSHMomentum/MGSHBacktest.cs | 24 ++++++++++++++++--- 2 files changed, 25 insertions(+), 7 deletions(-) diff --git a/MarketDataLib/DataAccess/HolidayDA.cs b/MarketDataLib/DataAccess/HolidayDA.cs index a242bd2..f13a266 100644 --- a/MarketDataLib/DataAccess/HolidayDA.cs +++ b/MarketDataLib/DataAccess/HolidayDA.cs @@ -25,7 +25,7 @@ namespace MarketData.DataAccess { StringBuilder sb=new StringBuilder(); sqlConnection=SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); - sb.Append("select description from MarketHolidays where date='").Append(Utils.SqlUtils.SqlDate(date)).Append("'"); + sb.Append("select description from marketholidays where date='").Append(Utils.SqlUtils.SqlDate(date)).Append("'"); strQuery=sb.ToString(); sqlCommand=new MySqlCommand(strQuery,sqlConnection); sqlCommand.CommandTimeout=SqlUtils.COMMAND_TIMEOUT; @@ -60,7 +60,7 @@ namespace MarketData.DataAccess { StringBuilder sb=new StringBuilder(); sqlConnection=SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); - sb.Append("select max(date) from MarketHolidays"); + sb.Append("select max(date) from marketholidays"); strQuery=sb.ToString(); sqlCommand=new MySqlCommand(strQuery,sqlConnection); sqlCommand.CommandTimeout=SqlUtils.COMMAND_TIMEOUT; @@ -96,7 +96,7 @@ namespace MarketData.DataAccess { StringBuilder sb=new StringBuilder(); sqlConnection=SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); - sb.Append("select count(*) from MarketHolidays where date='").Append(Utility.DateTimeToStringYYYYHMMHDD(date)).Append("' "); + sb.Append("select count(*) from marketholidays where date='").Append(Utility.DateTimeToStringYYYYHMMHDD(date)).Append("' "); strQuery=sb.ToString(); sqlCommand=new MySqlCommand(strQuery,sqlConnection); sqlCommand.CommandTimeout=SqlUtils.COMMAND_TIMEOUT; @@ -131,7 +131,7 @@ namespace MarketData.DataAccess { StringBuilder sb=new StringBuilder(); sqlConnection=SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); - sb.Append("select date from MarketHolidays order by date desc"); + sb.Append("select date from marketholidays order by date desc"); strQuery=sb.ToString(); sqlCommand=new MySqlCommand(strQuery,sqlConnection); sqlCommand.CommandTimeout=SqlUtils.COMMAND_TIMEOUT; diff --git a/MarketDataLib/Generator/MGSHMomentum/MGSHBacktest.cs b/MarketDataLib/Generator/MGSHMomentum/MGSHBacktest.cs index 182e6ea..e040d0f 100644 --- a/MarketDataLib/Generator/MGSHMomentum/MGSHBacktest.cs +++ b/MarketDataLib/Generator/MGSHMomentum/MGSHBacktest.cs @@ -103,10 +103,12 @@ namespace MarketData.Generator.MGSHMomentum if(!BackupSession())return false; MGSHPositions activePositions = ActivePositions.GetPositions(); MGSHPosition position = activePositions.Where(x => x.Symbol.Equals(symbol) && x.PurchaseDate.Equals(purchaseDate)).FirstOrDefault(); + bool isHedgePosition=false; if (null == position) { MGSHPositions hedgePositions = HedgePositions; position = hedgePositions.Where(x => x.Symbol.Equals(symbol) && x.PurchaseDate.Equals(purchaseDate)).FirstOrDefault(); + isHedgePosition=true; if(null == position) { MDTrace.WriteLine(LogLevel.DEBUG, String.Format("Cannot locate position for symbol '{0}' purchased on {1}.", symbol, purchaseDate.ToShortDateString())); @@ -120,7 +122,8 @@ namespace MarketData.Generator.MGSHMomentum { MDTrace.WriteLine(LogLevel.DEBUG, String.Format("Adjusting Cash for Position for symbol '{0}' purchased on {1}. Original Price: {2} New Price: {3} Change in Cash: {4}", symbol, purchaseDate.ToShortDateString(), Utility.FormatCurrency(position.PurchasePrice), Utility.FormatCurrency(purchasePrice), Utility.FormatCurrency((position.PurchasePrice - purchasePrice) * position.Shares))); MDTrace.WriteLine(LogLevel.DEBUG, String.Format("Adjusting R for Position for symbol '{0}' purchased on {1}. Original R: {2} New R: {3} ", symbol, purchaseDate.ToShortDateString(), Utility.FormatNumber(position.R, 2), Utility.FormatNumber(position.PositionRiskPercentDecimal * purchasePrice))); - CashBalance += (position.PurchasePrice - purchasePrice) * position.Shares; + if(isHedgePosition)HedgeCashBalance += (position.PurchasePrice - purchasePrice) * position.Shares; + else CashBalance += (position.PurchasePrice - purchasePrice) * position.Shares; position.Comment = (String.IsNullOrEmpty(position.Comment) ? "" : position.Comment + ".") + String.Format("Price changed on {0} from {1} to {2}", DateTime.Now.ToShortDateString(), Utility.FormatCurrency(position.PurchasePrice), Utility.FormatCurrency(purchasePrice)); position.PurchasePrice = purchasePrice; } @@ -160,6 +163,13 @@ namespace MarketData.Generator.MGSHMomentum MGSHPositions activePositions = ActivePositions.GetPositions(); MGSHPosition position=activePositions.Where(x => x.Symbol.Equals(symbol) && x.PurchaseDate.Equals(purchaseDate)).FirstOrDefault(); + bool isHedgePosition=false; + if(null==position) // It could be an open hedge position that we are closing + { + MGSHPositions hedgePositions = HedgePositions; + position = hedgePositions.Where(x => x.Symbol.Equals(symbol) && x.PurchaseDate.Equals(purchaseDate)).FirstOrDefault(); + isHedgePosition=true; + } if(null==position) // if it is not in the active positions then the position is already closed and we are modifying either the sell date or the sell price { position=AllPositions.Where(x => x.Symbol.Equals(symbol)&&x.PurchaseDate.Equals(purchaseDate)).FirstOrDefault(); @@ -178,8 +188,16 @@ namespace MarketData.Generator.MGSHMomentum position.SellDate=sellDate; position.CurrentPrice=price; position.Comment="Manual close."; - CashBalance+=position.MarketValue; - ActivePositions.Remove(position); + if(isHedgePosition) + { + HedgeCashBalance+=position.MarketValue; + HedgePositions.Remove(position); + } + else + { + CashBalance+=position.MarketValue; + ActivePositions.Remove(position); + } AllPositions.Add(position); MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Position for symbol '{0}' purchased on {1} is now closed.",symbol,purchaseDate.ToShortDateString())); SaveSession();