From 0d8ce7d70ebe7b28fbedf0d287f4bcfb9eb1a175 Mon Sep 17 00:00:00 2001 From: Sean Date: Tue, 11 Feb 2025 19:25:25 -0500 Subject: [PATCH] Add ClosePosition to MGSHMomentumViewModel --- ViewModels/MGSHMomentumViewModel.cs | 95 ++++++++++++++++++++++++++++- 1 file changed, 93 insertions(+), 2 deletions(-) diff --git a/ViewModels/MGSHMomentumViewModel.cs b/ViewModels/MGSHMomentumViewModel.cs index f2f7442..ebaac26 100644 --- a/ViewModels/MGSHMomentumViewModel.cs +++ b/ViewModels/MGSHMomentumViewModel.cs @@ -92,6 +92,7 @@ namespace TradeBlotter.ViewModels private RelayCommand displayHistoricalCommandPosition; private RelayCommand displayHeadlinesCommandPosition; private RelayCommand editPositionCommandPosition; + private RelayCommand closePositionCommandPosition; // chart plotter private bool showAsGainLoss=true; @@ -225,6 +226,7 @@ namespace TradeBlotter.ViewModels collection.Add(new MenuItem() { Text = "Display DCF Valuation", MenuItemClickedCommand = DisplayDCFValuationPosition, StaysOpenOnClick = false }); collection.Add(new MenuItem() { Text = "Add to Watchlist", MenuItemClickedCommand = AddToWatchListPosition, StaysOpenOnClick = false }); collection.Add(new MenuItem() { Text = "Remove from Watchlist", MenuItemClickedCommand = RemoveFromWatchListPosition, StaysOpenOnClick = false }); + collection.Add(new MenuItem() { Text="Close Position...",MenuItemClickedCommand=ClosePosition,StaysOpenOnClick=false }); collection.Add(new MenuItem() { Text="Edit Position...",MenuItemClickedCommand=EditPosition,StaysOpenOnClick=false }); return collection; } @@ -854,6 +856,22 @@ namespace TradeBlotter.ViewModels } } + public ICommand ClosePosition + { + get + { + if(closePositionCommandPosition==null) + { + closePositionCommandPosition=new RelayCommand(param => this.ClosePositionCommand(selectedPosition),param => + { + if(null==selectedPosition||null==selectedPosition.Symbol) return false; + return true; + }); + } + return closePositionCommandPosition; + } + } + public ICommand EditPosition { get @@ -955,6 +973,26 @@ namespace TradeBlotter.ViewModels // ************************************************************************************************************************************************************* // ********************************************************************** C O M M A N D W O R K E R S P O S I T I O N **************************************** // ************************************************************************************************************************************************************* + public void ClosePositionCommand(MGSHPositionModel selectedPosition) + { + bool deleteStop=false; + MGSHPosition clonedPosition=MGSHPosition.Clone(selectedPosition.Position); + bool hasStopLimit=PortfolioDA.HasStopLimit(clonedPosition.Symbol); + IPosition changedPosition=ClosePositionDialog.Prompt("Close Position",clonedPosition,hasStopLimit,ref deleteStop); + if(null==changedPosition) return; + MGSHMomentumBacktest mgshMomentumBacktest = new MGSHMomentumBacktest(); + if(!mgshMomentumBacktest.ClosePosition(changedPosition.Symbol,changedPosition.PurchaseDate,changedPosition.SellDate,changedPosition.CurrentPrice,pathFileName)) + { + MessageBox.Show("Failed to close the position, check log for details.","Close Position"); + return; + } + if(deleteStop) PortfolioDA.DeleteStopLimit(changedPosition.Symbol); + String strMessage=String.Format("Closed position for {0}, Purchase Date:{1}, Sell Date{2}, Current Price:{3}, Delete Stop:{4} to {5}. A backup was created.", + changedPosition.Symbol,changedPosition.PurchaseDate.ToShortDateString(),changedPosition.SellDate.ToShortDateString(),Utility.FormatCurrency(changedPosition.CurrentPrice),deleteStop,pathFileName); + MessageBox.Show(strMessage,"Close Position"); + LoadSessionFile(); + } + public void EditPositionCommand(MGSHPositionModel selectedPosition) { MGSHPosition clonedPosition = MGSHPosition.Clone(selectedPosition.Position); @@ -1416,8 +1454,8 @@ namespace TradeBlotter.ViewModels { get { - StringBuilder sb=new StringBuilder(); if(null==selectedPosition) return "Please select a position by clicking on a row."; + StringBuilder sb=new StringBuilder(); sb.Append("[TrailingStop]=([TrailingStopLimit])").Append("\n"); sb.Append(Utility.FormatCurrency(selectedPosition.TrailingStopLimit)).Append("=").Append(Utility.FormatCurrency(selectedPosition.TrailingStopLimit)).Append("\n"); List stopLimits=GetHistoricalStopLimits(); @@ -1446,14 +1484,67 @@ namespace TradeBlotter.ViewModels { get { - StringBuilder sb=new StringBuilder(); if(null==selectedPosition) return "Please select a position by clicking on a row."; + StringBuilder sb=new StringBuilder(); sb.Append("[InitialStop]=([InitialStopLimit])").Append("\n"); sb.Append(Utility.FormatCurrency(selectedPosition.InitialStopLimit)).Append("=").Append(Utility.FormatCurrency(selectedPosition.InitialStopLimit)); return sb.ToString(); } } + public String ToolTipR + { + get + { + if(null==selectedPosition)return "Please select a position by clicking on a row."; + StringBuilder sb=new StringBuilder(); + sb.Append("Current R/Share. See RMultiple for initial risk assumptions.").Append("\n"); + sb.Append("R/Share=TrailingStop>PurchasePrice?0.00:PurchasePrice-TrailingStop").Append("\n"); + if(selectedPosition.TrailingStopLimit>selectedPosition.PurchasePrice) + { + sb.Append(Utility.FormatCurrency(0)).Append("=").Append(Utility.FormatCurrency(0)); + } + else + { + sb.Append(Utility.FormatCurrency(selectedPosition.TrailingStopLimit>selectedPosition.PurchasePrice?0.00:selectedPosition.PurchasePrice-selectedPosition.TrailingStopLimit)); + sb.Append("=").Append(Utility.FormatCurrency(selectedPosition.PurchasePrice)).Append("-").Append(Utility.FormatCurrency(selectedPosition.TrailingStopLimit)); + } + return sb.ToString(); + } + } + + public String ToolTipTotalRiskExposure + { + get + { + if(null==selectedPosition)return "Please select a position by clicking on a row."; + StringBuilder sb=new StringBuilder(); + sb.Append("Current Risk. See RMultiple for initial risk assumptions.").Append("\n"); + sb.Append("[TotalRiskExposure]=([R/Share]*[Shares])").Append("\n"); + if(null==selectedPosition) return sb.ToString(); + sb.Append(Utility.FormatCurrency(selectedPosition.TotalRiskExposure)).Append("=(").Append(Utility.FormatCurrency(selectedPosition.R)).Append("*").Append(Utility.FormatNumber(selectedPosition.Shares,0)).Append(")"); + return sb.ToString(); + } + } + + public String ToolTipRMultiple + { + get + { + StringBuilder sb=new StringBuilder(); + sb.Append("RMultiple is based on original position setup.").Append("\n"); + sb.Append("Original Exposure=").Append(Utility.FormatCurrency(selectedPosition.PurchasePrice*selectedPosition.Shares)).Append("\n"); + sb.Append("Original R/Share=PurchasePrice-InitialStop").Append("\n"); + sb.Append(Utility.FormatCurrency(selectedPosition.PurchasePrice-selectedPosition.InitialStopLimit)).Append("=").Append(Utility.FormatCurrency(selectedPosition.PurchasePrice)).Append("-").Append(Utility.FormatCurrency(selectedPosition.InitialStopLimit)).Append("\n"); + sb.Append("Original Risk=Original R/Share*Shares").Append("\n"); + sb.Append(Utility.FormatCurrency((selectedPosition.PurchasePrice-selectedPosition.InitialStopLimit)*selectedPosition.Shares)).Append("=").Append(Utility.FormatCurrency(selectedPosition.PurchasePrice-selectedPosition.InitialStopLimit)).Append("*").Append(selectedPosition.Shares).Append("\n"); + sb.Append("RMultiple=(CurrentPrice-PurchasePrice)/(PurchasePrice-InitialStop)").Append("\n"); + sb.Append(selectedPosition.RMultipleAsString).Append("=").Append("(").Append(Utility.FormatCurrency(selectedPosition.CurrentPrice)).Append("-").Append(Utility.FormatCurrency(selectedPosition.PurchasePrice)).Append(")"); + sb.Append("/").Append("(").Append(Utility.FormatCurrency(selectedPosition.PurchasePrice)).Append("-").Append(Utility.FormatCurrency(selectedPosition.InitialStopLimit)).Append(")"); + return sb.ToString(); + } + } + // ************************************************************** T O O L T I P H E L P E R S ************************************************************** public MarketData.Generator.Model.StopLimits GetHistoricalStopLimits() {