# GodStra Strategy # Author: @Mablue (Masoud Azizi) # github: https://github.com/mablue/ # IMPORTANT:Add to your pairlists inside config.json (Under StaticPairList): # { # "method": "AgeFilter", # "min_days_listed": 30 # }, # IMPORTANT: INSTALL TA BEFOUR RUN(pip install ta) # IMPORTANT: Use Smallest "max_open_trades" for getting best results inside config.json # --- Do not remove these libs --- from freqtrade.strategy.interface import IStrategy from datetime import timedelta, datetime from freqtrade.persistence import Trade from freqtrade.strategy import (BooleanParameter, CategoricalParameter, DecimalParameter, stoploss_from_open, IntParameter, IStrategy, merge_informative_pair, informative, stoploss_from_absolute) from pandas import DataFrame # -------------------------------- from datetime import timezone, timedelta # Add your lib to import here # import talib.abstract as ta from ta import add_all_ta_features from ta.utils import dropna import freqtrade.vendor.qtpylib.indicators as qtpylib from functools import reduce import numpy as np class GodStra(IStrategy): position_adjustment_enable = True columns_logged = False pairs = { pair: { "first_buy": 0, "last_buy": 0.0, "last_min": 999999999999999.5, "last_max": 0, "trade_info": {}, "max_touch": 0.0, "last_sell": 0.0, 'count_of_buys': 0, 'current_profit': 0, 'expected_profit': 0, 'previous_profit': 0, "last_candle": {}, "last_count_of_buys": 0, 'base_stake_amount': 0, 'stop_buy': False, 'last_date': 0, 'stop': False, 'max_profit': 0, 'first_amount': 0, 'total_amount': 0, 'has_gain': 0, 'force_sell': False, 'force_buy': False } for pair in ["BTC/USDC", "ETH/USDC", "DOGE/USDC", "XRP/USDC", "SOL/USDC", "BTC/USDT", "ETH/USDT", "DOGE/USDT", "XRP/USDT", "SOL/USDT"] } # 5/66: 9 trades. 8/0/1 Wins/Draws/Losses. Avg profit 21.83%. Median profit 35.52%. Total profit 1060.11476586 USDT ( 196.50Σ%). Avg duration 3440.0 min. Objective: -7.06960 # +--------+---------+----------+------------------+--------------+-------------------------------+----------------+-------------+ # | Best | Epoch | Trades | Win Draw Loss | Avg profit | Profit | Avg duration | Objective | # |--------+---------+----------+------------------+--------------+-------------------------------+----------------+-------------| # | * Best | 1/500 | 11 | 2 1 8 | 5.22% | 280.74230393 USDT (57.40%) | 2,421.8 m | -2.85206 | # | * Best | 2/500 | 10 | 7 0 3 | 18.76% | 983.46414442 USDT (187.58%) | 360.0 m | -4.32665 | # | * Best | 5/500 | 9 | 8 0 1 | 21.83% | 1,060.11476586 USDT (196.50%) | 3,440.0 m | -7.0696 | # Buy hyperspace params: buy_params = { 'buy-cross-0': 'volatility_kcc', 'buy-indicator-0': 'trend_ichimoku_base', 'buy-int-0': 42, 'buy-oper-0': ' DataFrame: # Add all ta features dataframe = dropna(dataframe) dataframe = add_all_ta_features( dataframe, open="open", high="high", low="low", close="close", volume="volume", fillna=True) # dataframe.to_csv("df.csv", index=True) return dataframe def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame: conditions = list() # /5: Cuz We have 5 Group of variables inside buy_param for i in range(self.dna_size(self.buy_params)): OPR = self.buy_params[f'buy-oper-{i}'] IND = self.buy_params[f'buy-indicator-{i}'] CRS = self.buy_params[f'buy-cross-{i}'] INT = self.buy_params[f'buy-int-{i}'] REAL = self.buy_params[f'buy-real-{i}'] DFIND = dataframe[IND] DFCRS = dataframe[CRS] if OPR == ">": conditions.append(DFIND > DFCRS) elif OPR == "=": conditions.append(np.isclose(DFIND, DFCRS)) elif OPR == "<": conditions.append(DFIND < DFCRS) elif OPR == "CA": conditions.append(qtpylib.crossed_above(DFIND, DFCRS)) elif OPR == "CB": conditions.append(qtpylib.crossed_below(DFIND, DFCRS)) elif OPR == ">I": conditions.append(DFIND > INT) elif OPR == "=I": conditions.append(DFIND == INT) elif OPR == "R": conditions.append(DFIND > REAL) elif OPR == "=R": conditions.append(np.isclose(DFIND, REAL)) elif OPR == " DataFrame: conditions = list() for i in range(self.dna_size(self.sell_params)): OPR = self.sell_params[f'sell-oper-{i}'] IND = self.sell_params[f'sell-indicator-{i}'] CRS = self.sell_params[f'sell-cross-{i}'] INT = self.sell_params[f'sell-int-{i}'] REAL = self.sell_params[f'sell-real-{i}'] DFIND = dataframe[IND] DFCRS = dataframe[CRS] if OPR == ">": conditions.append(DFIND > DFCRS) elif OPR == "=": conditions.append(np.isclose(DFIND, DFCRS)) elif OPR == "<": conditions.append(DFIND < DFCRS) elif OPR == "CA": conditions.append(qtpylib.crossed_above(DFIND, DFCRS)) elif OPR == "CB": conditions.append(qtpylib.crossed_below(DFIND, DFCRS)) elif OPR == ">I": conditions.append(DFIND > INT) elif OPR == "=I": conditions.append(DFIND == INT) elif OPR == "R": conditions.append(DFIND > REAL) elif OPR == "=R": conditions.append(np.isclose(DFIND, REAL)) elif OPR == "= max_stake: return 0 dataframe, _ = self.dp.get_analyzed_dataframe(trade.pair, self.timeframe) last_candle = dataframe.iloc[-1].squeeze() before_last_candle = dataframe.iloc[-2].squeeze() # prépare les données current_time = current_time.astimezone(timezone.utc) open_date = trade.open_date.astimezone(timezone.utc) dispo = round(self.wallets.get_available_stake_amount()) hours_since_first_buy = (current_time - trade.open_date_utc).seconds / 3600.0 days_since_first_buy = (current_time - trade.open_date_utc).days hours = (current_time - trade.date_last_filled_utc).total_seconds() / 3600.0 count_of_buys = trade.nr_of_successful_entries current_time_utc = current_time.astimezone(timezone.utc) open_date = trade.open_date.astimezone(timezone.utc) days_since_open = (current_time_utc - open_date).days pair = trade.pair profit = trade.calc_profit(current_rate) #round(current_profit * trade.stake_amount, 1) last_lost = self.getLastLost(last_candle, pair) pct_first = 0 total_counts = sum( pair_data['count_of_buys'] for pair_data in self.pairs.values() if not self.getShortName(pair) == 'BTC') if self.pairs[pair]['first_buy']: pct_first = self.getPctFirstBuy(pair, last_candle) lim = 0.3 if (len(dataframe) < 1): # self.printLog("skip dataframe") return None # Dernier prix d'achat réel (pas le prix moyen) last_fill_price = self.pairs[trade.pair]['last_buy'] #trade.open_rate # remplacé juste après ↓ # if len(trade.orders) > 0: # # On cherche le dernier BUY exécuté # buy_orders = [o for o in trade.orders if o.is_buy and o.status == "closed"] # if buy_orders: # last_fill_price = buy_orders[-1].price # baisse relative dca_threshold = 0.0025 * count_of_buys decline = (last_fill_price - current_rate) / last_fill_price increase = - decline # if decline >= self.dca_threshold: # # Exemple : on achète 50% du montant du dernier trade # last_amount = buy_orders[-1].amount if buy_orders else 0 # stake_amount = last_amount * current_rate * 0.5 # return stake_amount condition = last_candle['percent'] > 0 #and last_candle['sma24_deriv1'] > 0 limit_buy = 40 # or (last_candle['close'] <= last_candle['min180'] and hours > 3) if (decline >= dca_threshold) and condition: print('decline') try: if self.pairs[pair]['has_gain'] and profit > 0: self.pairs[pair]['force_sell'] = True self.pairs[pair]['previous_profit'] = profit return None max_amount = self.config.get('stake_amount') * 2.5 stake_amount = min(min(max_amount, self.wallets.get_available_stake_amount()), self.adjust_stake_amount(pair, last_candle)) # print(f"profit={profit} previous={self.pairs[pair]['previous_profit']} count_of_buys={trade.nr_of_successful_entries}") if stake_amount > 0: self.pairs[pair]['previous_profit'] = profit trade_type = "Loss " + (last_candle['enter_tag'] if last_candle['enter_long'] == 1 else '') self.pairs[trade.pair]['count_of_buys'] += 1 self.pairs[pair]['total_amount'] += stake_amount # self.log_trade( # last_candle=last_candle, # date=current_time, # action="🟧 Loss -", # dispo=dispo, # pair=trade.pair, # rate=current_rate, # trade_type=trade_type, # profit=round(profit, 1), # buys=trade.nr_of_successful_entries + 1, # stake=round(stake_amount, 2) # ) self.pairs[trade.pair]['last_buy'] = current_rate self.pairs[trade.pair]['max_touch'] = last_candle['close'] self.pairs[trade.pair]['last_candle'] = last_candle # df = pd.DataFrame.from_dict(self.pairs, orient='index') # colonnes_a_exclure = ['last_candle', 'stop', # 'trade_info', 'last_date', 'expected_profit', 'last_count_of_buys', 'base_stake_amount', 'stop_buy'] # df_filtered = df[df['count_of_buys'] > 0].drop(columns=colonnes_a_exclure) # # df_filtered = df_filtered["first_buy", "last_max", "max_touch", "last_sell","last_buy", 'count_of_buys', 'current_profit'] # # self.printLog(df_filtered) return stake_amount return None except Exception as exception: self.printLog(exception) return None if current_profit > dca_threshold and (increase >= dca_threshold and self.wallets.get_available_stake_amount() > 0): print('increase') try: self.pairs[pair]['previous_profit'] = profit stake_amount = max(20, min(self.wallets.get_available_stake_amount(), self.adjust_stake_amount(pair, last_candle))) if stake_amount > 0: self.pairs[pair]['has_gain'] += 1 trade_type = 'Gain +' + (last_candle['enter_tag'] if last_candle['enter_long'] == 1 else '') self.pairs[trade.pair]['count_of_buys'] += 1 self.pairs[pair]['total_amount'] += stake_amount # self.log_trade( # last_candle=last_candle, # date=current_time, # action="🟡 Gain +", # dispo=dispo, # pair=trade.pair, # rate=current_rate, # trade_type='Gain', # profit=round(profit, 1), # buys=trade.nr_of_successful_entries + 1, # stake=round(stake_amount, 2) # ) self.pairs[trade.pair]['last_buy'] = current_rate self.pairs[trade.pair]['max_touch'] = last_candle['close'] self.pairs[trade.pair]['last_candle'] = last_candle return stake_amount return None except Exception as exception: self.printLog(exception) return None return None