428-backtester/user_data/strategies/SampleStrategy.py
Artemii Peretiachenko 99de26e7f0 Add private Freqtrade scaffold for partner backtesting.
Ship SampleStrategy and Integral workflow scripts without proprietary V15 logic, Pine, or run results.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-02 23:55:44 +02:00

63 lines
2.2 KiB
Python

"""
Minimal sample strategy for the 428 / Integral backtester scaffold.
Replace this file (or add your own under user_data/strategies/) and set
STRATEGY=<ClassName> when running scripts. Defaults in config / compose
point here so a fresh clone backtests without proprietary logic.
"""
from __future__ import annotations
from pandas import DataFrame
from freqtrade.strategy import IStrategy, IntParameter
import talib.abstract as ta
class SampleStrategy(IStrategy):
"""EMA crossover + RSI filter — placeholder only, not a production system."""
INTERFACE_VERSION = 3
timeframe = "15m"
can_short = True
minimal_roi = {"0": 0.04, "60": 0.02, "180": 0.01, "360": 0}
stoploss = -0.03
trailing_stop = False
process_only_new_candles = True
startup_candle_count = 50
buy_rsi = IntParameter(20, 40, default=30, space="buy", optimize=True)
sell_rsi = IntParameter(60, 80, default=70, space="sell", optimize=True)
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
dataframe["ema_fast"] = ta.EMA(dataframe, timeperiod=12)
dataframe["ema_slow"] = ta.EMA(dataframe, timeperiod=26)
dataframe["rsi"] = ta.RSI(dataframe, timeperiod=14)
return dataframe
def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
dataframe.loc[
(dataframe["ema_fast"] > dataframe["ema_slow"])
& (dataframe["rsi"] < self.buy_rsi.value)
& (dataframe["volume"] > 0),
"enter_long",
] = 1
dataframe.loc[
(dataframe["ema_fast"] < dataframe["ema_slow"])
& (dataframe["rsi"] > self.sell_rsi.value)
& (dataframe["volume"] > 0),
"enter_short",
] = 1
return dataframe
def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
dataframe.loc[
(dataframe["ema_fast"] < dataframe["ema_slow"]) & (dataframe["volume"] > 0),
"exit_long",
] = 1
dataframe.loc[
(dataframe["ema_fast"] > dataframe["ema_slow"]) & (dataframe["volume"] > 0),
"exit_short",
] = 1
return dataframe