Init
This commit is contained in:
474
Model/ModelPerformanceAggregator.cs
Normal file
474
Model/ModelPerformanceAggregator.cs
Normal file
@@ -0,0 +1,474 @@
|
||||
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<CMTPositionModel> positions)
|
||||
{
|
||||
ModelPerformanceSeries performanceSeries=GetModelPerformance(positions);
|
||||
if(null==performanceSeries) return double.NaN;
|
||||
return performanceSeries[performanceSeries.Count-1].CumProdMinusOne;
|
||||
}
|
||||
public static ModelPerformanceSeries GetModelPerformance(IEnumerable<CMTPositionModel> 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<DateTime> historicalDates=dateGenerator.GenerateHistoricalDates(minDate,maxDate);
|
||||
|
||||
foreach(CMTPositionModel position in positions)
|
||||
{
|
||||
if(dateGenerator.IsWeekend(position.PurchaseDate))
|
||||
{
|
||||
while(true)
|
||||
{
|
||||
position.PurchaseDate=dateGenerator.GetNextBusinessDay(position.PurchaseDate);
|
||||
if(!HolidayDA.IsMarketHoliday(position.PurchaseDate)) break;
|
||||
}
|
||||
}
|
||||
if(dateGenerator.IsWeekend(position.SellDate))
|
||||
{
|
||||
while(true)
|
||||
{
|
||||
position.SellDate=dateGenerator.GetNextBusinessDay(position.SellDate);
|
||||
if(!HolidayDA.IsMarketHoliday(position.SellDate)) break;
|
||||
}
|
||||
}
|
||||
}
|
||||
foreach(DateTime currentDate in historicalDates)
|
||||
{
|
||||
IEnumerable<CMTPositionModel> openPositions=positions.Where(x => (x.PurchaseDate<=currentDate&&(!Utility.IsEpoch(x.SellDate)&&x.SellDate>currentDate))||(x.PurchaseDate<=currentDate&&Utility.IsEpoch(x.SellDate))).ToList();
|
||||
IEnumerable<CMTPositionModel> 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,90);
|
||||
LocalPriceCache.GetInstance().Add(prices);
|
||||
}
|
||||
Price price=LocalPriceCache.GetInstance().GetPrice(openPosition.Symbol,currentDate);
|
||||
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<performanceSeries.Count;index++)
|
||||
{
|
||||
ModelPerformanceItem currentModelPerformanceItem=performanceSeries[index];
|
||||
ModelPerformanceItem prevModelPerformanceItem=0==index?null:performanceSeries[index-1];
|
||||
if(null==prevModelPerformanceItem)
|
||||
{
|
||||
currentModelPerformanceItem.CumulativeGainLoss=currentModelPerformanceItem.GainLossDOD;
|
||||
currentModelPerformanceItem.R=(currentModelPerformanceItem.MarketValue-currentModelPerformanceItem.Exposure)/currentModelPerformanceItem.Exposure;
|
||||
currentModelPerformanceItem.OnePlusR=1.00+currentModelPerformanceItem.R;
|
||||
currentModelPerformanceItem.CumProd=currentModelPerformanceItem.OnePlusR;
|
||||
currentModelPerformanceItem.CumProdMinusOne=currentModelPerformanceItem.CumProd-1.00;
|
||||
}
|
||||
else
|
||||
{
|
||||
currentModelPerformanceItem.CumulativeGainLoss=currentModelPerformanceItem.GainLossDOD+prevModelPerformanceItem.CumulativeGainLoss;
|
||||
currentModelPerformanceItem.R=prevModelPerformanceItem.Exposure.Equals(currentModelPerformanceItem.Exposure)?(currentModelPerformanceItem.MarketValue-prevModelPerformanceItem.MarketValue)/prevModelPerformanceItem.MarketValue:0;
|
||||
currentModelPerformanceItem.OnePlusR=1.00+currentModelPerformanceItem.R;
|
||||
currentModelPerformanceItem.CumProd=currentModelPerformanceItem.OnePlusR*prevModelPerformanceItem.CumProd;
|
||||
currentModelPerformanceItem.CumProdMinusOne=currentModelPerformanceItem.CumProd-1.00;
|
||||
}
|
||||
}
|
||||
return performanceSeries;
|
||||
}
|
||||
catch(Exception)
|
||||
{
|
||||
return performanceSeries;
|
||||
}
|
||||
}
|
||||
//public static double CalculateCumulativeReturn(IEnumerable<MMPositionModel> positions)
|
||||
//{
|
||||
// ModelPerformanceSeries performanceSeries=GetModelPerformance(positions);
|
||||
// if(null==performanceSeries) return double.NaN;
|
||||
// return performanceSeries[performanceSeries.Count-1].CumProdMinusOne;
|
||||
//}
|
||||
//public static ModelPerformanceSeries GetModelPerformance(IEnumerable<MMPositionModel> 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<DateTime> historicalDates=dateGenerator.GenerateHistoricalDates(minDate,maxDate);
|
||||
|
||||
// foreach(MMPositionModel position in positions)
|
||||
// {
|
||||
// if(dateGenerator.IsWeekend(position.PurchaseDate))
|
||||
// {
|
||||
// while(true)
|
||||
// {
|
||||
// position.PurchaseDate=dateGenerator.GetNextBusinessDay(position.PurchaseDate);
|
||||
// if(!HolidayDA.IsMarketHoliday(position.PurchaseDate)) break;
|
||||
// }
|
||||
// }
|
||||
// if(dateGenerator.IsWeekend(position.SellDate))
|
||||
// {
|
||||
// while(true)
|
||||
// {
|
||||
// position.SellDate=dateGenerator.GetNextBusinessDay(position.SellDate);
|
||||
// if(!HolidayDA.IsMarketHoliday(position.SellDate)) break;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// foreach(DateTime currentDate in historicalDates)
|
||||
// {
|
||||
// IEnumerable<MMPositionModel> openPositions=positions.Where(x => (x.PurchaseDate<=currentDate&&(!Utility.IsEpoch(x.SellDate)&&x.SellDate>currentDate))||(x.PurchaseDate<=currentDate&&Utility.IsEpoch(x.SellDate))).ToList();
|
||||
// IEnumerable<MMPositionModel> 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(MMPositionModel openPosition in openPositions)
|
||||
// {
|
||||
// exposure+=openPosition.Shares*openPosition.PurchasePrice;
|
||||
// if(!LocalPriceCache.GetInstance().ContainsPrice(openPosition.Symbol,currentDate))
|
||||
// {
|
||||
// Prices prices=PricingDA.GetPricesForward(openPosition.Symbol,currentDate,90);
|
||||
// LocalPriceCache.GetInstance().Add(prices);
|
||||
// }
|
||||
// Price price=LocalPriceCache.GetInstance().GetPrice(openPosition.Symbol,currentDate);
|
||||
// gainLoss+=((price.Close*openPosition.Shares)-(openPosition.PurchasePrice*openPosition.Shares));
|
||||
// marketValue+=(price.Close*openPosition.Shares);
|
||||
// }
|
||||
// foreach(MMPositionModel 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<performanceSeries.Count;index++)
|
||||
// {
|
||||
// ModelPerformanceItem currentModelPerformanceItem=performanceSeries[index];
|
||||
// ModelPerformanceItem prevModelPerformanceItem=0==index?null:performanceSeries[index-1];
|
||||
// if(null==prevModelPerformanceItem)
|
||||
// {
|
||||
// currentModelPerformanceItem.CumulativeGainLoss=currentModelPerformanceItem.GainLossDOD;
|
||||
// currentModelPerformanceItem.R=(currentModelPerformanceItem.MarketValue-currentModelPerformanceItem.Exposure)/currentModelPerformanceItem.Exposure;
|
||||
// currentModelPerformanceItem.OnePlusR=1.00+currentModelPerformanceItem.R;
|
||||
// currentModelPerformanceItem.CumProd=currentModelPerformanceItem.OnePlusR;
|
||||
// currentModelPerformanceItem.CumProdMinusOne=currentModelPerformanceItem.CumProd-1.00;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// currentModelPerformanceItem.CumulativeGainLoss=currentModelPerformanceItem.GainLossDOD+prevModelPerformanceItem.CumulativeGainLoss;
|
||||
// currentModelPerformanceItem.R=prevModelPerformanceItem.Exposure.Equals(currentModelPerformanceItem.Exposure)?(currentModelPerformanceItem.MarketValue-prevModelPerformanceItem.MarketValue)/prevModelPerformanceItem.MarketValue:0;
|
||||
// currentModelPerformanceItem.OnePlusR=1.00+currentModelPerformanceItem.R;
|
||||
// currentModelPerformanceItem.CumProd=currentModelPerformanceItem.OnePlusR*prevModelPerformanceItem.CumProd;
|
||||
// currentModelPerformanceItem.CumProdMinusOne=currentModelPerformanceItem.CumProd-1.00;
|
||||
// }
|
||||
// }
|
||||
// return performanceSeries;
|
||||
// }
|
||||
// catch(Exception)
|
||||
// {
|
||||
// return performanceSeries;
|
||||
// }
|
||||
//}
|
||||
// ***********************************************************************************************************************************************************************************************************
|
||||
// *********************************************************************************** C L E N O W M O M E N T U M **************************************************************************************
|
||||
// ***********************************************************************************************************************************************************************************************************
|
||||
public static double CalculateCumulativeReturn(IEnumerable<CMPositionModel> positions)
|
||||
{
|
||||
ModelPerformanceSeries performanceSeries=GetModelPerformance(positions);
|
||||
if(null==performanceSeries)return double.NaN;
|
||||
return performanceSeries[performanceSeries.Count-1].CumProdMinusOne;
|
||||
}
|
||||
public static double CalculateCumulativeReturn(IEnumerable<MGPositionModel> positions)
|
||||
{
|
||||
ModelPerformanceSeries performanceSeries=GetModelPerformance(positions);
|
||||
if(null==performanceSeries) return double.NaN;
|
||||
return performanceSeries[performanceSeries.Count-1].CumProdMinusOne;
|
||||
}
|
||||
public static ModelPerformanceSeries GetModelPerformance(IEnumerable<CMPositionModel> 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<DateTime> historicalDates=dateGenerator.GenerateHistoricalDates(minDate,maxDate);
|
||||
|
||||
foreach(CMPositionModel position in positions)
|
||||
{
|
||||
if(dateGenerator.IsWeekend(position.PurchaseDate))
|
||||
{
|
||||
while(true)
|
||||
{
|
||||
position.PurchaseDate=dateGenerator.GetNextBusinessDay(position.PurchaseDate);
|
||||
if(!HolidayDA.IsMarketHoliday(position.PurchaseDate)) break;
|
||||
}
|
||||
}
|
||||
if(dateGenerator.IsWeekend(position.SellDate))
|
||||
{
|
||||
while(true)
|
||||
{
|
||||
position.SellDate=dateGenerator.GetNextBusinessDay(position.SellDate);
|
||||
if(!HolidayDA.IsMarketHoliday(position.SellDate)) break;
|
||||
}
|
||||
}
|
||||
}
|
||||
foreach(DateTime currentDate in historicalDates)
|
||||
{
|
||||
IEnumerable<CMPositionModel> openPositions=positions.Where(x => (x.PurchaseDate<=currentDate&&(!Utility.IsEpoch(x.SellDate)&&x.SellDate>currentDate))||(x.PurchaseDate<=currentDate&&Utility.IsEpoch(x.SellDate))).ToList();
|
||||
IEnumerable<CMPositionModel> 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,90);
|
||||
LocalPriceCache.GetInstance().Add(prices);
|
||||
}
|
||||
Price price=LocalPriceCache.GetInstance().GetPrice(openPosition.Symbol,currentDate);
|
||||
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<performanceSeries.Count;index++)
|
||||
{
|
||||
ModelPerformanceItem currentModelPerformanceItem=performanceSeries[index];
|
||||
ModelPerformanceItem prevModelPerformanceItem=0==index?null:performanceSeries[index-1];
|
||||
if(null==prevModelPerformanceItem)
|
||||
{
|
||||
currentModelPerformanceItem.CumulativeGainLoss=currentModelPerformanceItem.GainLossDOD;
|
||||
currentModelPerformanceItem.R=(currentModelPerformanceItem.MarketValue-currentModelPerformanceItem.Exposure)/currentModelPerformanceItem.Exposure;
|
||||
currentModelPerformanceItem.OnePlusR=1.00+currentModelPerformanceItem.R;
|
||||
currentModelPerformanceItem.CumProd=currentModelPerformanceItem.OnePlusR;
|
||||
currentModelPerformanceItem.CumProdMinusOne=currentModelPerformanceItem.CumProd-1.00;
|
||||
}
|
||||
else
|
||||
{
|
||||
currentModelPerformanceItem.CumulativeGainLoss=currentModelPerformanceItem.GainLossDOD+prevModelPerformanceItem.CumulativeGainLoss;
|
||||
currentModelPerformanceItem.R=prevModelPerformanceItem.Exposure.Equals(currentModelPerformanceItem.Exposure)?(currentModelPerformanceItem.MarketValue-prevModelPerformanceItem.MarketValue)/prevModelPerformanceItem.MarketValue:0;
|
||||
currentModelPerformanceItem.OnePlusR=1.00+currentModelPerformanceItem.R;
|
||||
currentModelPerformanceItem.CumProd=currentModelPerformanceItem.OnePlusR*prevModelPerformanceItem.CumProd;
|
||||
currentModelPerformanceItem.CumProdMinusOne=currentModelPerformanceItem.CumProd-1.00;
|
||||
}
|
||||
}
|
||||
return performanceSeries;
|
||||
}
|
||||
catch(Exception)
|
||||
{
|
||||
return performanceSeries;
|
||||
}
|
||||
}
|
||||
// ***********************************************************************************************************************************************************************************************************
|
||||
// *********************************************************************************** Q U A N T U M M O M E N T U M **************************************************************************************
|
||||
// ***********************************************************************************************************************************************************************************************************
|
||||
public static ModelPerformanceSeries GetModelPerformance(IEnumerable<MGPositionModel> 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<DateTime> historicalDates=dateGenerator.GenerateHistoricalDates(minDate,maxDate);
|
||||
|
||||
foreach(MGPositionModel position in positions)
|
||||
{
|
||||
if(dateGenerator.IsWeekend(position.PurchaseDate))
|
||||
{
|
||||
while(true)
|
||||
{
|
||||
position.PurchaseDate=dateGenerator.GetNextBusinessDay(position.PurchaseDate);
|
||||
if(!HolidayDA.IsMarketHoliday(position.PurchaseDate)) break;
|
||||
}
|
||||
}
|
||||
if(dateGenerator.IsWeekend(position.SellDate))
|
||||
{
|
||||
while(true)
|
||||
{
|
||||
position.SellDate=dateGenerator.GetNextBusinessDay(position.SellDate);
|
||||
if(!HolidayDA.IsMarketHoliday(position.SellDate)) break;
|
||||
}
|
||||
}
|
||||
}
|
||||
foreach(DateTime currentDate in historicalDates)
|
||||
{
|
||||
IEnumerable<MGPositionModel> openPositions=positions.Where(x => (x.PurchaseDate<=currentDate&&(!Utility.IsEpoch(x.SellDate)&&x.SellDate>currentDate))||(x.PurchaseDate<=currentDate&&Utility.IsEpoch(x.SellDate))).ToList();
|
||||
IEnumerable<MGPositionModel> 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,90);
|
||||
LocalPriceCache.GetInstance().Add(prices);
|
||||
}
|
||||
Price price=LocalPriceCache.GetInstance().GetPrice(openPosition.Symbol,currentDate);
|
||||
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<performanceSeries.Count;index++)
|
||||
{
|
||||
ModelPerformanceItem currentModelPerformanceItem=performanceSeries[index];
|
||||
ModelPerformanceItem prevModelPerformanceItem=0==index?null:performanceSeries[index-1];
|
||||
if(null==prevModelPerformanceItem)
|
||||
{
|
||||
currentModelPerformanceItem.CumulativeGainLoss=currentModelPerformanceItem.GainLossDOD;
|
||||
currentModelPerformanceItem.R=(currentModelPerformanceItem.MarketValue-currentModelPerformanceItem.Exposure)/currentModelPerformanceItem.Exposure;
|
||||
currentModelPerformanceItem.OnePlusR=1.00+currentModelPerformanceItem.R;
|
||||
currentModelPerformanceItem.CumProd=currentModelPerformanceItem.OnePlusR;
|
||||
currentModelPerformanceItem.CumProdMinusOne=currentModelPerformanceItem.CumProd-1.00;
|
||||
}
|
||||
else
|
||||
{
|
||||
currentModelPerformanceItem.CumulativeGainLoss=currentModelPerformanceItem.GainLossDOD+prevModelPerformanceItem.CumulativeGainLoss;
|
||||
currentModelPerformanceItem.R=prevModelPerformanceItem.Exposure.Equals(currentModelPerformanceItem.Exposure)?(currentModelPerformanceItem.MarketValue-prevModelPerformanceItem.MarketValue)/prevModelPerformanceItem.MarketValue:0;
|
||||
currentModelPerformanceItem.OnePlusR=1.00+currentModelPerformanceItem.R;
|
||||
currentModelPerformanceItem.CumProd=currentModelPerformanceItem.OnePlusR*prevModelPerformanceItem.CumProd;
|
||||
currentModelPerformanceItem.CumProdMinusOne=currentModelPerformanceItem.CumProd-1.00;
|
||||
}
|
||||
}
|
||||
return performanceSeries;
|
||||
}
|
||||
catch(Exception)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user