Strategy: Adaptive Trend Confirmation Author: Gemini AI Version: 1.3 (Corrected column overlap issue by renaming HA columns)
Timeframe
15m
Direction
Long & Short
Stoploss
-5.0%
Trailing Stop
Yes
ROI
0m: 10000.0%
Interface Version
3
Startup Candles
N/A
Indicators
4
freqtrade/freqtrade-strategies
Strategy 003 author@: Gerald Lonlas github@: https://github.com/freqtrade/freqtrade-strategies
# --- Do not remove these libs ---
import numpy as np
import pandas as pd
from pandas import DataFrame
from freqtrade.strategy import IStrategy
from freqtrade.strategy import DecimalParameter, IntParameter
from functools import reduce
# --- Technical analysis library ---
import talib.abstract as ta
import freqtrade.vendor.qtpylib.indicators as qtpylib
class FutureKamaHaObv(IStrategy):
"""
Strategy: Adaptive Trend Confirmation
Author: Gemini AI
Version: 1.3 (Corrected column overlap issue by renaming HA columns)
Description:
This futures strategy uses a combination of KAMA, Heikin Ashi, and OBV.
- KAMA defines the adaptive trend.
- Heikin Ashi provides smooth momentum-based entry triggers.
- OBV confirms that volume supports the trade direction.
Exits are based on a reversal in the Heikin Ashi candle pattern.
"""
# --- Strategy Configuration ---
INTERFACE_VERSION = 3
timeframe = '15m'
can_short = True
# --- Risk Management ---
stoploss = -0.05 # 5% stop-loss. MUST be optimized.
minimal_roi = {
"0": 100 # Disable ROI, rely on Heikin Ashi exit signal
}
# --- Trailing Stop ---
trailing_stop = True
trailing_stop_positive = 0.015
trailing_stop_positive_offset = 0.03
trailing_only_offset_is_reached = True
# --- Hyperparameters ---
buy_kama_period = IntParameter(20, 80, default=60, space="buy")
buy_obv_sma_period = IntParameter(10, 30, default=20, space="buy")
sell_kama_period = IntParameter(20, 80, default=60, space="sell")
sell_obv_sma_period = IntParameter(10, 30, default=20, space="sell")
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
"""
Adds all necessary indicators to the given DataFrame
"""
# --- Heikin Ashi ---------------
ha_df = qtpylib.heikinashi(dataframe)
# First, rename the Heikin Ashi columns to avoid a name collision
ha_df.rename(columns={'open': 'ha_open', 'high': 'ha_high', 'low': 'ha_low', 'close': 'ha_close'}, inplace=True)
# Now, join the renamed Heikin Ashi dataframe to the main dataframe
dataframe = dataframe.join(ha_df)
# --- Trend Indicator: KAMA ---
dataframe['kama_buy'] = ta.KAMA(dataframe, timeperiod=self.buy_kama_period.value)
dataframe['kama_sell'] = ta.KAMA(dataframe, timeperiod=self.sell_kama_period.value)
# --- Volume Confirmation: OBV ---
dataframe['obv'] = ta.OBV(dataframe)
dataframe['obv_sma_buy'] = ta.SMA(dataframe['obv'], timeperiod=self.buy_obv_sma_period.value)
dataframe['obv_sma_sell'] = ta.SMA(dataframe['obv'], timeperiod=self.sell_obv_sma_period.value)
return dataframe
def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
"""
Based on the populated indicators, combines them to generate entry signals.
"""
# --- Long Entry Conditions ---
long_conditions = [
# 1. Main Trend is UP (Price is above adaptive MA)
(dataframe['close'] > dataframe['kama_buy']),
# 2. Volume confirms bullish pressure (OBV is above its own SMA)
(dataframe['obv'] > dataframe['obv_sma_buy']),
# 3. Heikin Ashi momentum signal: A green candle appears
(qtpylib.crossed_above(dataframe['ha_close'], dataframe['ha_open']))
]
# --- Short Entry Conditions ---
short_conditions = [
# 1. Main Trend is DOWN (Price is below adaptive MA)
(dataframe['close'] < dataframe['kama_sell']),
# 2. Volume confirms bearish pressure (OBV is below its own SMA)
(dataframe['obv'] < dataframe['obv_sma_sell']),
# 3. Heikin Ashi momentum signal: A red candle appears
(qtpylib.crossed_below(dataframe['ha_close'], dataframe['ha_open']))
]
# Combine conditions with 'and'
if long_conditions:
dataframe.loc[
reduce(lambda x, y: x & y, long_conditions),
'enter_long'] = 1
if short_conditions:
dataframe.loc[
reduce(lambda x, y: x & y, short_conditions),
'enter_short'] = 1
return dataframe
def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
"""
Based on the populated indicators, generates custom exit signals.
The exit is a reversal in the Heikin Ashi pattern.
"""
# --- Long Exit Condition: A red HA candle appears ---
long_exit_conditions = [
qtpylib.crossed_below(dataframe['ha_close'], dataframe['ha_open'])
]
# --- Short Exit Condition: A green HA candle appears ---
short_exit_conditions = [
qtpylib.crossed_above(dataframe['ha_close'], dataframe['ha_open'])
]
# Combine conditions
if long_exit_conditions:
dataframe.loc[
reduce(lambda x, y: x & y, long_exit_conditions),
'exit_long'] = 1
if short_exit_conditions:
dataframe.loc[
reduce(lambda x, y: x & y, short_exit_conditions),
'exit_short'] = 1
return dataframe