Files
ARM64/MarketData/MarketDataLib/ValueAtRisk/BinManager.cs
Sean 26a8c4794b
All checks were successful
Build .NET Project / build (push) Successful in 4m53s
Use AI to fix some issues with the HVaR
2026-02-19 20:12:40 -05:00

149 lines
4.3 KiB
C#
Executable File

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace MarketData.ValueAtRisk
{
public class BinResult<T>
{
public double Value{get;private set;}
public T Item{get;private set;}
public BinResult()
{
}
public BinResult(double value,T item)
{
this.Value=value;
this.Item=item;
}
}
public class BinManager<T>
{
private List<BinItem<T>> binItems;
private long binCount;
private long samples;
public BinManager(long binCount=100)
{
this.binCount = binCount;
InitializeBins();
}
private void InitializeBins()
{
this.binItems = new List<BinItem<T>>();
this.samples=0;
}
public BinResult<T> GetVaRReturn(double[] values,List<T> items,double percentile)
{
double minValue = float.NaN;
double maxValue = float.NaN;
double binSize = double.NaN;
T item=default(T);
InitializeBins();
GetMinMax(ref minValue,ref maxValue,values);
binSize=(maxValue-minValue)/(double)binCount;
if (binSize == 0) binSize = 1e-10;
for (double value = minValue; value <= maxValue; value += binSize)
{
binItems.Add(new BinItem<T>(value));
}
for (int index = 0; index < values.Length; index++)
{
AddValueToBin(values[index]);
AddObjectToBin(values[index],items[index]);
}
double samplesAtRank = samples-(samples * (percentile/100.00));
if (samplesAtRank < 1) samplesAtRank = 1;
long samplesInRank = 0;
double percentVaR = 0;
for (int index = 0; index < binItems.Count; index++)
{
BinItem<T> binItem = binItems[index];
samplesInRank += binItem.BinCount;
percentVaR = binItem.BinValue;
item=binItem.BinObject;
if (samplesInRank > samplesAtRank) break;
}
return new BinResult<T>(percentVaR,item);
}
public double GetVaRReturn(double[] values,double percentile)
{
double minValue = float.NaN;
double maxValue = float.NaN;
double binSize = double.NaN;
InitializeBins();
GetMinMax(ref minValue,ref maxValue,values);
binSize=(maxValue-minValue)/(double)binCount;
if (binSize == 0) binSize = 1e-10;
for (double value = minValue; value <= maxValue; value += binSize)
{
binItems.Add(new BinItem<T>(value));
}
for (int index = 0; index < values.Length; index++)
{
AddValueToBin(values[index]);
}
double samplesAtRank = samples-(samples * (percentile/100.00));
if (samplesAtRank < 1) samplesAtRank = 1;
long samplesInRank = 0;
double percentVaR = 0;
for (int index = 0; index < binItems.Count; index++)
{
BinItem<T> binItem = binItems[index];
samplesInRank += binItem.BinCount;
percentVaR = binItem.BinValue;
if (samplesInRank > samplesAtRank) break;
}
return percentVaR;
}
private static void GetMinMax(ref double minValue,ref double maxValue,double[] values)
{
for (int index = 0; index < values.Length; index++)
{
double value = values[index];
if (0 == index)
{
minValue = maxValue = value;
continue;
}
if (value > maxValue) maxValue = value;
if (value < minValue) minValue = value;
}
}
private void AddValueToBin(double value)
{
bool added = false;
samples++;
for (int index = 0; index < binItems.Count; index++)
{
BinItem<T> binItem = binItems[index];
if (value <= binItem.BinValue)
{
binItem.BinCount++;
added = true;
break;
}
}
if (false == added && binItems.Count>0) binItems[binItems.Count - 1].BinCount++;
}
private void AddObjectToBin(double value,T item)
{
bool added = false;
for (int index = 0; index < binItems.Count; index++)
{
BinItem<T> binItem = binItems[index];
if (value <= binItem.BinValue)
{
binItem.BinObject=item;
added = true;
break;
}
}
if (false == added && binItems.Count>0) binItems[binItems.Count - 1].BinObject=item;
}
}
}