using MarketData; 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.Tasks; namespace TradeBlotter.Model { public class ModelPerformanceAggregator { private ModelPerformanceAggregator() { } // *********************************************************************************************************************************************************************************************************** // *********************************************************************************** M A R C M I N E R V I N I M O M E N T U M ************************************************************************* // *********************************************************************************************************************************************************************************************************** // 2 versions : one handles MMTrend the other handes the CMTrend. public static double CalculateCumulativeReturn(IEnumerable positions) { ModelPerformanceSeries performanceSeries=GetModelPerformance(positions); if(null==performanceSeries) return double.NaN; return performanceSeries[performanceSeries.Count-1].CumProdMinusOne; } public static ModelPerformanceSeries GetModelPerformance(IEnumerable positions) { ModelPerformanceSeries performanceSeries=new ModelPerformanceSeries(); try { DateTime minDate=positions.Min(x => x.PurchaseDate); DateTime maxDate=PricingDA.GetLatestDate(); DateGenerator dateGenerator=new DateGenerator(); double cumulativeReturn=double.NaN; double prevGainLoss=double.NaN; LocalPriceCache.GetInstance().RemoveDate(maxDate); List historicalDates=dateGenerator.GenerateHistoricalDates(minDate,maxDate); foreach(DateTime currentDate in historicalDates) { IEnumerable openPositions=positions.Where(x => (x.PurchaseDate<=currentDate&&(!Utility.IsEpoch(x.SellDate)&&x.SellDate>currentDate))||(x.PurchaseDate<=currentDate&&Utility.IsEpoch(x.SellDate))).ToList(); IEnumerable closedPositions=positions.Where(x => (!Utility.IsEpoch(x.SellDate)&&x.SellDate.Equals(currentDate))).ToList(); if(0==openPositions.Count()&&0==closedPositions.Count()) continue; double gainLoss=0.00; double gainLossClosedPositions=0.00; double exposure=0.00; double marketValue=0.00; // if(HolidayDA.IsMarketHoliday(currentDate)) continue; ModelPerformanceItem performanceItem=new ModelPerformanceItem(); foreach(CMTPositionModel openPosition in openPositions) { exposure+=openPosition.Shares*openPosition.PurchasePrice; if(!LocalPriceCache.GetInstance().ContainsPrice(openPosition.Symbol,currentDate)) { Prices prices=PricingDA.GetPricesForward(openPosition.Symbol,currentDate,PricingDA.ForwardLookingDays); LocalPriceCache.GetInstance().Add(prices); } Price price=LocalPriceCache.GetInstance().GetPrice(openPosition.Symbol,currentDate); if(null==price) { MDTrace.WriteLine(LogLevel.DEBUG,String.Format("GetModelPerformance: No price for {0} on {1}",openPosition.Symbol,currentDate.ToShortDateString())); continue; } gainLoss+=((price.Close*openPosition.Shares)-(openPosition.PurchasePrice*openPosition.Shares)); marketValue+=(price.Close*openPosition.Shares); } foreach(CMTPositionModel closedPosition in closedPositions) { double gainLossPosition=(closedPosition.CurrentPrice*closedPosition.Shares)-(closedPosition.PurchasePrice*closedPosition.Shares); gainLossClosedPositions+=gainLossPosition; } double dailyReturn=0.00; if(double.IsNaN(prevGainLoss)) dailyReturn=(marketValue-exposure)/Math.Abs(exposure); else dailyReturn=((gainLoss-prevGainLoss)/Math.Abs(prevGainLoss))/100.00; if(double.IsNaN(cumulativeReturn)) cumulativeReturn=1.00*(1.00+dailyReturn); else cumulativeReturn=cumulativeReturn*(1.00+dailyReturn); performanceItem.Date=currentDate; performanceItem.Exposure=exposure; performanceItem.MarketValue=marketValue; performanceItem.GainLossDOD=double.IsNaN(prevGainLoss)?gainLoss:(gainLoss-prevGainLoss)+gainLossClosedPositions; performanceItem.GainLoss=gainLoss+gainLossClosedPositions; performanceItem.ClosedPositions=closedPositions.Count()>0?true:false; performanceSeries.Add(performanceItem); prevGainLoss=gainLoss; } for(int index=0;index positions) { ModelPerformanceSeries performanceSeries=GetModelPerformance(positions); if(null==performanceSeries)return double.NaN; return performanceSeries[performanceSeries.Count-1].CumProdMinusOne; } public static double CalculateCumulativeReturn(IEnumerable positions) { ModelPerformanceSeries performanceSeries=GetModelPerformance(positions); if(null==performanceSeries) return double.NaN; return performanceSeries[performanceSeries.Count-1].CumProdMinusOne; } public static double CalculateCumulativeReturn(IEnumerable positions) { ModelPerformanceSeries performanceSeries=GetModelPerformance(positions); if(null==performanceSeries) return double.NaN; return performanceSeries[performanceSeries.Count-1].CumProdMinusOne; } public static ModelPerformanceSeries GetModelPerformance(IEnumerable positions) { ModelPerformanceSeries performanceSeries=new ModelPerformanceSeries(); try { DateTime minDate=positions.Min(x => x.PurchaseDate); DateTime maxDate=PricingDA.GetLatestDate(); DateGenerator dateGenerator=new DateGenerator(); double cumulativeReturn=double.NaN; double prevGainLoss=double.NaN; LocalPriceCache.GetInstance().RemoveDate(maxDate); List historicalDates=dateGenerator.GenerateHistoricalDates(minDate,maxDate); foreach(DateTime currentDate in historicalDates) { IEnumerable openPositions=positions.Where(x => (x.PurchaseDate<=currentDate&&(!Utility.IsEpoch(x.SellDate)&&x.SellDate>currentDate))||(x.PurchaseDate<=currentDate&&Utility.IsEpoch(x.SellDate))).ToList(); IEnumerable closedPositions=positions.Where(x => (!Utility.IsEpoch(x.SellDate)&&x.SellDate.Equals(currentDate))).ToList(); if(0==openPositions.Count()&&0==closedPositions.Count()) continue; double gainLoss=0.00; double gainLossClosedPositions=0.00; double exposure=0.00; double marketValue=0.00; // if(HolidayDA.IsMarketHoliday(currentDate)) continue; ModelPerformanceItem performanceItem=new ModelPerformanceItem(); foreach(CMPositionModel openPosition in openPositions) { exposure+=openPosition.Shares*openPosition.PurchasePrice; if(!LocalPriceCache.GetInstance().ContainsPrice(openPosition.Symbol,currentDate)) { Prices prices=PricingDA.GetPricesForward(openPosition.Symbol,currentDate,PricingDA.ForwardLookingDays); LocalPriceCache.GetInstance().Add(prices); } Price price=LocalPriceCache.GetInstance().GetPrice(openPosition.Symbol,currentDate); if(null==price) { MDTrace.WriteLine(LogLevel.DEBUG,String.Format("GetModelPerformance: No price for {0} on {1}",openPosition.Symbol,currentDate.ToShortDateString())); continue; } gainLoss+=((price.Close*openPosition.Shares)-(openPosition.PurchasePrice*openPosition.Shares)); marketValue+=(price.Close*openPosition.Shares); } foreach(CMPositionModel closedPosition in closedPositions) { double gainLossPosition=(closedPosition.CurrentPrice*closedPosition.Shares)-(closedPosition.PurchasePrice*closedPosition.Shares); gainLossClosedPositions+=gainLossPosition; } double dailyReturn=0.00; if(double.IsNaN(prevGainLoss)) dailyReturn=(marketValue-exposure)/Math.Abs(exposure); else dailyReturn=((gainLoss-prevGainLoss)/Math.Abs(prevGainLoss))/100.00; if(double.IsNaN(cumulativeReturn)) cumulativeReturn=1.00*(1.00+dailyReturn); else cumulativeReturn=cumulativeReturn*(1.00+dailyReturn); performanceItem.Date=currentDate; performanceItem.Exposure=exposure; performanceItem.MarketValue=marketValue; performanceItem.GainLossDOD=double.IsNaN(prevGainLoss)?gainLoss:(gainLoss-prevGainLoss)+gainLossClosedPositions; performanceItem.GainLoss=gainLoss+gainLossClosedPositions; performanceItem.ClosedPositions=closedPositions.Count()>0?true:false; performanceSeries.Add(performanceItem); prevGainLoss=gainLoss; } for(int index=0;index positions) { ModelPerformanceSeries performanceSeries=new ModelPerformanceSeries(); try { DateTime minDate=positions.Min(x => x.PurchaseDate); DateTime maxDate=PricingDA.GetLatestDate(); DateGenerator dateGenerator=new DateGenerator(); double cumulativeReturn=double.NaN; double prevGainLoss=double.NaN; LocalPriceCache.GetInstance().RemoveDate(maxDate); List historicalDates=dateGenerator.GenerateHistoricalDates(minDate,maxDate); foreach(DateTime currentDate in historicalDates) { IEnumerable openPositions=positions.Where(x => (x.PurchaseDate<=currentDate&&(!Utility.IsEpoch(x.SellDate)&&x.SellDate>currentDate))||(x.PurchaseDate<=currentDate&&Utility.IsEpoch(x.SellDate))).ToList(); IEnumerable closedPositions=positions.Where(x => (!Utility.IsEpoch(x.SellDate)&&x.SellDate.Equals(currentDate))).ToList(); if(0==openPositions.Count()&&0==closedPositions.Count()) continue; double gainLoss=0.00; double gainLossClosedPositions=0.00; double exposure=0.00; double marketValue=0.00; // if(HolidayDA.IsMarketHoliday(currentDate)) continue; ModelPerformanceItem performanceItem=new ModelPerformanceItem(); foreach(MGPositionModel openPosition in openPositions) { exposure+=openPosition.Shares*openPosition.PurchasePrice; if(!LocalPriceCache.GetInstance().ContainsPrice(openPosition.Symbol,currentDate)) { Prices prices=PricingDA.GetPricesForward(openPosition.Symbol,currentDate,PricingDA.ForwardLookingDays); LocalPriceCache.GetInstance().Add(prices); } Price price=LocalPriceCache.GetInstance().GetPrice(openPosition.Symbol,currentDate); if(null==price) { MDTrace.WriteLine(LogLevel.DEBUG,String.Format("GetModelPerformance: No price for {0} on {1}",openPosition.Symbol,currentDate.ToShortDateString())); continue; } gainLoss+=((price.Close*openPosition.Shares)-(openPosition.PurchasePrice*openPosition.Shares)); marketValue+=(price.Close*openPosition.Shares); } foreach(MGPositionModel closedPosition in closedPositions) { double gainLossPosition=(closedPosition.CurrentPrice*closedPosition.Shares)-(closedPosition.PurchasePrice*closedPosition.Shares); gainLossClosedPositions+=gainLossPosition; } double dailyReturn=0.00; if(double.IsNaN(prevGainLoss)) dailyReturn=(marketValue-exposure)/Math.Abs(exposure); else dailyReturn=((gainLoss-prevGainLoss)/Math.Abs(prevGainLoss))/100.00; if(double.IsNaN(cumulativeReturn)) cumulativeReturn=1.00*(1.00+dailyReturn); else cumulativeReturn=cumulativeReturn*(1.00+dailyReturn); performanceItem.Date=currentDate; performanceItem.Exposure=exposure; performanceItem.MarketValue=marketValue; performanceItem.GainLossDOD=double.IsNaN(prevGainLoss)?gainLoss:(gainLoss-prevGainLoss)+gainLossClosedPositions; performanceItem.GainLoss=gainLoss+gainLossClosedPositions; performanceItem.ClosedPositions=closedPositions.Count()>0?true:false; performanceSeries.Add(performanceItem); prevGainLoss=gainLoss; } for(int index=0;index positions) { ModelPerformanceSeries performanceSeries=new ModelPerformanceSeries(); try { DateTime minDate=positions.Min(x => x.PurchaseDate); DateTime maxDate=PricingDA.GetLatestDate(); DateGenerator dateGenerator=new DateGenerator(); double cumulativeReturn=double.NaN; double prevGainLoss=double.NaN; LocalPriceCache.GetInstance().RemoveDate(maxDate); List historicalDates=dateGenerator.GenerateHistoricalDates(minDate,maxDate); foreach(DateTime currentDate in historicalDates) { IEnumerable openPositions=positions.Where(x => (x.PurchaseDate<=currentDate&&(!Utility.IsEpoch(x.SellDate)&&x.SellDate>currentDate))||(x.PurchaseDate<=currentDate&&Utility.IsEpoch(x.SellDate))).ToList(); IEnumerable closedPositions=positions.Where(x => (!Utility.IsEpoch(x.SellDate)&&x.SellDate.Equals(currentDate))).ToList(); if(0==openPositions.Count()&&0==closedPositions.Count()) continue; double gainLoss=0.00; double gainLossClosedPositions=0.00; double exposure=0.00; double marketValue=0.00; // if(HolidayDA.IsMarketHoliday(currentDate)) continue; ModelPerformanceItem performanceItem=new ModelPerformanceItem(); foreach(MGSHPositionModel openPosition in openPositions) { exposure+=openPosition.Shares*openPosition.PurchasePrice; if(!LocalPriceCache.GetInstance().ContainsPrice(openPosition.Symbol,currentDate)) { Prices prices=PricingDA.GetPricesForward(openPosition.Symbol,currentDate,PricingDA.ForwardLookingDays); LocalPriceCache.GetInstance().Add(prices); } Price price=LocalPriceCache.GetInstance().GetPrice(openPosition.Symbol,currentDate); if(null==price) { MDTrace.WriteLine(LogLevel.DEBUG,String.Format("GetModelPerformance: No price for {0} on {1}",openPosition.Symbol,currentDate.ToShortDateString())); continue; } gainLoss+=((price.Close*openPosition.Shares)-(openPosition.PurchasePrice*openPosition.Shares)); marketValue+=(price.Close*openPosition.Shares); } foreach(MGSHPositionModel closedPosition in closedPositions) { double gainLossPosition=(closedPosition.CurrentPrice*closedPosition.Shares)-(closedPosition.PurchasePrice*closedPosition.Shares); gainLossClosedPositions+=gainLossPosition; } double dailyReturn=0.00; if(double.IsNaN(prevGainLoss)) dailyReturn=(marketValue-exposure)/Math.Abs(exposure); else dailyReturn=((gainLoss-prevGainLoss)/Math.Abs(prevGainLoss))/100.00; if(double.IsNaN(cumulativeReturn)) cumulativeReturn=1.00*(1.00+dailyReturn); else cumulativeReturn=cumulativeReturn*(1.00+dailyReturn); performanceItem.Date=currentDate; performanceItem.Exposure=exposure; performanceItem.MarketValue=marketValue; performanceItem.GainLossDOD=double.IsNaN(prevGainLoss)?gainLoss:(gainLoss-prevGainLoss)+gainLossClosedPositions; performanceItem.GainLoss=gainLoss+gainLossClosedPositions; performanceItem.ClosedPositions=closedPositions.Count()>0?true:false; performanceSeries.Add(performanceItem); prevGainLoss=gainLoss; } for(int index=0;index