Adaptive Moving Average
Explanation & Rationale
The Adaptive Moving Average (AMA) strategy dynamically adjusts to market conditions by incorporating an efficiency ratio that measures trend strength relative to volatility. Unlike traditional moving averages, the AMA responds more quickly during strong trends and smooths out noise during sideways markets, making it more adaptive to price changes. This approach helps traders capture meaningful trends while avoiding false signals in choppy or low-volatility environments.
Code
'''Adaptive Moving Average (AMA) Strategy.
Buy when the AMA turns upward.Short when the AMA turns downward.This strategy adjusts dynamically to market volatility using an efficiency ratio.Learn more @ docs.ubacktest.com/examples/moving-averages/ama'''
import pandas as pdimport numpy as np
def calculate_ama(series, window=10, fast_ema=2, slow_ema=30):
# calculate efficiency ratio from price diffs / volatility price_change = abs(series.diff(window)) volatility = series.diff().abs().rolling(window=window).sum()
efficiency_ratio = price_change / volatility.replace(0, np.nan) efficiency_ratio.fillna(0, inplace=True)
smoothing_constant = (efficiency_ratio * (2 / (fast_ema + 1) - 2 / (slow_ema + 1)) + 2 / (slow_ema + 1)) ** 2 ama = series.copy()
# build a series of ama values to correspond with the smoothed ama for i in range(1, len(series)): ama.iloc[i] = ama.iloc[i - 1] + smoothing_constant.iloc[i] * (series.iloc[i] - ama.iloc[i - 1])
return ama
def strategy(data): data['AMA'] = calculate_ama(data['close'])
# Generate signals based on AMA trend data['signal'] = 0 data.loc[data['AMA'].diff() > 0, 'signal'] = 1 # Buy data.loc[data['AMA'].diff() < 0, 'signal'] = -1 # Short
return data