using System; using System.Collections.Generic; using System.Linq; using System.Text; using MarketData.DataAccess; using MarketData.Numerical; using MarketData.MarketDataModel; using MarketData.Utils; namespace MarketData.Generator { public class ValuationGenerator { public delegate bool OnItemCompleteHandler(Valuation valuation); public delegate void OnErrorItemHandler(String symbol,String message); private ValuationGenerator() { } public static Valuations GenerateValuations(List symbols,OnItemCompleteHandler onItemCompleteHandler=null,OnErrorItemHandler onErrorItemHandler=null) { try { Valuations valuations = new Valuations(); valuations.ValuationDate = DateTime.Now; Prices pricesIndex90 = PricingDA.GetPrices("SPY",90); Prices pricesIndex720 = PricingDA.GetPrices("SPY", 720); for (int index = 0; index < symbols.Count; index++) { Valuation valuation=GenerateValuation(symbols[index],pricesIndex90,pricesIndex720,onItemCompleteHandler,onErrorItemHandler); if (null == valuation) continue; valuations.Add(valuation); if (null != onItemCompleteHandler) { if (!onItemCompleteHandler(valuation)) break; } } TLBRankGenerator.ApplyTLBRanks(valuations); AcquirersMultipeGenerator.ApplyRanks(valuations); return valuations; } catch (Exception exception) { MDTrace.WriteLine(LogLevel.DEBUG,exception.ToString()); return null; } } public static Valuations GenerateValuations(OnItemCompleteHandler onItemCompleteHandler=null,OnErrorItemHandler onErrorItemHandler=null) { try { List symbols = PricingDA.GetSymbols(); Valuations valuations = new Valuations(); valuations.ValuationDate = DateTime.Now; Prices pricesIndex90 = PricingDA.GetPrices("SPY",90); Prices pricesIndex720 = PricingDA.GetPrices("SPY", 720); for (int index = 0; index < symbols.Count; index++) { Valuation valuation=GenerateValuation(symbols[index],pricesIndex90,pricesIndex720,onItemCompleteHandler,onErrorItemHandler); if (null == valuation) continue; valuations.Add(valuation); if (null != onItemCompleteHandler) { if (!onItemCompleteHandler(valuation)) break; } } TLBRankGenerator.ApplyTLBRanks(valuations); AcquirersMultipeGenerator.ApplyRanks(valuations); return valuations; } catch (Exception exception) { MDTrace.WriteLine(LogLevel.DEBUG,exception.ToString()); return null; } } public static Valuation GenerateValuation(String symbol,Prices pricesIndex90,Prices pricesIndex720,OnItemCompleteHandler onItemCompleteHandler=null,OnErrorItemHandler onErrorItemHandler=null) { try { Valuation valuation = new Valuation(); symbol = symbol.ToUpper(); String companyName = PricingDA.GetNameForSymbol(symbol); Price price = PricingDA.GetPrice(symbol); CompanyProfile companyProfile=CompanyProfileDA.GetCompanyProfile(symbol); Prices pricesSymbol90=PricingDA.GetPrices(symbol,90); Prices pricesSymbol720=PricingDA.GetPrices(symbol,720); if (null == price) { if (null != onErrorItemHandler) onErrorItemHandler(symbol, "No Prices."); return null; } IncomeStatement incomeStatement=IncomeStatementDA.GetIncomeStatement(symbol,IncomeStatement.PeriodType.Annual); CashflowStatement cashflowStatement=CashflowStatementDA.GetCashflowStatement(symbol,CashflowStatement.PeriodType.Annual); BalanceSheet balanceSheet = BalanceSheetDA.GetBalanceSheet(symbol,BalanceSheet.PeriodType.Annual); TimeSeriesCollection bookValuePerShareCollection = HistoricalDA.GetTimeSeries(symbol, TimeSeriesElement.ElementType.BVPS); TimeSeriesCollection epsCollection = HistoricalDA.GetTimeSeries(symbol, TimeSeriesElement.ElementType.EPS); TimeSeriesCollection roicCollection = HistoricalDA.GetTimeSeries(symbol, TimeSeriesElement.ElementType.ROIC); TimeSeriesCollection revenueCollection = HistoricalDA.GetTimeSeries(symbol, TimeSeriesElement.ElementType.Revenue); TimeSeriesCollection freeCashflowCollection = HistoricalDA.GetTimeSeries(symbol, TimeSeriesElement.ElementType.FreeCashflow); TimeSeriesCollection operatingCashflowCollection = HistoricalDA.GetTimeSeries(symbol, TimeSeriesElement.ElementType.OperatingCashflow); TimeSeriesCollection workingCapitalCollection = HistoricalDA.GetTimeSeries(symbol, TimeSeriesElement.ElementType.WorkingCapital); if (null == bookValuePerShareCollection || 0 == bookValuePerShareCollection.Count) { bookValuePerShareCollection=new TimeSeriesCollection(); TimeSeriesElement timeSeriesElement=new TimeSeriesElement(); timeSeriesElement.AsOf=DateTime.Now; timeSeriesElement.Value=0; bookValuePerShareCollection.Add(new TimeSeriesElement()); } Fundamental fundamental = FundamentalDA.GetFundamental(symbol); if (null == fundamental) { if (null != onErrorItemHandler) onErrorItemHandler(symbol, "No Fundamental Data."); return null; } AnalystPriceTarget analystPriceTarget = AnalystPriceTargetDA.GetAnalystPriceTarget(symbol); // These series are ordered by date with the latest date appearing at the lowest ordinal index. float[] bookValuesPerShareSeries = bookValuePerShareCollection.ToFloat(); float[] epsSeries = epsCollection.ToFloat(); float[] roicSeries = roicCollection.ToFloat(); float[] revenueSeries = revenueCollection.ToFloat(); float[] freeCashflowSeries = freeCashflowCollection.ToFloat(); float[] operatingCashflowSeries = operatingCashflowCollection.ToFloat(); float[] workingCapitalSeries = workingCapitalCollection.ToFloat(); double averageGrowth = Numerics.AverageReturn(ref bookValuesPerShareSeries); double averageGrowth2Year = Numerics.AverageReturnTop(ref bookValuesPerShareSeries, 2); double averageGrowth4Year = Numerics.AverageReturnTop(ref bookValuesPerShareSeries, 4); double epsGrowth = Numerics.AverageReturn(ref epsSeries); double epsGrowth2Year = Numerics.AverageReturnTop(ref epsSeries, 2); double epsGrowth4Year = Numerics.AverageReturnTop(ref epsSeries, 4); double roic = Numerics.Mean(ref roicSeries); double revenueGrowth = Numerics.AverageReturn(ref revenueSeries); double revenueGrowth2Year = Numerics.AverageReturnTop(ref revenueSeries, 2); double revenueGrowth4Year = Numerics.AverageReturnTop(ref revenueSeries, 4); double freeCashflowGrowth = Numerics.AverageReturn(ref freeCashflowSeries); double averageOperatingCashflow = Numerics.Mean(ref operatingCashflowSeries); double averageWorkingCapital = Numerics.Mean(ref workingCapitalSeries); double latestPrice = price.Close; // Shares Oustanding valuation.SharesOutstanding=fundamental.SharesOutstanding; // Dividend Yield valuation.DividendYield=DividendHistoryGenerator.GetDividendYield(symbol); // Benjamin Graham Formula. EPS=Trailing Twelve month, 8.5=PE base for no growth company, g=reasonably expected 7-10 year growth rate double intrinsicValue =GrahamGenerator.IntrinsicValue(fundamental.EPS,epsGrowth); valuation.FundamentalValue=GrahamGenerator.GrahamNumber(fundamental.EPS,fundamental.BookValuePerShare); if(0!=fundamental.SharesOutstanding&&!double.IsNaN(fundamental.SharesOutstanding)&&null!=balanceSheet&&!double.IsNaN(balanceSheet.NetCurrentAssetValue))valuation.NetCurrentAssetValuePerShare=balanceSheet.NetCurrentAssetValue/fundamental.SharesOutstanding; else valuation.NetCurrentAssetValuePerShare=double.NaN; valuation.DebtToEquity=fundamental.DebtToEquity; // ************************************************************************************************************************************************** valuation.MarketCap=fundamental.MarketCap; valuation.EnterpriseValue=fundamental.EnterpriseValue; valuation.EBIT=fundamental.EBIT; // ******************************************************* T H E L I T T L E B O O K ******************************************************* // Calculate the earnings yield to be used by TLB rankings (TLB=The Little Book) // earnings_yield=EBIT/EnterpriseValue if(!double.IsNaN(fundamental.EBIT)&&null!=balanceSheet&&!double.IsNaN(balanceSheet.NetFixedAssets)) { valuation.LatestROC=fundamental.EBIT/balanceSheet.NetFixedAssets; } else valuation.LatestROC=double.NaN; if(!double.IsNaN(fundamental.EBIT)&&!double.IsNaN(fundamental.EnterpriseValue)&&fundamental.EnterpriseValue>0.00&&fundamental.EBIT>0.00) { valuation.EarningsYield=fundamental.EBIT/fundamental.EnterpriseValue; } else valuation.EarningsYield=double.NaN; // ******************************************************** T H E A C Q U I R E R S M U L T I P L E ******************************************** if(null!=fundamental&&!double.IsNaN(fundamental.EnterpriseValue)&&null!=cashflowStatement&&!double.IsNaN(cashflowStatement.DepreciationAndAmortization)&&null!=incomeStatement&&!double.IsNaN(incomeStatement.TotalRevenue)&&!double.IsNaN(incomeStatement.CostOfRevenue)&&!double.IsNaN(incomeStatement.SGA)) { valuation.OperatingEarnings=incomeStatement.TotalRevenue-(cashflowStatement.DepreciationAndAmortization+incomeStatement.CostOfRevenue+incomeStatement.SGA); valuation.AcquirersMultiple=fundamental.EnterpriseValue/valuation.OperatingEarnings; } else { valuation.OperatingEarnings=double.NaN; valuation.AcquirersMultiple=double.NaN; } // ******************************************************************** S E C F O R M 1 3 D ********************************************************************************************* SEC13Info sec13Info=SECFilingDA.GetSEC13Info(symbol); if(sec13Info.SEC13) { valuation.SEC13=true; valuation.SEC13FilingDate=sec13Info.MostRecentFilingDate; } // ***************************************************************************************************************************************************************************************** valuation.Company=companyName.Replace(",", ""); valuation.Symbol=symbol; valuation.NextEarningsDate=fundamental.NextEarningsDate; valuation.Beta90 = BetaGenerator.Beta(symbol, PricingDA.GetLatestDate(symbol),3); valuation.Beta720 = BetaGenerator.Beta(symbol, PricingDA.GetLatestDate(symbol),24); if (null != roicSeries && roicSeries.Length > 0) { valuation.ROICDates = Utility.FormatDates(roicCollection[roicCollection.Count - 1].AsOf, roicCollection[0].AsOf); TimeSeriesElement[] roicTimeSeriesElement=(from roicItem in roicCollection select roicItem).OrderBy(roicItem => roicItem.AsOf).ToArray(); double[] orderedROICValues=(from element in roicTimeSeriesElement select element.Value).ToArray(); valuation.ROICSlope = Numerics.Slope(orderedROICValues); valuation.LatestROIC=roicCollection[0].Value; } if (null != revenueSeries && revenueSeries.Length > 0 && null != balanceSheet && !double.IsNaN(balanceSheet.LongTermDebt)) { double latestRevenue = revenueSeries[0]; valuation.LongTermDebt=balanceSheet.LongTermDebt; valuation.Revenue=latestRevenue; if (latestRevenue * 3 > balanceSheet.LongTermDebt) valuation.DebtLoad="Pass"; else valuation.DebtLoad="Fail"; } else { valuation.LongTermDebt=double.NaN; valuation.Revenue=double.NaN; valuation.DebtLoad="N/A"; } valuation.AverageROIC=roic / 100.00; if (null != bookValuePerShareCollection && 0 != bookValuePerShareCollection.Count) { valuation.BVPS = bookValuePerShareCollection[0].Value; valuation.BVPSDates = Utility.FormatDates(bookValuePerShareCollection[bookValuePerShareCollection.Count - 1].AsOf, bookValuePerShareCollection[0].AsOf); } else valuation.BVPSDates = "N/A"; valuation.AverageEquityGrowth=averageGrowth; valuation.AverageEquityGrowth2Y=averageGrowth2Year; valuation.AverageEquityGrowth4Y=averageGrowth4Year; if (null != epsCollection && epsCollection.Count > 0) valuation.EPSDates = Utility.FormatDates(epsCollection[epsCollection.Count - 1].AsOf, epsCollection[0].AsOf); else valuation.EPSDates="N/A"; valuation.AverageEPSGrowth=epsGrowth; valuation.AverageEPSGrowth2Y=epsGrowth2Year; valuation.AverageEPSGrowth4Y=epsGrowth4Year; if (null != revenueCollection && revenueCollection.Count > 0) valuation.RevenueDates = Utility.FormatDates(revenueCollection[revenueCollection.Count - 1].AsOf, revenueCollection[0].AsOf); else valuation.RevenueDates="N/A"; valuation.AverageRevenueGrowth=revenueGrowth; valuation.AverageRevenueGrowth2Y=revenueGrowth2Year; valuation.AverageRevenueGrowth4Y=revenueGrowth4Year; valuation.AverageFreeCashflowGrowth=freeCashflowGrowth; valuation.AverageOperatingCashflow=averageOperatingCashflow; valuation.OperatingCashflow=null!=operatingCashflowSeries&&operatingCashflowSeries.Length>0?operatingCashflowSeries[0]:double.NaN; valuation.AverageWorkingCapital=averageWorkingCapital; if(null!=companyProfile) { valuation.Industry=companyProfile.Industry; valuation.Sector=companyProfile.Sector; } valuation.EPS=fundamental.EPS; valuation.PE=latestPrice / fundamental.EPS; valuation.PEG = fundamental.PEG; if(!double.IsNaN(valuation.BVPS)&&!double.IsNaN(latestPrice))valuation.PBVPS=latestPrice/valuation.BVPS; if (!double.IsNaN(valuation.PE) && !double.IsNaN(valuation.PEG)) valuation.ImpliedEarningsGrowth = (valuation.PE / valuation.PEG) / 100.00; StickerPrice stickerPrice = new StickerPrice(symbol); valuation.BVPSItems = stickerPrice.BVPSItems; valuation.AverageBVPSGrowth = stickerPrice.AverageBVPSGrowth; valuation.LowPE=stickerPrice.LowPE; valuation.TrailingPE=stickerPrice.TrailingPE; valuation.AverageLowTrailing=stickerPrice.AverageLowTrailing; valuation.CurrentStockEstimatePrice=stickerPrice.CurrentStockEstimatePrice; valuation.PriceEstimate10Y=stickerPrice.PriceEstimate10y; valuation.TodaysPriceForRequiredReturn=stickerPrice.TodaysPriceForRequiredReturn; valuation.MOS=stickerPrice.MarginOfSafety; valuation.MOS80=stickerPrice.MarginOfSafety80Pcnt; valuation.IntrinsicValue=intrinsicValue; valuation.RGV=intrinsicValue/latestPrice; valuation.LatestPrice=latestPrice; if (null != analystPriceTarget) { valuation.MeanTargetPrice=analystPriceTarget.MeanTargetPrice; valuation.LowTargetPrice=analystPriceTarget.LowTargetPrice; valuation.HighTargetPrice=analystPriceTarget.HighTargetPrice; } else { valuation.MeanTargetPrice=double.NaN; valuation.LowTargetPrice=double.NaN; valuation.HighTargetPrice=double.NaN; } valuation.UpsidePcnt = double.IsNaN(valuation.HighTargetPrice)||0>=valuation.HighTargetPrice ? double.NaN : (valuation.HighTargetPrice - valuation.LatestPrice) / valuation.LatestPrice; valuation.DownsidePcnt=double.IsNaN(valuation.LowTargetPrice)||0>=valuation.LowTargetPrice?double.NaN:(valuation.LowTargetPrice-valuation.LatestPrice)/valuation.LatestPrice; valuation.Bargain=latestPrice < stickerPrice.MarginOfSafety ? true : false; valuation.Bargain80=latestPrice < stickerPrice.MarginOfSafety80Pcnt ? true : false; return valuation; } catch (Exception exception) { MDTrace.WriteLine(LogLevel.DEBUG,"Error calculating sticker for '" + symbol + "', exception was " + exception.ToString()); return null; } } public static Valuation GenerateValuationWithOverride(String symbol,Prices pricesIndex90,Prices pricesIndex720,double bvpsGrowthOverride,OnItemCompleteHandler onItemCompleteHandler=null,OnErrorItemHandler onErrorItemHandler=null) { try { Valuation valuation = new Valuation(); symbol = symbol.ToUpper(); String companyName = PricingDA.GetNameForSymbol(symbol); Price price = PricingDA.GetPrice(symbol); CompanyProfile companyProfile=CompanyProfileDA.GetCompanyProfile(symbol); Prices pricesSymbol90=PricingDA.GetPrices(symbol,90); Prices pricesSymbol720=PricingDA.GetPrices(symbol,720); if (null == price) { if (null != onErrorItemHandler) onErrorItemHandler(symbol, "No Prices."); return null; } BalanceSheet balanceSheet = BalanceSheetDA.GetBalanceSheet(symbol,BalanceSheet.PeriodType.Annual); IncomeStatement incomeStatement=IncomeStatementDA.GetIncomeStatement(symbol,IncomeStatement.PeriodType.Annual); CashflowStatement cashflowStatement=CashflowStatementDA.GetCashflowStatement(symbol,CashflowStatement.PeriodType.Annual); // These series are ordered by date with the latest date appearing at the lowest ordinal index TimeSeriesCollection bookValuePerShareCollection = HistoricalDA.GetTimeSeries(symbol, TimeSeriesElement.ElementType.BVPS); TimeSeriesCollection epsCollection = HistoricalDA.GetTimeSeries(symbol, TimeSeriesElement.ElementType.EPS); TimeSeriesCollection roicCollection = HistoricalDA.GetTimeSeries(symbol, TimeSeriesElement.ElementType.ROIC); TimeSeriesCollection revenueCollection = HistoricalDA.GetTimeSeries(symbol, TimeSeriesElement.ElementType.Revenue); TimeSeriesCollection freeCashflowCollection = HistoricalDA.GetTimeSeries(symbol, TimeSeriesElement.ElementType.FreeCashflow); TimeSeriesCollection operatingCashflowCollection = HistoricalDA.GetTimeSeries(symbol, TimeSeriesElement.ElementType.OperatingCashflow); TimeSeriesCollection workingCapitalCollection = HistoricalDA.GetTimeSeries(symbol, TimeSeriesElement.ElementType.WorkingCapital); if (null == bookValuePerShareCollection || 0 == bookValuePerShareCollection.Count) { bookValuePerShareCollection=new TimeSeriesCollection(); TimeSeriesElement timeSeriesElement=new TimeSeriesElement(); timeSeriesElement.AsOf=DateTime.Now; timeSeriesElement.Value=0; bookValuePerShareCollection.Add(new TimeSeriesElement()); } Fundamental fundamental = FundamentalDA.GetFundamental(symbol); if (null == fundamental) { if (null != onErrorItemHandler) onErrorItemHandler(symbol, "No Fundamental Data."); return null; } AnalystPriceTarget analystPriceTarget = AnalystPriceTargetDA.GetAnalystPriceTarget(symbol); float[] bookValuesPerShareSeries = bookValuePerShareCollection.ToFloat(); float[] epsSeries = epsCollection.ToFloat(); float[] roicSeries = roicCollection.ToFloat(); float[] revenueSeries = revenueCollection.ToFloat(); float[] freeCashflowSeries = freeCashflowCollection.ToFloat(); float[] operatingCashflowSeries = operatingCashflowCollection.ToFloat(); float[] workingCapitalSeries = workingCapitalCollection.ToFloat(); double averageGrowth = bvpsGrowthOverride; double averageGrowth2Year = bvpsGrowthOverride; double averageGrowth4Year = bvpsGrowthOverride; double epsGrowth = Numerics.AverageReturn(ref epsSeries); double epsGrowth2Year = Numerics.AverageReturnTop(ref epsSeries, 2); double epsGrowth4Year = Numerics.AverageReturnTop(ref epsSeries, 4); double roic = Numerics.Mean(ref roicSeries); double revenueGrowth = Numerics.AverageReturn(ref revenueSeries); double revenueGrowth2Year = Numerics.AverageReturnTop(ref revenueSeries, 2); double revenueGrowth4Year = Numerics.AverageReturnTop(ref revenueSeries, 4); double freeCashflowGrowth = Numerics.AverageReturn(ref freeCashflowSeries); double averageOperatingCashflow = Numerics.Mean(ref operatingCashflowSeries); double averageWorkingCapital = Numerics.Mean(ref workingCapitalSeries); double latestPrice = price.Close; // Shares Oustanding valuation.SharesOutstanding=fundamental.SharesOutstanding; // Dividend Yield valuation.DividendYield=DividendHistoryGenerator.GetDividendYield(symbol); // Benjamin Graham Formula. EPS=Trailing Twelve month, 8.5=PE base for no growth company, g=reasonably expected 7-10 year growth rate double intrinsicValue = GrahamGenerator.IntrinsicValue(fundamental.EPS,epsGrowth); valuation.FundamentalValue=GrahamGenerator.GrahamNumber(fundamental.EPS,fundamental.BookValuePerShare); if(0!=fundamental.SharesOutstanding&&!double.IsNaN(fundamental.SharesOutstanding)&&null!=balanceSheet&&!double.IsNaN(balanceSheet.NetCurrentAssetValue))valuation.NetCurrentAssetValuePerShare=balanceSheet.NetCurrentAssetValue/fundamental.SharesOutstanding; else valuation.NetCurrentAssetValuePerShare=double.NaN; valuation.DebtToEquity=fundamental.DebtToEquity; // ************************************************************************************************************************************************** valuation.MarketCap=fundamental.MarketCap; valuation.EnterpriseValue=fundamental.EnterpriseValue; valuation.EBIT=fundamental.EBIT; // ******************************************************* T H E L I T T L E B O O K ******************************************************* // Calculate the earnings yield to be used by TLB rankings (TLB=The Little Book) // earnings_yield=EBIT/EnterpriseValue if(!double.IsNaN(fundamental.EBIT)&&!double.IsNaN(fundamental.EnterpriseValue)&&fundamental.EnterpriseValue>0.00&&fundamental.EBIT>0.00) { valuation.EarningsYield=fundamental.EBIT/fundamental.EnterpriseValue; } else valuation.EarningsYield=double.NaN; // ******************************************************** T H E A C Q U I R E R S M U L T I P L E ******************************************** if(null!=fundamental&&!double.IsNaN(fundamental.EnterpriseValue)&&null!=cashflowStatement&&!double.IsNaN(cashflowStatement.DepreciationAndAmortization)&&null!=incomeStatement&&!double.IsNaN(incomeStatement.TotalRevenue)&&!double.IsNaN(incomeStatement.CostOfRevenue)&&!double.IsNaN(incomeStatement.SGA)) { valuation.OperatingEarnings=incomeStatement.TotalRevenue-(cashflowStatement.DepreciationAndAmortization+incomeStatement.CostOfRevenue+incomeStatement.SGA); valuation.AcquirersMultiple=fundamental.EnterpriseValue/valuation.OperatingEarnings; } else { valuation.OperatingEarnings=double.NaN; valuation.AcquirersMultiple=double.NaN; } // ******************************************************************** S E C F O R M 1 3 D ********************************************************************************************* SEC13Info sec13Info=SECFilingDA.GetSEC13Info(symbol); if(sec13Info.SEC13) { valuation.SEC13=true; valuation.SEC13FilingDate=sec13Info.MostRecentFilingDate; } // ***************************************************************************************************************************************************************************************** if(null!=companyProfile) { valuation.Industry=companyProfile.Industry; valuation.Sector=companyProfile.Sector; } valuation.Company=companyName.Replace(",", ""); valuation.Symbol=symbol; valuation.NextEarningsDate=fundamental.NextEarningsDate; valuation.Beta90 = BetaGenerator.Beta(symbol, PricingDA.GetLatestDate(symbol), 3); valuation.Beta720 = BetaGenerator.Beta(symbol, PricingDA.GetLatestDate(symbol), 24); if (null != roicSeries && roicSeries.Length > 0) { valuation.ROICDates = Utility.FormatDates(roicCollection[roicCollection.Count - 1].AsOf, roicCollection[0].AsOf); TimeSeriesElement[] roicTimeSeriesElement=(from roicItem in roicCollection select roicItem).OrderBy(roicItem => roicItem.AsOf).ToArray(); double[] orderedROICValues=(from element in roicTimeSeriesElement select element.Value).ToArray(); valuation.ROICSlope = Numerics.Slope(orderedROICValues); valuation.LatestROIC=roicCollection[0].Value; } if (null != revenueSeries && revenueSeries.Length > 0 && null != balanceSheet && !double.IsNaN(balanceSheet.LongTermDebt)) { double latestRevenue = revenueSeries[0]; valuation.LongTermDebt=balanceSheet.LongTermDebt; valuation.Revenue=latestRevenue; if (latestRevenue * 3 > balanceSheet.LongTermDebt) valuation.DebtLoad="Pass"; else valuation.DebtLoad="Fail"; } else { valuation.LongTermDebt=double.NaN; valuation.Revenue=double.NaN; valuation.DebtLoad="N/A"; } valuation.AverageROIC=roic / 100.00; if (null != bookValuePerShareCollection && 0 != bookValuePerShareCollection.Count) { valuation.BVPS = bookValuePerShareCollection[0].Value; valuation.BVPSDates = Utility.FormatDates(bookValuePerShareCollection[bookValuePerShareCollection.Count - 1].AsOf, bookValuePerShareCollection[0].AsOf); } else valuation.BVPSDates = "N/A"; valuation.AverageEquityGrowth=averageGrowth; valuation.AverageEquityGrowth2Y=averageGrowth2Year; valuation.AverageEquityGrowth4Y=averageGrowth4Year; if (null != epsCollection && epsCollection.Count > 0) valuation.EPSDates = Utility.FormatDates(epsCollection[epsCollection.Count - 1].AsOf, epsCollection[0].AsOf); else valuation.EPSDates="N/A"; valuation.AverageEPSGrowth=epsGrowth; valuation.AverageEPSGrowth2Y=epsGrowth2Year; valuation.AverageEPSGrowth4Y=epsGrowth4Year; if (null != revenueCollection && revenueCollection.Count > 0) valuation.RevenueDates = Utility.FormatDates(revenueCollection[revenueCollection.Count - 1].AsOf, revenueCollection[0].AsOf); else valuation.RevenueDates="N/A"; valuation.AverageRevenueGrowth=revenueGrowth; // if (null != fundamental) valuation.AverageRevenueGrowthQtr=fundamental.QtrlyRevenueGrowth / 100.00; // else valuation.AverageRevenueGrowthQtr=double.NaN; valuation.AverageRevenueGrowth2Y=revenueGrowth2Year; valuation.AverageRevenueGrowth4Y=revenueGrowth4Year; valuation.AverageFreeCashflowGrowth=freeCashflowGrowth; valuation.AverageOperatingCashflow=averageOperatingCashflow; valuation.OperatingCashflow=null!=operatingCashflowSeries&&operatingCashflowSeries.Length>0?operatingCashflowSeries[0]:double.NaN; valuation.AverageWorkingCapital=averageWorkingCapital; valuation.EPS=fundamental.EPS; valuation.PE=latestPrice / fundamental.EPS; valuation.PEG = fundamental.PEG; if(!double.IsNaN(valuation.BVPS)&&!double.IsNaN(latestPrice))valuation.PBVPS=latestPrice/valuation.BVPS; if (!double.IsNaN(valuation.PE) && !double.IsNaN(valuation.PEG)) valuation.ImpliedEarningsGrowth = (valuation.PE / valuation.PEG) / 100.00; StickerPrice stickerPrice = new StickerPrice(symbol,bvpsGrowthOverride); valuation.BVPSItems = stickerPrice.BVPSItems; valuation.AverageBVPSGrowth = stickerPrice.AverageBVPSGrowth; valuation.LowPE=stickerPrice.LowPE; valuation.TrailingPE=stickerPrice.TrailingPE; valuation.AverageLowTrailing=stickerPrice.AverageLowTrailing; valuation.CurrentStockEstimatePrice=stickerPrice.CurrentStockEstimatePrice; valuation.PriceEstimate10Y=stickerPrice.PriceEstimate10y; valuation.TodaysPriceForRequiredReturn=stickerPrice.TodaysPriceForRequiredReturn; valuation.MOS=stickerPrice.MarginOfSafety; valuation.MOS80=stickerPrice.MarginOfSafety80Pcnt; valuation.IntrinsicValue=intrinsicValue; valuation.RGV=intrinsicValue/latestPrice; valuation.LatestPrice=latestPrice; if (null != analystPriceTarget) { valuation.MeanTargetPrice=analystPriceTarget.MeanTargetPrice; valuation.LowTargetPrice=analystPriceTarget.LowTargetPrice; valuation.HighTargetPrice=analystPriceTarget.HighTargetPrice; } else { valuation.MeanTargetPrice=double.NaN; valuation.LowTargetPrice=double.NaN; valuation.HighTargetPrice=double.NaN; } valuation.UpsidePcnt = double.IsNaN(valuation.HighTargetPrice)||0>=valuation.HighTargetPrice ? double.NaN : (valuation.HighTargetPrice - valuation.LatestPrice) / valuation.LatestPrice; valuation.DownsidePcnt=double.IsNaN(valuation.LowTargetPrice)||0>=valuation.LowTargetPrice?double.NaN:(valuation.LowTargetPrice-valuation.LatestPrice)/valuation.LatestPrice; valuation.Bargain=latestPrice < stickerPrice.MarginOfSafety ? true : false; valuation.Bargain80=latestPrice < stickerPrice.MarginOfSafety80Pcnt ? true : false; return valuation; } catch (Exception exception) { MDTrace.WriteLine(LogLevel.DEBUG,"Error calculating sticker for '" + symbol + "', exception was " + exception.ToString()); return null; } } public static String ToString(Valuation valuation) { StringBuilder sb = new StringBuilder(); sb.Append(valuation.Company).Append(","); sb.Append(valuation.Symbol).Append(","); sb.Append(Utility.DateTimeToStringMMHDDHYYYY(valuation.NextEarningsDate)).Append(","); sb.Append(Utility.FormatNumber(valuation.LongTermDebt)).Append(","); sb.Append(Utility.FormatNumber(valuation.Revenue)).Append(","); sb.Append(valuation.DebtLoad).Append(","); sb.Append(Utility.FormatNumber(valuation.AverageROIC)).Append(","); sb.Append(valuation.BVPSDates).Append(","); sb.Append(Utility.FormatNumber(valuation.AverageEquityGrowth)).Append(","); sb.Append(Utility.FormatNumber(valuation.AverageEquityGrowth2Y)).Append(","); sb.Append(Utility.FormatNumber(valuation.AverageEquityGrowth4Y)).Append(","); sb.Append(valuation.EPSDates).Append(","); sb.Append(Utility.FormatNumber(valuation.AverageEPSGrowth)).Append(","); sb.Append(Utility.FormatNumber(valuation.AverageEPSGrowth2Y)).Append(","); sb.Append(Utility.FormatNumber(valuation.AverageEPSGrowth4Y)).Append(","); sb.Append(valuation.RevenueDates).Append(","); sb.Append(Utility.FormatNumber(valuation.AverageRevenueGrowth)).Append(","); // sb.Append(valuation.AverageRevenueGrowthQtr).Append(","); sb.Append(Utility.FormatNumber(valuation.AverageRevenueGrowth2Y)).Append(","); sb.Append(Utility.FormatNumber(valuation.AverageRevenueGrowth4Y)).Append(","); sb.Append(Utility.FormatNumber(valuation.AverageFreeCashflowGrowth)).Append(","); sb.Append(Utility.FormatNumber(valuation.AverageOperatingCashflow)).Append(","); sb.Append(Utility.FormatNumber(valuation.AverageWorkingCapital)).Append(","); sb.Append(Utility.FormatNumber(valuation.BVPS)).Append(","); sb.Append(Utility.FormatNumber(valuation.EPS)).Append(","); sb.Append(Utility.FormatNumber(valuation.PE)).Append(","); sb.Append(Utility.FormatNumber(valuation.PEG)).Append(","); sb.Append(Utility.FormatNumber(valuation.ImpliedEarningsGrowth)).Append(","); sb.Append(Utility.FormatNumber(valuation.LowPE)).Append(","); sb.Append(Utility.FormatNumber(valuation.TrailingPE)).Append(","); sb.Append(Utility.FormatNumber(valuation.AverageLowTrailing)).Append(","); sb.Append(Utility.FormatNumber(valuation.CurrentStockEstimatePrice)).Append(","); sb.Append(Utility.FormatNumber(valuation.PriceEstimate10Y)).Append(","); sb.Append(Utility.FormatNumber(valuation.TodaysPriceForRequiredReturn)).Append(","); sb.Append(Utility.FormatNumber(valuation.MOS)).Append(","); sb.Append(Utility.FormatNumber(valuation.MOS80)).Append(","); sb.Append(Utility.FormatNumber(valuation.IntrinsicValue)).Append(","); sb.Append(Utility.FormatNumber(valuation.RGV)).Append(","); sb.Append(Utility.FormatNumber(valuation.LatestPrice)).Append(","); sb.Append(Utility.FormatNumber(valuation.UpsidePcnt)).Append(","); sb.Append(Utility.FormatNumber(valuation.DownsidePcnt)).Append(","); sb.Append(Utility.FormatNumber(valuation.MeanTargetPrice)).Append(","); sb.Append(Utility.FormatNumber(valuation.LowTargetPrice)).Append(","); sb.Append(Utility.FormatNumber(valuation.HighTargetPrice)).Append(","); sb.Append(valuation.Bargain ? true : false).Append(","); sb.Append(valuation.Bargain80 ? true : false).Append(","); sb.Append(Utility.FormatNumber(valuation.DividendYield)); return sb.ToString(); } public static String Heading() { StringBuilder sb = new StringBuilder(); sb.Append("Company,Symbol,NextEarningDate,LongTermDebt,Revenue,DebtLoad,ROIC(Avg%),BVPSDates,AvgEquityGrowth(AvgBVPS%),AvgEquityGrowth_2Y(AvgBVPS%),AvgEquityGrowth_4Y(AvgBVPS%),EPSDates,EPSGrowth(Avg%),EPSGrowth_2Y(Avg%),EPSGrowth_4Y(Avg%),RevenueDates,RevenueGrowth(Avg%),RevenueGrowth_QTR(Avg%),RevenueGrowth_2Y(Avg%),RevenueGrowth_4Y(Avg%),FreeCashflowGrowth(Avg%),OperatingCashflow(Avg),WorkingCapital(Avg),BVPS,EPS,PE,PEG,ImpliedEarningsGrowth,LowPE,TrailingPE,AverageLowTrailing,CurrentStockEstimatePrice,PriceEstimate10y,TodaysPriceForRequiredReturn,MOS,MOS(80%),IntrinsicValue,RGV(sb>1),LatestPrice,UpsidePcnt,DownsidePcnt,MeanTargetPrice,LowTargetPrice,HighPrice,Bargain(MOS),Bargain(MOS80%),DividendYield"); return sb.ToString(); } } }