This commit is contained in:
2024-02-23 06:53:16 -05:00
commit dbdccce727
1094 changed files with 57645 additions and 0 deletions

View File

@@ -0,0 +1,139 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
//using MarketData.DataAccess;
using MarketData.MarketDataModel;
using MarketData.Utils;
// This Beta calculator is modelled after Yahoo Finance Beta calculator. It calculates Beta using 36 monthly prices start at beginning of previous month and going back 36 months
// While the calculator does not match exactly to Yahoo Finance I will use this as an alternative in the event that Yahoo Finance Beta is no longer available.
namespace MarketData.Numerical
{
public class BetaPrices : List<BetaPrice>
{
public BetaPrices()
{
}
// assuming that the list is in descending date order
public double[] ReturnsBenchmark()
{
double[] returns=new double[Count-1];
for(int index=Count-2;index>=0;index--)
{
if(this[index+1].PriceBenchmark.Close==0.00)returns[index]=0.00;
else returns[index]=(this[index].PriceBenchmark.Close-this[index+1].PriceBenchmark.Close)/this[index+1].PriceBenchmark.Close;
}
return returns;
}
public double[] ReturnsSymbol()
{
double[] returns=new double[Count-1];
for(int index=Count-2;index>=0;index--)
{
if(this[index+1].PriceSymbol.Close==0.00)returns[index]=0.00;
else returns[index]=(this[index].PriceSymbol.Close-this[index+1].PriceSymbol.Close)/this[index+1].PriceSymbol.Close;
}
return returns;
}
}
public class BetaPrice
{
public BetaPrice(String symbol,String benchmark,Price symbolPrice,Price benchmarkPrice,DateTime pricingDate)
{
Symbol=symbol;
Benchmark=benchmark;
PricingDate=pricingDate;
PriceSymbol=symbolPrice;
PriceBenchmark=benchmarkPrice;
}
public DateTime PricingDate{get;set;}
public String Symbol{get;set;}
public String Benchmark{get;set;}
public Price PriceSymbol{get;set;}
public Price PriceBenchmark{get;set;}
}
public class BetaGenerator
{
private BetaGenerator()
{
}
//public static double Beta(String symbol,int months = 36)
//{
// return Beta(symbol, PricingDA.GetLatestDate(symbol), months);
//}
//public static double Beta(String symbol,DateTime asof,int months=36)
//{
// try
// {
// String benchmark = "SPY";
// DateGenerator dateGenerator = new DateGenerator();
// BetaPrices betaPrices = new BetaPrices();
// DateTime startDate = dateGenerator.GetPrevMonthStart(asof);
// DateTime minPricingDate = PricingDA.GetEarliestDate(symbol);
// Dictionary<DateTime, Price> symbolPricesByDate = new Dictionary<DateTime, Price>();
// Dictionary<DateTime, Price> benchmarkPricesByDate = new Dictionary<DateTime, Price>();
// List<DateTime> historicalDates = new List<DateTime>();
// while (historicalDates.Count < (months + 1))
// {
// historicalDates.Add(startDate);
// startDate = dateGenerator.GetPrevMonthStart(startDate);
// }
// Prices symbolPrices = PricingDA.GetPrices(symbol, asof, historicalDates[historicalDates.Count - 1]);
// Prices benchmarkPrices = PricingDA.GetPrices(benchmark, asof, historicalDates[historicalDates.Count - 1]);
// foreach (Price price in symbolPrices) symbolPricesByDate.Add(price.Date, price);
// foreach (Price price in benchmarkPrices) benchmarkPricesByDate.Add(price.Date, price);
// startDate = dateGenerator.GetPrevMonthStart(asof);
// while (betaPrices.Count < (months + 1))
// {
// BetaPrice betaPrice = GetPrice(symbol, benchmark, startDate, symbolPricesByDate, benchmarkPricesByDate);
// if (null == betaPrice)
// {
// return double.NaN;
// }
// betaPrices.Add(betaPrice);
// startDate = dateGenerator.GetPrevMonthStart(startDate);
// if (startDate < minPricingDate) break;
// }
// double[] returnsSymbol = betaPrices.ReturnsSymbol();
// double[] returnsBenchmark = betaPrices.ReturnsBenchmark();
// double beta = Numerics.Beta(ref returnsSymbol, ref returnsBenchmark);
// return beta;
// }
// catch (Exception exception)
// {
// MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Exception:{0}",exception.ToString()));
// return double.NaN;
// }
//}
private static BetaPrice GetPrice(String symbol, String benchmark, DateTime requestedDate, Dictionary<DateTime, Price> symbolPricesByDate, Dictionary<DateTime, Price> benchmarkPricesByDate)
{
try
{
int maxAdvanceDays = 10;
Price symbolPrice = null;
Price benchmarkPrice = null;
for (int advanceDays = 0; advanceDays < maxAdvanceDays; advanceDays++)
{
if (!symbolPricesByDate.ContainsKey(requestedDate)) { requestedDate = requestedDate.AddDays(1); continue; }
symbolPrice = symbolPricesByDate[requestedDate];
if (!benchmarkPricesByDate.ContainsKey(requestedDate)) { requestedDate = requestedDate.AddDays(1); continue; }
benchmarkPrice = benchmarkPricesByDate[requestedDate];
}
if (null == symbolPrice || null == benchmarkPrice) return null;
symbolPrice.Date = requestedDate.Date;
benchmarkPrice.Date = requestedDate.Date;
return new BetaPrice(symbol, benchmark, symbolPrice, benchmarkPrice, requestedDate);
}
catch (Exception exception)
{
MDTrace.WriteLine(LogLevel.DEBUG, String.Format("Exception:{0}", exception.ToString()));
return null;
}
}
}
}

View File

@@ -0,0 +1,66 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MarketData.Numerical
{
public interface IBinValueExtractor
{
double BinValue();
}
public class BinCollection<T> : List<BinItems<T>>
{
}
public class BinItems<T> : List<T>
{
public BinItems()
{
}
public BinItems(List<T> list)
{
foreach(T item in list)Add(item);
}
}
public class BinHelper<T> where T : IBinValueExtractor
{
public static BinCollection<T> CreateBins(BinItems<T> items,int bins)
{
BinCollection<T> binCollection=new BinCollection<T>();
if(null==items||0==items.Count)
{
for(int index=0;index<bins;index++)binCollection.Add(new BinItems<T>());
return binCollection;
}
items.Sort();
T minItem=items[0];
T maxItem=items[items.Count-1];
double midPoint=(maxItem.BinValue()-minItem.BinValue())/(double)bins;
List<double> borderValues=new List<double>();
for(int index=0;index<bins+1;index++)
{
if(0==index){borderValues.Add(minItem.BinValue());continue;}
else if(index==bins)borderValues.Add(borderValues[index-1]+midPoint+1);
else borderValues.Add(borderValues[index-1]+midPoint);
}
binCollection.Add(new BinItems<T>());
for(int index=0;index<borderValues.Count;index++)
{
double lowerBound;
double upperBound;
BinItems<T> binItems=binCollection[binCollection.Count-1];
lowerBound=borderValues[index];
if(index==borderValues.Count-1)upperBound=maxItem.BinValue();
else upperBound=borderValues[index+1];
for(int itemIndex=0;itemIndex<items.Count;itemIndex++)
{
T item=items[itemIndex];
if(item.BinValue()>=lowerBound&&item.BinValue()<upperBound)binItems.Add(item);
}
if(index<borderValues.Count-2)binCollection.Add(new BinItems<T>());
}
return binCollection;
}
}
}

View File

@@ -0,0 +1,73 @@
using System;
using System.Collections.Generic;
using MarketData.MarketDataModel;
namespace MarketData.Numerical
{
/// <summary>
/// Black Sholes Option Pricing Model for simplest scenario
/// </summary>
public class BlackScholesOptionPricingModel
{
private BlackScholesOptionPricingModel()
{
}
/// <summary>
/// Get Option price by applying BlackScholesOptionPricingModel
/// </summary>
/// <param name="optionType">Enum to indicate whether Call or Put</param>
/// <param name="S">Price of underlying</param>
/// <param name="X">Strike price</param>
/// <param name="T">Time to expiration in years</param>
/// <param name="r">Risk free interest rate</param>
/// <param name="v">Volatility</param>
/// <returns></returns>
//public static double GetPrice(OptionTypeEnum optionType, double S, double X, double T, double r, double v)
//{
// double d1 = 0.0;
// double d2 = 0.0;
// double optionValue = 0.0;
// d1 = (Math.Log(S / X) + (r + v * v / 2.0) * T) / (v * Math.Sqrt(T));
// d2 = d1 - v * Math.Sqrt(T);
// if (optionType == OptionTypeEnum.CallOption)
// {
// optionValue = S * CumulativeNormalDistributionFun(d1) - X * Math.Exp(-r * T) * CumulativeNormalDistributionFun(d2);
// }
// else if (optionType == OptionTypeEnum.PutOption)
// {
// optionValue = X * Math.Exp(-r * T) * CumulativeNormalDistributionFun(-d2) - S * CumulativeNormalDistributionFun(-d1);
// }
// return optionValue;
//}
/// <summary>
/// Cumulative normal distribution function
/// </summary>
/// <param name="d"></param>
/// <returns></returns>
private static double CumulativeNormalDistributionFun(double d)
{
double L = 0.0;
double K = 0.0;
double dCND = 0.0;
const double a1 = 0.31938153;
const double a2 = -0.356563782;
const double a3 = 1.781477937;
const double a4 = -1.821255978;
const double a5 = 1.330274429;
L = Math.Abs(d);
K = 1.0 / (1.0 + 0.2316419 * L);
dCND = 1.0 - 1.0 / Math.Sqrt(2 * Convert.ToDouble(Math.PI)) * Math.Exp(-L * L / 2.0) * (a1 * K + a2 * K * K + a3 * Math.Pow(K, 3.0) + a4 * Math.Pow(K, 4.0) + a5 * Math.Pow(K, 5.0));
if (d < 0)
{
return 1.0 - dCND;
}
else
{
return dCND;
}
}
}
}

View File

@@ -0,0 +1,52 @@
using System;
using System.Collections;
//using System.Data.SqlClient;
using System.Text;
using System.IO;
// Filename: KSTest.cs
// Author:Yan Kvitko
// Date:01/2005
namespace MarketData.Numerical
{
[Serializable]
public class KSTest
{
private int h;
private double pValue;
private double ksStat;
private double criticalValue;
public KSTest()
{
}
public KSTest(int h, double pValue, double ksStat, double criticalValue)
{
this.h=h;
this.pValue=pValue;
this.ksStat=ksStat;
this.criticalValue=criticalValue;
}
public int H
{
get{return h;}
set{h=value;}
}
public double PValue
{
get{return pValue;}
set{pValue=value;}
}
public double KSStat
{
get{return ksStat;}
set{ksStat=value;}
}
public double CriticalValue
{
get{return criticalValue;}
set{criticalValue=value;}
}
}
}

View File

@@ -0,0 +1,134 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using MarketData.Utils;
namespace MarketData.Numerical
{
public class LeastSquaresResult
{
public double[] LeastSquares { get; set; }
public double YIntercept { get; set; }
public double XIntercept { get; set; }
public double Slope { get; set; }
public void Extend(int itemCount, double slope) // extend the result set by itemCount by applying the slope to subsequent values
{
if (null == LeastSquares || 0 == LeastSquares.Length) return;
double[] extendedItems = new double[itemCount + LeastSquares.Length];
Array.Copy(LeastSquares, 0, extendedItems, itemCount, LeastSquares.Length);
for (int index = itemCount - 1; index >= 0; index--)
{
extendedItems[index] = extendedItems[index + 1] + slope;
}
LeastSquares = extendedItems;
}
}
public class LeastSquaresResultWithR2 : LeastSquaresResult
{
public double RSquared { get; set; }
}
// **********************************************************************************************************************************************
public class LeastSquaresHelper
{
private LeastSquaresHelper()
{
}
// This version reverses the slope because the input data is in reverse order
// The input data should be in the following manner observations[count-1]=earliest data point, observations[0]=most recent data point
// This version should be retained as-is because it is being referenced in models etc.,
public static LeastSquaresResult CalculateLeastSquares(double[] observations)
{
try
{
LeastSquaresResult leastSquaresResult = new LeastSquaresResult();
double[] xSeries = new double[observations.Length];
double[] xMinusXMean = new double[observations.Length];
double[] yMinusYMean = new double[observations.Length];
double[] meanProduct = new double[observations.Length];
double[] xMinusXMeanSquared = new double[observations.Length];
double[] leastSquares = new double[observations.Length];
double xMean = double.NaN;
double yMean = double.NaN;
double slope = double.NaN;
double yIntercept = double.NaN;
for (int index = 0; index < xSeries.Length; index++) xSeries[index] = index + 1;
xMean = Numerics.Mean(ref xSeries);
yMean = Numerics.Mean(ref observations);
for (int index = 0; index < observations.Length; index++)
{
xMinusXMean[index] = xSeries[index] - xMean;
yMinusYMean[index] = observations[index] - yMean;
meanProduct[index] = xMinusXMean[index] * yMinusYMean[index];
xMinusXMeanSquared[index] = xMinusXMean[index] * xMinusXMean[index];
}
slope = Numerics.Sum(ref meanProduct) / Numerics.Sum(ref xMinusXMeanSquared);
yIntercept = Numerics.YIntercept(xMean, yMean, slope);
for (int index = 0; index < leastSquares.Length; index++) leastSquares[index] = slope * xSeries[index] + yIntercept;
leastSquaresResult.LeastSquares = leastSquares;
leastSquaresResult.YIntercept = yIntercept;
leastSquaresResult.XIntercept = xMean;
leastSquaresResult.Slope = slope * -1.00;
return leastSquaresResult;
}
catch (Exception exception)
{
MDTrace.WriteLine(LogLevel.DEBUG, exception.ToString());
return null;
}
}
// This version uses the true slope whereas the version above reverses the slope due to the arrangement of the input data
// The input data should be in the following manner observations[0]=earliest data point, observations[count-1]=most recent data point
public static LeastSquaresResultWithR2 CalculateLeastSquaresWithR2(double[] observations)
{
try
{
LeastSquaresResultWithR2 leastSquaresResultWithR2 = new LeastSquaresResultWithR2();
double[] xSeries = new double[observations.Length];
double[] xMinusXMean = new double[observations.Length];
double[] yMinusYMean = new double[observations.Length];
double[] meanProduct = new double[observations.Length];
double[] xMinusXMeanSquared = new double[observations.Length];
double[] leastSquares = new double[observations.Length];
double xMean = double.NaN;
double yMean = double.NaN;
double slope = double.NaN;
double yIntercept = double.NaN;
for (int index = 0; index < xSeries.Length; index++) xSeries[index] = index + 1;
xMean = Numerics.Mean(ref xSeries);
yMean = Numerics.Mean(ref observations);
for (int index = 0; index < observations.Length; index++)
{
xMinusXMean[index] = xSeries[index] - xMean;
yMinusYMean[index] = observations[index] - yMean;
meanProduct[index] = xMinusXMean[index] * yMinusYMean[index];
xMinusXMeanSquared[index] = xMinusXMean[index] * xMinusXMean[index];
}
slope = Numerics.Sum(ref meanProduct) / Numerics.Sum(ref xMinusXMeanSquared);
yIntercept = Numerics.YIntercept(xMean, yMean, slope);
for (int index = 0; index < leastSquares.Length; index++) leastSquares[index] = slope * xSeries[index] + yIntercept;
leastSquaresResultWithR2.LeastSquares = leastSquares;
leastSquaresResultWithR2.YIntercept = yIntercept;
leastSquaresResultWithR2.XIntercept = xMean;
leastSquaresResultWithR2.Slope = slope;
// calculate the R2
double[] estimated = new double[observations.Length];
double[] estimatedLessMeanSquared = new double[observations.Length];
double sumOfEstimatedLessMeanSquared = 0.00;
double sumofsquares = 0.00;
foreach (double observation in observations) sumofsquares += Math.Pow(observation - yMean, 2);
for (int index = 0; index < observations.Length; index++) estimated[index] = yIntercept + (slope * (index + 1));
for (int index = 0; index < observations.Length; index++) estimatedLessMeanSquared[index] = Math.Pow(estimated[index] - yMean, 2);
foreach (double value in estimatedLessMeanSquared) sumOfEstimatedLessMeanSquared += value;
leastSquaresResultWithR2.RSquared = sumOfEstimatedLessMeanSquared / sumofsquares;
return leastSquaresResultWithR2;
}
catch (Exception exception)
{
MDTrace.WriteLine(LogLevel.DEBUG, exception.ToString());
return null;
}
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,114 @@
using System;
using System.Collections;
namespace MarketData.Numerical
{
// The column is the key, the row is the value.
// For Time series elements put the date in the column and the value in the row
public class Element
{
private double row;
private double column;
public Element()
{
}
public Element(double column, double row)
{
this.column = column;
this.row = row;
}
public double Row
{
get { return row; }
set { row = value; }
}
public double Column
{
get { return column; }
set { column = value; }
}
}
public class CatmullRom
{
private CatmullRom()
{
}
public static bool PerformSpline(Element[] sourcePairs, Element[] destPairs)
{
double a0, a1, a2, a3;
double dx, dx1, dx2;
double dy, dy1, dy2;
double endPointOne;
double endPointTwo;
double resamplingPos;
double xPoint;
int clampOne, clampTwo;
int direction;
int destSize = destPairs.Length;
int sourceSize = sourcePairs.Length;
int inputIndex, index;
a0 = a1 = a2 = a3 = endPointOne = 0;
if (sourceSize < 2 || destSize < 1) return false;
if (((Element)sourcePairs[0]).Column < ((Element)sourcePairs[1]).Column)
{
if (((Element)destPairs[0]).Column < ((Element)sourcePairs[0]).Column ||
((Element)destPairs[destSize - 1]).Column > ((Element)sourcePairs[sourceSize - 1]).Column)
direction = 0;
else direction = 1;
}
else
{
if (((Element)destPairs[0]).Column > ((Element)sourcePairs[0]).Column ||
((Element)destPairs[destSize - 1]).Column < ((Element)sourcePairs[sourceSize - 1]).Column)
direction = 0;
else direction = -1;
}
if (0 == direction) return false;
if (1 == direction) endPointTwo = ((Element)destPairs[0]).Column - 1;
else endPointTwo = ((Element)destPairs[0]).Column + 1;
for (index = 0; index < destSize; index++)
{
resamplingPos = ((Element)destPairs[index]).Column;
if ((1 == direction && resamplingPos > endPointTwo) ||
(-1 == direction && resamplingPos < endPointTwo))
{
for (inputIndex = 0; inputIndex < sourceSize && resamplingPos > ((Element)sourcePairs[inputIndex]).Column; inputIndex++) ;
if (resamplingPos < ((Element)sourcePairs[inputIndex]).Column) inputIndex--;
if (inputIndex < 0) inputIndex = 0;
else if (inputIndex == sourceSize-1) inputIndex--;
endPointOne = ((Element)sourcePairs[inputIndex]).Column;
endPointTwo = ((Element)sourcePairs[inputIndex + 1]).Column;
clampOne = Math.Max(inputIndex - 1, 0);
clampTwo = Math.Min(inputIndex + 2, sourceSize - 1);
double clampOneValue = ((Element)sourcePairs[clampOne]).Column;
double clampTwoValue = ((Element)sourcePairs[clampTwo]).Column;
dx = 1.0 / ((endPointTwo - endPointOne)==0?1:(endPointTwo-endPointOne));
dx1 = 1.0 / ((endPointTwo - clampOneValue) == 0 ? 1 : (endPointTwo - clampOneValue));
dx2 = 1.0 / (clampTwoValue-endPointOne == 0 ? 1 : (clampTwoValue - endPointOne));
dy = (((Element)sourcePairs[inputIndex + 1]).Row - ((Element)sourcePairs[inputIndex]).Row) * dx;
dy1 = (((Element)sourcePairs[inputIndex + 1]).Row - ((Element)sourcePairs[clampOne]).Row) * dx1;
dy2 = (((Element)sourcePairs[clampTwo]).Row - ((Element)sourcePairs[inputIndex]).Row) * dx2;
a0 = ((Element)sourcePairs[inputIndex]).Row;
a1 = dy1;
a2 = dx * (3 * dy - 2 * dy1 - dy2);
a3 = dx * dx * (-2 * dy + dy1 + dy2);
}
xPoint = resamplingPos - endPointOne;
((Element)destPairs[index]).Row = ((a3 * xPoint + a2) * xPoint + a1) * xPoint + a0;
}
return true;
}
public static Element[] CreateSplineSourceElements(double[] columns, double[] rows)
{
Element[] elements = new Element[columns.Length];
if (columns.Length != rows.Length) return null;
for (int index = 0; index < columns.Length; index++)
{
elements[index] = new Element(columns[index], rows[index]);
}
return elements;
}
}
} // namespace