Commit Latest
This commit is contained in:
295
PortfolioManager/Renderers/BollingerBandRenderer.cs
Normal file
295
PortfolioManager/Renderers/BollingerBandRenderer.cs
Normal file
@@ -0,0 +1,295 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Text;
|
||||
using System.Linq;
|
||||
using Eremex.AvaloniaUI.Charts;
|
||||
using MarketData.DataAccess;
|
||||
using MarketData.Generator;
|
||||
using MarketData.MarketDataModel;
|
||||
using MarketData.Utils;
|
||||
using PortfolioManager.Cache;
|
||||
using PortfolioManager.DataSeriesViewModels;
|
||||
using PortfolioManager.Models;
|
||||
using PortfolioManager.ViewModels;
|
||||
using ScottPlot;
|
||||
using ScottPlot.Avalonia;
|
||||
using ScottPlot.Plottables;
|
||||
using SkiaSharp;
|
||||
|
||||
namespace PortfolioManager.Renderers
|
||||
{
|
||||
public class BollingerBandRenderer : ModelBase
|
||||
{
|
||||
private Price latestPrice = default;
|
||||
private Price zeroPrice = default;
|
||||
private bool showLabels =true;
|
||||
private bool showMarkers = true;
|
||||
private bool showLegend = true;
|
||||
private bool syncTradeToBand = true;
|
||||
private StopLimit stopLimit = default;
|
||||
private PortfolioTrades portfolioTrades = default;
|
||||
private PortfolioTrades portfolioTradesLots = default;
|
||||
private Prices prices = default;
|
||||
private BollingerBands bollingerBands;
|
||||
private InsiderTransactionSummaries insiderTransactionSummaries = null;
|
||||
|
||||
public BollingerBandRenderer(AvaPlot plotter)
|
||||
{
|
||||
Plotter = plotter ?? throw new ArgumentNullException(nameof(plotter));
|
||||
PropertyChanged += OnBollingerBandRendererPropertyChanged;
|
||||
}
|
||||
|
||||
private void OnBollingerBandRendererPropertyChanged(Object sender, PropertyChangedEventArgs eventArgs)
|
||||
{
|
||||
if (eventArgs.PropertyName.Equals("ShowLabels"))
|
||||
{
|
||||
}
|
||||
else if (eventArgs.PropertyName.Equals("ShowMarkers"))
|
||||
{
|
||||
}
|
||||
else if (eventArgs.PropertyName.Equals("ShowLegend"))
|
||||
{
|
||||
if (!ShowLegend) Plotter.Plot.HideLegend();
|
||||
else Plotter.Plot.ShowLegend();
|
||||
}
|
||||
}
|
||||
|
||||
public void Render()
|
||||
{
|
||||
Plotter.Plot.Axes.AutoScale();
|
||||
Plotter.Refresh();
|
||||
base.OnPropertyChanged("ShowLegend");
|
||||
}
|
||||
|
||||
public void SetData(String selectedSymbol, int selectedDayCount)
|
||||
{
|
||||
stopLimit = PortfolioDA.GetStopLimit(selectedSymbol);
|
||||
portfolioTrades = PortfolioDA.GetTradesSymbol(selectedSymbol);
|
||||
portfolioTradesLots = LotAggregator.CombineLots(portfolioTrades);
|
||||
|
||||
if (null != portfolioTrades && 0 != portfolioTrades.Count)
|
||||
{
|
||||
DateGenerator dateGenerator = new DateGenerator();
|
||||
DateTime earliestTrade = portfolioTrades[0].TradeDate;
|
||||
earliestTrade = earliestTrade.AddDays(-30);
|
||||
int daysBetween = dateGenerator.DaysBetween(earliestTrade, DateTime.Now);
|
||||
if (daysBetween < selectedDayCount || !syncTradeToBand) prices = PricingDA.GetPrices(selectedSymbol, selectedDayCount);
|
||||
else prices = PricingDA.GetPrices(selectedSymbol, earliestTrade);
|
||||
|
||||
DateTime earliestInsiderTransactionDate = dateGenerator.GenerateFutureBusinessDate(prices[prices.Count - 1].Date, 30);
|
||||
insiderTransactionSummaries = InsiderTransactionDA.GetInsiderTransactionSummaries(selectedSymbol, earliestInsiderTransactionDate);
|
||||
|
||||
// calculate the break even price on the open trades for this symbol
|
||||
PortfolioTrades openTrades = portfolioTrades.GetOpenTrades();
|
||||
DateTime latestPricingDate = PricingDA.GetLatestDate(selectedSymbol);
|
||||
latestPrice = PricingDA.GetPrice(selectedSymbol, latestPricingDate);
|
||||
zeroPrice = ParityGenerator.GenerateGainLossValue(openTrades, latestPrice);
|
||||
|
||||
|
||||
if (!syncTradeToBand)
|
||||
{
|
||||
DateTime earliestPricingDate = prices[prices.Count - 1].Date;
|
||||
earliestPricingDate = earliestPricingDate.AddDays(30);
|
||||
IEnumerable<PortfolioTrade> tradesInRange = (from portfolioTrade in portfolioTradesLots where portfolioTrade.TradeDate >= earliestPricingDate select portfolioTrade);
|
||||
portfolioTrades = new PortfolioTrades();
|
||||
foreach (PortfolioTrade portfolioTrade in tradesInRange) portfolioTrades.Add(portfolioTrade);
|
||||
portfolioTradesLots = portfolioTrades;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
prices = PricingDA.GetPrices(selectedSymbol, selectedDayCount);
|
||||
if (null != prices && 0 != prices.Count)
|
||||
{
|
||||
DateGenerator dateGenerator = new DateGenerator();
|
||||
DateTime earliestInsiderTransactionDate = dateGenerator.GenerateFutureBusinessDate(prices[prices.Count - 1].Date, 30);
|
||||
insiderTransactionSummaries = InsiderTransactionDA.GetInsiderTransactionSummaries(selectedSymbol, earliestInsiderTransactionDate);
|
||||
}
|
||||
}
|
||||
bollingerBands = BollingerBandGenerator.GenerateBollingerBands(prices);
|
||||
GenerateCompositeDataSources(bollingerBands);
|
||||
GenerateZeroPoint(zeroPrice);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generate the ZeroPoint marker and text
|
||||
/// </summary>
|
||||
/// <param name="zeroPrice"></param>
|
||||
private void GenerateZeroPoint(Price zeroPrice)
|
||||
{
|
||||
if (!ShowMarkers) return;
|
||||
ImageMarker imageMarker = default;
|
||||
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));
|
||||
|
||||
image = TextMarkerImageGenerator.ToSPImage(ImageCache.GetInstance().GetImage(ImageCache.ImageType.BlueTriangleUp));
|
||||
coordinates = new Coordinates(dates[0].ToOADate(), values[0]);
|
||||
imageMarker = Plotter.Plot.Add.ImageMarker(coordinates, image, 0.125f);
|
||||
|
||||
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, 11);
|
||||
coordinates = new Coordinates(dates[0].ToOADate(), values[0]-5.00);
|
||||
imageMarker = Plotter.Plot.Add.ImageMarker(coordinates, image);
|
||||
}
|
||||
|
||||
private void GenerateCompositeDataSources(BollingerBands bollingerBands)
|
||||
{
|
||||
K = BollingerBandModel.K(bollingerBands);
|
||||
KL1 = BollingerBandModel.KL1(bollingerBands);
|
||||
L = BollingerBandModel.L(bollingerBands);
|
||||
LP1 = BollingerBandModel.LP1(bollingerBands);
|
||||
High = BollingerBandModel.High(bollingerBands);
|
||||
Low = BollingerBandModel.Low(bollingerBands);
|
||||
Close = BollingerBandModel.Close(bollingerBands);
|
||||
SMAN = BollingerBandModel.SMAN(bollingerBands);
|
||||
Volume = BollingerBandModel.Volume(bollingerBands);
|
||||
LeastSquares = BollingerBandModel.LeastSquares(bollingerBands);
|
||||
|
||||
Scatter scatter = default;
|
||||
{
|
||||
(DateTime[] dates, double[] values) = K.ToXYData();
|
||||
scatter = Plotter.Plot.Add.ScatterLine(dates, values, ScottPlot.Color.FromSKColor(SKColors.Green));
|
||||
scatter.LegendText = "K";
|
||||
scatter.LineWidth = 3;
|
||||
}
|
||||
|
||||
{
|
||||
(DateTime[] dates, double[] values) = KL1.ToXYData();
|
||||
scatter = Plotter.Plot.Add.ScatterLine(dates, values, ScottPlot.Color.FromSKColor(SKColors.Green));
|
||||
scatter.LegendText = "KL1";
|
||||
scatter.LineWidth = 2;
|
||||
}
|
||||
|
||||
{
|
||||
(DateTime[] dates, double[] values) = L.ToXYData();
|
||||
scatter = Plotter.Plot.Add.ScatterLine(dates, values, ScottPlot.Color.FromSKColor(SKColors.Green));
|
||||
scatter.LegendText = "L";
|
||||
scatter.LineWidth = 3;
|
||||
}
|
||||
|
||||
{
|
||||
(DateTime[] dates, double[] values) = LP1.ToXYData();
|
||||
scatter = Plotter.Plot.Add.ScatterLine(dates, values, ScottPlot.Color.FromSKColor(SKColors.Green));
|
||||
scatter.LegendText = "LP1";
|
||||
scatter.LineWidth = 2;
|
||||
}
|
||||
|
||||
{
|
||||
(DateTime[] dates, double[] values) = High.ToXYData();
|
||||
scatter = Plotter.Plot.Add.ScatterLine(dates, values, ScottPlot.Color.FromSKColor(SKColors.Blue));
|
||||
scatter.LegendText = "High";
|
||||
scatter.LineWidth = 2;
|
||||
}
|
||||
|
||||
{
|
||||
(DateTime[] dates, double[] values) = Low.ToXYData();
|
||||
scatter = Plotter.Plot.Add.ScatterLine(dates, values, ScottPlot.Color.FromSKColor(SKColors.Red));
|
||||
scatter.LegendText = "Low";
|
||||
scatter.LineWidth = 2;
|
||||
}
|
||||
|
||||
{
|
||||
(DateTime[] dates, double[] values) = Close.ToXYData();
|
||||
scatter = Plotter.Plot.Add.ScatterLine(dates, values, ScottPlot.Color.FromSKColor(SKColors.Black));
|
||||
scatter.LegendText = "Close";
|
||||
scatter.LineWidth = 2;
|
||||
}
|
||||
|
||||
{
|
||||
(DateTime[] dates, double[] values) = LeastSquares.ToXYData();
|
||||
scatter = Plotter.Plot.Add.ScatterLine(dates, values, ScottPlot.Color.FromSKColor(SKColors.Orange));
|
||||
scatter.LegendText = "LeastSquares";
|
||||
scatter.LineWidth = 2;
|
||||
}
|
||||
|
||||
{
|
||||
(DateTime[] dates, double[] values) = SMAN.ToXYData();
|
||||
scatter = Plotter.Plot.Add.ScatterLine(dates, values, ScottPlot.Color.FromSKColor(SKColors.Purple));
|
||||
scatter.LegendText = "SMAN";
|
||||
scatter.LineWidth = 2;
|
||||
}
|
||||
}
|
||||
|
||||
public bool SyncTradeToBand
|
||||
{
|
||||
get
|
||||
{
|
||||
return syncTradeToBand;
|
||||
}
|
||||
set
|
||||
{
|
||||
syncTradeToBand = value;
|
||||
base.OnPropertyChanged("SyncTradeToBand");
|
||||
}
|
||||
}
|
||||
|
||||
public bool ShowLabels
|
||||
{
|
||||
get
|
||||
{
|
||||
return showLabels;
|
||||
}
|
||||
set
|
||||
{
|
||||
showLabels = value;
|
||||
base.OnPropertyChanged("ShowLabels");
|
||||
}
|
||||
}
|
||||
|
||||
public bool ShowMarkers
|
||||
{
|
||||
get
|
||||
{
|
||||
return showMarkers;
|
||||
}
|
||||
set
|
||||
{
|
||||
showMarkers = value;
|
||||
base.OnPropertyChanged("ShowMarkers");
|
||||
}
|
||||
}
|
||||
|
||||
public bool ShowLegend
|
||||
{
|
||||
get
|
||||
{
|
||||
return showLegend;
|
||||
}
|
||||
set
|
||||
{
|
||||
showLegend = value;
|
||||
base.OnPropertyChanged("ShowLegend");
|
||||
}
|
||||
}
|
||||
|
||||
public AvaPlot Plotter { get; private set; }
|
||||
public CompositeDataSource K { get; private set; } = Empty();
|
||||
public CompositeDataSource KL1 { get; private set; } = Empty();
|
||||
public CompositeDataSource L { get; private set; } = Empty();
|
||||
public CompositeDataSource LP1 { get; private set; } = Empty();
|
||||
public CompositeDataSource High { get; private set; } = Empty();
|
||||
public CompositeDataSource Low { get; private set; } = Empty();
|
||||
public CompositeDataSource Close { get; private set; } = Empty();
|
||||
public CompositeDataSource SMAN { get; private set; } = Empty();
|
||||
public CompositeDataSource Volume { get; private set; } = Empty();
|
||||
public CompositeDataSource LeastSquares { get; private set; } = Empty();
|
||||
public CompositeDataSource ZeroPoint { get; private set; } = Empty();
|
||||
|
||||
private static CompositeDataSource Empty()
|
||||
{
|
||||
return new CompositeDataSource()
|
||||
{
|
||||
DataAdapter = new SortedDateTimeDataAdapter()
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user