FRAMA (Fractal Adaptive Moving Average) in Python

Does anyone have this indicator in Python? I can find it for other platforms and languages, but come up empty when it comes to Python.

11 responses

Found one here

Thanks, but it doesn't look complete. There are lines commented out at the bottom where the author doesn't understand what they do.

Well, Ehler's paper isn't really clear on that, 'CurrentBar' isn't defined anywhere. But I might know what these lines mean and the code from github doesn't need them.

Alpha is calculated with 2 consecutive time windows, say N = 5 days. You calculate n1 with the first and n2 with the second 5 day values. For n3 you need the ten days together. If you iterate over a price and look backwards, you won't have 10 values in the beginning. So you can't compute the filter and just set it to the price - that's the 2 lines in my opinion. However, the code on github looks forward, so it always has enough data and doesn't need this.
The results only differ in the lenght: Ehler has more data in the beginning - but that's very boring data because it's just the price.

EDIT:
Actually they have the same lenght, the code from github has the price at the end - that's bad indeed, because as traders we are interested in the most recent values. I've rewritten it to look backwards, the 2 missing lines are at the beginning of the loop.

import numpy as np
from matplotlib import pyplot as plt

# Create input
Length = 10000
x = np.linspace(0,10 * np.pi, Length)
Price = 2 * np.sin(x)
Price[Length//2:Length] += 3
Noise = np.random.randn(Price.shape[0]) # white noise
InputPrice = Price + Noise
batch = 10

# Initialize output before the algorithm
Filt = np.array(InputPrice)

# sequencially calculate all variables and the output
for i in range(0, Length, 1):
# If there's not enough data, Filt is the price - whitch it already is, so just skip
if i < 2 * batch:
continue
# take 2 batches of the input
v1 = InputPrice[i-2*batch:i - batch]
v2 = InputPrice[i - batch:i]

# for the 1st batch calculate N1
H1 = np.max(v1)
L1 = np.min(v1)
N1 = (H1 - L1) / batch

# for the 2nd batch calculate N2
H2 = np.max(v2)
L2 = np.min(v2)
N2 = (H2 - L2) / batch

# for both batches calculate N3
H = np.max([H1, H2])
L = np.min([L1, L2])
N3 = (H - L) / (2 * batch)

# calculate fractal dimension
Dimen = 0
if N1 > 0 and N2 > 0 and N3 > 0:
Dimen = (np.log(N1 + N2) - np.log(N3)) / np.log(2)

# calculate lowpass filter factor
alpha = np.exp(-4.6 * (Dimen) - 1)
alpha = np.max([alpha, 0.1])
alpha = np.min([alpha, 1])

# filter the input data
Filt[i] = alpha * InputPrice[i] + (1 - alpha) * Filt[i-1]
# if currentBar < 2*batch + 1: <--- i dont get what these 2 lines do
# Filt = InputPrice[i]

# Filt = np.append(InputPrice[:batch*2], Filt[:-batch*2])
# plot the result to figure out the difference
# beween it (Filt) and the desired outcome (Price)
plt.plot(Price, color='k')
plt.plot(Filt, color='y', alpha=.5)
plt.show()


Wow, you know your way with this. How difficult would it be to make this work with a dataframe instead of the generated input?

Assuming you have a csv file on your harddrive with a column called 'close' you just change this part

# Create input
Length = 10000
x = np.linspace(0,10 * np.pi, Length)
Price = 2 * np.sin(x)
Price[Length//2:Length] += 3
Noise = np.random.randn(Price.shape[0]) # white noise
InputPrice = Price + Noise


to this

import pandas as pd

df = pd.read_csv('SPY.csv') # if the file isn't in the dir where you run the script, use the full path to the file
Price = df.close
Length = len(df)
InputPrice = Price



I left out the addition of noise, which makes no sense and also isn't part of the original paper...

Or here in research with SPY:

2