FrictradeLearning.py gestion steps de mises adjust
This commit is contained in:
@@ -9,7 +9,7 @@
|
||||
},
|
||||
"trailing": {
|
||||
"trailing_stop": false,
|
||||
"trailing_stop_positive": 0.2,
|
||||
"trailing_stop_positive": 0.15,
|
||||
"trailing_stop_positive_offset": 1,
|
||||
"trailing_only_offset_is_reached": true
|
||||
},
|
||||
@@ -26,10 +26,10 @@
|
||||
"indic_1h_force_buy": "sma5_deriv1_1h"
|
||||
},
|
||||
"sell": {
|
||||
"offset_max": 18,
|
||||
"offset_min": 17
|
||||
"offset_max": 6,
|
||||
"offset_min": 27
|
||||
}
|
||||
},
|
||||
"ft_stratparam_v": 1,
|
||||
"export_time": "2025-12-14 18:44:03.713386+00:00"
|
||||
"export_time": "2025-12-15 19:03:21.177158+00:00"
|
||||
}
|
||||
@@ -126,8 +126,8 @@ class FrictradeLearning(IStrategy):
|
||||
columns_logged = False
|
||||
pairs = {
|
||||
pair: {
|
||||
"first_buy": 0,
|
||||
"last_buy": 0.0,
|
||||
"first_price": 0,
|
||||
"last_price": 0.0,
|
||||
"last_min": 999999999999999.5,
|
||||
"last_max": 0,
|
||||
"trade_info": {},
|
||||
@@ -145,7 +145,6 @@ class FrictradeLearning(IStrategy):
|
||||
'stop': False,
|
||||
'max_profit': 0,
|
||||
'first_amount': 0,
|
||||
'first_price': 0,
|
||||
'total_amount': 0,
|
||||
'has_gain': 0,
|
||||
'force_sell': False,
|
||||
@@ -178,19 +177,19 @@ class FrictradeLearning(IStrategy):
|
||||
"note": "pic oct. 2025 (source agrégée, à vérifier selon l'exchange)"}
|
||||
]
|
||||
|
||||
def dynamic_trailing_offset(self, price, ath, nb_entries, max_dca=5):
|
||||
dd_ath = (ath - price) / ath
|
||||
dd_ath = max(0.0, min(dd_ath, 0.5))
|
||||
def dynamic_trailing_offset(self, pair, price, ath, count_of_buys, max_dca=5):
|
||||
# dd_ath = (ath - price) / ath
|
||||
# dd_ath = max(0.0, min(dd_ath, 0.5))
|
||||
#
|
||||
# dca_risk = min(count_of_buys / max_dca, 1.0)
|
||||
#
|
||||
# breathing_score = 0.7 * dd_ath + 0.3 * (1 - dca_risk)
|
||||
# breathing_score = min(max(breathing_score, 0.0), 1.0)
|
||||
#
|
||||
# OFFSET_MIN = self.offset_min.value
|
||||
# OFFSET_MAX = self.offset_min.value + self.offset_max.value
|
||||
|
||||
dca_risk = min(nb_entries / max_dca, 1.0)
|
||||
|
||||
breathing_score = 0.7 * dd_ath + 0.3 * (1 - dca_risk)
|
||||
breathing_score = min(max(breathing_score, 0.0), 1.0)
|
||||
|
||||
OFFSET_MIN = self.offset_min.value
|
||||
OFFSET_MAX = self.offset_min.value + self.offset_max.value
|
||||
|
||||
return OFFSET_MIN + breathing_score * (OFFSET_MAX - OFFSET_MIN)
|
||||
return self.pairs[pair]['total_amount'] / 100 # OFFSET_MIN + breathing_score * (OFFSET_MAX - OFFSET_MIN)
|
||||
|
||||
def confirm_trade_entry(self, pair: str, order_type: str, amount: float, rate: float, time_in_force: str,
|
||||
current_time: datetime, entry_tag: Optional[str], **kwargs) -> bool:
|
||||
@@ -210,8 +209,8 @@ class FrictradeLearning(IStrategy):
|
||||
|
||||
if allow_to_buy:
|
||||
self.trades = list()
|
||||
self.pairs[pair]['first_buy'] = rate
|
||||
self.pairs[pair]['last_buy'] = rate
|
||||
self.pairs[pair]['first_price'] = rate
|
||||
self.pairs[pair]['last_price'] = rate
|
||||
self.pairs[pair]['max_touch'] = last_candle['close']
|
||||
self.pairs[pair]['last_candle'] = last_candle
|
||||
self.pairs[pair]['count_of_buys'] = 1
|
||||
@@ -329,7 +328,7 @@ class FrictradeLearning(IStrategy):
|
||||
self.pairs[pair]['total_amount'] = 0
|
||||
self.pairs[pair]['count_of_buys'] = 0
|
||||
self.pairs[pair]['max_touch'] = 0
|
||||
self.pairs[pair]['last_buy'] = 0
|
||||
self.pairs[pair]['last_price'] = 0
|
||||
self.pairs[pair]['last_date'] = current_time
|
||||
self.pairs[pair]['current_trade'] = None
|
||||
else:
|
||||
@@ -367,8 +366,8 @@ class FrictradeLearning(IStrategy):
|
||||
# self.pairs[pair]['current_profit'] = profit
|
||||
#
|
||||
# dispo = round(self.wallets.get_available_stake_amount())
|
||||
# hours_since_first_buy = (current_time - trade.open_date_utc).seconds / 3600.0
|
||||
# days_since_first_buy = (current_time - trade.open_date_utc).days
|
||||
# hours_since_first_price = (current_time - trade.open_date_utc).seconds / 3600.0
|
||||
# days_since_first_price = (current_time - trade.open_date_utc).days
|
||||
# hours = (current_time - trade.date_last_filled_utc).total_seconds() / 3600.0
|
||||
# minutes = (current_time - trade.date_last_filled_utc).total_seconds() / 60.0
|
||||
#
|
||||
@@ -406,10 +405,10 @@ class FrictradeLearning(IStrategy):
|
||||
return last_lost
|
||||
|
||||
def getPctFirstBuy(self, pair, last_candle):
|
||||
return round((last_candle['close'] - self.pairs[pair]['first_buy']) / self.pairs[pair]['first_buy'], 3)
|
||||
return round((last_candle['close'] - self.pairs[pair]['first_price']) / self.pairs[pair]['first_price'], 3)
|
||||
|
||||
def getPctLastBuy(self, pair, last_candle):
|
||||
return round((last_candle['close'] - self.pairs[pair]['last_buy']) / self.pairs[pair]['last_buy'], 4)
|
||||
return round((last_candle['close'] - self.pairs[pair]['last_price']) / self.pairs[pair]['last_price'], 4)
|
||||
|
||||
def expectedProfit(self, pair: str, last_candle: DataFrame):
|
||||
lim = 0.01
|
||||
@@ -442,7 +441,7 @@ class FrictradeLearning(IStrategy):
|
||||
colonnes_a_exclure = ['last_candle',
|
||||
'trade_info', 'last_date', 'last_count_of_buys', 'base_stake_amount', 'stop_buy']
|
||||
df_filtered = df[df['count_of_buys'] > 0].drop(columns=colonnes_a_exclure)
|
||||
# df_filtered = df_filtered["first_buy", "last_max", "max_touch", "last_sell","last_buy", 'count_of_buys', 'current_profit']
|
||||
# df_filtered = df_filtered["first_price", "last_max", "max_touch", "last_sell","last_price", 'count_of_buys', 'current_profit']
|
||||
|
||||
self.printLog(df_filtered)
|
||||
|
||||
@@ -645,14 +644,14 @@ class FrictradeLearning(IStrategy):
|
||||
min_price = min(min_price, buy.price)
|
||||
max_price = max(max_price, buy.price)
|
||||
dataframe['first_price'] = buy.price
|
||||
self.pairs[pair]['first_buy'] = buy.price
|
||||
self.pairs[pair]['first_price'] = buy.price
|
||||
self.pairs[pair]['first_amount'] = buy.price * buy.filled
|
||||
# dataframe['close01'] = buy.price * 1.01
|
||||
|
||||
# Order(id=2396, trade=1019, order_id=29870026652, side=buy, filled=0.00078, price=63921.01,
|
||||
# status=closed, date=2024-08-26 02:20:11)
|
||||
dataframe['last_price'] = buy.price
|
||||
self.pairs[pair]['last_buy'] = buy.price
|
||||
self.pairs[pair]['last_price'] = buy.price
|
||||
count = count + 1
|
||||
amount += buy.price * buy.filled
|
||||
self.pairs[pair]['count_of_buys'] = count
|
||||
@@ -911,11 +910,17 @@ class FrictradeLearning(IStrategy):
|
||||
# f"steps={steps} "
|
||||
# f"pct={(round(val - (ath * (1 - self.allow_decrease_rate.value))) / val, 4)}")
|
||||
# print(dca_thresholds)
|
||||
if self.pairs[pair]['last_ath'] == 0:
|
||||
ath = max(val, self.get_last_ath_before_candle(last_candle['date']))
|
||||
self.pairs[pair]['last_ath'] = ath
|
||||
if len(self.pairs[pair]['dca_thresholds']) == 0:
|
||||
self.calculateStepsDcaThresholds(last_candle, pair)
|
||||
|
||||
print(f"val={val} dca={self.pairs[pair]['dca_thresholds']} ath={self.pairs[pair]['last_ath']} first_price={self.pairs[pair]['first_price']}")
|
||||
|
||||
if self.dp:
|
||||
if self.dp and self.pairs[pair]['first_price'] > 0:
|
||||
if self.dp.runmode.value in ('live', 'dry_run'):
|
||||
full, mises, steps = self.calculateMises(last_candle, pair)
|
||||
full, mises, steps = self.calculateMises(pair, self.pairs[pair]['last_ath'], val)
|
||||
# stake = min(self.wallets.get_available_stake_amount(), self.adjust_stake_amount(pair, last_candle))
|
||||
if val and len(self.pairs[pair]['dca_thresholds']) > 0:
|
||||
print(self.pairs[pair]['dca_thresholds'])
|
||||
@@ -925,14 +930,14 @@ class FrictradeLearning(IStrategy):
|
||||
for dca in self.pairs[pair]['dca_thresholds']:
|
||||
stake = mises[count]
|
||||
pct += dca
|
||||
offset = self.dynamic_trailing_offset(price=val, ath=ath, nb_entries=count)
|
||||
offset = self.dynamic_trailing_offset(pair, price=val, ath=ath, count_of_buys=count)
|
||||
|
||||
if (count == self.pairs[pair]['count_of_buys']):
|
||||
print(f"next_buy={val * (1 - pct)} count={count} pct={round(pct, 4)}")
|
||||
if count == self.pairs[pair]['count_of_buys']:
|
||||
print(f"next_buy={round(val * (1 - pct),1)} count={count} pct={round(pct, 4)}")
|
||||
dataframe[f"next_buy"] = val * (1 - pct)
|
||||
count += 1
|
||||
print(
|
||||
f"stake={stake} count={count} pct={round(pct, 4)} offset={offset} next_buy={val * (1 - pct)}")
|
||||
f"stake={round(stake, 1)} count={count} pct={round(pct, 4)} offset={round(offset, 1)} next_buy={round(val * (1 - pct), 2)}")
|
||||
|
||||
return dataframe
|
||||
|
||||
@@ -1131,17 +1136,18 @@ class FrictradeLearning(IStrategy):
|
||||
count = self.pairs[pair]['count_of_buys'] - self.pairs[pair]['has_gain']
|
||||
return mises[count] if count < len(mises) else self.pairs[pair]['first_amount']
|
||||
|
||||
full, mises, steps = self.calculateMises(last_candle, pair)
|
||||
ath = max(self.pairs[pair]['last_max'], self.get_last_ath_before_candle(last_candle['date']))
|
||||
full, mises, steps = self.calculateMises(pair, ath, last_candle['mid'])
|
||||
|
||||
base_stake = mises[self.pairs[pair]['count_of_buys']] if self.pairs[pair]['count_of_buys'] < len(
|
||||
mises) else full / (steps * 2)
|
||||
return base_stake
|
||||
|
||||
def calculateMises(self, last_candle, pair):
|
||||
ath = max(self.pairs[pair]['last_max'], self.get_last_ath_before_candle(last_candle['date']))
|
||||
def calculateMises(self, pair, ath, val):
|
||||
# ath = max(self.pairs[pair]['last_max'], self.get_last_ath_before_candle(last_candle['date']))
|
||||
self.pairs[pair]['last_ath'] = ath
|
||||
full = self.wallets.get_total_stake_amount()
|
||||
steps = self.calculateNumberOfSteps(last_candle['mid'], ath, max_steps=self.max_steps.value)
|
||||
steps = self.calculateNumberOfSteps(val, ath, max_steps=self.max_steps.value)
|
||||
mises = self.progressive_parts(full, steps, full / (steps * 2))
|
||||
print(f"ath={ath} full={full} steps={steps} mises={mises} ")
|
||||
self.pairs[pair]['mises'] = mises
|
||||
@@ -1167,8 +1173,8 @@ class FrictradeLearning(IStrategy):
|
||||
current_time = current_time.astimezone(timezone.utc)
|
||||
# open_date = trade.open_date.astimezone(timezone.utc)
|
||||
dispo = round(self.wallets.get_available_stake_amount())
|
||||
# hours_since_first_buy = (current_time - trade.open_date_utc).seconds / 3600.0
|
||||
# days_since_first_buy = (current_time - trade.open_date_utc).days
|
||||
# hours_since_first_price = (current_time - trade.open_date_utc).seconds / 3600.0
|
||||
# days_since_first_price = (current_time - trade.open_date_utc).days
|
||||
hours = (current_time - trade.date_last_filled_utc).total_seconds() / 3600.0
|
||||
# minutes = (current_time - trade.date_last_filled_utc).total_seconds() / 60.0
|
||||
|
||||
@@ -1184,7 +1190,7 @@ class FrictradeLearning(IStrategy):
|
||||
# total_counts = sum(
|
||||
# pair_data['count_of_buys'] for pair_data in self.pairs.values() if not self.getShortName(pair) == 'BTC')
|
||||
#
|
||||
# if self.pairs[pair]['first_buy']:
|
||||
# if self.pairs[pair]['first_price']:
|
||||
# pct_first = self.getPctFirstBuy(pair, last_candle)
|
||||
|
||||
# if profit > - self.pairs[pair]['first_amount'] \
|
||||
@@ -1208,7 +1214,7 @@ class FrictradeLearning(IStrategy):
|
||||
# stake=round(stake_amount, 2)
|
||||
# )
|
||||
#
|
||||
# self.pairs[trade.pair]['last_buy'] = current_rate
|
||||
# self.pairs[trade.pair]['last_price'] = current_rate
|
||||
# self.pairs[trade.pair]['max_touch'] = last_candle['close']
|
||||
# self.pairs[trade.pair]['last_candle'] = last_candle
|
||||
#
|
||||
@@ -1223,7 +1229,7 @@ class FrictradeLearning(IStrategy):
|
||||
return None
|
||||
|
||||
# Dernier prix d'achat réel (pas le prix moyen)
|
||||
last_fill_price = self.pairs[trade.pair]['last_buy'] # trade.open_rate # remplacé juste après ↓
|
||||
last_fill_price = self.pairs[trade.pair]['last_price'] # trade.open_rate # remplacé juste après ↓
|
||||
|
||||
# if len(trade.orders) > 0:
|
||||
# # On cherche le dernier BUY exécuté
|
||||
@@ -1287,8 +1293,9 @@ class FrictradeLearning(IStrategy):
|
||||
|
||||
# FIN ########################## ALGO ATH
|
||||
force = False #hours > self.hours_force.value and last_candle[self.indic_1h_force_buy.value] > 0
|
||||
condition = last_candle['percent'] > 0 and last_candle['sma24_deriv1'] > 0 \
|
||||
and last_candle['close'] < self.pairs[pair]['first_buy']
|
||||
condition = last_candle['percent'] > 0 \
|
||||
and ((count_of_buys <= 4 and last_candle['sma24_deriv1'] > 0) or (count_of_buys > 4 and last_candle['sma60_deriv1'] > 0))\
|
||||
and last_candle['close'] < self.pairs[pair]['first_price']
|
||||
|
||||
if ((force or decline >= dca_threshold) and condition):
|
||||
try:
|
||||
@@ -1321,7 +1328,7 @@ class FrictradeLearning(IStrategy):
|
||||
stake=round(stake_amount, 2)
|
||||
)
|
||||
|
||||
self.pairs[trade.pair]['last_buy'] = current_rate
|
||||
self.pairs[trade.pair]['last_price'] = current_rate
|
||||
self.pairs[trade.pair]['max_touch'] = last_candle['close']
|
||||
self.pairs[trade.pair]['last_candle'] = last_candle
|
||||
|
||||
@@ -1329,7 +1336,7 @@ class FrictradeLearning(IStrategy):
|
||||
# colonnes_a_exclure = ['last_candle', 'stop',
|
||||
# 'trade_info', 'last_date', 'expected_profit', 'last_count_of_buys', 'base_stake_amount', 'stop_buy']
|
||||
# df_filtered = df[df['count_of_buys'] > 0].drop(columns=colonnes_a_exclure)
|
||||
# # df_filtered = df_filtered["first_buy", "last_max", "max_touch", "last_sell","last_buy", 'count_of_buys', 'current_profit']
|
||||
# # df_filtered = df_filtered["first_price", "last_max", "max_touch", "last_sell","last_price", 'count_of_buys', 'current_profit']
|
||||
#
|
||||
# self.printLog(df_filtered)
|
||||
|
||||
@@ -1365,7 +1372,7 @@ class FrictradeLearning(IStrategy):
|
||||
buys=trade.nr_of_successful_entries + 1,
|
||||
stake=round(stake_amount, 2)
|
||||
)
|
||||
self.pairs[trade.pair]['last_buy'] = current_rate
|
||||
self.pairs[trade.pair]['last_price'] = current_rate
|
||||
self.pairs[trade.pair]['max_touch'] = last_candle['close']
|
||||
self.pairs[trade.pair]['last_candle'] = last_candle
|
||||
return stake_amount
|
||||
@@ -1417,8 +1424,8 @@ class FrictradeLearning(IStrategy):
|
||||
self.pairs[pair]['current_profit'] = profit
|
||||
|
||||
dispo = round(self.wallets.get_available_stake_amount())
|
||||
# hours_since_first_buy = (current_time - trade.open_date_utc).seconds / 3600.0
|
||||
# days_since_first_buy = (current_time - trade.open_date_utc).days
|
||||
# hours_since_first_price = (current_time - trade.open_date_utc).seconds / 3600.0
|
||||
# days_since_first_price = (current_time - trade.open_date_utc).days
|
||||
# hours = (current_time - trade.date_last_filled_utc).total_seconds() / 3600.0
|
||||
minutes = (current_time - trade.date_last_filled_utc).total_seconds() / 60.0
|
||||
|
||||
@@ -1432,9 +1439,9 @@ class FrictradeLearning(IStrategy):
|
||||
current_trailing_only_offset_is_reached = self.trailing_only_offset_is_reached
|
||||
current_trailing_stop_positive_offset = self.trailing_stop_positive_offset
|
||||
|
||||
current_trailing_stop_positive_offset = self.dynamic_trailing_offset(price=current_rate,
|
||||
current_trailing_stop_positive_offset = self.dynamic_trailing_offset(pair, price=current_rate,
|
||||
ath=self.pairs[pair]['last_ath'],
|
||||
nb_entries=count_of_buys)
|
||||
count_of_buys=count_of_buys)
|
||||
|
||||
# max_ = last_candle['max180']
|
||||
# min_ = last_candle['min180']
|
||||
|
||||
Reference in New Issue
Block a user