Materialized paper candidate for the Harness trend_pullback_reversion winner.
Timeframe
1h
Direction
Long & Short
Stoploss
-12.0%
Trailing Stop
No
ROI
0m: 8.0%, 24m: 3.0%, 48m: 0.0%
Interface Version
N/A
Startup Candles
72
Indicators
0
freqtrade/freqtrade-strategies
freqtrade/freqtrade-strategies
freqtrade/freqtrade-strategies
this is an example class, implementing a PSAR based trailing stop loss you are supposed to take the `custom_stoploss()` and `populate_indicators()` parts and adapt it to your own strategy
freqtrade/freqtrade-strategies
from __future__ import annotations
from datetime import timedelta
from freqtrade.persistence import Trade
from freqtrade.strategy import IStrategy
from pandas import DataFrame
class TrendPullbackReversionGridL48Z125H24C6(IStrategy):
"""Materialized paper candidate for the Harness trend_pullback_reversion winner.
This is a Freqtrade dry-run artifact for paper certification. It mirrors the
low-turnover z-score recovery candidate that the Harness found inside
liquid-trend contexts, but it does not replace MarketContext/Risk Auditor
gating in QuantOdyssey.
"""
timeframe = "1h"
startup_candle_count = 72
can_short = True
process_only_new_candles = True
stoploss = -0.12
minimal_roi = {"0": 0.08, "24": 0.03, "48": 0}
lookback_bars = 48
entry_zscore = 1.25
horizon_bars = 24
cooldown_bars = 6
min_trend_abs_return = 0.015
protections = [
{
"method": "CooldownPeriod",
"stop_duration_candles": cooldown_bars,
}
]
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
close = dataframe["close"]
rolling_mean = close.rolling(self.lookback_bars).mean()
rolling_std = close.rolling(self.lookback_bars).std(ddof=0)
dataframe["qo_center"] = rolling_mean
dataframe["qo_zscore"] = (close - rolling_mean) / rolling_std.replace(0, float("nan"))
dataframe["qo_trend_return"] = close / close.shift(self.lookback_bars) - 1
dataframe["qo_liquid_trend_proxy"] = dataframe["qo_trend_return"].abs() >= self.min_trend_abs_return
return dataframe
def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
base = dataframe["qo_liquid_trend_proxy"] & (dataframe["volume"] > 0)
dataframe.loc[
base & (dataframe["qo_zscore"] <= -self.entry_zscore),
"enter_long",
] = 1
dataframe.loc[
base & (dataframe["qo_zscore"] >= self.entry_zscore),
"enter_short",
] = 1
return dataframe
def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
dataframe.loc[dataframe["qo_zscore"] >= 0, "exit_long"] = 1
dataframe.loc[dataframe["qo_zscore"] <= 0, "exit_short"] = 1
return dataframe
def custom_exit(
self,
pair: str,
trade: Trade,
current_time,
current_rate: float,
current_profit: float,
**kwargs,
):
if current_time - trade.open_date_utc >= timedelta(hours=self.horizon_bars):
return "horizon_exit"
return None