using MarketData.DataAccess; using MarketData.MarketDataModel; using MarketData.Utils; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace MarketData.Generator { public class RiskFreeRateGenerator { private RiskFreeRateGenerator() { } public static Price GeneratePriceAtRiskFreeRate(PortfolioTrades portfolioTrades) { Price price=new Price(); double cumulativePortfolioInvestment=0; if(null==portfolioTrades||0==portfolioTrades.Count) return null; double totalShares=(from PortfolioTrade portfolioTrade in portfolioTrades select portfolioTrade.Shares).Sum(); List yearsToProcess=GetYearsToProcess(portfolioTrades); foreach(int processYear in yearsToProcess) { cumulativePortfolioInvestment=GetInvestmentForYear(portfolioTrades,processYear,cumulativePortfolioInvestment); if(double.NaN.Equals(cumulativePortfolioInvestment)) return null; } price.Close=price.Open=price.High=price.Low=price.AdjClose=cumulativePortfolioInvestment/totalShares; price.Date=DateTime.Now; return price; } private static List GetYearsToProcess(PortfolioTrades portfolioTrades) { List investmentYears=new List(); int startingYear=portfolioTrades[0].TradeDate.Year; int endingYear=DateTime.Now.Year; for(int processYear=startingYear;processYear<=endingYear;processYear++) { investmentYears.Add(processYear); } return investmentYears; } private static double GetInvestmentForYear(PortfolioTrades portfolioTrades,int investmentYear,double initialInvestment) { double cumulativeYearInvestment=0; DateTime yearEnd=new DateTime(investmentYear,12,31); DateTime startOfYear=new DateTime(investmentYear,1,1); double riskFreeRate; PortfolioTrades tradesInYear=new PortfolioTrades((from PortfolioTrade portfolioTrade in portfolioTrades where portfolioTrade.TradeDate.Year.Equals(investmentYear) select portfolioTrade).ToList()); if(0.00!=initialInvestment) { riskFreeRate=YieldCurveDA.GetRiskFreeRate1Yr(startOfYear,10); if(double.NaN.Equals(riskFreeRate)) return double.NaN; riskFreeRate/=100.00; double fractionOfYearHeld=1.00; if(yearEnd>DateTime.Now) { fractionOfYearHeld=GetFractionOfYearHeld(DateTime.Now,startOfYear); cumulativeYearInvestment=initialInvestment*Math.Pow(1.00+riskFreeRate,fractionOfYearHeld); } else cumulativeYearInvestment=initialInvestment*Math.Pow(1.00+riskFreeRate,fractionOfYearHeld); } foreach(PortfolioTrade portfolioTrade in tradesInYear) { riskFreeRate=YieldCurveDA.GetRiskFreeRate1Yr(portfolioTrade.TradeDate,10); // suggestion: move this database call out of the inner loop if(double.NaN.Equals(riskFreeRate)) return double.NaN; riskFreeRate/=100.00; double fractionOfYearHeld=GetFractionOfYearHeld(portfolioTrade,yearEnd); double tradeInvestment=portfolioTrade.Exposure()*Math.Pow((1.00+riskFreeRate),fractionOfYearHeld); cumulativeYearInvestment+=tradeInvestment; } return cumulativeYearInvestment; } private static double GetFractionOfYearHeld(PortfolioTrade portfolioTrade,DateTime yearEnd) { DateGenerator dateGenerator=new DateGenerator(); double fractionOfYearHeld=dateGenerator.DaysBetween(portfolioTrade.TradeDate,yearEnd)/365.00; return fractionOfYearHeld; } private static double GetFractionOfYearHeld(DateTime effectiveDate,DateTime yearEnd) { DateGenerator dateGenerator=new DateGenerator(); double fractionOfYearHeld=dateGenerator.DaysBetween(effectiveDate,yearEnd)/365.00; return fractionOfYearHeld; } } }