Files
TradeBlotter/ViewModels/StickerPriceViewModel.cs
2024-05-24 15:12:29 -04:00

676 lines
23 KiB
C#

using System;
using System.ComponentModel;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.Linq;
using System.Text;
using System.Windows.Media;
using System.Windows.Input;
using System.Threading.Tasks;
using System.Windows;
using MarketData;
using MarketData.Numerical;
using MarketData.Utils;
using MarketData.MarketDataModel;
using MarketData.Generator;
using MarketData.DataAccess;
using TradeBlotter.DataAccess;
using TradeBlotter.Command;
using TradeBlotter.Model;
using Microsoft.Research.DynamicDataDisplay.DataSources;
using TradeBlotter.UIUtils;
using TradeBlotter.Cache;
namespace TradeBlotter.ViewModels
{
public class StickerPriceViewModel : WorkspaceViewModel
{
private RelayCommand copyToClipboardCommand;
private RelayCommand refreshCommand;
private List<String> symbols;
private List<String> watchLists;
private String selectedWatchList;
private String selectedSymbol;
private Price price = null;
private String companyName;
private ObservableCollection<ReturnItem> bvps = null;
private bool busyIndicator = false;
private Prices pricesIndex90 = null;
private Prices pricesIndex720 = null;
private Valuation valuation = null;
private double selectedRequiredReturn = .15;
private double bvpsOverride=double.NaN;
public StickerPriceViewModel()
{
base.DisplayName = "Sticker Price";
watchLists = WatchListDA.GetWatchLists();
watchLists.Insert(0, Constants.CONST_ALL);
selectedWatchList = watchLists.Find(x => x.Equals("Valuations"));
symbols = WatchListDA.GetWatchList(selectedWatchList);
selectedSymbol = null;
pricesIndex90 = PricingDA.GetPrices("SPY", 90);
pricesIndex720 = PricingDA.GetPrices("SPY", 720);
bvps = new ObservableCollection<ReturnItem>();
PropertyChanged += OnStickerPriceViewModelPropertyChanged;
base.OnPropertyChanged("SelectedSymbol");
base.OnPropertyChanged("RequiredReturn");
}
// ******************************************************************************************** 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 (null == 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));
return saveParams;
}
public override void SetSaveParameters(SaveParameters saveParameters)
{
try
{
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;
Referer=saveParameters.Referer;
base.OnPropertyChanged("SelectedWatchList");
base.OnPropertyChanged("SelectedSymbol");
}
catch (Exception exception)
{
MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Exception:{0}",exception.ToString()));
}
}
// ******************************************************************************************************************************************************
public bool BusyIndicator
{
get { return busyIndicator; }
set
{
busyIndicator = value;
base.OnPropertyChanged("BusyIndicator");
}
}
public ObservableCollection<ReturnItem> AllBVPS
{
get {return bvps ;}
set
{
bvps=value ;
base.OnPropertyChanged("AllBVPS");
}
}
private void OnStickerPriceViewModelPropertyChanged(object sender, PropertyChangedEventArgs eventArgs)
{
if (eventArgs.PropertyName.Equals("SelectedSymbol"))
{
base.DisplayName = "Sticker Price(" + selectedSymbol + ")";
base.OnPropertyChanged("DisplayName");
HandleSelectedSymbol();
}
else if (eventArgs.PropertyName.Equals("SelectedWatchList"))
{
HandleSelectedWatchList();
}
else if(eventArgs.PropertyName.Equals("AverageGrowth"))
{
HandleSelectedBVPS();
}
}
private void HandleSelectedBVPS()
{
BusyIndicator = true;
Task workerTask = Task.Factory.StartNew(() =>
{
if (null != selectedSymbol)
{
if(double.NaN.Equals(bvpsOverride))return;
companyName=PricingDA.GetNameForSymbol(selectedSymbol);
price=PricingDA.GetPrice(selectedSymbol);
if(!double.NaN.Equals(bvpsOverride))valuation = ValuationGenerator.GenerateValuationWithOverride(selectedSymbol, pricesIndex90, pricesIndex720,bvpsOverride, null, new ValuationGenerator.OnErrorItemHandler(OnErrorItemHandler));
}
});
workerTask.ContinueWith((continuation) =>
{
BusyIndicator = false;
base.OnPropertyChanged("AllBVPS");
base.OnPropertyChanged("EPS");
base.OnPropertyChanged("PE");
base.OnPropertyChanged("LowPE");
base.OnPropertyChanged("TrailingPE");
base.OnPropertyChanged("AvgLowTrailing");
base.OnPropertyChanged("CurrentEstimatedPrice");
base.OnPropertyChanged("PriceEstimate10Y");
base.OnPropertyChanged("TodaysPriceForRequiredReturn");
base.OnPropertyChanged("LatestPrice");
base.OnPropertyChanged("PricingDate");
base.OnPropertyChanged("MOS");
base.OnPropertyChanged("MOSBackground");
base.OnPropertyChanged("PEBackground");
base.OnPropertyChanged("MOS80");
base.OnPropertyChanged("MOS80Background");
base.OnPropertyChanged("RGV");
base.OnPropertyChanged("BVPS");
base.OnPropertyChanged("PBVPS");
base.OnPropertyChanged("IntrinsicValue");
base.OnPropertyChanged("FundamentalValue");
base.OnPropertyChanged("NetCurrentAssetValuePerShare");
base.OnPropertyChanged("NetCurrentAssetValuePerShareBackground");
base.OnPropertyChanged("DebtToEquity");
base.OnPropertyChanged("DebtToEquityBackground");
base.OnPropertyChanged("DividendYield");
base.OnPropertyChanged("Title");
base.OnPropertyChanged("PCF");
base.OnPropertyChanged("SharesOutstanding");
base.OnPropertyChanged("Beta");
base.OnPropertyChanged("EarningsYield");
base.OnPropertyChanged("EBIT");
base.OnPropertyChanged("EnterpriseValue");
});
}
private void HandleSelectedSymbol()
{
BusyIndicator = true;
Task workerTask = Task.Factory.StartNew(() =>
{
if (null != selectedSymbol)
{
companyName=PricingDA.GetNameForSymbol(selectedSymbol);
price=PricingDA.GetPrice(selectedSymbol);
valuation = ValuationGenerator.GenerateValuation(selectedSymbol, pricesIndex90, pricesIndex720, null, new ValuationGenerator.OnErrorItemHandler(OnErrorItemHandler));
bvps = new ObservableCollection<ReturnItem>();
for (int index = 0; index < valuation.BVPSItems.Count; index++)
{
ReturnItem returnItem = valuation.BVPSItems[index];
bvps.Add(returnItem);
}
}
});
workerTask.ContinueWith((continuation) =>
{
BusyIndicator = false;
base.OnPropertyChanged("AllBVPS");
base.OnPropertyChanged("EPS");
base.OnPropertyChanged("PE");
base.OnPropertyChanged("LowPE");
base.OnPropertyChanged("TrailingPE");
base.OnPropertyChanged("AvgLowTrailing");
base.OnPropertyChanged("CurrentEstimatedPrice");
base.OnPropertyChanged("PriceEstimate10Y");
base.OnPropertyChanged("TodaysPriceForRequiredReturn");
base.OnPropertyChanged("LatestPrice");
base.OnPropertyChanged("PricingDate");
base.OnPropertyChanged("MOS");
base.OnPropertyChanged("MOSBackground");
base.OnPropertyChanged("PEBackground");
base.OnPropertyChanged("MOS80");
base.OnPropertyChanged("MOS80Background");
base.OnPropertyChanged("RGV");
base.OnPropertyChanged("BVPS");
base.OnPropertyChanged("PBVPS");
base.OnPropertyChanged("IntrinsicValue");
base.OnPropertyChanged("FundamentalValue");
base.OnPropertyChanged("NetCurrentAssetValuePerShare");
base.OnPropertyChanged("NetCurrentAssetValuePerShareBackground");
base.OnPropertyChanged("AverageGrowth");
base.OnPropertyChanged("DebtToEquity");
base.OnPropertyChanged("DebtToEquityBackground");
base.OnPropertyChanged("DividendYield");
base.OnPropertyChanged("PExPBVPS");
base.OnPropertyChanged("Title");
base.OnPropertyChanged("PCF");
base.OnPropertyChanged("SharesOutstanding");
base.OnPropertyChanged("Beta");
base.OnPropertyChanged("EarningsYield");
base.OnPropertyChanged("EBIT");
base.OnPropertyChanged("EnterpriseValue");
});
}
public void OnErrorItemHandler(String symbol, String message)
{
}
private void HandleSelectedWatchList()
{
// if (selectedWatchList.Equals(Constants.CONST_ALL)) symbols = PricingDA.GetSymbols();
if (selectedWatchList.Equals(Constants.CONST_ALL)) symbols = SymbolCache.GetInstance().GetSymbols();
else
{
symbols = WatchListDA.GetWatchList(selectedWatchList);
}
base.OnPropertyChanged("Symbols");
}
// *************************************************************************** C O L O R S C H E M E ***************************************************************
public Brush DebtToEquityBackground
{
get
{
if (null == valuation) return null;
if(double.IsNaN(valuation.DebtToEquity)||double.IsInfinity(valuation.DebtToEquity))return BrushCollection.GetContextBrush(BrushCollection.BrushColor.LightGreen);
if (valuation.DebtToEquity>.50 ) return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Red);
return BrushCollection.GetContextBrush(BrushCollection.BrushColor.LightGreen);
}
}
public Brush PExPBVPSBackground
{
get
{
if(null==valuation)return null;
if(double.IsNaN(valuation.PExPBVPS)||double.IsInfinity(valuation.PExPBVPS))return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Red);
if(valuation.PExPBVPS>22.5)return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Red);
return BrushCollection.GetContextBrush(BrushCollection.BrushColor.LightGreen);
}
}
public Brush PEBackground
{
get
{
if(null==valuation)return null;
if(valuation.PE>15 && valuation.PE<25)return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Yellow);
if(valuation.PE>=25)BrushCollection.GetContextBrush(BrushCollection.BrushColor.Red);
return BrushCollection.GetContextBrush(BrushCollection.BrushColor.LightGreen);
}
}
public Brush MOSBackground
{
get
{
if(null==valuation || null==price)return null;
if(price.Close>valuation.MOS)return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Red);
return BrushCollection.GetContextBrush(BrushCollection.BrushColor.LightGreen);
}
}
public Brush MOS80Background
{
get
{
if (null == valuation || null == price) return null;
if (price.Close > valuation.MOS80) return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Red);
return BrushCollection.GetContextBrush(BrushCollection.BrushColor.LightGreen);
}
}
public Brush NetCurrentAssetValuePerShareBackground
{
get
{
if (null == valuation || null == price) return null;
if (price.Close*.67 < valuation.NetCurrentAssetValuePerShare)return BrushCollection.GetContextBrush(BrushCollection.BrushColor.LightGreen);
return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Red);
}
}
// *****************************************************************************************************************************************************************
public override String Title
{
get
{
if (null != companyName && null!=selectedSymbol) return "Sticker Price - (" + selectedSymbol+") "+companyName;
return "Sticker Price";
}
}
public String PCF
{
get
{
return valuation == null ? Constants.CONST_DASHES : Utility.FormatNumber(valuation.PCF(price.Close),2);
}
}
public String SharesOutstanding
{
get
{
return valuation == null ? Constants.CONST_DASHES : Utility.FormatNumber(valuation.SharesOutstanding,0,true);
}
}
public double RequiredReturn
{
get
{
return selectedRequiredReturn;
}
set
{
selectedRequiredReturn = value;
base.OnPropertyChanged("SelectedRequiredReturn");
}
}
public String AverageGrowth
{
get
{
if(!double.NaN.Equals(bvpsOverride))return Utility.FormatPercent(bvpsOverride);
return valuation == null ? Constants.CONST_DASHES : Utility.FormatPercent(valuation.AverageBVPSGrowth);
}
set
{
bvpsOverride=Utility.ParsePercent(value);
base.OnPropertyChanged("AverageGrowth");
}
}
public String DividendYield
{
get
{
if(null==price)return valuation == null ? Constants.CONST_DASHES : Utility.FormatPercent(valuation.DividendYield);
else return Utility.FormatPercent(DividendHistoryGenerator.GetDividendYield(selectedSymbol,price));
}
}
public String EarningsYield
{
get
{
if (null == valuation) return Constants.CONST_DASHES;
if (!double.IsNaN(valuation.EarningsYield)) return Utility.FormatPercent(valuation.EarningsYield);
if (!double.IsNaN(valuation.PE) && !double.IsNaN(valuation.LatestPrice) && 0.00 != valuation.LatestPrice) return Utility.FormatPercent(valuation.PE / valuation.LatestPrice);
return Constants.CONST_DASHES;
}
}
public String EBIT
{
get
{
if (null == valuation || double.IsNaN(valuation.EBIT)) return Constants.CONST_DASHES;
return Utility.FormatCurrency(valuation.EBIT);
}
}
public String EnterpriseValue
{
get
{
if (null == valuation || double.IsNaN(valuation.EnterpriseValue)) return Constants.CONST_DASHES;
return Utility.FormatCurrency(valuation.EnterpriseValue);
}
}
public String Beta
{
get
{
return valuation == null || double.IsNaN(valuation.Beta720) || 0 == valuation.Beta720 ? Constants.CONST_DASHES : Utility.FormatNumber(valuation.Beta720,2);
}
}
public String SharesOustanding
{
get
{
return valuation == null || double.IsNaN(valuation.SharesOutstanding) || 0==valuation.SharesOutstanding? Constants.CONST_DASHES : Utility.FormatNumber(valuation.LatestPrice/(valuation.OperatingCashflow/valuation.SharesOutstanding));
}
}
public String DebtToEquity
{
get
{
return valuation == null ? Constants.CONST_DASHES : Utility.FormatNumber(valuation.DebtToEquity,2);
}
}
public String PExPBVPS
{
get
{
return valuation == null ? Constants.CONST_DASHES : Utility.FormatNumber(valuation.PExPBVPS,2);
}
}
public String LowPE
{
get
{
return valuation == null ? Constants.CONST_DASHES : Utility.FormatCurrency(valuation.LowPE);
}
}
public String TrailingPE
{
get
{
return valuation == null ? Constants.CONST_DASHES : Utility.FormatCurrency(valuation.TrailingPE);
}
}
public String AvgLowTrailing
{
get
{
return valuation == null ? Constants.CONST_DASHES : Utility.FormatCurrency(valuation.AverageLowTrailing);
}
}
public String CurrentEstimatedPrice
{
get
{
return valuation == null ? Constants.CONST_DASHES : Utility.FormatCurrency(valuation.CurrentStockEstimatePrice);
}
}
public String PriceEstimate10Y
{
get
{
return valuation == null ? Constants.CONST_DASHES : Utility.FormatCurrency(valuation.PriceEstimate10Y);
}
}
public String TodaysPriceForRequiredReturn
{
get
{
return valuation == null ? Constants.CONST_DASHES : Utility.FormatCurrency(valuation.TodaysPriceForRequiredReturn);
}
}
public String PE
{
get
{
return valuation == null ? Constants.CONST_DASHES : Utility.FormatNumber(valuation.PE,2);
}
set
{
if(null==valuation)return;
if(null==price)price=new Price();
double modifiedPE=Utility.ParseCurrency(value);
if(modifiedPE.Equals(valuation.PE))return;
valuation.PE=modifiedPE;
if(null!=valuation.EPS&&0!=valuation.EPS)price.Close=valuation.LatestPrice=modifiedPE*valuation.EPS;
base.OnPropertyChanged("PE");
base.OnPropertyChanged("LatestPrice");
base.OnPropertyChanged("PEBackground");
base.OnPropertyChanged("DividendYield");
}
}
public String EPS
{
get
{
return valuation == null ? Constants.CONST_DASHES : Utility.FormatCurrency(valuation.EPS);
}
set
{
if(null==valuation)return;
double modifiedEPS=Utility.ParseCurrency(value);
if(modifiedEPS.Equals(valuation.EPS))return;
valuation.EPS=modifiedEPS;
if(null!=valuation.EPS&&0!=valuation.EPS)valuation.PE=valuation.LatestPrice/valuation.EPS;
base.OnPropertyChanged("EPS");
base.OnPropertyChanged("PE");
base.OnPropertyChanged("PExPBVPS");
base.OnPropertyChanged("LatestPrice");
base.OnPropertyChanged("PEBackground");
base.OnPropertyChanged("PExPBVPSBackground");
}
}
public String LatestPrice
{
get
{
return price == null ? Constants.CONST_DASHES : Utility.FormatCurrency(price.Close);
}
set
{
if(null==valuation)return;
if(null==price)price=new Price();
double modifiedPrice=Utility.ParseCurrency(value);
if(modifiedPrice.Equals(price.Close))return;
price.Close=modifiedPrice;
valuation.LatestPrice=price.Close;
valuation.DividendYield=DividendHistoryGenerator.GetDividendYield(price.Symbol,price);
if(null!=valuation.EPS&&0!=valuation.EPS&&!double.IsNaN(valuation.EPS))valuation.PE=valuation.LatestPrice/valuation.EPS;
if(null!=valuation.BVPS&&0!=valuation.BVPS)valuation.PBVPS=valuation.LatestPrice/valuation.BVPS;
base.OnPropertyChanged("DividendYield");
base.OnPropertyChanged("LatestPrice");
base.OnPropertyChanged("PBVPS");
base.OnPropertyChanged("PE");
base.OnPropertyChanged("PExPBVPS");
base.OnPropertyChanged("PEBackground");
base.OnPropertyChanged("PExPBVPSBackground");
base.OnPropertyChanged("PCF");
}
}
public String PricingDate
{
get
{
return price == null ? Constants.CONST_DASHES : Utility.DateTimeToStringMMHDDHYYYY(price.Date);
}
}
public String MOS
{
get
{
return valuation == null ? Constants.CONST_DASHES : Utility.FormatCurrency(valuation.MOS);
}
}
// *****************************************************************************************************************************************************************
// *****************************************************************************************************************************************************************
public String MOS80
{
get
{
return valuation == null ? Constants.CONST_DASHES : Utility.FormatCurrency(valuation.MOS80);
}
}
public String BVPS
{
get
{
return valuation == null ? Constants.CONST_DASHES : Utility.FormatNumber(valuation.BVPS, 2);
}
}
public String PBVPS
{
get
{
return valuation == null ? Constants.CONST_DASHES : Utility.FormatNumber(valuation.PBVPS, 2);
}
}
public String RGV
{
get
{
return valuation == null ? Constants.CONST_DASHES : Utility.FormatNumber(valuation.RGV, 2);
}
}
public String IntrinsicValue
{
get
{
return valuation == null ? Constants.CONST_DASHES : Utility.FormatCurrency(valuation.IntrinsicValue);
}
}
public String FundamentalValue
{
get
{
return valuation == null ? Constants.CONST_DASHES : Utility.FormatCurrency(valuation.FundamentalValue);
}
}
public String NetCurrentAssetValuePerShare
{
get
{
return valuation == null ? Constants.CONST_DASHES : Utility.FormatCurrency(valuation.NetCurrentAssetValuePerShare);
}
}
public List<String> Symbols
{
get
{
return symbols;
}
}
public String SelectedSymbol
{
get
{
return selectedSymbol;
}
set
{
if (value == selectedSymbol || String.IsNullOrEmpty(value)) return;
selectedSymbol = value;
base.OnPropertyChanged("SelectedSymbol");
}
}
public List<String> WatchListNames
{
get
{
return watchLists;
}
set { ;}
}
public String SelectedWatchList
{
get { return selectedWatchList; }
set { selectedWatchList = value; base.OnPropertyChanged("SelectedWatchList"); }
}
public ICommand RefreshCommand
{
get
{
if (refreshCommand == null)
{
refreshCommand = new RelayCommand(param => this.Refresh(), param => {return true;});
}
return refreshCommand;
}
}
public void Refresh()
{
bvpsOverride=double.NaN;
base.OnPropertyChanged("SelectedSymbol");
}
public ICommand CopyToClipboardCommand
{
get
{
if (copyToClipboardCommand == null)
{
copyToClipboardCommand = new RelayCommand(param => this.CopyToClipboard(), param => this.CanCopyToClipboard);
}
return copyToClipboardCommand;
}
}
public void CopyToClipboard()
{
StringBuilder sb=new StringBuilder();
sb.Append("Date,BVPS,Return").Append("\r\n");;
for(int index=0;index<bvps.Count;index++)
{
ReturnItem returnItem=bvps[index];
sb.Append(Utility.DateTimeToStringMMHDDHYYYY(returnItem.Date)).Append(",").Append(Utility.FormatCurrency(returnItem.Value)).Append(",").Append(Utility.FormatPercent(returnItem.Return));
if(index<bvps.Count-1)sb.Append("\r\n");
}
Clipboard.SetData("Text",sb.ToString());
}
public bool CanCopyToClipboard
{
get
{
if(null==bvps||0==bvps.Count)return false;
return true;
}
}
}
}