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 symbols; private List watchLists; private String selectedWatchList; private String selectedSymbol; private Price price = null; private String companyName; private ObservableCollection 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(); 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("Type", GetType().Namespace + "." + GetType().Name)); saveParams.Add(new KeyValuePair("SelectedSymbol", selectedSymbol)); saveParams.Add(new KeyValuePair("SelectedWatchList", selectedWatchList)); return saveParams; } public override void SetSaveParameters(SaveParameters saveParameters) { try { selectedSymbol = (from KeyValuePair item in saveParameters where item.Key.Equals("SelectedSymbol") select item).FirstOrDefault().Value; selectedWatchList = (from KeyValuePair 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 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(); 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 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 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