Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Common/Statistics/PortfolioStatistics.cs
Original file line number Diff line number Diff line change
Expand Up @@ -299,7 +299,7 @@ public PortfolioStatistics(
var benchmarkVariance = listBenchmark.Variance();
Beta = benchmarkVariance.IsNaNOrZero() ? 0 : (decimal)(listPerformance.Covariance(listBenchmark) / benchmarkVariance);

Alpha = Beta == 0 ? 0 : annualPerformance - (riskFreeRate + Beta * (benchmarkAnnualPerformance - riskFreeRate));
Alpha = Beta == 0 ? 0 : Extensions.SafeDecimalCast((double)annualPerformance - ((double)riskFreeRate + (double)Beta * ((double)benchmarkAnnualPerformance - (double)riskFreeRate)));

TrackingError = (decimal)Statistics.TrackingError(listPerformance, listBenchmark, (double)tradingDaysPerYear);

Expand Down
20 changes: 20 additions & 0 deletions Tests/Common/Statistics/PortfolioStatisticsTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,26 @@ public void PortfolioStatisticsDoesNotFailWhenAnnualPerformanceIsLarge()
Assert.DoesNotThrow(() => new PortfolioStatistics(profitLoss, equity, portfolioTurnover, listPerformance, listBenchmark, startingCapital, riskFreeInterestRateModel, tradingDaysPerYear));
}

[Test]
public void PortfolioStatisticsDoesNotFailWhenAlphaExceedsDecimalRange()
{
var profitLoss = new SortedDictionary<DateTime, decimal>();
var equity = new SortedDictionary<DateTime, decimal>();
var portfolioTurnover = new SortedDictionary<DateTime, decimal>();
// A deposit into a live account shows up as one huge daily return, which caps the annual performance at decimal.MaxValue
var listPerformance = new List<double>() { 0.001, 0.004, 1.56, 0.002 };
// The benchmark rises on the deposit day and falls overall, so beta is large and the benchmark term of alpha is negative
var listBenchmark = new List<double>() { -0.004, -0.006, 0.005, -0.003 };
var startingCapital = 100000;
var riskFreeInterestRateModel = new InterestRateProvider();
var tradingDaysPerYear = 252;

var statistics = default(PortfolioStatistics);
Assert.DoesNotThrow(() => statistics = new PortfolioStatistics(profitLoss, equity, portfolioTurnover, listPerformance, listBenchmark, startingCapital, riskFreeInterestRateModel, tradingDaysPerYear));

Assert.AreEqual(decimal.MaxValue, statistics.Alpha);
}

/// <summary>
/// Initialize and return Portfolio Statistics depends on input data
/// </summary>
Expand Down
Loading