using System;
using System.Threading;
using System.Collections;
using System.Linq;
using System.Collections.Generic;
using MarketData.MarketDataModel;
using MarketData.Utils;
// Filename: Numerics.cs
// Author:Sean Kessler / Werner Stanzl
// Date:07/2003
namespace MarketData.Numerical
{
public class Numerics
{
public enum CorrelationType{PerfectDownhill,StrongDownhill,ModerateDownhill,WeakDownhill,NoLinearRelationship,WeakUphill,ModerateUphill,StrongUphill,PerfectUphill};
///
/// Discount - Discounts the given number by a percentage. For example to discount $600.00 by 20% call Discount(600.00,.20)
///
///
///
///
public static double Discount(double number, double discountPercentDecimal)
{
return number * (1.00 - discountPercentDecimal);
}
// (i.e.) 2.789 will round to 2.79
public static double Round(double x)
{
return Math.Round(x, 2, MidpointRounding.AwayFromZero);
}
public static void ZeroForNaNOrInfinity(ref float[] floatArray)
{
for(int index=0;index (deviations*-1)*stddev select value).ToArray();
return newObservations;
}
public static LeastSquaresResult LeastSquares(double[] observations)
{
return LeastSquaresHelper.CalculateLeastSquares(observations);
}
public static LeastSquaresResultWithR2 LeastSquaresWithR2(double[] observations)
{
return LeastSquaresHelper.CalculateLeastSquaresWithR2(observations);
}
public static double RSquared(double[] observations)
{
try
{
double[] estimated = new double[observations.Length];
double[] estimatedLessMeanSquared = new double[observations.Length];
double sumOfEstimatedLessMeanSquared = 0.00;
double rSquared = 0.00;
LeastSquaresResult leastSquaresResult = null;
double mean = Numerics.Mean(ref observations);
double sumofsquares = 0.00;
foreach (double observation in observations) sumofsquares += Math.Pow(observation - mean, 2);
leastSquaresResult = LeastSquares(observations);
double slope = leastSquaresResult.Slope * -1.00; // LeastSquares generator reverses the slope. Because prices fed to it are in reverse order
double yIntercept = leastSquaresResult.YIntercept;
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] - mean, 2);
foreach (double value in estimatedLessMeanSquared) sumOfEstimatedLessMeanSquared += value;
rSquared = sumOfEstimatedLessMeanSquared / sumofsquares;
return rSquared;
}
catch (Exception)
{
return double.NaN;
}
}
/// YIntercept - Calculates slope of values.
/// YIntercept
public static double YIntercept(double xMean,double yMean,double slope)
{
return yMean-(slope*xMean);
}
public static double Slope(ref double[] x,ref double[] y)
{
double sumxy=0.00;
double sumx=0.00;
double sumy=0.00;
double sumx2=0.00;
if(x.Length!=y.Length)return double.NaN;
for(int index=0;indexSlope - Calculates slope of values.
/// y-values x-values are assumed to be sequential
/// Slope
public static float Slope(float[] y)
{
float sum1 = 0.00F;
float sum2 = 0.00F;
float[] x=new float[y.Length];
for (int index = 0; index < y.Length; index++) x[index] = index + 1;
float averageY = Mean(ref y);
float averageX = Mean(ref x);
for (int index = 0; index < y.Length; index++)
{
float currX = x[index];
sum1+=(currX-averageX)*(y[index]-averageY);
sum2 += (float)Math.Pow(currX-averageX,2);
}
if (0 == sum2) return float.NaN;
return sum1 / sum2;
}
/// Slope - Calculates slope of values.
/// y-values x-values are assumed to be sequential
/// Slope
public static double Slope(ref double[] y)
{
double sum1 = 0.00F;
double sum2 = 0.00F;
double[] x=new double[y.Length];
for (int index = 0; index < y.Length; index++) x[index] = index + 1;
double averageY = Mean(ref y);
double averageX = Mean(ref x);
for (int index = 0; index < y.Length; index++)
{
double currX = x[index];
sum1+=(currX-averageX)*(y[index]-averageY);
sum2 += (float)Math.Pow(currX-averageX,2);
}
if (0 == sum2) return float.NaN;
return sum1 / sum2;
}
/// Slope - Calculates slope of values.
/// y-values x-values are assumed to be sequential
/// Slope
public static double Slope(double[] y)
{
double sum1 = 0.00F;
double sum2 = 0.00F;
double[] x = new double[y.Length];
for (int index = 0; index < y.Length; index++) x[index] = index + 1;
double averageY = Mean(ref y);
double averageX = Mean(ref x);
for (int index = 0; index < y.Length; index++)
{
double currX = x[index];
sum1 += (currX - averageX) * (y[index] - averageY);
sum2 += (float)Math.Pow(currX - averageX, 2);
}
if (0 == sum2) return float.NaN;
return sum1 / sum2;
}
/// Median - Calculates median of values.
/// values
/// Median
public static double Median(ref double[] values)
{
int length=values.Length;
if (length == 0)throw new Exception("Numerics::cannot calculate median of an empty array");
if (length == 1 )return values[0];
double [] sorted = new double[length];
Array.Copy(values, 0, sorted, 0, length);
Array.Sort(sorted);
if( (length%2) == 0 ) return (sorted[length/2]+sorted[length/2-1])/2;
return sorted[(length-1)/2];
}
/// Floor - Calculates floor of values.
/// values
/// floor
public static void Floor(ref double[] values)
{
for (int i=0; i< values.Length; i++)
{
values[i] = Math.Floor(values[i]);
}
}
/// Percentile - Calculates percentile of values.
/// values
/// Percentile
public static float Percentile(int perc,ref float[] values)
{
if(values.Length<5)return float.NaN;
int index;
Array.Sort(values);
index=(int)Math.Floor(perc*(values.Length)/100.00F)-1;
if(index<0)index=0;
else if(index>=values.Length)index=values.Length-1;
return values[index];
}
/// Min - Calculates minimum of values.
/// values
/// minimum
public static float Min(ref float[] values)
{
if(0==values.Length)return 0;
float min=values[0];
for(int index=1;indexMin - Calculates minimum of values.
/// values
/// minimum
public static double Min(ref double[] values)
{
if(0==values.Length)return 0;
double min=values[0];
for(int index=1;indexMax - Calculates maximum of values.
/// values
/// maximum
public static float Max(ref float[] values)
{
if(0==values.Length)return 0;
float max=values[0];
for(int index=1;indexmax)max=values[index];
}
return max;
}
/// Max - Calculates maximum of values.
/// values
/// maximum
public static double Max(ref double[] values)
{
double max=values[0];
for(int index=1;indexmax)max=values[index];
}
return max;
}
/// Mean - Calculates mean of values.
/// values
/// Mean
public static float Mean(ref float[] values)
{
if (null == values) return float.NaN;
int length=values.Length;
float mean=0;
if(0==length)return float.NaN;
for(int index=0;indexMean - Calculates mean of values.
/// values
/// Mean
public static double Mean(ref double[] values)
{
if (null == values) return float.NaN;
int length=values.Length;
double mean=0;
if(0==values.Length)return double.NaN;
for(int index=0;indexMeanAbs - Calculates mean of abs(values).
/// values
/// Mean
public static float MeanAbs(ref float[] values)
{
int length=values.Length;
float mean=0;
if(0==length)return mean;
for(int index=0;indexGeometricMean - Calculates mean of values.
/// values
/// Mean
public static float GeometricMean(ref float[] values)
{
float geometricMean=1.00F;
int length=values.Length;
if(0==length)return geometricMean;
for(int index=0;indexSum - Calculates Sum.
/// float array x.
/// float Sum
public static float Sum(ref float[] x)
{
float sum=0;
int length=x.Length;
if(0==length)return sum;
for(int index=0;indexSum - Calculates Sum.
/// double array x.
/// double Sum
public static double Sum(ref double[] x)
{
double sum=0;
int length=x.Length;
if(0==length)return sum;
for(int index=0;indexAnnualizedVolatility - Calculates annualized volatility of values. can be any number of period
/// values
/// volatility
public static float AnnualizedVolatility(ref float[] values)
{
return (float)(Math.Sqrt(252.00)*StdDev(ref values)); // 252 is average number of trading days in a year
}
/// AnnualizedVolatility - Calculates annualized volatility of values. can be any number of periods
/// values
/// volatility
public static double AnnualizedVolatility(ref double[] values)
{
return Math.Sqrt(252)*StdDev(ref values); // 252 is average number of trading days in a year
}
/// Volatility - Calculates volatility of values.
/// values
/// volatility
public static float Volatility(ref float[] values)
{
return StdDev(ref values);
}
/// Volatility - Calculates volatility of values.
/// values
/// volatility
public static double Volatility(ref double[] values)
{
return StdDev(ref values);
}
/// Standardize - Standardizes the input.
/// values
/// volatility
public static float[] Standardize(ref float[] values)
{
float[] returnData=new float[values.Length];
float valuesMean=Mean(ref values);
float valuesStd=Volatility(ref values);
if(0==valuesStd)return values;
for(int index=0;indexDownStd - Returns downside standard deviation of values.
/// values
/// downside standard deviation
public static float DownStd(ref float[] values)
{
float average;
float downStd=0;
if(1>=values.Length)return downStd;
average=Mean(ref values);
foreach(float value in values)
{
if(valueBattingAverage - Returns batting average of values.
/// values
/// batting average
public static float BattingAverage(ref float[] values)
{
float battingAverage=0;
if(0==values.Length)return float.NaN;
foreach(float value in values)
{
if(value>0)battingAverage++;
}
return battingAverage/values.Length;
}
/// AverageReturnWithSpline -This is a collection of prices ordered highest date first.
/// values
/// AverageReturnWithSpline
public static double AverageReturnWithSpline(TimeSeriesCollection timeSeriesCollection)
{
List sourceElements = new List();
List destElements = null;
List values = new List();
if (null == timeSeriesCollection || 0 == timeSeriesCollection.Count) return double.NaN;
for (int index = timeSeriesCollection.Count-1; index >=0; index--)
{
TimeSeriesElement timeSeriesElement=timeSeriesCollection[index];
sourceElements.Add(new Element(Utility.DateToLong(timeSeriesElement.AsOf), timeSeriesElement.Value));
}
DateTime startDate = timeSeriesCollection[timeSeriesCollection.Count - 1].AsOf;
DateTime endDate = timeSeriesCollection[0].AsOf;
DateTime valueDate = startDate;
while (valueDate <= endDate)
{
destElements = new List();
destElements.Add(new Element(Utility.DateToLong(valueDate), 0));
CatmullRom.PerformSpline((Element[])sourceElements.ToArray(), (Element[])destElements.ToArray());
double value = destElements[0].Row;
values.Add((float)value);
valueDate = new DateTime(valueDate.Year+1,valueDate.Month,valueDate.Day);
}
List inverseValues = new List();
for (int index = values.Count - 1; index >= 0; index--)
{
inverseValues.Add(values[index]);
}
float[] fvalues = inverseValues.ToArray();
double averageReturn = Numerics.AverageReturn(ref fvalues);
return averageReturn;
}
/// AverageReturnWithSpline -This is a collection of prices ordered highest date first.
/// values
/// AverageReturnWithSpline
public static double AverageReturnWithSpline(TimeSeriesCollection timeSeriesCollection,ReturnItems returnItems)
{
List sourceElements = new List();
List destElements = null;
returnItems.Clear();
if (null == timeSeriesCollection || 0 == timeSeriesCollection.Count) return double.NaN;
for (int index = timeSeriesCollection.Count - 1; index >= 0; index--)
{
TimeSeriesElement timeSeriesElement = timeSeriesCollection[index];
sourceElements.Add(new Element(Utility.DateToLong(timeSeriesElement.AsOf), timeSeriesElement.Value));
}
DateTime startDate = timeSeriesCollection[timeSeriesCollection.Count - 1].AsOf;
DateTime endDate = timeSeriesCollection[0].AsOf;
DateTime valueDate = startDate;
while (valueDate <= endDate)
{
destElements = new List();
destElements.Add(new Element(Utility.DateToLong(valueDate), 0));
CatmullRom.PerformSpline((Element[])sourceElements.ToArray(), (Element[])destElements.ToArray());
double value = destElements[0].Row;
returnItems.Add(new ReturnItem(valueDate,value));
valueDate = new DateTime(valueDate.Year + 1, valueDate.Month, valueDate.Day);
}
returnItems.CalculateReturns();
float[] values = null;
values = returnItems.ToFloat();
double averageReturn = Numerics.Mean(ref values);
return averageReturn;
}
/// AverageReturn -Assumes this is a collection of prices ordered highest date first.
/// timeSeriesCollection,if exclusionThreshold is provided then return values>than threshold will be thrown away
/// AverageReturn
public static double AverageReturn(TimeSeriesCollection timeSeriesCollection)
{
if(null==timeSeriesCollection || 0==timeSeriesCollection.Count)return double.NaN;
float[] values = timeSeriesCollection.ToFloat();
return AverageReturn(ref values);
}
/// AverageReturn -Assumes this is a collection of prices ordered highest date first.
/// values,if exclusionThreshold is provided then return values>than threshold will be thrown away
/// AverageReturn
public static double AverageReturn(ref float[] values)
{
try
{
if (0 == values.Length) return double.NaN;
List returns = new List();
for (int index = 0; index < values.Length - 1; index++)
{
float current = values[index];
float prev = values[index + 1];
if (0 == prev) returns.Add(0.00);
else
{
double currentReturn=double.NaN;
if (prev == 0.00) currentReturn = 0;
else currentReturn = (float)((current - prev) / Math.Abs(prev));
returns.Add(currentReturn);
}
}
double[] returnsArray = returns.ToArray();
return Mean(ref returnsArray);
}
catch (Exception)
{
return double.NaN;
}
}
/// AverageReturnTop -Assumes this is a collection of prices ordered highest date first.
/// values
/// AverageReturnTop - Calculates return of top n elements, count must be greater than 1
public static double AverageReturnTop(ref float[] values,int top)
{
try
{
if (0 == values.Length || 1==values.Length || values.LengthPeriodicReturn -Assumes this is a collection of daily prices ordered highest date first.
/// values
/// PeriodicReturn - Calculates return of elements
public static double AnnualReturn(ref float[] values)
{
double periodicReturn = double.NaN;
double p0 = values[values.Length - 1];
double p1 = values[0];
double returnValue=(p1-p0)/Math.Abs(p0);
double n = values.Length / 365;
periodicReturn = Math.Pow(1 + returnValue, 1 / n) - 1;
return periodicReturn;
}
/// PowerHit - Returns power hitting of vector x.
/// values
/// power hit
public static float PowerHitting(ref float[] values)
{
float win=0;
long winCount=0;
float lose=0;
long loseCount=0;
if(0==values.Length)return float.NaN;
foreach(float value in values)
{
if(value>0)
{
win+=value;
winCount++;
}
else if(value<0)
{
lose+=(-value);
loseCount++;
}
}
return (loseCount*win/(winCount*lose));
}
/// Product - Returns sum of products.
/// values
/// product
public static float Product(ref float[] values)
{
float product=1;
if(0==values.Length)return 0;
foreach(float value in values)
{
product*=value;
}
return product;
}
/// CumProduct - Returns cumulative product of values.
/// values
/// cumulative product
public static float[] CumProduct(ref float[] values)
{
if(0==values.Length)return new float[0];
float[] cumProduct=new float[values.Length];
cumProduct[0]=values[0];
for(int index=1;indexStdDev - Calculates standard deviation of values.
/// values
/// standard deviation
public static float StdDev(ref float[] values)
{
long length = 0;// values.Length;
float value;
float sum=0;
float sqr=0;
if(null==values || 1>=(length=values.Length))return float.NaN;
for(int index=0;indexStdDev - Calculates standard deviation of values.
/// values
/// standard deviation
public static double StdDev(ref double[] values)
{
long length = 0; ;
double value;
double sum=0;
double sqr=0;
if(null==values || 1>=(length=values.Length))return float.NaN;
for(int index=0;indexStDevWithDecay - Calculates StDev with a Decay.
/// float array x.
/// float StDev
public static float StdDevWithDecay(ref float[] x)
{
if(1>=x.Length)return 0;
return ApplyDecay(ref x);
}
/// Covariance - Calculates covariance of x and y.
/// vector x
/// vector y.
/// covariance
///In probability theory and statistics, covariance is a measure of the joint variability of two random variables.
///[1] If the greater values of one variable mainly correspond with the greater values of the other variable,
///and the same holds for the lesser values, (i.e., the variables tend to show similar behavior),
///the covariance is positive.[2] In the opposite case, when the greater values of one variable mainly
///correspond to the lesser values of the other, (i.e., the variables tend to show opposite behavior),
///the covariance is negative. The sign of the covariance therefore shows the tendency in the linear
///relationship between the variables. The magnitude of the covariance is not easy to interpret because
///it is not normalized and hence depends on the magnitudes of the variables. The normalized version of the
///covariance, the correlation coefficient, however, shows by its magnitude the strength of the linear relation.
public static float Covariance(ref float[] x,ref float[] y)
{
float meanx;
float meany;
int length;
float product;
if(0==x.Length && 0==y.Length)return 0;
if((length=x.Length)!=y.Length)return 0;
product=0;
meanx=Mean(ref x);
meany=Mean(ref y);
for(int index=0;indexCovariance - Calculates covariance of x and y.
/// vector x
/// vector y.
/// covariance
public static double Covariance(ref double[] x,ref double[] y)
{
double meanx;
double meany;
int length;
double product;
if(0==x.Length && 0==y.Length)return 0;
if((length=x.Length)!=y.Length)return 0;
product=0;
meanx=Mean(ref x);
meany=Mean(ref y);
for(int index=0;indexVariance - Calculates variance of x (population).
/// vector x
/// variance
public static float Variance(ref float[] xarray)
{
return Covariance(ref xarray, ref xarray);
}
/// Variance - Calculates variance of x (population).
/// vector x
/// variance
public static double Variance(ref double[] xarray)
{
return Covariance(ref xarray, ref xarray);
}
/// Skewness - Calculates skewness of x (population).
/// vector x
/// skewness
public static float Skewness(ref float[] x)
{
float meanx;
float sd_x;
int length;
float product;
if(0==x.Length)return float.NaN;
product=0;
meanx=Mean(ref x);
sd_x=StdDev(ref x);
if(float.NaN==sd_x)return float.NaN;
length=x.Length;
for(int index=0;indexKurtosis - Calculates kurtosis of x.
/// vector x
/// kurtosis
public static float Kurtosis(ref float[] x)
{
float meanx;
float sd_x;
int length;
float product;
if(0==x.Length)return float.NaN;
product=0;
meanx=Mean(ref x);
sd_x=StdDev(ref x);
if(float.NaN==sd_x) return float.NaN;
length=x.Length;
for(int index=0;indexRemoveDuplicates
/// Removes duplicates from x and y and stores the rest of the values in result.
/// This is a helper function for KStest.
/// vector x
/// vector y
/// ArrayList result
/// x without duplicates
private static float[] RemoveDuplicates(float[] x,float[] y,ArrayList result)
{
ArrayList list= new ArrayList();
int newLength=0;
for(int i=0; i Do not reject the null hypothesis at 0.05 significance level.
H = 1 => Reject the null hypothesis at 0.05 significance level.
(2) pValue: the asymptotic P-value P.
(3) KSstat: the K-S test statistic, T = max|S(x) - CDF|, where S(x) is the
empirical c.d.f. estimated from the sample vector X and CDF is the
standard normal.
(4) criticalValue: the critical value of the test, on which the decision
to reject the null hypothesis is based.
NaN's are removed and a blank is returned if the length of the input array is 0.
The implementation of this function is based on the Matlab function kstest.m
*/
public static KSTest KSTest(ref float[]x)
{
float alpha=0.05f;
KSTest blank=new KSTest(0,Double.NaN,Double.NaN,Double.NaN);
ArrayList xNoNaNs=new ArrayList();
for(int i=0; icriticalValue?1:0;
double lambda=Math.Max((Math.Sqrt(n)+0.12+0.11/Math.Sqrt(n))*KSstatistic,0);
int[] j=new int[101];
double sumP=0;
for(int i=0; i1)pValue=1;
KSTest ret=new KSTest(H,pValue,KSstatistic,criticalValue);
return ret;
}
/* ERFC Complementary error function for each element of x.
* The function is defined as:
* erfc(x) = 2/sqrt(pi) * integral from x to inf of exp(-t^2) dt.
* = 1 - erf(x).
*
* This is a helper function to KStest and is based on the Matlab function erfc.m
* /
*/
private static double[] ERFCore(double[] x, int jint)
{
double[] result = new double[x.Length];
for(int i=0; i0)
{
double[] a=new double[] {3.16112374387056560e00, 1.13864154151050156e02, 3.77485237685302021e02, 3.20937758913846947e03,1.85777706184603153e-1};
double[] b=new double[] {2.36012909523441209e01, 2.44024637934444173e02, 1.28261652607737228e03, 2.84423683343917062e03};
double[] y=new double[k.Length];
double[] z=new double[k.Length];
double[] xnum=new double[k.Length];
double[] xden=new double[k.Length];
for(int i=0; ixbreak && Math.Abs(x[i])<=4.0)
{
kList1.Add(i);
newLength1++;
}
int[] k1=new int[newLength1];
kList1.CopyTo(k1);
if(k1.Length>0)
{
double[] c=new double[] {5.64188496988670089e-1, 8.88314979438837594e00, 6.61191906371416295e01, 2.98635138197400131e02, 8.81952221241769090e02, 1.71204761263407058e03, 2.05107837782607147e03, 1.23033935479799725e03, 2.15311535474403846e-8};
double[] d=new double[] {1.57449261107098347e01, 1.17693950891312499e02, 5.37181101862009858e02, 1.62138957456669019e03, 3.29079923573345963e03, 4.36261909014324716e03, 3.43936767414372164e03, 1.23033935480374942e03};
double[] y=new double[k1.Length];
double[] z=new double[k1.Length];
double[] xnum=new double[k1.Length];
double[] xden=new double[k1.Length];
double[] del=new double[k1.Length];
for(int i=0; i0?Math.Floor(y[i]*16)/16:Math.Ceiling(y[i]*16)/16;
del[i]=(y[i]-z[i])*(y[i]+z[i]);
result[k1[i]]=Math.Exp(z[i]*z[i]*-1)*Math.Exp(del[i]*-1)*result[k1[i]];
}
}
ArrayList kList2 = new ArrayList();
int newLength2=0;
for(int i=0; i4.0)
{
kList2.Add(i);
newLength2++;
}
int[] k2=new int[newLength2];
kList2.CopyTo(k2);
if(k2.Length>0)
{
double[] p=new double[] {3.05326634961232344e-1, 3.60344899949804439e-1, 1.25781726111229246e-1, 1.60837851487422766e-2, 6.58749161529837803e-4, 1.63153871373020978e-2};
double[] q=new double[] {2.56852019228982242e00, 1.87295284992346047e00, 5.27905102951428412e-1, 6.05183413124413191e-2, 2.33520497626869185e-3};
double[] y=new double[k2.Length];
double[] z=new double[k2.Length];
double[] xnum=new double[k2.Length];
double[] xden=new double[k2.Length];
double[] del=new double[k2.Length];
for(int i=0; i0?Math.Floor(y[i]*16)/16:Math.Ceiling(y[i]*16)/16;
del[i]=(y[i]-z[i])*(y[i]+z[i]);
result[k2[i]]=Math.Exp(z[i]*z[i]*-1)*Math.Exp(del[i]*-1)*result[k2[i]];
}
ArrayList kList3 = new ArrayList();
int newLength3=0;
for(int i=0; iCorrelation - Calculates correlation coefficient from input vectors.
/// vector x
/// vector y.
/// correlation coefficient
/// Interpretation of results:
/// -1 : A perfect downhill (negative) linear relationship
/// -0.70 : A strong downhill (negative) linear relationship
/// �0.50. A moderate downhill (negative) relationship
/// �0.30. A weak downhill (negative) linear relationship
/// 0. No linear relationship
/// +0.30. A weak uphill (positive) linear relationship
/// +0.50. A moderate uphill (positive) relationship
/// +0.70. A strong uphill (positive) linear relationship
/// Exactly +1. A perfect uphill (positive) linear relationship
///In probability theory and statistics, covariance is a measure of the joint variability of two random variables.
///[1] If the greater values of one variable mainly correspond with the greater values of the other variable,
///and the same holds for the lesser values, (i.e., the variables tend to show similar behavior),
///the covariance is positive.[2] In the opposite case, when the greater values of one variable mainly
///correspond to the lesser values of the other, (i.e., the variables tend to show opposite behavior),
///the covariance is negative. The sign of the covariance therefore shows the tendency in the linear
///relationship between the variables. The magnitude of the covariance is not easy to interpret because
///it is not normalized and hence depends on the magnitudes of the variables. The normalized version of the
///covariance, the correlation coefficient, however, shows by its magnitude the strength of the linear relation.
public static float Correlation(ref float[] x, ref float[] y)
{
float sd_x = StdDev(ref x);
float sd_y = StdDev(ref y);
return Covariance(ref x, ref y)*x.Length/((sd_x * sd_y)*(x.Length-1));
}
public static Numerics.CorrelationType GetCorrelationType(float correlationCovarianeResult)
{
if(correlationCovarianeResult>=1)return CorrelationType.PerfectUphill;
if(correlationCovarianeResult>=.70)return CorrelationType.StrongUphill;
if(correlationCovarianeResult>=.50)return CorrelationType.ModerateUphill;
if(correlationCovarianeResult>=.50)return CorrelationType.ModerateUphill;
if(correlationCovarianeResult>=.30)return CorrelationType.WeakUphill;
if(correlationCovarianeResult<=-1)return CorrelationType.PerfectDownhill;
if(correlationCovarianeResult<=-.70)return CorrelationType.StrongDownhill;
if(correlationCovarianeResult<=-.50)return CorrelationType.ModerateDownhill;
if(correlationCovarianeResult<=-.30)return CorrelationType.WeakDownhill;
return CorrelationType.NoLinearRelationship;
}
/// Correlation - Calculates correlation matrix from input matrix.
/// source matrix
/// number of columns in source.
/// number of columns in source.
/// tranposed array
public static float[,] Correlation(ref float[,] matrix,int rows,int cols)
{
float[,] result=new float[cols,cols];
float[] x=new float[rows];
float[] y=new float[rows];
int col=0;
int row;
for(int srcIndex=0;srcIndexCreateCorrelationMatrix - Creates correlation matrix from input matrix.
/// the input matrix.
/// indicates whether to transpose the input matrix.
/// float[,] correlation matrix
public static float[,] CreateCorrelationMatrix(ref float[,] values,bool transpose)
{
int columns=values.GetLength(1);
int rows=values.GetLength(0);
if(!transpose)return Correlation(ref values,rows,columns);
float[,] transposeMatrix=Transpose(ref values,ref rows,ref columns);
return Correlation(ref transposeMatrix,rows,columns);
}
/// Transpose - Convert horizontal range of cells to vertical.
/// number of rows in source
/// number of columns in source.
/// the source matrix.
/// tranposed array
public static float[] Transpose(ref int srcRows,ref int srcCols,ref float[] source)
{
float[] result=new float[srcRows*srcCols];
long dstRow=0;
long dstCol=0;
for(int srcRow=0;srcRowTranspose - Convert horizontal range of cells to vertical.
/// number of rows in source
/// number of columns in source.
/// the source matrix.
/// tranposed array
public static float[,] Transpose(ref float[,] source,ref int srcRows,ref int srcCols)
{
float[,] result=new float[srcCols,srcRows];
long dstRow=0;
long dstCol=0;
for(int srcRow=0;srcRowTransposeXAY - Transpose(x)*A*y.
/// row vector
/// matrix.
/// column vector.
/// number of elements in each dimension.
/// tranposed array
public static float TransposeXAY(ref float[] x,ref float[,] a,ref float[] y,int elements)
{
float[] acol=new float[elements];
float[] intermediate=new float[elements];
for(int col=0;colMMult - Performs matrix multiplication of vectors.
/// the row vector
/// the column vector
/// Product
public static float MMult(ref float[] rowVector,ref float[] colVector)
{
float product=0;
int length;
if((length=rowVector.Length)!=colVector.Length)return product;
for(int index=0;indexGetXY - Get vertical columns from matrix[,] into x and y.
/// column from matrix to copy to x array
/// column from matrix to copy to y array
/// source matrix
/// destination array x
/// destination array y
/// None
private static void GetXY(int xColumn,int yColumn,ref float[,] matrix,ref float[] x,ref float[] y,int rows)
{
for(int row=0;rowGetX - Get vertical column from matrix[,] into x.
/// column from matrix to copy
/// the source matrix.
/// the destination vector.
/// number of rows in matrix.
/// None
private static void GetX(int xColumn,ref float[,] matrix,ref float[] x,int rows)
{
for(int row=0;rowBeta - Calculates Beta.
/// ticker returns.
/// sector returns.
/// Beta value
/// A beta of 1.00 indicates that the security's price will move with the market
/// A beta of less than 1.00 indicates that the security will be less volatile than the market
/// A beta of more than 1.00 indicates that the security will be more volatile than the market
/// The revised code (i.e.) Beta=Covariance(x,y)/Variance(x) was taken from Investopedia
public static double Beta(ref double[] assetReturns, ref double[] benchmarkReturns)
{
double variance = Variance(ref benchmarkReturns);
if(0.00 == variance)return double.NaN;
return Covariance(ref assetReturns, ref benchmarkReturns) / variance;
}
/// ApplyDecay - Apply exponential weighting.
/// the samples to weight.
/// The weighted standard deviation
private static float ApplyDecay(ref float[] samples)
{
int numSamples=samples.Length;
Decay decay=new Decay(numSamples);
float average=0;
float weightedVariance=0;
float weightedError=0;
float stddev=0;
float error=0;
for(int item=0;itemTStatistic - Calculate TStatistic.
/// The average for the samples.
/// Standard deviation of the samples.
/// The number of samples.
/// TStatistic
public static float TStatistic(float average,float stddev,int samples)
{
if(0==samples||0==stddev)return float.NaN;
return (float)((average/stddev)*Math.Sqrt(samples));
}
/// TStatistic - Calculate TStatistic.
/// Least squares estimates.
/// Standard errors.
/// TStatistic
public static double[] TStatistic(ref double[] leastSquaresEstimates,ref double[] standardErrors)
{
double[] tStats;
int length;
if((length=leastSquaresEstimates.Length)!=standardErrors.Length)return new double[0];
tStats=new double[length];
for(int index=0;index maxPrice) maxPrice = prices[i];
else if (prices[i] < maxPrice) maxDd = Math.Min(maxDd, prices[i] / maxPrice - 1);
}
return maxDd;
}
// a float version
public static float MaxDrawdown(float[] prices)
{
if (prices.Length <= 1) return 0;
float maxPrice = prices[0];
float maxDd = 0;
for (int i = 1; i < prices.Length; i++)
{
if (prices[i] > maxPrice) maxPrice = prices[i];
else if (prices[i] < maxPrice) maxDd = Math.Min(maxDd, prices[i] / maxPrice - 1);
}
return maxDd;
}
// float MaxUpside
public static float MaxUpside(float[] prices)
{
if (prices.Length <= 1) return 0;
float minPrice = prices[0];
float maxUpside = 0;
for (int i = 1; i < prices.Length; i++)
{
if (prices[i] < minPrice) minPrice = prices[i];
else if (prices[i] > minPrice) maxUpside = Math.Max(maxUpside, prices[i] / minPrice - 1);
}
return maxUpside;
}
}
}