Mar-26-2025, 10:01 PM
(This post was last modified: Mar-27-2025, 06:40 PM by deanhystad.)
Seems like you're calculation is backwards. I think this is what you are doing:
If you look at the calculation, cma = sum_clovol / sum volume. Doing the calculations in the order above doesn't make use of clovol or volume data sums already collected. However, if you compute the values in reverse order:
cma[7] = clovol[7] / volume[7]
cma[6, 7] = (clovol[7] + clovol[6]) / (volumn[7] + volume[6])
cma[5, 6, 7] = (clovol[7] + clovol[6] + clovol[5]) / (volumn[7] + volume[6] + volume[5])
You can see that we can compute the next sums using the sum we just calculated.
cma[N] = (clovol_sum(N+1) + clovol[N]) / (volume_sum(N + 1) + volume[N])
This can be written in Python as:
I would use numpy to do the calculations in C because python loops are slow and numpy has functions for computing cumulative sums and can supports element-wise array multiplication.
1000 points
loop in loop time = 16.6 seconds
backward loop time = 0.006 seconds
numpy time = 0.0009 seconds
I started running a test for 10,000 points. After 10 minutes I stopped the test. A rough calculation extrapolating 16.6 seconds for 1000 points returned a time of 1.8 days to calculate 10,000 points.
10,000 points
loop in loop time = 1.8 days (estimated)
backward loop time = 0.017 seconds
numpy time = 0.0019 seconds
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
price = [ 1 , 3 , 5 , 7 , 11 , 13 , 17 ] volume = [ 1 , 1 , 2 , 3 , 5 , 8 , 13 ] def cma_calc(price, volume, start = 0 ): total_clovol = 0 total_volume = 0 for p, v in zip (price[start:], volume[start:]): clovol = p * v total_clovol + = clovol total_volume + = v return total_clovol / total_volume cma = [] for start in range ( len (price)): cma.append(cma_calc(price, volume, start)) print (cma) |
Output:[12.575757575757576, 12.9375, 13.258064516129032, 13.827586206896552, 14.615384615384615, 15.476190476190476, 17.0]
It is very inefficient because you keep computing the cma over and over again for the same data. Computing cma for the 7 points above takes 7 + 6 + 5 + 4 + 3 + 2 + 1 = 28 calculations. The number grows quickly. 1000 points takes 499500 calculations.If you look at the calculation, cma = sum_clovol / sum volume. Doing the calculations in the order above doesn't make use of clovol or volume data sums already collected. However, if you compute the values in reverse order:
cma[7] = clovol[7] / volume[7]
cma[6, 7] = (clovol[7] + clovol[6]) / (volumn[7] + volume[6])
cma[5, 6, 7] = (clovol[7] + clovol[6] + clovol[5]) / (volumn[7] + volume[6] + volume[5])
You can see that we can compute the next sums using the sum we just calculated.
cma[N] = (clovol_sum(N+1) + clovol[N]) / (volume_sum(N + 1) + volume[N])
This can be written in Python as:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
price = [ 1 , 3 , 5 , 7 , 11 , 13 , 17 ] volume = [ 1 , 1 , 2 , 3 , 5 , 8 , 13 ] def cma_calc_2(price, volume): clovol_sum = 0 volume_sum = 0 cma = [] for p, v in zip (price[:: - 1 ], volume[:: - 1 ]): # Loop backward through the price and volume data clovol_sum + = p * v volume_sum + = v cma.append(clovol_sum / volume_sum) # reverse order of the cma back to the original data return cma[:: - 1 ] print (cma_calc_2(price, volume)) |
Output:[12.575757575757576, 12.9375, 13.258064516129032, 13.827586206896552, 14.615384615384615, 15.476190476190476, 17.0]
The results are the same, but this code only requires 7 calculations to compute 7 cma values. 1000 points takes 1000 calculations, a 98% reduction over the loop in loop solution.I would use numpy to do the calculations in C because python loops are slow and numpy has functions for computing cumulative sums and can supports element-wise array multiplication.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
import numpy as np price = [ 1 , 3 , 5 , 7 , 11 , 13 , 17 ] volume = [ 1 , 1 , 2 , 3 , 5 , 8 , 13 ] def cma_calc_3(price, volume): price = np.flip(np.array(price)) volume = np.flip(np.array(volume)) clovol = price * volume clovol_sum = np.cumsum(clovol) volume_sum = np.cumsum(volume) cma = clovol_sum / volume_sum return np.flip(cma) print (cma_calc_3(price, volume)) |
Output:[12.57575758 12.9375 13.25806452 13.82758621 14.61538462 15.47619048 17. ]
I did some timing of all three algorithms. For 1000 points of data:1000 points
loop in loop time = 16.6 seconds
backward loop time = 0.006 seconds
numpy time = 0.0009 seconds
I started running a test for 10,000 points. After 10 minutes I stopped the test. A rough calculation extrapolating 16.6 seconds for 1000 points returned a time of 1.8 days to calculate 10,000 points.
10,000 points
loop in loop time = 1.8 days (estimated)
backward loop time = 0.017 seconds
numpy time = 0.0019 seconds