# source: https://raw.githubusercontent.com/ncu571633/finance/b5f9c503c7f07fa9ecef4de4c949e84d7f04c978/freqtrade-bot/user_data/strategies/BTCETHSwing.py
# directory_url: https://github.com/ncu571633/finance/blob/main/freqtrade-bot/user_data/strategies/
# User: ncu571633
# Repository: finance
# --------------------# Github_ncu571633_finance__BTCETHSwing__20260923_000635 — a multi-day "swing" momentum strategy for BTC + ETH (4h timeframe).
#
# Motivation: academic work on crypto (Liu & Tsyvinski 2021; Liu, Tsyvinski & Wu 2022)
# finds a robust TIME-SERIES MOMENTUM effect at ~1-4 week horizons, and that it works
# best in LARGE coins (BTC/ETH). That is neither intraday (noise, fees) nor months-long
# (the daily 200-SMA). This targets that middle "hold for days to ~2 weeks" band.
#
# Logic on the 4h chart:
#   Regime  : only trade long while EMA50 > EMA200  (an uptrend is in force).
#   Hold    : stay long while price is above the EMA50 (the short trend line).
#   Exit    : price closes back below EMA50 (momentum faded) — plus a safety stop.
# Long-only, spot.

from pandas import DataFrame
import talib.abstract as ta

from freqtrade.strategy import IStrategy


class Github_ncu571633_finance__BTCETHSwing__20260923_000635(IStrategy):
    INTERFACE_VERSION = 3

    timeframe = "4h"
    can_short = False

    # Let the trend decide the exit; keep only a loose safety stop. No ROI cap so
    # winners can run for the full multi-day swing.
    minimal_roi = {"0": 100.0}   # effectively off
    stoploss = -0.10             # -10% safety net
    trailing_stop = False

    process_only_new_candles = True
    use_exit_signal = True
    exit_profit_only = False

    # EMA200 on 4h needs 200 candles of warm-up.
    startup_candle_count = 200

    def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        dataframe["ema_fast"] = ta.EMA(dataframe, timeperiod=50)   # ~8 days on 4h
        dataframe["ema_slow"] = ta.EMA(dataframe, timeperiod=200)  # ~33 days on 4h
        return dataframe

    def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        dataframe.loc[
            (
                (dataframe["ema_fast"] > dataframe["ema_slow"])   # uptrend regime
                & (dataframe["close"] > dataframe["ema_fast"])    # above the short trend
                & (dataframe["volume"] > 0)
            ),
            "enter_long",
        ] = 1
        return dataframe

    def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        dataframe.loc[
            (
                (dataframe["close"] < dataframe["ema_fast"])      # momentum faded -> exit
                & (dataframe["volume"] > 0)
            ),
            "exit_long",
        ] = 1
        return dataframe
