# GodStraNew Strategy # Author: @Mablue (Masoud Azizi) # github: https://github.com/mablue/ # freqtrade hyperopt --hyperopt-loss SharpeHyperOptLoss --spaces buy roi trailing sell --strategy GodStraNew # --- Do not remove these libs --- from datetime import timedelta, datetime from freqtrade.strategy.strategy_helper import merge_informative_pair from freqtrade import data from freqtrade.persistence import Trade from freqtrade.strategy.parameters import CategoricalParameter, DecimalParameter, IntParameter, BooleanParameter from numpy.lib import math from freqtrade.strategy.interface import IStrategy import pandas from pandas import DataFrame # -------------------------------- # Add your lib to import here # TODO: talib is fast but have not more indicators import talib.abstract as ta import freqtrade.vendor.qtpylib.indicators as qtpylib from functools import reduce import numpy as np from random import shuffle # TODO: this gene is removed 'MAVP' cuz or error on periods import user_data.strategies.custom_indicators as csa all_god_genes = { 'Overlap Studies': { 'BBANDS-0', # Bollinger Bands 'BBANDS-1', # Bollinger Bands 'BBANDS-2', # Bollinger Bands 'DEMA', # Double Exponential Moving Average 'EMA', # Exponential Moving Average 'HT_TRENDLINE', # Hilbert Transform - Instantaneous Trendline 'KAMA', # Kaufman Adaptive Moving Average 'MA', # Moving average 'MAMA-0', # MESA Adaptive Moving Average 'MAMA-1', # MESA Adaptive Moving Average # TODO: Fix this # 'MAVP', # Moving average with variable period 'MIDPOINT', # MidPoint over period 'MIDPRICE', # Midpoint Price over period 'SAR', # Parabolic SAR 'SAREXT', # Parabolic SAR - Extended 'SMA', # Simple Moving Average 'T3', # Triple Exponential Moving Average (T3) 'TEMA', # Triple Exponential Moving Average 'TRIMA', # Triangular Moving Average 'WMA', # Weighted Moving Average }, 'Momentum Indicators': { 'ADX', # Average Directional Movement Index 'ADXR', # Average Directional Movement Index Rating 'APO', # Absolute Price Oscillator 'AROON-0', # Aroon 'AROON-1', # Aroon 'AROONOSC', # Aroon Oscillator 'BOP', # Balance Of Power 'CCI', # Commodity Channel Index 'CMO', # Chande Momentum Oscillator 'DX', # Directional Movement Index 'MACD-0', # Moving Average Convergence/Divergence 'MACD-1', # Moving Average Convergence/Divergence 'MACD-2', # Moving Average Convergence/Divergence 'MACDEXT-0', # MACD with controllable MA type 'MACDEXT-1', # MACD with controllable MA type 'MACDEXT-2', # MACD with controllable MA type 'MACDFIX-0', # Moving Average Convergence/Divergence Fix 12/26 'MACDFIX-1', # Moving Average Convergence/Divergence Fix 12/26 'MACDFIX-2', # Moving Average Convergence/Divergence Fix 12/26 'MFI', # Money Flow Index 'MINUS_DI', # Minus Directional Indicator 'MINUS_DM', # Minus Directional Movement 'MOM', # Momentum 'PLUS_DI', # Plus Directional Indicator 'PLUS_DM', # Plus Directional Movement 'PPO', # Percentage Price Oscillator 'ROC', # Rate of change : ((price/prevPrice)-1)*100 # Rate of change Percentage: (price-prevPrice)/prevPrice 'ROCP', 'ROCR', # Rate of change ratio: (price/prevPrice) # Rate of change ratio 100 scale: (price/prevPrice)*100 'ROCR100', 'RSI', # Relative Strength Index 'STOCH-0', # Stochastic 'STOCH-1', # Stochastic 'STOCHF-0', # Stochastic Fast 'STOCHF-1', # Stochastic Fast 'STOCHRSI-0', # Stochastic Relative Strength Index 'STOCHRSI-1', # Stochastic Relative Strength Index # 1-day Rate-Of-Change (ROC) of a Triple Smooth EMA 'TRIX', 'ULTOSC', # Ultimate Oscillator 'WILLR', # Williams' %R }, 'Volume Indicators': { 'AD', # Chaikin A/D Line 'ADOSC', # Chaikin A/D Oscillator 'OBV', # On Balance Volume }, 'Volatility Indicators': { 'ATR', # Average True Range 'NATR', # Normalized Average True Range 'TRANGE', # True Range }, 'Price Transform': { 'AVGPRICE', # Average Price 'MEDPRICE', # Median Price 'TYPPRICE', # Typical Price 'WCLPRICE', # Weighted Close Price }, 'Cycle Indicators': { 'HT_DCPERIOD', # Hilbert Transform - Dominant Cycle Period 'HT_DCPHASE', # Hilbert Transform - Dominant Cycle Phase 'HT_PHASOR-0', # Hilbert Transform - Phasor Components 'HT_PHASOR-1', # Hilbert Transform - Phasor Components 'HT_SINE-0', # Hilbert Transform - SineWave 'HT_SINE-1', # Hilbert Transform - SineWave 'HT_TRENDMODE', # Hilbert Transform - Trend vs Cycle Mode }, 'Pattern Recognition': { 'CDL2CROWS', # Two Crows 'CDL3BLACKCROWS', # Three Black Crows 'CDL3INSIDE', # Three Inside Up/Down 'CDL3LINESTRIKE', # Three-Line Strike 'CDL3OUTSIDE', # Three Outside Up/Down 'CDL3STARSINSOUTH', # Three Stars In The South 'CDL3WHITESOLDIERS', # Three Advancing White Soldiers 'CDLABANDONEDBABY', # Abandoned Baby 'CDLADVANCEBLOCK', # Advance Block 'CDLBELTHOLD', # Belt-hold 'CDLBREAKAWAY', # Breakaway 'CDLCLOSINGMARUBOZU', # Closing Marubozu 'CDLCONCEALBABYSWALL', # Concealing Baby Swallow 'CDLCOUNTERATTACK', # Counterattack 'CDLDARKCLOUDCOVER', # Dark Cloud Cover 'CDLDOJI', # Doji 'CDLDOJISTAR', # Doji Star 'CDLDRAGONFLYDOJI', # Dragonfly Doji 'CDLENGULFING', # Engulfing Pattern 'CDLEVENINGDOJISTAR', # Evening Doji Star 'CDLEVENINGSTAR', # Evening Star 'CDLGAPSIDESIDEWHITE', # Up/Down-gap side-by-side white lines 'CDLGRAVESTONEDOJI', # Gravestone Doji 'CDLHAMMER', # Hammer 'CDLHANGINGMAN', # Hanging Man 'CDLHARAMI', # Harami Pattern 'CDLHARAMICROSS', # Harami Cross Pattern 'CDLHIGHWAVE', # High-Wave Candle 'CDLHIKKAKE', # Hikkake Pattern 'CDLHIKKAKEMOD', # Modified Hikkake Pattern 'CDLHOMINGPIGEON', # Homing Pigeon 'CDLIDENTICAL3CROWS', # Identical Three Crows 'CDLINNECK', # In-Neck Pattern 'CDLINVERTEDHAMMER', # Inverted Hammer 'CDLKICKING', # Kicking 'CDLKICKINGBYLENGTH', # Kicking - bull/bear determined by the longer marubozu 'CDLLADDERBOTTOM', # Ladder Bottom 'CDLLONGLEGGEDDOJI', # Long Legged Doji 'CDLLONGLINE', # Long Line Candle 'CDLMARUBOZU', # Marubozu 'CDLMATCHINGLOW', # Matching Low 'CDLMATHOLD', # Mat Hold 'CDLMORNINGDOJISTAR', # Morning Doji Star 'CDLMORNINGSTAR', # Morning Star 'CDLONNECK', # On-Neck Pattern 'CDLPIERCING', # Piercing Pattern 'CDLRICKSHAWMAN', # Rickshaw Man 'CDLRISEFALL3METHODS', # Rising/Falling Three Methods 'CDLSEPARATINGLINES', # Separating Lines 'CDLSHOOTINGSTAR', # Shooting Star 'CDLSHORTLINE', # Short Line Candle 'CDLSPINNINGTOP', # Spinning Top 'CDLSTALLEDPATTERN', # Stalled Pattern 'CDLSTICKSANDWICH', # Stick Sandwich # Takuri (Dragonfly Doji with very long lower shadow) 'CDLTAKURI', 'CDLTASUKIGAP', # Tasuki Gap 'CDLTHRUSTING', # Thrusting Pattern 'CDLTRISTAR', # Tristar Pattern 'CDLUNIQUE3RIVER', # Unique 3 River 'CDLUPSIDEGAP2CROWS', # Upside Gap Two Crows 'CDLXSIDEGAP3METHODS', # Upside/Downside Gap Three Methods }, 'Statistic Functions': { 'BETA', # Beta 'CORREL', # Pearson's Correlation Coefficient (r) 'LINEARREG', # Linear Regression 'LINEARREG_ANGLE', # Linear Regression Angle 'LINEARREG_INTERCEPT', # Linear Regression Intercept 'LINEARREG_SLOPE', # Linear Regression Slope 'STDDEV', # Standard Deviation 'TSF', # Time Series Forecast 'VAR', # Variance } } god_genes = set() ########################### SETTINGS ############################## # god_genes = {'SMA'} god_genes |= all_god_genes['Overlap Studies'] god_genes |= all_god_genes['Momentum Indicators'] god_genes |= all_god_genes['Volume Indicators'] god_genes |= all_god_genes['Volatility Indicators'] god_genes |= all_god_genes['Price Transform'] god_genes |= all_god_genes['Cycle Indicators'] god_genes |= all_god_genes['Pattern Recognition'] god_genes |= all_god_genes['Statistic Functions'] #timeperiods = [5, 6, 12, 15, 50, 55, 100, 110] timeperiods = [5, 10, 20, 50, 100] 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] > dataframe[crossed_indicator] ) elif operator == "=": condition = ( np.isclose(dataframe[indicator], dataframe[crossed_indicator]) ) elif operator == "<": condition = ( dataframe[indicator] < dataframe[crossed_indicator] ) elif operator == "C": condition = ( (qtpylib.crossed_below(dataframe[indicator], dataframe[crossed_indicator])) | (qtpylib.crossed_above( dataframe[indicator], dataframe[crossed_indicator])) ) elif operator == "CA": condition = ( qtpylib.crossed_above( dataframe[indicator], dataframe[crossed_indicator]) ) elif operator == "CB": condition = ( qtpylib.crossed_below( dataframe[indicator], dataframe[crossed_indicator]) ) elif operator == ">R": condition = ( dataframe[indicator] > real_num ) elif operator == "=R": condition = ( np.isclose(dataframe[indicator], real_num) ) elif operator == "R": condition = ( dataframe[indicator].div(dataframe[crossed_indicator]) > real_num ) elif operator == "/=R": condition = ( np.isclose(dataframe[indicator].div( dataframe[crossed_indicator]), real_num) ) elif operator == "/ dataframe[indicator_trend_sma] ) elif operator == "DT": condition = ( dataframe[indicator] < dataframe[indicator_trend_sma] ) elif operator == "OT": condition = ( np.isclose(dataframe[indicator], dataframe[indicator_trend_sma]) ) elif operator == "CUT": condition = ( ( qtpylib.crossed_above( dataframe[indicator], dataframe[indicator_trend_sma] ) ) & ( dataframe[indicator] > dataframe[indicator_trend_sma] ) ) elif operator == "CDT": condition = ( ( qtpylib.crossed_below( dataframe[indicator], dataframe[indicator_trend_sma] ) ) & ( dataframe[indicator] < dataframe[indicator_trend_sma] ) ) elif operator == "COT": condition = ( ( ( qtpylib.crossed_below( dataframe[indicator], dataframe[indicator_trend_sma] ) ) | ( qtpylib.crossed_above( dataframe[indicator], dataframe[indicator_trend_sma] ) ) ) & ( np.isclose( dataframe[indicator], dataframe[indicator_trend_sma] ) ) ) return condition, dataframe class GodStraJD3_9(IStrategy): # #################### RESULTS PASTE PLACE #################### # ROI table: minimal_roi = { "0": 10, # "600": 0.12, # "1200": 0.08, # "2400": 0.06, # "3600": 0.04, # "7289": 0 } # Stoploss: stoploss = -1 # Buy hypers timeframe = '5m' # Trailing stoploss trailing_stop = False trailing_stop_positive = 0.15 trailing_stop_positive_offset = 0.20 trailing_only_offset_is_reached = True sell_percent = DecimalParameter(0, 0.02, decimals=3, default=0, space='sell') sell_percent3 = DecimalParameter(0, 0.03, decimals=3, default=0, space='sell') sell_percent5 = DecimalParameter(0, 0.04, decimals=3, default=0, space='sell') # Sell Hyperoptable Parameters/Spaces. sell_crossed_indicator0 = CategoricalParameter(god_genes_with_timeperiod, default="CDLSHOOTINGSTAR-150", space='sell') # sell_crossed_indicator1 = CategoricalParameter(god_genes_with_timeperiod, default="MAMA-1-100", space='sell') # sell_crossed_indicator2 = CategoricalParameter(god_genes_with_timeperiod, default="CDLMATHOLD-6", space='sell') sell_indicator0 = CategoricalParameter(god_genes_with_timeperiod, default="CDLUPSIDEGAP2CROWS-5", space='sell') # sell_indicator1 = CategoricalParameter(god_genes_with_timeperiod, default="CDLHARAMICROSS-150", space='sell') # sell_indicator2 = CategoricalParameter(god_genes_with_timeperiod, default="CDL2CROWS-5", space='sell') sell_operator0 = CategoricalParameter(operators, default=" float: fee = 1.0007 profit = ((current*fee) - (price*fee)) return float(f"{profit:.8f}") def calc_percentage_lower(self, price: float, current: float) -> float: fee = 1.0007 price = price*fee current = current*fee lowerpercent = ((price-current)/(price*fee))*100 return float(f"{lowerpercent:.8f}") @property def protections(self): return [ { "method": "CooldownPeriod", "stop_duration_candles": self.protection_cooldown.value }, # { # "method": "MaxDrawdown", # "lookback_period_candles": self.lookback.value, # "trade_limit": self.trade_limit.value, # "stop_duration_candles": self.protection_stop.value, # "max_allowed_drawdown": self.protection_max_allowed_dd.value, # "only_per_pair": False # }, # { # "method": "StoplossGuard", # "lookback_period_candles": self.lookback_stoploss.value, # "trade_limit": self.trade_limit_stoploss.value, # "stop_duration_candles": self.protection_stoploss_stop.value, # "only_per_pair": False # }, ] 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() if (current_profit > 0) & ( (last_candle['percent5'] <= -0.015) | (last_candle['percent10'] <= -0.015) | (last_candle['percent20'] <= -0.015) ) \ & ((current_time - trade.open_date_utc).seconds >= 2400): return "quick_lost" if self.profit_quick_lost: if (current_profit >= 0) & (last_candle['percent3'] < -0.01) & (last_candle['percent5'] < 0) \ & ((current_time - trade.open_date_utc).seconds >= 2400): return "quick_lost_1H" if self.profit_no_change: if (current_profit > 0.015) & (last_candle['percent20'] < 0.0) & \ (last_candle['sma10'] < 0.0) & ((current_time - trade.open_date_utc).seconds >= 2400): return "no_change" #if (current_profit > 0.01) & (last_candle['rsi'] < 30): # return "small_rsi" if self.profit_quick_gain_3: if (current_profit >= 0.03) & (last_candle['percent3'] < 0) & ((current_time - trade.open_date_utc).seconds <= 3600): return "quick_gain_3" if self.profit_quick_gain: if (0.01 < current_profit < 0.03) & (last_candle['percent3'] < 0): #& ((current_time - trade.open_date_utc).seconds <= 3600) return "quick_gain" if self.profit_sma10: if (current_profit > 0.01) \ & ((previous_5_candle['sma10'] > last_candle['sma10'] * 1.005) \ | (last_candle['percent3'] < -0.01) | (last_candle['percent5'] < -0.01)) \ & ((last_candle['percent'] < 0) & (last_candle['percent3'] < 0)): # print("over_bb_band_sma10_desc", pair, trade, " profit=", current_profit, " rate=", current_rate) return 'sma10' if self.profit_sma20: if (current_profit > 0.005) & (last_candle['percent5'] < 0) & (last_candle['sma20_pente'] < -0.015)\ & ((current_time - trade.open_date_utc).seconds >= 3600) \ & ((previous_last_candle['sma20'] > last_candle['sma20'] * 1.005) & ((last_candle['percent10'] < 0) | (last_candle['percent20'] < 0))): # print("over_bb_band_sma10_desc", pair, trade, " profit=", current_profit, " rate=", current_rate) return 'sma20' # if self.profit_old_sma10: # if (current_profit > 0) \ # & ((current_time - trade.open_date_utc).days >= 3) \ # & ((previous_5_candle['sma10'] > last_candle['sma10']) | (last_candle['percent3'] < -0.005) | (last_candle['percent5'] < -0.005)) \ # & ((last_candle['percent'] < 0) & (last_candle['percent3'] < 0)): # # print("over_bb_band_sma10_desc", pair, trade, " profit=", current_profit, " rate=", current_rate) # return 'old_sma10' # if self.profit_very_old_sma10: # if (current_profit > -0.01) \ # & ((current_time - trade.open_date_utc).days >= 6) \ # & ((previous_5_candle['sma10'] > last_candle['sma10']) | (last_candle['percent3'] < 0) | (last_candle['percent5'] < 0)) \ # & ((last_candle['percent'] < 0) & (last_candle['percent3'] < 0)): # # print("over_bb_band_sma10_desc", pair, trade, " profit=", current_profit, " rate=", current_rate) # return 'very_old_sma10' if self.profit_over_rsi: if (current_profit > 0) \ & (last_candle['rsi'] > 88): #| (previous_last_candle['rsi'] > 75 & last_candle['rsi'] < 70)): # print("over_rsi", pair, trade, " profit=", current_profit, " rate=", current_rate) return 'over_rsi' if self.profit_short_loss: if (current_profit > -0.01) & (previous_last_candle['percent10'] > 0.04) & (last_candle['percent'] < 0)\ & ((current_time - trade.open_date_utc).days >= 1): #| (previous_last_candle['rsi'] > 75 & last_candle['rsi'] < 70)): # print("over_rsi", pair, trade, " profit=", current_profit, " rate=", current_rate) return 'short_lost' # if (current_profit > 0) \ # & (last_candle['rsi'] > 82) & (previous_last_candle['rsi'] > 75): #| (previous_last_candle['rsi'] > 75 & last_candle['rsi'] < 70)): # # print("over_rsi", pair, trade, " profit=", current_profit, " rate=", current_rate) # return 'over_rsi_2' def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame: dataframe['profit'] = 0 # RSI dataframe['rsi'] = ta.RSI(dataframe) dataframe['sma10'] = ta.SMA(dataframe, timeperiod=10) dataframe['sma20'] = ta.SMA(dataframe, timeperiod=20) dataframe['sma50'] = ta.SMA(dataframe, timeperiod=50) dataframe['sma100'] = ta.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() # if (dataframe["percent50"] < -0.03) & (dataframe['sma10'] > dataframe['sma10'].shift(2)): # dataframe["percent_ok"] = new dataframe() # else: # dataframe["percent_ok"] = 0 dataframe['min'] = ta.MIN(dataframe['close'], timeperiod=200) dataframe['min20'] = ta.MIN(dataframe['close'], timeperiod=20) dataframe['min50'] = ta.MIN(dataframe['close'], timeperiod=50) dataframe["volume10"] = dataframe["volume"].rolling(10).mean() dataframe['max'] = ta.MAX(dataframe['close'], timeperiod=200) dataframe['max20'] = ta.MAX(dataframe['close'], timeperiod=20) dataframe['max50'] = ta.MAX(dataframe['close'], timeperiod=50) dataframe['max_min'] = dataframe['max'] / dataframe['min'] # 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_pente"] = 100 * (dataframe["bb_lowerband"] - dataframe["bb_lowerband"].shift(1)) / dataframe["bb_lowerband"] dataframe["sma10_pente"] = 100 * (dataframe["sma10"] - dataframe["sma10"].shift(1)) / dataframe["sma10"] dataframe["sma20_pente"] = 100 * (dataframe["sma20"] - dataframe["sma20"].shift(1)) / dataframe["sma20"] dataframe['bb_min'] = ta.MIN(dataframe['bb_lowerband'], timeperiod=36) # Bollinger Bands - Weighted (EMA based instead of SMA) weighted_bollinger = qtpylib.weighted_bollinger_bands( qtpylib.typical_price(dataframe), window=20, stds=2 ) dataframe["wbb_upperband"] = weighted_bollinger["upper"] dataframe["wbb_lowerband"] = weighted_bollinger["lower"] dataframe["wbb_middleband"] = weighted_bollinger["mid"] dataframe["wbb_percent"] = ( (dataframe["close"] - dataframe["wbb_lowerband"]) / (dataframe["wbb_upperband"] - dataframe["wbb_lowerband"]) ) dataframe["wbb_width"] = ( (dataframe["wbb_upperband"] - dataframe["wbb_lowerband"]) / dataframe["wbb_middleband"] ) 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["HT_PHASOR-0-100"] = gene_calculator(dataframe, "HT_PHASOR-0-100") dataframe["CDLIDENTICAL3CROWS-100"] = gene_calculator(dataframe, "CDLIDENTICAL3CROWS-100") dataframe["DEMA-10"] = gene_calculator(dataframe, "DEMA-10") dataframe["CDLMORNINGDOJISTAR-20"] = gene_calculator(dataframe, "CDLMORNINGDOJISTAR-20") dataframe["cond1"] = dataframe[buy_indicator0].div(dataframe[buy_crossed_indicator0]) # dataframe["q_0.1"] = dataframe.rolling(50).quantile(.1)['close'] # dataframe["q_0.25"] = dataframe.rolling(50).quantile(.25)['close'] # dataframe["q_0.33"] = dataframe.rolling(50).quantile(.33)['close'] dataframe["MACD-2-10"] = gene_calculator(dataframe, "MACD-2-10") dataframe["CDLIDENTICAL3CROWS-10"] = gene_calculator(dataframe, "CDLIDENTICAL3CROWS-10") dataframe["PPO-10"] = gene_calculator(dataframe, "PPO-10") dataframe["MINUS_DM-10"] = gene_calculator(dataframe, "MINUS_DM-10") dataframe["MOM-10"] = gene_calculator(dataframe, "MOM-10") dataframe["MACDEXT-0-100"] = gene_calculator(dataframe, "MACDEXT-0-100") # # EMA - Exponential Moving Average # dataframe['ema3'] = ta.EMA(dataframe, timeperiod=3) percent_lower = False current_price = dataframe['close'].iloc[-1] dataframe['should_sell'] = False dataframe['should_buy'] = False # Get the previous trade # open_trades = Trade.get_trades_proxy(is_open=True) # print(open_trades) trade = Trade.get_trades_proxy(is_open=False, pair=metadata['pair']) if trade: trade = trade[-1] lsp = trade.close_rate if lsp: percent_lower = self.calc_percentage_lower(price=lsp, current=current_price) # Found a bug? When force selling it doesnt close it else: lsp = trade.open_rate if lsp: percent_lower = self.calc_percentage_lower(price=lsp, current=current_price) else: lsp = 0.00 # Get the current Trade trade = Trade.get_trades_proxy(is_open=True, pair=metadata['pair']) if trade: trade = trade[-1] lbp = trade.open_rate open_trade = True profit = self.calc_profit(price=lbp, current=current_price) profit_percent = (profit/lbp)*100 else: lbp = 0.00 open_trade = False profit = False profit_percent = False # print("------------") # print("Last Sold For:", lsp) # if open_trade: # print("Bought for: ", lbp) # print("Current Price: ", current_price) # if profit: # print("Current Profit: ", profit, " ", float(f"{profit_percent:.8f}"), "%") # if percent_lower and not open_trade: # print("Percent Lower: ", float(f"{percent_lower:.8f}"), "%") # Should we Sell? if profit_percent: if profit_percent > 1: dataframe['should_sell'] = True # Should we buy? if not open_trade: if (lsp == 0.00) & (lbp == 0.00): dataframe['should_buy'] = True # Is the percentage of what we sold for and the current price 2% lower if percent_lower > 2: dataframe['should_buy'] = True dataframe['last_sell_price'] = lsp dataframe['last_buy_price'] = lbp dataframe['current_price'] = current_price dataframe['profit_percent'] = profit_percent # print("Current Dataframe:") # print(dataframe.tail(1)) # ## Base Timeframe / Pair # # # Kaufmann Adaptive Moving Average # dataframe['kama'] = ta.KAMA(dataframe, length=233) # # # RMI: https://www.tradingview.com/script/kwIt9OgQ-Relative-Momentum-Index/ # dataframe['rmi'] = csa.RMI(dataframe, length=24, mom=5) # # # Momentum Pinball: https://www.tradingview.com/script/fBpVB1ez-Momentum-Pinball-Indicator/ # dataframe['roc-mp'] = ta.ROC(dataframe, timeperiod=1) # dataframe['mp'] = ta.RSI(dataframe['roc-mp'], timeperiod=3) # # # MA Streak: https://www.tradingview.com/script/Yq1z7cIv-MA-Streak-Can-Show-When-a-Run-Is-Getting-Long-in-the-Tooth/ # dataframe['mastreak'] = csa.mastreak(dataframe, period=4) # # # Percent Change Channel: https://www.tradingview.com/script/6wwAWXA1-MA-Streak-Change-Channel/ # upper, mid, lower = csa.pcc(dataframe, period=40, mult=3) # dataframe['pcc-lowerband'] = lower # dataframe['pcc-upperband'] = upper # # lookup_idxs = dataframe.index.values - (abs(dataframe['mastreak'].values) + 1) # valid_lookups = lookup_idxs >= 0 # dataframe['sbc'] = np.nan # dataframe.loc[valid_lookups, 'sbc'] = dataframe['close'].to_numpy()[lookup_idxs[valid_lookups].astype(int)] # # dataframe['streak-roc'] = 100 * (dataframe['close'] - dataframe['sbc']) / dataframe['sbc'] # # # Trends, Peaks and Crosses # dataframe['candle-up'] = np.where(dataframe['close'] >= dataframe['open'], 1, 0) # dataframe['candle-up-trend'] = np.where(dataframe['candle-up'].rolling(5).sum() >= 3, 1, 0) # # dataframe['rmi-up'] = np.where(dataframe['rmi'] >= dataframe['rmi'].shift(), 1, 0) # dataframe['rmi-up-trend'] = np.where(dataframe['rmi-up'].rolling(5).sum() >= 3, 1, 0) # # dataframe['rmi-dn'] = np.where(dataframe['rmi'] <= dataframe['rmi'].shift(), 1, 0) # dataframe['rmi-dn-count'] = dataframe['rmi-dn'].rolling(8).sum() # # dataframe['streak-bo'] = np.where(dataframe['streak-roc'] < dataframe['pcc-lowerband'], 1, 0) # dataframe['streak-bo-count'] = dataframe['streak-bo'].rolling(8).sum() # # # Indicators used only for ROI and Custom Stoploss # ssldown, sslup = csa.SSLChannels_ATR(dataframe, length=21) # dataframe['sroc'] = csa.SROC(dataframe, roclen=21, emalen=13, smooth=21) # dataframe['ssl-dir'] = np.where(sslup > ssldown, 'up', 'down') # # Base pair informative timeframe indicators # informative = self.dp.get_pair_dataframe(pair=metadata['pair'], timeframe=self.inf_timeframe) # # # Get the "average day range" between the 1d high and 1d low to set up guards # informative['1d-high'] = informative['close'].rolling(24).max() # informative['1d-low'] = informative['close'].rolling(24).min() # informative['adr'] = informative['1d-high'] - informative['1d-low'] # # # Base pair informative timeframe indicators # informative = self.dp.get_pair_dataframe(pair=metadata['pair'], timeframe=self.inf_timeframe) # # # Get the "average day range" between the 1d high and 1d low to set up guards # informative['1d-high'] = informative['close'].rolling(24).max() # informative['1d-low'] = informative['close'].rolling(24).min() # informative['adr'] = informative['1d-high'] - informative['1d-low'] # # dataframe = merge_informative_pair(dataframe, informative, self.timeframe, self.inf_timeframe, ffill=True) # # # # Other stake specific informative indicators # # e.g if stake is BTC and current coin is XLM (pair: XLM/BTC) # if self.config['stake_currency'] in ('BTC', 'ETH'): # coin, stake = metadata['pair'].split('/') # fiat = self.custom_fiat # coin_fiat = f"{coin}/{fiat}" # stake_fiat = f"{stake}/{fiat}" # # # Informative COIN/FIAT e.g. XLM/USD - Base Timeframe # coin_fiat_tf = self.dp.get_pair_dataframe(pair=coin_fiat, timeframe=self.timeframe) # dataframe[f"{fiat}_rmi"] = csa.RMI(coin_fiat_tf, length=55, mom=5) # # # Informative STAKE/FIAT e.g. BTC/USD - Base Timeframe # stake_fiat_tf = self.dp.get_pair_dataframe(pair=stake_fiat, timeframe=self.timeframe) # dataframe[f"{stake}_rmi"] = csa.RMI(stake_fiat_tf, length=55, mom=5) # # # Informatives for BTC/STAKE if not in whitelist # else: # pairs = self.dp.current_whitelist() # btc_stake = f"BTC/{self.config['stake_currency']}" # if not btc_stake in pairs: # self.custom_btc_inf = True # # BTC/STAKE - Base Timeframe # btc_stake_tf = self.dp.get_pair_dataframe(pair=btc_stake, timeframe=self.timeframe) # dataframe['BTC_rmi'] = csa.RMI(btc_stake_tf, length=55, mom=5) # dataframe['BTC_close'] = btc_stake_tf['close'] # dataframe['BTC_kama'] = ta.KAMA(btc_stake_tf, length=144) return dataframe def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame: conditions = list() conditions2 = list() condition1, dataframe = condition_generator( dataframe, buy_operator0, buy_indicator0, buy_crossed_indicator0, 0.7 #self.buy_real_num0.value ) conditions.append(condition1) dataframe.loc[ ( reduce(lambda x, y: x & y, conditions) & (dataframe['volume10'] * dataframe['close'] / 1000 >= 10) & (dataframe['close'] < dataframe['sma10']) & (dataframe['open'] < dataframe['sma10']) & (dataframe['low'] < dataframe['min20']) & (dataframe['percent'] > 0) # & (dataframe['max'] < dataframe['close'] * self.buy_signal_condition_high.value) ), ['buy', 'buy_tag']] = (1, 'buy_signal_condition') #################################################################### condition2, dataframe = condition_generator(dataframe, "/=R", "CMO-10", "HT_DCPERIOD-20", 0.37) conditions2.append(condition2) dataframe.loc[ (reduce(lambda x, y: x & y, conditions2) # & (dataframe['volume10'] * dataframe['close'] / 1000 >= 10) & (dataframe['close'].shift(9) < dataframe['bb_lowerband'].shift(9)) # & (dataframe['max'] < dataframe['close'] * self.buy_signal_bb_width.value) ), ['buy', 'buy_tag']] = (1, 'buy_bb_width_1') #################################################################### conditions = list() condition, dataframe = condition_generator(dataframe, "/= 10) & (dataframe['sma10_pente'] > self.buy_signal_sma10_pente.value) & (dataframe['sma10'].shift(1) < dataframe['sma10'] * self.buy_signal_sma10.value) & (dataframe['sma20'].shift(1) < dataframe['sma20']) & (dataframe['sma50'].shift(1) < dataframe['sma50']) & (dataframe['close'] < dataframe['bb_upperband']) & (dataframe['open'] < dataframe['sma10']) & (dataframe['percent50'] < self.buy_signal_sma_percent50.value) # & (dataframe['max'] < dataframe['close'] * self.buy_signal_sma_max.value) # & (dataframe['close'] < dataframe['min'] * self.buy_signal_sma_min.value) # & (dataframe['close'] > dataframe['1d-low_1h'] * self.buy_signal_sma_min.value) # & (dataframe['close'] < dataframe['1d-high_1h'] * self.buy_signal_sma_max.value) ), ['buy', 'buy_tag']] = (1, 'buy_sma') # print(len(dataframe.keys())) #################################################################### # conditions3 = list() # # condition3, dataframe = condition_generator(dataframe, "D", "MACD-2-10", "CDLIDENTICAL3CROWS-10", 0.88) # conditions3.append(condition3) # # condition3, dataframe = condition_generator(dataframe, "/", "MOM-10", "MACDEXT-0-100", 0.87) # #conditions3.append(condition3) # # if conditions3: # dataframe.loc[ # (reduce(lambda x, y: x & y, conditions3) # # & (dataframe['volume10'] * dataframe['close'] / 1000 >= 10) # & (dataframe['close'].shift(7) < dataframe['bb_lowerband'].shift(7)) # & (dataframe['max'] < dataframe['close'] * self.buy_signal_minus.value) # ), # ['buy', 'buy_tag']] = (1, 'buy_minus_dm') # print(len(dataframe.keys())) # ################################################################### # # dataframe.loc[ # (dataframe['close'] > dataframe['bb_upperband']) # & (dataframe['percent'] > 0.01) # & (dataframe['percent20'] < 0.035) # & (dataframe['cond1'] > 13) # & (dataframe['bb_width'] > 0.02) # & (dataframe['cond1'].shift(4) < 8) # & (dataframe['bb_width'].shift(4) < 0.012) # , ['buy', 'buy_tag']] = (1, 'buy_cond1') # # #################################################################### # # dataframe.loc[ # (dataframe['bb_lower_pente'].shift(4) < -0.50) # & (dataframe['sma10_pente'] > -0.2) # & (dataframe['sma10_pente'].shift(4) < -0.4) # & (dataframe['percent5'] < 0.01) # , ['buy', 'buy_tag']] = (1, 'buy_lower_pente') # # #################################################################### # # dataframe.loc[ # (dataframe['percent50'].shift(4) < -0.05) # & (dataframe['sma10_pente'].shift(1) < 0) # & (dataframe['sma10_pente'] >= 0) # & (dataframe['open'] < dataframe['sma10']) # , ['buy', 'buy_tag']] = (1, 'buy_sma50') # # pandas.set_option('display.max_rows', dataframe.shape[0] + 1) # pandas.set_option('display.max_columns', 30) # print(condition1) # print(dataframe["q_0.1"]) return dataframe def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame: # conditions = list() # # condition1, dataframe = condition_generator( # dataframe, # self.sell_operator0.value, # self.sell_indicator0.value, # self.sell_crossed_indicator0.value, # self.sell_real_num0.value # ) # conditions.append(condition1) # # # print(self.sell_percent.value, ' ', # # self.sell_percent.value + self.sell_percent3.value, ' ', # # self.sell_percent.value + self.sell_percent3.value + self.sell_percent5.value) # dataframe.loc[ # ( # (reduce(lambda x, y: x & y, conditions)) & # (dataframe['percent'] < - self.sell_percent.value) & # (dataframe['percent3'] < - (self.sell_percent3.value + self.sell_percent.value)) & # (dataframe['percent5'] < - (self.sell_percent5.value + self.sell_percent3.value + self.sell_percent.value)) & # (dataframe['close'] < dataframe['open']) # # (((dataframe['bb_lowerband'].shift(2) - dataframe['bb_lowerband']) / dataframe['bb_lowerband']) >= 0.02) # # (((dataframe['close'].shift(1) - dataframe['close']) / dataframe['close']) >= 0.025) # ), 'sell'] = 1 return dataframe