arrays

R

RobcPettit

Hi, What is the best way to use an array to find moving averages. I
want to calculate a 15 day and 41 day m/a. I know my array will need
to contain 12 columns, but the rows need to be dynamic. The row size
will need to be aminium of 50 rows. So far Im thinking of either
creating 2 arrays, one for 15 and one for 41 day m/a. Keeping them
each to that row size then iterate through them creating new arrays
when new data added. Eg when 16 data point added to the 15 day m/a,
remove the first data point, add the new data point at the end. I
think im right in thinking that I would have to add the data to a new
array to do this. The other idea was to create an array 12 cols wide
and some how have dynamic rows. Add data indefinatly, then itirate
through the array in reverse, first back 15 points, summing as I go,
and the again 41 points to calculate the average. I dont know how to
iterate in reverse or create an array with set col width but dynamic
rows. Any ideas appreciated.
Regards Rober
 
N

Nicholas Paldino [.NET/C# MVP]

Rober,

Do the "columns" in your data have any significance, or are they just
sets of 15 values? If they are sets of 15 values, then I would create a
List<int[]> (or List<decimal[]>, or List<double[]>), creating your arrays,
and then adding them to the list, then have one method that takes your list
and calculates your average.

Hope this helps.
 
R

RobcPettit

Hi, thankyou for your replys. Plenty to read up on. The columns relate
to 12 different shares, and the values represent changes updated every
minute. So over a day there can be many values, whence the need for
dynamic rows.
Regards Robert
 
P

Peter Duniho

Hi, What is the best way to use an array to find moving averages. [...]

In answer to the basic question, I would say that two good solutions would
be to either use the Queue<> generic class, or implement a circular buffer
yourself with an array. Using the Queue<> class involves a little more
overhead "behind the scenes", but allows your own code to most closely
match what it is you're actually doing. A circular buffer is slightly
more efficient, but the implementation in your own code would be less
direct.

Now, that said, your question has a bunch of other pieces of information
that may or may not be relevant to those of us trying to answer it. If
that information is relevant, IMHO you should do a better job of
explaining why. The information about the length of the moving average
(15 and 41 days) seems useful, but I'm left having no idea why you say "my
array will need to contain 12 columns", nor do I know why you say "the row
size will need to be a minimum of 50 rows". These statements may well be
correct, but we don't have enough context from you to understand why.

As an example of what I mentioned above, here are a couple of
implementations of a moving average you might consider using as an outline
for your own needs:

// Circular buffer

void MovingAverage(double[] pricesHistory, int cdayAverage)
{
double priceSum, priceMovingAverage;
double[] pricesMoving = new double[cdayAverage];
int ipriceCur, ipriceCircle, cpriceAveraged;

ipriceCur = 0;
ipriceCircle = 0;
cpriceAveraged = 0;

while (ipriceCur < pricesHistory.Length)
{
double priceCur = pricesHistory[ipriceCur];

priceSum += priceCur;

if (cpriceAveraged < pricesMoving.Length)
{
cpriceAveraged++;
}
else
{
ipriceCircle = ipriceCircle % pricesMoving.Length;
priceSum -= pricesMoving[ipriceCircle];
}

pricesMoving[ipriceCircle++] = priceCur;

priceMovingAverage = priceSum / cpriceAveraged;
}
}


// Queue

void MovingAverage(double[] pricesHistory, int cdayAverage)
{
double priceSum, priceMovingAverage;
Queue<double> pricesMoving = new Queue<double>(cdayAverage)
int ipriceCur;

ipriceCur = 0;

while (ipriceCur < pricesHistory.Length)
{
double priceCur = pricesHistory[ipriceCur];

priceSum += priceCur;

if (!(pricesMoving.Count < cdayAverage))
{
priceSum -= pricesMoving.Dequeue();
}

pricesMoving.Enqueue(priceCur);

priceMovingAverage = priceSum / pricesMoving.Count;
}
}

In either algorithm, the input data is passed in with "pricesHistory", the
number of days to average is pased in with "cdayAverage", and the
"priceMovingAverage" variable contains, at the end of each loop, the
current moving average given the input data.

Hope that helps.

Pete
 
R

RobcPettit

Thankyou for your reply Peter, After reading my posts , yuor right its
not very clear. My data is for 12 shares, and I was thinking Id need 1
column for each share. Then when I collected the data,
 
R

RobcPettit

Thankyou for your reply Peter, After reading my posts , yuor right its
not very clear. My data is for 12 shares, and I was thinking Id need 1
column for each share. Then when I collected the data, Id add the
result for each share to its relevent column. Id have to have a new
row for each set of new data. The min 50 rows was to make sure that
the 41 day average was calculated correctly. The 15 and 41 day would
be calculated on the same data.In my program I iterate through each
share, updating the data to a row, andhopefully to an array to do the
ave calcs. Thanks for your code example.
Regards Robert
 
P

Peter Duniho

Thankyou for your reply Peter, After reading my posts , yuor right its
not very clear. My data is for 12 shares, and I was thinking Id need 1
column for each share.

If you want to keep all of your data in a single two-dimensional array,
then yes...I see now why you would want 12 columns.

That said, I think it might make more sense to just maintain a per-share
moving average data structure, rather than trying to combine everything
into a single array.
Then when I collected the data, Id add the
result for each share to its relevent column. Id have to have a new
row for each set of new data. The min 50 rows was to make sure that
the 41 day average was calculated correctly.

Well, you only need 41 rows (or whatever) for that.
The 15 and 41 day would
be calculated on the same data.

Well, part of the question if implementation depends on exactly how you're
going to be using the data. The code I posted would be most useful if you
intended to generate a daily moving average value for every day in a
series of days for which you have data.

However, if you are only going to generate the "moving average" on request
for a particular day, then it makes more sense to just retrieve the
maximum number of days (41 in this case) up to and including the day for
which you want the calculation, and then calculate the averages directly
for that day only. This would correspond more closely to your "rows and
columns" description, especially if you are retrieving the data from a
database in a way that creates such a two-dimensional array.

Pete
 
R

RobcPettit

Thanks again for your reply. The more I delve into this, I think your
suggestion of maintaining a per share data structure is the best
route. The m/a are calculated throughout the day. Eg 41 minutes into
the day the first 15/41 point is calculated, then from that point
onwards its maintained for each share. The calcs itself are easy
enough, its the 12 different share arrays/variables I struggle with.
Regards Robert
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top