How to multiply all elements in an doubles list? - c#

How do I multiply the contents of a list <double>?
List<double> mult=new List<double>{3, 5, 10};
So far I have:
double r=0.0;
for(int i=0;i<mult.Count;i++)
{
r=mult[i]*mult[(i+1)];
}

To fix your loop, start with 1.0 and multiply each item in the list, like this:
double r = 1.0;
for(int i = 0; i < mult.Count; i++)
{
r = r * mult[i]; // or equivalently r *= mult[i];
}
But for simplicity, you could use a little Linq with the Aggregate extension method:
double r = mult.Aggregate((a, x) => a * x);

What do you mean by multiply? If you like to calculate the product, then your code is wrong and the correct code is
double r=1.0;
for(int i=0;i<mult.Count;i++)
{
r *= mult[i];
}

Related

How to fill a SortedList with a Dictionary as TValue

I want to use the following method but as hobbyist programmer I cannot understand how to fill(format?) the SortedList that will be used as input to the method.
I have a sql table with DateTime and a Value that will have always "close" string associated (see code)
looked at several answers but no conclusions at all
public static void AddBollingerBands(ref SortedList<DateTime, Dictionary<string, double>> data, int period, int factor)
{
double total_average = 0;
double total_squares = 0;
for (int i = 0; i < data.Count(); i++)
{
total_average += data.Values[i]["close"];
total_squares += Math.Pow(data.Values[i]["close"], 2);
if (i >= period - 1)
{
double total_bollinger = 0;
double average = total_average / period;
double stdev = Math.Sqrt((total_squares - Math.Pow(total_average,2)/period) / period);
data.Values[i]["bollinger_average"] = average;
data.Values[i]["bollinger_top"] = average + factor * stdev;
data.Values[i]["bollinger_bottom"] = average - factor * stdev;
.......
......
Using .Values is a get operation only. The result is not a reference to the element in your sorted list, but instead an immutable var.
Ignoring the issues with not using SortedList properly, you can only change the value of a sortedList if you reference the element directly via its key:
data[keyValue]["total_bollinger"] = average;
The above line of code would update that value in the list accordingly.
Rather than iterate over the list via data.Count(), I would recommend iterating over the keys like this:
var keys = data.Keys;
foreach(var key in data.Keys)
{
double total_bollinger = 0;
double average = total_average / period;
double stdev = Math.Sqrt((total_squares - Math.Pow(total_average, 2) / period) / period);
data[key]["total_bollinger"] = total_average;
}

Get n distinct random numbers between two values whose sum is equal to a given number

I would like to find distinct random numbers within a range that sums up to given number.
Note: I found similar questions in stackoverflow, however they do not address exactly this problem (ie they do not consider a negative lowerLimit for the range).
If I wanted that the sum of my random number was equal to 1 I just generate the required random numbers, compute the sum and divided each of them by the sum; however here I need something a bit different; I will need my random numbers to add up to something different than 1 and still my random numbers must be within a given range.
Example: I need 30 distinct random numbers (non integers) between -50 and 50 where the sum of the 30 generated numbers must be equal to 300; I wrote the code below, however it will not work when n is much larger than the range (upperLimit - lowerLimit), the function could return numbers outside the range [lowerLimit - upperLimit]. Any help to improve the current solution?
static void Main(string[] args)
{
var listWeights = GetRandomNumbersWithConstraints(30, 50, -50, 300);
}
private static List<double> GetRandomNumbersWithConstraints(int n, int upperLimit, int lowerLimit, int sum)
{
if (upperLimit <= lowerLimit || n < 1)
throw new ArgumentOutOfRangeException();
Random rand = new Random(Guid.NewGuid().GetHashCode());
List<double> weight = new List<double>();
for (int k = 0; k < n; k++)
{
//multiply by rand.NextDouble() to avoid duplicates
double temp = (double)rand.Next(lowerLimit, upperLimit) * rand.NextDouble();
if (weight.Contains(temp))
k--;
else
weight.Add(temp);
}
//divide each element by the sum
weight = weight.ConvertAll<double>(x => x / weight.Sum()); //here the sum of my weight will be 1
return weight.ConvertAll<double>(x => x * sum);
}
EDIT - to clarify
Running the current code will generate the following 30 numbers that add up to 300. However those numbers are not within -50 and 50
-4.425315699
67.70219958
82.08592061
46.54014109
71.20352208
-9.554070146
37.65032717
-75.77280868
24.68786878
30.89874589
142.0796933
-1.964407284
9.831226893
-15.21652248
6.479463312
49.61283063
118.1853036
-28.35462683
49.82661159
-65.82706541
-29.6865969
-54.5134262
-56.04708803
-84.63783048
-3.18402453
-13.97935982
-44.54265204
112.774348
-2.911427266
-58.94098071
Ok, here how it could be done
We will use Dirichlet Distribution, which is distribution for random numbers xi in the range [0...1] such that
Sumi xi = 1
So, after linear rescaling condition for sum would be satisfied automatically. Dirichlet distribution is parametrized by αi, but we assume all RN to be from the same marginal distribution, so there is only one parameter α for each and every index.
For reasonable large value of α, mean value of sampled random numbers would be =1/n, and variance ~1/(n * α), so larger α lead to random value more close to the mean.
Ok, now back to rescaling,
vi = A + B*xi
And we have to get A and B. As #HansKesting rightfully noted, with only two free parameters we could satisfy only two constraints, but you have three. So we would strictly satisfy low bound constraint, sum value constraint, but occasionally violate upper bound constraint. In such case we just throw whole sample away and do another one.
Again, we have a knob to turn, α getting larger means we are close to mean values and less likely to hit upper bound. With α = 1 I'm rarely getting any good sample, but with α = 10 I'm getting close to 40% of good samples. With α = 16 I'm getting close to 80% of good samples.
Dirichlet sampling is done via Gamma distribution, using code from MathDotNet.
Code, tested with .NET Core 2.1
using System;
using MathNet.Numerics.Distributions;
using MathNet.Numerics.Random;
class Program
{
static void SampleDirichlet(double alpha, double[] rn)
{
if (rn == null)
throw new ArgumentException("SampleDirichlet:: Results placeholder is null");
if (alpha <= 0.0)
throw new ArgumentException($"SampleDirichlet:: alpha {alpha} is non-positive");
int n = rn.Length;
if (n == 0)
throw new ArgumentException("SampleDirichlet:: Results placeholder is of zero size");
var gamma = new Gamma(alpha, 1.0);
double sum = 0.0;
for(int k = 0; k != n; ++k) {
double v = gamma.Sample();
sum += v;
rn[k] = v;
}
if (sum <= 0.0)
throw new ApplicationException($"SampleDirichlet:: sum {sum} is non-positive");
// normalize
sum = 1.0 / sum;
for(int k = 0; k != n; ++k) {
rn[k] *= sum;
}
}
static bool SampleBoundedDirichlet(double alpha, double sum, double lo, double hi, double[] rn)
{
if (rn == null)
throw new ArgumentException("SampleDirichlet:: Results placeholder is null");
if (alpha <= 0.0)
throw new ArgumentException($"SampleDirichlet:: alpha {alpha} is non-positive");
if (lo >= hi)
throw new ArgumentException($"SampleDirichlet:: low {lo} is larger than high {hi}");
int n = rn.Length;
if (n == 0)
throw new ArgumentException("SampleDirichlet:: Results placeholder is of zero size");
double mean = sum / (double)n;
if (mean < lo || mean > hi)
throw new ArgumentException($"SampleDirichlet:: mean value {mean} is not within [{lo}...{hi}] range");
SampleDirichlet(alpha, rn);
bool rc = true;
for(int k = 0; k != n; ++k) {
double v = lo + (mean - lo)*(double)n * rn[k];
if (v > hi)
rc = false;
rn[k] = v;
}
return rc;
}
static void Main(string[] args)
{
double[] rn = new double [30];
double lo = -50.0;
double hi = 50.0;
double alpha = 10.0;
double sum = 300.0;
for(int k = 0; k != 1_000; ++k) {
var q = SampleBoundedDirichlet(alpha, sum, lo, hi, rn);
Console.WriteLine($"Rng(BD), v = {q}");
double s = 0.0;
foreach(var r in rn) {
Console.WriteLine($"Rng(BD), r = {r}");
s += r;
}
Console.WriteLine($"Rng(BD), summa = {s}");
}
}
}
UPDATE
Usually, when people ask such question, there is an implicit assumption/requirement - all random numbers shall be distribution in the same way. It means that if I draw marginal probability density function (PDF) for item indexed 0 from the sampled array, I shall get the same distribution as I draw marginal probability density function for the last item in the array. People usually sample random arrays to pass it down to other routines to do some interesting stuff. If marginal PDF for item 0 is different from marginal PDF for last indexed item, then just reverting array will produce wildly different result with the code which uses such random values.
Here I plotted distributions of random numbers for item 0 and last item (#29) for original conditions([-50...50] sum=300), using my sampling routine. Look similar, isn't it?
Ok, here is a picture from your sampling routine, same original conditions([-50...50] sum=300), same number of samples
UPDATE II
User supposed to check return value of the sampling routine and accept and use sampled array if (and only if) return value is true. This is acceptance/rejection method. As an illustration, below is code used to histogram samples:
int[] hh = new int[100]; // histogram allocated
var s = 1.0; // step size
int k = 0; // good samples counter
for( ;; ) {
var q = SampleBoundedDirichlet(alpha, sum, lo, hi, rn);
if (q) // good sample, accept it
{
var v = rn[0]; // any index, 0 or 29 or ....
var i = (int)((v - lo) / s);
i = System.Math.Max(i, 0);
i = System.Math.Min(i, hh.Length-1);
hh[i] += 1;
++k;
if (k == 100000) // required number of good samples reached
break;
}
}
for(k = 0; k != hh.Length; ++k)
{
var x = lo + (double)k * s + 0.5*s;
var v = hh[k];
Console.WriteLine($"{x} {v}");
}
Here you go. It'll probably run for centuries before actually returning the list, but it'll comply :)
public List<double> TheThing(int qty, double lowest, double highest, double sumto)
{
if (highest * qty < sumto)
{
throw new Exception("Impossibru!");
// heresy
highest = sumto / 1 + (qty * 2);
lowest = -highest;
}
double rangesize = (highest - lowest);
Random r = new Random();
List<double> ret = new List<double>();
while (ret.Sum() != sumto)
{
if (ret.Count > 0)
ret.RemoveAt(0);
while (ret.Count < qty)
ret.Add((r.NextDouble() * rangesize) + lowest);
}
return ret;
}
I come up with this solution which is fast. I am sure it couldbe improved, but for the moment it does the job.
n = the number of random numbers that I will need to find
Constraints
the n random numbers must add up to finalSum the n random numbers
the n random numbers must be within lowerLimit and upperLimit
The idea is to remove from the initial list (that sums up to finalSum) of random numbers the numbers outside the range [lowerLimit, upperLimit].
Then count the number left of the list (called nValid) and their sum (called sumOfValid).
Now, iteratively search for (n-nValid) random numbers within the range [lowerLimit, upperLimit] whose sum is (finalSum-sumOfValid)
I tested it with several combinations for the inputs variables (including negative sum) and the results looks good.
static void Main(string[] args)
{
int n = 100;
int max = 5000;
int min = -500000;
double finalSum = -1000;
for (int i = 0; i < 5000; i++)
{
var listWeights = GetRandomNumbersWithConstraints(n, max, min, finalSum);
Console.WriteLine("=============");
Console.WriteLine("sum = " + listWeights.Sum());
Console.WriteLine("max = " + listWeights.Max());
Console.WriteLine("min = " + listWeights.Min());
Console.WriteLine("count = " + listWeights.Count());
}
}
private static List<double> GetRandomNumbersWithConstraints(int n, int upperLimit, int lowerLimit, double finalSum, int precision = 6)
{
if (upperLimit <= lowerLimit || n < 1) //todo improve here
throw new ArgumentOutOfRangeException();
Random rand = new Random(Guid.NewGuid().GetHashCode());
List<double> randomNumbers = new List<double>();
int adj = (int)Math.Pow(10, precision);
bool flag = true;
List<double> weights = new List<double>();
while (flag)
{
foreach (var d in randomNumbers.Where(x => x <= upperLimit && x >= lowerLimit).ToList())
{
if (!weights.Contains(d)) //only distinct
weights.Add(d);
}
if (weights.Count() == n && weights.Max() <= upperLimit && weights.Min() >= lowerLimit && Math.Round(weights.Sum(), precision) == finalSum)
return weights;
/* worst case - if the largest sum of the missing elements (ie we still need to find 3 elements,
* then the largest sum is 3*upperlimit) is smaller than (finalSum - sumOfValid)
*/
if (((n - weights.Count()) * upperLimit < (finalSum - weights.Sum())) ||
((n - weights.Count()) * lowerLimit > (finalSum - weights.Sum())))
{
weights = weights.Where(x => x != weights.Max()).ToList();
weights = weights.Where(x => x != weights.Min()).ToList();
}
int nValid = weights.Count();
double sumOfValid = weights.Sum();
int numberToSearch = n - nValid;
double sum = finalSum - sumOfValid;
double j = finalSum - weights.Sum();
if (numberToSearch == 1 && (j <= upperLimit || j >= lowerLimit))
{
weights.Add(finalSum - weights.Sum());
}
else
{
randomNumbers.Clear();
int min = lowerLimit;
int max = upperLimit;
for (int k = 0; k < numberToSearch; k++)
{
randomNumbers.Add((double)rand.Next(min * adj, max * adj) / adj);
}
if (sum != 0 && randomNumbers.Sum() != 0)
randomNumbers = randomNumbers.ConvertAll<double>(x => x * sum / randomNumbers.Sum());
}
}
return randomNumbers;
}

c# calculating portfolio beta between stock and index

does anyone know a way to calculate Beta (beta coefficient) for a portfolio or stock vs. a benchmark, such as an index like S&P in c#?
I already have 2 arrays of type double that would be required for such a calculation but I can't find any sleek way to do this.
StatisticFormula.BetaFunction Method (Double, Double) exists but this accepts one value for each param, not an array - which statistically makes no sense.
thanks in advance
I'm not aware of any good C# Finance/Statistics packages, so I wrote the method directly and borrowed from this stats package: https://www.codeproject.com/Articles/42492/Using-LINQ-to-Calculate-Basic-Statistics
using System;
using System.Collections.Generic;
using System.Linq;
namespace ConsoleApplication1
{
static class Program
{
static void Main(string[] args)
{
double[] closingPriceStock = { 39.32, 39.45, 39.27, 38.73, 37.99, 38.38, 39.53, 40.55, 40.78, 41.3, 41.35, 41.25, 41.1, 41.26, 41.48, 41.68, 41.77, 41.92, 42.12, 41.85, 41.54 };
double[] closingPriceMarket = { 1972.18, 1988.87, 1987.66, 1940.51, 1867.61, 1893.21, 1970.89, 2035.73, 2079.61, 2096.92, 2102.44, 2091.54, 2083.39, 2086.05, 2084.07, 2104.18, 2077.57, 2083.56, 2099.84, 2093.32, 2098.04 };
double[] closingPriceStockDailyChange = new double[closingPriceStock.Length - 1];
double[] closingPriceMarketDailyChange = new double[closingPriceMarket.Length - 1];
for (int i = 0; i < closingPriceStockDailyChange.Length; i++)
{
closingPriceStockDailyChange[i] = (closingPriceStock[i + 1] - closingPriceStock[i]) * 100 / closingPriceStock[i];
closingPriceMarketDailyChange[i] = (closingPriceMarket[i + 1] - closingPriceMarket[i]) * 100 / closingPriceMarket[i];
}
double beta = Covariance(closingPriceStockDailyChange, closingPriceMarketDailyChange) / Variance(closingPriceMarketDailyChange);
Console.WriteLine(beta);
Console.Read();
}
public static double Variance(this IEnumerable<double> source)
{
int n = 0;
double mean = 0;
double M2 = 0;
foreach (double x in source)
{
n = n + 1;
double delta = x - mean;
mean = mean + delta / n;
M2 += delta * (x - mean);
}
return M2 / (n - 1);
}
public static double Covariance(this IEnumerable<double> source, IEnumerable<double> other)
{
int len = source.Count();
double avgSource = source.Average();
double avgOther = other.Average();
double covariance = 0;
for (int i = 0; i < len; i++)
covariance += (source.ElementAt(i) - avgSource) * (other.ElementAt(i) - avgOther);
return covariance / len;
}
}
}
This would have to be refactored to calculate beta in a function, you can import the linked package to avoid the static methods I included, etc., but this is just a toy example.

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))

Which is faster, for loop or LINQ

I have two lists of double values same as here:
List<double> list1 = something;
List<double> list2 = somethingElse;
I want to subtract these two lists. Lists are huge and I want to do it as fast as possible. Which of the below methods is faster:
public double CalculateDistance(List<double> list1, List<double> list2)
{
double dist = 0;
for (int i = 0; i != list1.Count; i++)
{
dist += Math.Pow(list1 [i] - list2 [i], 2.0);
}
return dist;
}
or this:
public double CalculateDistance(List<double> list1, List<double> list2)
{
double dist = list1.Zip(list2, (v1, v2) => Math.Pow(v1 - v2, 2.0)).Sum();
return dist;
}
I dont know what LINQ does under the hood so I'm not sure which one is better.
Neither. Using a loop has less overhead than LINQ, so that is a good start.
Use the < operator in the loop condition, that is the standard way of writing such a loop, so it's more likely that the compiler will recognise it and optimise it properly.
Using Math.Pow to square a number is not effective. It's somewhere in the ballpark of 100 times faster to multiply it by itself:
public double CalculateDistance(List<double> list1, List<double> list2) {
double dist = 0;
for (int i = 0; i < list1.Count; i++) {
double n = list1[i] - list2[i];
dist += n * n;
}
return dist;
}
Edit:
Using PLINQ you would get a better performance for large sets. Testing it on my computer I found that with less than 10000 items it's not faster to use PLINQ. For lists with 10 million items, I got about 40% shorter execution time.
I also found that using a projection I got about 30% shorter execution time than using Zip:
public double CalculateDistance(List<double> list1, List<double> list2) {
return
ParallelEnumerable.Range(0, list1.Count).Select(i => {
double n = list1[i] - list2[i];
return n * n;
}).Sum();
}

Categories