Timeframe
1h
Direction
Long Only
Stoploss
-10.0%
Trailing Stop
Yes
ROI
0m: 5.0%, 60m: 3.0%, 120m: 1.0%
Interface Version
N/A
Startup Candles
N/A
Indicators
14
from freqtrade.strategy import IStrategy
from pandas_ta import ema, sma, wma, hma, tema, dema, linreg, vwma
import pandas as pd
import numpy as np
import talib
from freqtrade.exchange import timeframe_to_minutes
from typing import Dict, List
from pandas import DataFrame
class GKD_BaselineAllMAs(IStrategy):
# Strategy parameters
timeframe = "1h"
minimal_roi = {"0": 0.05, "60": 0.03, "120": 0.01}
stoploss = -0.10
trailing_stop = True
trailing_stop_positive = 0.02
trailing_stop_positive_offset = 0.03
# Custom parameters
ma_type = "EMA" # Select one of the 64 MAs
ma_period = 20 # Period for the moving average
atr_period = 14 # Period for ATR (volatility filter)
goldie_locks_min = 0.5 # Min multiplier for Goldie Locks Zone
goldie_locks_max = 2.0 # Max multiplier for Goldie Locks Zone
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
# Moving Averages (implementing all 64 as described)
ma_functions = {
"AMA": lambda df, p: self.ama(df, p), # Adaptive Moving Average (placeholder)
"ADXvma": lambda df, p: self.adxvma(df, p), # ADX Volatility MA (placeholder)
"Ahrens": lambda df, p: self.ahrens(df, p), # Ahrens MA
"ALXMA": lambda df, p: wma(df["close"], length=7), # Alexander MA (7-period WMA)
"DSMA": lambda df, p: self.dsma(df, p), # Deviation-Scaled MA (placeholder)
"Donchian": lambda df, p: self.donchian(df, p), # Donchian Midline
"DEMA": lambda df, p: dema(df["close"], length=p),
"DSEMA": lambda df, p: self.dsema(df, p), # Double Smoothed EMA
"DSFEMA": lambda df, p: self.dsfema(df, p), # Double Smoothed Fast EMA
"DSRWEMA": lambda df, p: self.dsrwema(df, p), # Double Smoothed Range Weighted EMA
"DSWEMA": lambda df, p: self.dswema(df, p), # Double Smoothed Wilders EMA
"DWMA": lambda df, p: self.dwma(df, p), # Double Weighted MA
"EOTF": lambda df, p: ema(df["close"], length=p), # Ehlers Optimal Tracking Filter (placeholder)
"EMA": lambda df, p: ema(df["close"], length=p),
"FEMA": lambda df, p: ema(df["close"], length=int(p/2)), # Fast EMA
"FRAMA": lambda df, p: self.frama(df, p), # Fractal Adaptive MA (placeholder)
"GDEMA": lambda df, p: self.gdema(df, p), # Generalized DEMA
"GDDEMA": lambda df, p: self.gddema(df, p), # Generalized Double DEMA
"HMA1": lambda df, p: hma(df["close"], length=p), # Hull MA (SMA-based)
"HMA2": lambda df, p: self.hma_ema(df, p), # Hull MA (EMA-based)
"HMA3": lambda df, p: self.hma_wma(df, p), # Hull MA (WMA-based)
"HMA4": lambda df, p: self.hma_smma(df, p), # Hull MA (SMMA-based)
"IE2": lambda df, p: self.t3(df, p), # Early T3 (T3 implementation)
"ILRS": lambda df, p: self.ilrs(df, p), # Integral of Linear Regression Slope
"Instantaneous": lambda df, p: ema(df["close"], length=p), # Instantaneous Trendline (placeholder)
"Kalman": lambda df, p: self.kalman(df, p), # Kalman Filter (placeholder)
"KAMA": lambda df, p: self.kama(df, p), # Kaufman Adaptive MA
"Laguerre": lambda df, p: self.laguerre(df, p), # Laguerre Filter
"Leader": lambda df, p: self.leader_ema(df, p), # Leader EMA
"LSMA": lambda df, p: linreg(df["close"], length=p), # Linear Regression MA
"LWMA": lambda df, p: wma(df["close"], length=p), # Linear Weighted MA
"McGinley": lambda df, p: self.mcginley(df, p), # McGinley Dynamic
"McNicholl": lambda df, p: ema(df["close"], length=p), # McNicholl EMA (placeholder)
"NonLag": lambda df, p: self.nonlag(df, p), # Non-Lag MA
"ONMAMA": lambda df, p: ema(df["close"], length=p), # Ocean NMA (placeholder)
"OMA": lambda df, p: self.oma(df, p), # One More MA
"Parabolic": lambda df, p: self.parabolic_wma(df, p), # Parabolic Weighted MA
"PDFMA": lambda df, p: self.pdfma(df, p), # Probability Density Function MA
"QRMA": lambda df, p: self.qrma(df, p), # Quadratic Regression MA
"REMA": lambda df, p: self.rema(df, p), # Regularized EMA
"RWEMA": lambda df, p: self.rwema(df, p), # Range Weighted EMA
"Recursive": lambda df, p: self.recursive(df, p), # Recursive Moving Trendline
"SDEC": lambda df, p: self.sdec(df, p), # Simple Decycler
"SJMA": lambda df, p: ema(df["close"], length=p), # Simple Jurik MA (placeholder)
"SMA": lambda df, p: sma(df["close"], length=p),
"Sine": lambda df, p: self.sine_wma(df, p), # Sine Weighted MA
"SLWMA": lambda df, p: self.slwma(df, p), # Smoothed LWMA
"SMMA": lambda df, p: self.smma(df, p), # Smoothed MA
"Smoother": lambda df, p: self.smoother(df, p), # Smoother
"SuperSmoother": lambda df, p: self.super_smoother(df, p), # Super Smoother
"T3": lambda df, p: self.t3(df, p), # T3 MA
"ThreePoleButterworth": lambda df, p: self.three_pole_butterworth(df, p), # 3-Pole Butterworth
"ThreePoleSmoother": lambda df, p: self.three_pole_smoother(df, p), # 3-Pole Smoother
"TMA": lambda df, p: self.tma(df, p), # Triangular MA
"TEMA": lambda df, p: tema(df["close"], length=p), # Triple EMA
"TwoPoleButterworth": lambda df, p: self.two_pole_butterworth(df, p), # 2-Pole Butterworth
"TwoPoleSmoother": lambda df, p: self.two_pole_smoother(df, p), # 2-Pole Smoother
"VIDYA": lambda df, p: self.vidya(df, p), # Variable Index Dynamic Average
"VMA": lambda df, p: self.vma(df, p), # Variable MA
"VEMA": lambda df, p: self.vema(df, p), # Volume Weighted EMA
"VWMA": lambda df, p: vwma(df["close"], df["volume"], length=p), # Volume Weighted MA
"ZeroLagDEMA": lambda df, p: self.zero_lag_dema(df, p), # Zero-Lag DEMA
"ZeroLagMA": lambda df, p: self.zero_lag_ma(df, p), # Zero-Lag MA
"ZeroLagTEMA": lambda df, p: self.zero_lag_tema(df, p), # Zero-Lag TEMA
}
# Apply selected MA
if self.ma_type in ma_functions:
dataframe["baseline"] = ma_functions[self.ma_type](dataframe, self.ma_period)
else:
raise ValueError(f"MA type {self.ma_type} not implemented")
# Volatility (ATR for Goldie Locks Zone)
dataframe["atr"] = talib.ATR(
dataframe["high"], dataframe["low"], dataframe["close"], timeperiod=self.atr_period
)
dataframe["goldie_min"] = dataframe["baseline"] - (dataframe["atr"] * self.goldie_locks_min)
dataframe["goldie_max"] = dataframe["baseline"] + (dataframe["atr"] * self.goldie_locks_max)
# Price crossover signals
dataframe["price_above"] = dataframe["close"] > dataframe["baseline"]
dataframe["price_below"] = dataframe["close"] < dataframe["baseline"]
return dataframe
# Custom MA Implementations (simplified or placeholders)
def ama(self, df, period):
# Placeholder: Adaptive MA based on volatility
return ema(df["close"], length=period)
def adxvma(self, df, period):
# Placeholder: ADX-based volatility MA
adx = talib.ADX(df["high"], df["low"], df["close"], timeperiod=period)
return ema(df["close"], length=period) * (adx / 100)
def ahrens(self, df, period):
# Ahrens MA: Uses open and close
return (df["open"] + df["close"]).rolling(window=period).mean() / 2
def dsma(self, df, period):
# Deviation-Scaled MA: Adjusts EMA based on standard deviation
std = df["close"].rolling(period).std()
alpha = 2 / (1 + period) * (std / std.mean())
return df["close"].ewm(alpha=alpha, adjust=False).mean()
def donchian(self, df, period):
# Donchian Midline: (High + Low) / 2
high = df["high"].rolling(window=period).max()
low = df["low"].rolling(window=period).min()
return (high + low) / 2
def dsema(self, df, period):
# Double Smoothed EMA
ema1 = ema(df["close"], length=period)
return ema(ema1, length=period)
def dsfema(self, df, period):
# Double Smoothed Fast EMA
ema1 = ema(df["close"], length=int(period/2))
return ema(ema1, length=int(period/2))
def dsrwema(self, df, period):
# Double Smoothed Range Weighted EMA
range_weight = (df["high"] - df["low"]).rolling(window=period).mean()
weighted_price = df["close"] * range_weight
ema1 = ema(weighted_price, length=period)
return ema(ema1, length=period)
def dswema(self, df, period):
# Double Smoothed Wilders EMA
wilder_period = period * 2 - 1
ema1 = ema(df["close"], length=wilder_period)
return ema(ema1, length=wilder_period)
def dwma(self, df, period):
# Double Weighted MA
wma1 = wma(df["close"], length=period)
return wma(wma1, length=period)
def frama(self, df, period):
# Placeholder: Fractal Adaptive MA
return ema(df["close"], length=period)
def gdema(self, df, period, vol_factor=0.5):
# Generalized DEMA
ema1 = ema(df["close"], length=period)
ema2 = ema(ema1, length=period)
return (1 + vol_factor) * ema1 - vol_factor * ema2
def gddema(self, df, period):
# Generalized Double DEMA
gdema1 = self.gdema(df, period)
return self.gdema(pd.Series(gdema1), period)
def hma_ema(self, df, period):
# Hull MA with EMA smoothing
wma1 = wma(df["close"], length=int(period/2)) * 2
wma2 = wma(df["close"], length=period)
raw_hma = wma1 - wma2
return ema(raw_hma, length=int(np.sqrt(period)))
def hma_wma(self, df, period):
# Hull MA with WMA smoothing
wma1 = wma(df["close"], length=int(period/2)) * 2
wma2 = wma(df["close"], length=period)
raw_hma = wma1 - wma2
return wma(raw_hma, length=int(np.sqrt(period)))
def hma_smma(self, df, period):
# Hull MA with SMMA smoothing
wma1 = wma(df["close"], length=int(period/2)) * 2
wma2 = wma(df["close"], length=period)
raw_hma = wma1 - wma2
return self.smma(pd.Series(raw_hma), int(np.sqrt(period)))
def t3(self, df, period, v_factor=0.7):
# T3 Moving Average
ema1 = ema(df["close"], length=period)
ema2 = ema(ema1, length=period)
ema3 = ema(ema2, length=period)
c1 = -v_factor ** 3
c2 = 3 * v_factor ** 2 * (1 + v_factor)
c3 = -6 * v_factor ** 2 - 3 * v_factor * (1 + v_factor)
c4 = 1 + 3 * v_factor + v_factor ** 3 + 3 * v_factor ** 2
return c1 * ema3 + c2 * ema2 + c3 * ema1 + c4 * df["close"]
def ilrs(self, df, period):
# Integral of Linear Regression Slope
lsma = linreg(df["close"], length=period)
return lsma.cumsum() / period
def kalman(self, df, period):
# Placeholder: Kalman Filter
return ema(df["close"], length=period)
def kama(self, df, period, fast=2, slow=30):
# Kaufman Adaptive MA
close_diff = df["close"].diff().abs()
signal = close_diff.rolling(window=period).sum()
noise = (df["high"] - df["low"]).rolling(window=period).sum()
er = signal / noise
sc = ((er * (2/(fast+1) - 2/(slow+1)) + 2/(slow+1)) ** 2)
kama = pd.Series(index=df.index)
kama.iloc[period] = df["close"].iloc[period]
for i in range(period + 1, len(df)):
kama.iloc[i] = kama.iloc[i-1] + sc.iloc[i] * (df["close"].iloc[i] - kama.iloc[i-1])
return kama
def laguerre(self, df, period, alpha=0.2):
# Laguerre Filter
l0 = pd.Series(0, index=df.index)
l1 = pd.Series(0, index=df.index)
l2 = pd.Series(0, index=df.index)
l3 = pd.Series(0, index=df.index)
for i in range(1, len(df)):
l0.iloc[i] = (1 - alpha) * df["close"].iloc[i] + alpha * l0.iloc[i-1]
l1.iloc[i] = -alpha * l0.iloc[i] + l0.iloc[i-1] + alpha * l1.iloc[i-1]
l2.iloc[i] = -alpha * l1.iloc[i] + l1.iloc[i-1] + alpha * l2.iloc[i-1]
l3.iloc[i] = -alpha * l2.iloc[i] + l2.iloc[i-1] + alpha * l3.iloc[i-1]
return (l0 + 2 * l1 + 2 * l2 + l3) / 6
def leader_ema(self, df, period):
# Leader EMA (simplified)
return ema(df["close"], length=period)
def mcginley(self, df, period):
# McGinley Dynamic
mg = pd.Series(df["close"].iloc[0], index=df.index)
for i in range(1, len(df)):
mg.iloc[i] = mg.iloc[i-1] + (df["close"].iloc[i] - mg.iloc[i-1]) / (period * (df["close"].iloc[i] / mg.iloc[i-1]) ** 4)
return mg
def nonlag(self, df, period):
# Non-Lag MA (simplified)
return ema(df["close"], length=int(period/2))
def oma(self, df, period):
# One More MA (simplified Jurik-style)
ema1 = ema(df["close"], length=period)
ema2 = ema(ema1, length=period)
return ema(ema2, length=period)
def parabolic_wma(self, df, period, power=2):
# Parabolic Weighted MA
weights = np.array([((i+1)/period)**power for i in range(period)])
weights = weights / weights.sum()
return df["close"].rolling(window=period).apply(lambda x: np.sum(x * weights), raw=True)
def pdfma(self, df, period):
# Probability Density Function MA
weights = np.exp(-np.linspace(-2, 2, period)**2)
weights = weights / weights.sum()
return df["close"].rolling(window=period).apply(lambda x: np.sum(x * weights), raw=True)
def qrma(self, df, period):
# Quadratic Regression MA
x = np.arange(period)
def quad_reg(y):
coeffs = np.polyfit(x, y, 2)
return np.polyval(coeffs, period-1)
return df["close"].rolling(window=period).apply(quad_reg, raw=True)
def rema(self, df, period):
# Regularized EMA
alpha = 2 / (period + 1)
return ema(df["close"], length=period) * (1 + alpha)
def rwema(self, df, period):
# Range Weighted EMA
range_weight = (df["high"] - df["low"]).rolling(window=period).mean()
return ema(df["close"] * range_weight, length=period) / ema(range_weight, length=period)
def recursive(self, df, period):
# Recursive Moving Trendline (simplified)
return linreg(df["close"], length=period)
def sdec(self, df, period):
# Simple Decycler
return df["close"] - ema(df["close"], length=period)
def slwma(self, df, period):
# Smoothed LWMA
lwma1 = wma(df["close"], length=period)
return ema(lwma1, length=period)
def smma(self, df, period):
# Smoothed MA
smma = pd.Series(index=df.index)
smma.iloc[period-1] = df["close"].iloc[:period].mean()
for i in range(period, len(df)):
smma.iloc[i] = (smma.iloc[i-1] * (period - 1) + df["close"].iloc[i]) / period
return smma
def smoother(self, df, period):
# Smoother
return ema(df["close"], length=int(period/2))
def super_smoother(self, df, period):
# Super Smoother (simplified)
a = np.exp(-1.414 * np.pi / period)
b = 2 * a * np.cos(1.414 * np.pi / period)
c = a * a
d = 1 - b - c
ss = pd.Series(0, index=df.index)
for i in range(2, len(df)):
ss.iloc[i] = d * df["close"].iloc[i] + b * ss.iloc[i-1] + c * ss.iloc[i-2]
return ss
def three_pole_butterworth(self, df, period):
# 3-Pole Butterworth
a = np.exp(-np.pi / period)
b = 2 * a * np.cos(1.738 * np.pi / period)
c = a * a
d = 1 - b - c
butter = pd.Series(0, index=df.index)
for i in range(3, len(df)):
butter.iloc[i] = d * df["close"].iloc[i] + b * butter.iloc[i-1] + c * butter.iloc[i-2]
return butter
def three_pole_smoother(self, df, period):
# 3-Pole Smoother
return self.three_pole_butterworth(df, period) * 1.1 # Slightly adjusted
def tma(self, df, period):
# Triangular MA
sma1 = sma(df["close"], length=period)
return sma(sma1, length=period)
def two_pole_butterworth(self, df, period):
# 2-Pole Butterworth
a = np.exp(-np.pi / period)
b = 2 * a * np.cos(1.414 * np.pi / period)
c = a * a
d = 1 - b - c
butter = pd.Series(0, index=df.index)
for i in range(2, len(df)):
butter.iloc[i] = d * df["close"].iloc[i] + b * butter.iloc[i-1] + c * butter.iloc[i-2]
return butter
def two_pole_smoother(self, df, period):
# 2-Pole Smoother
return self.two_pole_butterworth(df, period) * 1.05 # Slightly adjusted
def vidya(self, df, period):
# Variable Index Dynamic Average
cmo = talib.CMO(df["close"], timeperiod=period)
alpha = 2 / (period + 1) * (cmo / 100)
vidya = pd.Series(df["close"].iloc[0], index=df.index)
for i in range(1, len(df)):
vidya.iloc[i] = alpha.iloc[i] * df["close"].iloc[i] + (1 - alpha.iloc[i]) * vidya.iloc[i-1]
return vidya
def vma(self, df, period):
# Variable MA (simplified)
return ema(df["close"], length=period)
def vema(self, df, period):
# Volume Weighted EMA
vol_price = df["close"] * df["volume"]
return ema(vol_price, length=period) / ema(df["volume"], length=period)
def zero_lag_dema(self, df, period):
# Zero-Lag DEMA
ema1 = ema(df["close"], length=period)
lag = ema1.shift(period)
return 2 * ema1 - lag
def zero_lag_ma(self, df, period):
# Zero-Lag MA
ema1 = ema(df["close"], length=period)
lag = ema1.shift(period)
return 2 * ema1 - lag
def zero_lag_tema(self, df, period):
# Zero-Lag TEMA
tema1 = tema(df["close"], length=period)
lag = tema1.shift(period)
return 2 * tema1 - lag
def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
# Baseline Entry Logic
dataframe.loc[
(dataframe["price_above"].shift(1) == False) &
(dataframe["price_above"]) &
(dataframe["close"] >= dataframe["goldie_min"]) &
(dataframe["close"] <= dataframe["goldie_max"]),
"enter_long"
] = 1
dataframe.loc[
(dataframe["price_below"].shift(1) == False) &
(dataframe["price_below"]) &
(dataframe["close"] >= dataframe["goldie_min"]) &
(dataframe["close"] <= dataframe["goldie_max"]),
"enter_short"
] = 1
return dataframe
def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
# Exit Logic
dataframe.loc[dataframe["price_below"], "exit_long"] = 1
dataframe.loc[dataframe["price_above"], "exit_short"] = 1
return dataframe