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
2
from freqtrade.strategy import IStrategy
from pandas_ta import ema
import pandas as pd
import numpy as np
import talib
from typing import Dict, List
from pandas import DataFrame
class GKD_PFE(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
pfe_period = 10 # Lookback period for PFE
pfe_smooth = 5 # EMA smoothing period for PFE
pfe_buy_threshold = 30 # PFE threshold for buy signal
pfe_sell_threshold = -30 # PFE threshold for sell signal
baseline_period = 20 # Period for baseline EMA
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:
# Calculate Polarized Fractal Efficiency (PFE)
dataframe["pfe"] = self.calculate_pfe(dataframe, self.pfe_period)
# Smooth PFE with EMA
dataframe["pfe_smooth"] = ema(dataframe["pfe"], length=self.pfe_smooth)
# Baseline (EMA)
dataframe["baseline"] = ema(dataframe["close"], length=self.baseline_period)
dataframe["baseline_diff"] = dataframe["baseline"].diff()
dataframe["baseline_up"] = dataframe["baseline_diff"] > 0
dataframe["baseline_down"] = dataframe["baseline_diff"] < 0
# 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)
return dataframe
def calculate_pfe(self, dataframe: DataFrame, period: int) -> pd.Series:
# Polarized Fractal Efficiency calculation
close = dataframe["close"]
pfe = pd.Series(0.0, index=dataframe.index)
for i in range(period, len(dataframe)):
# Straight-line distance
price_diff = close.iloc[i] - close.iloc[i - period]
straight_dist = np.sqrt(price_diff**2 + period**2)
# Path length (sum of segment lengths)
path_length = 0
for j in range(i - period + 1, i + 1):
segment_diff = close.iloc[j] - close.iloc[j - 1]
segment_length = np.sqrt(segment_diff**2 + 1)
path_length += segment_length
# PFE calculation
if path_length != 0:
pfe.iloc[i] = 100 * straight_dist / path_length
# Polarize: positive for upward movement, negative for downward
if price_diff < 0:
pfe.iloc[i] = -pfe.iloc[i]
return pfe
def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
# Standard Entry Logic (GKD-C Confirmation)
dataframe.loc[
(dataframe["pfe_smooth"] > self.pfe_buy_threshold) & # PFE indicates strong upward efficiency
(dataframe["baseline_up"]) & # Baseline confirms uptrend
(dataframe["close"] >= dataframe["goldie_min"]) & # Within Goldie Locks Zone
(dataframe["close"] <= dataframe["goldie_max"]),
"enter_long"
] = 1
if self.can_short == True:
dataframe.loc[
(dataframe["pfe_smooth"] < self.pfe_sell_threshold) & # PFE indicates strong downward efficiency
(dataframe["baseline_down"]) & # Baseline confirms downtrend
(dataframe["close"] >= dataframe["goldie_min"]) & # Within Goldie Locks Zone
(dataframe["close"] <= dataframe["goldie_max"]),
"enter_short"
] = 1
return dataframe
def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
# Exit Logic: PFE reverses or crosses neutral zone
dataframe.loc[
(dataframe["pfe_smooth"] < 0), # PFE indicates weakening or downward efficiency
"exit_long"
] = 1
if self.can_short == True:
dataframe.loc[
(dataframe["pfe_smooth"] > 0), # PFE indicates weakening or upward efficiency
"exit_short"
] = 1
return dataframe