using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace MarketData.ValueAtRisk { public class BinResult { 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 { private List> binItems; private long binCount; private long samples; public BinManager(long binCount=100) { this.binCount = binCount; InitializeBins(); } private void InitializeBins() { this.binItems = new List>(); this.samples=0; } public BinResult GetVaRReturn(double[] values,List 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(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 binItem = binItems[index]; samplesInRank += binItem.BinCount; percentVaR = binItem.BinValue; item=binItem.BinObject; if (samplesInRank > samplesAtRank) break; } return new BinResult(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(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 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 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 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; } } }