Commit Latest

This commit is contained in:
2025-06-28 23:49:24 -04:00
parent 0d8402b234
commit 6bf92a14f2
10 changed files with 293 additions and 1397 deletions

View File

@@ -107,7 +107,7 @@ namespace PortfolioManager.Renderers
Plotter.Plot.Axes.Left.TickGenerator = new ScottPlot.TickGenerators.NumericAutomatic()
{
LabelFormatter = (double value) => value.ToString("C") // "C" format specifier formats as currency
};
};
Plotter.Plot.Axes.DateTimeTicksBottom();
Plotter.Plot.Axes.AutoScale();
Plotter.Plot.XLabel("Date");
@@ -166,11 +166,11 @@ namespace PortfolioManager.Renderers
bollingerBands = BollingerBandGenerator.GenerateBollingerBands(prices);
CalculateOffsets();
GenerateBollingerBands();
GenerateLeastSquares();
GenerateInsiderTransactions();
GenerateStopLimits();
GenerateTradePoints();
GenerateZeroPoint(zeroPrice);
GenerateLeastSquares();
}
/// <summary>
@@ -335,7 +335,7 @@ namespace PortfolioManager.Renderers
sb.Append("@");
sb.Append(Utility.FormatCurrency(portfolioTrade.Price));
Image image = TextMarkerImageGenerator.GenerateImage(sb.ToString(), 150, 24, FontFactor.FontSize);
Image image = TextMarkerImageGenerator.GenerateImage(sb.ToString(), 130, 24, FontFactor.FontSize);
Coordinates coordinates = new Coordinates(portfolioTrade.TradeDate.ToOADate(), portfolioTrade.Price - offsets.Offset(OffsetDictionary.OffsetType.VerticalOffset5PC));
ImageMarker imageMarker = Plotter.Plot.Add.ImageMarker(coordinates, image);
}
@@ -455,7 +455,7 @@ namespace PortfolioManager.Renderers
Close = BollingerBandModel.Close(bollingerBands);
SMAN = BollingerBandModel.SMAN(bollingerBands);
Volume = BollingerBandModel.Volume(bollingerBands);
LeastSquares = BollingerBandModel.LeastSquares(bollingerBands);
// LeastSquares = BollingerBandModel.LeastSquares(bollingerBands);
Scatter scatter = default;
{
@@ -507,13 +507,6 @@ namespace PortfolioManager.Renderers
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));

File diff suppressed because it is too large Load Diff

View File

@@ -97,7 +97,7 @@ namespace PortfolioManager.ViewModels
{
return new List<CommandViewModel>()
{
new CommandViewModel("ScottPlot", new MyRelayCommand(ParamArrayAttribute => this.ViewScottPlot())),
// new CommandViewModel("ScottPlot", new MyRelayCommand(ParamArrayAttribute => this.ViewScottPlot())),
new CommandViewModel("Bollinger Bands", new MyRelayCommand(ParamArrayAttribute => this.ViewBollingerBands())),
new CommandViewModel("Gain/Loss", new MyRelayCommand(ParamArrayAttribute => this.ViewGainLoss())),
new CommandViewModel("Momentum Model", new MyRelayCommand(ParamArrayAttribute => this.ViewMomentum())),
@@ -107,19 +107,19 @@ namespace PortfolioManager.ViewModels
};
}
private void ViewScottPlot()
{
ScottPlotViewModel workspace = null;
if (null == workspace)
{
workspace = new ScottPlotViewModel();
workspace.WorkspaceInstantiator = InstantiateWorkspace;
workspace.Referer = GetReferal();
// AddMenuItem(workspace);
this.Workspaces.Add(workspace);
}
this.SetActiveWorkspace(workspace);
}
// private void ViewScottPlot()
// {
// ScottPlotViewModel workspace = null;
// if (null == workspace)
// {
// workspace = new ScottPlotViewModel();
// workspace.WorkspaceInstantiator = InstantiateWorkspace;
// workspace.Referer = GetReferal();
// // AddMenuItem(workspace);
// this.Workspaces.Add(workspace);
// }
// this.SetActiveWorkspace(workspace);
// }
private void ViewBollingerBands()
{

View File

@@ -1,341 +0,0 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using CommunityToolkit.Mvvm.Input;
using DynamicData;
using MarketData;
using MarketData.DataAccess;
using MarketData.MarketDataModel;
using MarketData.Utils;
using PortfolioManager.Renderers;
using PortfolioManager.UIUtils;
namespace PortfolioManager.ViewModels
{
public partial class ScottPlotViewModel : PlotterWorkspaceViewModel
{
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;
private bool showTradeLabels = true;
private bool syncTradeToBand = true;
private bool useLeastSquaresFit = true;
public ScottPlotViewModel()
{
DisplayName = "Bollinger";
OnPlotterLoadedEventHandler += PlotterLoadedEvent;
PropertyChanged += OnViewModelPropertyChanged;
Initialize();
}
protected override void OnDispose()
{
MDTrace.WriteLine(LogLevel.DEBUG, $"Dispose BollingerBandViewModel");
base.OnDispose();
}
public override String Title
{
get
{
if (null == selectedSymbol) return DisplayName;
return "Bollinger " + "(" + selectedSymbol + ")";
}
}
public override String DisplayName
{
get
{
return "Bollinger Band";
}
}
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");
}
});
}
// *******************************************************************************************************************************************
/// <summary>
/// This event will be called the first time the view is rendered and each time the view comes back into focus (i.e.) Tab activated
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
public void PlotterLoadedEvent(object sender, PlotterLoadedEventArgs e)
{
base.OnPropertyChanged("Plotter");
}
private void OnViewModelPropertyChanged(object sender, PropertyChangedEventArgs eventArgs)
{
if ((eventArgs.PropertyName.Equals("SyncTradeToBand") ||
eventArgs.PropertyName.Equals("ShowTradeLabels") ||
eventArgs.PropertyName.Equals("SelectedSymbol") ||
eventArgs.PropertyName.Equals("ShowRiskFree") ||
eventArgs.PropertyName.Equals("UseLeastSquaresFit") ||
eventArgs.PropertyName.Equals("CheckBoxShowInsiderTransactions") ||
eventArgs.PropertyName.Equals("SelectedDayCount"))
&& !String.IsNullOrEmpty(selectedSymbol)
&& default != Plotter)
{
IsBusy = true;
Task workerTask = Task.Factory.StartNew(() =>
{
companyName = PricingDA.GetNameForSymbol(selectedSymbol);
bollingerBandRenderer = new BollingerBandRenderer(Plotter);
bollingerBandRenderer.ShowLeastSquares = useLeastSquaresFit;
bollingerBandRenderer.SyncTradeToBand = syncTradeToBand;
bollingerBandRenderer.ShowInsiderTransactions = showInsiderTransactions;
bollingerBandRenderer.ShowTradeLabels = showTradeLabels;
bollingerBandRenderer.SetData(selectedSymbol, selectedDayCount);
bollingerBandRenderer.Render();
});
workerTask.ContinueWith((continuation) =>
{
base.OnPropertyChanged("GraphTitle");
base.OnPropertyChanged("Title");
IsBusy = false;
});
}
}
// ********************************************** P E R S I S T E N C E *************************
public override bool CanPersist()
{
return false;
}
public override SaveParameters GetSaveParameters()
{
return null;
// SaveParameters saveParams = new SaveParameters();
// if (String.IsNullOrEmpty(selectedSymbol)) return null;
// saveParams.Add(new KeyValuePair<String, String>("Type", GetType().Namespace + "." + GetType().Name));
// saveParams.Add(new KeyValuePair<String, String>("SelectedSymbol", selectedSymbol));
// saveParams.Add(new KeyValuePair<String, String>("SelectedWatchList", selectedWatchList));
// saveParams.Add(new KeyValuePair<String, String>("SelectedDayCount", selectedDayCount.ToString()));
// saveParams.Add(new KeyValuePair<String, String>("SyncTradeToBand", syncTradeToBand.ToString()));
// saveParams.Add(new KeyValuePair<String, String>("ShowTradeLabels", showTradeLabels.ToString()));
// saveParams.Add(new KeyValuePair<String, String>("UseLeastSquaresFit", useLeastSquaresFit.ToString()));
// saveParams.Add(new KeyValuePair<String, String>("ShowInsiderTransactions", showInsiderTransactions.ToString()));
// if (null != stopLimits && 0 != stopLimits.Count)
// {
// saveParams.Add(new KeyValuePair<String, String>("StopHistoryCount", stopLimits.Count.ToString()));
// for (int index = 0; index < stopLimits.Count; index++)
// {
// String strItemKey = String.Format("StopHistory_{0}", index);
// StopLimit stopLimit = stopLimits[index];
// NVPCollection nvpCollection = stopLimit.ToNVPCollection();
// String strStopHistoryItem = nvpCollection.ToString();
// saveParams.Add(new KeyValuePair<String, String>(strItemKey, strStopHistoryItem));
// }
// }
// return saveParams;
}
public override void SetSaveParameters(SaveParameters saveParameters)
{
}
// ****************************************************** P R O P E R T I E S ************************************************
public String GraphTitle
{
get
{
if (null == companyName || null == bollingerBandRenderer || null == bollingerBandRenderer.Prices) return "";
String displayCompanyName = companyName;
if (displayCompanyName.Length > 40) displayCompanyName = displayCompanyName.Substring(0, 40) + "...";
StringBuilder sb = new StringBuilder();
float change = float.NaN;
Prices prices2day = new Prices(bollingerBandRenderer.Prices.Take(2).ToList());
if (2 == prices2day.Count) change = prices2day.GetReturns()[0];
sb.Append(displayCompanyName);
sb.Append(" (").Append(selectedSymbol).Append(") ");
sb.Append(Utility.DateTimeToStringMMHDDHYYYY(bollingerBandRenderer.Prices[bollingerBandRenderer.Prices.Count - 1].Date));
sb.Append(" Thru ");
sb.Append(Utility.DateTimeToStringMMHDDHYYYY(bollingerBandRenderer.Prices[0].Date));
sb.Append(" (").Append(Utility.FormatCurrency(bollingerBandRenderer.Prices[0].Close));
sb.Append("/").Append(Utility.FormatCurrency(bollingerBandRenderer.Prices[0].Low));
if (!float.IsNaN(change))
{
sb.Append(",");
sb.Append(change >= 0.00 ? "+" : "").Append(Utility.FormatPercent((double)change));
}
sb.Append(")");
return sb.ToString();
}
}
public List<String> WatchListNames
{
get
{
return watchListNames;
}
}
public String SelectedWatchList
{
get
{
return selectedWatchList;
}
set
{
selectedWatchList = value;
base.OnPropertyChanged("SelectedWatchList");
}
}
public ObservableCollection<String> Symbols
{
get
{
return symbols;
}
}
public int SelectedDayCount
{
get
{
return selectedDayCount;
}
set
{
selectedDayCount = value;
base.OnPropertyChanged("SelectedDayCount");
}
}
public List<int> DayCounts
{
get
{
return dayCounts;
}
}
public String SelectedSymbol
{
get
{
return selectedSymbol;
}
set
{
if (String.IsNullOrEmpty(value))
{
return;
}
selectedSymbol = value;
base.OnPropertyChanged("SelectedSymbol");
}
}
public bool IsBusy
{
get
{
return isBusy;
}
set
{
isBusy = value;
base.OnPropertyChanged("IsBusy");
}
}
public bool SyncTradeToBand
{
get
{
return syncTradeToBand;
}
set
{
syncTradeToBand = value;
base.OnPropertyChanged("SyncTradeToBand");
}
}
public bool ShowTradeLabels
{
get
{
return showTradeLabels;
}
set
{
showTradeLabels = value;
base.OnPropertyChanged("ShowTradeLabels");
}
}
public bool UseLeastSquaresFit
{
get
{
return useLeastSquaresFit;
}
set
{
useLeastSquaresFit = value;
base.OnPropertyChanged("UseLeastSquaresFit");
}
}
public Boolean CheckBoxShowInsiderTransactions
{
get
{
return showInsiderTransactions;
}
set
{
showInsiderTransactions = value;
base.OnPropertyChanged("CheckBoxShowInsiderTransactions");
}
}
[RelayCommand]
public async Task Refresh()
{
base.OnPropertyChanged("SelectedSymbol");
await Task.FromResult(true);
}
}
}

View File

@@ -2,16 +2,15 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:ScottPlot="clr-namespace:ScottPlot.Avalonia;assembly=ScottPlot.Avalonia"
xmlns:vm="using:PortfolioManager.ViewModels"
xmlns:vw="using:PortfolioManager.Views"
xmlns:md="using:PortfolioManager.Models"
xmlns:local="using:PortfolioManager.UIUtils"
xmlns:li="using:LoadingIndicators.Avalonia"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
xmlns:mxc="https://schemas.eremexcontrols.net/avalonia/charts"
x:DataType="vm:BollingerBandViewModel"
x:Class="PortfolioManager.Views.BollingerBandView"
>
x:Class="PortfolioManager.Views.BollingerBandView">
<UserControl.Resources>
<local:CurrencyValueConverter x:Key="CurrencyFormat"/>
<local:DoubleValueConverter x:Key="DoubleFormat"/>
@@ -63,157 +62,27 @@
<Label Content="Day Count" HorizontalAlignment="Left" ></Label>
<ComboBox ItemsSource="{Binding Path=DayCounts, Mode=OneWay}" SelectedItem="{Binding Path=SelectedDayCount}"/>
<Button Content="Refresh" HorizontalAlignment="Stretch" Command="{Binding Path=Refresh}"></Button>
<CheckBox Content="Show Least Squares" IsChecked="{Binding Mode=TwoWay,Path=UseLeastSquaresFit}" HorizontalAlignment="Stretch" />
<CheckBox Content="Sync Trade To Band" IsChecked="{Binding Mode=TwoWay,Path=SyncTradeToBand}" HorizontalAlignment="Stretch" />
<CheckBox Content="Show Trade Labels" IsChecked="{Binding Mode=TwoWay,Path=ShowTradeLabels}" HorizontalAlignment="Stretch" />
<CheckBox Content="Show Insider Transactions" IsChecked="{Binding Mode=TwoWay,Path=CheckBoxShowInsiderTransactions}" HorizontalAlignment="Stretch" />
</StackPanel>
</Grid>
</Grid>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="3*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid >
<Grid.RowDefinitions>
<RowDefinition Height="24" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" FontSize="16" Text="{Binding Path=GraphTitle}" HorizontalAlignment="Center"></TextBlock>
<mxc:CartesianChart Grid.Row="1" >
<mxc:CartesianChart.AxesY>
<mxc:AxisY Title="Price" >
<mxc:AxisYRange AlwaysShowZeroLevel="False" />
</mxc:AxisY>
</mxc:CartesianChart.AxesY>
<mxc:CartesianChart.AxesX>
<mxc:AxisX Title="Date"/>
</mxc:CartesianChart.AxesX>
<mxc:CartesianChart.Series>
<mxc:CartesianSeries Name="KSeries" DataAdapter="{Binding K.DataAdapter}" >
<mxc:CartesianLineSeriesView ShowInCrosshair="False" Color="Green" MarkerSize="4" ShowMarkers="{Binding Path=ShowMarkers, Mode=TwoWay}" Thickness="3"/>
</mxc:CartesianSeries>
</mxc:CartesianChart.Series>
<mxc:CartesianChart.Series>
<mxc:CartesianSeries Name="KL1Series" DataAdapter="{Binding KL1.DataAdapter}" >
<mxc:CartesianLineSeriesView ShowInCrosshair="False" Color="Green" MarkerSize="4" ShowMarkers="{Binding Path=ShowMarkers, Mode=TwoWay}" Thickness="2"/>
</mxc:CartesianSeries>
</mxc:CartesianChart.Series>
<mxc:CartesianChart.Series>
<mxc:CartesianSeries Name="LSeries" DataAdapter="{Binding L.DataAdapter}" >
<mxc:CartesianLineSeriesView ShowInCrosshair="False" Color="Green" MarkerSize="4" ShowMarkers="{Binding Path=ShowMarkers, Mode=TwoWay}" Thickness="3"/>
</mxc:CartesianSeries>
</mxc:CartesianChart.Series>
<mxc:CartesianChart.Series>
<mxc:CartesianSeries Name="LP1Series" DataAdapter="{Binding LP1.DataAdapter}" >
<mxc:CartesianLineSeriesView ShowInCrosshair="False" Color="Green" MarkerSize="4" ShowMarkers="{Binding Path=ShowMarkers, Mode=TwoWay}" Thickness="2"/>
</mxc:CartesianSeries>
</mxc:CartesianChart.Series>
<mxc:CartesianChart.Series>
<mxc:CartesianSeries Name="HighSeries" DataAdapter="{Binding High.DataAdapter}" >
<mxc:CartesianLineSeriesView ShowInCrosshair="False" Color="Blue" MarkerSize="4" ShowMarkers="{Binding Path=ShowMarkers, Mode=TwoWay}" Thickness="2"/>
</mxc:CartesianSeries>
</mxc:CartesianChart.Series>
<mxc:CartesianChart.Series>
<mxc:CartesianSeries Name="LowSeries" DataAdapter="{Binding Low.DataAdapter}" >
<mxc:CartesianLineSeriesView ShowInCrosshair="False" Color="Red" MarkerSize="4" ShowMarkers="{Binding Path=ShowMarkers, Mode=TwoWay}" Thickness="2"/>
</mxc:CartesianSeries>
</mxc:CartesianChart.Series>
<mxc:CartesianChart.Series>
<mxc:CartesianSeries Name="CloseSeries" DataAdapter="{Binding Close.DataAdapter}" >
<mxc:CartesianLineSeriesView ShowInCrosshair="False" Color="Black" MarkerSize="4" ShowMarkers="{Binding Path=ShowMarkers, Mode=TwoWay}" Thickness="2"/>
</mxc:CartesianSeries>
</mxc:CartesianChart.Series>
<mxc:CartesianChart.Series>
<mxc:CartesianSeries Name="LeastSquares" DataAdapter="{Binding LeastSquares.DataAdapter}" >
<mxc:CartesianLineSeriesView ShowInCrosshair="False" Color="Orange" MarkerSize="4" ShowMarkers="{Binding Path=ShowMarkers, Mode=TwoWay}" Thickness="2"/>
</mxc:CartesianSeries>
</mxc:CartesianChart.Series>
<mxc:CartesianChart.Series>
<mxc:CartesianSeries Name="SMANSeries" DataAdapter="{Binding SMAN.DataAdapter}" >
<mxc:CartesianLineSeriesView ShowInCrosshair="False" Color="Purple" MarkerSize="4" ShowMarkers="{Binding Path=ShowMarkers, Mode=TwoWay}" Thickness="2"/>
</mxc:CartesianSeries>
</mxc:CartesianChart.Series>
<mxc:CartesianChart.Series>
<mxc:CartesianSeries Name="TradeMarkersPointsGraph" DataAdapter="{Binding TradePoints.DataAdapter}" >
<mxc:CartesianPointSeriesView MarkerImage="{Binding Path=TradePointMarkers, Mode=OneWay}" ShowInCrosshair="False" MarkerSize="{Binding Path=MarkerSize, Converter={StaticResource OSValueConverter},ConverterParameter=25|.5}"/>
</mxc:CartesianSeries>
</mxc:CartesianChart.Series>
<mxc:CartesianChart.Series>
<mxc:CartesianSeries Name="ZeroPointMarkersPointsGraph" DataAdapter="{Binding ZeroPoint.DataAdapter}">
<mxc:CartesianPointSeriesView MarkerImage="{Binding Path=ZeroPointMarkers, Mode=OneWay}" ShowInCrosshair="False" MarkerSize="{Binding Path=MarkerSize, Converter={StaticResource OSValueConverter},ConverterParameter=25|.5}"/>
</mxc:CartesianSeries>
</mxc:CartesianChart.Series>
<!-- <mxc:CartesianChart.Series>
<mxc:CartesianSeries Name="ZeroPointMarkersPointsGraph" DataAdapter="{Binding ZeroPoint.DataAdapter}">
<mxc:CartesianPointSeriesView MarkerImage="{Binding Path=ZeroPointMarkersTextMarkers, Mode=OneWay}" ShowInCrosshair="False" MarkerSize="30" />
</mxc:CartesianSeries>
</mxc:CartesianChart.Series> -->
<mxc:CartesianChart.Series>
<mxc:CartesianSeries Name="StopLimitMarkersPointsGraph" DataAdapter="{Binding StopLimits.DataAdapter}">
<mxc:CartesianPointSeriesView MarkerImage="{Binding Path=StopLimitMarkers, Mode=OneWay}" ShowInCrosshair="False" MarkerSize="{Binding Path=MarkerSize, Converter={StaticResource OSValueConverter},ConverterParameter=25|.5}"/>
</mxc:CartesianSeries>
</mxc:CartesianChart.Series>
<mxc:CartesianChart.Series>
<mxc:CartesianSeries Name="InsiderTransactionsPointMarkersPointsGraphDisposedSmall" DataAdapter="{Binding InsiderTransactionPointDisposedSmall.DataAdapter}" >
<mxc:CartesianPointSeriesView MarkerImage="{Binding Path=InsiderTransactionPointMarkersDisposedSmall, Mode=OneWay}" ShowInCrosshair="False" MarkerSize="{Binding Path=MarkerSize, Converter={StaticResource OSValueConverter},ConverterParameter=20|.5}"/>
</mxc:CartesianSeries>
</mxc:CartesianChart.Series>
<mxc:CartesianChart.Series>
<mxc:CartesianSeries Name="InsiderTransactionsPointMarkersPointsGraphDisposedMedium" DataAdapter="{Binding InsiderTransactionPointDisposedMedium.DataAdapter}" >
<mxc:CartesianPointSeriesView MarkerImage="{Binding Path=InsiderTransactionPointMarkersDisposedMedium, Mode=OneWay}" ShowInCrosshair="False" MarkerSize="{Binding Path=MarkerSize, Converter={StaticResource OSValueConverter},ConverterParameter=30|.5}"/>
</mxc:CartesianSeries>
</mxc:CartesianChart.Series>
<mxc:CartesianChart.Series>
<mxc:CartesianSeries Name="InsiderTransactionsPointMarkersPointsGraphDisposedLarge" DataAdapter="{Binding InsiderTransactionPointDisposedLarge.DataAdapter}" >
<mxc:CartesianPointSeriesView MarkerImage="{Binding Path=InsiderTransactionPointMarkersDisposedLarge, Mode=OneWay}" ShowInCrosshair="False" MarkerSize="{Binding Path=MarkerSize, Converter={StaticResource OSValueConverter},ConverterParameter=40|.5}"/>
</mxc:CartesianSeries>
</mxc:CartesianChart.Series>
<mxc:CartesianChart.Series>
<mxc:CartesianSeries Name="InsiderTransactionsPointMarkersPointsGraphAcquiredSmall" DataAdapter="{Binding InsiderTransactionPointAcquiredSmall.DataAdapter}" >
<mxc:CartesianPointSeriesView MarkerImage="{Binding Path=InsiderTransactionPointMarkersAcquiredSmall, Mode=OneWay}" ShowInCrosshair="False" MarkerSize="{Binding Path=MarkerSize, Converter={StaticResource OSValueConverter},ConverterParameter=20|.5}"/>
</mxc:CartesianSeries>
</mxc:CartesianChart.Series>
<mxc:CartesianChart.Series>
<mxc:CartesianSeries Name="InsiderTransactionsPointMarkersPointsGraphAcquiredMedium" DataAdapter="{Binding InsiderTransactionPointAcquiredMedium.DataAdapter}" >
<mxc:CartesianPointSeriesView MarkerImage="{Binding Path=InsiderTransactionPointMarkersAcquiredMedium, Mode=OneWay}" ShowInCrosshair="False" MarkerSize="{Binding Path=MarkerSize, Converter={StaticResource OSValueConverter},ConverterParameter=30|.5}"/>
</mxc:CartesianSeries>
</mxc:CartesianChart.Series>
<mxc:CartesianChart.Series>
<mxc:CartesianSeries Name="InsiderTransactionsPointMarkersPointsGraphAcquiredLarge" DataAdapter="{Binding InsiderTransactionPointAcquiredLarge.DataAdapter}" >
<mxc:CartesianPointSeriesView MarkerImage="{Binding Path=InsiderTransactionPointMarkersAcquiredLarge, Mode=OneWay}" ShowInCrosshair="False" MarkerSize="{Binding Path=MarkerSize, Converter={StaticResource OSValueConverter},ConverterParameter=40|.5}"/>
</mxc:CartesianSeries>
</mxc:CartesianChart.Series>
</mxc:CartesianChart>
<!-- <ScottPlot:AvaPlot Grid.Row="1" Name="AvaPlot" Loaded="AvaPlot_Loaded"/> -->
<ContentControl Grid.Row="1" Content="{Binding Path=Plotter}"/>
</Grid>
</Grid>
</DockPanel>
</Grid>

View File

@@ -1,13 +1,32 @@
using System;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Interactivity;
using Avalonia.Markup.Xaml;
using PortfolioManager.ViewModels;
using ScottPlot.Avalonia;
namespace PortfolioManager.Views;
public partial class BollingerBandView : UserControl
{
public BollingerBandView()
public BollingerBandView()
{
this.DataContextChanged += OnDataContextChanged;
InitializeComponent();
}
private void OnDataContextChanged(object sender, EventArgs e)
{
if (default != (sender as BollingerBandView))
{
InitializeComponent();
BollingerBandView view = (sender as BollingerBandView);
PlotterWorkspaceViewModel viewModel = (DataContext as PlotterWorkspaceViewModel);
if (null!=viewModel && default == viewModel.Plotter)
{
viewModel.Plotter = new AvaPlot();
viewModel.OnPlotterLoaded(viewModel.Plotter);
}
}
}
}

View File

@@ -21,7 +21,7 @@
</Design.DataContext>
<Window.DataTemplates>
<DataTemplate DataType="vm:MGSHMomentumViewModel">
<!-- <DataTemplate DataType="vm:MGSHMomentumViewModel">
<vw:MGSHMomentumView />
</DataTemplate>
<DataTemplate DataType="vm:MomentumViewModel">
@@ -35,13 +35,10 @@
</DataTemplate>
<DataTemplate DataType="vm:GainLossViewModel">
<vw:GainLossView />
</DataTemplate>
<DataTemplate DataType="vm:BollingerBandViewModel">
</DataTemplate> -->
<!-- <DataTemplate DataType="vm:BollingerBandViewModel">
<vw:BollingerBandView />
</DataTemplate>
<DataTemplate DataType="vm:ScottPlotViewModel">
<vw:ScottPlotView />
</DataTemplate>
</DataTemplate> -->
</Window.DataTemplates>
<Window.Styles>

View File

@@ -1,89 +0,0 @@
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:ScottPlot="clr-namespace:ScottPlot.Avalonia;assembly=ScottPlot.Avalonia"
xmlns:vm="using:PortfolioManager.ViewModels"
xmlns:vw="using:PortfolioManager.Views"
xmlns:md="using:PortfolioManager.Models"
xmlns:local="using:PortfolioManager.UIUtils"
xmlns:li="using:LoadingIndicators.Avalonia"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:DataType="vm:ScottPlotViewModel"
x:Class="PortfolioManager.Views.ScottPlotView">
<UserControl.Resources>
<local:CurrencyValueConverter x:Key="CurrencyFormat"/>
<local:DoubleValueConverter x:Key="DoubleFormat"/>
<local:IntValueConverter x:Key="IntFormat"/>
<local:DateValueConverter x:Key="DateFormat"/>
<local:RMultipleValueConverter x:Key="RMultipleFormat"/>
<local:BoolValueConverter x:Key="BoolFormat"/>
<local:OSValueConverter x:Key="OSValueConverter"/>
</UserControl.Resources>
<Grid Background="LightGray">
<li:LoadingIndicator ZIndex="1" IsActive="{Binding IsBusy}" Mode="Arcs" SpeedRatio="1.2" Width="200" Height="200"/>
<DockPanel>
<Grid Margin="4">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="6" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="3" />
<RowDefinition Height="30" />
<RowDefinition Height="30" />
<RowDefinition Height="30" />
<RowDefinition Height="30" />
<RowDefinition Height="30" />
<RowDefinition Height="89*" />
</Grid.RowDefinitions>
<StackPanel Grid.Row="0" Grid.Column="0" Orientation="Vertical">
<Label Content="Watch List" HorizontalAlignment="Left" ></Label>
<ComboBox ItemsSource="{Binding Path=WatchListNames, Mode=OneWay}" SelectedItem="{Binding Path=SelectedWatchList}">
<ComboBox.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel/>
</ItemsPanelTemplate>
</ComboBox.ItemsPanel>
</ComboBox>
<Label Content="Symbols" HorizontalAlignment="Left" ></Label>
<ComboBox ItemsSource="{Binding Path=Symbols, Mode=OneWay}" SelectedItem="{Binding Path=SelectedSymbol}">
<ComboBox.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel/>
</ItemsPanelTemplate>
</ComboBox.ItemsPanel>
</ComboBox>
<Label Content="Day Count" HorizontalAlignment="Left" ></Label>
<ComboBox ItemsSource="{Binding Path=DayCounts, Mode=OneWay}" SelectedItem="{Binding Path=SelectedDayCount}"/>
<Button Content="Refresh" HorizontalAlignment="Stretch" Command="{Binding Path=Refresh}"></Button>
<CheckBox Content="Show Least Squares" IsChecked="{Binding Mode=TwoWay,Path=UseLeastSquaresFit}" HorizontalAlignment="Stretch" />
<CheckBox Content="Sync Trade To Band" IsChecked="{Binding Mode=TwoWay,Path=SyncTradeToBand}" HorizontalAlignment="Stretch" />
<CheckBox Content="Show Trade Labels" IsChecked="{Binding Mode=TwoWay,Path=ShowTradeLabels}" HorizontalAlignment="Stretch" />
<CheckBox Content="Show Insider Transactions" IsChecked="{Binding Mode=TwoWay,Path=CheckBoxShowInsiderTransactions}" HorizontalAlignment="Stretch" />
</StackPanel>
</Grid>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="3*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid >
<Grid.RowDefinitions>
<RowDefinition Height="24" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" FontSize="16" Text="{Binding Path=GraphTitle}" HorizontalAlignment="Center"></TextBlock>
<!-- <ScottPlot:AvaPlot Grid.Row="1" Name="AvaPlot" Loaded="AvaPlot_Loaded"/> -->
<ContentControl Grid.Row="1" Content="{Binding Path=Plotter}"/>
</Grid>
</Grid>
</DockPanel>
</Grid>
</UserControl>

View File

@@ -1,32 +0,0 @@
using System;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Interactivity;
using Avalonia.Markup.Xaml;
using PortfolioManager.ViewModels;
using ScottPlot.Avalonia;
namespace PortfolioManager.Views;
public partial class ScottPlotView : UserControl
{
public ScottPlotView()
{
this.DataContextChanged += OnDataContextChanged;
InitializeComponent();
}
private void OnDataContextChanged(object sender, EventArgs e)
{
if (default != (sender as ScottPlotView))
{
ScottPlotView view = (sender as ScottPlotView);
PlotterWorkspaceViewModel viewModel = (DataContext as PlotterWorkspaceViewModel);
if (null!=viewModel && default == viewModel.Plotter)
{
viewModel.Plotter = new AvaPlot();
viewModel.OnPlotterLoaded(viewModel.Plotter);
}
}
}
}

View File

@@ -1 +1,19 @@
Type,PortfolioManager.ViewModels.BollingerBandViewModel,SelectedSymbol,KEP,SelectedWatchList,Valuations,SelectedDayCount,180,SyncTradeToBand,False,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,SPY,SelectedWatchList,Valuations,SelectedDayCount,180,SyncTradeToBand,False,ShowTradeLabels,True,UseLeastSquaresFit,True,ShowInsiderTransactions,True
Type,PortfolioManager.ViewModels.BollingerBandViewModel,SelectedSymbol,CRK,SelectedWatchList,Valuations,SelectedDayCount,90,SyncTradeToBand,True,ShowTradeLabels,True,UseLeastSquaresFit,True,ShowInsiderTransactions,True
Type,PortfolioManager.ViewModels.BollingerBandViewModel,SelectedSymbol,JFNNX,SelectedWatchList,Valuations,SelectedDayCount,180,SyncTradeToBand,False,ShowTradeLabels,True,UseLeastSquaresFit,True,ShowInsiderTransactions,True
Type,PortfolioManager.ViewModels.BollingerBandViewModel,SelectedSymbol,VSTCX,SelectedWatchList,Valuations,SelectedDayCount,180,SyncTradeToBand,False,ShowTradeLabels,True,UseLeastSquaresFit,True,ShowInsiderTransactions,True
Type,PortfolioManager.ViewModels.BollingerBandViewModel,SelectedSymbol,PSO,SelectedWatchList,Valuations,SelectedDayCount,180,SyncTradeToBand,False,ShowTradeLabels,True,UseLeastSquaresFit,True,ShowInsiderTransactions,True
Type,PortfolioManager.ViewModels.BollingerBandViewModel,SelectedSymbol,PRIM,SelectedWatchList,Valuations,SelectedDayCount,180,SyncTradeToBand,False,ShowTradeLabels,True,UseLeastSquaresFit,True,ShowInsiderTransactions,True
Type,PortfolioManager.ViewModels.BollingerBandViewModel,SelectedSymbol,RNMBY,SelectedWatchList,Valuations,SelectedDayCount,180,SyncTradeToBand,False,ShowTradeLabels,True,UseLeastSquaresFit,True,ShowInsiderTransactions,True
Type,PortfolioManager.ViewModels.BollingerBandViewModel,SelectedSymbol,DRD,SelectedWatchList,Valuations,SelectedDayCount,180,SyncTradeToBand,False,ShowTradeLabels,True,UseLeastSquaresFit,True,ShowInsiderTransactions,True
Type,PortfolioManager.ViewModels.MGSHMomentumViewModel,PathFileName,C:\3\MGSH20250331.TXT
Type,PortfolioManager.ViewModels.BollingerBandViewModel,SelectedSymbol,SXT,SelectedWatchList,Valuations,SelectedDayCount,360,SyncTradeToBand,True,ShowTradeLabels,True,UseLeastSquaresFit,True,ShowInsiderTransactions,True
Type,PortfolioManager.ViewModels.BollingerBandViewModel,SelectedSymbol,RGLD,SelectedWatchList,Valuations,SelectedDayCount,360,SyncTradeToBand,True,ShowTradeLabels,True,UseLeastSquaresFit,True,ShowInsiderTransactions,True
Type,PortfolioManager.ViewModels.BollingerBandViewModel,SelectedSymbol,PSO,SelectedWatchList,Valuations,SelectedDayCount,360,SyncTradeToBand,True,ShowTradeLabels,True,UseLeastSquaresFit,True,ShowInsiderTransactions,True
Type,PortfolioManager.ViewModels.BollingerBandViewModel,SelectedSymbol,TSCDY,SelectedWatchList,Valuations,SelectedDayCount,360,SyncTradeToBand,True,ShowTradeLabels,True,UseLeastSquaresFit,True,ShowInsiderTransactions,True
Type,PortfolioManager.ViewModels.BollingerBandViewModel,SelectedSymbol,DBX,SelectedWatchList,Valuations,SelectedDayCount,360,SyncTradeToBand,True,ShowTradeLabels,True,UseLeastSquaresFit,True,ShowInsiderTransactions,True
Type,PortfolioManager.ViewModels.BollingerBandViewModel,SelectedSymbol,NRG,SelectedWatchList,Valuations,SelectedDayCount,360,SyncTradeToBand,True,ShowTradeLabels,True,UseLeastSquaresFit,True,ShowInsiderTransactions,True
Type,PortfolioManager.ViewModels.BollingerBandViewModel,SelectedSymbol,OPRA,SelectedWatchList,Valuations,SelectedDayCount,360,SyncTradeToBand,True,ShowTradeLabels,True,UseLeastSquaresFit,True,ShowInsiderTransactions,True
Type,PortfolioManager.ViewModels.BollingerBandViewModel,SelectedSymbol,MO,SelectedWatchList,Valuations,SelectedDayCount,360,SyncTradeToBand,True,ShowTradeLabels,True,UseLeastSquaresFit,True,ShowInsiderTransactions,True
Type,PortfolioManager.ViewModels.BollingerBandViewModel,SelectedSymbol,EXC,SelectedWatchList,Valuations,SelectedDayCount,360,SyncTradeToBand,True,ShowTradeLabels,True,UseLeastSquaresFit,True,ShowInsiderTransactions,True