using MarketData.Cache; using MarketData.DataAccess; using MarketData.MarketDataModel; using MarketData.Utils; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; namespace MarketData.Generator { public class DividendHistoryGenerator { private DividendHistoryGenerator() { } public static double GetDividendYield(String symbol) { try { Price currentPrice=PricingDA.GetPrice(symbol); return GetDividendYield(symbol,currentPrice); } catch(Exception exception) { MDTrace.WriteLine(LogLevel.DEBUG,String.Format("{0}",exception.ToString())); return double.NaN; } } public static double GetDividendYield(String symbol,Price currentPrice) { try { int currentYear=DateTime.Now.Year; int priorYear=currentYear-1; DividendHistory dividendHistory=DividendHistoryCache.GetInstance().GetDividendHistory(symbol,new int[]{currentYear, priorYear}); // DividendHistory dividendHistory=DividendHistoryDA.GetDividendHistory(symbol,new int[] { currentYear,priorYear }); if(null==currentPrice||double.IsNaN(currentPrice.Close)||!currentPrice.Date.Year.Equals(currentYear)) return double.NaN; DividendHistory lastYearsDividendPayments=new DividendHistory((from DividendHistoryItem item in dividendHistory where item.DivExDate.Year==priorYear&&null!=item.CashAmount select item).ToList()); DividendHistory currentYearsDividendPayments=new DividendHistory((from DividendHistoryItem item in dividendHistory where item.DivExDate.Year==currentYear&&null!=item.CashAmount select item).ToList()); if(currentYearsDividendPayments.HasConsecutivePayments(3)) return (currentYearsDividendPayments.Average(x => x.CashAmount.Value)*12)/currentPrice.Close; if(0==lastYearsDividendPayments.Count&&0==currentYearsDividendPayments.Count) return double.NaN; double lastYearsAverageDividendPayment=lastYearsDividendPayments.Count()>1?lastYearsDividendPayments.Average(x => x.CashAmount.Value):double.NaN; // calculate last years min and max dividend payments in order to determine if there were special payments double lastYearMinDividendPayment=lastYearsDividendPayments.Count>0?lastYearsDividendPayments.Min(x => x.CashAmount.Value):0.00; DividendHistory lastYearsSpecialPayments=lastYearsDividendPayments.Count>0?new DividendHistory((from DividendHistoryItem item in lastYearsDividendPayments where item.CashAmount.Value>3*lastYearMinDividendPayment select item).ToList()):new DividendHistory(); bool lastYearHasSpecialItems=lastYearsSpecialPayments.Count()>0?true:false; if(0==currentYearsDividendPayments.Count) // if no dividends in current year then go back to last year { if(lastYearHasSpecialItems) lastYearsDividendPayments=new DividendHistory(lastYearsDividendPayments.Where(x => !lastYearsSpecialPayments.Any(z => z.DivExDate==x.DivExDate)).ToList()); else if(1==lastYearsDividendPayments.Count) return lastYearsDividendPayments[0].CashAmount.Value/currentPrice.Close; return lastYearsDividendPayments.Sum(x => x.CashAmount.Value)/currentPrice.Close; } double currentYearMaxDividendPayment=currentYearsDividendPayments.Max(x => x.CashAmount.Value); double currentYearMinDividendPayment=currentYearsDividendPayments.Min(x => x.CashAmount.Value); DividendHistory currentYearsSpecialPayments=new DividendHistory((from DividendHistoryItem item in currentYearsDividendPayments where item.CashAmount.Value>3*currentYearMinDividendPayment select item).ToList()); bool currentYearhasSpecialItems=currentYearsSpecialPayments.Count()>0?true:false; double currentYearsAverageDividendPayment=currentYearsDividendPayments.Average(x => x.CashAmount.Value); if(1==lastYearsDividendPayments.Count&&1==currentYearsDividendPayments.Count) return currentYearsAverageDividendPayment/currentPrice.Close; if(0==lastYearsDividendPayments.Count) // there was no dividend payment last year. check if this years is a special dividend (>25%) { double dividendPayment=currentYearsDividendPayments.Average(x => x.CashAmount.Value); double dividendYield=dividendPayment/currentPrice.Close; if(dividendYield>=.25) return dividendYield; } if(4==lastYearsDividendPayments.Count) { if(currentYearhasSpecialItems) // exclude special payments from consideration { currentYearsDividendPayments=new DividendHistory(currentYearsDividendPayments.Where(x => !currentYearsSpecialPayments.Any(z => z.DivExDate==x.DivExDate)).ToList()); double dividendYield=currentYearsDividendPayments.Average(x => x.CashAmount.Value); dividendYield*=4.00; dividendYield/=currentPrice.Close; return dividendYield; } if(1==currentYearsDividendPayments.Count&&lastYearHasSpecialItems) // if only one payment this year and last year has a special payment then use last year minus special payment { lastYearsDividendPayments=new DividendHistory(lastYearsDividendPayments.Where(x => !lastYearsSpecialPayments.Any(z => z.DivExDate==x.DivExDate)).ToList()); double dividendYield=lastYearsDividendPayments.Average(x => x.CashAmount.Value); dividendYield*=4.00; dividendYield/=currentPrice.Close; return dividendYield; } return (currentYearsAverageDividendPayment*4.00)/currentPrice.Close; } if(3==currentYearsDividendPayments.Count) { if(currentYearhasSpecialItems) // exclude special payments from consideration { currentYearsDividendPayments=new DividendHistory(currentYearsDividendPayments.Where(x => !currentYearsSpecialPayments.Any(z => z.DivExDate==x.DivExDate)).ToList()); double dividendYield=currentYearsDividendPayments.Average(x => x.CashAmount.Value); dividendYield*=4.00; dividendYield/=currentPrice.Close; return dividendYield; } else return (currentYearsAverageDividendPayment*4.00)/currentPrice.Close; } if(2==lastYearsDividendPayments.Count) return Math.Min(lastYearsDividendPayments.Sum(x => x.CashAmount.Value),currentYearsDividendPayments.Sum(x => x.CashAmount.Value))/currentPrice.Close; return (currentYearsDividendPayments.Average(x => x.CashAmount.Value)*4.00)/currentPrice.Close; } catch(Exception exception) { MDTrace.WriteLine(LogLevel.DEBUG,String.Format("{0}",exception.ToString())); return double.NaN; } } } }