Back to Community
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.

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:  
    # 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)  

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:

Loading notebook preview...

I've corrected some errors in the github code and made a new function that uses pandas and can calculate FRAMA for several symbols at once

Loading notebook preview...

Thats fantastic. Thanks for taking the time to sort out the errors and making this work here and with external data sources, really appreciate it.

I've been experimenting with this indicator and came across a modified version from the creator, Ehlers. This website explains it better and includes the format. Is adding the ability to set a fast or slow MA a difficult thing to include in this code?

@Tentor Testivis - Would you mind posting this as an algorithm for SPY, buying when above the yellow line and shorting when below?

Thank you in advance!