Files
Avalonia/PortfolioManager/ViewModels/BollingerBandViewModel.cs

423 lines
15 KiB
C#

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.Extensions;
using PortfolioManager.Renderers;
using PortfolioManager.UIUtils;
namespace PortfolioManager.ViewModels
{
public partial class BollingerBandViewModel : 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 = false;
private bool useLeastSquaresFit = true;
private StopLimits stopLimits = default;
public BollingerBandViewModel()
{
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");
if (default != selectedSymbol)
{
base.OnPropertyChanged("SelectedSymbol");
}
}
private void OnViewModelPropertyChanged(object sender, PropertyChangedEventArgs eventArgs)
{
if(eventArgs.PropertyName.Equals("SelectedWatchList"))
{
IsBusy=true;
Task workerTask = Task.Factory.StartNew(()=>
{
symbols.Clear();
if(UIConstants.CONST_ALL.Equals(selectedWatchList))
{
symbols.AddRange(PricingDA.GetSymbols());
}
else
{
symbols.AddRange(WatchListDA.GetWatchList(selectedWatchList));
}
});
workerTask.ContinueWith((continuation)=>
{
IsBusy=false;
base.OnPropertyChanged("Symbols");
});
}
else 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.ExternalStopLimits = stopLimits;
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 true;
}
public override SaveParameters GetSaveParameters()
{
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)
{
try
{
Task workerTask = Task.Factory.StartNew(() =>
{
Referer = saveParameters.Referer;
selectedSymbol = (from KeyValuePair<String, String> item in saveParameters where item.Key.Equals("SelectedSymbol") select item).FirstOrDefault().Value;
selectedWatchList = (from KeyValuePair<String, String> item in saveParameters where item.Key.Equals("SelectedWatchList") select item).FirstOrDefault().Value;
selectedDayCount = Int32.Parse((from KeyValuePair<String, String> item in saveParameters where item.Key.Equals("SelectedDayCount") select item).FirstOrDefault().Value);
MDTrace.WriteLine(LogLevel.DEBUG, $"BollingerBandViewModel::SetSaveParameters('{selectedSymbol}','{selectedWatchList}','{selectedDayCount}')");
try
{
if (saveParameters.ContainsKey("SyncTradeToBand")) syncTradeToBand = Boolean.Parse((from KeyValuePair<String, String> item in saveParameters where item.Key.Equals("SyncTradeToBand") select item).FirstOrDefault().Value);
else syncTradeToBand = false;
}
catch (Exception) { syncTradeToBand = false; }
try
{
if (saveParameters.ContainsKey("ShowTradeLabels")) showTradeLabels = Boolean.Parse((from KeyValuePair<String, String> item in saveParameters where item.Key.Equals("ShowTradeLabels") select item).FirstOrDefault().Value);
else showTradeLabels = true;
}
catch (Exception) { showTradeLabels = true; }
try
{
if (saveParameters.ContainsKey("UseLeastSquaresFit")) useLeastSquaresFit = Boolean.Parse((from KeyValuePair<String, String> item in saveParameters where item.Key.Equals("UseLeastSquaresFit") select item).FirstOrDefault().Value);
}
catch (Exception) {; }
try
{
if (saveParameters.ContainsKey("ShowInsiderTransactions")) showInsiderTransactions = Boolean.Parse((from KeyValuePair<String, String> item in saveParameters where item.Key.Equals("ShowInsiderTransactions") select item).FirstOrDefault().Value);
}
catch (Exception) {; }
try
{
if (saveParameters.ContainsKey("StopHistoryCount"))
{
stopLimits = StopLimitsExtensions.FromSaveParams(saveParameters);
}
}
catch (Exception exception)
{
MDTrace.WriteLine(LogLevel.DEBUG, String.Format("Exception:{0}", exception.ToString()));
}
});
workerTask.ContinueWith((continuation) =>
{
base.OnPropertyChanged("SelectedWatchList");
base.OnPropertyChanged("SelectedSymbol");
base.OnPropertyChanged("Title");
});
}
catch (Exception exception)
{
MDTrace.WriteLine(LogLevel.DEBUG, exception.ToString());
}
}
// ****************************************************** 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);
}
}
}