Commit Latest

This commit is contained in:
2025-06-25 21:05:14 -04:00
parent bf6d6ee6d7
commit 27881870f6
4 changed files with 115 additions and 93 deletions

View File

@@ -33,8 +33,30 @@ namespace PortfolioManager.Renderers
public class OffsetDictionary
{
enum OffsetType {VerticalOffset5PC, VerticalOffset3PC, VerticalOffset1PC,HorizontalOffset5PC,HorizontalOffset3PC,HorizontalOffset1PC};
private Dictionary<int, double> offsetDictionary;
public enum OffsetType
{
VerticalOffset5PC, VerticalOffset3PC, VerticalOffset1PC, HorizontalOffset5PC, HorizontalOffset3PC, HorizontalOffset1PC,
MinBollingerDate, MaxBollingerDate, MinBollingerValue, MaxBollingerValue
};
private Dictionary<OffsetType, double> offsetDictionary = new Dictionary<OffsetType, double>();
public void Add(OffsetType offsetType, double value)
{
if (offsetDictionary.ContainsKey(offsetType))
{
offsetDictionary[offsetType] = value;
}
else
{
offsetDictionary.Add(offsetType, value);
}
}
public double Offset(OffsetType offsetType)
{
return offsetDictionary[offsetType];
}
}
@@ -58,14 +80,7 @@ namespace PortfolioManager.Renderers
private BollingerBands bollingerBands;
private InsiderTransactionSummaries insiderTransactionSummaries = null;
// double maxBollingerDate = 0.00;
// double minBollingerDate = 0.00;
//double spread = 0.00;
double percentShiftHorz3PC = 0.00;
double percentShiftHorz1PC = 0.00;
double percentShiftVert3PC = 0.00;
double percentShiftVert1PC = 0.00;
double percentShiftVert5PC = 0.00;
private OffsetDictionary offsets = new OffsetDictionary();
public BollingerBandRenderer(AvaPlot plotter)
{
@@ -91,10 +106,10 @@ namespace PortfolioManager.Renderers
if (!ShowLegend) Plotter.Plot.HideLegend();
else Plotter.Plot.ShowLegend();
}
else if (eventArgs.PropertyName.Equals("ShowInsiderTransactions"))
{
SetData(selectedSymbol, selectedDayCount);
}
// else if (eventArgs.PropertyName.Equals("ShowInsiderTransactions"))
// {
// SetData(selectedSymbol, selectedDayCount);
// }
}
public void Render()
@@ -152,20 +167,7 @@ namespace PortfolioManager.Renderers
}
}
bollingerBands = BollingerBandGenerator.GenerateBollingerBands(prices);
double maxBollingerDate = bollingerBands.Max(x => x.Date).ToOADate();
double minBollingerDate = bollingerBands.Min(x => x.Date).ToOADate();
double maxBollingerValue = bollingerBands.Max(x => x.K);
double minBollingerValue = bollingerBands.Min(x => x.L);
double spreadHorz = (maxBollingerDate - minBollingerDate);
double spreadVert = (maxBollingerValue - minBollingerValue);
percentShiftHorz3PC = spreadHorz * .03;
percentShiftHorz1PC = spreadHorz * .01;
percentShiftVert3PC = spreadVert * .03;
percentShiftVert1PC = spreadVert * .01;
percentShiftVert5PC = spreadVert * .05;
CalculateOffsets();
GenerateBollingerBands();
GenerateZeroPoint(zeroPrice);
GenerateInsiderTransactions();
@@ -173,6 +175,28 @@ namespace PortfolioManager.Renderers
GenerateTradePoints();
}
private void CalculateOffsets()
{
double maxBollingerDate = bollingerBands.Max(x => x.Date).ToOADate();
double minBollingerDate = bollingerBands.Min(x => x.Date).ToOADate();
double maxBollingerValue = bollingerBands.Max(x => x.K);
double minBollingerValue = bollingerBands.Min(x => x.L);
offsets.Add(OffsetDictionary.OffsetType.MaxBollingerDate,maxBollingerDate);
offsets.Add(OffsetDictionary.OffsetType.MinBollingerDate,minBollingerDate);
offsets.Add(OffsetDictionary.OffsetType.MaxBollingerValue,maxBollingerValue);
offsets.Add(OffsetDictionary.OffsetType.MinBollingerValue,minBollingerValue);
double spreadHorz = (maxBollingerDate - minBollingerDate);
double spreadVert = (maxBollingerValue - minBollingerValue);
offsets.Add(OffsetDictionary.OffsetType.HorizontalOffset1PC,spreadHorz * .01);
offsets.Add(OffsetDictionary.OffsetType.HorizontalOffset3PC,spreadHorz * .03);
offsets.Add(OffsetDictionary.OffsetType.HorizontalOffset5PC,spreadHorz * .05);
offsets.Add(OffsetDictionary.OffsetType.VerticalOffset1PC,spreadVert * .01);
offsets.Add(OffsetDictionary.OffsetType.VerticalOffset3PC,spreadVert *.03);
offsets.Add(OffsetDictionary.OffsetType.VerticalOffset5PC,spreadVert * .05);
}
/// <summary>
/// Generate the ZeroPoint marker and text
/// </summary>
@@ -184,21 +208,21 @@ namespace PortfolioManager.Renderers
Coordinates coordinates = default;
Image image = default;
ZeroPoint = GainLossModel.Price(zeroPrice);
(DateTime[] dates, double[] values) = ZeroPoint.ToXYData();
Scatter scatter = Plotter.Plot.Add.Scatter(dates, values, ScottPlot.Color.FromSKColor(SKColors.Blue));
(DateTime[] dates, double[] values) = ZeroPoint.ToXYData(); // There is only a single value in this collection
// Place the triangle marker
image = TextMarkerImageGenerator.ToSPImage(ImageCache.GetInstance().GetImage(ImageCache.ImageType.BlueTriangleUp));
coordinates = new Coordinates(dates[0].ToOADate(), values[0]);
imageMarker = Plotter.Plot.Add.ImageMarker(coordinates, image, SizeFactor.Normal);
// Place the text marker
StringBuilder sb = new StringBuilder();
sb.Append("Even ");
sb.Append(Utility.FormatCurrency(zeroPrice.Close));
double parityOffsetPercent = (latestPrice.Close - zeroPrice.Close) / zeroPrice.Close;
sb.Append("(").Append(parityOffsetPercent < 0 ? "" : "+").Append(Utility.FormatPercent(parityOffsetPercent)).Append(")");
image = TextMarkerImageGenerator.GenerateImage(sb.ToString(), 130, 24, FontFactor.FontSize);
coordinates = new Coordinates(dates[0].ToOADate(), values[0] - 5.00);
coordinates = new Coordinates(dates[0].ToOADate() - offsets.Offset(OffsetDictionary.OffsetType.HorizontalOffset3PC), values[0] - offsets.Offset(OffsetDictionary.OffsetType.VerticalOffset5PC));
imageMarker = Plotter.Plot.Add.ImageMarker(coordinates, image);
}
@@ -245,8 +269,7 @@ namespace PortfolioManager.Renderers
sb.Append(" (").Append(percentOffsetFromLow > 0 ? "+" : "").Append(Utility.FormatPercent(percentOffsetFromLow)).Append(")");
}
Image image = TextMarkerImageGenerator.GenerateImage(sb.ToString(), 155, 24, FontFactor.FontSize);
// Coordinates coordinates = new Coordinates(dates[0].ToOADate()-1, values[0] - 5.00);
Coordinates coordinates = new Coordinates(limit.EffectiveDate.ToOADate(), limit.StopPrice - 5.00);
Coordinates coordinates = new Coordinates(limit.EffectiveDate.ToOADate(), limit.StopPrice - offsets.Offset(OffsetDictionary.OffsetType.VerticalOffset5PC));
ImageMarker imageMarker = Plotter.Plot.Add.ImageMarker(coordinates, image);
}
}
@@ -261,10 +284,8 @@ namespace PortfolioManager.Renderers
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(), 155, 24, FontFactor.FontSize);
// Coordinates coordinates = new Coordinates(latestPrice.Date.ToOADate()/(1+onePercent), stopLimit.StopPrice - 5.00);
Coordinates coordinates = new Coordinates(latestPrice.Date.ToOADate() - percentShiftHorz3PC, stopLimit.StopPrice - 5.00);
Coordinates coordinates = new Coordinates(latestPrice.Date.ToOADate() - offsets.Offset(OffsetDictionary.OffsetType.HorizontalOffset3PC), stopLimit.StopPrice - offsets.Offset(OffsetDictionary.OffsetType.VerticalOffset5PC));
ImageMarker imageMarker = Plotter.Plot.Add.ImageMarker(coordinates, image);
}
}
@@ -295,7 +316,7 @@ namespace PortfolioManager.Renderers
sb.Append(Utility.FormatCurrency(portfolioTrade.Price));
Image image = TextMarkerImageGenerator.GenerateImage(sb.ToString(), 150, 24, FontFactor.FontSize);
Coordinates coordinates = new Coordinates(portfolioTrade.TradeDate.ToOADate(), portfolioTrade.Price - percentShiftVert5PC);
Coordinates coordinates = new Coordinates(portfolioTrade.TradeDate.ToOADate(), portfolioTrade.Price - offsets.Offset(OffsetDictionary.OffsetType.VerticalOffset5PC));
ImageMarker imageMarker = Plotter.Plot.Add.ImageMarker(coordinates, image);
}
}
@@ -337,7 +358,7 @@ namespace PortfolioManager.Renderers
{
DateTime date = dates[index];
double value = values[index];
coordinates = new Coordinates(date.ToOADate(), value);
coordinates = new Coordinates(date.ToOADate(),offsets.Offset(OffsetDictionary.OffsetType.MinBollingerValue) - offsets.Offset(OffsetDictionary.OffsetType.VerticalOffset5PC));
imageMarker = Plotter.Plot.Add.ImageMarker(coordinates, imageDisposed, SizeFactor.Small);
}
}
@@ -348,7 +369,7 @@ namespace PortfolioManager.Renderers
{
DateTime date = dates[index];
double value = values[index];
coordinates = new Coordinates(date.ToOADate(), value);
coordinates = new Coordinates(date.ToOADate(),offsets.Offset(OffsetDictionary.OffsetType.MinBollingerValue) - offsets.Offset(OffsetDictionary.OffsetType.VerticalOffset5PC));
imageMarker = Plotter.Plot.Add.ImageMarker(coordinates, imageDisposed, SizeFactor.Normal);
}
}
@@ -359,7 +380,7 @@ namespace PortfolioManager.Renderers
{
DateTime date = dates[index];
double value = values[index];
coordinates = new Coordinates(date.ToOADate(), value);
coordinates = new Coordinates(date.ToOADate(),offsets.Offset(OffsetDictionary.OffsetType.MinBollingerValue) - offsets.Offset(OffsetDictionary.OffsetType.VerticalOffset5PC));
imageMarker = Plotter.Plot.Add.ImageMarker(coordinates, imageDisposed, SizeFactor.Large);
}
}
@@ -371,7 +392,7 @@ namespace PortfolioManager.Renderers
{
DateTime date = dates[index];
double value = values[index];
coordinates = new Coordinates(date.ToOADate(), value);
coordinates = new Coordinates(date.ToOADate(),offsets.Offset(OffsetDictionary.OffsetType.MinBollingerValue) - offsets.Offset(OffsetDictionary.OffsetType.VerticalOffset5PC));
imageMarker = Plotter.Plot.Add.ImageMarker(coordinates, imageAcquired, SizeFactor.Small);
}
}
@@ -382,7 +403,7 @@ namespace PortfolioManager.Renderers
{
DateTime date = dates[index];
double value = values[index];
coordinates = new Coordinates(date.ToOADate(), value);
coordinates = new Coordinates(date.ToOADate(),offsets.Offset(OffsetDictionary.OffsetType.MinBollingerValue) - offsets.Offset(OffsetDictionary.OffsetType.VerticalOffset5PC));
imageMarker = Plotter.Plot.Add.ImageMarker(coordinates, imageAcquired, SizeFactor.Normal);
}
}
@@ -393,7 +414,7 @@ namespace PortfolioManager.Renderers
{
DateTime date = dates[index];
double value = values[index];
coordinates = new Coordinates(date.ToOADate(), value);
coordinates = new Coordinates(date.ToOADate(),offsets.Offset(OffsetDictionary.OffsetType.MinBollingerValue) - offsets.Offset(OffsetDictionary.OffsetType.VerticalOffset5PC));
imageMarker = Plotter.Plot.Add.ImageMarker(coordinates, imageAcquired, SizeFactor.Large);
}
}

View File

@@ -20,53 +20,51 @@ namespace PortfolioManager.ViewModels
{
public partial class ScottPlotViewModel : PlotterWorkspaceViewModel
{
// private AvaPlot plotter = default;
private List<String> watchListNames;
private String selectedWatchList;
private ObservableCollection<String> symbols = new ObservableCollection<String>();
private List<Int32> dayCounts = new int[] { 60, 90, 180, 360, 720, 1440, 3600 }.ToList<int>();
private int selectedDayCount = 90;
private bool isBusy = false;
private String selectedSymbol = default;
private String companyName = default;
BollingerBandRenderer bollingerBandRenderer = default;
private List<String> watchListNames;
private String selectedWatchList;
private ObservableCollection<String> symbols = new ObservableCollection<String>();
private List<Int32> dayCounts = new int[] { 60, 90, 180, 360, 720, 1440, 3600 }.ToList<int>();
private int selectedDayCount = 90;
private bool isBusy = false;
private String selectedSymbol = default;
private String companyName = default;
private BollingerBandRenderer bollingerBandRenderer = default;
private bool showInsiderTransactions = true;
public ScottPlotViewModel()
{
DisplayName = "Bollinger";
// Plotter = new AvaPlot();
// base.OnPropertyChanged("Plotter");
OnPlotterLoadedEventHandler += PlotterLoadedEvent;
PropertyChanged += OnViewModelPropertyChanged;
Initialize();
}
public ScottPlotViewModel()
{
DisplayName = "Bollinger";
OnPlotterLoadedEventHandler += PlotterLoadedEvent;
PropertyChanged += OnViewModelPropertyChanged;
Initialize();
}
protected override void OnDispose()
{
MDTrace.WriteLine(LogLevel.DEBUG, $"Dispose BollingerBandViewModel");
base.OnDispose();
}
protected override void OnDispose()
{
MDTrace.WriteLine(LogLevel.DEBUG, $"Dispose BollingerBandViewModel");
base.OnDispose();
}
private void Initialize(bool executePropertyChanged = true)
{
Task workerTask = Task.Factory.StartNew(() =>
{
MDTrace.WriteLine(LogLevel.DEBUG, $"BollingerBandViewModel::Initialize()");
watchListNames = WatchListDA.GetWatchLists();
watchListNames.Insert(0, UIConstants.CONST_ALL);
selectedWatchList = watchListNames.Find(x => x.Equals("Valuations"));
symbols.AddRange(WatchListDA.GetWatchList(selectedWatchList));
});
workerTask.ContinueWith((continuation) =>
{
if (executePropertyChanged)
{
base.OnPropertyChanged("Symbols");
base.OnPropertyChanged("WatchListNames");
base.OnPropertyChanged("SelectedWatchList");
}
});
}
private void Initialize(bool executePropertyChanged = true)
{
Task workerTask = Task.Factory.StartNew(() =>
{
MDTrace.WriteLine(LogLevel.DEBUG, $"BollingerBandViewModel::Initialize()");
watchListNames = WatchListDA.GetWatchLists();
watchListNames.Insert(0, UIConstants.CONST_ALL);
selectedWatchList = watchListNames.Find(x => x.Equals("Valuations"));
symbols.AddRange(WatchListDA.GetWatchList(selectedWatchList));
});
workerTask.ContinueWith((continuation) =>
{
if (executePropertyChanged)
{
base.OnPropertyChanged("Symbols");
base.OnPropertyChanged("WatchListNames");
base.OnPropertyChanged("SelectedWatchList");
}
});
}
// *******************************************************************************************************************************************
@@ -78,7 +76,7 @@ namespace PortfolioManager.ViewModels
public void PlotterLoadedEvent(object sender, PlotterLoadedEventArgs e)
{
base.OnPropertyChanged("Plotter");
}
}
private void OnViewModelPropertyChanged(object sender, PropertyChangedEventArgs eventArgs)
{
@@ -88,6 +86,7 @@ namespace PortfolioManager.ViewModels
eventArgs.PropertyName.Equals("SelectedSymbol") ||
eventArgs.PropertyName.Equals("ShowRiskFree") ||
eventArgs.PropertyName.Equals("LeastSquaresFit") ||
eventArgs.PropertyName.Equals("CheckBoxShowInsiderTransactions") ||
eventArgs.PropertyName.Equals("SelectedDayCount"))
&& !String.IsNullOrEmpty(selectedSymbol)
&& default != Plotter)
@@ -97,6 +96,7 @@ namespace PortfolioManager.ViewModels
{
companyName = PricingDA.GetNameForSymbol(selectedSymbol);
bollingerBandRenderer = new BollingerBandRenderer(Plotter);
bollingerBandRenderer.ShowInsiderTransactions=showInsiderTransactions;
bollingerBandRenderer.SetData(selectedSymbol, selectedDayCount);
bollingerBandRenderer.Render();
});
@@ -276,12 +276,12 @@ namespace PortfolioManager.ViewModels
{
get
{
if (null == bollingerBandRenderer) return false;
return bollingerBandRenderer.ShowInsiderTransactions;
return showInsiderTransactions;
}
set
{
bollingerBandRenderer.ShowInsiderTransactions = value;
showInsiderTransactions = value;
base.OnPropertyChanged("CheckBoxShowInsiderTransactions");
}
}

View File

@@ -22,7 +22,7 @@ public partial class ScottPlotView : UserControl
{
ScottPlotView view = (sender as ScottPlotView);
PlotterWorkspaceViewModel viewModel = (DataContext as PlotterWorkspaceViewModel);
if (default == viewModel.Plotter)
if (null!=viewModel && default == viewModel.Plotter)
{
viewModel.Plotter = new AvaPlot();
viewModel.OnPlotterLoaded(viewModel.Plotter);

View File

@@ -0,0 +1 @@
Type,PortfolioManager.ViewModels.BollingerBandViewModel,SelectedSymbol,KEP,SelectedWatchList,Valuations,SelectedDayCount,180,SyncTradeToBand,False,ShowTradeLabels,True,UseLeastSquaresFit,True,ShowInsiderTransactions,True