diff --git a/MarketDataServer/Controllers/GainLossController.cs b/MarketDataServer/Controllers/GainLossController.cs
index 0a87acf..b78b6e0 100755
--- a/MarketDataServer/Controllers/GainLossController.cs
+++ b/MarketDataServer/Controllers/GainLossController.cs
@@ -125,54 +125,68 @@ namespace MarketDataServer.Controllers
}
///
- /// GetGainLossWithDetailByDate - Optimizing calls to DA methods
+ /// GetGainLossWithDetailByDate2 - Refactored: cache primed once before loop.
+ /// GenerateGainLoss still called per symbol (GainLossCollection is a time series,
+ /// not keyed by symbol) but cache is already populated so DB fetches are skipped.
///
- ///
- ///
- ///
[HttpGet]
- public IEnumerable GetGainLossWithDetailByDate(String token,DateTime selectedDate)
+ public IEnumerable GetGainLossWithDetailByDate(String token, DateTime selectedDate)
{
Profiler profiler = new Profiler();
try
{
- MDTrace.WriteLine(LogLevel.DEBUG,$"Start");
+ MDTrace.WriteLine(LogLevel.DEBUG, $"Start");
if (!Authorizations.GetInstance().IsAuthorized(token)) return null;
- GLPriceCache.GetInstance().Refresh();
+
PortfolioTrades portfolioTrades = PortfolioDA.GetTrades();
PortfolioTrades tradesOnOrBefore = portfolioTrades.GetTradesOnOrBefore(selectedDate);
+
+ // Prime cache once for all symbols before any calculation begins.
+ // Guarantees all symbols are cached and open positions have the latest intraday price.
+ // GenerateGainLoss calls Add(PortfolioTrades) internally per symbol — those calls
+ // will hit the cache and skip DB fetches since all symbols are already populated.
+ GLPriceCache.GetInstance().Add(tradesOnOrBefore);
GainLossSummaryItemCollection gainLossSummaryItems = new GainLossSummaryItemCollection(tradesOnOrBefore, selectedDate);
List symbols = gainLossSummaryItems.Select(x => x.Symbol).ToList();
- Dictionary latestDates = PricingDA.GetLatestDates(symbols);
-
+ Dictionary latestDates = PricingDA.GetLatestDates(symbols);
+ if (null == gainLossGenerator) gainLossGenerator = new ActiveGainLossGenerator();
List gainLossSummaryItemDetailCollection = new List();
foreach (GainLossSummaryItem gainLossSummaryItem in gainLossSummaryItems)
{
GainLossSummaryItemDetail gainLossSummaryItemDetail = new GainLossSummaryItemDetail(gainLossSummaryItem);
- portfolioTrades = PortfolioDA.GetOpenTradesSymbol(gainLossSummaryItem.Symbol);
- double weightAdjustedDividendYield = portfolioTrades.GetWeightAdjustedDividendYield();
+
+ PortfolioTrades symbolTrades = PortfolioDA.GetOpenTradesSymbol(gainLossSummaryItem.Symbol);
+ if (null == symbolTrades || 0 == symbolTrades.Count) continue;
+
+ double weightAdjustedDividendYield = symbolTrades.GetWeightAdjustedDividendYield();
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());
- if(null==gainLossGenerator) gainLossGenerator=new ActiveGainLossGenerator();
- GainLossCollection gainLoss=gainLossGenerator.GenerateGainLoss(portfolioTrades); // gainLoss contains the gain/loss from active positions. Never includes dividends .. just positions
+ double shares = symbolTrades.Sum(x => x.Shares);
+ double exposure = symbolTrades.Sum(x => x.Exposure());
+
+ // GainLossCollection is a date-based time series — must be called per symbol
+ // Cache is already primed so internal Add(PortfolioTrades) skips DB fetches
+ GainLossCollection gainLoss = gainLossGenerator.GenerateGainLoss(symbolTrades);
GainLossItem gainLossItem = gainLoss.OrderByDescending(x => x.GainLossPercent).FirstOrDefault();
- gainLossSummaryItemDetail.Lots = portfolioTrades.Count;
+
+ gainLossSummaryItemDetail.Lots = symbolTrades.Count;
gainLossSummaryItemDetail.Shares = shares;
gainLossSummaryItemDetail.Exposure = exposure;
+
if (!double.IsNaN(weightAdjustedDividendYield))
{
gainLossSummaryItemDetail.DividendYield = weightAdjustedDividendYield;
gainLossSummaryItemDetail.AnnualDividend = exposure * weightAdjustedDividendYield;
}
- Prices prices = GLPriceCache.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);
+ // Cache is already primed — pure memory read
+ Prices prices = GLPriceCache.GetInstance().GetPrices(gainLossSummaryItem.Symbol, currentDate, 3);
+ Price p1 = prices.Count > 0 ? prices[0] : default;
+ Price p2 = prices.Count > 1 ? prices[1] : default;
+
+ PortfolioTrades tradesForSymbol = new PortfolioTrades(symbolTrades.Where(x => x.Symbol.Equals(gainLossSummaryItem.Symbol)).ToList());
+ ParityElement parityElement = ParityGenerator.GenerateBreakEven(tradesForSymbol, p1);
gainLossSummaryItemDetail.ParityElement = parityElement;
- if (null != parityElement)
+
+ if (null != parityElement && null != gainLossItem)
{
gainLossSummaryItemDetail.AllTimeGainLossPercent = gainLossItem.GainLossPercent;
gainLossSummaryItemDetail.PercentDistanceFromAllTimeGainLossPercent = parityElement.ParityOffsetPercent - (gainLossItem.GainLossPercent / 100);
@@ -185,11 +199,11 @@ namespace MarketDataServer.Controllers
}
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);
@@ -215,71 +229,195 @@ namespace MarketDataServer.Controllers
// ****
return gainLossSummaryItemDetailCollection;
}
- catch(Exception exception)
+ catch (Exception exception)
{
- MDTrace.WriteLine(LogLevel.DEBUG,$"Exception:{exception.ToString()}");
+ MDTrace.WriteLine(LogLevel.DEBUG, $"Exception:{exception.ToString()}");
return null;
}
finally
{
- MDTrace.WriteLine(LogLevel.DEBUG,$"Done, total took {profiler.End()} (ms)");
+ MDTrace.WriteLine(LogLevel.DEBUG, $"Done, total took {profiler.End()} (ms)");
}
}
+ // ///
+ // /// GetGainLossWithDetailByDate - Optimizing calls to DA methods
+ // ///
+ // ///
+ // ///
+ // ///
+ // [HttpGet]
+ // public IEnumerable GetGainLossWithDetailByDate1(String token,DateTime selectedDate)
+ // {
+ // Profiler profiler = new Profiler();
+ // try
+ // {
+ // MDTrace.WriteLine(LogLevel.DEBUG,$"Start");
+ // if (!Authorizations.GetInstance().IsAuthorized(token)) return null;
+ // GLPriceCache.GetInstance().Refresh();
+ // PortfolioTrades portfolioTrades = PortfolioDA.GetTrades();
+ // 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)
+ // {
+ // GainLossSummaryItemDetail gainLossSummaryItemDetail = new GainLossSummaryItemDetail(gainLossSummaryItem);
+ // portfolioTrades = PortfolioDA.GetOpenTradesSymbol(gainLossSummaryItem.Symbol);
+ // double weightAdjustedDividendYield = portfolioTrades.GetWeightAdjustedDividendYield();
+ // 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());
+ // 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;
+ // }
+ // Prices prices = GLPriceCache.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);
+ // }
+ // 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)
{
Profiler profiler = new Profiler();
try
{
- MDTrace.WriteLine(LogLevel.DEBUG,$"Start");
+ MDTrace.WriteLine(LogLevel.DEBUG, $"Start");
if (!Authorizations.GetInstance().IsAuthorized(token)) return null;
- GLPriceCache.GetInstance().Refresh();
+
PortfolioTrades portfolioTrades = PortfolioDA.GetTrades();
portfolioTrades = new PortfolioTrades(portfolioTrades.Where(x => x.Account.Equals(account)).ToList());
PortfolioTrades tradesOnOrBefore = portfolioTrades.GetTradesOnOrBefore(selectedDate);
+
+ // Prime cache once for all symbols before any calculation begins.
+ // Guarantees all symbols are cached and open positions have the latest intraday price.
+ // GenerateGainLoss calls Add(PortfolioTrades) internally per symbol those calls
+ // will hit the cache and skip DB fetches since all symbols are already populated.
+ GLPriceCache.GetInstance().Add(tradesOnOrBefore);
+
GainLossSummaryItemCollection gainLossSummaryItems = new GainLossSummaryItemCollection(tradesOnOrBefore, selectedDate);
List symbols = gainLossSummaryItems.Select(x => x.Symbol).ToList();
- Dictionary latestDates = PricingDA.GetLatestDates(symbols);
+ Dictionary latestDates = PricingDA.GetLatestDates(symbols);
- List gainLossSummaryItemDetailCollection=new List();
- foreach(GainLossSummaryItem gainLossSummaryItem in gainLossSummaryItems)
+ if (null == gainLossGenerator) gainLossGenerator = new ActiveGainLossGenerator();
+
+ List gainLossSummaryItemDetailCollection = new List();
+
+ foreach (GainLossSummaryItem gainLossSummaryItem in gainLossSummaryItems)
{
GainLossSummaryItemDetail gainLossSummaryItemDetail = new GainLossSummaryItemDetail(gainLossSummaryItem);
- portfolioTrades = PortfolioDA.GetOpenTradesSymbol(gainLossSummaryItem.Symbol);
- double weightAdjustedDividendYield = portfolioTrades.GetWeightAdjustedDividendYield();
+
+ PortfolioTrades symbolTrades = PortfolioDA.GetOpenTradesSymbol(gainLossSummaryItem.Symbol);
+ if (null == symbolTrades || 0 == symbolTrades.Count) continue;
+
+ double weightAdjustedDividendYield = symbolTrades.GetWeightAdjustedDividendYield();
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());
- if(null==gainLossGenerator) gainLossGenerator=new ActiveGainLossGenerator();
- GainLossCollection gainLoss = gainLossGenerator.GenerateGainLoss(portfolioTrades); // gainLoss contains the gain/loss from active positions. Never includes dividends .. just positions
+ double shares = symbolTrades.Sum(x => x.Shares);
+ double exposure = symbolTrades.Sum(x => x.Exposure());
+
+ // GainLossCollection is a date-based time series must be called per symbol
+ // Cache is already primed so internal Add(PortfolioTrades) skips DB fetches
+ GainLossCollection gainLoss = gainLossGenerator.GenerateGainLoss(symbolTrades);
GainLossItem gainLossItem = gainLoss.OrderByDescending(x => x.GainLossPercent).FirstOrDefault();
- gainLossSummaryItemDetail.Lots=portfolioTrades.Count;
- gainLossSummaryItemDetail.Shares=shares;
- gainLossSummaryItemDetail.Exposure=exposure;
+
+ gainLossSummaryItemDetail.Lots = symbolTrades.Count;
+ gainLossSummaryItemDetail.Shares = shares;
+ gainLossSummaryItemDetail.Exposure = exposure;
+
if (!double.IsNaN(weightAdjustedDividendYield))
{
- gainLossSummaryItemDetail.DividendYield=weightAdjustedDividendYield;
- gainLossSummaryItemDetail.AnnualDividend=exposure * weightAdjustedDividendYield;
+ gainLossSummaryItemDetail.DividendYield = weightAdjustedDividendYield;
+ gainLossSummaryItemDetail.AnnualDividend = exposure * weightAdjustedDividendYield;
}
- Prices prices = GLPriceCache.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)
+
+ // Cache is already primed pure memory read
+ Prices prices = GLPriceCache.GetInstance().GetPrices(gainLossSummaryItem.Symbol, currentDate, 3);
+ Price p1 = prices.Count > 0 ? prices[0] : default;
+ Price p2 = prices.Count > 1 ? prices[1] : default;
+
+ PortfolioTrades tradesForSymbol = new PortfolioTrades(symbolTrades.Where(x => x.Symbol.Equals(gainLossSummaryItem.Symbol)).ToList());
+ ParityElement parityElement = ParityGenerator.GenerateBreakEven(tradesForSymbol, p1);
+ gainLossSummaryItemDetail.ParityElement = parityElement;
+
+ if (null != parityElement && null != gainLossItem)
{
- gainLossSummaryItemDetail.AllTimeGainLossPercent=gainLossItem.GainLossPercent;
- gainLossSummaryItemDetail.PercentDistanceFromAllTimeGainLossPercent=parityElement.ParityOffsetPercent - (gainLossItem.GainLossPercent / 100);
+ gainLossSummaryItemDetail.AllTimeGainLossPercent = gainLossItem.GainLossPercent;
+ gainLossSummaryItemDetail.PercentDistanceFromAllTimeGainLossPercent = parityElement.ParityOffsetPercent - (gainLossItem.GainLossPercent / 100);
}
- if(null!=p1 && null!=p2)
+
+ if (null != p1 && null != p2)
{
double change = (p1.Close - p2.Close) / p2.Close;
- gainLossSummaryItemDetail.LatestPrice=p1;
- gainLossSummaryItemDetail.PriceChange=change;
+ gainLossSummaryItemDetail.LatestPrice = p1;
+ gainLossSummaryItemDetail.PriceChange = change;
}
+
gainLossSummaryItemDetailCollection.Add(gainLossSummaryItemDetail);
}
@@ -287,16 +425,17 @@ namespace MarketDataServer.Controllers
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.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;
+ gainLossSummaryTotals.LatestPrice = new Price();
+ gainLossSummaryTotals.PriceChange = 0;
}
else
{
@@ -309,20 +448,116 @@ namespace MarketDataServer.Controllers
gainLossSummaryTotals.PriceChange = 0;
}
gainLossSummaryItemDetailCollection.Insert(0, gainLossSummaryTotals);
- // ****
return gainLossSummaryItemDetailCollection;
}
- catch(Exception exception)
+ catch (Exception exception)
{
- MDTrace.WriteLine(LogLevel.DEBUG,$"Exception:{exception.ToString()}");
+ MDTrace.WriteLine(LogLevel.DEBUG, $"Exception:{exception.ToString()}");
return null;
}
finally
{
- MDTrace.WriteLine(LogLevel.DEBUG,$"Done, total took {profiler.End()} (ms)");
+ MDTrace.WriteLine(LogLevel.DEBUG, $"Done, total took {profiler.End()} (ms)");
}
}
+ // [HttpGet]
+ // public IEnumerable GetGainLossWithDetailByDateAndAccount(String token, DateTime selectedDate, String account)
+ // {
+ // Profiler profiler = new Profiler();
+ // try
+ // {
+ // MDTrace.WriteLine(LogLevel.DEBUG,$"Start");
+ // if (!Authorizations.GetInstance().IsAuthorized(token)) return null;
+ // GLPriceCache.GetInstance().Refresh();
+ // PortfolioTrades portfolioTrades = PortfolioDA.GetTrades();
+ // 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)
+ // {
+ // GainLossSummaryItemDetail gainLossSummaryItemDetail = new GainLossSummaryItemDetail(gainLossSummaryItem);
+ // portfolioTrades = PortfolioDA.GetOpenTradesSymbol(gainLossSummaryItem.Symbol);
+ // double weightAdjustedDividendYield = portfolioTrades.GetWeightAdjustedDividendYield();
+ // 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());
+ // 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;
+ // }
+ // Prices prices = GLPriceCache.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);
+ // }
+ // 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(Name = "GetCompoundGainLoss")]
public GainLossCompoundModelCollection GetCompoundGainLoss(String token, int selectedDays, bool includeDividends)
{