Commit Latest

This commit is contained in:
2025-06-19 22:05:10 -04:00
parent a5b2369034
commit 9e6feaf252
4 changed files with 377 additions and 73 deletions

View File

@@ -2,6 +2,7 @@ using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
@@ -21,28 +22,44 @@ using PortfolioManager.DataSeriesViewModels;
using PortfolioManager.Extensions;
using PortfolioManager.Models;
using PortfolioManager.UIUtils;
using ScottPlot;
using SkiaSharp;
namespace PortfolioManager.ViewModels
{
public static class TextMarkerImageGenerator
{
public static IImage GenerateImage(String text)
public static Image GenerateImage(String text)
{
ImageHelper imageHelper = new ImageHelper();
int fontSize = 36;
int width = 640;
int width = 130;
imageHelper.CreateImage(width, fontSize);
imageHelper.Fill(SKColors.White);
SKTextAlign align = SKTextAlign.Center;
SKFont font = new SKFont(SKTypeface.FromFamilyName("Helvetica"), fontSize);
imageHelper.DrawText(text, new SKPoint(width / 2, fontSize - 2), SKColors.Black, align, font);
Avalonia.Media.Imaging.Bitmap avBitmap = new Avalonia.Media.Imaging.Bitmap(imageHelper.ToStream());
return avBitmap;
// avBitmap.Save("c:\\3\\mybitmap.jpg"); }
using MemoryStream memoryStream = new MemoryStream();
imageHelper.ToStream().CopyTo(memoryStream);
return new ScottPlot.Image(memoryStream.ToArray());
}
// public static IImage GenerateImage(String text)
// {
// ImageHelper imageHelper = new ImageHelper();
// int fontSize = 36;
// int width = 130;
// imageHelper.CreateImage(width, fontSize);
// imageHelper.Fill(SKColors.White);
// SKTextAlign align = SKTextAlign.Center;
// SKFont font = new SKFont(SKTypeface.FromFamilyName("Helvetica"), fontSize);
// imageHelper.DrawText(text, new SKPoint(width / 2, fontSize - 2), SKColors.Black, align, font);
// Avalonia.Media.Imaging.Bitmap avBitmap = new Avalonia.Media.Imaging.Bitmap(imageHelper.ToStream());
// return avBitmap;
// // avBitmap.Save("c:\\3\\mybitmap.jpg"); }
// }
public static IImage GenerateImage(int width, int height,SKColor color)
public static IImage GenerateImage(int width, int height, SKColor color)
{
ImageHelper imageHelper = new ImageHelper();
imageHelper.CreateImage(width, height);

View File

@@ -1,10 +1,12 @@
using System;
using Avalonia.Media;
using Eremex.AvaloniaUI.Charts;
using MarketData.DataAccess;
using MarketData.Generator;
using MarketData.MarketDataModel;
using PortfolioManager.DataSeriesViewModels;
using PortfolioManager.Models;
using ScottPlot;
using ScottPlot.Avalonia;
using ScottPlot.Plottables;
using ShimSkiaSharp;
@@ -12,13 +14,60 @@ using SkiaSharp;
namespace PortfolioManager.ViewModels
{
public class BollingerBandCompositeDataSourceGenerater
public class BollingerBandCompositeDataSourceGenerater
{
public BollingerBandCompositeDataSourceGenerater()
{
public BollingerBandCompositeDataSourceGenerater()
{
}
}
public void GenerateCompositeDataSources(AvaPlot plotter, BollingerBands bollingerBands)
public void Render(AvaPlot plotter)
{
plotter.Plot.Axes.AutoScale();
plotter.Refresh();
}
public void SetData(String selectedSymbol, int selectedDayCount, AvaPlot plotter)
{
Prices prices = PricingDA.GetPrices(selectedSymbol, selectedDayCount);
BollingerBands bollingerBands = BollingerBandGenerator.GenerateBollingerBands(prices);
// calculate the break even price on the open trades for this symbol
PortfolioTrades portfolioTrades = PortfolioDA.GetTradesSymbol(selectedSymbol);
PortfolioTrades openTrades = portfolioTrades.GetOpenTrades();
DateTime latestPricingDate = PricingDA.GetLatestDate(selectedSymbol);
Price latestPrice = PricingDA.GetPrice(selectedSymbol, latestPricingDate);
Price zeroPrice = ParityGenerator.GenerateGainLossValue(openTrades, latestPrice);
GenerateCompositeDataSources(plotter, bollingerBands);
GenerateZeroPoint(plotter, zeroPrice);
}
private void GenerateZeroPoint(AvaPlot plotter, Price zeroPrice)
{
ZeroPoint = GainLossModel.Price(zeroPrice);
(DateTime[] dates, double[] values) = ZeroPoint.ToXYData();
Scatter scatter = plotter.Plot.Add.Scatter(dates, values, ScottPlot.Color.FromSKColor(SKColors.Blue));
// Marker marker = plotter.Plot.Add.Marker(dates[0].ToOADate(), values[0] / 1.025);
// marker.MarkerFillColor = ScottPlot.Color.FromSKColor(SKColors.Blue);
// marker.MarkerStyle.Shape = MarkerShape.TriUp;
// marker.MarkerStyle.Size = 15;
IImage image = TextMarkerImageGenerator.GenerateImage("Even $52.14 (+.25%");
Coordinates coordinates = new Coordinates(dates[0].ToOADate(), values[0] / 1.025);
Marker marker = plotter.Plot.Add.ImageMarker(coordinates, image);
Image image = default;
// Marker marker=plotter.Plot.Add.Marker(K.DataAdapter.ItemCount-1,values[0]);
// Marker marker=plotter.Plot.Add.Marker(0,values[0]);
// marker.MarkerFillColor = ScottPlot.Color.FromSKColor(SKColors.Blue);
// marker.MarkerStyle.Shape = MarkerShape.TriUp;
// marker.MarkerStyle.Size = 15;
}
private void GenerateCompositeDataSources(AvaPlot plotter, BollingerBands bollingerBands)
{
K = BollingerBandModel.K(bollingerBands);
KL1 = BollingerBandModel.KL1(bollingerBands);
@@ -36,74 +85,66 @@ namespace PortfolioManager.ViewModels
(DateTime[] dates, double[] values) = K.ToXYData();
scatter = plotter.Plot.Add.ScatterLine(dates, values, ScottPlot.Color.FromSKColor(SKColors.Green));
scatter.LegendText = "K";
scatter.LineWidth = 2;
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 = 1;
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 = 2;
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 = 1;
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 = 1;
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 = 1;
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 = 1;
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 = 1;
}
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 = 1;
}
scatter.LineWidth = 2;
}
}
public CompositeDataSource K { get; private set; } = Empty();
public CompositeDataSource KL1 { get; private set; } = Empty();
public CompositeDataSource L { get; private set; } = Empty();
@@ -114,20 +155,17 @@ namespace PortfolioManager.ViewModels
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()
};
}
return new CompositeDataSource()
{
DataAdapter = new SortedDateTimeDataAdapter()
};
}
}
public partial class ScottPlotViewModel : PlotterWorkspaceViewModel
{
private AvaPlot plotter = default;
@@ -138,37 +176,21 @@ namespace PortfolioManager.ViewModels
public void PlotterLoadedEvent(object sender, PlotterLoadedEventArgs e)
{
String selectedSymbol = "SPY";
int selectedDayCount = 180;
plotter = e.AvaPlot; // we should store this somewhere
Prices prices = PricingDA.GetPrices("SPY", 180);
BollingerBands bollingerBands = BollingerBandGenerator.GenerateBollingerBands(prices);
// Prices prices = PricingDA.GetPrices("SPY", 180);
// BollingerBands bollingerBands = BollingerBandGenerator.GenerateBollingerBands(prices);
BollingerBandCompositeDataSourceGenerater bollingerBandCompositeDataSourceGenerater = new BollingerBandCompositeDataSourceGenerater();
bollingerBandCompositeDataSourceGenerater.GenerateCompositeDataSources(plotter, bollingerBands);
plotter.Plot.Axes.AutoScale();
plotter.Refresh();
bollingerBandCompositeDataSourceGenerater.SetData(selectedSymbol, selectedDayCount, plotter);
//public void SetData(String selectedSymbol, int selectedDayCount, AvaPlot plotter)
// DateTime[] dates = new DateTime[prices.Count];
// double[] closes = new double[prices.Count];
// for (int index = 0; index < prices.Count; index++)
// {
// dates[index] = prices[index].Date;
// closes[index] = prices[index].Close;
// }
// plotter = e.AvaPlot;
// double[] dataX = { 1, 2, 3, 4, 5 };
// double[] dataY = { 1, 4, 9, 16, 25 };
// plotter.Plot.Add.Scatter(dataX, dataY);
// Scatter closeScatter = plotter.Plot.Add.ScatterLine(dates, closes, ScottPlot.Color.FromSKColor(SKColors.Red));
// closeScatter.LegendText = "Close";
// closeScatter.LineWidth = 2;
// bollingerBandCompositeDataSourceGenerater.GenerateCompositeDataSources(plotter, bollingerBands);
bollingerBandCompositeDataSourceGenerater.Render(plotter);
// plotter.Plot.Axes.AutoScale();
// plotter.Refresh();
// plotter.Refresh();
}
// ********************************************** P E R S I S T E N C E *************************
public override bool CanPersist()