Let's say I have a list:
y = ['1', '2', '3', '4','5','6','7','8','9','10']
I want to create a function that calculates the moving n-day average.
So if n
was 5, I would want my code to calculate the first 1-5, add it and find the average, which would be 3.0, then go on to 2-6, calculate the average, which would be 4.0, then 3-7, 4-8, 5-9, 6-10.
I don't want to calculate the first n-1 days, so starting from the nth day, it'll count the previous days.
def moving_average(x:'list of prices', n):
for num in range(len(x)+1):
print(x[num-n:num])
This seems to print out what I want:
[]
[]
[]
[]
[]
['1', '2', '3', '4', '5']
['2', '3', '4', '5', '6']
['3', '4', '5', '6', '7']
['4', '5', '6', '7', '8']
['5', '6', '7', '8', '9']
['6', '7', '8', '9', '10']
However, I don't know how to calculate the numbers inside those lists. Any ideas?
Using Python sum() function len() function is used to calculate the length of the list i.e. the count of data items present in the list. Further, statistics. sum() function is used to calculate the sum of all the data items in the list. Note: average = (sum)/(count).
A simple moving average (SMA) is an arithmetic moving average calculated by adding recent prices and then dividing that figure by the number of time periods in the calculation average.
So, when there's no previous smma value, we're supposed to take the simple moving average of (src,length). The next calculations is according to (smma[1] * (length - 1) + src) / length. smmma[1] being the previous smma value.
An approach that avoids recomputing intermediate sums..
list=range(0,12)
def runs(v):
global runningsum
runningsum+=v
return(runningsum)
runningsum=0
runsumlist=[ runs(v) for v in list ]
result = [ (runsumlist[k] - runsumlist[k-5])/5 for k in range(0,len(list)+1)]
print result
[2,3,4,5,6,7,8,9]
make that runs(int(v)) .. then .. repr( runsumlist[k] - runsumlist[k-5])/5 ) if you ant to carry around numbers a strings..
Alt without the global:
list = [float[x] for x in range(0,12)]
nave = 5
movingave = sum(list[:nave]/nave)
for i in range(len(list)-nave):movingave.append(movingave[-1]+(list[i+nave]-list[i])/nave)
print movingave
be sure to do floating math even if you input values are integers
[2.0,3.0,4.0,5.0,6.0,7.0,8.0,9,0]
There is a great sliding window generator in an old version of the Python docs with itertools
examples:
from itertools import islice
def window(seq, n=2):
"Returns a sliding window (of width n) over data from the iterable"
" s -> (s0,s1,...s[n-1]), (s1,s2,...,sn), ... "
it = iter(seq)
result = tuple(islice(it, n))
if len(result) == n:
yield result
for elem in it:
result = result[1:] + (elem,)
yield result
Using that your moving averages is trivial:
from __future__ import division # For Python 2
def moving_averages(values, size):
for selection in window(values, size):
yield sum(selection) / size
Running this against your input (mapping the strings to integers) gives:
>>> y= ['1', '2', '3', '4','5','6','7','8','9','10']
>>> for avg in moving_averages(map(int, y), 5):
... print(avg)
...
3.0
4.0
5.0
6.0
7.0
8.0
To return None
the first n - 1
iterations for 'incomplete' sets, just expand the moving_averages
function a little:
def moving_averages(values, size):
for _ in range(size - 1):
yield None
for selection in window(values, size):
yield sum(selection) / size
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With