diff --git a/MarketData/MarketDataLib/Cache/DividendHistoryCache.cs b/MarketData/MarketDataLib/Cache/DividendHistoryCache.cs index cca6017..519ad44 100755 --- a/MarketData/MarketDataLib/Cache/DividendHistoryCache.cs +++ b/MarketData/MarketDataLib/Cache/DividendHistoryCache.cs @@ -44,6 +44,7 @@ namespace MarketData.Cache private DividendHistoryCache() { } + public void Dispose() { lock(thisLock) @@ -52,6 +53,7 @@ namespace MarketData.Cache instance=null; } } + public static DividendHistoryCache GetInstance() { lock(typeof(DividendHistoryCache)) @@ -60,6 +62,7 @@ namespace MarketData.Cache return instance; } } + public void ClearCache() { lock(typeof(DividendHistoryCache)) @@ -67,6 +70,7 @@ namespace MarketData.Cache dividendHistoryCache.Clear(); } } + public void Add(DividendHistory dividendHistory) { lock(typeof(DividendHistoryCache)) @@ -84,6 +88,7 @@ namespace MarketData.Cache } } } + private void Add(String symbol,int divExYear,DividendHistory dividendHistory) { lock(typeof(DividendHistoryCache)) @@ -104,6 +109,7 @@ namespace MarketData.Cache } } } + public DividendHistory GetDividendHistory(String symbol, int[] divExYears) { DividendHistory dividendHistory=new DividendHistory(); @@ -123,7 +129,8 @@ namespace MarketData.Cache } } return dividendHistory; - } + } + private DividendHistory GetDividendHistory(String symbol,int divExYear) { lock(typeof(DividendHistoryCache)) @@ -134,6 +141,7 @@ namespace MarketData.Cache return dividendHistoryByDixExYear[divExYear]; } } + public bool ContainsDividendHistory(String symbol,int divExYear) { lock(typeof(DividendHistoryCache)) diff --git a/MarketData/MarketDataLib/Generator/DividendHistoryGenerator.cs b/MarketData/MarketDataLib/Generator/DividendHistoryGenerator.cs index 0f6bf18..fabee64 100755 --- a/MarketData/MarketDataLib/Generator/DividendHistoryGenerator.cs +++ b/MarketData/MarketDataLib/Generator/DividendHistoryGenerator.cs @@ -37,8 +37,6 @@ namespace MarketData.Generator 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()); diff --git a/MarketDataServer/Controllers/GainLossController.cs b/MarketDataServer/Controllers/GainLossController.cs index d894920..d1789f2 100755 --- a/MarketDataServer/Controllers/GainLossController.cs +++ b/MarketDataServer/Controllers/GainLossController.cs @@ -12,6 +12,15 @@ using Microsoft.AspNetCore.Mvc; namespace MarketDataServer.Controllers { + /// + /// GainLossController : + /// GetGainLossByDate(String token,DateTime selectedDate) + /// GetGainLossByDateAndAccount(String token,DateTime selectedDate,String account) + /// GetGainLossWithDetailByDate(String token,DateTime selectedDate) + /// GetGainLossWithDetailByDateAndAccount(String token, DateTime selectedDate, String account) + /// GetCompoundGainLoss(String token, int selectedDays, bool includeDividends) + /// + [ApiController] [Route("api/[controller]/[action]")] public class GainLossController : ControllerBase @@ -158,7 +167,6 @@ namespace MarketDataServer.Controllers gainLossSummaryItemDetail.AnnualDividend = exposure * weightAdjustedDividendYield; } Prices prices = LocalPriceCache.GetInstance().GetPrices(gainLossSummaryItem.Symbol, currentDate, 3); // cache should be refreshed after GainLossSummaryItemCollection -// Prices prices = PricingDA.GetPrices(gainLossSummaryItem.Symbol, currentDate, 2); Price p1 = prices.Count>0?prices[0]:default; Price p2 = prices.Count>1?prices[1]:default; PortfolioTrades symbolTrades = new PortfolioTrades(portfolioTrades.Where(x=>x.Symbol.Equals(gainLossSummaryItem.Symbol)).ToList()); @@ -218,105 +226,6 @@ namespace MarketDataServer.Controllers } } - // [HttpGet] - // public IEnumerable GetGainLossWithDetailByDate(String token,DateTime selectedDate) - // { - // Profiler profiler = new Profiler(); - // try - // { - // MDTrace.WriteLine(LogLevel.DEBUG,$"Start"); - // if (!Authorizations.GetInstance().IsAuthorized(token)) return null; - // LocalPriceCache.GetInstance().Refresh(); - // PortfolioTrades portfolioTrades = PortfolioDA.GetTrades(); - // PortfolioTrades tradesOnOrBefore = portfolioTrades.GetTradesOnOrBefore(selectedDate); - // GainLossSummaryItemCollection gainLossSummaryItems = new GainLossSummaryItemCollection(tradesOnOrBefore, selectedDate); - - // List gainLossSummaryItemDetailCollection = new List(); - // foreach (GainLossSummaryItem gainLossSummaryItem in gainLossSummaryItems) - // { - // GainLossSummaryItemDetail gainLossSummaryItemDetail = new GainLossSummaryItemDetail(gainLossSummaryItem); - // portfolioTrades = PortfolioDA.GetOpenTradesSymbol(gainLossSummaryItem.Symbol); - // double weightAdjustedDividendYield = portfolioTrades.GetWeightAdjustedDividendYield(); - // DateTime currentDate = PricingDA.GetLatestDate(gainLossSummaryItem.Symbol); - // if (null == portfolioTrades || 0 == portfolioTrades.Count) continue; - // double shares = (from PortfolioTrade portfolioTrade in portfolioTrades select portfolioTrade.Shares).Sum(); - // double exposure = portfolioTrades.Sum(x => x.Exposure()); - // if(null==gainLossGenerator) gainLossGenerator=new ActiveGainLossGenerator(); - // GainLossCollection gainLoss=gainLossGenerator.GenerateGainLoss(portfolioTrades); // gainLoss contains the gain/loss from active positions. Never includes dividends .. just positions - // GainLossItem gainLossItem = gainLoss.OrderByDescending(x => x.GainLossPercent).FirstOrDefault(); - // gainLossSummaryItemDetail.Lots = portfolioTrades.Count; - // gainLossSummaryItemDetail.Shares = shares; - // gainLossSummaryItemDetail.Exposure = exposure; - // if (!double.IsNaN(weightAdjustedDividendYield)) - // { - // gainLossSummaryItemDetail.DividendYield = weightAdjustedDividendYield; - // gainLossSummaryItemDetail.AnnualDividend = exposure * weightAdjustedDividendYield; - // } - // ParityElement parityElement = ParityGenerator.GenerateBreakEven(gainLossSummaryItem.Symbol); - // gainLossSummaryItemDetail.ParityElement = parityElement; - // if (null != parityElement) - // { - // gainLossSummaryItemDetail.AllTimeGainLossPercent = gainLossItem.GainLossPercent; - // gainLossSummaryItemDetail.PercentDistanceFromAllTimeGainLossPercent = parityElement.ParityOffsetPercent - (gainLossItem.GainLossPercent / 100); - // } - // DateGenerator dateGenerator = new DateGenerator(); - // DateTime priorDate = dateGenerator.FindPrevBusinessDay(currentDate); - // Price p1 = PricingDA.GetPrice(gainLossSummaryItem.Symbol, currentDate); - // Price p2 = PricingDA.GetPrice(gainLossSummaryItem.Symbol, priorDate); - // if (null == p2 && null != p1) - // { - // priorDate = dateGenerator.FindPrevBusinessDay(priorDate); - // p2 = PricingDA.GetPrice(gainLossSummaryItem.Symbol, priorDate); - // } - // if (null != p1 && null != p2) - // { - // double change = (p1.Close - p2.Close) / p2.Close; - // gainLossSummaryItemDetail.LatestPrice = p1; - // gainLossSummaryItemDetail.PriceChange = change; - // } - // gainLossSummaryItemDetailCollection.Add(gainLossSummaryItemDetail); - // } - - // // **** Add an aggregate entry - // GainLossSummaryItemDetail gainLossSummaryTotals = new GainLossSummaryItemDetail(); - // gainLossSummaryTotals.Symbol = ""; - // gainLossSummaryTotals.CompanyName = "Account Summary"; - // if (null != gainLossSummaryItemDetailCollection && gainLossSummaryItemDetailCollection.Count > 0) - // { - // gainLossSummaryTotals.Date = gainLossSummaryItemDetailCollection.Min(x => x.Date); - // gainLossSummaryTotals.Exposure = gainLossSummaryItemDetailCollection.Sum(x => x.Exposure); - // gainLossSummaryTotals.Change = gainLossSummaryItemDetailCollection.Sum(x => x.Change); - // gainLossSummaryTotals.CurrentGainLoss = gainLossSummaryItemDetailCollection.Sum(x => x.CurrentGainLoss); - // gainLossSummaryTotals.PreviousGainLoss = gainLossSummaryItemDetailCollection.Sum(x => x.PreviousGainLoss); - // gainLossSummaryTotals.ChangePercent = ((gainLossSummaryTotals.CurrentGainLoss - gainLossSummaryTotals.PreviousGainLoss) / Math.Abs(gainLossSummaryTotals.PreviousGainLoss)) * 100.00; - // gainLossSummaryTotals.LatestPrice = new Price(); - // gainLossSummaryTotals.PriceChange = 0; - // } - // else - // { - // gainLossSummaryTotals.Date = selectedDate; - // gainLossSummaryTotals.Change = 0.00; - // gainLossSummaryTotals.CurrentGainLoss = 0.00; - // gainLossSummaryTotals.PreviousGainLoss = 0.00; - // gainLossSummaryTotals.ChangePercent = 0.00; - // gainLossSummaryTotals.LatestPrice = new Price(); - // gainLossSummaryTotals.PriceChange = 0; - // } - // gainLossSummaryItemDetailCollection.Insert(0, gainLossSummaryTotals); - // // **** - // return gainLossSummaryItemDetailCollection; - // } - // catch(Exception exception) - // { - // MDTrace.WriteLine(LogLevel.DEBUG,$"Exception:{exception.ToString()}"); - // return null; - // } - // finally - // { - // MDTrace.WriteLine(LogLevel.DEBUG,$"Done, total took {profiler.End()} (ms)"); - // } - // } - [HttpGet] public IEnumerable GetGainLossWithDetailByDateAndAccount(String token, DateTime selectedDate, String account) { @@ -330,6 +239,8 @@ namespace MarketDataServer.Controllers portfolioTrades = new PortfolioTrades(portfolioTrades.Where(x => x.Account.Equals(account)).ToList()); PortfolioTrades tradesOnOrBefore = portfolioTrades.GetTradesOnOrBefore(selectedDate); GainLossSummaryItemCollection gainLossSummaryItems = new GainLossSummaryItemCollection(tradesOnOrBefore, selectedDate); + List symbols = gainLossSummaryItems.Select(x => x.Symbol).ToList(); + Dictionary latestDates = PricingDA.GetLatestDates(symbols); List gainLossSummaryItemDetailCollection=new List(); foreach(GainLossSummaryItem gainLossSummaryItem in gainLossSummaryItems) @@ -337,7 +248,7 @@ namespace MarketDataServer.Controllers GainLossSummaryItemDetail gainLossSummaryItemDetail = new GainLossSummaryItemDetail(gainLossSummaryItem); portfolioTrades = PortfolioDA.GetOpenTradesSymbol(gainLossSummaryItem.Symbol); double weightAdjustedDividendYield = portfolioTrades.GetWeightAdjustedDividendYield(); - DateTime currentDate = PricingDA.GetLatestDate(gainLossSummaryItem.Symbol); + DateTime currentDate = latestDates[gainLossSummaryItem.Symbol]; if(null==portfolioTrades||0==portfolioTrades.Count)continue; double shares = (from PortfolioTrade portfolioTrade in portfolioTrades select portfolioTrade.Shares).Sum(); double exposure = portfolioTrades.Sum(x => x.Exposure()); @@ -352,23 +263,18 @@ namespace MarketDataServer.Controllers gainLossSummaryItemDetail.DividendYield=weightAdjustedDividendYield; gainLossSummaryItemDetail.AnnualDividend=exposure * weightAdjustedDividendYield; } - ParityElement parityElement = ParityGenerator.GenerateBreakEven(gainLossSummaryItem.Symbol); + Prices prices = LocalPriceCache.GetInstance().GetPrices(gainLossSummaryItem.Symbol, currentDate, 3); // cache should be refreshed after GainLossSummaryItemCollection + Price p1 = prices.Count>0?prices[0]:default; + Price p2 = prices.Count>1?prices[1]:default; + PortfolioTrades symbolTrades = new PortfolioTrades(portfolioTrades.Where(x=>x.Symbol.Equals(gainLossSummaryItem.Symbol)).ToList()); + ParityElement parityElement = ParityGenerator.GenerateBreakEven(symbolTrades, p1); gainLossSummaryItemDetail.ParityElement=parityElement; if (null != parityElement) { gainLossSummaryItemDetail.AllTimeGainLossPercent=gainLossItem.GainLossPercent; gainLossSummaryItemDetail.PercentDistanceFromAllTimeGainLossPercent=parityElement.ParityOffsetPercent - (gainLossItem.GainLossPercent / 100); } - DateGenerator dateGenerator = new DateGenerator(); - DateTime priorDate = dateGenerator.FindPrevBusinessDay(currentDate); - Price p1 = PricingDA.GetPrice(gainLossSummaryItem.Symbol, currentDate); - Price p2 = PricingDA.GetPrice(gainLossSummaryItem.Symbol, priorDate); - if (null == p2 && null != p1) - { - priorDate = dateGenerator.FindPrevBusinessDay(priorDate); - p2 = PricingDA.GetPrice(gainLossSummaryItem.Symbol, priorDate); - } - if(null!=p1&&null!=p2) + if(null!=p1 && null!=p2) { double change = (p1.Close - p2.Close) / p2.Close; gainLossSummaryItemDetail.LatestPrice=p1; diff --git a/MarketDataServer/MarketDataServer.sln b/MarketDataServer/MarketDataServer.sln index e8efa87..6e12dbf 100644 --- a/MarketDataServer/MarketDataServer.sln +++ b/MarketDataServer/MarketDataServer.sln @@ -4,6 +4,8 @@ VisualStudioVersion = 17.5.2.0 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MarketDataServer", "MarketDataServer.csproj", "{95632102-7AD8-9B9D-1583-0C986A476083}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MarketDataLib", "..\MarketData\MarketDataLib\MarketDataLib.csproj", "{40159117-A4E2-F689-5B94-20FB81B71B98}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU