synchronise HeikinAshi

This commit is contained in:
Jérôme Delacotte
2025-03-22 17:54:06 +01:00
parent 59daa1af70
commit 117d466722
3 changed files with 478 additions and 250 deletions

View File

@@ -274,7 +274,6 @@ class HammerReversalStrategy(IStrategy):
self.pairs[pair]['max_touch'] = max(last_candle['haclose'], self.pairs[pair]['max_touch']) self.pairs[pair]['max_touch'] = max(last_candle['haclose'], self.pairs[pair]['max_touch'])
# On ne déclenche le trailing stop que si un profit mini a déjà été atteint # On ne déclenche le trailing stop que si un profit mini a déjà été atteint
# and (limit_sell < -0.01) # and (limit_sell < -0.01)
if (current_profit > 0.01) and (last_candle['percent12'] < 0) and (last_candle['percent5'] < 0): if (current_profit > 0.01) and (last_candle['percent12'] < 0) and (last_candle['percent5'] < 0):

View File

@@ -32,23 +32,14 @@ from ta.utils import dropna
import freqtrade.vendor.qtpylib.indicators as qtpylib import freqtrade.vendor.qtpylib.indicators as qtpylib
from functools import reduce from functools import reduce
import numpy as np import numpy as np
from scipy.special import binom
from ta.trend import SMAIndicator, EMAIndicator, MACD, ADXIndicator
from ta.momentum import RSIIndicator, StochasticOscillator
class HeikinAshi(IStrategy): class HeikinAshi(IStrategy):
plot_config = { plot_config = {
"main_plot": { "main_plot": {
"min12": {
"color": "#197260"
},
'max12': {
'color': 'green'
},
"haclose": {
"color": "red"
},
'haopen': {
'color': 'blue'
},
"min288": { "min288": {
"color": "#197260" "color": "#197260"
}, },
@@ -57,13 +48,47 @@ class HeikinAshi(IStrategy):
}, },
'mid288': { 'mid288': {
'color': 'blue' 'color': 'blue'
} },
'hasma5': {
'color': 'red'
},
'max48': {
'color': 'yellow'
},
'min48': {
'color': 'yellow'
},
'sma12': {
'color': 'pink'
},
'ema5_1d': {
'color': "#74effc"
},
'ema20_1d': {
'color': "cyan"
},
}, },
"subplots": { "subplots": {
"Percent": { "Percent": {
"hapercent": { "hapercent": {
"color": "#74effc" "color": "#74effc"
} }
},
'up_down': {
'up_pct': {
'color': 'red'
},
'down_pct': {
'color': 'blue'
}
},
'tag': {
'rsi_downtrend': {
'color': 'red'
},
'ma_downtrend': {
'color': 'blue'
}
} }
} }
@@ -92,7 +117,7 @@ class HeikinAshi(IStrategy):
# Optimal timeframe use it in your config # Optimal timeframe use it in your config
timeframe = '5m' timeframe = '5m'
columns_logged = False columns_logged = False
max_entry_position_adjustment = 20 max_entry_position_adjustment = 30
startup_candle_count = 288 startup_candle_count = 288
# Trailing stoploss # Trailing stoploss
@@ -100,7 +125,7 @@ class HeikinAshi(IStrategy):
# trailing_stop_positive = 0.001 # trailing_stop_positive = 0.001
# trailing_stop_positive_offset = 0.015 # trailing_stop_positive_offset = 0.015
# trailing_only_offset_is_reached = True # trailing_only_offset_is_reached = True
position_adjustment_enable = False position_adjustment_enable = True
pairs = { pairs = {
pair: { pair: {
@@ -108,12 +133,18 @@ class HeikinAshi(IStrategy):
"trade_info": {}, "trade_info": {},
"max_touch": 0.0, "max_touch": 0.0,
"last_sell": 0.0, "last_sell": 0.0,
"last_buy": 0.0 "last_buy": 0.0,
'count_of_buys': 0,
'current_profit': 0,
'expected_profit': 0,
"last_candle": {},
"last_trade": None,
'base_stake_amount': 0
} }
for pair in ["BTC/USDT", "ETH/USDT", "DOGE/USDT", "DASH/USDT", "XRP/USDT", "SOL/USDT"] for pair in ["BTC/USDT", "ETH/USDT", "DOGE/USDT", "DASH/USDT", "XRP/USDT", "SOL/USDT"]
} }
decalage = IntParameter(0, 48, default=12, space='buy') decalage = IntParameter(0, 10, default=3, space='buy')
########################################## END RESULT PASTE PLACE ##################################### ########################################## END RESULT PASTE PLACE #####################################
# ------------------------------------------------------------------------------------------------------------------ # ------------------------------------------------------------------------------------------------------------------
@@ -125,26 +156,95 @@ class HeikinAshi(IStrategy):
**kwargs **kwargs
) -> Union[Optional[float], Tuple[Optional[float], Optional[str]]]: ) -> Union[Optional[float], Tuple[Optional[float], Optional[str]]]:
# ne rien faire si ordre deja en cours # ne rien faire si ordre deja en cours
if trade.has_open_orders: if trade.has_open_orders:
return None return None
if (self.wallets.get_available_stake_amount() < 50): # or trade.stake_amount >= max_stake:
return 0
dataframe, _ = self.dp.get_analyzed_dataframe(trade.pair, self.timeframe) dataframe, _ = self.dp.get_analyzed_dataframe(trade.pair, self.timeframe)
last_candle = dataframe.iloc[-1].squeeze() last_candle = dataframe.iloc[-1].squeeze()
last_candle_24 = dataframe.iloc[-25].squeeze() # last_candle_decalage = dataframe.iloc[-1 - self.decalage.value].squeeze()
# last_candle_24 = dataframe.iloc[-25].squeeze()
# if (last_candle['sma5_diff_1d'] < -0.1):
# return None
# prépare les données # prépare les données
count_of_buys = trade.nr_of_successful_entries count_of_buys = trade.nr_of_successful_entries
current_time = current_time.astimezone(timezone.utc) current_time = current_time.astimezone(timezone.utc)
open_date = trade.open_date.astimezone(timezone.utc) open_date = trade.open_date.astimezone(timezone.utc)
dispo = round(self.wallets.get_available_stake_amount()) dispo = round(self.wallets.get_available_stake_amount())
hours = (current_time - trade.date_last_filled_utc).total_seconds() / 3600.0
limit_buy = 4 # if (current_profit > 0.008) \
# and (last_candle['up_pct'] >= 1)\
# and (last_candle['volume'] >= 250) \
# and (hours >= 1):
# additional_stake = self.config['stake_amount']
# self.log_trade(
# last_candle=last_candle,
# date=current_time,
# action="Gain +",
# dispo=dispo,
# pair=trade.pair,
# rate=current_rate,
# trade_type='Increase',
# profit=round(current_profit, 4), # round(current_profit * trade.stake_amount, 2),
# buys=trade.nr_of_successful_entries,
# stake=round(additional_stake, 2)
# )
# # self.pairs[trade.pair]['last_max'] = last_candle['haclose']
# self.pairs[trade.pair]['max_touch'] = last_candle['haclose']
# return additional_stake
# if (last_candle['percent'] > 0.001) and (current_profit > 0):
# # and (last_candle_decalage['min12'] == last_candle['min12']) \
# # and (last_candle_decalage['close'] < last_candle_decalage['mid288']):
# additional_stake = self.config['stake_amount'] / 10
# self.log_trade(
# last_candle=last_candle,
# date=current_time,
# action="Gain +",
# dispo=dispo,
# pair=trade.pair,
# rate=current_rate,
# trade_type='Increase',
# profit=round(current_profit, 4), # round(current_profit * trade.stake_amount, 2),
# buys=trade.nr_of_successful_entries,
# stake=round(additional_stake, 2)
# )
# return additional_stake
max_touch = self.pairs[trade.pair]['max_touch']
pct_max = - round(100 * (last_candle['close'] - max_touch) / max_touch, 1)
# if (last_candle['enter_long'] == 1) and (current_profit < - 0.0075 or hours >= 1) and (count_of_buys == 1):
# additional_stake = self.config['stake_amount'] / 2
# self.log_trade(
# last_candle=last_candle,
# date=current_time,
# action="Long",
# dispo=dispo,
# pair=trade.pair,
# rate=current_rate,
# trade_type='Increase',
# profit=round(current_profit, 4), # round(current_profit * trade.stake_amount, 2),
# buys=trade.nr_of_successful_entries + 1,
# stake=round(additional_stake, 2)
# )
# self.expectedProfit(trade.pair, last_candle, current_rate)
# 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 additional_stake
limit_buy = 5
if (count_of_buys < limit_buy) \ if (count_of_buys < limit_buy) \
and (last_candle['min288'] == last_candle_24['min288']) \ and ((last_candle['enter_long'] == 1)) \
and (current_profit < -0.01 * count_of_buys) \ and (current_profit < -0.015 * count_of_buys):
and (last_candle['close'] < last_candle['mid288']): # and (last_candle_decalage['min12'] == last_candle['min12']) \
additional_stake = self.config['stake_amount'] # and (last_candle_decalage['close'] < last_candle_decalage['mid288']):
additional_stake = self.calculate_stake(trade.pair, last_candle, 1) # self.config['stake_amount']
self.log_trade( self.log_trade(
last_candle=last_candle, last_candle=last_candle,
date=current_time, date=current_time,
@@ -154,12 +254,39 @@ class HeikinAshi(IStrategy):
rate=current_rate, rate=current_rate,
trade_type='Decrease', trade_type='Decrease',
profit=round(current_profit, 4), # round(current_profit * trade.stake_amount, 2), profit=round(current_profit, 4), # round(current_profit * trade.stake_amount, 2),
buys=trade.nr_of_successful_entries, buys=trade.nr_of_successful_entries + 1,
stake=round(additional_stake, 2) stake=round(additional_stake, 2)
) )
self.expectedProfit(trade.pair, last_candle, current_rate)
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 additional_stake return additional_stake
if (count_of_buys >= limit_buy) & (current_profit < - 0.03 * count_of_buys):
additional_stake = self.config['stake_amount'] * 2 # if (count_of_buys == limit_buy) & (current_profit < - 0.03 * count_of_buys)\
# and ((last_candle['enter_long'] == 1) or last_candle['percent48'] < - 0.03):
# additional_stake = - trade.stake_amount / 2 #self.config['stake_amount'] * (-current_profit / 0.10)
# self.log_trade(
# last_candle=last_candle,
# date=current_time,
# action="Loss -",
# dispo=dispo,
# pair=trade.pair,
# rate=current_rate,
# trade_type='Decrease',
# profit=round(current_profit, 4), # round(current_profit * trade.stake_amount, 2),
# buys=trade.nr_of_successful_entries,
# stake=round(additional_stake, 2)
# )
# # self.pairs[trade.pair]['last_max'] = last_candle['haclose']
# self.pairs[trade.pair]['max_touch'] = last_candle['haclose']
# return additional_stake
pct_limit = (-0.015 * limit_buy) + (- 0.03 * (count_of_buys - limit_buy))
if (count_of_buys >= limit_buy) & (current_profit < pct_limit) \
and ((last_candle['enter_long'] == 1) or last_candle['percent48'] < - 0.03):
additional_stake = self.calculate_stake(trade.pair, last_candle, 1) * (-current_profit / 0.10)
self.log_trade( self.log_trade(
last_candle=last_candle, last_candle=last_candle,
date=current_time, date=current_time,
@@ -169,15 +296,49 @@ class HeikinAshi(IStrategy):
rate=current_rate, rate=current_rate,
trade_type='Decrease', trade_type='Decrease',
profit=round(current_profit, 4), # round(current_profit * trade.stake_amount, 2), profit=round(current_profit, 4), # round(current_profit * trade.stake_amount, 2),
buys=trade.nr_of_successful_entries, buys=trade.nr_of_successful_entries + 1,
stake=round(additional_stake, 2) stake=round(additional_stake, 2)
) )
self.expectedProfit(trade.pair, last_candle, current_rate)
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 additional_stake return additional_stake
return None return None
def custom_stake_amount(self, pair: str, current_time: datetime, current_rate: float,
proposed_stake: float, min_stake: float, max_stake: float,
**kwargs) -> float:
dataframe, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe)
# Obtenir les données actuelles pour cette paire
last_candle = dataframe.iloc[-1].squeeze()
stake_amount = self.config['stake_amount']
# if last_candle['close'] < last_candle['max5_1d'] * 0.98 :
# stake_amount = 2 * stake_amount
# else:
# if last_candle['close'] > last_candle['max5_1d'] * 1.02:
# stake_amount = 0.5 * stake_amount
# if last_candle['entry_tag'] == 'buy_hammer':
# stake_amount = stake_amount * 2
return stake_amount
def calculate_stake(self, pair, last_candle, factor=1): def calculate_stake(self, pair, last_candle, factor=1):
amount = self.config['stake_amount'] * factor #1000 / self.first_stack_factor.value self.protection_stake_amount.value #
# if self.pairs[pair]['count_of_buys'] == 1 and factor == 1:
# if last_candle['close'] > last_candle['min5_1d'] + (last_candle['max5_1d'] - last_candle['min5_1d']) / 2:
# factor = 0.5
# amount = self.config['stake_amount'] * factor
# else:
# amount = self.config['stake_amount']
# self.pairs[pair]['base_stake_amount'] = amount
# else:
# amount = max(self.config['stake_amount'], self.pairs[pair]['base_stake_amount'])
amount = self.config['stake_amount']
return amount return amount
def confirm_trade_entry(self, pair: str, order_type: str, amount: float, rate: float, time_in_force: str, def confirm_trade_entry(self, pair: str, order_type: str, amount: float, rate: float, time_in_force: str,
@@ -185,8 +346,32 @@ class HeikinAshi(IStrategy):
dataframe, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe) dataframe, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe)
last_candle = dataframe.iloc[-1].squeeze() last_candle = dataframe.iloc[-1].squeeze()
dispo = round(self.wallets.get_available_stake_amount()) dispo = round(self.wallets.get_available_stake_amount())
# if (self.pairs[pair]['last_sell'] > 0) and (last_candle['close'] * 1.01 > self.pairs[pair]['last_sell']):
# self.log_trade(
# last_candle=last_candle,
# date=current_time,
# action="CANCEL BUY",
# pair=pair,
# rate=rate,
# dispo=dispo,
# profit=0,
# stake=round(stake_amount, 2)
# )
# return False
self.pairs[pair]['last_buy'] = rate
self.pairs[pair]['max_touch'] = last_candle['close']
self.pairs[pair]['last_max'] = last_candle['close']
self.pairs[pair]['last_candle'] = last_candle
self.pairs[pair]['count_of_buys'] = 1
self.pairs[pair]['current_profit'] = 0
stake_amount = self.calculate_stake(pair, last_candle, 1) stake_amount = self.calculate_stake(pair, last_candle, 1)
# self.columns_logged = False
print(
f"|{'-' * 18}+{'-' * 12}+{'-' * 12}+{'-' * 20}+{'-' * 14}+{'-' * 8}+{'-' * 10}+{'-' * 7}+{'-' * 13}+{'-' * 14}+{'-' * 14}+{'-' * 7}+{'-' * 12}|"
)
self.log_trade( self.log_trade(
last_candle=last_candle, last_candle=last_candle,
date=current_time, date=current_time,
@@ -195,8 +380,11 @@ class HeikinAshi(IStrategy):
rate=rate, rate=rate,
dispo=dispo, dispo=dispo,
profit=0, profit=0,
trade_type=entry_tag,
buys=1,
stake=round(stake_amount, 2) stake=round(stake_amount, 2)
) )
self.expectedProfit(pair, last_candle, rate)
return True return True
def confirm_trade_exit(self, pair: str, trade: Trade, order_type: str, amount: float, rate: float, def confirm_trade_exit(self, pair: str, trade: Trade, order_type: str, amount: float, rate: float,
@@ -210,10 +398,9 @@ class HeikinAshi(IStrategy):
allow_to_sell = (last_candle['percent5'] < -0.00) allow_to_sell = (last_candle['percent5'] < -0.00)
ok = (allow_to_sell) | (exit_reason == 'force_exit') ok = (allow_to_sell) | (exit_reason == 'force_exit')
if ok: if ok:
# self.pairs[pair]['last_max'] = 0
# self.pairs[pair]['max_touch'] = 0
self.pairs[pair]['last_buy'] = 0
self.pairs[pair]['last_sell'] = rate self.pairs[pair]['last_sell'] = rate
self.pairs[pair]['last_trade'] = trade
self.pairs[pair]['last_candle'] = last_candle
self.log_trade( self.log_trade(
last_candle=last_candle, last_candle=last_candle,
date=current_time, date=current_time,
@@ -224,7 +411,11 @@ class HeikinAshi(IStrategy):
dispo=dispo, dispo=dispo,
profit=round(trade.calc_profit(rate, amount), 2) profit=round(trade.calc_profit(rate, amount), 2)
) )
#print(f"Sell {current_time} {exit_reason} rate={rate:.3f} amount={amount} profit={amount * rate:.3f}") self.pairs[pair]['last_max'] = 0
self.pairs[pair]['max_touch'] = 0
self.pairs[pair]['last_buy'] = 0
# print(f"Sell {current_time} {exit_reason} rate={rate:.3f} amount={amount} profit={amount * rate:.3f}")
return ok return ok
@@ -232,23 +423,94 @@ class HeikinAshi(IStrategy):
dataframe, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe) dataframe, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe)
last_candle = dataframe.iloc[-1].squeeze() last_candle = dataframe.iloc[-1].squeeze()
before_last_candle = dataframe.iloc[-2].squeeze()
if (current_profit > 0.004) \ max_touch_before = self.pairs[pair]['max_touch']
& (last_candle['hapercent'] < 0.0) \ last_max_before = self.pairs[pair]['last_max']
& (last_candle['percent'] < 0.0): self.pairs[pair]['last_max'] = max(last_candle['haclose'], self.pairs[pair]['last_max'])
last_lost = (last_candle['close'] - max_touch_before) / max_touch_before
count_of_buys = trade.nr_of_successful_entries count_of_buys = trade.nr_of_successful_entries
return 'profit_' + str(count_of_buys)
def log_trade(self, action, pair, date, trade_type=None, rate=None, dispo=None, profit=None, buys=None, stake=None, last_candle=None): self.pairs[pair]['count_of_buys'] = count_of_buys
self.pairs[pair]['current_profit'] = current_profit
days = (current_time - trade.open_date_utc).days
days = max(1, days)
factor = 1
# if days > 10:
# factor = 1 + days / 10
expected_profit = self.pairs[pair]['expected_profit'] / factor
# print(
# f"{current_time} days={days} expected={expected_profit:.3f} rate={current_rate} max_touch={max_touch_before:.1f} profit={current_profit:.3f} last_lost={last_lost:.3f} buys={count_of_buys} percent={last_candle['percent']:.4f}")
if (current_profit > expected_profit) \
& (last_candle['percent'] < 0.0) \
& (last_lost > - current_profit / 5):
# & (before_last_candle['hasma5'] < last_candle['hasma5']):
# & (last_lost < min(-0.003, - min(0.006, current_profit / 4))):
# & (last_candle['up_count'] > 0):
return 'last_lost_' + str(count_of_buys)
self.pairs[pair]['max_touch'] = max(last_candle['haclose'], self.pairs[pair]['max_touch'])
# if (current_profit > 0.004) \
# & (last_candle['hapercent'] < 0.0) \
# & (last_candle['percent3'] < - min(0.01, current_profit / 4)):
# return 'profit_' + str(count_of_buys)
def detect_loose_hammer(self, df: DataFrame) -> DataFrame:
"""
Détection large de marteaux : accepte des corps plus gros, ne vérifie pas le volume,
ne demande pas de divergence, juste un pattern visuel simple.
"""
body = abs(df['close'] - df['open'])
upper_shadow = abs(df['high'] - np.maximum(df['close'], df['open']))
lower_shadow = abs(np.minimum(df['close'], df['open']) - df['low'])
# Critères simplifiés :
df['loose_hammer'] = (
(lower_shadow > body * 2.5) # mèche basse > 1.5x corps
& (upper_shadow < body) # petite mèche haute
& (df['low'] < df['bb_lowerband']) # bougie verte (optionnel, on peut prendre aussi les rouges)
).astype(int)
df['won_hammer'] = (
(upper_shadow > body * 2.5) # mèche basse > 1.5x corps
& (lower_shadow < body) # petite mèche haute
& (df['high'] > df['bb_upperband']) # bougie verte (optionnel, on peut prendre aussi les rouges)
).astype(int)
return df
def expectedProfit(self, pair: str, last_candle, current_rate):
last_buy = self.pairs[pair]['last_buy']
max_touch = self.pairs[pair]['max_touch']
last_max = self.pairs[pair]['last_max']
expected_profit = ((max_touch - last_buy) / max_touch)
self.pairs[pair]['expected_profit'] = max(0.004, expected_profit)
# print(f"expected max_touch={max_touch:.1f} last_buy={last_buy:.1f} expected={expected_profit:.3f} max5_1d={last_candle['max5_1d']:.1f}")
return expected_profit
def log_trade(self, action, pair, date, trade_type=None, rate=None, dispo=None, profit=None, buys=None, stake=None,
last_candle=None):
# Afficher les colonnes une seule fois # Afficher les colonnes une seule fois
if self.config.get('runmode') == 'hyperopt': if self.config.get('runmode') == 'hyperopt':
return return
if self.columns_logged % 30 == 0: if self.columns_logged % 30 == 0:
# print(
# f"|{'-' * 18}+{'-' * 12}+{'-' * 12}+{'-' * 20}+{'-' * 14}+{'-' * 8}+{'-' * 10}+{'-' * 7}+{'-' * 13}+{'-' * 14}+{'-' * 14}+{'-' * 7}+{'-' * 12}|"
# )
print( print(
f"| {'Date':<16} | {'Action':<10} | {'Pair':<10} | {'Trade Type':<18} | {'Rate':>12} | {'Dispo':>6} | {'Profit':>8} | {'Pct':>5} | {'max7_1d':>11} | {'max_touch':>12} | {'last_max':>12} | {'Buys':>5} | {'Stake':>10} |" f"| {'Date':<16} | {'Action':<10} | {'Pair':<10} | {'Trade Type':<18} | {'Rate':>12} | {'Dispo':>6} | {'Profit':>8} | {'Pct':>5} | {'max_touch':>11} | {'last_lost':>12} | {'last_max':>12} | {'Buys':>5} | {'Stake':>10} |"
) )
print( print(
f"|{'-' * 18}|{'-' * 12}|{'-' * 12}|{'-' * 20}|{'-' * 14}|{'-' * 8}|{'-' * 10}|{'-' * 7}|{'-' * 13}|{'-' * 14}|{'-' * 14}|{'-' * 7}|{'-' * 12}|" f"|{'-' * 18}+{'-' * 12}+{'-' * 12}+{'-' * 20}+{'-' * 14}+{'-' * 8}+{'-' * 10}+{'-' * 7}+{'-' * 13}+{'-' * 14}+{'-' * 14}+{'-' * 7}+{'-' * 12}|"
) )
self.columns_logged += 1 self.columns_logged += 1
date = str(date)[:16] if date else "-" date = str(date)[:16] if date else "-"
@@ -279,28 +541,46 @@ class HeikinAshi(IStrategy):
# if action != 'Sell': # if action != 'Sell':
# profit = round((last_candle['close'] - self.pairs[pair]['last_max']) / self.pairs[pair]['last_max'], 2) # profit = round((last_candle['close'] - self.pairs[pair]['last_max']) / self.pairs[pair]['last_max'], 2)
last_lost = round((last_candle['haclose'] - self.pairs[pair]['max_touch']) / self.pairs[pair]['max_touch'], 3)
limit_sell = rsi_pct # round((last_candle['close'] - self.pairs[pair]['last_max']) / self.pairs[pair]['last_max'], 4) limit_sell = rsi_pct # round((last_candle['close'] - self.pairs[pair]['last_max']) / self.pairs[pair]['last_max'], 4)
max7_1d = round(self.pairs[pair]['max_touch'], 1) #last_candle['max7_1d'] #round(100 * (last_candle['close'] - self.pairs[pair]['last_max']) / self.pairs[pair]['last_max'], 1) max_touch = round(self.pairs[pair]['max_touch'],
pct_max = round(100 * (last_candle['close'] - max7_1d) / max7_1d, 1) 1) # last_candle['max7_1d'] #round(100 * (last_candle['close'] - self.pairs[pair]['last_max']) / self.pairs[pair]['last_max'], 1)
pct_max = round(100 * self.pairs[pair]['current_profit'],
1) # round(100 * (last_candle['close'] - max_touch) / max_touch, 1)
if trade_type is not None:
trade_type = trade_type + " " + str(round(100 * self.pairs[pair]['expected_profit'], 1))
print( print(
f"| {date:<16} | {action:<10} | {pair:<10} | {trade_type or '-':<18} | {rate or '-':>12} | {dispo or '-':>6} | {profit or '-':>8} | {pct_max or '-':>5} | {max7_1d or '-':>11} | {round(self.pairs[pair]['max_touch'], 2) or '-':>12} | {round(self.pairs[pair]['last_max'],2) or '-':>12} | {buys or '-':>5} | {stake or '-':>10} |" f"| {date:<16} | {action:<10} | {pair:<10} | {trade_type or '-':<18} | {rate or '-':>12} | {dispo or '-':>6} | {profit or '-':>8} | {pct_max or '-':>5} | {max_touch or '-':>11} | {last_lost or '-':>12} | {round(self.pairs[pair]['last_max'], 2) or '-':>12} | {self.pairs[pair]['count_of_buys'] or '-':>5} | {stake or '-':>10} |"
) )
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame: def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
heikinashi = qtpylib.heikinashi(dataframe) heikinashi = qtpylib.heikinashi(dataframe)
dataframe['haopen'] = heikinashi['open'] dataframe['haopen'] = heikinashi['open']
dataframe['haclose'] = heikinashi['close'] dataframe['haclose'] = heikinashi['close']
dataframe['hamid'] = dataframe['haclose'] + (dataframe['haopen'] - dataframe['haclose']) / 2
dataframe['mid'] = dataframe['open'] + (dataframe['close'] - dataframe['open']) / 2
dataframe['sma12'] = dataframe['mid'].rolling(12).sum() / 12
dataframe['hasma5'] = dataframe['hamid'].rolling(5).sum() / 5
dataframe['hasma5_diff'] = dataframe['hasma5'] - dataframe['hasma5'].shift(1)
dataframe['halow'] = heikinashi['low'] dataframe['halow'] = heikinashi['low']
dataframe['hapercent'] = (dataframe['haclose'] - dataframe['haopen']) / dataframe['haclose'] dataframe['hapercent'] = (dataframe['haclose'] - dataframe['haopen']) / dataframe['haclose']
dataframe['min12'] = talib.MIN(dataframe['close'], timeperiod=12) dataframe['min12'] = talib.MIN(dataframe['close'], timeperiod=12)
dataframe['max12'] = talib.MAX(dataframe['close'], timeperiod=12) dataframe['max12'] = talib.MAX(dataframe['close'], timeperiod=12)
dataframe['min48'] = talib.MIN(dataframe['close'], timeperiod=48)
dataframe['max48'] = talib.MAX(dataframe['close'], timeperiod=48)
dataframe['min288'] = talib.MIN(dataframe['close'], timeperiod=288) dataframe['min288'] = talib.MIN(dataframe['close'], timeperiod=288)
dataframe['max288'] = talib.MAX(dataframe['close'], timeperiod=288) dataframe['max288'] = talib.MAX(dataframe['close'], timeperiod=288)
dataframe['mid288'] = dataframe['min288'] + (dataframe['max288'] - dataframe['min288']) / 2 dataframe['mid288'] = dataframe['min288'] + (dataframe['max288'] - dataframe['min288']) / 2
dataframe["percent"] = (dataframe["close"] - dataframe["open"]) / dataframe["open"] dataframe["percent"] = (dataframe["close"] - dataframe["open"]) / dataframe["open"]
dataframe["percent3"] = dataframe['close'].pct_change(3)
dataframe["percent5"] = dataframe['close'].pct_change(5) dataframe["percent5"] = dataframe['close'].pct_change(5)
dataframe["percent12"] = dataframe['close'].pct_change(12)
dataframe["percent48"] = dataframe['close'].pct_change(48)
# Bollinger Bands # Bollinger Bands
bollinger = qtpylib.bollinger_bands(qtpylib.typical_price(dataframe), window=20, stds=2) bollinger = qtpylib.bollinger_bands(qtpylib.typical_price(dataframe), window=20, stds=2)
@@ -309,26 +589,95 @@ class HeikinAshi(IStrategy):
dataframe['bb_upperband'] = bollinger['upper'] dataframe['bb_upperband'] = bollinger['upper']
dataframe['bb_diff'] = (dataframe['bb_upperband'] - dataframe['bb_lowerband']) / dataframe['bb_lowerband'] dataframe['bb_diff'] = (dataframe['bb_upperband'] - dataframe['bb_lowerband']) / dataframe['bb_lowerband']
# Compter les baisses consécutives
dataframe['down'] = dataframe['hapercent'] <= 0.001
dataframe['up'] = dataframe['hapercent'] >= -0.001
dataframe['down_count'] = - dataframe['down'].astype(int) * (
dataframe['down'].groupby((dataframe['down'] != dataframe['down'].shift()).cumsum()).cumcount() + 1)
dataframe['up_count'] = dataframe['up'].astype(int) * (
dataframe['up'].groupby((dataframe['up'] != dataframe['up'].shift()).cumsum()).cumcount() + 1)
dataframe['down_tag'] = (dataframe['down_count'] < -7)
dataframe['up_tag'] = (dataframe['up_count'] > 7)
# Créer une colonne vide
dataframe['down_pct'] = self.calculateUpDownPct(dataframe, 'down_count')
dataframe['up_pct'] = self.calculateUpDownPct(dataframe, 'up_count')
# # ======================================================================================Decrease
# ################### INFORMATIVE 1d
informative = self.dp.get_pair_dataframe(pair=metadata['pair'], timeframe="1d")
# # Moving Averages
# informative['ema5'] = EMAIndicator(informative['close'], window=5).ema_indicator()
# informative['ema20'] = EMAIndicator(informative['close'], window=20).ema_indicator()
# informative['ma_downtrend'] = (informative['close'] < informative['ema5']) & (informative['ema5'] < informative['ema20'])
#
# # RSI
# informative['rsi'] = RSIIndicator(informative['close'], window=14).rsi()
# informative['rsi_downtrend'] = informative['rsi'] < 50
informative['max5'] = talib.MAX(informative['close'], timeperiod=5)
informative['max12'] = talib.MAX(informative['close'], timeperiod=12)
informative['min5'] = talib.MIN(informative['close'], timeperiod=5)
informative['min12'] = talib.MIN(informative['close'], timeperiod=12)
informative['sma5'] = talib.SMA(informative, timeperiod=25)
informative['sma5_diff'] = 100 * (informative['sma5'] - informative['sma5'].shift(1)) / informative['sma5']
# informative = self.detect_loose_hammer(informative)
dataframe = merge_informative_pair(dataframe, informative, self.timeframe, "1d", ffill=True)
dataframe = self.detect_loose_hammer(dataframe)
return dataframe return dataframe
def calculateUpDownPct(self, dataframe, key):
down_pct_values = np.full(len(dataframe), np.nan)
# Remplir la colonne avec les bons calculs
for i in range(len(dataframe)):
shift_value = abs(int(dataframe[key].iloc[i])) # Récupérer le shift actuel
if i - shift_value > 1: # Vérifier que le shift ne dépasse pas l'index
down_pct_values[i] = 100 * (dataframe['close'].iloc[i] - dataframe['close'].iloc[i - shift_value]) / \
dataframe['close'].iloc[i - shift_value]
return down_pct_values
def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame: def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
""" """
Buy strategy Hyperopt will build and use. Buy strategy Hyperopt will build and use.
""" """
d = self.decalage.value
# dataframe.loc[ # dataframe.loc[
# (dataframe['halow'] <= dataframe['min12']) # (dataframe['halow'].shift(d) <= dataframe['min12'].shift(d))
# & (dataframe['min12'].shift(d) == dataframe['min12'])
# # & (dataframe['close'] < dataframe['hasma5'])
# # & (dataframe['bb_diff'] > 0.01)
# ,
# ['enter_long', 'enter_tag']] = [1, 'buy_halow']
# dataframe.loc[
# (dataframe['hasma5_diff'].shift(2) >= dataframe['hasma5_diff'].shift(1))
# & (dataframe['hasma5_diff'].shift(1) <= dataframe['hasma5_diff'])
# # & (dataframe['bb_diff'] > 0.01)
# ,
# ['enter_long', 'enter_tag']] = [1, 'buy_hasma5_diff']
# dataframe.loc[
# (dataframe['halow'].shift(decalage) <= dataframe['min288'].shift(decalage))
# # & (dataframe['min288'].shift(decalage) == dataframe['min288'])
# # & (dataframe['open'] <= dataframe['bb_middleband']) # # & (dataframe['open'] <= dataframe['bb_middleband'])
# # & (dataframe['bb_diff'] > 0.01) # # & (dataframe['bb_diff'] > 0.01)
# , # ,
# 'buy']=1 # 'buy']=1
decalage = 3
dataframe.loc[ dataframe.loc[
(dataframe['halow'].shift(decalage) <= dataframe['min288'].shift(decalage)) (
& (dataframe['min288'].shift(decalage) == dataframe['min288']) (dataframe['down_count'].shift(1) <= -8)
# & (dataframe['open'] <= dataframe['bb_middleband']) | (dataframe['percent12'] <= -0.012)
# & (dataframe['bb_diff'] > 0.01) )
& (dataframe['down_count'] == 0)
, ,
'buy']=1 ['enter_long', 'enter_tag']] = [1, 'buy_down']
dataframe.loc[(dataframe['loose_hammer'] == 1)
,
['enter_long', 'enter_tag']] = [1, 'buy_hammer']
return dataframe return dataframe
@@ -340,3 +689,11 @@ class HeikinAshi(IStrategy):
# (qtpylib.crossed_above(dataframe['haclose'], dataframe['haopen'])), # (qtpylib.crossed_above(dataframe['haclose'], dataframe['haopen'])),
# 'sell']=1 # 'sell']=1
return dataframe return dataframe
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, '1h') for pair in pairs]
return informative_pairs

View File

@@ -39,28 +39,6 @@ def normalize(df):
df = (df - df.min()) / (df.max() - df.min()) df = (df - df.min()) / (df.max() - df.min())
return df return df
def get_limit_from_config(section, pair):
file_path = '/HOME/home/souti/freqtrade2/user_data/strategies/Zeus_8_3_2_B_4_2.txt'
# Créez un objet ConfigParser
config = configparser.ConfigParser()
try:
# Lisez le fichier avec les valeurs
config.read(file_path)
# Vérifiez si la section existe
if config.has_section(section):
# Obtenez les valeurs à partir de la section et de la clé (pair)
limit = config.get(section, pair)
return limit
else:
raise ValueError(f"La section '{section}' n'existe pas dans le fichier de configuration.")
except Exception as e:
print(f"Erreur lors de la lecture du fichier de configuration : {e}")
return None
class Zeus_8_3_2_B_4_2(IStrategy): class Zeus_8_3_2_B_4_2(IStrategy):
levels = [1, 2, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20] levels = [1, 2, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
@@ -198,14 +176,14 @@ class Zeus_8_3_2_B_4_2(IStrategy):
# hard stoploss profit # hard stoploss profit
sell_allow_decrease = DecimalParameter(0.005, 0.02, default=0.2, decimals=2, space='sell', optimize=True, load=True) sell_allow_decrease = DecimalParameter(0.005, 0.02, default=0.2, decimals=2, space='sell', optimize=True, load=True)
pHSL = DecimalParameter(-0.200, -0.040, default=-0.08, decimals=3, space='sell', optimize=False, load=True) # pHSL = DecimalParameter(-0.200, -0.040, default=-0.08, decimals=3, space='sell', optimize=False, load=True)
# profit threshold 1, trigger point, SL_1 is used # # profit threshold 1, trigger point, SL_1 is used
pPF_1 = DecimalParameter(0.008, 0.020, default=0.016, decimals=3, space='sell', optimize=True, load=True) # pPF_1 = DecimalParameter(0.008, 0.020, default=0.016, decimals=3, space='sell', optimize=True, load=True)
pSL_1 = DecimalParameter(0.008, 0.020, default=0.011, decimals=3, space='sell', optimize=True, load=True) # pSL_1 = DecimalParameter(0.008, 0.020, default=0.011, decimals=3, space='sell', optimize=True, load=True)
#
# profit threshold 2, SL_2 is used # # profit threshold 2, SL_2 is used
pPF_2 = DecimalParameter(0.040, 0.100, default=0.080, decimals=3, space='sell', optimize=True, load=True) # pPF_2 = DecimalParameter(0.040, 0.100, default=0.080, decimals=3, space='sell', optimize=True, load=True)
pSL_2 = DecimalParameter(0.020, 0.070, default=0.040, decimals=3, space='sell', optimize=True, load=True) # pSL_2 = DecimalParameter(0.020, 0.070, default=0.040, decimals=3, space='sell', optimize=True, load=True)
def min_max_scaling(self, series: pd.Series) -> pd.Series: def min_max_scaling(self, series: pd.Series) -> pd.Series:
"""Normaliser les données en les ramenant entre 0 et 100.""" """Normaliser les données en les ramenant entre 0 et 100."""
@@ -223,18 +201,15 @@ class Zeus_8_3_2_B_4_2(IStrategy):
# filled_buys = trade.select_filled_orders('buy') # filled_buys = trade.select_filled_orders('buy')
# count_buys = len(filled_buys) # count_buys = len(filled_buys)
print('entry_tag' + str(entry_tag))
dataframe, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe) dataframe, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe)
last_candle = dataframe.iloc[-1].squeeze() last_candle = dataframe.iloc[-1].squeeze()
# last_candle_12 = dataframe.iloc[-13].squeeze() # last_candle_12 = dataframe.iloc[-13].squeeze()
limit = get_limit_from_config('Achats', pair)
# allow_to_buy = True #(not self.stop_all) #& (not self.all_down) # allow_to_buy = True #(not self.stop_all) #& (not self.all_down)
allow_to_buy = True # (rate <= float(limit)) | (entry_tag == 'force_entry') allow_to_buy = True # (rate <= float(limit)) | (entry_tag == 'force_entry')
# allow_to_buy = rate <= dataframe['lbp_3']
self.trades = list() self.trades = list()
dispo = round(self.wallets.get_available_stake_amount()) dispo = round(self.wallets.get_available_stake_amount())
logger.info(f"BUY {pair} allow_to_buy {allow_to_buy} limit={limit} Buy {entry_tag} {current_time} dispo={dispo}") print(f"BUY {pair} {entry_tag} {current_time} allow_to_buy={allow_to_buy} dispo={dispo}")
return allow_to_buy return allow_to_buy
@@ -242,23 +217,17 @@ class Zeus_8_3_2_B_4_2(IStrategy):
time_in_force: str, time_in_force: str,
exit_reason: str, current_time, **kwargs, ) -> bool: exit_reason: str, current_time, **kwargs, ) -> bool:
# allow_to_sell = (minutes > 30) # allow_to_sell = (minutes > 30)
limit = get_limit_from_config('Ventes', pair)
dataframe, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe) dataframe, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe)
last_candle = dataframe.iloc[-1].squeeze() last_candle = dataframe.iloc[-1].squeeze()
allow_to_sell = (last_candle['percent'] < 0) # rate > float(limit) allow_to_sell = (last_candle['percent'] < 0)
string = ""
if allow_to_sell: if allow_to_sell:
self.trades = list() self.trades = list()
logger.info('Sell ' + exit_reason + ' ' + str(current_time) + ' ' + pair + " dispo=" + str( dispo= round(self.wallets.get_available_stake_amount())
round(self.wallets.get_available_stake_amount())) # "+ str(amount) + ' ' + str(rate) print(f"Sell {pair} {current_time} {exit_reason} dispo={dispo} amount={amount} rate={rate} open_rate={trade.open_rate}")
+ " open_rate=" + str(trade.open_rate) + " rate=" + str(rate) + " profit=" + str(
trade.calc_profit(rate, amount))
+ " " + string)
# del self.max_profit_pairs[pair]
else: else:
logger.info('Cancel Sell ' + exit_reason + ' ' + str(current_time) + ' ' + pair) print('Cancel Sell ' + exit_reason + ' ' + str(current_time) + ' ' + pair)
return (allow_to_sell) | (exit_reason == 'force_exit') return (allow_to_sell) | (exit_reason == 'force_exit')
def custom_stake_amount(self, pair: str, current_time: datetime, current_rate: float, def custom_stake_amount(self, pair: str, current_time: datetime, current_rate: float,
@@ -269,83 +238,10 @@ class Zeus_8_3_2_B_4_2(IStrategy):
current_candle = dataframe.iloc[-1].squeeze() current_candle = dataframe.iloc[-1].squeeze()
adjusted_stake_amount = self.adjust_stake_amount(pair, current_candle) adjusted_stake_amount = self.adjust_stake_amount(pair, current_candle)
logger.info(f"{pair} adjusted_stake_amount{adjusted_stake_amount}") # print(f"{pair} adjusted_stake_amount{adjusted_stake_amount}")
# Use default stake amount. # Use default stake amount.
return adjusted_stake_amount return adjusted_stake_amount
#
# def custom_stoploss(self, pair: str, trade: 'Trade', current_time: datetime,
# current_rate: float, current_profit: float, **kwargs) -> float:
#
# # # hard stoploss profit
# # HSL = self.pHSL.value
# # PF_1 = self.pPF_1.value
# # SL_1 = self.pSL_1.value
# # PF_2 = self.pPF_2.value
# # SL_2 = self.pSL_2.value
# #
# # # For profits between PF_1 and PF_2 the stoploss (sl_profit) used is linearly interpolated
# # # between the values of SL_1 and SL_2. For all profits above PL_2 the sl_profit value
# # # rises linearly with current profit, for profits below PF_1 the hard stoploss profit is used.
# #
# # if current_profit > PF_2:
# # sl_profit = SL_2 + (current_profit - PF_2)
# # elif current_profit > PF_1:
# # sl_profit = SL_1 + ((current_profit - PF_1) * (SL_2 - SL_1) / (PF_2 - PF_1))
# # else:
# # sl_profit = HSL
#
# #print(f"entry_tag={trade.entry_tag} max={trade.max_rate} min={trade.min_rate} ")
# if current_profit > 0.0125:
# sl_profit = 0.75 * current_profit # 75% du profit en cours
# else:
# sl_profit = self.pHSL.value # Hard stop-loss
# stoploss = stoploss_from_open(sl_profit, current_profit)
# return stoploss
#
# dataframe, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe)
# last_candle = dataframe.iloc[-1].squeeze()
# limit = get_limit_from_config('Ventes', pair)
#
# print(pair + " " + str(current_rate) + " " + str(limit))
#
# #stop_loss = self.adjust_stop_loss(dataframe.iloc[-1])
#
# #if current_rate < float(limit):
# # return -1
#
# # "pHSL": -0.99,
# # "pPF_1": 0.022,
# # "pSL_1": 0.021,
# # "pPF_2": 0.08,
# # "pSL_2": 0.04,
# #
# # hard stoploss profit
# HSL = self.pHSL.value
# PF_1 = self.pPF_1.value
# SL_1 = self.pSL_1.value
# PF_2 = self.pPF_2.value
# SL_2 = self.pSL_2.value
#
# # For profits between PF_1 and PF_2 the stoploss (sl_profit) used is linearly interpolated
# # between the values of SL_1 and SL_2. For all profits above PL_2 the sl_profit value
# # rises linearly with current profit, for profits below PF_1 the hard stoploss profit is used.
#
# # 0.04
# if current_profit > PF_2:
# # 0.04 + (current_profit - 0.08)
# sl_profit = SL_2 + (current_profit - PF_2)
# # 0.022
# elif current_profit > PF_1:
# # 0.021 + ((current_profit - 0.022) * (0.04 - 0.021) / (0.08 - 0.022))
# sl_profit = SL_1 + ((current_profit - PF_1) * (SL_2 - SL_1) / (PF_2 - PF_1))
# else:
# sl_profit = HSL
#
# slfo = stoploss_from_open(sl_profit, current_profit)
# print('current_profit=' + str(current_profit) + ' stop from open=' + str(slfo))
# return slfo
def custom_exit(self, pair: str, trade: Trade, current_time, current_rate, current_profit, **kwargs): def custom_exit(self, pair: str, trade: Trade, current_time, current_rate, current_profit, **kwargs):
@@ -360,12 +256,12 @@ class Zeus_8_3_2_B_4_2(IStrategy):
# Calcul du prix cible basé sur l'ATR # Calcul du prix cible basé sur l'ATR
atr_take_profit = trade.open_rate + (last_candle['atr'] * 2) # Prendre profit à 2x l'ATR atr_take_profit = trade.open_rate + (last_candle['atr'] * 2) # Prendre profit à 2x l'ATR
# logger.info(f"{pair} Custom exit atr_take_profit={atr_take_profit:.4f}") # print(f"{pair} Custom exit atr_take_profit={atr_take_profit:.4f}")
# if current_rate >= atr_take_profit: # if current_rate >= atr_take_profit:
# return 'sell_atr_take_profit' # return 'sell_atr_take_profit'
if (last_candle['percent3'] < -0.002) & (last_candle['percent12'] < 0) & ( if (last_candle['percent3'] < -0.002) & (last_candle['percent12'] < 0) & (
current_profit > last_candle['min_max200'] / 2): current_profit > last_candle['min_max200'] / 3):
self.trades = list() self.trades = list()
return 'min_max200' return 'min_max200'
if (last_candle['percent12'] <= -0.01) & (current_profit >= expected_profit): if (last_candle['percent12'] <= -0.01) & (current_profit >= expected_profit):
@@ -384,9 +280,6 @@ class Zeus_8_3_2_B_4_2(IStrategy):
# Add all ta features # Add all ta features
pair = metadata['pair'] pair = metadata['pair']
dataframe['achats'] = get_limit_from_config('Achats', pair)
dataframe['ventes'] = get_limit_from_config('Ventes', pair)
heikinashi = qtpylib.heikinashi(dataframe) heikinashi = qtpylib.heikinashi(dataframe)
dataframe['haopen'] = heikinashi['open'] dataframe['haopen'] = heikinashi['open']
dataframe['haclose'] = heikinashi['close'] dataframe['haclose'] = heikinashi['close']
@@ -546,27 +439,27 @@ class Zeus_8_3_2_B_4_2(IStrategy):
dataframe['amount'] = amount dataframe['amount'] = amount
print(f"amount= {amount}") print(f"amount= {amount}")
# trades = Trade.get_trades([Trade.is_open is False]).all() # # trades = Trade.get_trades([Trade.is_open is False]).all()
trades = Trade.get_trades_proxy(is_open=False, pair=metadata['pair']) # trades = Trade.get_trades_proxy(is_open=False, pair=metadata['pair'])
if trades: # if trades:
trade = trades[-1] # trade = trades[-1]
print('closed trade pair is : ') # print('closed trade pair is : ')
print(trade) # print(trade)
dataframe['expected_profit'] = (1 + self.expectedProfit(pair, dataframe.iloc[-1])) * dataframe[ # dataframe['expected_profit'] = (1 + self.expectedProfit(pair, dataframe.iloc[-1])) * dataframe[
'last_price'] # 'last_price']
dataframe['lbp'] = dataframe['last_price'] # dataframe['lbp'] = dataframe['last_price']
dataframe['lbp_3'] = dataframe['lbp'] * 0.97 # 3 # dataframe['lbp_3'] = dataframe['lbp'] * 0.97 # 3
dataframe['lbp_6'] = dataframe['lbp'] * 0.94 # 6 # dataframe['lbp_6'] = dataframe['lbp'] * 0.94 # 6
dataframe['lbp_9'] = dataframe['lbp'] * 0.90 # 10 # dataframe['lbp_9'] = dataframe['lbp'] * 0.90 # 10
dataframe['lbp_12'] = dataframe['lbp'] * 0.85 # 15 # dataframe['lbp_12'] = dataframe['lbp'] * 0.85 # 15
dataframe['lbp_20'] = dataframe['lbp'] * 0.8 # 20 # dataframe['lbp_20'] = dataframe['lbp'] * 0.8 # 20
dataframe['fbp'] = trade.open_rate # dataframe['fbp'] = trade.open_rate
# else: # # else:
# last_trade = self.get_trades(pair=pair).order_by('-close_date').first() # # last_trade = self.get_trades(pair=pair).order_by('-close_date').first()
# filled_buys = last_trade.select_filled_orders('buy') # # filled_buys = last_trade.select_filled_orders('buy')
# print(last_trade) # # print(last_trade)
# for buy in filled_buys: # # for buy in filled_buys:
# print(filled_buys) # # print(filled_buys)
dataframe['buy_level'] = dataframe['lowest_4_average'] * (1 - self.levels[count_buys] / 100) dataframe['buy_level'] = dataframe['lowest_4_average'] * (1 - self.levels[count_buys] / 100)
# ---------------------------------------------------------- # ----------------------------------------------------------
@@ -615,7 +508,7 @@ class Zeus_8_3_2_B_4_2(IStrategy):
dataframe['amplitude_pct_60'] = dataframe['amplitude_pct'].rolling(60).sum() dataframe['amplitude_pct_60'] = dataframe['amplitude_pct'].rolling(60).sum()
# ---------------------------------------------------------- # ----------------------------------------------------------
self.getBinanceOrderBook(pair, dataframe) # self.getBinanceOrderBook(pair, dataframe)
return dataframe return dataframe
@@ -641,9 +534,7 @@ class Zeus_8_3_2_B_4_2(IStrategy):
expected_profit = self.expectedProfit(pair, dataframe.iloc[-1]) expected_profit = self.expectedProfit(pair, dataframe.iloc[-1])
# self.getBinanceOrderBook(pair, dataframe) # self.getBinanceOrderBook(pair, dataframe)
last_candle = dataframe.iloc[-1].squeeze() last_candle = dataframe.iloc[-1].squeeze()
# limit = last_candle['first_price'] * (1 - self.baisse[last_candle['count_buys']] / 100)
# self.updateLastValue(dataframe, 'expected_profit', expected_profit)
print("---------------" + pair + "----------------") print("---------------" + pair + "----------------")
print('adjust stake amount ' + str(self.adjust_stake_amount(pair, dataframe.iloc[-1]))) print('adjust stake amount ' + str(self.adjust_stake_amount(pair, dataframe.iloc[-1])))
# print('adjust exit price ' + str(self.adjust_exit_price(dataframe.iloc[-1]))) # print('adjust exit price ' + str(self.adjust_exit_price(dataframe.iloc[-1])))
@@ -772,13 +663,7 @@ class Zeus_8_3_2_B_4_2(IStrategy):
& (dataframe['min50'].shift(3) == dataframe['min50']) & (dataframe['min50'].shift(3) == dataframe['min50'])
& (dataframe['close'] <= dataframe['min50'] * 1.002) & (dataframe['close'] <= dataframe['min50'] * 1.002)
), ['enter_long', 'enter_tag']] = (1, 'buy_close_02') ), ['enter_long', 'enter_tag']] = (1, 'buy_close_02')
# dataframe.loc[
# (
# (dataframe['close'] <= dataframe['lowest_4_average'] * 1.002)
# & (dataframe['haopen'] >= dataframe['lbp_3'])
# & (dataframe['haclose'] <= dataframe['lbp_3'])
# & (dataframe['haopen'] < buy_level)
# ), ['enter_long', 'enter_tag']] = (1, 'buy_lbp_3')
dataframe.loc[ dataframe.loc[
( (
(dataframe['close'] <= dataframe['lowest_4_average'] * 1.002) (dataframe['close'] <= dataframe['lowest_4_average'] * 1.002)
@@ -801,38 +686,26 @@ class Zeus_8_3_2_B_4_2(IStrategy):
return dataframe return dataframe
# def get_buy_level(self, pair, dataframe):
# limit = get_limit_from_config('Achats', pair)
#
# filled_buys = {}
# for trade in self.trades:
# if trade.pair != pair:
# continue
# filled_buys = trade.select_filled_orders('enter_long')
# print('populate_buy_trend filled_buys : ' + str(len(filled_buys)))
# # Affichez les valeurs
# print(pair, limit)
# # BUY_LEVELS = {
# # 'BTC/USDT': [int(btc_limit), 42600, 41000, 40000, 39000, 38000, 37000, 36000, 35000],
# # 'ETH/USDT': [int(eth_limit), 2290, 1900, 1800, 1700, 1600, 1500, 1400, 1300],
# # 'ETC/USDT': [int(eth_limit), 2290, 1900, 1800, 1700, 1600, 1500, 1400, 1300],
# # 'DOGE/USDT': [int(eth_limit), 2290, 1900, 1800, 1700, 1600, 1500, 1400, 1300],
# # # Ajoutez d'autres paires avec leurs niveaux d'achat ici...
# # }
# count_of_buys = len(filled_buys)
# buy_level = dataframe['lbp'] * (1 - self.levels[count_of_buys] / 100) # float(limit) #BUY_LEVELS.get(pair, [])[0] #dataframe['lbp_3'] #"
# return buy_level
def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame: def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
return dataframe return dataframe
def adjust_trade_position(self, trade: Trade, current_time: datetime, def adjust_trade_position(self, trade: Trade, current_time: datetime,
current_rate: float, current_profit: float, min_stake: float, current_rate: float, current_profit: float, min_stake: float,
max_stake: float, **kwargs): max_stake: float, **kwargs):
# ne rien faire si ordre deja en cours
if trade.has_open_orders:
return None
if (self.wallets.get_available_stake_amount() < 50): # or trade.stake_amount >= max_stake:
return 0
dataframe, _ = self.dp.get_analyzed_dataframe(trade.pair, self.timeframe) dataframe, _ = self.dp.get_analyzed_dataframe(trade.pair, self.timeframe)
# print(dataframe)
last_candle = dataframe.iloc[-1].squeeze() last_candle = dataframe.iloc[-1].squeeze()
last_candle_12 = dataframe.iloc[-13].squeeze() # prépare les données
count_of_buys = trade.nr_of_successful_entries
current_time = current_time.astimezone(timezone.utc)
open_date = trade.open_date.astimezone(timezone.utc)
dispo = round(self.wallets.get_available_stake_amount())
hours = (current_time - trade.date_last_filled_utc).total_seconds() / 3600.0
if (len(dataframe) < 1): if (len(dataframe) < 1):
return None return None
@@ -851,25 +724,24 @@ class Zeus_8_3_2_B_4_2(IStrategy):
# else: # else:
# condition = False # condition = False
# self.protection_nb_buy_lost.value # self.protection_nb_buy_lost.value
# limits = ['lbp_3', 'lbp_6', 'lbp_9', 'lbp_12', 'lbp_20']
# limit = last_candle[limits[count_of_buys]]
limit = last_candle['limit'] limit = last_candle['limit']
stake_amount = min(200, self.adjust_stake_amount(pair, last_candle) * self.fibo[count_of_buys]) stake_amount = min(200, self.adjust_stake_amount(pair, last_candle) * self.fibo[count_of_buys])
# print("Adjust " + trade.pair + " time=" + str(current_time) + ' rate=' + str(current_rate) + " buys=" + str(count_of_buys) + " limit=" + str(limit) + " stake=" + str(stake_amount))
# logger.info(
# f"Adjust price={trade.pair} buy={condition} rate={current_rate:.4f} buys={count_of_buys} limit={limit:.4f} stake={stake_amount:.4f}")
current_time_utc = current_time.astimezone(timezone.utc) current_time_utc = current_time.astimezone(timezone.utc)
open_date = trade.open_date.astimezone(timezone.utc) open_date = trade.open_date.astimezone(timezone.utc)
days_since_open = (current_time_utc - open_date).days days_since_open = (current_time_utc - open_date).days
if (days_since_open > count_of_buys) & (0 < count_of_buys <= max_buys) & (current_rate <= limit) & (last_candle['enter_long'] == 1): # if (days_since_open > count_of_buys) & (0 < count_of_buys <= max_buys) & (current_rate <= limit) & (last_candle['enter_long'] == 1):
limit_buy = 5
if (count_of_buys < limit_buy) \
and ((last_candle['enter_long'] == 1) or last_candle['percent48'] < - 0.03) \
and (current_profit < -0.015 * count_of_buys) \
and (last_candle['enter_long'] == 1):
try: try:
# This then calculates current safety order size # This then calculates current safety order size
# stake_amount = stake_amount * pow(1.5, count_of_buys) # stake_amount = stake_amount * pow(1.5, count_of_buys)
# print("Effective Adjust " + trade.pair + " time=" + str(current_time) + ' rate=' + str(current_rate) + " buys=" + str(count_of_buys) + " limit=" + str(limit) + " stake=" + str(stake_amount)) print(
logger.info(
f"Adjust {current_time} price={trade.pair} rate={current_rate:.4f} buys={count_of_buys} limit={limit:.4f} stake={stake_amount:.4f}") f"Adjust {current_time} price={trade.pair} rate={current_rate:.4f} buys={count_of_buys} limit={limit:.4f} stake={stake_amount:.4f}")
return stake_amount return stake_amount
@@ -901,7 +773,7 @@ class Zeus_8_3_2_B_4_2(IStrategy):
# max_min = max_14_days / min_14_days # max_min = max_14_days / min_14_days
# Stack amount ajusté price=2473.47 min_max=0.15058074985054215 percent=0.8379141364642171 amount=20.0 # Stack amount ajusté price=2473.47 min_max=0.15058074985054215 percent=0.8379141364642171 amount=20.0
adjusted_stake_amount = max(base_stake_amount / 2.5, min(75, base_stake_amount * percent_4)) adjusted_stake_amount = max(base_stake_amount / 2.5, min(100, base_stake_amount * percent_4))
# if pair in ('BTC/USDT', 'ETH/USDT'): # if pair in ('BTC/USDT', 'ETH/USDT'):
# if percent_4 > 0.5: # if percent_4 > 0.5:
# adjusted_stake_amount = 300 # adjusted_stake_amount = 300
@@ -927,17 +799,17 @@ class Zeus_8_3_2_B_4_2(IStrategy):
# #
# return exit_price # return exit_price
def adjust_stoploss(self, pair: str, trade: 'Trade', current_time: datetime, # def adjust_stoploss(self, pair: str, trade: 'Trade', current_time: datetime,
current_rate: float, current_profit: float, **kwargs) -> float: # current_rate: float, current_profit: float, **kwargs) -> float:
dataframe, _ = self.dp.get_analyzed_dataframe(trade.pair, self.timeframe) # dataframe, _ = self.dp.get_analyzed_dataframe(trade.pair, self.timeframe)
# print(dataframe) # # print(dataframe)
last_candle = dataframe.iloc[-1].squeeze() # last_candle = dataframe.iloc[-1].squeeze()
#
# Utiliser l'ATR pour ajuster le stoploss # # Utiliser l'ATR pour ajuster le stoploss
atr_stoploss = current_rate - (last_candle['atr'] * 1.5) # Stoploss à 1.5x l'ATR # atr_stoploss = current_rate - (last_candle['atr'] * 1.5) # Stoploss à 1.5x l'ATR
#
# Retourner le stoploss dynamique en pourcentage du prix actuel # # Retourner le stoploss dynamique en pourcentage du prix actuel
return (atr_stoploss / current_rate) - 1 # return (atr_stoploss / current_rate) - 1
def expectedProfit(self, pair: str, dataframe: DataFrame): def expectedProfit(self, pair: str, dataframe: DataFrame):