import numpy as np import talib.abstract as ta import freqtrade.vendor.qtpylib.indicators as qtpylib import arrow from freqtrade.strategy.interface import IStrategy from freqtrade.strategy import merge_informative_pair from pandas import DataFrame, Series from functools import reduce from datetime import datetime from freqtrade.persistence import Trade from technical.indicators import RMI from statistics import mean from cachetools import TTLCache from scipy.optimize import curve_fit class Infinite_ROI(IStrategy): """ Strategy Configuration Items """ timeframe = '5m' inf_timeframe = '1h' minimal_roi = { "0": 0.05, "10": 0.025, "20": 0.015, "30": 0.01, "720": 0.005, "1440": 0 } dynamic_roi = { 'enabled': True, 'type': 'exponential', # linear, exponential, or connect 'decay-rate': 0.015, # bigger is faster, recommended to graph f(t) = start-pct * e(-rate*t) 'decay-time': 1440, # amount of time to reach zero, only relevant for linear decay 'start': 0.10, # starting percentage 'end': 0, # ending percentage } """ Informative Pair Definitions """ def informative_pairs(self): return informative_pairs """ Indicator Definitions """ def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame: return dataframe """ Buy Trigger Signals """ def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame: return dataframe """ Sell Trigger Signals """ def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame: return dataframe """ Override for default Freqtrade ROI table functionality """ def min_roi_reached_entry(self, trade_dur: int) -> Tuple[Optional[int], Optional[float]]: dynamic_roi = self.dynamic_roi if dynamic_roi and dynamic_roi['enabled']: if dynamic_roi['type'] == 'linear': rate = (dynamic_roi['start'] - dynamic_roi['end']) / dynamic_roi['decay-time'] min_roi = max(dynamic_roi['end'], dynamic_roi['start'] - (rate * trade_dur)) elif dynamic_roi['type'] == 'exponential': min_roi = max(dynamic_roi['end'], dynamic_roi['start'] * np.exp(-dynamic_roi['decay-rate']*trade_dur)) elif dynamic_roi['type'] == 'connect': past_roi = list(filter(lambda x: x <= trade_dur, self.minimal_roi.keys())) next_roi = list(filter(lambda x: x > trade_dur, self.minimal_roi.keys())) if not past_roi: return None, None current_entry = max(past_roi) if not next_roi: return current_entry, self.minimal_roi[current_entry] else: next_entry = min(next_roi) x1 = current_entry x2 = next_entry y1 = self.minimal_roi[current_entry] y2 = self.minimal_roi[next_entry] m = (y1-y2)/(x1-x2) b = (x1*y2 - x2*y1)/(x1-x2) min_roi = (m * trade_dur) + b else: min_roi = 0 return trade_dur, min_roi else: roi_list = list(filter(lambda x: x <= trade_dur, self.minimal_roi.keys())) if not roi_list: return None, None roi_entry = max(roi_list) return roi_entry, self.minimal_roi[roi_entry]