# Zeus Strategy: First Generation of GodStra Strategy with maximum # AVG/MID profit in USDT # Author: @Mablue (Masoud Azizi) # github: https://github.com/mablue/ # IMPORTANT: INSTALL TA BEFOUR RUN(pip install ta) # freqtrade hyperopt --hyperopt-loss SharpeHyperOptLoss --spaces buy sell roi --strategy Zeus # --- Do not remove these libs --- from datetime import timedelta, datetime from typing import Optional from freqtrade import data from freqtrade.persistence import Trade from freqtrade.strategy.hyper import CategoricalParameter, DecimalParameter, IntParameter, BooleanParameter from numpy.lib import math from freqtrade.strategy.interface import IStrategy import pandas from pandas import DataFrame import time import logging import calendar from freqtrade.loggers import setup_logging from freqtrade.strategy.strategy_helper import merge_informative_pair # -------------------------------- # Add your lib to import here import ta from functools import reduce import numpy as np import talib.abstract as talib from freqtrade.strategy.strategy_helper import merge_informative_pair import freqtrade.vendor.qtpylib.indicators as qtpylib from random import shuffle logger = logging.getLogger(__name__) operators = [ "D", # Disabled gene ">", # Indicator, bigger than cross indicator "<", # Indicator, smaller than cross indicator "=", # Indicator, equal with cross indicator "C", # Indicator, crossed the cross indicator "CA", # Indicator, crossed above the cross indicator "CB", # Indicator, crossed below the cross indicator ">R", # Normalized indicator, bigger than real number "=R", # Normalized indicator, equal with real number "R", # Normalized indicator devided to cross indicator, bigger than real number "/=R", # Normalized indicator devided to cross indicator, equal with real number "/ 10) # TODO : it ill callculated in populate indicators. dataframe[indicator] = gene_calculator(dataframe, indicator) dataframe[crossed_indicator] = gene_calculator(dataframe, crossed_indicator) indicator_trend_sma = f"{indicator}-SMA-{TREND_CHECK_CANDLES}" if operator in ["UT", "DT", "OT", "CUT", "CDT", "COT"]: dataframe[indicator_trend_sma] = gene_calculator(dataframe, indicator_trend_sma) if operator == ">": condition = (dataframe[indicator].shift(decalage) > dataframe[crossed_indicator].shift(decalage)) elif operator == "=": condition = (np.isclose(dataframe[indicator].shift(decalage), dataframe[crossed_indicator].shift(decalage))) elif operator == "<": condition = (dataframe[indicator].shift(decalage) < dataframe[crossed_indicator].shift(decalage)) elif operator == "C": condition = ( (qtpylib.crossed_below(dataframe[indicator].shift(decalage), dataframe[crossed_indicator].shift(decalage))) | (qtpylib.crossed_above(dataframe[indicator].shift(decalage), dataframe[crossed_indicator].shift(decalage))) ) elif operator == "CA": condition = (qtpylib.crossed_above(dataframe[indicator].shift(decalage), dataframe[crossed_indicator].shift(decalage))) elif operator == "CB": condition = (qtpylib.crossed_below(dataframe[indicator].shift(decalage), dataframe[crossed_indicator].shift(decalage))) elif operator == ">R": condition = (dataframe[indicator].shift(decalage) > real_num) elif operator == "=R": condition = (np.isclose(dataframe[indicator].shift(decalage), real_num)) elif operator == "R": condition = (dataframe[indicator].shift(decalage).div(dataframe[crossed_indicator].shift(decalage)) > real_num) elif operator == "/=R": condition = (np.isclose(dataframe[indicator].shift(decalage).div(dataframe[crossed_indicator].shift(decalage)), real_num)) elif operator == "/ dataframe[indicator_trend_sma].shift(decalage)) elif operator == "DT": condition = (dataframe[indicator].shift(decalage) < dataframe[indicator_trend_sma].shift(decalage)) elif operator == "OT": condition = (np.isclose(dataframe[indicator].shift(decalage), dataframe[indicator_trend_sma].shift(decalage))) elif operator == "CUT": condition = ( ( qtpylib.crossed_above(dataframe[indicator].shift(decalage), dataframe[indicator_trend_sma].shift(decalage)) ) & ( dataframe[indicator].shift(decalage) > dataframe[indicator_trend_sma].shift(decalage) ) ) elif operator == "CDT": condition = ( ( qtpylib.crossed_below(dataframe[indicator].shift(decalage), dataframe[indicator_trend_sma].shift(decalage)) ) & ( dataframe[indicator].shift(decalage) < dataframe[indicator_trend_sma].shift(decalage) ) ) elif operator == "COT": condition = ( ( ( qtpylib.crossed_below(dataframe[indicator].shift(decalage), dataframe[indicator_trend_sma].shift(decalage)) ) | ( qtpylib.crossed_above(dataframe[indicator].shift(decalage), dataframe[indicator_trend_sma].shift(decalage)) ) ) & ( np.isclose(dataframe[indicator].shift(decalage), dataframe[indicator_trend_sma].shift(decalage)) ) ) return condition, dataframe class Zeus_6(IStrategy): # * 1/43: 86 trades. 72/6/8 Wins/Draws/Losses. Avg profit 12.66%. Median profit 11.99%. Total profit 0.10894395 BTC ( 108.94Σ%). Avg duration 3 days, 0:31:00 min. Objective: -48.48793 # "max_open_trades": 10, # "stake_currency": "BTC", # "stake_amount": 0.01, # "tradable_balance_ratio": 0.99, # "timeframe": "4h", # "dry_run_wallet": 0.1, # Buy hyperspace params: buy_b_params = { "buy_b_cat": "R", "=R", "R", "=R", "R", "=R", " float: # # dataframe, _ = self.dp.get_analyzed_dataframe(pair=pair, timeframe=self.timeframe) # current_candle = dataframe.iloc[-1].squeeze() # # if current_candle['close'] < current_candle['sma10_1d']: # print("use more stake", pair, " ", proposed_stake * 2) # return min(max_stake, proposed_stake * 2) # else: # if current_candle['close'] < current_candle['sma5_1d']: # print("use more stake", pair, " ", proposed_stake * 1.5) # return min(max_stake, proposed_stake * 1.5) # # # Use default stake amount. # return proposed_stake # def bot_loop_start(self, **kwargs) -> None: # inf_tf = '5m' # pairs = self.dp.current_whitelist() # market_overview = {'up': 0, 'down': 0} # sum_pct5 = 0 # sum_pct1 = 0 # self.max_open_trades = self.config['max_open_trades'] # self.max_amount = self.config['stake_amount'] # if self.dp: # if self.dp.runmode.value in ('live', 'dry_run'): # for pairname in pairs: # informative = self.dp.get_pair_dataframe(pair=pairname, timeframe=inf_tf) # informative['pct'] = informative['close'].pct_change(1) # informative['pct5'] = informative['close'].pct_change(5) # # print(informative['pct5']) # pct5 = (informative.tail(1).iloc[0]['pct5']) * 100 # pct1 = (informative.tail(1).iloc[0]['pct']) * 100 # if pairname == "COCOS/USDT": # print(pairname, round(pct1, 5), round(pct5, 5)) #, informative.tail(1).iloc[0]) # # if pairname == "BTC/USDT": # current = informative.tail(1).iloc[0]['close'] # # 50000 => 2 30000 => 20 # if (current > 50000): # self.max_open_trades = 2 # self.max_amount = self.config['stake_amount'] / 2 # else: # if (current > 32000): # self.max_open_trades = 2 + int((50000 - current) / 1000) # self.max_amount = self.config['stake_amount'] / 2 \ # + self.config['stake_amount'] * self.max_open_trades / self.config['max_open_trades'] # else: # self.max_open_trades = self.config['max_open_trades'] # self.max_amount = self.config['stake_amount'] # # logger.info("pair '%s' prix %s max open trade %s max amount %s.", # pairname, current, self.max_open_trades, self.max_amount) # # if pct5 > 0: # market_overview['up'] += 1 # elif pct5 < 0: # market_overview['down'] += 1 # sum_pct5 += pct5 # sum_pct1 += pct1 # # self.market_overview_pct1 = sum_pct1 / len(pairs) # self.market_overview_pct5 = sum_pct5 / len(pairs) # # logger.info("market_overview_pct1 %s %s %s", round(self.market_overview_pct1,5), round(self.market_overview_pct5, 5), market_overview) # self.market_overview = market_overview # def confirm_trade_entry(self, pair: str, order_type: str, amount: float, rate: float, time_in_force: str, # current_time: datetime, entry_tag: Optional[str], **kwargs) -> bool: # # # {'symbol': 'FTM/USDT', 'timestamp': 1646494199570, 'datetime': '2022-03-05T15:29:59.570Z', 'high': 1.7489, # # 'low': 1.6084, 'bid': 1.6505, 'bidVolume': 2135.0, 'ask': 1.6508, 'askVolume': 2815.0, 'vwap': 1.66852198, # # 'open': 1.7313, 'close': 1.6505, 'last': 1.6505, 'previousClose': '1.73170000', 'change': -0.0808, # # 'percentage': -4.667, 'average': 1.6909, 'baseVolume': 124656725.0, 'quoteVolume': 207992485.7799, # # 'info': # # {'symbol': 'FTMUSDT', 'priceChange': '-0.08080000', 'priceChangePercent': '-4.667', # # 'weightedAvgPrice': '1.66852198', 'prevClosePrice': '1.73170000', 'lastPrice': '1.65050000', # # 'lastQty': '143.00000000', 'bidPrice': '1.65050000', 'bidQty': '2135.00000000', # # 'askPrice': '1.65080000', 'askQty': '2815.00000000', 'openPrice': '1.73130000', # # 'highPrice': '1.74890000', 'lowPrice': '1.60840000', 'volume': '124656725.00000000', # # 'quoteVolume': '207992485.77990000', 'openTime': '1646407799570', 'closeTime': '1646494199570', # # 'firstId': '137149614', 'lastId': '137450289', 'count': '300676'}} - 0.9817468621938484 # # allow_to_buy = True # if self.dp: # if self.dp.runmode.value in ('live', 'dry_run'): # if len(Trade.get_open_trades()) >= self.max_open_trades: # logger.info("too much open trades for BTC current value") # allow_to_buy = False # # return allow_to_buy def custom_sell(self, pair: str, trade: 'Trade', current_time: 'datetime', current_rate: float, current_profit: float, **kwargs): dataframe, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe) last_candle = dataframe.iloc[-1].squeeze() previous_last_candle = dataframe.iloc[-2].squeeze() previous_5_candle = dataframe.iloc[-5].squeeze() expected_profit = 0.01 #print(last_candle['buy_tag']) days = (current_time - trade.open_date_utc).days ###### # if self.dp: # if self.dp.runmode.value in ('live', 'dry_run'): # if (current_profit > - 0.04) & (self.market_overview_pct1 < - 1) & (self.market_overview['up'] / (self.market_overview['down'] + self.market_overview['up']) < 0.05): # return 'send_all' # if (current_profit > 0) & (last_candle['percent'] < 0) \ # (self.market_overview['up'] / (self.market_overview['down'] + self.market_overview['up']) < 0.25): # return 'all_down' if (self.market_overview_pct5 < 0) | (last_candle['pct_change_1_4h'] < 0): if (current_profit > 0.015) & ((last_candle['percent'] < -0.005) | (last_candle['percent3'] < -0.005) | (last_candle['percent5'] < -0.005)): return 'b_percent_quick' if (current_profit >= - self.sell_b_too_old_percent.value) & (days >= self.sell_b_too_old_day.value)\ & (days < self.sell_b_too_old_day.value * 2)\ & (previous_last_candle['sma10'] > last_candle['sma10']) & (last_candle['percent3'] < 0): return "b_too_old_0.01" if (current_profit >= - self.sell_b_too_old_percent.value * 2) & (days >= self.sell_b_too_old_day.value * 2)\ & (days < self.sell_b_too_old_day.value * 3) \ & (previous_last_candle['sma10'] > last_candle['sma10']) & (last_candle['percent3'] < 0): return "b_too_old_0.02" if (current_profit >= - self.sell_b_too_old_percent.value * 3) & (days >= self.sell_b_too_old_day.value * 3) \ & (previous_last_candle['sma10'] > last_candle['sma10']) & (last_candle['percent3'] < 0): return "b_too_old_0.03" if self.profit_b_quick_lost.value and (current_profit >= 0.015) & (last_candle['percent3'] < -0.005): return "b_quick_lost" if self.profit_b_no_change.value and (current_profit > self.sell_b_profit_no_change.value) \ & (last_candle['percent10'] < self.sell_b_profit_percent10.value) & (last_candle['percent5'] < 0) \ & ((current_time - trade.open_date_utc).seconds >= 3600): return "b_no_change" if (current_profit > self.sell_b_percent.value) & (last_candle['percent3'] < - self.sell_b_percent3.value) \ & ((current_time - trade.open_date_utc).seconds <= 300 * self.sell_b_candels.value): return "b_quick_gain_param" if self.profit_b_sma5.value: if (current_profit > expected_profit) \ & ((previous_5_candle['sma5'] > last_candle['sma5']) \ | (last_candle['percent3'] < -expected_profit) | ( last_candle['percent5'] < -expected_profit)) \ & ((last_candle['percent'] < 0) & (last_candle['percent3'] < 0)): # print("over_bb_band_sma10_desc", pair, trade, " profit=", current_profit, " rate=", current_rate) return 'b_sma5' if self.profit_b_sma10.value: if (current_profit > expected_profit) \ & ((previous_5_candle['sma10'] > last_candle['sma10']) \ | (last_candle['percent3'] < -expected_profit) | ( last_candle['percent5'] < -expected_profit)) \ & ((last_candle['percent'] < 0) & (last_candle['percent3'] < 0)): # print("over_bb_band_sma10_desc", pair, trade, " profit=", current_profit, " rate=", current_rate) return 'b_sma10' if self.profit_b_sma20.value: if (current_profit > last_candle['bb_width'] / 1.3) \ & (previous_last_candle['sma10'] > last_candle['sma10']) \ & ((current_time - trade.open_date_utc).seconds >= 3600) \ & ((previous_last_candle['sma20'] > last_candle['sma20']) & ((last_candle['percent5'] < 0) | (last_candle['percent10'] < 0) | (last_candle['percent20'] < 0))): # print("over_bb_band_sma10_desc", pair, trade, " profit=", current_profit, " rate=", current_rate) return 'b_sma20' if self.profit_b_over_rsi.value: if (current_profit > 0) & (previous_last_candle['rsi'] > self.sell_b_RSI.value): # & (last_candle['percent'] < 0): #| (previous_last_candle['rsi'] > 75 & last_candle['rsi'] < 70)): # print("over_rsi", pair, trade, " profit=", current_profit, " rate=", current_rate) return 'b_over_rsi' if (current_profit > 0) & (previous_last_candle['rsi'] > self.sell_b_RSI2.value) & \ (last_candle['percent'] < - self.sell_b_RSI2_percent.value): #| (previous_last_candle['rsi'] > 75 & last_candle['rsi'] < 70)): # print("over_rsi", pair, trade, " profit=", current_profit, " rate=", current_rate) return 'b_over_rsi_2' if (current_profit > 0) & (previous_last_candle['rsi'] > self.sell_b_RSI3.value) & \ (last_candle['close'] >= last_candle['max200']) & (last_candle['percent'] < - self.sell_b_RSI2_percent.value): #| (previous_last_candle['rsi'] > 75 & last_candle['rsi'] < 70)): # print("over_rsi", pair, trade, " profit=", current_profit, " rate=", current_rate) return 'b_over_rsi_max' if self.profit_b_short_loss.value: if (current_profit > -expected_profit) & (previous_last_candle['percent10'] > 0.04) & (last_candle['percent'] < 0)\ & (days >= 1): #| (previous_last_candle['rsi'] > 75 & last_candle['rsi'] < 70)): # print("over_rsi", pair, trade, " profit=", current_profit, " rate=", current_rate) return 'b_short_lost' else: if (current_profit > 0.025) & ((last_candle['percent'] < -0.005) | (last_candle['percent3'] < -0.005) | (last_candle['percent5'] < -0.005)): return 'h_percent_quick' if (current_profit >= - self.sell_h_too_old_percent.value) & (days >= self.sell_h_too_old_day.value)\ & (days < self.sell_h_too_old_day.value * 2)\ & (previous_last_candle['sma10'] > last_candle['sma10']) & (last_candle['percent3'] < 0): return "h_too_old_0.01" if (current_profit >= - self.sell_h_too_old_percent.value * 2) & (days >= self.sell_h_too_old_day.value * 2)\ & (days < self.sell_h_too_old_day.value * 3) \ & (previous_last_candle['sma10'] > last_candle['sma10']) & (last_candle['percent3'] < 0): return "h_too_old_0.02" if (current_profit >= - self.sell_h_too_old_percent.value * 3) & (days >= self.sell_h_too_old_day.value * 3) \ & (previous_last_candle['sma10'] > last_candle['sma10']) & (last_candle['percent3'] < 0): return "h_too_old_0.03" if self.profit_h_quick_lost.value and (current_profit >= 0.015) & (last_candle['percent3'] < -0.005): return "h_quick_lost" if self.profit_h_no_change.value and (current_profit > self.sell_h_profit_no_change.value) \ & (last_candle['percent10'] < self.sell_h_profit_percent10.value) & (last_candle['percent5'] < 0) \ & ((current_time - trade.open_date_utc).seconds >= 3600): return "h_no_change" if (current_profit > self.sell_h_percent.value) & (last_candle['percent3'] < - self.sell_h_percent3.value) \ & ((current_time - trade.open_date_utc).seconds <= 300 * self.sell_h_candels.value): return "h_quick_gain_param" if self.profit_h_sma5.value: if (current_profit > expected_profit) \ & ((previous_5_candle['sma5'] > last_candle['sma5']) \ | (last_candle['percent3'] < -expected_profit) | (last_candle['percent5'] < -expected_profit)) \ & ((last_candle['percent'] < 0) & (last_candle['percent3'] < 0)): # print("over_bb_band_sma10_desc", pair, trade, " profit=", current_profit, " rate=", current_rate) return 'h_sma5' if self.profit_h_sma10.value: if (current_profit > expected_profit) \ & ((previous_5_candle['sma10'] > last_candle['sma10']) \ | (last_candle['percent3'] < -expected_profit) | (last_candle['percent5'] < -expected_profit)) \ & ((last_candle['percent'] < 0) & (last_candle['percent3'] < 0)): # print("over_bb_band_sma10_desc", pair, trade, " profit=", current_profit, " rate=", current_rate) return 'h_sma10' if self.profit_h_sma20.value: if (current_profit > last_candle['bb_width'] / 0.8) \ & (previous_last_candle['sma10'] > last_candle['sma10']) \ & ((current_time - trade.open_date_utc).seconds >= 3600) \ & ((previous_last_candle['sma20'] > last_candle['sma20']) & ((last_candle['percent5'] < 0) | (last_candle['percent10'] < 0) | (last_candle['percent20'] < 0))): # print("over_bb_band_sma10_desc", pair, trade, " profit=", current_profit, " rate=", current_rate) return 'h_sma20' if self.profit_h_over_rsi.value: if (current_profit > 0) & (previous_last_candle['rsi'] > self.sell_h_RSI.value): # & (last_candle['percent'] < 0): #| (previous_last_candle['rsi'] > 75 & last_candle['rsi'] < 70)): # print("over_rsi", pair, trade, " profit=", current_profit, " rate=", current_rate) return 'h_over_rsi' if (current_profit > 0) & (previous_last_candle['rsi'] > self.sell_h_RSI2.value) & \ (last_candle['percent'] < - self.sell_h_RSI2_percent.value): #| (previous_last_candle['rsi'] > 75 & last_candle['rsi'] < 70)): # print("over_rsi", pair, trade, " profit=", current_profit, " rate=", current_rate) return 'h_over_rsi_2' if (current_profit > 0) & (previous_last_candle['rsi'] > self.sell_h_RSI3.value) & \ (last_candle['close'] >= last_candle['max200']): #| (previous_last_candle['rsi'] > 75 & last_candle['rsi'] < 70)): # print("over_rsi", pair, trade, " profit=", current_profit, " rate=", current_rate) return 'h_over_rsi_max' if self.profit_h_short_loss.value: if (current_profit > -expected_profit) & (previous_last_candle['percent10'] > 0.04) & (last_candle['percent'] < 0)\ & (days >= 1): #| (previous_last_candle['rsi'] > 75 & last_candle['rsi'] < 70)): # print("over_rsi", pair, trade, " profit=", current_profit, " rate=", current_rate) return 'h_short_lost' def informative_pairs(self): # get access to all pairs available in whitelist. pairs = self.dp.current_whitelist() informative_pairs = [(pair, '1d') for pair in pairs] informative_pairs += [(pair, '4h') for pair in pairs] informative_pairs += [(pair, '1h') for pair in pairs] return informative_pairs def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame: # Add all ta features dataframe['trend_ichimoku_base'] = ta.trend.ichimoku_base_line( dataframe['high'], dataframe['low'], window1=9, window2=26, visual=False, fillna=False ) KST = ta.trend.KSTIndicator( close=dataframe['close'], roc1=10, roc2=15, roc3=20, roc4=30, window1=10, window2=10, window3=10, window4=15, nsig=9, fillna=False ) dataframe['trend_kst_diff'] = KST.kst_diff() dataframe['rsi'] = talib.RSI(dataframe) dataframe['rsi5'] = talib.RSI(dataframe, timeperiod=5) dataframe['pct_change'] = dataframe['close'].pct_change(5) dataframe['min'] = talib.MIN(dataframe['close'], timeperiod=self.buy_min_horizon.value) dataframe['min10'] = talib.MIN(dataframe['close'], timeperiod=10) dataframe['min20'] = talib.MIN(dataframe['close'], timeperiod=20) dataframe['min50'] = talib.MIN(dataframe['close'], timeperiod=50) dataframe['min200'] = talib.MIN(dataframe['close'], timeperiod=200) dataframe['min200_5'] = dataframe['min200'] * 1.005 dataframe['moy200_12'] = dataframe['min200'].rolling(12).mean() dataframe['max50'] = talib.MAX(dataframe['close'], timeperiod=50) dataframe['max200'] = talib.MAX(dataframe['close'], timeperiod=200) dataframe['min_max50'] = (dataframe['max50'] - dataframe['min50']) / dataframe['min50'] dataframe['min_max200'] = (dataframe['max200'] - dataframe['min200']) / dataframe['min200'] dataframe['min_max200_5'] = (dataframe['min200'] * (1 + dataframe['min_max200'] / 5)) dataframe['sma5'] = talib.SMA(dataframe, timeperiod=5) dataframe['sma10'] = talib.SMA(dataframe, timeperiod=10) dataframe['sma20'] = talib.SMA(dataframe, timeperiod=20) dataframe['sma50'] = talib.SMA(dataframe, timeperiod=50) dataframe['sma100'] = talib.SMA(dataframe, timeperiod=100) dataframe["percent"] = (dataframe["close"] - dataframe["open"]) / dataframe["open"] dataframe["percent5"] = dataframe["percent"].rolling(5).sum() dataframe["percent3"] = dataframe["percent"].rolling(3).sum() dataframe["percent10"] = dataframe["percent"].rolling(10).sum() dataframe["percent20"] = dataframe["percent"].rolling(20).sum() dataframe["percent50"] = dataframe["percent"].rolling(50).sum() dataframe["volume10"] = dataframe["volume"].rolling(10).mean() dataframe["volume10"] = dataframe["volume"].rolling(10).mean() # Bollinger Bands bollinger = qtpylib.bollinger_bands(qtpylib.typical_price(dataframe), window=20, stds=2) dataframe['bb_lowerband'] = bollinger['lower'] dataframe['bb_middleband'] = bollinger['mid'] dataframe['bb_upperband'] = bollinger['upper'] dataframe["bb_percent"] = ( (dataframe["close"] - dataframe["bb_lowerband"]) / (dataframe["bb_upperband"] - dataframe["bb_lowerband"]) ) dataframe["bb_width"] = ( (dataframe["bb_upperband"] - dataframe["bb_lowerband"]) / dataframe["bb_middleband"] ) dataframe['bb_lower_var_5'] = (dataframe['bb_lowerband'] - dataframe['min50']).rolling(5).var() dataframe['bb_lower_5'] = 100 * ((dataframe['bb_lowerband'].rolling(5).mean() / dataframe['bb_lowerband']) - 1) # dataframe['bb_min'] = ta.MIN(dataframe['bb_lowerband'], timeperiod=36) dataframe['distance_min'] = (dataframe['close'] - dataframe['min']) / dataframe['close'] dataframe['min1.1'] = 1.01 * dataframe['min'] dataframe['normal'] = 100 * (dataframe['close'] / dataframe['close'].rolling(200).mean()) dataframe['normal_var_20'] = dataframe['normal'].rolling(20).var() dataframe['normal_var_50'] = dataframe['normal'].rolling(50).var() dataframe['sar'] = talib.SAR(dataframe) # Normalization tib = dataframe['trend_ichimoku_base'] dataframe['trend_ichimoku_base'] = (tib-tib.min())/(tib.max()-tib.min()) tkd = dataframe['trend_kst_diff'] dataframe['trend_kst_diff'] = (tkd-tkd.min())/(tkd.max()-tkd.min()) dataframe[buy_crossed_indicator0] = gene_calculator(dataframe, buy_crossed_indicator0) dataframe[buy_crossed_indicator1] = gene_calculator(dataframe, buy_crossed_indicator1) dataframe[buy_crossed_indicator2] = gene_calculator(dataframe, buy_crossed_indicator2) dataframe[buy_indicator0] = gene_calculator(dataframe, buy_indicator0) dataframe[buy_indicator1] = gene_calculator(dataframe, buy_indicator1) dataframe[buy_indicator2] = gene_calculator(dataframe, buy_indicator2) dataframe["cond1"] = dataframe[buy_indicator0].div(dataframe[buy_crossed_indicator0]) dataframe['atr'] = talib.ATR(dataframe, timeperiod=14) ################### INFORMATIVE 1D informative = self.dp.get_pair_dataframe(pair=metadata['pair'], timeframe="1d") informative["rsi"] = talib.RSI(informative) informative["max3"] = talib.MAX(informative['close'], timeperiod=3) informative["min3"] = talib.MIN(informative['close'], timeperiod=3) informative['pct_change_1'] = informative['close'].pct_change(1) informative['pct_change_3'] = informative['close'].pct_change(3) informative['pct_change_5'] = informative['close'].pct_change(5) informative['sma3'] = talib.SMA(informative, timeperiod=3) informative['sma5'] = talib.SMA(informative, timeperiod=5) informative['sma10'] = talib.SMA(informative, timeperiod=10) informative['sar'] = talib.SAR(informative) bollinger = qtpylib.bollinger_bands(qtpylib.typical_price(informative), window=20, stds=2) informative['bb_lowerband'] = bollinger['lower'] informative['bb_middleband'] = bollinger['mid'] informative['bb_upperband'] = bollinger['upper'] informative["bb_percent"] = ( (informative["close"] - informative["bb_lowerband"]) / (informative["bb_upperband"] - informative["bb_lowerband"]) ) informative["bb_width"] = ( (informative["bb_upperband"] - informative["bb_lowerband"]) / informative["bb_middleband"] ) dataframe = merge_informative_pair(dataframe, informative, self.timeframe, "1d", ffill=True) ######################## INFORMATIVE 4h informative = self.dp.get_pair_dataframe(pair=metadata['pair'], timeframe="4h") informative["rsi"] = talib.RSI(informative) informative['pct_change_1'] = informative['close'].pct_change(1) informative['pct_change_3'] = informative['close'].pct_change(3) informative['pct_change_5'] = informative['close'].pct_change(5) dataframe = merge_informative_pair(dataframe, informative, self.timeframe, "4h", ffill=True) ################### INFORMATIVE BTC 1H informative = self.dp.get_pair_dataframe(pair=metadata['pair'], timeframe="1h") informative["rsi"] = talib.RSI(informative) informative["rsi_5"] = talib.RSI(informative, timeperiod=5) informative['pct_change_1'] = informative['close'].pct_change(1) dataframe = merge_informative_pair(dataframe, informative, self.timeframe, "1h", ffill=True) return dataframe def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame: ok = True #if self.dp: # if self.dp.runmode.value in ('live', 'dry_run'): # ok = (self.market_overview['up'] / (self.market_overview['down'] + self.market_overview['up']) > 0.35) conditions = [] IND = 'trend_ichimoku_base' REAL = self.buy_h_real.value OPR = self.buy_h_cat.value DFIND = dataframe[IND] # print(DFIND.mean()) if OPR == ">R": conditions.append(DFIND > REAL) elif OPR == "=R": conditions.append(np.isclose(DFIND, REAL)) elif OPR == "= 10) & (dataframe['pct_change'] < - self.buy_h_pct.value) & (dataframe['close'] <= dataframe['min200'] * 1.002) & (dataframe['pct_change_1_1d'] > 0) & (dataframe['pct_change_3_1d'] > 0) & (dataframe['pct_change_5_1d'] > 0) #self.buy_h_pct_5.value) #& (dataframe['close_1d'] < dataframe['bb_lowerband_1d'] * self.buy_h_bb_lowerband.value) & (dataframe['bb_width_1d'] >= self.buy_h_bb_width.value) & (dataframe['close'] <= dataframe['sma5_1d']) & (dataframe['sma10_1d'].shift(1) <= dataframe['sma10_1d']) & (dataframe['cond1'] <= 0.45) # self.buy_real_num0.value / 2) , ['buy', 'buy_tag']] = (1, 'buy_h') conditions = [] IND = 'trend_ichimoku_base' REAL = self.buy_b_real.value OPR = self.buy_b_cat.value DFIND = dataframe[IND] # print(DFIND.mean()) if OPR == ">R": conditions.append(DFIND > REAL) elif OPR == "=R": conditions.append(np.isclose(DFIND, REAL)) elif OPR == "= 10) & (dataframe['pct_change'] < - self.buy_b_pct.value) & (dataframe['close'] <= dataframe['min200'] * 1.002) & (dataframe['pct_change_1_1d'] > 0) & (dataframe['pct_change_3_1d'] < 0) # self.buy_b_pct_3.value) & (dataframe['pct_change_5_1d'] < 0) #self.buy_b_pct_5.value) #& (dataframe['close_1d'] < dataframe['bb_lowerband_1d'] * self.buy_b_bb_lowerband.value) & (dataframe['bb_width_1d'] >= self.buy_b_bb_width.value) & (dataframe['close'] <= dataframe['sma5_1d']) & (dataframe['sma10_1d'].shift(1) <= dataframe['sma10_1d']) & (dataframe['cond1'] <= 0.45) # self.buy_real_num0.value / 2) , ['buy', 'buy_tag']] = (1, 'buy_b') for decalage in range(self.buy_decalage_deb_0.value, self.buy_decalage0.value): #if self.buy_0.value: conditions = list() condition1, dataframe = condition_generator( dataframe, buy_operator0, buy_indicator0, buy_crossed_indicator0, self.buy_real_num0.value, self.buy_decalage0.value ) conditions.append(condition1) dataframe.loc[ ( reduce(lambda x, y: x & y, conditions) #& (ok) & (dataframe['volume10'].shift(decalage) * dataframe['close'].shift(decalage) / 1000 >= 10) & (dataframe['sma10'].shift(1) <= dataframe['sma10']) & (dataframe['bb_width'] >= 0.05) & (dataframe['close'] < dataframe['bb_middleband']) & (dataframe['open'] < dataframe['sma10']) & (dataframe['open'] < dataframe['sma20']) & (dataframe['min50'].shift(decalage) == dataframe['min50']) & (dataframe['min10'] <= dataframe['min50'] * 1.02) & (dataframe['percent20'].shift(decalage) <= self.buy_0_percent20.value) # & (dataframe['min20'] == dataframe['min50']) & (dataframe['distance_min'] <= self.buy_0_distance.value) & ((dataframe['close'] - dataframe['open'].shift(decalage)) / dataframe['open'].shift(decalage) <= 0.005) # & (dataframe['bb_lower_var_5'] <= self.buy_1_bb_lower_var_5.value) & (dataframe['bb_lower_5'] <= self.buy_1_bb_lower_5.value) #& (dataframe['percent_1d'] >= self.buy_1_percent_1d_num.value) #& (dataframe['percent_4h'] > 0) #& (dataframe['percent3_4h'] <= self.buy_1_percent_4h_num.value) ), ['buy', 'buy_tag']] = (1, 'buy_1_' + str(decalage)) for decalage in range(self.buy_decalage_deb_2.value, self.buy_decalage2.value): #if self.buy_2.value: dataframe.loc[ ( (dataframe['cond1'].shift(decalage) <= 0.45) #self.buy_real_num0.value / 2) #& (ok) & (dataframe['volume10'].shift(decalage) * dataframe['close'].shift(decalage) / 1000 >= 10) & (dataframe['bb_width'] >= 0.05) & (dataframe['close'] < dataframe['sma10']) & (dataframe['open'] < dataframe['sma20']) & (dataframe['open'] < dataframe['sma10']) & (dataframe['min50'].shift(decalage) == dataframe['min50']) & (dataframe['percent20'].shift(decalage) <= self.buy_2_percent20.value) & (dataframe['distance_min'] <= self.buy_2_distance.value) & ((dataframe['close'] - dataframe['open'].shift(decalage)) / dataframe['open'].shift( decalage) <= 0.005) & (dataframe['bb_lower_5'] <= self.buy_2_bb_lower_5.value) ), ['buy', 'buy_tag']] = (1, 'buy_2_' + str(decalage)) # d = dataframe.tail(1).iloc[0] # print(metadata['pair'], d['cond1'], d['bb_width'], d['close'], d['sma10'], d['sma20']) for decalage in range(self.buy_decalage_deb_3.value, self.buy_decalage3.value): #if self.buy_3.value: dataframe.loc[ ( (dataframe['cond1'].shift(decalage) <= 0.2) #& (ok) & (dataframe['volume10'].shift(decalage) * dataframe['close'].shift(decalage) / 1000 >= 10) # & (dataframe['sma10'].shift(1) <= dataframe['sma10']) & (dataframe['bb_width'] >= 0.05) & (dataframe['close'] < dataframe['sma10']) & (dataframe['open'] < dataframe['sma20']) & (dataframe['open'] < dataframe['sma10']) & (dataframe['min50'].shift(decalage) == dataframe['min50']) #& (dataframe['min10'] <= dataframe['min50'] * 1.02) & (dataframe['percent20'].shift(decalage) <= self.buy_3_percent20.value) & (dataframe['distance_min'] <= self.buy_3_distance.value) & ((dataframe['close'] - dataframe['open'].shift(decalage)) / dataframe['open'].shift( decalage) <= 0.005) # & (dataframe['bb_lower_var_5'] <= self.buy_3_bb_lower_var_5.value) & (dataframe['bb_lower_5'] <= self.buy_3_bb_lower_5.value) #& (dataframe['percent_4h'] > 0) #& (dataframe['percent3_4h'] <= self.buy_3_percent_4h_num.value) ), ['buy', 'buy_tag']] = (1, 'buy_3_' + str(decalage)) # dataframe.loc[ # ( # (dataframe['cond1'] <= 1) # & (dataframe['close'] < dataframe['sma10']) # & (dataframe['open'] < dataframe['sma20']) # & (dataframe['open'] < dataframe['sma10']) # & (dataframe['close'] <= dataframe['min'] * 1.005) # & (dataframe['moy200_12'] == dataframe['min200']) # & (dataframe['volume10'].shift(1) * dataframe['close'].shift(1) / 1000 >= 10) # & (dataframe['percent20'] >= -0.005) # # ), ['buy', 'buy_tag']] = (1, 'buy_near_m50') # dataframe.loc[ # ( # (dataframe['trend_ichimoku_base'] <= 0.08) # & (dataframe['rsi'] < 42) # & (dataframe['rsi_1h'] >= self.buy_rsi.value) # & (dataframe['close'] < dataframe['sma10']) # # & (dataframe['min50'].shift(2) == dataframe['min50']) # ), ['buy', 'buy_tag']] = (1, 'buy_ichimoku') # d = dataframe.tail(1) # print(metadata['pair'], d['percent50'].iloc[0], d['buy'].iloc[0], d['buy_tag'].iloc[0]) dataframe.loc[ ( ( (dataframe['trend_ichimoku_base'] <= self.buy_base.value) | (dataframe['trend_kst_diff'] <= self.buy_diff.value) ) & (dataframe['rsi_1h'] < self.buy_rsi_1h.value) & (dataframe['rsi_1h'] >= self.buy_rsi_max_1h.value) & (dataframe['rsi'] > self.buy_rsi.value) & (dataframe['rsi'] <= self.buy_rsi_max.value) #& (dataframe['close'] < dataframe['sma10']) # & (dataframe['close'] < dataframe['min200'] * (1 + dataframe['min_max200'] / 5)) #& (dataframe['sma10'].shift(1) * 1.001 < dataframe['sma10']) # & (dataframe['min50'].shift(2) == dataframe['min50']) # & (dataframe['rsi_5_1h'] > 35) & (dataframe['close'] <= dataframe['min50'] * (1 + dataframe['min_max50'] / 2)) ), ['buy', 'buy_tag']] = (1, 'buy_ichimoku_h') return dataframe def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame: return dataframe