💬 Forum

ZaratustraV3

🏆 League #34 / 1909

remiotore/ccxt-freqtrade/my-strategies/ZaratustraV3.py · ★3 · ⑂2 · first seen 2026-07-16 · repo updated 2026-01-11

Basics mode: futures timeframe: 15m interface version: 3
Settings stoploss: -0.296 has minimal roi trailing
Indicators MACD pandas_ta talib technical
Concepts trailing
Methods leverage
15 related strategies ( identical code, similar name)

Each tile is a different kind of check — from an instant code lint to full sandboxed backtests and forward tests on recent data. Not sure what a check actually proves? See the FAQ →

Source

Download Raw
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
# By Remiotore (Jorge F. F.)
# Espero poder darte una buena vida algún día...

# pragma pylint: disable=missing-docstring, invalid-name, pointless-string-statement
# flake8: noqa: F401
# isort: skip_file
# --- Do not remove these imports ---
import numpy as np
import pandas as pd
from datetime import datetime, timedelta, timezone
from pandas import DataFrame
from typing import Dict, Optional, Union, Tuple
from freqtrade.strategy import (
    IStrategy,
    #Trade,
    #Order,
    #PairLocks,
    #informative,
    #BooleanParameter,
    #CategoricalParameter,
    #DecimalParameter,
    #IntParameter,
    #RealParameter,
    #timeframe_to_minutes,
    #timeframe_to_next_date,
    #timeframe_to_prev_date,
    #merge_informative_pair,
    #stoploss_from_absolute,
    #stoploss_from_open,
)
# --------------------------------
# Add your lib to import here
import talib.abstract as ta
import pandas_ta as pta
from technical import qtpylib


class ZaratustraV3(IStrategy):
    INTERFACE_VERSION = 3
    timeframe = '15m'
    can_short = True
    use_exit_signal = True
    exit_profit_only = True
    exit_profit_offset = 0.05

    # ROI table:
    minimal_roi = {
        '0': 0.30,
        '109': 0.13,
        '267': 0.04,
        '428': 0.02,
        '720': 0.00,
    }

    # Stoploss:
    stoploss = -0.296

    # Trailing stop:
    trailing_stop = True
    trailing_stop_positive = 0.011
    trailing_stop_positive_offset = 0.071
    trailing_only_offset_is_reached = True
    
    def leverage(self, pair: str, current_time: datetime, current_rate: float, proposed_leverage: float, max_leverage: float, entry_tag: Optional[str], side: str, **kwargs) -> float:
        return 10.0

    def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        macd = ta.MACD(dataframe)
        dataframe['macd'] = macd['macd']
        dataframe['signal'] = macd['macdsignal']

        dataframe['max'] = (dataframe['close'] == dataframe['close'].rolling(15).max()).astype(int)
        dataframe['min'] = (dataframe['close'] == dataframe['close'].rolling(15).min()).astype(int)

        dataframe['max_check'] = dataframe['max'].rolling(5).apply(lambda x: x.all(), raw=True).fillna(0).astype(int)
        dataframe['min_check'] = dataframe['min'].rolling(5).apply(lambda x: x.all(), raw=True).fillna(0).astype(int)

        return dataframe
    
    def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        dataframe.loc[
            (
                (dataframe['macd']   > 0) &
                (dataframe['signal'] > 0) &
                (dataframe['macd']   > dataframe['signal']) &
                (dataframe['max_check'] == 0)
            ),
            ['enter_long', 'enter_tag']
        ] = (1, 'High RSI extrema')

        dataframe.loc[
            (
                (dataframe['macd']   < 0) &
                (dataframe['signal'] < 0) &
                (dataframe['macd']   < dataframe['signal']) &
                (dataframe['min_check'] == 0)
            ),
            ['enter_short', 'enter_tag']
        ] = (1, 'Low RSI extrema')
        
        return dataframe
    
    def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        dataframe.loc[
            (
                (dataframe['max_check'].shift(1) == 1) &
                (dataframe['max_check'] == 0)
            ),
            ['exit_long', 'exit_tag']
        ] = (1, 'Max detected')
        
        dataframe.loc[
            (
                (dataframe['min_check'].shift(1) == 1) &
                (dataframe['min_check'] == 0)
            ),
            ['exit_short', 'exit_tag']
        ] = (1, 'Min detected')
        
        return dataframe