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 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; 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"); } }); } // ******************************************************************************************************************************************* /// /// 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) { 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("Type", GetType().Namespace + "." + GetType().Name)); // saveParams.Add(new KeyValuePair("SelectedSymbol", selectedSymbol)); // saveParams.Add(new KeyValuePair("SelectedWatchList", selectedWatchList)); // saveParams.Add(new KeyValuePair("SelectedDayCount", selectedDayCount.ToString())); // saveParams.Add(new KeyValuePair("SyncTradeToBand", syncTradeToBand.ToString())); // saveParams.Add(new KeyValuePair("ShowTradeLabels", showTradeLabels.ToString())); // saveParams.Add(new KeyValuePair("UseLeastSquaresFit", useLeastSquaresFit.ToString())); // saveParams.Add(new KeyValuePair("ShowInsiderTransactions", showInsiderTransactions.ToString())); // if (null != stopLimits && 0 != stopLimits.Count) // { // saveParams.Add(new KeyValuePair("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(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 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 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); } } }