Use AI to fix some issues with the HVaR
All checks were successful
Build .NET Project / build (push) Successful in 4m53s
All checks were successful
Build .NET Project / build (push) Successful in 4m53s
This commit is contained in:
@@ -44,7 +44,8 @@ namespace MarketData.ValueAtRisk
|
||||
InitializeBins();
|
||||
GetMinMax(ref minValue,ref maxValue,values);
|
||||
binSize=(maxValue-minValue)/(double)binCount;
|
||||
for (double value = minValue; value < maxValue; value += binSize)
|
||||
if (binSize == 0) binSize = 1e-10;
|
||||
for (double value = minValue; value <= maxValue; value += binSize)
|
||||
{
|
||||
binItems.Add(new BinItem<T>(value));
|
||||
}
|
||||
@@ -76,7 +77,8 @@ namespace MarketData.ValueAtRisk
|
||||
InitializeBins();
|
||||
GetMinMax(ref minValue,ref maxValue,values);
|
||||
binSize=(maxValue-minValue)/(double)binCount;
|
||||
for (double value = minValue; value < maxValue; value += binSize)
|
||||
if (binSize == 0) binSize = 1e-10;
|
||||
for (double value = minValue; value <= maxValue; value += binSize)
|
||||
{
|
||||
binItems.Add(new BinItem<T>(value));
|
||||
}
|
||||
@@ -130,7 +132,6 @@ namespace MarketData.ValueAtRisk
|
||||
private void AddObjectToBin(double value,T item)
|
||||
{
|
||||
bool added = false;
|
||||
// samples++;
|
||||
for (int index = 0; index < binItems.Count; index++)
|
||||
{
|
||||
BinItem<T> binItem = binItems[index];
|
||||
|
||||
@@ -17,33 +17,50 @@ namespace MarketData.ValueAtRisk
|
||||
public static VaRResult GetVaR(PortfolioHoldings portfolioHoldings, double percentile,int returnDays=1)
|
||||
{
|
||||
VaRResult varResult=new VaRResult();
|
||||
if (null == portfolioHoldings || 0 == portfolioHoldings.Count)
|
||||
|
||||
if (portfolioHoldings == null || portfolioHoldings.Count == 0)
|
||||
{
|
||||
varResult.Success=false;
|
||||
return varResult;
|
||||
varResult.Success = false;
|
||||
varResult.Message = "Portfolio is null or empty.";
|
||||
return varResult;
|
||||
}
|
||||
|
||||
// Determine the minimum common price history across holdings
|
||||
int minPriceCount = int.MaxValue;
|
||||
|
||||
for (int i = 0; i < portfolioHoldings.Count; i++)
|
||||
{
|
||||
int count = portfolioHoldings[i].Prices.Count;
|
||||
if (count < minPriceCount)
|
||||
minPriceCount = count;
|
||||
}
|
||||
// This ensures that the pricing information for each holding is symmetric.
|
||||
// The piece of code that checks for jagged pricing should be handled differently. For example, we should be able to continue the VaR analysis and simply account for no exposure to the
|
||||
// given symbol in the event of a lack of pricing data. This would handle the current issue with securities that have been trading for less than the number of observation days.
|
||||
if (portfolioHoldings.Count > 1)
|
||||
|
||||
// Enforce minimum observation requirement (optional but recommended)
|
||||
if (minPriceCount < 30) // or whatever threshold you prefer
|
||||
{
|
||||
int priceCount=-1;
|
||||
for (int index = 1; index < portfolioHoldings.Count; index++)
|
||||
{
|
||||
if(portfolioHoldings[index].Prices.Count>priceCount)priceCount=portfolioHoldings[index].Prices.Count;
|
||||
}
|
||||
for (int index = 1; index < portfolioHoldings.Count; index++)
|
||||
{
|
||||
if (portfolioHoldings[index].Prices.Count != priceCount)
|
||||
varResult.Success = false;
|
||||
varResult.Message = $"Insufficient common price history ({minPriceCount} observations).";
|
||||
return varResult;
|
||||
}
|
||||
|
||||
// Truncate all holdings to the common window
|
||||
for (int i = 0; i < portfolioHoldings.Count; i++)
|
||||
{
|
||||
if (portfolioHoldings[i].Prices.Count > minPriceCount)
|
||||
{
|
||||
varResult.Success=false;
|
||||
varResult.Message=String.Format("Insufficient price history for {0}. {1}/{2}",portfolioHoldings[index].Symbol,portfolioHoldings[index].Prices.Count,priceCount);
|
||||
return varResult;
|
||||
portfolioHoldings[i].Prices = new MarketDataModel.Prices(portfolioHoldings[i].Prices.Skip(portfolioHoldings[i].Prices.Count - minPriceCount).ToList());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate total market value and then calculate the weightings of each holding
|
||||
double marketValue = portfolioHoldings.GetMarketValue();
|
||||
if (marketValue == 0)
|
||||
{
|
||||
varResult.Success = false;
|
||||
varResult.Message = "Portfolio market value is zero.";
|
||||
return varResult;
|
||||
}
|
||||
|
||||
for (int index = 0; index < portfolioHoldings.Count; index++)
|
||||
{
|
||||
PortfolioHolding portfolioHolding = portfolioHoldings[index];
|
||||
@@ -51,7 +68,8 @@ namespace MarketData.ValueAtRisk
|
||||
}
|
||||
// Calculate the weighted returns for the observation period
|
||||
portfolioHoldings.SetReturnDays(returnDays);
|
||||
int numReturns=portfolioHoldings[0].Returns.Length;
|
||||
// int numReturns=portfolioHoldings[0].Returns.Length;
|
||||
int numReturns = portfolioHoldings.Min(p => p.Returns.Length);
|
||||
WeightedReturnsWithContribution weightedReturnsWithContrbution=new WeightedReturnsWithContribution();
|
||||
for (int index = 0; index < numReturns; index++)
|
||||
{
|
||||
@@ -80,7 +98,7 @@ namespace MarketData.ValueAtRisk
|
||||
portfolioHoldingsBySymbol[contribution.Symbol].Contribution=contribution.ContributionValue;
|
||||
portfolioHoldingsBySymbol[contribution.Symbol].ContributionDate=contribution.AnalysisDate;
|
||||
}
|
||||
return new VaRResult(binResult.Value, portfolioHoldings.GetMarketValue() * binResult.Value);
|
||||
return new VaRResult(binResult.Value, marketValue * binResult.Value);
|
||||
}
|
||||
public int ReturnDays
|
||||
{
|
||||
|
||||
@@ -126,7 +126,6 @@ namespace MarketData.ValueAtRisk
|
||||
}
|
||||
public void SetReturnDays(int days)
|
||||
{
|
||||
if (returnDays == days) return;
|
||||
returnDays = days;
|
||||
returns = prices.GetReturnsAsDoubleArray(returnDays);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user