Multiple paire detection / limit 3

This commit is contained in:
Jérôme Delacotte
2025-07-15 13:45:23 +02:00
parent e26c3f44f1
commit 4d37361bc6

View File

@@ -27,6 +27,7 @@ import requests
from datetime import timezone, timedelta
from scipy.signal import savgol_filter
from ta.trend import SMAIndicator, EMAIndicator, MACD, ADXIndicator
from collections import Counter
logger = logging.getLogger(__name__)
@@ -261,6 +262,9 @@ class Zeus_8_3_2_B_4_2(IStrategy):
# if count < 3:
# allow_to_buy = False
if not self.should_enter_trade(pair):
allow_to_buy = False
if allow_to_buy:
self.trades = list()
self.pairs[pair]['first_buy'] = rate
@@ -925,6 +929,9 @@ class Zeus_8_3_2_B_4_2(IStrategy):
days_since_open = (current_time_utc - open_date).days
pair = trade.pair
if not self.should_enter_trade(pair):
return None
pct_first = 0
if self.pairs[pair]['first_buy']:
pct_first = round((last_candle['close'] - self.pairs[pair]['first_buy']) / self.pairs[pair]['first_buy'], 3)
@@ -950,10 +957,12 @@ class Zeus_8_3_2_B_4_2(IStrategy):
if (len(dataframe) < 1):
print("skip dataframe")
return None
if self.dp.runmode.value in ('dry_run'):
if pair not in ('BTC/USDT', 'BTC/USDC', 'XRP/USDT', 'XRP/USDC', 'ETH/USDT', 'ETH/USDC'):
# print(f"skip pair {pair}")
return None
# if self.dp.runmode.value in ('dry_run'):
# if pair not in ('BTC/USDT', 'BTC/USDC', 'XRP/USDT', 'XRP/USDC', 'ETH/USDT', 'ETH/USDC', 'SOL/USDT', 'SOL/USDT'):
# # print(f"skip pair {pair}")
# return None
# else:
# if pair not in ('BTC/USDT', 'BTC/USDC'):
# btc_count = self.pairs['BTC/USDT']['count_of_buys'] + self.pairs['BTC/USDC']['count_of_buys']
@@ -1166,6 +1175,8 @@ class Zeus_8_3_2_B_4_2(IStrategy):
def adjust_stake_amount(self, pair: str, last_candle: DataFrame):
# Calculer le minimum des 14 derniers jours
base_stake_amount = self.config.get('stake_amount') # Montant de base configuré
if not pair.startswith('BTC'):
base_stake_amount = base_stake_amount * 0.75
first_price = self.pairs[pair]['first_buy']
if (first_price == 0):
@@ -1371,50 +1382,50 @@ class Zeus_8_3_2_B_4_2(IStrategy):
return numeric_matrice[row_idx, col_idx]
# @property
# def protections(self):
# return [
# {
# "method": "CooldownPeriod",
# "stop_duration_candles": 12
# }
# # {
# # "method": "MaxDrawdown",
# # "lookback_period_candles": self.lookback.value,
# # "trade_limit": self.trade_limit.value,
# # "stop_duration_candles": self.protection_stop.value,
# # "max_allowed_drawdown": self.protection_max_allowed_dd.value,
# # "only_per_pair": False
# # },
# # {
# # "method": "StoplossGuard",
# # "lookback_period_candles": 24,
# # "trade_limit": 4,
# # "stop_duration_candles": self.protection_stoploss_stop.value,
# # "only_per_pair": False
# # },
# # {
# # "method": "StoplossGuard",
# # "lookback_period_candles": 24,
# # "trade_limit": 4,
# # "stop_duration_candles": 2,
# # "only_per_pair": False
# # },
# # {
# # "method": "LowProfitPairs",
# # "lookback_period_candles": 6,
# # "trade_limit": 2,
# # "stop_duration_candles": 60,
# # "required_profit": 0.02
# # },
# # {
# # "method": "LowProfitPairs",
# # "lookback_period_candles": 24,
# # "trade_limit": 4,
# # "stop_duration_candles": 2,
# # "required_profit": 0.01
# # }
# ]
@property
def protections(self):
return [
{
"method": "CooldownPeriod",
"stop_duration_candles": 12
}
# {
# "method": "MaxDrawdown",
# "lookback_period_candles": self.lookback.value,
# "trade_limit": self.trade_limit.value,
# "stop_duration_candles": self.protection_stop.value,
# "max_allowed_drawdown": self.protection_max_allowed_dd.value,
# "only_per_pair": False
# },
# {
# "method": "StoplossGuard",
# "lookback_period_candles": 24,
# "trade_limit": 4,
# "stop_duration_candles": self.protection_stoploss_stop.value,
# "only_per_pair": False
# },
# {
# "method": "StoplossGuard",
# "lookback_period_candles": 24,
# "trade_limit": 4,
# "stop_duration_candles": 2,
# "only_per_pair": False
# },
# {
# "method": "LowProfitPairs",
# "lookback_period_candles": 6,
# "trade_limit": 2,
# "stop_duration_candles": 60,
# "required_profit": 0.02
# },
# {
# "method": "LowProfitPairs",
# "lookback_period_candles": 24,
# "trade_limit": 4,
# "stop_duration_candles": 2,
# "required_profit": 0.01
# }
]
def conditional_smoothing(self, series, threshold=0.002):
smoothed = [series.iloc[0]]
@@ -1696,4 +1707,41 @@ class Zeus_8_3_2_B_4_2(IStrategy):
# Résultat
print("Moyenne des valeurs par double-tranche :")
print(pivot_mean.round(2))
print(pivot_mean.round(2))
def should_enter_trade(self, pair: str) -> bool:
limit = 3
if pair.startswith('BTC'):
return True # BTC toujours autorisé
# Filtrer les paires non-BTC
non_btc_pairs = [p for p in self.pairs if not p.startswith('BTC')]
# Compter les positions actives sur les paires non-BTC
has_more_than_3 = False
total_non_btc = 0
for p in non_btc_pairs:
nb_trades = self.pairs[p]['count_of_buys']
if nb_trades > 0:
if nb_trades > limit and pair != p:
has_more_than_3 = True
total_non_btc += nb_trades
this_pair_count = self.pairs[p]['count_of_buys']
if total_non_btc >= 12:
# print("total_non_btc > 10")
return False
if this_pair_count >= limit:
# Si une autre paire non-BTC a aussi >3 trades, blocage
# for other_pair, count in pair_counts.items():
# if other_pair != pair and count >= 3:
# return False
if not has_more_than_3:
print(f"{pair} Cette paire est la seule avec >=3 / {this_pair_count}")
return not has_more_than_3
else:
return True