using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.ComponentModel; using System.Linq; using System.Text; using System.Threading.Tasks; using DynamicData; using MarketData; using MarketData.Cache; using MarketData.DataAccess; using MarketData.MarketDataModel; using MarketData.Utils; using PortfolioManager.Renderers; using PortfolioManager.UIUtils; using ScottPlot.Avalonia; namespace PortfolioManager.ViewModels { public partial class ScottPlotViewModel : PlotterWorkspaceViewModel { // private AvaPlot plotter = default; private List watchListNames; private String selectedWatchList; private ObservableCollection symbols = new ObservableCollection(); private List dayCounts = new int[] { 60, 90, 180, 360, 720, 1440, 3600 }.ToList(); private int selectedDayCount = 90; private bool isBusy = false; private String selectedSymbol = default; private String companyName = default; BollingerBandRenderer bollingerBandRenderer = default; public ScottPlotViewModel() { DisplayName = "Bollinger"; Plotter = new AvaPlot(); base.OnPropertyChanged("Plotter"); OnPlotterLoadedEventHandler += PlotterLoadedEvent; PropertyChanged += OnViewModelPropertyChanged; Initialize(); } 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"); } }); } // ******************************************************************************************************************************************* /// /// 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 /// /// /// public void PlotterLoadedEvent(object sender, PlotterLoadedEventArgs e) { // Plotter = e.AvaPlot; // Plotter.Plot.Clear(); // Plotter.Refresh(); // base.OnPropertyChanged("SelectedSymbol"); // MDTrace.WriteLine(LogLevel.DEBUG,$"SelectedSymbol:{selectedSymbol}"); // if (default == Plotter) // { // Plotter = e.AvaPlot; // Plotter.Plot.Clear(); // } // else // { // Plotter = e.AvaPlot; // Plotter.Plot.Clear(); // base.OnPropertyChanged("SelectedSymbol"); // } } 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("LeastSquaresFit") || 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.SetData(selectedSymbol, selectedDayCount); bollingerBandRenderer.Render(); }); workerTask.ContinueWith((continuation) => { base.OnPropertyChanged("GraphTitle"); 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; } public override void SetSaveParameters(SaveParameters saveParameters) { } // ****************************************************** P R O P E R T I E S ************************************************ public AvaPlot Plotter { get; set; } = default; 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 WatchListNames { get { return watchListNames; } } public String SelectedWatchList { get { return selectedWatchList; } set { selectedWatchList = value; base.OnPropertyChanged("SelectedWatchList"); } } public ObservableCollection Symbols { get { return symbols; } } public int SelectedDayCount { get { return selectedDayCount; } set { selectedDayCount = value; base.OnPropertyChanged("SelectedDayCount"); } } public List 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 override String Title { get { if (null == selectedSymbol) return DisplayName; return "Bollinger " + "(" + selectedSymbol + ")"; } } } }