The descriptions of technical analysis algorithms are a bit annoying. They are written to calculate a single point, assuming a programming model that is non-vectorized. I really don't get why the algorithms are so poorly described.
Take this description of Money Flow Index as an example.
First off, this:
MoneyFlowIndex = 100 - (100 / (1 + MoneyRatio))
is the same as this:
MoneyFlowIndex = 100 * PositiveMoneyFlow / (PositiveMoneyFlow + NegativeMoneyFlow)
or even:
MoneyFlowIndex = 100 * PositiveMoneyFlow / TotalMoneyFlow
Now we have a formula which works even when NegativeMoneyFlow is zero.
We have just two concepts, PositiveMoneyFlow and TotalMoneyFlow:
pmf = sum(mfi for mfi, reti in zip(mf, returns) if reti > 0) tmf = sum(mf) MoneyFlowIndex = pmf / tmf
where:
typ = [ (p.high + p.low + p.close) / 3 for p in prices ]
vol = [ p.volume for p in prices ]
returns = [ (typ[i] - typ[i-1]) / typ[i-1]
for i in range(1, len(typ)) ]
Okay, we turned a price series into typical prices, created daily returns and money flows from the typical prices, produced the positive money flow and total money flow, and finally got the money flow index. What did it buy us to do it with series like this?
Lots. The original algorithm totally glosses over the fact that we don't want a single money flow index -- we want a time series of money flow indexes. All of the basic series are viewed through a window, and windowing like this makes the basic algorithm really inefficient. The Positive Money Flow for the range 0..n differs in only two places from the range 1..n+1 (pmf[0] drops and pmf[n+1] is added) but a naive implementation will sum the series as if there were no overlap. To do this properly, we need series that have partial sums.
If you want to add up the m-sized windows on data of size n, you can optimize by creating a series that is the running total of the data seen so far and subtracting element[x] from element[x+m] to get the x'th window. You will iterate from 0 to n-m inclusive, giving you n-m+1 windows of size m. Here is how you make your running total:
def runningTotal(series) :
result, s = [0], 0
for ss in series :
s += ss
result.append(s)
return result
Then we can write a summedSeries() function:
def summedSeries (series, length) :
s = runningTotal(series)
for i in xrange(len(s) - length) :
yield s[i + length] - s[i]
and rewrite the Money Flow Index function like this:
pmf = ((mfi if reti > 0 else 0)
for mfi, reti in zip(mf, returns) )
return [ 100.0 * pos/tot for pos, tot in
zip(summedSeries(pmf, n), summedSeries(mf, n)) ]
Now we have an optimized function that works on price and volume time series and returns a Money Flow Index time series. And once you get your head around python, it even feels right.

Leave a comment