Generate a random number in a Gaussian Range? - c#

I want to use a random number generator that creates random numbers in a gaussian range where I can define the median by myself. I already asked a similar question here and now I'm using this code:
class RandomGaussian
{
private static Random random = new Random();
private static bool haveNextNextGaussian;
private static double nextNextGaussian;
public static double gaussianInRange(double from, double mean, double to)
{
if (!(from < mean && mean < to))
throw new ArgumentOutOfRangeException();
int p = Convert.ToInt32(random.NextDouble() * 100);
double retval;
if (p < (mean * Math.Abs(from - to)))
{
double interval1 = (NextGaussian() * (mean - from));
retval = from + (float)(interval1);
}
else
{
double interval2 = (NextGaussian() * (to - mean));
retval = mean + (float)(interval2);
}
while (retval < from || retval > to)
{
if (retval < from)
retval = (from - retval) + from;
if (retval > to)
retval = to - (retval - to);
}
return retval;
}
private static double NextGaussian()
{
if (haveNextNextGaussian)
{
haveNextNextGaussian = false;
return nextNextGaussian;
}
else
{
double v1, v2, s;
do
{
v1 = 2 * random.NextDouble() - 1;
v2 = 2 * random.NextDouble() - 1;
s = v1 * v1 + v2 * v2;
} while (s >= 1 || s == 0);
double multiplier = Math.Sqrt(-2 * Math.Log(s) / s);
nextNextGaussian = v2 * multiplier;
haveNextNextGaussian = true;
return v1 * multiplier;
}
}
}
Then to verify the results I plotted them with gaussianInRange(0, 0.5, 1) for n=100000000
As one can see the median is really at 0.5 but there isn't really a curve visible. So what I'm doing wrong?
EDIT
What i want is something like this where I can set the highest probability by myself by passing a value.

The simplest way to draw normal deviates conditional on them being in a particular range is with rejection sampling:
do {
retval = NextGaussian() * stdev + mean;
} while (retval < from || to < retval);
The same sort of thing is used when you draw coordinates (v1, v2) in a circle in your unconditional normal generator.
Simply folding in values outside the range doesn't produce the same distribution.
Also, if you have a good implementation of the error function and its inverse, you can calculate the values directly using an inverse CDF. The CDF of a normal distribution is
F(retval) = (1 + erf((retval-mean) / (stdev*sqrt(2)))) / 2
The CDF of a censored distribution is
C(retval) = (F(retval) - F(from)) / (F(to) - F(from)), from ≤ x < to
To draw a random number using a CDF, you draw v from a uniform distribution on [0, 1] and solve C(retval) = v. This gives
double v = random.NextDouble();
double t1 = erf((from - mean) / (stdev*sqrt(2)));
t2 = erf((to - mean) / (stdev*sqrt(2)));
double retval = mean + stdev * sqrt(2) * erf_inv(t1*(1-v) + t2*v);
You can precalculate t1 and t2 for specific parameters. The advantage of this approach is that there is no rejection sampling, so you only need a single NextDouble() per draw. If the [from, to] interval is small this will be faster.
However, it sounds like you might want the binomial distribution instead.

I have similar methods in my Graph generator (had to modify it a bit):
Returns a random floating-point number using a generator function with a specific range:
private double NextFunctional(Func<double, double> func, double from, double to, double height, out double x)
{
double halfWidth = (to - from) / 2;
double distance = halfWidth + from;
x = this.rand.NextDouble() * 2 - 1;// -1 .. 1
double y = func(x);
x = halfWidth * x + distance;
y *= height;
return y;
}
Gaussian function:
private double Gauss(double x)
{
// Graph should look better with double-x scale.
x *= 2;
double σ = 1 / Math.Sqrt(2 * Math.PI);
double variance = Math.Pow(σ, 2);
double exp = -0.5 * Math.Pow(x, 2) / variance;
double y = 1 / Math.Sqrt(2 * Math.PI * variance) * Math.Pow(Math.E, exp);
return y;
}
A method that generates a graph using the random numbers:
private void PlotGraph(Graphics g, Pen p, double from, double to, double height)
{
for (int i = 0; i < 1000; i++)
{
double x;
double y = this.NextFunctional(this.Gauss, from, to, height, out x);
this.DrawPoint(g, p, x, y);
}
}
I would rather used a cosine function - it is much faster and pretty close to the gaussian function for your needs:
double x;
double y = this.NextFunctional(a => Math.Cos(a * Math.PI), from, to, height, out x);
The out double x parameter in the NextFunctional() method is there so you can easily test it on your graphs (I use an iterator in my method).

Related

Calculating floating point error bound

I have geometrical algorithms and im struggling with floating point inaccuracies.
For example, I'm calculating wether a point lies on the left/right/on a plane (C#):
const double Epsilon = 1e-10;
internal double ComputeDistance(Vector3D v)
{
Vector3D normal = Plane.Normal;
Vertex v0 = Plane.Origin;
double a = normal.X;
double b = normal.Y;
double c = normal.Z;
double d = -(a * v0.X + b * v0.Y + c * v0.Z);
return a * v.X + b * v.Y + c * v.Z + d;
}
internal string DistanceSign(Vector3D v)
{
var distance = ComputeDistance(v);
return (distance > Epsilon ? "left" : (distance < -Epsilon ? "right" : "on"));
}
As shown in the code, I use a fixed Epsilon value.
But I don't trust this fixed epsilon because I don't know the size of the floating point error. If the fp error is bigger than my epsilon interval, then my algorithm will fail.
How can I make it robust? I have searched on the internet but haven't found a solution so far. I have read "What Every Computer Scientist Should Know About Floating-Point Arithmetic", it describes why fp errors occur but not how to solve them practically.
Edit
Here is a shewchuk predicate that doesn't seem work:
double[] pa = {0, 0};
double[] pb = {2 * Double.Epsilon, 0};
double[] pc = { 0, Double.Epsilon };
Assert.IsTrue(GeometricPredicates.Orient2D(pa, pb, pc) > 0);
The assertion fails because Orient2D return 0. The code is here
Edit2
Shouldn't it be possible to calculate an error bound by using the machine epsilon? According to wikipedia, the machine epsilon is an upper bound due to rounding. For double, it is 2^−53. So as I take it, when I have an arithmetic calculation:
double x = y + z
then the maximum error should be 2^−53. Shouldn't this fact enable the possiblity to calculate an appropriate epsilon? So two rewrite my method:
double const Machine_Eps = 1.11022302462516E-16 // (2^-53)
double Epsilon = Machine_Eps;
internal double ComputeDistance(Vector3D v)
{
Vector3D normal = Plane.Normal;
Vertex v0 = Plane.Origin;
double a = normal.X;
double b = normal.Y;
double c = normal.Z;
// 3 multiplications + 2 additions = maximum of 5*Machine_Eps
double d = -(a * v0.X + b * v0.Y + c * v0.Z);
// 3 multiplications + 3 additions = maximum of 6*Machine_Eps
Epsilon = 11 * Machine_Eps;
return a * v.X + b * v.Y + c * v.Z + d;
}
internal string DistanceSign(Vector3D v)
{
var distance = ComputeDistance(v);
return (distance > Epsilon ? "left" : (distance < -Epsilon ? "right" : "on"));
}
Ok now you can tell me how wrong I am. :)

Bicubic Interpolation?

I looked through the internet, and in terms of Bicubic Interpolation, I can't find a simple equation for it. Wikipedia's page on the subject wasn't very helpful, so is there any easy method to learning how Bicubic Interpolation works and how to implement it? I'm using it to generate Perlin Noise, but using bilinear interpolation is way to choppy for my needs (I already tried it).
If anyone can point me in the right direction by either a good website or just an answer, I would greatly appreciate it. (I'm using C# by the way)
Using this (Thanks to Ahmet Kakıcı who found this), I figured out how to add Bicubic Interpolation. For those also looking for the answer, here is what I used:
private float CubicPolate( float v0, float v1, float v2, float v3, float fracy ) {
float A = (v3-v2)-(v0-v1);
float B = (v0-v1)-A;
float C = v2-v0;
float D = v1;
return A*Mathf.Pow(fracy,3)+B*Mathf.Pow(fracy,2)+C*fracy+D;
}
In order to get 2D Interpolation, I first got the x, then interpolated the y. Eg.
float x1 = CubicPolate( ndata[0,0], ndata[1,0], ndata[2,0], ndata[3,0], fracx );
float x2 = CubicPolate( ndata[0,1], ndata[1,1], ndata[2,1], ndata[3,1], fracx );
float x3 = CubicPolate( ndata[0,2], ndata[1,2], ndata[2,2], ndata[3,2], fracx );
float x4 = CubicPolate( ndata[0,3], ndata[1,3], ndata[2,3], ndata[3,3], fracx );
float y1 = CubicPolate( x1, x2, x3, x4, fracy );
Where ndata is defined as:
float[,] ndata = new float[4,4];
for( int X = 0; X < 4; X++ )
for( int Y = 0; Y < 4; Y++ )
//Smoothing done by averaging the general area around the coords.
ndata[X,Y] = SmoothedNoise( intx+(X-1), inty+(Y-1) );
(intx and inty are the floored values of the requested coordinates. fracx and fracy are the fractional parts of the inputted coordinates, to be x-intx, and y-inty, respectively)
Took Eske Rahn answer and made a single call (note, the code below uses matrix dimensions convention of (j, i) rather than image of (x, y) but that shouldn't matter for interpolation sake):
/// <summary>
/// Holds extension methods.
/// </summary>
public static class Extension
{
/// <summary>
/// Performs a bicubic interpolation over the given matrix to produce a
/// [<paramref name="outHeight"/>, <paramref name="outWidth"/>] matrix.
/// </summary>
/// <param name="data">
/// The matrix to interpolate over.
/// </param>
/// <param name="outWidth">
/// The width of the output matrix.
/// </param>
/// <param name="outHeight">
/// The height of the output matrix.
/// </param>
/// <returns>
/// The interpolated matrix.
/// </returns>
/// <remarks>
/// Note, dimensions of the input and output matrices are in
/// conventional matrix order, like [matrix_height, matrix_width],
/// not typical image order, like [image_width, image_height]. This
/// shouldn't effect the interpolation but you must be aware of it
/// if you are working with imagery.
/// </remarks>
public static float[,] BicubicInterpolation(
this float[,] data,
int outWidth,
int outHeight)
{
if (outWidth < 1 || outHeight < 1)
{
throw new ArgumentException(
"BicubicInterpolation: Expected output size to be " +
$"[1, 1] or greater, got [{outHeight}, {outWidth}].");
}
// props to https://stackoverflow.com/a/20924576/240845 for getting me started
float InterpolateCubic(float v0, float v1, float v2, float v3, float fraction)
{
float p = (v3 - v2) - (v0 - v1);
float q = (v0 - v1) - p;
float r = v2 - v0;
return (fraction * ((fraction * ((fraction * p) + q)) + r)) + v1;
}
// around 6000 gives fastest results on my computer.
int rowsPerChunk = 6000 / outWidth;
if (rowsPerChunk == 0)
{
rowsPerChunk = 1;
}
int chunkCount = (outHeight / rowsPerChunk)
+ (outHeight % rowsPerChunk != 0 ? 1 : 0);
var width = data.GetLength(1);
var height = data.GetLength(0);
var ret = new float[outHeight, outWidth];
Parallel.For(0, chunkCount, (chunkNumber) =>
{
int jStart = chunkNumber * rowsPerChunk;
int jStop = jStart + rowsPerChunk;
if (jStop > outHeight)
{
jStop = outHeight;
}
for (int j = jStart; j < jStop; ++j)
{
float jLocationFraction = j / (float)outHeight;
var jFloatPosition = height * jLocationFraction;
var j2 = (int)jFloatPosition;
var jFraction = jFloatPosition - j2;
var j1 = j2 > 0 ? j2 - 1 : j2;
var j3 = j2 < height - 1 ? j2 + 1 : j2;
var j4 = j3 < height - 1 ? j3 + 1 : j3;
for (int i = 0; i < outWidth; ++i)
{
float iLocationFraction = i / (float)outWidth;
var iFloatPosition = width * iLocationFraction;
var i2 = (int)iFloatPosition;
var iFraction = iFloatPosition - i2;
var i1 = i2 > 0 ? i2 - 1 : i2;
var i3 = i2 < width - 1 ? i2 + 1 : i2;
var i4 = i3 < width - 1 ? i3 + 1 : i3;
float jValue1 = InterpolateCubic(
data[j1, i1], data[j1, i2], data[j1, i3], data[j1, i4], iFraction);
float jValue2 = InterpolateCubic(
data[j2, i1], data[j2, i2], data[j2, i3], data[j2, i4], iFraction);
float jValue3 = InterpolateCubic(
data[j3, i1], data[j3, i2], data[j3, i3], data[j3, i4], iFraction);
float jValue4 = InterpolateCubic(
data[j4, i1], data[j4, i2], data[j4, i3], data[j4, i4], iFraction);
ret[j, i] = InterpolateCubic(
jValue1, jValue2, jValue3, jValue4, jFraction);
}
}
});
return ret;
}
}
I'm a bit confused on the third degree polynomial used.
Yes it gives the correct values in 0 and 1, but the derivatives of neighbouring cells does not fit, as far as I can calculate. If the grid-data is linear, it does not even return a line....
And it is not point symmetric in x=0.5
The polynomial that fits in 0 and 1 AND also have the same derivatives for neighbouring cells, and thus is smooth, is (almost) as easy to calculate.
(and it reduces to linear form if that fits the data)
In the labelling p and m is a short hand for plus and minus e.g. vm1 is v(-1)
//Bicubic convolution algorithm, cubic Hermite spline
static double CubicPolateConv
(double vm1, double v0, double vp1, double vp2, double frac) {
//The polynomial of degree 3 where P(x)=f(x) for x in {0,1}
//and P'(1) in one cell matches P'(0) in the next, gives a continuous smooth curve.
//And we also wants it to reduce nicely to a line, if that matches the data
//P(x)=Dx³+Cx²+Bx+A=((Dx+C)x+B)x+A
//P'(x)=3Dx²+2Cx+B
//P(0)=A =v0
//P(1)=D+C+B+A =Vp1
//P'(0)=B =(vp1-vm1)/2
//P'(1)=3D+2C+B=(vp2-v0 )/2
//Subtracting expressions for A and B from D+C+B+A
//D+C =vp1-B-A = (vp1+vm1)/2 - v0
//Subtracting that twice and a B from the P'(1)
//D=(vp2-v0)/2 - 2(D+C) -B =(vp2-v0)/2 - (Vp1+vm1-2v0) - (vp1-vm1)/2
// = 3(v0-vp1)/2 + (vp2-vm1)/2
//C=(D+C)-D = (vp1+vm1)/2 - v0 - (3(v0-vp1)/2 + (vp2-vm1)/2)
// = vm1 + 2vp1 - (5v0+vp2)/2;
//It is quite easy to calculate P(½)
//P(½)=D/8+C/4+B/2+A = (9*(v0+vp1)-(vm1+vp2))/16
//i.e. symmetric in its uses, and a mean of closest adjusted by mean of next ones
double B = (vp1 - vm1) / 2;
double DpC =(vp1 -v0) -B; //D+C+B+A - A - B
double D = (vp2 - v0) / 2 - 2 * DpC - B;
double C = DpC - D;
//double C = vm1 + 2 * vp1 - (5 * v0 + vp2) / 2;
//double D = (3*(v0 - vp1) + (vp2 - vm1)) / 2;
return ((D * frac + C) * frac + B) * frac + A;
}
Inspired by the comment of ManuTOO below I made it as fourth order too, with an optional parameter, you can set/calculate as you please, without breaking the smoothness of the curve.
It is basically the same with an added term all the way in the calculations. And If you set E to Zero, it will be identical to the above.
(Obviously if the data is actually on a line your calculation of E must assure that E is zero to get a linear output)
//The polynomial of degree 4 where P(x)=f(x) for x in {0,1}
//and P'(1) in one cell matches P'(0) in the next, gives a continuous smooth curve.
//And we also wants the it to reduce nicely to a line, if that matches the data
//With high order quotient weight of your choice....
//P(x)=Ex⁴+Dx³+Cx²+Bx+A=((((Ex+D)x+C)x+B)x+A
//P'(x)=4Ex³+3Dx²+2Cx+B
//P(0)=A =v0
//P(1)=E+D+C+B+A =Vp1
//P'(0)=B =(vp1-vm1)/2
//P'(1)=4E+3D+2C+B=(vp2-v0 )/2
//Subtracting Expressions for A, B and E from the E+D+C+B+A
//D+C =vp1-B-A -E = (vp1+vm1)/2 - v0 -E
//Subtracting that twice, a B and 4E from the P'(1)
//D=(vp2-v0)/2 - 2(D+C) -B -4E =(vp2-v0)/2 - (Vp1+vm1-2v0-2E) - (vp1-vm1)/2 -4E
// = 3(v0-vp1)/2 + (vp2-vm1)/2 -2E
//C=(D+C)-(D) = (vp1+vm1)/2 - v0 -E - (3(v0-vp1)/2 + (vp2-vm1)/2 -2E)
// = vm1 + 2vp1 - (5v0+vp2)/2 +E;
double E = ????????; //Your feed.... If Zero, cubic, see below
double B = (vp1 - vm1) / 2;
double DpC =(vp1 -v0) -B -E; //E+D+C+B+A - A - B -E
double D = (vp2 - v0) / 2 - 2 * DpC - B - 4 * E;
double C = DpC - D;
return (((E * frac + D) * frac + C) * frac + B) * frac + v0;
ADD:
Quoted from suggestion by #ManTOO below:
double E = (v0 - vm1 + vp1 - vp2) * m_BicubicSharpness;
With m_BicubicSharpness at 1.5, it's very close of Photoshop's Bicubic Sharper ; personally, I set it to 1.75 for a bit of extra kick.
Note that if data is on a line, this suggestion reduces nicely to zero
Note: The Bicubic formula given by Nicholas above (as the answer) has an error in it. by interpolating a sinusoid, I was able to see it was not correct.
The correct formula is:
float A = 0.5f * (v3 - v0) + 1.5f * (v1 - v2);
float B = 0.5f * (v0 + v2) - v1 - A;
float C = 0.5f * (v2 - v0);
float D = v1;
For the derivation, see https://www.paulinternet.nl/?page=bicubic

Find minimum distance between 2 points in 2 arrays

I have 2 lists containing points (x,y and z) and would like to find the closest points.
I assume I need to do something like this:
for (int i = 0; i < myarray1.Count; i++)
{
for (int j = 0; j < myarray2.Count; j++)
{
// Calculate the quadratic distance between 2 points (point in index i and j)
// Then store the minimum distance I guess?
}
}
another option is to use Kd-tree
using the Nearest neighbour search will give you a O(log n) complexity to find the nearest point to a given set of points, and your code will have O( n log n), instead of O (n^2).
see here for implementation and example of how to use it.
double min_dist = DOUBLE_MAX;
for (i = 0; i < myarray1.Count; i++)
{
for (j = 0; j < myarray2.Count; j++)
{
curr_dist = dist(a[i],a[j]);
if( min_dist > curr_dist)
{
min_dist = curr_dist;
}
}
}
where
double dist(Point a, Point b) {
return sqrt(pow(a.x-b.x,2)+pow(a.y-b.y,2)+pow(a.z-b.z,2);
}
To compute the distance:
double sqr(double x) {return x*x;}
double distance(MyPoint a, MyPoint b) {
return sqrt(sqr(a.x-b.x)+sqr(a.y-b.y)+sqr(a.z-b.z);
}
Then in the second loop you store the minimum distance found so far:
double d = distance(myarray1[i],myarray2[j]);
if (d<min_d) min_d = d;
where min_d is defined at the beginning:
double min_d = Float.MAX_VALUE;
In C# I would do this using Linq.
First I would define the function that calculates the distance between two points as in Emanuelle Paolini's answer:
public double Distance(Point p1, Point p2)
{
return Math.Sqrt((p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p1.y) * (p1.y - p1.y) + (p1.z - p1.z) * (p1.z - p1.z));
}
Then I would query the two lists as follows:
var distanceQuery = from p1 in myarray1
from p2 in myarray2
select Dist(p1, p2);
And finally I would retrieve the minimum distance:
var minimumDistance = distanceQuery.Min();
Formula is
Math.sqrt(Math.pow(Math.abs(x1-x2),2) + Math.pow(Math.abs(y1-y2),2)+ Math.pow(Math.abs(z1-z2),2))

Confidence Intervals Using MathNET

I have a IEnumerable<double> data sample. I want to compute the 90% confidence interval for the signal/data. I have MathNET library at my disposal, but I am confused as to how to correctly work with the library. Given my data, the idea is to return two additional data arrays that contain the original signal's confidence intervals
using MathNet.Numerics.Statistics;
using MathNet.Numerics.Distributions;
public static List<double[]> ConfidenceIntervals(IEnumerable<double> sample, double interval)
{
Contract.Requires(interval > 0 && interval < 1.0);
int sampleSize = sample.Count();
double alpha = 1.0 - interval;
double mean = sample.Mean();
double sd = sample.StandardDeviation();
double t, mu;
double[] upper = new double[sampleSize];
double[] lower = new double[sampleSize];
StudentT studentT = new StudentT(mean, alpha, sampleSize - 1);
int index = 0;
foreach (double d in sample)
{
t = studentT.CumulativeDistribution(d);
double tmp = t * (sd / Math.Sqrt(sampleSize));
mu = mean - tmp;
upper[index] = d + mu;
lower[index] = d - mu;
}
return new List<double[]>() { upper, lower };
}
This really is not complex in terms of mathematics, I am just confused as to how to correctly use the functions/methods available to me in the MathNET library.
I'm not entirely sure I understand how the confidence interval of the signal is supposed to be applied to each sample of the signal, but we can compute the confidence interval of the sample set as follows:
public static Tuple<double, double> A(double[] samples, double interval)
{
double theta = (interval + 1.0)/2;
double mean = samples.Mean();
double sd = samples.StandardDeviation();
double T = StudentT.InvCDF(0,1,samples.Length-1,theta);
double t = T * (sd / Math.Sqrt(samples.Length));
return Tuple.Create(mean-t, mean+t);
}
Except that the line where we compute T does not compile because unfortunately there is no StudentT.InvCDF in current Math.NET Numerics yet. But we can still evaluate it numerically as a workaround in the meantime:
var student = new StudentT(0,1,samples.Length-1);
double T = FindRoots.OfFunction(x => student.CumulativeDistribution(x)-theta,-800,800);
For example, with 16 samples and alpha 0.05 we get 2.131 as expected. If there are more than ~60-100 samples, this can also be approximated with the normal distribution:
double T = Nomal.InvCDF(0,1,theta);
So all in all:
public static Tuple<double, double> B(double[] samples, double interval)
{
double theta = (interval + 1.0)/2;
double T = FindRoots.OfFunction(x => StudentT.CDF(0,1,samples.Length-1,x)-theta,-800,800);
double mean = samples.Mean();
double sd = samples.StandardDeviation();
double t = T * (sd / Math.Sqrt(samples.Length));
return Tuple.Create(mean-t, mean+t);
}
This is not the full answer yet as I understand you wanted to somehow apply the confidence interval to each sample, but hopefully it helps on the way to get there.
PS: Using Math.NET Numerics v3.0.0-alpha7
I noticed that you didn't increase the index value in foreach loop. This will make the value at index 0 is replaced by the next calculation (When you try to set upper[index] and lower[index] values).
So I guess this is a reason why you got the incorrect results.
If so, your code should be
using MathNet.Numerics.Statistics;
using MathNet.Numerics.Distributions;
public static List<double[]> ConfidenceIntervals(IEnumerable<double> sample, double interval)
{
Contract.Requires(interval > 0 && interval < 1.0);
int sampleSize = sample.Count();
double alpha = 1.0 - interval;
double mean = sample.Mean();
double sd = sample.StandardDeviation();
double t, mu;
double[] upper = new double[sampleSize];
double[] lower = new double[sampleSize];
StudentT studentT = new StudentT(mean, alpha, sampleSize - 1);
int index = 0;
foreach (double d in sample)
{
t = studentT.CumulativeDistribution(d);
double tmp = t * (sd / Math.Sqrt(sampleSize));
mu = mean - tmp;
upper[index] = d + mu;
lower[index] = d - mu;
index++;
}
return new List<double[]>() { upper, lower };
}

C# to mimic Excel SLOPE function

I'm trying to calculate the slope of two data lists. You can easily calculate this in EXCEL using the SLOPE function. =SLOPE(A1:A100, B1:B100). I'm trying to mimic this function in C# WinForm. Here is my code, it can calculate something, but not the correct number that you would get from the Excel function. Please help me find the error here. Thanks so much!
private double Getslope(List<double> ProductGrossExcessReturnOverRFR, List<double> primaryIndexExcessReturnOverRFR, int months, int go_back = 0)
{
double slope = 0;
double sumx = 0, sumy = 0, sumxy = 0, sumx2 = 0;
for (int i = ProductGrossExcessReturnOverRFR.Count - 1 - go_back; i > ProductGrossExcessReturnOverRFR.Count - (1 + months + go_back); i--)
{
sumxy += ProductGrossExcessReturnOverRFR[i] * primaryIndexExcessReturnOverRFR[i];
sumx += ProductGrossExcessReturnOverRFR[i];
sumy += primaryIndexExcessReturnOverRFR[i];
sumx2 += ProductGrossExcessReturnOverRFR[i] * ProductGrossExcessReturnOverRFR[i];
}
return slope = 1 / (((sumxy - sumx * sumy / months) / (sumx2 - sumx * sumx / months)));
}
Test data:
{1.085231224, 2.335034309, 0.346667278} and
{3.185231224,3.705034309 , -0.883332722} should have slope of 0.3373 if you calculate in Excel using =SLOPE function. But my code produces 0.47 somehow...
I think your formula is wrong
According to the Excel documentation the formula for SLOPE is
Note also that the first argument to the function is the the y values.
It's unclear how goback and months apply, but it looks like this might work:
private double Getslope(List<double> ProductGrossExcessReturnOverRFR,
List<double> primaryIndexExcessReturnOverRFR,
int months,
int go_back = 0)
{
// calc # of items to skip
int skip = ProductGrossExcessReturnOverRFR.Count - go_back - months;
// get list of x's and y's
var ys = ProductGrossExcessReturnOverRFR.Skip(skip).Take(months);
var xs = primaryIndexExcessReturnOverRFR.Skip(skip).Take(months);
// "zip" xs and ys to make the sum of products easier
var xys = Enumerable.Zip(xs,ys, (x, y) => new {x = x, y = y});
double xbar = xs.Average();
double ybar = ys.Average();
double slope = xys.Sum(xy => (xy.x - xbar) * (xy.y - ybar)) / xs.Sum(x => (x - xbar)*(x - xbar));
return slope;
}

Categories