forked from artemium/428-backtester
Ship SampleStrategy and Integral workflow scripts without proprietary V15 logic, Pine, or run results. Co-authored-by: Cursor <cursoragent@cursor.com>
63 lines
2.2 KiB
Python
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
|