550 lines
34 KiB
C#
Executable File
550 lines
34 KiB
C#
Executable File
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<String> 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<String> 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();
|
|
}
|
|
}
|
|
}
|