Changes to support MGSHMomentumView

This commit is contained in:
2025-02-10 08:02:49 -05:00
parent 549f9ca7d1
commit 230d84904a
10 changed files with 324 additions and 436 deletions

View File

@@ -26,6 +26,9 @@ using MarketData.Generator.Momentum;
using TradeBlotter.UIUtils;
using MarketData.Generator.Model;
using MarketData.Generator.MGSHMomentum;
using MarketData.Generator.Interface;
using StopLimit=MarketData.MarketDataModel.StopLimit;
using TradeBlotter.Extensions;
namespace TradeBlotter.ViewModels
{
@@ -88,6 +91,8 @@ namespace TradeBlotter.ViewModels
private RelayCommand movingAverageCommandPosition;
private RelayCommand displayHistoricalCommandPosition;
private RelayCommand displayHeadlinesCommandPosition;
private RelayCommand editPositionCommandPosition;
// chart plotter
private bool showAsGainLoss=true;
private bool isLegendVisible=false;
@@ -157,7 +162,10 @@ namespace TradeBlotter.ViewModels
// **************************************************************************************************************************************************************************
public bool BusyIndicator
{
get { return busyIndicator; }
get
{
return busyIndicator;
}
set
{
busyIndicator = value;
@@ -166,8 +174,15 @@ namespace TradeBlotter.ViewModels
}
public String BusyContent
{
get{return busyContent;}
set{busyContent=value;base.OnPropertyChanged("BusyContent");}
get
{
return busyContent;
}
set
{
busyContent=value;
base.OnPropertyChanged("BusyContent");
}
}
// **************************************************************************************************************************************************************************
public ObservableCollection<MenuItem> CandidateMenuItems
@@ -210,12 +225,15 @@ 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="Edit Position...",MenuItemClickedCommand=EditPosition,StaysOpenOnClick=false });
return collection;
}
}
private void OnMomentumViewModelPropertyChanged(object sender, PropertyChangedEventArgs eventArgs)
{
}
// ************************************************************************************************************************************************
// ************************************************************************************************************************************************
// ************************************************************************************************************************************************
@@ -224,9 +242,8 @@ namespace TradeBlotter.ViewModels
get
{
if(null==pathFileName)return "MGSHMomentum Model";
String fileName=Path.GetFileName(pathFileName);
fileName=Utility.BetweenString(fileName,null,".");
return "MGSHMomentum Model ("+fileName+")";
String pureFileName = Utility.GetFileNameNoExtension(pathFileName);
return "MGSHMomentum Model ("+pureFileName+")";
}
}
public override String Title
@@ -836,6 +853,22 @@ namespace TradeBlotter.ViewModels
return removeFromWatchListCommandPosition;
}
}
public ICommand EditPosition
{
get
{
if(editPositionCommandPosition==null)
{
editPositionCommandPosition=new RelayCommand(param => this.EditPositionCommand(selectedPosition),param =>
{
if(null==selectedPosition||null==selectedPosition.Symbol||!Utility.IsEpoch(selectedPosition.SellDate)) return false;
return true;
});
}
return editPositionCommandPosition;
}
}
// *************************************************************************************************************************************************************
// ******************************************************************* I C O M M A N D S E S S I O N *********************************************************
// *************************************************************************************************************************************************************
@@ -919,57 +952,74 @@ namespace TradeBlotter.ViewModels
saveParams.Referer=this;
WorkspaceInstantiator.Invoke(saveParams);
}
// *************************************************************************************************************************************************************
// ********************************************************************** C O M M A N D W O R K E R S P O S I T I O N ****************************************
// *************************************************************************************************************************************************************
//public void DisplayBollingerBandCommandPosition()
//{
// SaveParameters saveParams = SaveParameters.Parse("Type,TradeBlotter.ViewModels.BollingerBandViewModel,SelectedSymbol," + selectedPosition.Symbol + ",SelectedWatchList,{All},SelectedDayCount,90");
// saveParams.Referer=this;
// WorkspaceInstantiator.Invoke(saveParams);
//}
// *************************************************************************************************************************************************************
// ********************************************************************** C O M M A N D W O R K E R S P O S I T I O N ****************************************
// *************************************************************************************************************************************************************
public void EditPositionCommand(MGSHPositionModel selectedPosition)
{
MGSHPosition clonedPosition = MGSHPosition.Clone(selectedPosition.Position);
IPosition changedPosition = EditPositionDialog.Prompt("Edit Position", clonedPosition);
if (null == changedPosition) return;
MGSHMomentumBacktest mgshMomentumBacktest = new MGSHMomentumBacktest();
if (!mgshMomentumBacktest.EditPosition(changedPosition.Symbol, changedPosition.PurchaseDate, changedPosition.PurchasePrice, changedPosition.InitialStopLimit, changedPosition.TrailingStopLimit, pathFileName))
{
MessageBox.Show("Failed to edit the position, check log for details.", "Edit Position");
return;
}
if (!selectedPosition.TrailingStopLimit.Equals(changedPosition.TrailingStopLimit))
{
selectedPosition.TrailingStopLimit = changedPosition.TrailingStopLimit;
selectedPosition.LastStopAdjustment = DateTime.Now.Date;
StopLimit stopLimit = PortfolioDA.GetStopLimit(changedPosition.Symbol);
if (null == stopLimit)
{
stopLimit = new StopLimit();
stopLimit.Symbol = changedPosition.Symbol;
stopLimit.StopType = StopLimitConstants.STOP_QUOTE;
stopLimit.Shares = changedPosition.Shares;
}
stopLimit.StopPrice = changedPosition.TrailingStopLimit;
PortfolioDA.InsertUpdateStopLimit(stopLimit);
}
selectedPosition.PurchaseDate = changedPosition.PurchaseDate;
selectedPosition.PurchasePrice = changedPosition.PurchasePrice;
selectedPosition.TrailingStopLimit = changedPosition.TrailingStopLimit;
selectedPosition.InitialStopLimit = changedPosition.InitialStopLimit;
String strMessage = String.Format("Edited Position for {0} Purchase Date:{1} Purchase Price:{2}, Trailing Stop:{3}. A backup was created.",
selectedPosition.Symbol, selectedPosition.PurchaseDate.ToShortDateString(), Utility.FormatCurrency(selectedPosition.PurchasePrice), Utility.FormatCurrency(selectedPosition.TrailingStopLimit));
MessageBox.Show(strMessage, "Edit Position");
}
public void DisplayBollingerBandCommandPosition()
{
String strStopLimits = null;
MarketData.MarketDataModel.StopLimits stopLimits = GetHistoricalStopLimitsMarketDataModel();
StringBuilder sb = new StringBuilder();
if (null != stopLimits && 0 != stopLimits.Count)
{
sb.Append(",");
NVPCollections nvpCollections = stopLimits.ToNVPCollections();
sb.Append("StopHistoryCount").Append(",").Append(String.Format("{0}", nvpCollections.Count)).Append(",");
for (int index = 0; index < nvpCollections.Count; index++)
{
sb.Append(String.Format("StopHistory_{0}", index)).Append(",").Append(nvpCollections[index].ToString());
if (index < nvpCollections.Count - 1) sb.Append(",");
}
}
strStopLimits = sb.ToString();
SaveParameters saveParams = null;
if (null != strStopLimits)
{
sb = new StringBuilder();
sb.Append("Type,TradeBlotter.ViewModels.BollingerBandViewModel,SelectedSymbol,");
sb.Append(selectedPosition.Symbol).Append(",");
sb.Append("SelectedWatchList,{All},SelectedDayCount,");
sb.Append(GetDayCountSelectionForBollingerBands(selectedPosition));
sb.Append(String.IsNullOrEmpty(strStopLimits) ? "" : strStopLimits);
saveParams = SaveParameters.Parse(sb.ToString());
} else
{
saveParams = SaveParameters.Parse("Type,TradeBlotter.ViewModels.BollingerBandViewModel,SelectedSymbol," + selectedPosition.Symbol + ",SelectedWatchList,{All},SelectedDayCount,90");
}
sb = new StringBuilder();
sb.Append("Type,TradeBlotter.ViewModels.BollingerBandPositionViewModel,SelectedSymbol,");
sb.Append(selectedPosition.Symbol).Append(",");
sb.Append("SelectedWatchList,{All},SelectedDayCount,");
sb.Append(GetDayCountSelectionForBollingerBands(selectedPosition));
saveParams = SaveParameters.Parse(sb.ToString());
SaveParameters stopLimitParams = StopLimitsExtensions.FromStopLimits(stopLimits);
saveParams.AddRange(stopLimitParams);
SaveParameters portfolioTradesParams = PortfolioTradesExtensions.FromPosition(selectedPosition);
saveParams.AddRange(portfolioTradesParams);
saveParams.Referer=this;
WorkspaceInstantiator.Invoke(saveParams);
}
private int GetDayCountSelectionForBollingerBands(MGSHPositionModel selectedPosition)
{
DateGenerator dateGenerator=new DateGenerator();
int daysBetween=dateGenerator.DaysBetween(selectedPosition.PurchaseDate,DateTime.Today);
DateTime maxDate = PricingDA.GetLatestDate(selectedPosition.Symbol);
if(!selectedPosition.IsActivePosition)
{
maxDate = selectedPosition.SellDate;
}
int daysBetween=dateGenerator.DaysBetween(selectedPosition.PurchaseDate, maxDate);
if(daysBetween<90)return 90;
if(daysBetween<180)return 180;
if(daysBetween<360)return 360;
@@ -978,8 +1028,6 @@ namespace TradeBlotter.ViewModels
return 3600;
}
public void DisplayAnalystRatingsCommandPosition()
{
SaveParameters saveParams = SaveParameters.Parse("Type,TradeBlotter.ViewModels.AnalystRatingsViewModel,SelectedSymbol," + selectedPosition.Symbol + ",SelectedWatchList,{All}");
@@ -1157,28 +1205,51 @@ namespace TradeBlotter.ViewModels
}
else LoadSessionFile();
}
public bool LoadSessionFile()
{
try
BusyIndicator = true;
BusyContent = $"Loading {Utility.GetFileNameNoExtension(pathFileName)}...";
Task workerTask = Task.Factory.StartNew(() =>
{
if(!MGSHSessionManager.IsValidSessionFile(pathFileName))return false;
initialPath=Path.GetDirectoryName(pathFileName);
sessionParams=MGSHSessionManager.RestoreSession(pathFileName);
if(null==sessionParams){ MessageBox.Show(String.Format("Unable to open {0}",pathFileName));pathFileName=null;return false;}
modelStatistics=MGSHMomentumBacktest.GetModelStatistics(sessionParams);
modelPerformanceSeries=MGSHMomentumBacktest.GetModelPerformance(sessionParams);
configuration=sessionParams.Configuration;
NVPCollection nvpCollection=sessionParams.Configuration.ToNVPCollection();
nvpDictionary=nvpCollection.ToDictionary();
nvpDictionaryKeys=new ObservableCollection<String>(nvpDictionary.Keys);
selectedParameter=nvpDictionaryKeys[0];
positions=new MGSHPositionModelCollection();
positions.Add(sessionParams.ActivePositions); // active positions will go into their assigned slot
positions.Add(sessionParams.AllPositions);
// positions.Add(sessionParams.HedgePositions, -1); // hedge positions will go into slot -1
UpdatePositionPrices(false);
UpdatePositionRSI3(true);
RunPerformance();
try
{
if(!MGSHSessionManager.IsValidSessionFile(pathFileName))return false;
initialPath=Path.GetDirectoryName(pathFileName);
sessionParams=MGSHSessionManager.RestoreSession(pathFileName);
if(null==sessionParams)
{
MessageBox.Show(String.Format("Unable to open {0}",pathFileName));
pathFileName=null;
return false;
}
modelStatistics=MGSHMomentumBacktest.GetModelStatistics(sessionParams);
modelPerformanceSeries=MGSHMomentumBacktest.GetModelPerformance(sessionParams);
configuration=sessionParams.Configuration;
NVPCollection nvpCollection=sessionParams.Configuration.ToNVPCollection();
nvpDictionary=nvpCollection.ToDictionary();
nvpDictionaryKeys=new ObservableCollection<String>(nvpDictionary.Keys);
selectedParameter=nvpDictionaryKeys[0];
positions=new MGSHPositionModelCollection();
positions.Add(sessionParams.ActivePositions); // active positions will go into their assigned slot
positions.Add(sessionParams.AllPositions);
//// positions.Add(sessionParams.HedgePositions, -1); // hedge positions will go into slot -1
UpdatePositionPrices(false);
UpdatePositionRSI3(true);
RunPerformance();
return true;
}
catch(Exception exception)
{
MessageBox.Show(String.Format("Unable to open {0}",pathFileName));
pathFileName=null;
return false;
}
});
workerTask.ContinueWith(continuation =>
{
BusyIndicator=false;
base.OnPropertyChanged("Parameters");
base.OnPropertyChanged("SelectedParameter");
base.OnPropertyChanged("ParameterValue");
@@ -1191,14 +1262,11 @@ namespace TradeBlotter.ViewModels
base.OnPropertyChanged("ModelExpectation");
base.OnPropertyChanged("ExpectationColor");
base.OnPropertyChanged("ExpectationDescription");
return true;
}
catch(Exception exception)
{
System.Windows.MessageBox.Show(String.Format("Exception {0}",exception.ToString()),"Error",MessageBoxButton.OK,MessageBoxImage.Exclamation);
return false;
}
base.OnPropertyChanged("ReloadEnabled");
});
return true;
}
private void RunPerformance()
{
if(null==sessionParams)return;
@@ -1309,31 +1377,23 @@ namespace TradeBlotter.ViewModels
{
if (null == sessionParams || null == selectedPosition) return null;
DateGenerator dateGenerator = new DateGenerator();
MarketData.MarketDataModel.StopLimits marketDataModelStopLimits = new MarketData.MarketDataModel.StopLimits();
MarketData.Generator.Model.StopLimits stopLimits = default;
if (selectedPosition.IsActivePosition)
{
stopLimits = new MarketData.Generator.Model.StopLimits((from MarketData.Generator.Model.StopLimit stopLimit in sessionParams.StopLimits
where stopLimit.Symbol.Equals(selectedPosition.Symbol) && stopLimit.AnalysisDate > selectedPosition.PurchaseDate select stopLimit).
MarketData.Generator.Model.StopLimits stopLimits =
new MarketData.Generator.Model.StopLimits((from MarketData.Generator.Model.StopLimit stopLimit in sessionParams.StopLimits
where stopLimit.StopLimitId.Equals(selectedPosition.Symbol + Utility.DateTimeToStringYYYYMMDDMMSSTT(selectedPosition.PurchaseDate)) select stopLimit).
OrderByDescending(x => x.AnalysisDate).ToList());
} else
{
stopLimits = new MarketData.Generator.Model.StopLimits((from MarketData.Generator.Model.StopLimit stopLimit in sessionParams.StopLimits
where stopLimit.Symbol.Equals(selectedPosition.Symbol) && stopLimit.AnalysisDate > selectedPosition.PurchaseDate
&& stopLimit.AnalysisDate <= selectedPosition.SellDate select stopLimit).
OrderByDescending(x => x.AnalysisDate).ToList());
}
MarketData.MarketDataModel.StopLimit initialStopLimit = new MarketData.MarketDataModel.StopLimit();
initialStopLimit.Symbol = selectedPosition.Symbol;
initialStopLimit.Shares = 0;
initialStopLimit.StopPrice = selectedPosition.InitialStopLimit;
initialStopLimit.StopType = StopLimitConstants.STOP_QUOTE;
initialStopLimit.EffectiveDate = dateGenerator.FindNextBusinessDay(selectedPosition.PurchaseDate);
initialStopLimit.EffectiveDate = selectedPosition.PurchaseDate;
initialStopLimit.Active = 1;
marketDataModelStopLimits.Add(initialStopLimit);
foreach (MarketData.Generator.Model.StopLimit stopLimit in stopLimits)
{
MarketData.MarketDataModel.StopLimit marketDataModelStopLimit = new MarketData.MarketDataModel.StopLimit();
@@ -1345,11 +1405,64 @@ namespace TradeBlotter.ViewModels
marketDataModelStopLimit.Active = 1;
marketDataModelStopLimits.Add(marketDataModelStopLimit);
}
return marketDataModelStopLimits;
}
// ****************************************************************************************************************************************************************
// *************************************************************************** T O O L T I P C A L L O U T S *****************************************************
// ****************************************************************************************************************************************************************
public String ToolTipTrailingStop
{
get
{
StringBuilder sb=new StringBuilder();
if(null==selectedPosition) return "Please select a position by clicking on a row.";
sb.Append("[TrailingStop]=([TrailingStopLimit])").Append("\n");
sb.Append(Utility.FormatCurrency(selectedPosition.TrailingStopLimit)).Append("=").Append(Utility.FormatCurrency(selectedPosition.TrailingStopLimit)).Append("\n");
List<MarketData.Generator.Model.StopLimit> stopLimits=GetHistoricalStopLimits();
if(selectedPosition.TrailingStopLimit > selectedPosition.PurchasePrice)
{
sb.Append("Riskless Gain").Append(" = ");
sb.Append(String.Format("(Trailing Stop - Purchase Price) * Shares"));
sb.Append("\n");
sb.Append(String.Format("{0}",Utility.FormatCurrency((selectedPosition.TrailingStopLimit-selectedPosition.PurchasePrice)*selectedPosition.Shares)));
sb.Append(String.Format("=({0}-{1})*{2}",Utility.FormatCurrency(selectedPosition.TrailingStopLimit),Utility.FormatCurrency(selectedPosition.PurchasePrice),Utility.FormatNumber(selectedPosition.Shares,3)));
sb.Append("\n");
}
if(null!=stopLimits && 0!=stopLimits.Count)
{
sb.Append("Stop History").Append("\n");
foreach(MarketData.Generator.Model.StopLimit stopLimit in stopLimits)
{
sb.Append(String.Format("Analysis Date:{0} New Stop:{1} Previous Stop:{2}",Utility.DateTimeToStringMMSDDSYYYY(stopLimit.AnalysisDate),Utility.FormatCurrency(stopLimit.NewStop),Utility.FormatCurrency(stopLimit.PreviousStop)));
sb.Append("\n");
}
}
return sb.ToString();
}
}
public String ToolTipInitialStop
{
get
{
StringBuilder sb=new StringBuilder();
if(null==selectedPosition) return "Please select a position by clicking on a row.";
sb.Append("[InitialStop]=([InitialStopLimit])").Append("\n");
sb.Append(Utility.FormatCurrency(selectedPosition.InitialStopLimit)).Append("=").Append(Utility.FormatCurrency(selectedPosition.InitialStopLimit));
return sb.ToString();
}
}
// ************************************************************** T O O L T I P H E L P E R S **************************************************************
public MarketData.Generator.Model.StopLimits GetHistoricalStopLimits()
{
if(null==sessionParams||null==selectedPosition) return null;
MarketData.Generator.Model.StopLimits stopLimits=new MarketData.Generator.Model.StopLimits(
(from MarketData.Generator.Model.StopLimit stopLimit in sessionParams.StopLimits where stopLimit.StopLimitId.Equals(selectedPosition.Symbol + Utility.DateTimeToStringYYYYMMDDMMSSTT(selectedPosition.PurchaseDate)) select stopLimit)
.OrderByDescending(x => x.AnalysisDate).ToList());
return stopLimits;
}
}
}