synchronise HeikinAshi
This commit is contained in:
@@ -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):
|
||||||
|
|||||||
457
HeikinAshi.py
457
HeikinAshi.py
@@ -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
|
||||||
|
|||||||
@@ -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):
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user