diff --git a/PortfolioManager/Models/CMTPositionModelCollection.cs b/PortfolioManager/Models/CMTPositionModelCollection.cs index 6ff6005..f3296e6 100644 --- a/PortfolioManager/Models/CMTPositionModelCollection.cs +++ b/PortfolioManager/Models/CMTPositionModelCollection.cs @@ -270,7 +270,7 @@ namespace PortfolioManager.Models { if(!IsActivePosition) return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Blue); if(!Utility.IsEpoch(position.LastStopAdjustment)) return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Black); // if we have a trailing stop then we are no longer using the initial stop - StopLimit stopLimit=StopLimitDA.GetStopLimit(position.Symbol); + StopLimit stopLimit=StopLimitDA.GetStopLimit(position.Symbol,position.Shares); if(null==stopLimit||!stopLimit.StopPrice.Equals(Math.Round(position.InitialStopLimit,2))) return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Purple); if(currentPriceLow<=position.InitialStopLimit) return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Red); return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Black); @@ -295,7 +295,7 @@ namespace PortfolioManager.Models { return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Red); } - StopLimit stopLimit=StopLimitDA.GetStopLimit(position.Symbol); + StopLimit stopLimit=StopLimitDA.GetStopLimit(position.Symbol,position.Shares); if(null==stopLimit || !stopLimit.StopPrice.Equals(Math.Round(position.TrailingStopLimit,2))) { return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Purple); diff --git a/PortfolioManager/Models/GainLossModel.cs b/PortfolioManager/Models/GainLossModel.cs index 98e371d..6ca7c8c 100644 --- a/PortfolioManager/Models/GainLossModel.cs +++ b/PortfolioManager/Models/GainLossModel.cs @@ -36,17 +36,17 @@ namespace PortfolioManager.Models return compositeDataSource; } - public static CompositeDataSource CreateCompositeDataSource(DateTime xSource, double ySource) - { - if (Utility.IsEpoch(xSource)) return Empty(); - SortedDateTimeDataAdapter sortedDateTimeDataAdapter = new SortedDateTimeDataAdapter(); - sortedDateTimeDataAdapter.Add(xSource, ySource); - CompositeDataSource compositeDataSource = new CompositeDataSource() - { - DataAdapter = sortedDateTimeDataAdapter - }; - return compositeDataSource; - } + // public static CompositeDataSource CreateCompositeDataSource(DateTime xSource, double ySource) + // { + // if (Utility.IsEpoch(xSource)) return Empty(); + // SortedDateTimeDataAdapter sortedDateTimeDataAdapter = new SortedDateTimeDataAdapter(); + // sortedDateTimeDataAdapter.Add(xSource, ySource); + // CompositeDataSource compositeDataSource = new CompositeDataSource() + // { + // DataAdapter = sortedDateTimeDataAdapter + // }; + // return compositeDataSource; + // } // This is the active gain/loss as number or percent. public static CompositeDataSource GainLoss(ModelPerformanceSeries gainLossList, bool useGainLoss) diff --git a/PortfolioManager/Models/MGSHPositionModelCollection.cs b/PortfolioManager/Models/MGSHPositionModelCollection.cs index eb2644b..94fe138 100644 --- a/PortfolioManager/Models/MGSHPositionModelCollection.cs +++ b/PortfolioManager/Models/MGSHPositionModelCollection.cs @@ -542,7 +542,7 @@ namespace PortfolioManager.Models { if (!IsActivePosition) return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Blue); if (!Utility.IsEpoch(position.LastStopAdjustment)) return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Black); // if we have a trailing stop then we are no longer using the initial stop - StopLimit stopLimit = StopLimitDA.GetStopLimit(position.Symbol); + StopLimit stopLimit = StopLimitDA.GetStopLimit(position.Symbol,position.Shares); if (null == stopLimit || !stopLimit.StopPrice.Equals(Math.Round(position.InitialStopLimit, 2))) return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Purple); if (currentPriceLow <= position.InitialStopLimit) return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Red); return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Black); @@ -569,7 +569,7 @@ namespace PortfolioManager.Models { return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Red); } - StopLimit stopLimit = StopLimitDA.GetStopLimit(position.Symbol); + StopLimit stopLimit = StopLimitDA.GetStopLimit(position.Symbol,position.Shares); if (null == stopLimit || !stopLimit.StopPrice.Equals(Math.Round(position.TrailingStopLimit, 2))) return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Purple); return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Black); } diff --git a/PortfolioManager/Models/StopLimitCompositeModel.cs b/PortfolioManager/Models/StopLimitCompositeModel.cs index c40fdeb..88fd38b 100644 --- a/PortfolioManager/Models/StopLimitCompositeModel.cs +++ b/PortfolioManager/Models/StopLimitCompositeModel.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Linq; using Eremex.AvaloniaUI.Charts; using MarketData.MarketDataModel; +using MarketData.Utils; using PortfolioManager.DataSeriesViewModels; namespace PortfolioManager.Models @@ -37,5 +38,25 @@ namespace PortfolioManager.Models }; return compositeDataSource; } + + public static CompositeDataSource CreateCompositeDataSource(DateTime xSource,StopLimits stopLimits) + { + if (null == stopLimits || 0 == stopLimits.Count) return Empty(); + foreach(StopLimit stopLimit in stopLimits) + { + stopLimit.EffectiveDate = xSource; + } + SortedDateTimeDataAdapter sortedDateTimeDataAdapter = new SortedDateTimeDataAdapter(); + List sortedStopLimits = stopLimits.OrderBy(x => x.EffectiveDate).ToList(); + foreach (StopLimit stopLimit in sortedStopLimits) + { + sortedDateTimeDataAdapter.Add(stopLimit.EffectiveDate, stopLimit.StopPrice); + } + CompositeDataSource compositeDataSource = new CompositeDataSource() + { + DataAdapter = sortedDateTimeDataAdapter + }; + return compositeDataSource; + } } } \ No newline at end of file diff --git a/PortfolioManager/Renderers/BollingerBandRenderer.cs b/PortfolioManager/Renderers/BollingerBandRenderer.cs index 9fb9dae..4e2f202 100644 --- a/PortfolioManager/Renderers/BollingerBandRenderer.cs +++ b/PortfolioManager/Renderers/BollingerBandRenderer.cs @@ -40,7 +40,7 @@ namespace PortfolioManager.Renderers private bool showInsiderTransactions = true; private bool showLeastSquares = true; private bool syncTradeToBand = true; - private StopLimit stopLimit = default; // StopLimits that the renderer has located using StopLimitDA + private StopLimits internalStopLimits = default; // StopLimits that the renderer has located using StopLimitDA private StopLimits externalStopLimits = default; // StopLimits that are provided to the renderer externally by a model private PortfolioTrades portfolioTrades = default; private PortfolioTrades portfolioTradesLots = default; @@ -97,7 +97,8 @@ namespace PortfolioManager.Renderers MDTrace.WriteLine(LogLevel.DEBUG,$"[SetData] ENTER"); this.selectedSymbol = selectedSymbol; this.selectedDayCount = selectedDayCount; - stopLimit = StopLimitDA.GetStopLimit(selectedSymbol); + + internalStopLimits = StopLimitDA.GetStopLimits(selectedSymbol); portfolioTrades = PortfolioDA.GetTradesSymbol(selectedSymbol); portfolioTradesLots = LotAggregator.CombineLots(portfolioTrades); @@ -245,9 +246,9 @@ namespace PortfolioManager.Renderers { StopLimits = StopLimitCompositeModel.CreateCompositeDataSource(externalStopLimits); } - else if (null != stopLimit && null != zeroPrice) + else if (null != internalStopLimits && null != zeroPrice) { - StopLimits = GainLossModel.CreateCompositeDataSource(zeroPrice.Date, stopLimit.StopPrice); + StopLimits = StopLimitCompositeModel.CreateCompositeDataSource(zeroPrice.Date, internalStopLimits); } (DateTime[] dates, double[] values) = StopLimits.ToXYData(); @@ -262,6 +263,7 @@ namespace PortfolioManager.Renderers } if(!showTradeLabels)return; + Price latestPrice = prices[0]; // Add the text marker if (null != externalStopLimits) @@ -275,7 +277,6 @@ namespace PortfolioManager.Renderers sb.Append(Utility.FormatCurrency(limit.StopPrice)); if (index == externalStopLimits.Count - 1) { - Price latestPrice = prices[0]; double percentOffsetFromLow = ((latestPrice.Low - limit.StopPrice) / limit.StopPrice); sb.Append(" (").Append(percentOffsetFromLow > 0 ? "+" : "").Append(Utility.FormatPercent(percentOffsetFromLow)).Append(")"); } @@ -291,21 +292,41 @@ namespace PortfolioManager.Renderers else { if (null == zeroPrice) return; - if (null == stopLimit || null == zeroPrice) return; - Price latestPrice = prices[0]; - double percentOffsetFromLow = ((latestPrice.Low - stopLimit.StopPrice) / stopLimit.StopPrice); + if (null == internalStopLimits || null == zeroPrice) return; + for (int index = 0; index < internalStopLimits.Count; index++) + { + StopLimit limit = internalStopLimits[index]; - StringBuilder sb = new StringBuilder(); - sb.Append(stopLimit.StopType).Append(" "); - sb.Append(Utility.FormatCurrency(stopLimit.StopPrice)); - sb.Append(" (").Append(percentOffsetFromLow > 0 ? "+" : "").Append(Utility.FormatPercent(percentOffsetFromLow)).Append(")"); - Image image = TextMarkerImageGenerator.GenerateImage(sb.ToString(), FontFactor.FontSize); - Coordinates coordinates = new Coordinates(latestPrice.Date.ToOADate() - offsets.Offset(OffsetDictionary.OffsetType.HorizontalOffset3PC), - stopLimit.StopPrice - offsets.Offset(OffsetDictionary.OffsetType.VerticalOffset6P5PC)); + StringBuilder sb = new StringBuilder(); + sb.Append(limit.StopType).Append(" "); + sb.Append(Utility.FormatCurrency(limit.StopPrice)); + if (index == internalStopLimits.Count - 1) + { + double percentOffsetFromLow = ((latestPrice.Low - limit.StopPrice) / limit.StopPrice); + sb.Append(" (").Append(percentOffsetFromLow > 0 ? "+" : "").Append(Utility.FormatPercent(percentOffsetFromLow)).Append(")"); + } + Image image = TextMarkerImageGenerator.GenerateImage(sb.ToString(), FontFactor.FontSize); + Coordinates coordinates = new Coordinates(limit.EffectiveDate.ToOADate(), + limit.StopPrice - offsets.Offset(OffsetDictionary.OffsetType.VerticalOffset6P5PC)); - coordinates = textMarkerManager.GetBestMarkerLocation(coordinates.X, coordinates.Y,offsets, offsets.Offset(OffsetDictionary.OffsetType.VerticalOffset6P5PC)); + coordinates = textMarkerManager.GetBestMarkerLocation(coordinates.X, coordinates.Y,offsets, offsets.Offset(OffsetDictionary.OffsetType.VerticalOffset6P5PC)); - ImageMarker imageMarker = Plotter.Plot.Add.ImageMarker(coordinates, image); + ImageMarker imageMarker = Plotter.Plot.Add.ImageMarker(coordinates, image); + } + + // double percentOffsetFromLow = ((latestPrice.Low - stopLimit.StopPrice) / stopLimit.StopPrice); + + // StringBuilder sb = new StringBuilder(); + // sb.Append(stopLimit.StopType).Append(" "); + // sb.Append(Utility.FormatCurrency(stopLimit.StopPrice)); + // sb.Append(" (").Append(percentOffsetFromLow > 0 ? "+" : "").Append(Utility.FormatPercent(percentOffsetFromLow)).Append(")"); + // Image image = TextMarkerImageGenerator.GenerateImage(sb.ToString(), FontFactor.FontSize); + // Coordinates coordinates = new Coordinates(latestPrice.Date.ToOADate() - offsets.Offset(OffsetDictionary.OffsetType.HorizontalOffset3PC), + // stopLimit.StopPrice - offsets.Offset(OffsetDictionary.OffsetType.VerticalOffset6P5PC)); + + // coordinates = textMarkerManager.GetBestMarkerLocation(coordinates.X, coordinates.Y,offsets, offsets.Offset(OffsetDictionary.OffsetType.VerticalOffset6P5PC)); + + // ImageMarker imageMarker = Plotter.Plot.Add.ImageMarker(coordinates, image); } } diff --git a/PortfolioManager/saveparams.config b/PortfolioManager/saveparams.config index cba1dc0..4ebf593 100644 --- a/PortfolioManager/saveparams.config +++ b/PortfolioManager/saveparams.config @@ -1,12 +1,4 @@ Type,PortfolioManager.ViewModels.MGSHMomentumViewModel,PathFileName,C:\boneyard\marketdata\Sessions\MGSH20250331.TXT Type,PortfolioManager.ViewModels.MomentumViewModel,PathFileName,C:\boneyard\marketdata\Sessions\MG20180131.TXT Type,PortfolioManager.ViewModels.CMMomentumViewModel,PathFileName,C:\boneyard\marketdata\Sessions\CM20191031.TXT -Type,PortfolioManager.ViewModels.CMTrendViewModel,PathFileName,C:\boneyard\marketdata\Sessions\CMT20200817.TXT -Type,PortfolioManager.ViewModels.BollingerBandViewModel,SelectedSymbol,SPOT,SelectedWatchList,Valuations,SelectedDayCount,90,SyncTradeToBand,False,ShowTradeLabels,True,UseLeastSquaresFit,True,ShowInsiderTransactions,True -Type,PortfolioManager.ViewModels.BollingerBandViewModel,SelectedSymbol,GWRE,SelectedWatchList,Valuations,SelectedDayCount,90,SyncTradeToBand,True,ShowTradeLabels,True,UseLeastSquaresFit,True,ShowInsiderTransactions,True -Type,PortfolioManager.ViewModels.BollingerBandViewModel,SelectedSymbol,CRS,SelectedWatchList,Valuations,SelectedDayCount,90,SyncTradeToBand,True,ShowTradeLabels,True,UseLeastSquaresFit,True,ShowInsiderTransactions,True -Type,PortfolioManager.ViewModels.BollingerBandViewModel,SelectedSymbol,T,SelectedWatchList,Valuations,SelectedDayCount,90,SyncTradeToBand,True,ShowTradeLabels,True,UseLeastSquaresFit,True,ShowInsiderTransactions,True -Type,PortfolioManager.ViewModels.BollingerBandViewModel,SelectedSymbol,NRG,SelectedWatchList,Valuations,SelectedDayCount,90,SyncTradeToBand,False,ShowTradeLabels,True,UseLeastSquaresFit,True,ShowInsiderTransactions,True -Type,PortfolioManager.ViewModels.BollingerBandViewModel,SelectedSymbol,PSO,SelectedWatchList,Valuations,SelectedDayCount,90,SyncTradeToBand,True,ShowTradeLabels,True,UseLeastSquaresFit,True,ShowInsiderTransactions,True -Type,PortfolioManager.ViewModels.BollingerBandViewModel,SelectedSymbol,PARR,SelectedWatchList,Valuations,SelectedDayCount,180,SyncTradeToBand,False,ShowTradeLabels,True,UseLeastSquaresFit,True,ShowInsiderTransactions,True -Type,PortfolioManager.ViewModels.BollingerBandViewModel,SelectedSymbol,SH,SelectedWatchList,Valuations,SelectedDayCount,90,SyncTradeToBand,False,ShowTradeLabels,True,UseLeastSquaresFit,True,ShowInsiderTransactions,True +Type,PortfolioManager.ViewModels.BollingerBandViewModel,SelectedSymbol,ALHC,SelectedWatchList,{ALL},SelectedDayCount,90,SyncTradeToBand,False,ShowTradeLabels,True,UseLeastSquaresFit,True,ShowInsiderTransactions,True