# source: https://raw.githubusercontent.com/kanaxe/freqtrade_kanaxe/635577b7c04ea237bacbdb2e65c7ef450c0f2abb/stash/assemblestj.py
from freqtrade.strategy import IStrategy, DecimalParameter, IntParameter
import logging
from pandas import DataFrame
from freqtrade.resolvers import StrategyResolver
from itertools import combinations
from functools import reduce

logger = logging.getLogger(__name__)


STRATEGIES = [
    "CombinedBinHAndClucV8XHO",
    "ElliotV4",
    # "Low_BBHO2",
    "MadV9HO",
    "NFI46OffsetHOA1",
    "NFI46Offset",
    "NFI7MOHO",
    "NostalgiaForInfinityV7",
    "SMAOffsetProtectOptV1HO1",
    "ElliotV7"
]

STRAT_COMBINATIONS = reduce(
    lambda x, y: list(combinations(STRATEGIES, y)) + x, range(len(STRATEGIES) + 1), []
)

MAX_COMBINATIONS = len(STRAT_COMBINATIONS) - 2


class github_kanaxe_freqtrade_kanaxe__assemblestj__20211115_132756(IStrategy):
    loaded_strategies = {}
    informative_timeframe = "1h"
    timeframe = "5m"
    use_sell_signal = False
    ignore_roi_if_buy_signal = False
    sell_profit_only = False

    buy_action_diff_threshold = DecimalParameter(0, 1, default=0, decimals=2, optimize=True, load=True)
    buy_strategies = IntParameter(0, MAX_COMBINATIONS, default=0, optimize=True, load=True)

    stoploss = -0.3

    buy_params = {
    }

    sell_params = {}

    # ROI table:
    minimal_roi = {
        "0": 0.187,
        "23": 0.043,
        "72": 0.011,
        "163": 0
    }

    # Trailing stop:
    trailing_stop = True
    trailing_stop_positive = 0.074
    trailing_stop_positive_offset = 0.121
    trailing_only_offset_is_reached = False

    protections = [
        {
            "method": "CooldownPeriod",
            "stop_duration_candles": 2
        },
        {
            "method": "StoplossGuard",
            "lookback_period_candles": 100,
            "trade_limit": 4,
            "stop_duration_candles": 10,
            "only_per_pair": True
        },
    ]

    def __init__(self, config: dict) -> None:
        super().__init__(config)
        logger.info(f"Buy stratrategies: {STRAT_COMBINATIONS[self.buy_strategies.value]}")

    def informative_pairs(self):
        pairs = self.dp.current_whitelist()
        informative_pairs = [(pair, self.informative_timeframe) for pair in pairs]
        return informative_pairs

    def get_strategy(self, strategy_name):
        strategy = self.loaded_strategies.get(strategy_name)
        if not strategy:
            config = self.config
            config["strategy"] = strategy_name
            strategy = StrategyResolver.load_strategy(config)

        strategy.dp = self.dp
        strategy.wallets = self.wallets
        self.loaded_strategies[strategy_name] = strategy
        return strategy

    def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        strategies = STRATEGIES
        for strategy_name in strategies:
            strategy = self.get_strategy(strategy_name)
            strategy_indicators = strategy.advise_indicators(dataframe, metadata)
            dataframe[f"buy_signal_{strategy_name}"] = strategy.advise_buy(
                strategy_indicators, metadata
            )["buy"]

        buy_strategies = STRAT_COMBINATIONS[self.buy_strategies.value]
        buy_strategies = [f"buy_signal_{name}" for name in buy_strategies]

        dataframe["buy_mean"] = dataframe[buy_strategies].fillna(0).mean(axis=1)
        return dataframe

    def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        dataframe["buy"] = (
            dataframe["buy_mean"] > self.buy_action_diff_threshold.value
        ).astype(int)
        return dataframe

    def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        dataframe["sell"] = 0
        return dataframe

