Timeframe
4h
Direction
Long Only
Stoploss
-10.0%
Trailing Stop
No
ROI
N/A
Interface Version
N/A
Startup Candles
N/A
Indicators
3
freqtrade/freqtrade-strategies
This strategy uses custom_stoploss() to enforce a fixed risk/reward ratio by first calculating a dynamic initial stoploss via ATR - last negative peak
freqtrade/freqtrade-strategies
Strategy 003 author@: Gerald Lonlas github@: https://github.com/freqtrade/freqtrade-strategies
freqtrade/freqtrade-strategies
from freqtrade.strategy import (BooleanParameter, CategoricalParameter, DecimalParameter,
IStrategy, IntParameter, RealParameter, merge_informative_pair, informative)
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_FisherTransform(IStrategy):
# Strategy parameters
timeframe = "4h"
minimal_roi = {}
stoploss = -0.10
trailing_stop = False
trailing_stop_positive = 0.02
trailing_stop_positive_offset = 0.03
# Custom parameters
fisher_period = IntParameter(10, 15, default=12, space="buy") # Lookback period for Fisher Transform
fisher_smooth = IntParameter(5, 10, default=8, space="buy") # EMA smoothing period for Fisher Transform
fisher_sell_threshold = DecimalParameter(2.0, 3.9, default=2.5, decimals=2, space="sell")
fisher_buy_threshold = DecimalParameter(-1.0, 2.5, default=-0.5, decimals=2, space="buy")
baseline_period = IntParameter(5, 21, default=21, space="buy") # Period for baseline EMA
atr_period = IntParameter(10, 21, default=14, space="buy") # Period for ATR (volatility filter)
goldie_locks = DecimalParameter(1.5, 3.0, default=2.0, decimals=2, space="buy") # Max multiplier for Goldie Locks Zone
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
# Calculate Fisher Transform
dataframe["fisher"] = self.calculate_fisher(dataframe, self.fisher_period.value)
# Smooth Fisher with EMA
dataframe["fisher_smooth"] = ema(dataframe["fisher"], length=self.fisher_smooth.value)
dataframe["fisher_trend"] = ema(dataframe["fisher_smooth"], length=21)
# Baseline (EMA)
dataframe["baseline"] = ema(dataframe["close"], length=self.baseline_period.value)
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.value
)
dataframe["goldie_min"] = dataframe["baseline"] - (dataframe["atr"] * self.goldie_locks.value)
dataframe["goldie_max"] = dataframe["baseline"] + (dataframe["atr"] * self.goldie_locks.value)
return dataframe
def calculate_fisher(self, dataframe: DataFrame, period: int) -> pd.Series:
# Fisher Transform calculation
median_price = (dataframe["high"] + dataframe["low"]) / 2
fisher = pd.Series(0.0, index=dataframe.index)
for i in range(period, len(dataframe)):
# Normalize price
price_window = median_price.iloc[i-period:i]
price_min = price_window.min()
price_max = price_window.max()
if price_max != price_min:
norm = (median_price.iloc[i] - price_min) / (price_max - price_min)
norm = 2 * norm - 1 # Scale to [-0.999, 0.999]
norm = max(min(norm, 0.999), -0.999) # Prevent division by zero
# Apply Fisher Transform
fisher.iloc[i] = 0.5 * np.log((1 + norm) / (1 - norm))
else:
fisher.iloc[i] = 0.0
return fisher
def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
# Standard Entry Logic (GKD-C Confirmation)
dataframe.loc[
# (dataframe["fisher_smooth"] > self.fisher_buy_threshold.value) &
# (dataframe["fisher_smooth"] < self.fisher_sell_threshold.value) &
# (dataframe["fisher_smooth"] > 0) &
# (dataframe["fisher_smooth"].shift() < -0) &
(dataframe["fisher"] < self.fisher_sell_threshold.value) &
(dataframe["fisher_smooth"] < dataframe['fisher']), # &
# Fisher indicates bullish reversal
# (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["fisher_smooth"] < self.fisher_sell_threshold.value) & # Fisher indicates bearish reversal
(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: Fisher reverses or crosses neutral zone
dataframe.loc[
(
(dataframe["fisher_smooth"].shift() > 0) &
(dataframe["fisher_smooth"] < 0) &
(dataframe["fisher_smooth"] > dataframe['fisher'])
), # Fisher indicates weakening or bearish reversal
"exit_long"
] = 1
# dataframe.loc[
# (
# (dataframe["fisher_smooth"] < self.fisher_buy_threshold.value)
# ), # Fisher indicates weakening or bearish reversal
# "exit_long"
# ] = 1
if self.can_short == True:
dataframe.loc[
(dataframe["fisher_smooth"] > 0), # Fisher indicates weakening or bullish reversal
"exit_short"
] = 1
return dataframe
# 193/1000: 358 trades. 190/25/143 Wins/Draws/Losses. Avg profit 0.87%. Median profit 0.17%. Total profit 31413.09084858 USDT ( 157.07%). Avg duration 23:52:00 min. Objective: -31413.09085
# # Buy hyperspace params:
# buy_params = {
# "atr_period": 21,
# "baseline_period": 16,
# "fisher_buy_threshold": -3.5,
# "fisher_period": 12,
# "fisher_smooth": 8,
# "goldie_locks": 1.61,
# }
# # Sell hyperspace params:
# sell_params = {
# "fisher_sell_threshold": 3.74,
# }
# # ROI table:
# minimal_roi = {
# "0": 1.035,
# "1166": 0.25,
# "2510": 0.176,
# "3562": 0
# }
# # Stoploss:
# stoploss = -0.21
# # Trailing stop:
# trailing_stop = True
# trailing_stop_positive = 0.011
# trailing_stop_positive_offset = 0.045
# trailing_only_offset_is_reached = False
# # Max Open Trades:
# max_open_trades = 3
# 248/1000: 298 trades. 176/0/122 Wins/Draws/Losses. Avg profit 0.81%. Median profit 2.48%. Total profit 21364.22232610 USDT ( 106.82%). Avg duration 1 day, 2:44:00 min. Objective: -21364.22233
# # Buy hyperspace params:
# buy_params = {
# "atr_period": 5,
# "baseline_period": 9,
# "fisher_buy_threshold": -2.86,
# "fisher_period": 9,
# "fisher_smooth": 9,
# "goldie_locks": 2.38,
# }
# # Sell hyperspace params:
# sell_params = {
# "fisher_sell_threshold": 0.23,
# }
# # ROI table:
# minimal_roi = {
# "0": 1.234,
# "2209": 0.438,
# "3223": 0.166,
# "12718": 0
# }
# # Stoploss:
# stoploss = -0.22
# # Trailing stop:
# trailing_stop = True
# trailing_stop_positive = 0.01
# trailing_stop_positive_offset = 0.034
# trailing_only_offset_is_reached = False
# # Max Open Trades:
# max_open_trades = 3