0
  1. I want a function that works.
  2. I believe my logic is correct, thus my (vector out of range error) must be coming from the lack of familiarity and using the code correctly.
  3. I do know that there is long code out there for this fairly simple algorithm. Please help if you can.

Basically, I take the length as the "moving" window as it loops through j to the end of the size of the vector. This vector is filled with stock prices.

If the length equaled 2 for a 2 day moving average for numbers 1 2 3 4. I should be able to output 1.5, 2.5, and 3.5. However, I get an out of range error.

The logic is shown in the code. If an expert could help me with this simple moving average function that I am trying to create that would be great! Thanks.

void Analysis::SMA()
{

    double length;
    cout << "Enter number days for your Simple Moving Average:" << endl;
    cin >> length;
    double sum = 0;
    double a;
    while (length >= 2){
        vector<double>::iterator it;
        for (int j = 0; j < close.size(); j++){

                sum = vector1[length + j - 1] + vector1[length + j - 2];
                a = sum / length;
                vector2.push_back(a);

                vector<double>::iterator g;
                for (g = vector2.begin(); g != vector2.end(); ++g){

                    cout << "Your SMA: " << *g;
            }
        }
    }
}
mwf1234
  • 45
  • 1
  • 10

3 Answers3

6

You don't need 3 loops to calculate a moving average over an array of data, you only need 1. You iterate over the array and keep track of the sum of the last n items, and then just adjust it for each new value, adding one value and removing one each time.

For example suppose you have a data set:

4 8 1 6 9

and you want to calculate a moving average with a window size of 3, then you keep a running total like this:

iteration add subtract running-total output average
0         4   -        4             - (not enough values yet)
1         8   -        12            -
2         1   -        13            13 / 3
3         6   4        15            15 / 3
4         9   8        16            16 / 3

Notice that we add each time, we start subtracting at iteration 3 (for a window size of 3) and start outputting the average at iteration 2 (window size minus 1).

So the code will be something like this:

double runningTotal = 0.0;
int windowSize = 3;
for(int i = 0; i < length; i++)
{
     runningTotal += array[i];   // add
     if(i >= windowSize)
         runningTotal -= array[i - windowSize];   // subtract
     if(i >= (windowSize - 1))  // output moving average
         cout << "Your SMA: " << runningTotal / (double)windowSize;
}

You can adapt this to use your vector data structure.

samgak
  • 23,944
  • 4
  • 60
  • 82
  • Thanks. TBH I thought you were a random person at first just trying to be insinuating, but thanks for helping me out all along (with the edits) and now the code. I will try it out and hope it works!! Thanks samgak! – mwf1234 May 20 '15 at 01:50
  • Thanks. Your logic is correct. I really had a hard time with this not the logic, but I am just trying to practice in C++. – mwf1234 May 20 '15 at 01:57
  • 1
    Not "keep track of the average" but "keep track of the sum", to be correct – Sami Kuhmonen May 20 '15 at 04:04
  • Yes, very good well explained answer. I would +1 it if I could. However, everything works. I realized my vector feed was only one element (by mistake). Not a bad thing, because it made me try harder to understand the fundamentals of C++ and trying to figure out the algorithm. – mwf1234 May 20 '15 at 05:29
1

Within your outermost while loop you never change length so your function will run forever.

Then, notice that if length is two and closes.size() is four, length + j - 1 will be 5, so my psychic debugging skills tell me your vector1 is too short and you index off the end.

Mark B
  • 95,107
  • 10
  • 109
  • 188
  • Right that is for the concept, but the logic of the code is there. I am just trying to code a SMA function, typically the length would be like 9, 10, 20, 30, 50, 100, or 200. I see how the while loops forever. – mwf1234 May 20 '15 at 01:34
1

This question has been answered but I thought I'd post complete code for people in the future seeking information.

#include <iostream>
#include <vector>
using namespace std;

int main() {
vector<double> vector1 { 2, 4, 6, 8, 10, 12, 14, 16, 18, 20 };
double length;
cout << "Enter number days for your Simple Moving Average:" << endl;
cin >> length;
double sum = 0;
int cnt = 0;
for (int i = 0; i < vector1.size(); i++) {
    sum += vector1[i];
    cnt++;
    if (cnt >= length) {
        cout << "Your SMA: " << (sum / (double) length) << endl;
        sum -= vector1[cnt - length];           
        }
    }
return 0;
}

This is slightly different than the answer. A 'cnt' variable in introduced to avoid an additional if statement.

Dweeberly
  • 4,668
  • 2
  • 22
  • 41
  • I saw that the count had to be greater than or equal to the length. Cheers. Yeah, I still had some bugs. Maybe this will clear it up and answer my question IN vector mode and in the similar content. Thanks @Dweeberly! – mwf1234 May 20 '15 at 02:27
  • I'm guessing that saves big O time (processing time); less if and arguments. – mwf1234 May 20 '15 at 02:46
  • The big O (order of) processing time is dominated by the main loop so it's O(n) where n is the size of your vector. – Dweeberly May 20 '15 at 03:08
  • Thanks man. I just realized something. There is two if statements because it outputs at windowSize - 1. So maybe it really does need two if statements to be functional.. – mwf1234 May 20 '15 at 03:54
  • But cool rendition nonetheless. Does cnt++ go up to vector1.size(); or infinity? I'm guessing the size of the vector since it is retained in that for loop. – mwf1234 May 20 '15 at 03:56
  • Nothing in computers goes to infinity :-) The difference between 'i' and 'cnt' is that 'i' acts as a index to your array (which is 0-relative) while cnt is the count of the elements (1-relative). You could actually replace cnt with (i + 1), but that is harder to understand. – Dweeberly May 20 '15 at 14:39
  • Ok so your basically saying `for (int i = 1; i < vector1.size()+1; i++) {`, but cnt++ is more clean and fancy. Do you know why coders put += for adding and -= for subtracting; does it do anything or is it just notation? Thanks – mwf1234 May 22 '15 at 00:12
  • or `for (int i = 1; i <= vector1.size(); i++) {` – mwf1234 May 22 '15 at 00:55
  • Ok, I figured it out. Thanks tho :) – mwf1234 May 22 '15 at 01:11
  • The += and -= notation is just used as a shortcut, most simply use it because it's easier/shorter to type. It's easier to type 'x += 2;' than 'x = x + 2;'. In terms of the for loop, the answer is "sort'a". If you start your for loop at 1 then you have to subtract 1 when you do the sum. C programmers are use to loops beginning at zero and it makes 'sum += vector1[i];' look nicer. Combining += and index compare to 'sum = sum + vector[i - 1];' You want to write you code to look/be as simple as is necessary, but like many things YMMV :-) – Dweeberly May 22 '15 at 01:14
  • coders definitely do. not only that I like its convenience. I was just working on a YAHOO API and the months not days wanted to be fed 00 for Jan to 11 for Dec, so I put user input -1 essentially. It took some back testing with the output and querying, but I got it to work in the end. Hard work and perseverance pays off. – mwf1234 May 22 '15 at 05:21
  • Yes, it does, most of programming is perseverance and it gets easier. There is an old saw that says "We count from 1 and measure from 0". If it helps imagine that you are measuring your distance into the array, that way starting at 0 may feel more natural. Personally, I think the Yahoo API should have used the common 1...12 notation, but creating good APIs is a rare and under practiced art. It's also very common for language APIs to use relative zero notation for such things . – Dweeberly May 22 '15 at 14:22
  • lol yeah they definitely should have.. but it is a coincidence that I was literally debugging that issue whilst we were talking about it. Btw, that is a really good saying ;) – mwf1234 May 22 '15 at 18:20