Compare commits
139 Commits
main
...
123804b5f3
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
123804b5f3 | ||
|
|
f5bf4a4ac1 | ||
|
|
42832df325 | ||
|
|
26aa1ea32b | ||
|
|
0250e30e57 | ||
|
|
2c79bc706e | ||
|
|
70e1a57e47 | ||
|
|
63b425aaf6 | ||
|
|
18c392b7f2 | ||
|
|
91bf3ca8ae | ||
|
|
a09189064e | ||
|
|
60ed27529a | ||
|
|
a228e56172 | ||
|
|
18fa5151e8 | ||
|
|
8dd4db80f8 | ||
|
|
fb7a841bd2 | ||
|
|
978f062991 | ||
|
|
8210b5c0b3 | ||
|
|
c26966da45 | ||
|
|
54d028d4f8 | ||
|
|
17d8b7ccbc | ||
|
|
c82b3359fa | ||
|
|
639afa42f0 | ||
|
|
c039aa29bd | ||
|
|
94b9845619 | ||
|
|
2fac557edb | ||
|
|
d7b9059d40 | ||
|
|
11bb59636e | ||
|
|
3cac030f10 | ||
|
|
e8cdf10488 | ||
|
|
fc6d516252 | ||
|
|
ae98d11559 | ||
|
|
3efc95e415 | ||
|
|
496c4d7827 | ||
|
|
c66b9c4a8b | ||
|
|
89abd0b4da | ||
|
|
0e787f54e6 | ||
|
|
b270b3b283 | ||
|
|
340c651a8a | ||
|
|
682528444f | ||
|
|
a7b09858f4 | ||
|
|
51ca009751 | ||
|
|
8bf0a0e2c3 | ||
|
|
c7530208a3 | ||
|
|
dec03afd8b | ||
|
|
30a45d592a | ||
|
|
e35ee0ed23 | ||
|
|
a376e37e61 | ||
|
|
dfe04a3f0c | ||
|
|
1d77bf0399 | ||
|
|
d8b7dce28a | ||
|
|
a7135599bc | ||
|
|
a1f5bc1e41 | ||
|
|
3ca1c2d9c1 | ||
|
|
3b3cf5976a | ||
|
|
acaf1c9a7b | ||
|
|
a2f9942675 | ||
|
|
4b22f3efb6 | ||
|
|
82ab199e2d | ||
|
|
c4bba8aad8 | ||
|
|
d9f947481e | ||
|
|
bd6699493a | ||
|
|
fd4a487034 | ||
|
|
ad5a97a8c2 | ||
|
|
6757f4d432 | ||
|
|
b995936da2 | ||
|
|
96a0b0b2b0 | ||
|
|
d5e4c93947 | ||
|
|
f6951fd56f | ||
|
|
04c7d190b1 | ||
|
|
fdf1918b58 | ||
|
|
0f8b1a7c22 | ||
|
|
b25d6f5759 | ||
|
|
a26460cf10 | ||
|
|
074205cc09 | ||
|
|
8b581e5a39 | ||
|
|
b4b9669ee0 | ||
|
|
7640b204dd | ||
|
|
1a438686b0 | ||
|
|
f3f949455f | ||
|
|
0ee3916eb4 | ||
|
|
4c0692426e | ||
|
|
ee45dc890d | ||
|
|
7720646267 | ||
|
|
682c146a66 | ||
|
|
a061a9d941 | ||
|
|
aabfce79ec | ||
|
|
36f4e94020 | ||
|
|
67f617a5da | ||
|
|
96d6d4b679 | ||
|
|
bd0933cb6a | ||
|
|
48ceb7f460 | ||
|
|
b8da3af406 | ||
|
|
1090093735 | ||
|
|
70ceb76f1b | ||
|
|
7a55dd2565 | ||
|
|
6be42bc155 | ||
|
|
83f3923bbf | ||
|
|
5d8f5dcb96 | ||
|
|
88a43dbd23 | ||
|
|
3b14693536 | ||
|
|
39bd32370a | ||
|
|
845d2588d5 | ||
|
|
4d875a4c97 | ||
|
|
7f0e4905bf | ||
|
|
82391fcde1 | ||
|
|
5a9adb0b53 | ||
|
|
a932ebd369 | ||
|
|
468ada80ca | ||
|
|
d0ac71f60d | ||
|
|
96976e842d | ||
|
|
77e7f797fe | ||
|
|
b0a22e61c5 | ||
|
|
faec58ef19 | ||
|
|
685c04da50 | ||
|
|
09d9dd1583 | ||
|
|
23fa2f7765 | ||
|
|
27847fea95 | ||
|
|
9cce16610d | ||
|
|
24d10698d2 | ||
|
|
0efc4853a7 | ||
|
|
28c33cf3b9 | ||
|
|
121eda7837 | ||
|
|
088958952e | ||
|
|
2f66ab3be7 | ||
|
|
a0143c38e1 | ||
|
|
4ecc40b7aa | ||
|
|
d7280410ff | ||
|
|
384404e590 | ||
|
|
18c940b06c | ||
|
|
e43702f10c | ||
|
|
f10344fff2 | ||
|
|
340ada3221 | ||
|
|
2b0b8953c8 | ||
|
|
f5847ffc25 | ||
|
|
86bcb1240e | ||
|
|
d1cf9ab72f | ||
|
|
501f5507ca | ||
|
|
4d37361bc6 |
4
.gitignore
vendored
4
.gitignore
vendored
@@ -1,3 +1,5 @@
|
||||
.idea/
|
||||
__pycache__/
|
||||
__pycache__/
|
||||
Save/
|
||||
**/__pycache__/
|
||||
|
||||
|
||||
46
Empty.json
Normal file
46
Empty.json
Normal file
@@ -0,0 +1,46 @@
|
||||
{
|
||||
"strategy_name": "Empty",
|
||||
"params": {
|
||||
"roi": {
|
||||
"0": 5
|
||||
},
|
||||
"stoploss": {
|
||||
"stoploss": -1.0
|
||||
},
|
||||
"trailing": {
|
||||
"trailing_stop": false,
|
||||
"trailing_stop_positive": null,
|
||||
"trailing_stop_positive_offset": 0.0,
|
||||
"trailing_only_offset_is_reached": false
|
||||
},
|
||||
"max_open_trades": {
|
||||
"max_open_trades": 20
|
||||
},
|
||||
"protection": {
|
||||
"b30_indicateur": "sma36",
|
||||
"baisse": 0.33,
|
||||
"drop_from_last_entry": -0.03
|
||||
},
|
||||
"buy": {
|
||||
"buy_deriv1_sma12d": -0.04,
|
||||
"buy_deriv1_sma5d": -0.02,
|
||||
"buy_deriv1_sma60": 0.001,
|
||||
"buy_deriv2_sma12d": -0.02,
|
||||
"buy_deriv2_sma5d": 0.0,
|
||||
"buy_deriv2_sma60": -0.001,
|
||||
"buy_longue": 160,
|
||||
"buy_longue_derive": "sma80_deriv1_1d",
|
||||
"start_bear_deriv1": -0.004,
|
||||
"start_bear_deriv2": 0.002,
|
||||
"start_bear_indicator": "sma80",
|
||||
"start_bull_deriv1": 0.001,
|
||||
"start_bull_deriv2": -0.002,
|
||||
"start_bull_indicator": "sma120"
|
||||
},
|
||||
"sell": {
|
||||
"sell_score_indicator": "sma24_score"
|
||||
}
|
||||
},
|
||||
"ft_stratparam_v": 1,
|
||||
"export_time": "2026-02-28 17:28:20.867470+00:00"
|
||||
}
|
||||
512
Empty.txt
Normal file
512
Empty.txt
Normal file
@@ -0,0 +1,512 @@
|
||||
👉 Cette version est objectivement supérieure.
|
||||
|
||||
Même si le CAGR bouge légèrement, tout le reste s’améliore fortement.
|
||||
|
||||
📊 Comparaison claire
|
||||
Metric Avant Maintenant
|
||||
Trades 95 53
|
||||
CAGR 21.38% 22.45%
|
||||
Profit Factor 1.89 2.85
|
||||
SQN 1.87 2.38
|
||||
Winrate 48% 62%
|
||||
Max DD 21.97% 7.37%
|
||||
DD duration 309 jours 28 jours
|
||||
Calmar 7.08 22.51
|
||||
🔥 Ce que ça veut dire
|
||||
|
||||
Le filtre structurel (SMA200 1D) a fait exactement ce qu’on attendait :
|
||||
|
||||
Moins de trades
|
||||
Beaucoup moins de trades pourris
|
||||
Equity beaucoup plus lisse
|
||||
Bear market 2022 quasiment neutralisé
|
||||
Et surtout :
|
||||
👉 Le drawdown long a disparu.
|
||||
C’est LE point critique.
|
||||
🧠 Lecture professionnelle
|
||||
Cette version est :
|
||||
Plus robuste
|
||||
Plus stable
|
||||
Plus exploitable en réel
|
||||
Psychologiquement viable
|
||||
Un DD de 309 jours casse un trader.
|
||||
Un DD de 28 jours est gérable.
|
||||
|
||||
🎯 Ce qui est très intéressant
|
||||
|
||||
Regarde ça :
|
||||
Worst trade passe de -4.55% → -4.10%
|
||||
Profit factor explose à 2.85
|
||||
Expectancy 24.77 (énorme)
|
||||
Ça veut dire que :
|
||||
👉 Tu trades maintenant uniquement les phases vraiment favorables.
|
||||
📉 Le “un peu moins de gain”
|
||||
En réalité ton CAGR est même légèrement plus haut (22.45 vs 21.38).
|
||||
Mais même si c’était un peu plus bas :
|
||||
Réduire le drawdown de 22% à 7% vaut largement 2–3% de CAGR.
|
||||
Toujours.
|
||||
|
||||
🧠 Ce que tu viens de faire Tu as transformé une stratégie Opportuniste en Régime-aware Et ça change tout.
|
||||
|
||||
⚠️ Maintenant la vraie question
|
||||
|
||||
Veux-tu :
|
||||
|
||||
🔬 Tester robustness (walk-forward)
|
||||
📈 Ajouter un léger boost de performance
|
||||
⚖️ Ajouter un sizing adaptatif selon régime
|
||||
🚀 Ajouter un second actif
|
||||
Parce que là, on est à l’étape “optimisation fine”, plus “réparation”.
|
||||
=============================================================================
|
||||
Bon.
|
||||
|
||||
Là on va parler sérieusement 😄
|
||||
Parce que tes résultats ne sont pas mauvais du tout.
|
||||
|
||||
📊 Lecture objective de ton backtest
|
||||
✅ Points très solides
|
||||
CAGR 35% sur 4 ans → très correct
|
||||
Max DD 10.6% → excellent
|
||||
Profit factor 1.86 → bon edge
|
||||
Calmar 29 → extrêmement bon (drawdown très maîtrisé)
|
||||
Max underwater 11% → propre
|
||||
Pas d’explosion du risk
|
||||
|
||||
Franchement, c’est une stratégie saine.
|
||||
|
||||
⚠️ Le vrai problème
|
||||
|
||||
Regarde ces deux chiffres :
|
||||
Sharpe : 0.21
|
||||
Sortino : 1.31
|
||||
Sharpe très bas → equity curve irrégulière
|
||||
Sortino correct → pertes contrôlées
|
||||
|
||||
Ce que ça dit :
|
||||
|
||||
Tu gagnes bien… mais de manière irrégulière.
|
||||
|
||||
🎯 Ce qui saute aux yeux
|
||||
92 trades en 4 ans
|
||||
Ça fait :
|
||||
23 trades par an
|
||||
C’est extrêmement peu.
|
||||
Donc :
|
||||
Quelques gros trades font la perf
|
||||
Beaucoup de périodes mortes
|
||||
Equity plate pendant longtemps
|
||||
Ce n’est pas un problème technique. C’est un problème structurel.
|
||||
🧠Ce que ton système est en réalité Ce n’est pas un trend following classique.
|
||||
|
||||
C’est Un breakout / impulsion filtrée daily
|
||||
|
||||
Regarde :
|
||||
Best trade : +48%
|
||||
Avg winner duration : 6 jours
|
||||
Certains winners : 85 jours
|
||||
Tu attrapes des swings longs.
|
||||
Et tu survis entre deux cycles.
|
||||
|
||||
C’est cohérent.
|
||||
🚨 Pourquoi tu as l’impression que rien n’améliore ?
|
||||
Parce que tu es déjà dans un bon équilibre.
|
||||
Quand une stratégie est :
|
||||
Stable
|
||||
Faible DD
|
||||
PF proche de 2
|
||||
|
||||
👉 Les gains d’optimisation deviennent marginaux.
|
||||
|
||||
Tu n’es plus dans la phase “je corrige une erreur”.
|
||||
Tu es dans la phase “je modifie l’ADN”.
|
||||
|
||||
🔍 Ce que je vois comme axe réel d’amélioration
|
||||
|
||||
Pas le stoploss.
|
||||
Pas le RSI adaptatif.
|
||||
|
||||
Le vrai levier est ici :
|
||||
Winrate = 48.9%
|
||||
Tu es pile à l’équilibre.
|
||||
Si tu passes à 55% avec même RR,
|
||||
ta courbe devient radicalement plus stable.
|
||||
🎯 La vraie question
|
||||
|
||||
Tes losers durent :
|
||||
1d 12h en moyenne.
|
||||
Tes winners :
|
||||
6d 12h.
|
||||
Donc ton edge vient du R:R, pas du winrate.
|
||||
|
||||
💡 Deux directions possibles
|
||||
OPTION 1 — Rendre le système plus agressif
|
||||
Plus d’entrées
|
||||
Plus de trades
|
||||
Légèrement plus de DD
|
||||
|
||||
Sharpe augmente
|
||||
|
||||
→ Transformer ton système en semi-trend.
|
||||
|
||||
OPTION 2 — Assumer que c’est un cycle catcher
|
||||
|
||||
Et optimiser :
|
||||
La sortie en fin de cycle
|
||||
Le trailing dynamique
|
||||
La protection en marché neutre
|
||||
🎯 Analyse importante
|
||||
Market change : +44%
|
||||
Toi : +247%
|
||||
|
||||
Tu as largement surperformé le marché.
|
||||
|
||||
Donc ton edge est réel.
|
||||
|
||||
💬 Question importante
|
||||
|
||||
Tu veux :
|
||||
|
||||
A) Maximiser le CAGR
|
||||
B) Maximiser la stabilité (Sharpe > 1)
|
||||
C) Réduire encore le drawdown
|
||||
D) Multiplier les trades
|
||||
|
||||
Parce que selon ton objectif, on ne touche pas aux mêmes leviers.
|
||||
|
||||
Et là tu es à un point où chaque modification change la philosophie du système.
|
||||
|
||||
SUMMARY METRICS
|
||||
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
|
||||
┃ Metric ┃ Value ┃
|
||||
┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┩
|
||||
│ Backtesting from │ 2022-01-01 00:00:00 │
|
||||
│ Backtesting to │ 2026-02-20 00:00:00 │
|
||||
│ Trading Mode │ Spot │
|
||||
│ Max open trades │ 1 │
|
||||
│ │ │
|
||||
│ Total/Daily Avg Trades │ 92 / 0.06 │
|
||||
│ Starting balance │ 1000 USDT │
|
||||
│ Final balance │ 3474.507 USDT │
|
||||
│ Absolute profit │ 2474.507 USDT │
|
||||
│ Total profit % │ 247.45% │
|
||||
│ CAGR % │ 35.10% │
|
||||
│ Sortino │ 1.31 │
|
||||
│ Sharpe │ 0.21 │
|
||||
│ Calmar │ 29.34 │
|
||||
│ SQN │ 1.76 │
|
||||
│ Profit factor │ 1.86 │
|
||||
│ Expectancy (Ratio) │ 26.90 (0.44) │
|
||||
│ Avg. daily profit │ 1.638 USDT │
|
||||
│ Avg. stake amount │ 2413.03 USDT │
|
||||
│ Total trade volume │ 447365.827 USDT │
|
||||
│ │ │
|
||||
│ Best Pair │ BTC/USDT 247.45% │
|
||||
│ Worst Pair │ BTC/USDT 247.45% │
|
||||
│ Best trade │ BTC/USDT 48.98% │
|
||||
│ Worst trade │ BTC/USDT -5.61% │
|
||||
│ Best day │ 806.579 USDT │
|
||||
│ Worst day │ -137.268 USDT │
|
||||
│ Days win/draw/lose │ 44 / 1328 / 47 │
|
||||
│ Min/Max/Avg. Duration Winners │ 1d 03:00 / 85d 12:00 / 6d 12:21 │
|
||||
│ Min/Max/Avg. Duration Losers │ 0d 02:00 / 5d 12:00 / 1d 12:28 │
|
||||
│ Max Consecutive Wins / Loss │ 4 / 4 │
|
||||
│ Rejected Entry signals │ 0 │
|
||||
│ Entry/Exit Timeouts │ 0 / 0 │
|
||||
│ │ │
|
||||
│ Min balance │ 981.947 USDT │
|
||||
│ Max balance │ 3630.59 USDT │
|
||||
│ Max % of account underwater │ 11.64% │
|
||||
│ Absolute drawdown │ 359.078 USDT (10.66%) │
|
||||
│ Drawdown duration │ 86 days 03:00:00 │
|
||||
│ Profit at drawdown start │ 2367.463 USDT │
|
||||
│ Profit at drawdown end │ 2008.385 USDT │
|
||||
│ Drawdown start │ 2025-01-19 22:00:00 │
|
||||
│ Drawdown end │ 2025-04-16 01:00:00 │
|
||||
│ Market change │ 44.09% │
|
||||
└───────────────────────────────┴─────────────────────────────────┘
|
||||
|
||||
Backtested 2022-01-01 00:00:00 -> 2026-02-20 00:00:00 | Max open trades : 1
|
||||
STRATEGY SUMMARY
|
||||
┏━━━━━━━━━━┳━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━┓
|
||||
┃ Strategy ┃ Trades ┃ Avg Profit % ┃ Tot Profit USDT ┃ Tot Profit % ┃ Avg Duration ┃ Win Draw Loss Win% ┃ Drawdown ┃
|
||||
┡━━━━━━━━━━╇━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━┩
|
||||
│ Empty │ 92 │ 1.62 │ 2474.507 │ 247.45 │ 3 days, 23:07:00 │ 45 0 47 48.9 │ 359.078 USDT 10.66% │
|
||||
└──────────┴────────┴──────────────┴─────────────────┴──────────────┴──────────────────┴────────────────────────┴──────────────────────┘
|
||||
|
||||
| Date | Action |Pair | Trade Type | Rate | Dispo | Profit | Pct | max_touch | last_lost | last_max| last_max| Buys| Stake | rsi|
|
||||
+------------------+------------+-----+--------------------+---------+--------+------------+--------+-------------+--------------+------------------+-----+-------++------+-------+-----+-----+-----+-----+-----+-----+
|
||||
| 2023-01-10 17:00 |🟩Buy 0 | BTC | bull | 17302.55| 1000 | 0/0| - | 17302.15 | - | 17302 | 17302 | 1/1| 1000.0
|
||||
| 2023-02-09 22:00 |🟥Sell 43500 | BTC | B30 | 21856.3| - |260.9/395.52| 0.263 | 17302.15 | 0.263 | 17302 | 17302 | /1| -
|
||||
| 2023-02-15 00:00 |🟩Buy 7320 | BTC | bull | 22199.84| 1261 | 0/0| - | 22199.84 | - | 22199 | 17302 | 1/1| 1260.9
|
||||
| 2023-02-16 23:00 |🟥Sell 2820 | BTC | B30 | 23994.76| - |99.31/160.46| 0.081 | 22199.84 | 0.081 | 22199 | 17302 | /1| -
|
||||
| 2023-02-17 17:00 |🟩Buy 1080 | BTC | bull | 24091.21| 1360 | 0/0| - | 24091.21 | - | 24091 | 17302 | 1/1|1360.21
|
||||
| 2023-02-19 18:00 |🟥Sell 2940 | BTC | B30 | 24361.74| - |12.69/44.15| 0.011 | 24091.21 | 0.011 | 24091 | 17302 | /1| -
|
||||
| 2023-02-28 17:00 |🟩Buy 12900 | BTC | bull | 23456.05| 1373 | 0/0| - | 23456.05 | - | 24091 | 17302 | 1/1| 1372.9
|
||||
| 2023-03-03 02:00 |🟥Sell 3420 | BTC | sma60 | 22150.31| - |-79.09/21.4| -0.056 | 23456.05 | -0.056 | 24091 | 17302 | /1| -
|
||||
| 2023-03-16 09:00 |🟩Buy 19140 | BTC | bull | 24581.1| 1294 | 0/0| - | 24581.1 | - | 24581 | 17302 | 1/1| 1293.8
|
||||
| 2023-03-22 20:00 |🟥Sell 9300 | BTC | B30 | 26667.33| - |107.18/211.2| 0.085 | 24581.1 | 0.085 | 24581 | 17302 | /1| -
|
||||
| Date | Action |Pair | Trade Type | Rate | Dispo | Profit | Pct | max_touch | last_lost | last_max| last_max| Buys| Stake | rsi|
|
||||
+------------------+------------+-----+--------------------+---------+--------+------------+--------+-------------+--------------+------------------+-----+-------++------+-------+-----+-----+-----+-----+-----+-----+
|
||||
| 2023-03-30 03:00 |🟩Buy 10500 | BTC | bull | 28964.76| 1401 | 0/0| - | 28964.76 | - | 28964 | 17302 | 1/1|1400.98
|
||||
| 2023-03-30 18:00 |🟥Sell 900 | BTC | sma60 | 27839.41| - | -57.17/0| -0.039 | 28964.76 | -0.039 | 28964 | 17302 | /1| -
|
||||
| 2023-03-31 15:00 |🟩Buy 1260 | BTC | bull | 28521.78| 1344 | 0/0| - | 28521.78 | - | 28964 | 17302 | 1/1|1343.81
|
||||
| 2023-04-02 20:00 |🟥Sell 3180 | BTC | sma60 | 27943.85| - |-29.89/1.49| -0.02 | 28521.78 | -0.02 | 28964 | 17302 | /1| -
|
||||
| 2023-04-13 04:00 |🟩Buy 14880 | BTC | bull | 30072.17| 1314 | 0/0| - | 30072.17 | - | 30072 | 17302 | 1/1|1313.92
|
||||
| 2023-04-15 02:00 |🟥Sell 2760 | BTC | B30 | 30370.01| - |10.37/35.37| 0.01 | 30072.17 | 0.01 | 30072 | 17302 | /1| -
|
||||
| 2023-04-26 00:00 |🟩Buy 15720 | BTC | bull | 28300.8| 1324 | 0/0| - | 28300.79 | - | 30072 | 17302 | 1/1| 1324.3
|
||||
| 2023-04-28 14:00 |🟥Sell 3720 | BTC | B30 | 29029.48| - |31.41/75.16| 0.026 | 28300.79 | 0.026 | 30072 | 17302 | /1| -
|
||||
| 2023-04-28 23:00 |🟩Buy 540 | BTC | bull | 29345.35| 1356 | 0/0| - | 29345.34 | - | 30072 | 17302 | 1/1|1355.71
|
||||
| 2023-05-01 02:00 |🟥Sell 3060 | BTC | sma60 | 28504.36| - |-41.52/14.46| -0.029 | 29345.34 | -0.029 | 30072 | 17302 | /1| -
|
||||
| Date | Action |Pair | Trade Type | Rate | Dispo | Profit | Pct | max_touch | last_lost | last_max| last_max| Buys| Stake | rsi|
|
||||
+------------------+------------+-----+--------------------+---------+--------+------------+--------+-------------+--------------+------------------+-----+-------++------+-------+-----+-----+-----+-----+-----+-----+
|
||||
| 2023-05-30 12:00 |🟩Buy 42360 | BTC | bull | 28021.39| 1314 | 0/0| - | 28021.4 | - | 30072 | 17302 | 1/1|1314.19
|
||||
| 2023-05-31 05:00 |🟥Sell 1020 | BTC | sma60 | 27257.7| - | -38.4/0| -0.027 | 28021.4 | -0.027 | 30072 | 17302 | /1| -
|
||||
| 2023-06-19 19:00 |🟩Buy 28200 | BTC | bull | 26495.99| 1276 | 0/0| - | 26496.0 | - | 30072 | 17302 | 1/1|1275.79
|
||||
| 2023-07-17 19:00 |🟥Sell 40320 | BTC | B30 | 29802.39| - |156.49/243.25| 0.125 | 26496.0 | 0.125 | 30072 | 17302 | /1| -
|
||||
| 2023-07-19 05:00 |🟩Buy 2040 | BTC | bull | 30099.08| 1432 | 0/0| - | 30099.08 | - | 30099 | 17302 | 1/1|1432.28
|
||||
| 2023-07-24 10:00 |🟥Sell 7500 | BTC | sma60 | 29178.01| - |-46.65/8.02| -0.031 | 30099.08 | -0.031 | 30099 | 17302 | /1| -
|
||||
| 2023-09-20 03:00 |🟩Buy 83100 | BTC | bull | 27165.48| 1386 | 0/0| - | 27165.48 | - | 30099 | 17302 | 1/1|1385.64
|
||||
| 2023-09-21 11:00 |🟥Sell 1920 | BTC | sma60 | 26649.89| - | -29.04/0| -0.019 | 27165.48 | -0.019 | 30099 | 17302 | /1| -
|
||||
| 2023-10-01 08:00 |🟩Buy 14220 | BTC | bull | 27107.94| 1357 | 0/0| - | 27107.95 | - | 30099 | 17302 | 1/1| 1356.6
|
||||
| 2023-10-02 22:00 |🟥Sell 2280 | BTC | B30 | 27472.22| - |15.5/69.08| 0.013 | 27107.95 | 0.013 | 30099 | 17302 | /1| -
|
||||
| Date | Action |Pair | Trade Type | Rate | Dispo | Profit | Pct | max_touch | last_lost | last_max| last_max| Buys| Stake | rsi|
|
||||
+------------------+------------+-----+--------------------+---------+--------+------------+--------+-------------+--------------+------------------+-----+-------++------+-------+-----+-----+-----+-----+-----+-----+
|
||||
| 2023-10-15 20:00 |🟩Buy 18600 | BTC | bull | 27043.75| 1372 | 0/0| - | 27043.75 | - | 30099 | 17302 | 1/1| 1372.1
|
||||
| 2023-10-18 15:00 |🟥Sell 4020 | BTC | B30 | 28190.49| - |55.37/82.75| 0.042 | 27043.75 | 0.042 | 30099 | 17302 | /1| -
|
||||
| 2023-10-19 12:00 |🟩Buy 1260 | BTC | bull | 28450.7| 1427 | 0/0| - | 28450.69 | - | 30099 | 17302 | 1/1|1427.47
|
||||
| 2024-01-15 00:00 |🟥Sell 126000 | BTC | B30 | 41732.35| - |662.82/1005.58| 0.467 | 28450.69 | 0.467 | 30099 | 17302 | /1| -
|
||||
| 2024-01-27 22:00 |🟩Buy 18600 | BTC | bull | 42150.59| 2090 | 0/0| - | 42150.59 | - | 42150 | 17302 | 1/1|2090.29
|
||||
| 2024-01-31 00:00 |🟥Sell 4440 | BTC | B30 | 42941.1| - |34.98/68.37| 0.019 | 42150.59 | 0.019 | 42150 | 17302 | /1| -
|
||||
| 2024-02-08 00:00 |🟩Buy 11520 | BTC | bull | 44349.6| 2125 | 0/0| - | 44349.6 | - | 44349 | 17302 | 1/1|2125.27
|
||||
| 2024-03-19 09:00 |🟥Sell 58140 | BTC | B30 | 63464.0| - |910.78/1394.94| 0.431 | 44349.6 | 0.431 | 44349 | 17302 | /1| -
|
||||
| 2024-03-24 11:00 |🟩Buy 7320 | BTC | bull | 65098.01| 3036 | 0/0| - | 65098.01 | - | 65098 | 17302 | 1/1|3036.05
|
||||
| 2024-03-27 16:00 |🟥Sell 4620 | BTC | B30 | 68874.0| 1 |169.83/275.49| 0.058 | 65098.01 | 0.058 | 65098 | 17302 | /1| -
|
||||
| Date | Action |Pair | Trade Type | Rate | Dispo | Profit | Pct | max_touch | last_lost | last_max| last_max| Buys| Stake | rsi|
|
||||
+------------------+------------+-----+--------------------+---------+--------+------------+--------+-------------+--------------+------------------+-----+-------++------+-------+-----+-----+-----+-----+-----+-----+
|
||||
| 2024-03-28 07:00 |🟩Buy 900 | BTC | bull | 70363.74| 3206 | 0/0| - | 70363.74 | - | 70363 | 17302 | 1/1|3205.87
|
||||
| 2024-04-01 15:00 |🟥Sell 6240 | BTC | sma60 | 68906.07| - |-72.76/47.03| -0.021 | 70363.74 | -0.021 | 70363 | 17302 | /1| -
|
||||
| 2024-04-08 08:00 |🟩Buy 9660 | BTC | bull | 70698.64| 3133 | 0/0| - | 70698.63 | - | 70698 | 17302 | 1/1|3133.12
|
||||
| 2024-04-09 15:00 |🟥Sell 1860 | BTC | sma60 | 69358.32| - |-65.6/69.22| -0.019 | 70698.63 | -0.019 | 70698 | 17302 | /1| -
|
||||
| 2024-04-10 20:00 |🟩Buy 1740 | BTC | bull | 70084.0| 3068 | 0/0| - | 70083.99 | - | 70698 | 17302 | 1/1|3067.52
|
||||
| 2024-04-12 18:00 |🟥Sell 2760 | BTC | sma60 | 68140.02| 1 |-91.12/38.98| -0.028 | 70083.99 | -0.028 | 70698 | 17302 | /1| -
|
||||
| 2024-04-24 05:00 |🟩Buy 16500 | BTC | bull | 67008.0| 2976 | 0/0| - | 67008.0 | - | 70698 | 17302 | 1/1| 2976.4
|
||||
| 2024-04-24 15:00 |🟥Sell 600 | BTC | sma60 | 65234.85| 1 | -84.62/0| -0.026 | 67008.0 | -0.026 | 70698 | 17302 | /1| -
|
||||
| 2024-05-06 08:00 |🟩Buy 16860 | BTC | bull | 64540.75| 2892 | 0/0| - | 64540.75 | - | 70698 | 17302 | 1/1|2891.79
|
||||
| 2024-05-06 15:00 |🟥Sell 420 | BTC | sma60 | 63271.97| - |-62.57/22.21| -0.02 | 64540.75 | -0.02 | 70698 | 17302 | /1| -
|
||||
| Date | Action |Pair | Trade Type | Rate | Dispo | Profit | Pct | max_touch | last_lost | last_max| last_max| Buys| Stake | rsi|
|
||||
+------------------+------------+-----+--------------------+---------+--------+------------+--------+-------------+--------------+------------------+-----+-------++------+-------+-----+-----+-----+-----+-----+-----+
|
||||
| 2024-05-07 10:00 |🟩Buy 1140 | BTC | bull | 64119.98| 2829 | 0/0| - | 64119.98 | - | 70698 | 17302 | 1/1|2829.22
|
||||
| 2024-05-07 23:00 |🟥Sell 780 | BTC | sma60 | 62850.92| - | -61.59/0| -0.02 | 64119.98 | -0.02 | 70698 | 17302 | /1| -
|
||||
| 2024-05-17 08:00 |🟩Buy 13500 | BTC | bull | 66386.93| 2768 | 0/0| - | 66386.94 | - | 70698 | 17302 | 1/1|2767.63
|
||||
| 2024-05-19 15:00 |🟥Sell 3300 | BTC | B30 | 66928.0| 1 |17.0/33.73| 0.008 | 66386.94 | 0.008 | 70698 | 17302 | /1| -
|
||||
| 2024-05-27 16:00 |🟩Buy 11580 | BTC | bull | 70373.86| 2785 | 0/0| - | 70373.85 | - | 70698 | 17302 | 1/1|2784.62
|
||||
| 2024-05-28 02:00 |🟥Sell 600 | BTC | sma60 | 68614.11| 1 | -75.11/0| -0.025 | 70373.85 | -0.025 | 70698 | 17302 | /1| -
|
||||
| 2024-06-05 01:00 |🟩Buy 11460 | BTC | bull | 70775.99| 2710 | 0/0| - | 70776.0 | - | 70776 | 17302 | 1/1|2709.51
|
||||
| 2024-06-07 19:00 |🟥Sell 3960 | BTC | sma60 | 69154.43| - |-67.43/29.92| -0.023 | 70776.0 | -0.023 | 70776 | 17302 | /1| -
|
||||
| 2024-07-15 00:00 |🟩Buy 53580 | BTC | bull | 60797.91| 2642 | 0/0| - | 60797.91 | - | 70776 | 17302 | 1/1|2642.08
|
||||
| 2024-07-16 09:00 |🟥Sell 1980 | BTC | B30 | 62820.67| - |82.52/170.52| 0.033 | 60797.91 | 0.033 | 70776 | 17302 | /1| -
|
||||
| Date | Action |Pair | Trade Type | Rate | Dispo | Profit | Pct | max_touch | last_lost | last_max| last_max| Buys| Stake | rsi|
|
||||
+------------------+------------+-----+--------------------+---------+--------+------------+--------+-------------+--------------+------------------+-----+-------++------+-------+-----+-----+-----+-----+-----+-----+
|
||||
| 2024-07-16 17:00 |🟩Buy 480 | BTC | bull | 64500.0| 2725 | 0/0| - | 64500.0 | - | 70776 | 17302 | 1/1| 2724.6
|
||||
| 2024-07-22 15:00 |🟥Sell 8520 | BTC | B30 | 66712.0| - |87.89/150.43| 0.034 | 64500.0 | 0.034 | 70776 | 17302 | /1| -
|
||||
| 2024-07-27 00:00 |🟩Buy 6300 | BTC | bull | 67908.0| 2812 | 0/0| - | 67907.99 | - | 70776 | 17302 | 1/1|2812.49
|
||||
| 2024-07-30 01:00 |🟥Sell 4380 | BTC | sma60 | 66610.0| - |-59.32/72.62| -0.019 | 67907.99 | -0.019 | 70776 | 17302 | /1| -
|
||||
| 2024-08-25 23:00 |🟩Buy 38760 | BTC | bull | 64482.0| 2753 | 0/0| - | 64482.01 | - | 70776 | 17302 | 1/1|2753.17
|
||||
| 2024-08-26 22:00 |🟥Sell 1380 | BTC | sma60 | 63155.81| - | -62.06/0| -0.021 | 64482.01 | -0.021 | 70776 | 17302 | /1| -
|
||||
| 2024-09-14 00:00 |🟩Buy 26040 | BTC | bull | 60497.99| 2691 | 0/0| - | 60498.0 | - | 70776 | 17302 | 1/1| 2691.1
|
||||
| 2024-09-16 00:00 |🟥Sell 2880 | BTC | sma60 | 59132.0| - | -66.08/0| -0.023 | 60498.0 | -0.023 | 70776 | 17302 | /1| -
|
||||
| 2024-09-19 00:00 |🟩Buy 4320 | BTC | bull | 61759.98| 2625 | 0/0| - | 61759.99 | - | 70776 | 17302 | 1/1|2625.02
|
||||
| 2024-09-20 18:00 |🟥Sell 2520 | BTC | B30 | 62704.0| - |34.83/83.22| 0.015 | 61759.99 | 0.015 | 70776 | 17302 | /1| -
|
||||
| Date | Action |Pair | Trade Type | Rate | Dispo | Profit | Pct | max_touch | last_lost | last_max| last_max| Buys| Stake | rsi|
|
||||
+------------------+------------+-----+--------------------+---------+--------+------------+--------+-------------+--------------+------------------+-----+-------++------+-------+-----+-----+-----+-----+-----+-----+
|
||||
| 2024-09-28 04:00 |🟩Buy 10680 | BTC | bull | 66063.76| 2660 | 0/0| - | 66063.76 | - | 70776 | 17302 | 1/1|2659.86
|
||||
| 2024-09-30 02:00 |🟥Sell 2760 | BTC | sma60 | 64769.99| - | -57.35/0| -0.02 | 66063.76 | -0.02 | 70776 | 17302 | /1| -
|
||||
| 2024-10-14 05:00 |🟩Buy 20340 | BTC | bull | 64137.99| 2603 | 0/0| - | 64137.99 | - | 70776 | 17302 | 1/1| 2602.5
|
||||
| 2024-10-21 14:00 |🟥Sell 10620 | BTC | B30 | 67312.0| - |123.44/200.4| 0.049 | 64137.99 | 0.049 | 70776 | 17302 | /1| -
|
||||
| 2024-10-27 15:00 |🟩Buy 8700 | BTC | bull | 67696.0| 2726 | 0/0| - | 67695.99 | - | 70776 | 17302 | 1/1|2725.94
|
||||
| 2024-10-31 14:00 |🟥Sell 5700 | BTC | B30 | 71308.0| - |139.82/214.71| 0.053 | 67695.99 | 0.053 | 70776 | 17302 | /1| -
|
||||
| 2024-11-06 01:00 |🟩Buy 7860 | BTC | bull | 71096.03| 2866 | 0/0| - | 71096.04 | - | 71096 | 17302 | 1/1|2865.76
|
||||
| 2024-12-20 09:00 |🟥Sell 63840 | BTC | B30 | 95473.74| 1 |975.71/1490.41| 0.343 | 71096.04 | 0.343 | 71096 | 17302 | /1| -
|
||||
| 2024-12-26 00:00 |🟩Buy 8100 | BTC | bull | 99429.61| 3841 | 0/0| - | 99429.6 | - | 99429 | 17302 | 1/1|3841.47
|
||||
| 2024-12-26 09:00 |🟥Sell 540 | BTC | sma60 | 95878.56| 1 | -144.72/0| -0.036 | 99429.6 | -0.036 | 99429 | 17302 | /1| -
|
||||
| Date | Action |Pair | Trade Type | Rate | Dispo | Profit | Pct | max_touch | last_lost | last_max| last_max| Buys| Stake | rsi|
|
||||
+------------------+------------+-----+--------------------+---------+--------+------------+--------+-------------+--------------+------------------+-----+-------++------+-------+-----+-----+-----+-----+-----+-----+
|
||||
| 2025-01-05 23:00 |🟩Buy 15240 | BTC | bull | 98695.21| 3697 | 0/0| - | 98695.21 | - | 99429 | 17302 | 1/1|3696.75
|
||||
| 2025-01-07 13:00 |🟥Sell 2280 | BTC | B30 |100750.89| 1 |69.52/125.06| 0.021 | 98695.21 | 0.021 | 99429 | 17302 | /1| -
|
||||
| 2025-01-13 22:00 |🟩Buy 9180 | BTC | bull | 94193.49| 3766 | 0/0| - | 94193.49 | - | 99429 | 17302 | 1/1|3766.26
|
||||
| 2025-01-16 15:00 |🟥Sell 3900 | BTC | B30 | 97618.89| - |129.28/244.24| 0.036 | 94193.49 | 0.036 | 99429 | 17302 | /1| -
|
||||
| 2025-01-17 02:00 |🟩Buy 660 | BTC | bull | 101659.8| 3896 | 0/0| - | 101659.8 | - | 101659 | 17302 | 1/1|3895.54
|
||||
| 2025-01-19 22:00 |🟥Sell 4080 | BTC | B30 |103684.44| 1 |69.7/168.86| 0.02 | 101659.8 | 0.02 | 101659 | 17302 | /1| -
|
||||
| 2025-01-23 18:00 |🟩Buy 5520 | BTC | bull |105927.78| 3965 | 0/0| - | 105927.78 | - | 105927 | 17302 | 1/1|3965.24
|
||||
| 2025-01-23 20:00 |🟥Sell 120 | BTC | sma60 |103770.04| - | -88.61/0| -0.02 | 105927.78 | -0.02 | 105927 | 17302 | /1| -
|
||||
| 2025-01-31 17:00 |🟩Buy 11340 | BTC | bull |105081.86| 3877 | 0/0| - | 105081.87 | - | 105927 | 17302 | 1/1|3876.63
|
||||
| 2025-01-31 19:00 |🟥Sell 120 | BTC | sma60 |102627.29| - | -98.21/0| -0.023 | 105081.87 | -0.023 | 105927 | 17302 | /1| -
|
||||
| Date | Action |Pair | Trade Type | Rate | Dispo | Profit | Pct | max_touch | last_lost | last_max| last_max| Buys| Stake | rsi|
|
||||
+------------------+------------+-----+--------------------+---------+--------+------------+--------+-------------+--------------+------------------+-----+-------++------+-------+-----+-----+-----+-----+-----+-----+
|
||||
| 2025-04-14 04:00 |🟩Buy 104220 | BTC | bull | 84566.04| 3778 | 0/0| - | 84566.03 | - | 105927 | 17302 | 1/1|3778.41
|
||||
| 2025-06-05 20:00 |🟥Sell 75840 | BTC | B30 |101914.77| - |766.81/1207.18| 0.205 | 84566.03 | 0.205 | 105927 | 17302 | /1| -
|
||||
| 2025-06-08 17:00 |🟩Buy 4140 | BTC | bull | 106190.0| 4545 | 0/0| - | 106189.99 | - | 106189 | 17302 | 1/1|4545.22
|
||||
| 2025-06-11 18:00 |🟥Sell 4380 | BTC | B30 |108984.72| - |110.4/165.55| 0.026 | 106189.99 | 0.026 | 106189 | 17302 | /1| -
|
||||
| 2025-06-24 00:00 |🟩Buy 17640 | BTC | bull |105333.94| 4656 | 0/0| - | 105333.93 | - | 106189 | 17302 | 1/1|4655.63
|
||||
| 2025-06-26 14:00 |🟥Sell 3720 | BTC | B30 |106960.01| 1 |62.47/105.0| 0.015 | 105333.93 | 0.015 | 106189 | 17302 | /1| -
|
||||
| 2025-07-09 14:00 |🟩Buy 18720 | BTC | bull |109183.99| 4718 | 0/0| - | 109184.0 | - | 109184 | 17302 | 1/1| 4718.1
|
||||
| 2025-07-15 03:00 |🟥Sell 7980 | BTC | B30 |118251.05| - |381.96/575.56| 0.083 | 109184.0 | 0.083 | 109184 | 17302 | /1| -
|
||||
| 2025-07-23 00:00 |🟩Buy 11340 | BTC | bull |119954.43| 5100 | 0/0| - | 119954.42 | - | 119954 | 17302 | 1/1|5100.06
|
||||
| 2025-07-23 14:00 |🟥Sell 840 | BTC | sma60 |117381.44| 1 | -119.47/0| -0.021 | 119954.42 | -0.021 | 119954 | 17302 | /1| -
|
||||
| Date | Action |Pair | Trade Type | Rate | Dispo | Profit | Pct | max_touch | last_lost | last_max| last_max| Buys| Stake | rsi|
|
||||
+------------------+------------+-----+--------------------+---------+--------+------------+--------+-------------+--------------+------------------+-----+-------++------+-------+-----+-----+-----+-----+-----+-----+
|
||||
| 2025-07-24 02:00 |🟩Buy 720 | BTC | bull | 119094.4| 4981 | 0/0| - | 119094.4 | - | 119954 | 17302 | 1/1| 4980.6
|
||||
| 2025-07-25 03:00 |🟥Sell 1500 | BTC | sma60 |116353.67| - | -124.46/0| -0.023 | 119094.4 | -0.023 | 119954 | 17302 | /1| -
|
||||
| 2025-08-09 11:00 |🟩Buy 22080 | BTC | bull |117424.16| 4856 | 0/0| - | 117424.16 | - | 119954 | 17302 | 1/1|4856.13
|
||||
| 2025-08-11 18:00 |🟥Sell 3300 | BTC | B30 | 119500.0| 1 |76.04/191.73| 0.018 | 117424.16 | 0.018 | 119954 | 17302 | /1| -
|
||||
| 2025-08-12 17:00 |🟩Buy 1380 | BTC | bull |119647.69| 4932 | 0/0| - | 119647.7 | - | 119954 | 17302 | 1/1|4932.17
|
||||
| 2025-08-14 11:00 |🟥Sell 2520 | BTC | B30 | 120933.0| - |43.06/163.09| 0.011 | 119647.7 | 0.011 | 119954 | 17302 | /1| -
|
||||
| 2025-09-02 03:00 |🟩Buy 26880 | BTC | bull | 110246.0| 4975 | 0/0| - | 110246.01 | - | 119954 | 17302 | 1/1|4975.23
|
||||
| 2025-09-04 04:00 |🟥Sell 2940 | BTC | B30 |111148.97| 1 |30.75/83.2| 0.008 | 110246.01 | 0.008 | 119954 | 17302 | /1| -
|
||||
| 2025-09-05 00:00 |🟩Buy 1200 | BTC | bull |110730.87| 5006 | 0/0| - | 110730.87 | - | 119954 | 17302 | 1/1|5005.99
|
||||
| 2025-09-09 01:00 |🟥Sell 5820 | BTC | B30 |111650.03| 1 |31.49/102.15| 0.008 | 110730.87 | 0.008 | 119954 | 17302 | /1| -
|
||||
| Date | Action |Pair | Trade Type | Rate | Dispo | Profit | Pct | max_touch | last_lost | last_max| last_max| Buys| Stake | rsi|
|
||||
+------------------+------------+-----+--------------------+---------+--------+------------+--------+-------------+--------------+------------------+-----+-------++------+-------+-----+-----+-----+-----+-----+-----+
|
||||
| 2025-09-09 09:00 |🟩Buy 480 | BTC | bull |112992.69| 5037 | 0/0| - | 112992.69 | - | 119954 | 17302 | 1/1|5037.48
|
||||
| 2025-09-09 16:00 |🟥Sell 420 | BTC | sma60 |110880.76| - | -104.13/0| -0.019 | 112992.69 | -0.019 | 119954 | 17302 | /1| -
|
||||
| 2025-09-10 09:00 |🟩Buy 1020 | BTC | bull |112370.07| 4933 | 0/0| - | 112370.08 | - | 119954 | 17302 | 1/1|4933.35
|
||||
| 2025-09-14 16:00 |🟥Sell 6180 | BTC | B30 |115224.01| - |115.3/177.07| 0.025 | 112370.08 | 0.025 | 119954 | 17302 | /1| -
|
||||
| 2025-09-18 01:00 |🟩Buy 4860 | BTC | bull |116350.65| 5049 | 0/0| - | 116350.65 | - | 119954 | 17302 | 1/1|5048.65
|
||||
| 2025-09-22 03:00 |🟥Sell 5880 | BTC | sma60 |114187.81| - |-103.85/53.72| -0.019 | 116350.65 | -0.019 | 119954 | 17302 | /1| -
|
||||
| 2025-10-01 01:00 |🟩Buy 12840 | BTC | bull |114239.53| 4945 | 0/0| - | 114239.53 | - | 119954 | 17302 | 1/1| 4944.8
|
||||
| 2025-10-07 16:00 |🟥Sell 9540 | BTC | B30 |121846.01| 1 |318.99/499.08| 0.067 | 114239.53 | 0.067 | 119954 | 17302 | /1| -
|
||||
2026-02-28 17:34:59,918 - freqtrade.misc - INFO - dumping json to
|
||||
"/freqtrade/user_data/backtest_results/backtest-result-2026-02-28_17-34-59.meta.json"
|
||||
Result for strategy Empty
|
||||
BACKTESTING REPORT
|
||||
┏━━━━━━━━━━┳━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━┓
|
||||
┃ Pair ┃ Trades ┃ Avg Profit % ┃ Tot Profit USDT ┃ Tot Profit % ┃ Avg Duration ┃ Win Draw Loss Win% ┃
|
||||
┡━━━━━━━━━━╇━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━┩
|
||||
│ BTC/USDT │ 59 │ 3.3 │ 4263.790 │ 426.38 │ 6 days, 23:28:00 │ 33 0 26 55.9 │
|
||||
│ TOTAL │ 59 │ 3.3 │ 4263.790 │ 426.38 │ 6 days, 23:28:00 │ 33 0 26 55.9 │
|
||||
└──────────┴────────┴──────────────┴─────────────────┴──────────────┴──────────────────┴────────────────────────┘
|
||||
LEFT OPEN TRADES REPORT
|
||||
┏━━━━━━━┳━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━┓
|
||||
┃ Pair ┃ Trades ┃ Avg Profit % ┃ Tot Profit USDT ┃ Tot Profit % ┃ Avg Duration ┃ Win Draw Loss Win% ┃
|
||||
┡━━━━━━━╇━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━┩
|
||||
│ TOTAL │ 0 │ 0.0 │ 0.000 │ 0.0 │ 0:00 │ 0 0 0 0 │
|
||||
└───────┴────────┴──────────────┴─────────────────┴──────────────┴──────────────┴────────────────────────┘
|
||||
ENTER TAG STATS
|
||||
┏━━━━━━━━━━━┳━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━┓
|
||||
┃ Enter Tag ┃ Entries ┃ Avg Profit % ┃ Tot Profit USDT ┃ Tot Profit % ┃ Avg Duration ┃ Win Draw Loss Win% ┃
|
||||
┡━━━━━━━━━━━╇━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━┩
|
||||
│ bull │ 59 │ 3.3 │ 4263.790 │ 426.38 │ 6 days, 23:28:00 │ 33 0 26 55.9 │
|
||||
│ TOTAL │ 59 │ 3.3 │ 4263.790 │ 426.38 │ 6 days, 23:28:00 │ 33 0 26 55.9 │
|
||||
└───────────┴─────────┴──────────────┴─────────────────┴──────────────┴──────────────────┴────────────────────────┘
|
||||
EXIT REASON STATS
|
||||
┏━━━━━━━━━━━━━┳━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━┓
|
||||
┃ Exit Reason ┃ Exits ┃ Avg Profit % ┃ Tot Profit USDT ┃ Tot Profit % ┃ Avg Duration ┃ Win Draw Loss Win% ┃
|
||||
┡━━━━━━━━━━━━━╇━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━┩
|
||||
│ B30 │ 33 │ 8.0 │ 6194.610 │ 619.46 │ 11 days, 5:36:00 │ 33 0 0 100 │
|
||||
│ sma60 │ 26 │ -2.67 │ -1930.820 │ -193.08 │ 1 day, 13:51:00 │ 0 0 26 0 │
|
||||
│ TOTAL │ 59 │ 3.3 │ 4263.790 │ 426.38 │ 6 days, 23:28:00 │ 33 0 26 55.9 │
|
||||
└─────────────┴───────┴──────────────┴─────────────────┴──────────────┴──────────────────┴────────────────────────┘
|
||||
MIXED TAG STATS
|
||||
┏━━━━━━━━━━━┳━━━━━━━━━━━━━┳━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━┓
|
||||
┃ Enter Tag ┃ Exit Reason ┃ Trades ┃ Avg Profit % ┃ Tot Profit USDT ┃ Tot Profit % ┃ Avg Duration ┃ Win Draw Loss Win% ┃
|
||||
┡━━━━━━━━━━━╇━━━━━━━━━━━━━╇━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━┩
|
||||
│ bull │ B30 │ 33 │ 8.0 │ 6194.610 │ 619.46 │ 11 days, 5:36:00 │ 33 0 0 100 │
|
||||
│ bull │ sma60 │ 26 │ -2.67 │ -1930.820 │ -193.08 │ 1 day, 13:51:00 │ 0 0 26 0 │
|
||||
│ TOTAL │ │ 59 │ 3.3 │ 4263.790 │ 426.38 │ 6 days, 23:28:00 │ 33 0 26 55.9 │
|
||||
└───────────┴─────────────┴────────┴──────────────┴─────────────────┴──────────────┴──────────────────┴────────────────────────┘
|
||||
MONTH BREAKDOWN
|
||||
┏━━━━━━━━━━━━┳━━━━━━━━┳━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━┓
|
||||
┃ Month ┃ Trades ┃ Tot Profit USDT ┃ Profit Factor ┃ Win Draw Loss Win% ┃
|
||||
┡━━━━━━━━━━━━╇━━━━━━━━╇━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━┩
|
||||
│ 28/02/2023 │ 3 │ 372.897 │ 0.0 │ 3 0 0 100 │
|
||||
│ 31/03/2023 │ 3 │ -29.085 │ 0.79 │ 1 0 2 33.3 │
|
||||
│ 30/04/2023 │ 3 │ 11.898 │ 1.4 │ 2 0 1 66.7 │
|
||||
│ 31/05/2023 │ 2 │ -79.919 │ 0.0 │ 0 0 2 0 │
|
||||
│ 30/06/2023 │ 0 │ 0 │ 0.0 │ 0 0 0 0 │
|
||||
│ 31/07/2023 │ 2 │ 109.847 │ 3.35 │ 1 0 1 50.0 │
|
||||
│ 31/08/2023 │ 0 │ 0 │ 0.0 │ 0 0 0 0 │
|
||||
│ 30/09/2023 │ 1 │ -29.039 │ 0.0 │ 0 0 1 0 │
|
||||
│ 31/10/2023 │ 2 │ 70.87 │ 0.0 │ 2 0 0 100 │
|
||||
│ 30/11/2023 │ 0 │ 0 │ 0.0 │ 0 0 0 0 │
|
||||
│ 31/12/2023 │ 0 │ 0 │ 0.0 │ 0 0 0 0 │
|
||||
│ 31/01/2024 │ 2 │ 697.801 │ 0.0 │ 2 0 0 100 │
|
||||
│ 29/02/2024 │ 0 │ 0 │ 0.0 │ 0 0 0 0 │
|
||||
│ 31/03/2024 │ 2 │ 1080.605 │ 0.0 │ 2 0 0 100 │
|
||||
│ 30/04/2024 │ 4 │ -314.088 │ 0.0 │ 0 0 4 0 │
|
||||
│ 31/05/2024 │ 4 │ -182.279 │ 0.09 │ 1 0 3 25.0 │
|
||||
│ 30/06/2024 │ 1 │ -67.429 │ 0.0 │ 0 0 1 0 │
|
||||
│ 31/07/2024 │ 3 │ 111.09 │ 2.87 │ 2 0 1 66.7 │
|
||||
│ 31/08/2024 │ 1 │ -62.063 │ 0.0 │ 0 0 1 0 │
|
||||
│ 30/09/2024 │ 3 │ -88.603 │ 0.28 │ 1 0 2 33.3 │
|
||||
│ 31/10/2024 │ 2 │ 263.26 │ 0.0 │ 2 0 0 100 │
|
||||
│ 30/11/2024 │ 0 │ 0 │ 0.0 │ 0 0 0 0 │
|
||||
│ 31/12/2024 │ 2 │ 830.987 │ 6.74 │ 1 0 1 50.0 │
|
||||
│ 31/01/2025 │ 5 │ 81.667 │ 1.44 │ 3 0 2 60.0 │
|
||||
│ 28/02/2025 │ 0 │ 0 │ 0.0 │ 0 0 0 0 │
|
||||
│ 31/03/2025 │ 0 │ 0 │ 0.0 │ 0 0 0 0 │
|
||||
│ 30/04/2025 │ 0 │ 0 │ 0.0 │ 0 0 0 0 │
|
||||
│ 31/05/2025 │ 0 │ 0 │ 0.0 │ 0 0 0 0 │
|
||||
│ 30/06/2025 │ 3 │ 939.688 │ 0.0 │ 3 0 0 100 │
|
||||
│ 31/07/2025 │ 3 │ 138.029 │ 1.57 │ 1 0 2 33.3 │
|
||||
│ 31/08/2025 │ 2 │ 119.103 │ 0.0 │ 2 0 0 100 │
|
||||
│ 30/09/2025 │ 5 │ -30.436 │ 0.85 │ 3 0 2 60.0 │
|
||||
│ 31/10/2025 │ 1 │ 318.991 │ 0.0 │ 1 0 0 100 │
|
||||
└────────────┴────────┴─────────────────┴───────────────┴────────────────────────┘
|
||||
SUMMARY METRICS
|
||||
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
|
||||
┃ Metric ┃ Value ┃
|
||||
┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┩
|
||||
│ Backtesting from │ 2023-01-01 00:00:00 │
|
||||
│ Backtesting to │ 2025-10-11 00:00:00 │
|
||||
│ Trading Mode │ Spot │
|
||||
│ Max open trades │ 1 │
|
||||
│ │ │
|
||||
│ Total/Daily Avg Trades │ 59 / 0.06 │
|
||||
│ Starting balance │ 1000 USDT │
|
||||
│ Final balance │ 5263.79 USDT │
|
||||
│ Absolute profit │ 4263.79 USDT │
|
||||
│ Total profit % │ 426.38% │
|
||||
│ CAGR % │ 81.82% │
|
||||
│ Sortino │ 2.82 │
|
||||
│ Sharpe │ 0.35 │
|
||||
│ Calmar │ 42.68 │
|
||||
│ SQN │ 2.37 │
|
||||
│ Profit factor │ 3.21 │
|
||||
│ Expectancy (Ratio) │ 72.27 (0.97) │
|
||||
│ Avg. daily profit │ 4.205 USDT │
|
||||
│ Avg. stake amount │ 2946.519 USDT │
|
||||
│ Total trade volume │ 352657.589 USDT │
|
||||
│ │ │
|
||||
│ Best Pair │ BTC/USDT 426.38% │
|
||||
│ Worst Pair │ BTC/USDT 426.38% │
|
||||
│ Best trade │ BTC/USDT 46.39% │
|
||||
│ Worst trade │ BTC/USDT -5.76% │
|
||||
│ Best day │ 975.709 USDT │
|
||||
│ Worst day │ -144.722 USDT │
|
||||
│ Days win/draw/lose │ 32 / 914 / 26 │
|
||||
│ Min/Max/Avg. Duration Winners │ 1d 09:00 / 87d 12:00 / 11d 05:36 │
|
||||
│ Min/Max/Avg. Duration Losers │ 0d 02:00 / 5d 05:00 / 1d 13:51 │
|
||||
│ Max Consecutive Wins / Loss │ 6 / 6 │
|
||||
│ Rejected Entry signals │ 0 │
|
||||
│ Entry/Exit Timeouts │ 0 / 0 │
|
||||
│ │ │
|
||||
│ Min balance │ 1260.898 USDT │
|
||||
│ Max balance │ 5263.79 USDT │
|
||||
│ Max % of account underwater │ 18.82% │
|
||||
│ Absolute drawdown │ 603.373 USDT (18.82%) │
|
||||
│ Drawdown duration │ 186 days 10:00:00 │
|
||||
│ Profit at drawdown start │ 2205.874 USDT │
|
||||
│ Profit at drawdown end │ 1602.501 USDT │
|
||||
│ Drawdown start │ 2024-03-27 16:00:00 │
|
||||
│ Drawdown end │ 2024-09-30 02:00:00 │
|
||||
│ Market change │ 580.68% │
|
||||
└───────────────────────────────┴──────────────────────────────────┘
|
||||
|
||||
Backtested 2023-01-01 00:00:00 -> 2025-10-11 00:00:00 | Max open trades : 1
|
||||
STRATEGY SUMMARY
|
||||
┏━━━━━━━━━━┳━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━┓
|
||||
┃ Strategy ┃ Trades ┃ Avg Profit % ┃ Tot Profit USDT ┃ Tot Profit % ┃ Avg Duration ┃ Win Draw Loss Win% ┃ Drawdown ┃
|
||||
┡━━━━━━━━━━╇━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━┩
|
||||
│ Empty │ 59 │ 3.30 │ 4263.790 │ 426.38 │ 6 days, 23:28:00 │ 33 0 26 │ 603.373 USDT 18.82% │
|
||||
│ │ │ │ │ │ │ 55.9 │ │
|
||||
└──────────┴────────┴──────────────┴─────────────────┴──────────────┴──────────────────┴───────────────────────┴──────────────────────┘
|
||||
946
Frictrade.py
Normal file
946
Frictrade.py
Normal file
@@ -0,0 +1,946 @@
|
||||
# Zeus Strategy: First Generation of GodStra Strategy with maximum
|
||||
# AVG/MID profit in USDT
|
||||
# Author: @Mablue (Masoud Azizi)
|
||||
# github: https://github.com/mablue/
|
||||
# IMPORTANT: INSTALL TA BEFOUR RUN(pip install ta)
|
||||
# freqtrade hyperopt --hyperopt-loss SharpeHyperOptLoss --spaces buy sell roi --strategy Zeus
|
||||
# --- Do not remove these libs ---
|
||||
from datetime import timedelta, datetime
|
||||
from freqtrade.persistence import Trade
|
||||
from freqtrade.strategy import (BooleanParameter, CategoricalParameter, DecimalParameter, stoploss_from_open,
|
||||
IntParameter, IStrategy, merge_informative_pair, informative, stoploss_from_absolute)
|
||||
import pandas as pd
|
||||
import numpy as np
|
||||
import os
|
||||
import json
|
||||
import csv
|
||||
from pandas import DataFrame
|
||||
from typing import Optional, Union, Tuple
|
||||
import math
|
||||
import logging
|
||||
from pathlib import Path
|
||||
|
||||
# --------------------------------
|
||||
|
||||
# Add your lib to import here test git
|
||||
import ta
|
||||
import talib.abstract as talib
|
||||
import freqtrade.vendor.qtpylib.indicators as qtpylib
|
||||
from datetime import timezone, timedelta
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
# Couleurs ANSI de base
|
||||
RED = "\033[31m"
|
||||
GREEN = "\033[32m"
|
||||
YELLOW = "\033[33m"
|
||||
BLUE = "\033[34m"
|
||||
MAGENTA = "\033[35m"
|
||||
CYAN = "\033[36m"
|
||||
RESET = "\033[0m"
|
||||
|
||||
|
||||
class Frictrade(IStrategy):
|
||||
startup_candle_count = 180
|
||||
|
||||
# ROI table:
|
||||
minimal_roi = {
|
||||
"0": 10
|
||||
}
|
||||
|
||||
# Stoploss:
|
||||
stoploss = -1 # 0.256
|
||||
# Custom stoploss
|
||||
use_custom_stoploss = False
|
||||
|
||||
trailing_stop = False
|
||||
trailing_stop_positive = 0.15
|
||||
trailing_stop_positive_offset = 0.5
|
||||
trailing_only_offset_is_reached = True
|
||||
|
||||
# Buy hypers
|
||||
timeframe = '1m'
|
||||
max_open_trades = 5
|
||||
max_amount = 40
|
||||
|
||||
parameters = {}
|
||||
# DCA config
|
||||
position_adjustment_enable = True
|
||||
|
||||
columns_logged = False
|
||||
pairs = {
|
||||
pair: {
|
||||
"first_buy": 0,
|
||||
"last_buy": 0.0,
|
||||
"last_min": 999999999999999.5,
|
||||
"last_max": 0,
|
||||
"trade_info": {},
|
||||
"max_touch": 0.0,
|
||||
"last_sell": 0.0,
|
||||
'count_of_buys': 0,
|
||||
'current_profit': 0,
|
||||
'expected_profit': 0,
|
||||
'previous_profit': 0,
|
||||
"last_candle": {},
|
||||
"last_count_of_buys": 0,
|
||||
'base_stake_amount': 0,
|
||||
'stop_buy': False,
|
||||
'last_date': 0,
|
||||
'stop': False,
|
||||
'max_profit': 0,
|
||||
'first_amount': 0,
|
||||
'total_amount': 0,
|
||||
'has_gain': 0,
|
||||
'force_sell': False,
|
||||
'force_buy': False
|
||||
}
|
||||
for pair in ["BTC/USDC", "ETH/USDC", "DOGE/USDC", "XRP/USDC", "SOL/USDC",
|
||||
"BTC/USDT", "ETH/USDT", "DOGE/USDT", "XRP/USDT", "SOL/USDT"]
|
||||
}
|
||||
trades = list()
|
||||
max_profit_pairs = {}
|
||||
|
||||
btc_ath_history = [
|
||||
{"date": "2011-06-09", "price_usd": 26.15, "note": "pic 2011 (early breakout)"},
|
||||
{"date": "2013-11-29", "price_usd": 1132.00, "note": "bull run fin 2013"},
|
||||
{"date": "2017-12-17", "price_usd": 19783.00, "note": "ATH décembre 2017 (crypto bubble)"},
|
||||
{"date": "2020-12-31", "price_usd": 29001.72, "note": "fin 2020, nouveau record après accumulation)"},
|
||||
{"date": "2021-11-10", "price_usd": 68742.00, "note": "record novembre 2021 (institutional demand)"},
|
||||
{"date": "2024-03-05", "price_usd": 69000.00,
|
||||
"note": "nouveau pic début 2024 (source presse, valeur indicative)"},
|
||||
{"date": "2025-07-11", "price_usd": 118755.00, "note": "pic juillet 2025 (valeur rapportée par la presse)"},
|
||||
{"date": "2025-10-06", "price_usd": 126198.07,
|
||||
"note": "pic oct. 2025 (source agrégée, à vérifier selon l'exchange)"}
|
||||
]
|
||||
|
||||
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:
|
||||
|
||||
minutes = 0
|
||||
if self.pairs[pair]['last_date'] != 0:
|
||||
minutes = round(int((current_time - self.pairs[pair]['last_date']).total_seconds() / 60))
|
||||
|
||||
dataframe, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe)
|
||||
last_candle = dataframe.iloc[-1].squeeze()
|
||||
last_candle_2 = dataframe.iloc[-2].squeeze()
|
||||
last_candle_3 = dataframe.iloc[-3].squeeze()
|
||||
|
||||
condition = True #(last_candle[f"{indic_5m}_deriv1"] >= indic_deriv1_5m) and (last_candle[f"{indic_5m}_deriv2"] >= indic_deriv2_5m)
|
||||
|
||||
allow_to_buy = True #(condition and not self.pairs[pair]['stop']) | (entry_tag == 'force_entry')
|
||||
|
||||
if allow_to_buy:
|
||||
self.trades = list()
|
||||
self.pairs[pair]['first_buy'] = rate
|
||||
self.pairs[pair]['last_buy'] = rate
|
||||
self.pairs[pair]['max_touch'] = last_candle['close']
|
||||
self.pairs[pair]['last_candle'] = last_candle
|
||||
self.pairs[pair]['count_of_buys'] = 1
|
||||
self.pairs[pair]['current_profit'] = 0
|
||||
self.pairs[pair]['last_max'] = max(last_candle['close'], self.pairs[pair]['last_max'])
|
||||
self.pairs[pair]['last_min'] = min(last_candle['close'], self.pairs[pair]['last_min'])
|
||||
|
||||
dispo = round(self.wallets.get_available_stake_amount())
|
||||
self.printLineLog()
|
||||
|
||||
stake_amount = self.adjust_stake_amount(pair, last_candle)
|
||||
|
||||
self.pairs[pair]['total_amount'] = stake_amount
|
||||
|
||||
self.log_trade(
|
||||
last_candle=last_candle,
|
||||
date=current_time,
|
||||
action=("🟩Buy" if allow_to_buy else "Canceled") + " " + str(minutes),
|
||||
pair=pair,
|
||||
rate=rate,
|
||||
dispo=dispo,
|
||||
profit=0,
|
||||
trade_type=entry_tag,
|
||||
buys=1,
|
||||
stake=round(stake_amount, 2)
|
||||
)
|
||||
|
||||
return allow_to_buy
|
||||
|
||||
def confirm_trade_exit(self, pair: str, trade: Trade, order_type: str, amount: float, rate: float,
|
||||
time_in_force: str,
|
||||
exit_reason: str, current_time, **kwargs, ) -> bool:
|
||||
|
||||
# allow_to_sell = (minutes > 30)
|
||||
dataframe, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe)
|
||||
last_candle = dataframe.iloc[-1].squeeze()
|
||||
|
||||
minutes = int(round((current_time - trade.open_date_utc).seconds / 60, 0))
|
||||
profit =trade.calc_profit(rate)
|
||||
force = self.pairs[pair]['force_sell']
|
||||
allow_to_sell = minutes > 30 and (last_candle['hapercent'] < 0 ) or force or (exit_reason == 'force_exit') or (exit_reason == 'stop_loss')
|
||||
|
||||
if allow_to_sell:
|
||||
self.trades = list()
|
||||
self.pairs[pair]['last_count_of_buys'] = trade.nr_of_successful_entries # self.pairs[pair]['count_of_buys']
|
||||
self.pairs[pair]['last_sell'] = rate
|
||||
self.pairs[pair]['last_candle'] = last_candle
|
||||
self.pairs[pair]['previous_profit'] = 0
|
||||
self.trades = list()
|
||||
dispo = round(self.wallets.get_available_stake_amount())
|
||||
# print(f"Sell {pair} {current_time} {exit_reason} dispo={dispo} amount={amount} rate={rate} open_rate={trade.open_rate}")
|
||||
self.log_trade(
|
||||
last_candle=last_candle,
|
||||
date=current_time,
|
||||
action="🟥Sell " + str(minutes),
|
||||
pair=pair,
|
||||
trade_type=exit_reason,
|
||||
rate=last_candle['close'],
|
||||
dispo=dispo,
|
||||
profit=round(profit, 2)
|
||||
)
|
||||
self.pairs[pair]['max_profit'] = 0
|
||||
self.pairs[pair]['force_sell'] = False
|
||||
self.pairs[pair]['has_gain'] = 0
|
||||
self.pairs[pair]['current_profit'] = 0
|
||||
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_date'] = current_time
|
||||
self.pairs[pair]['current_trade'] = None
|
||||
# else:
|
||||
# self.printLog(f"{current_time} SELL triggered for {pair} ({exit_reason} profit={profit} minutes={minutes} percent={last_candle['hapercent']}) but condition blocked")
|
||||
return (allow_to_sell) | (exit_reason == 'force_exit') | (exit_reason == 'stop_loss')
|
||||
|
||||
# def custom_exit(self, pair: str, trade: Trade, current_time, current_rate, current_profit, **kwargs):
|
||||
#
|
||||
# dataframe, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe)
|
||||
# last_candle = dataframe.iloc[-1].squeeze()
|
||||
# last_candle_1h = dataframe.iloc[-13].squeeze()
|
||||
# before_last_candle = dataframe.iloc[-2].squeeze()
|
||||
# before_last_candle_2 = dataframe.iloc[-3].squeeze()
|
||||
# before_last_candle_12 = dataframe.iloc[-13].squeeze()
|
||||
#
|
||||
# expected_profit = self.expectedProfit(pair, last_candle)
|
||||
# # print(f"current_time={current_time} current_profit={current_profit} expected_profit={expected_profit}")
|
||||
#
|
||||
# max_touch_before = self.pairs[pair]['max_touch']
|
||||
# self.pairs[pair]['last_max'] = max(last_candle['close'], self.pairs[pair]['last_max'])
|
||||
# self.pairs[pair]['last_min'] = min(last_candle['close'], self.pairs[pair]['last_min'])
|
||||
# self.pairs[pair]['current_trade'] = trade
|
||||
#
|
||||
# count_of_buys = trade.nr_of_successful_entries
|
||||
#
|
||||
# profit = trade.calc_profit(current_rate) #round(current_profit * trade.stake_amount, 1)
|
||||
# self.pairs[pair]['max_profit'] = max(self.pairs[pair]['max_profit'], profit)
|
||||
# max_profit = last_candle['max5'] #self.pairs[pair]['max_profit']
|
||||
# baisse = 0
|
||||
# if profit > 0:
|
||||
# baisse = 1 - (profit / max_profit)
|
||||
# mx = max_profit / 5
|
||||
# self.pairs[pair]['count_of_buys'] = count_of_buys
|
||||
# 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 = (current_time - trade.date_last_filled_utc).total_seconds() / 3600.0
|
||||
# minutes = (current_time - trade.date_last_filled_utc).total_seconds() / 60.0
|
||||
#
|
||||
# if minutes % 4 == 0:
|
||||
# self.log_trade(
|
||||
# last_candle=last_candle,
|
||||
# date=current_time,
|
||||
# action="🟢 CURRENT", #🔴 CURRENT" if self.pairs[pair]['stop'] or last_candle['stop_buying'] else "
|
||||
# dispo=dispo,
|
||||
# pair=pair,
|
||||
# rate=last_candle['close'],
|
||||
# trade_type='',
|
||||
# profit=round(profit, 2),
|
||||
# buys=count_of_buys,
|
||||
# stake=0
|
||||
# )
|
||||
#
|
||||
# if (last_candle['close'] > last_candle['mid']) or (last_candle['sma5_deriv1'] > 0):
|
||||
# return None
|
||||
#
|
||||
# pair_name = self.getShortName(pair)
|
||||
#
|
||||
# if profit > 0.003 * count_of_buys and baisse > 0.30:
|
||||
# self.pairs[pair]['force_sell'] = False
|
||||
# self.pairs[pair]['force_buy'] = (self.pairs[pair]['count_of_buys'] - self.pairs[pair]['has_gain'] > 3)
|
||||
# return str(count_of_buys) + '_' + 'B30_' + pair_name + '_' + str(self.pairs[pair]['has_gain'])
|
||||
#
|
||||
# self.pairs[pair]['max_touch'] = max(last_candle['close'], self.pairs[pair]['max_touch'])
|
||||
|
||||
def getShortName(self, pair):
|
||||
return pair.replace("/USDT", '').replace("/USDC", '').replace("_USDC", '').replace("_USDT", '')
|
||||
|
||||
def getLastLost(self, last_candle, pair):
|
||||
last_lost = round((last_candle['close'] - self.pairs[pair]['max_touch']) / self.pairs[pair]['max_touch'], 3)
|
||||
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)
|
||||
|
||||
def getPctLastBuy(self, pair, last_candle):
|
||||
return round((last_candle['close'] - self.pairs[pair]['last_buy']) / self.pairs[pair]['last_buy'], 4)
|
||||
|
||||
def expectedProfit(self, pair: str, last_candle: DataFrame):
|
||||
lim = 0.01
|
||||
pct = 0.002
|
||||
if (self.getShortName(pair) == 'BTC'):
|
||||
lim = 0.005
|
||||
pct = 0.001
|
||||
pct_to_max = lim + pct * self.pairs[pair]['count_of_buys']
|
||||
expected_profit = lim * self.pairs[pair]['total_amount'] # min(3 * lim, max(lim, pct_to_max)) # 0.004 + 0.002 * self.pairs[pair]['count_of_buys'] #min(0.01, first_max)
|
||||
|
||||
self.pairs[pair]['expected_profit'] = expected_profit
|
||||
|
||||
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
|
||||
if self.config.get('runmode') == 'hyperopt' or self.dp.runmode.value in ('hyperopt'):
|
||||
return
|
||||
if self.columns_logged % 10 == 0:
|
||||
self.printLog(
|
||||
f"| {'Date':<16} | {'Action':<10} |{'Pair':<5}| {'Trade Type':<18} |{'Rate':>8} | {'Dispo':>6} | {'Profit':>8} "
|
||||
f"| {'Pct':>6} | {'max_touch':>11} | {'last_lost':>12} | {'last_max':>7}| {'last_min':>7}|{'Buys':>5}| {'Stake':>5} |"
|
||||
f"{'rsi':>6}" #|Distmax|s201d|s5_1d|s5_2d|s51h|s52h|smt1h|smt2h|tdc1d|tdc1h"
|
||||
)
|
||||
self.printLineLog()
|
||||
df = pd.DataFrame.from_dict(self.pairs, orient='index')
|
||||
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']
|
||||
|
||||
self.printLog(df_filtered)
|
||||
|
||||
self.columns_logged += 1
|
||||
date = str(date)[:16] if date else "-"
|
||||
limit = None
|
||||
rsi = ''
|
||||
rsi_pct = ''
|
||||
sma5_1d = ''
|
||||
sma5_1h = ''
|
||||
|
||||
sma5 = str(sma5_1d) + ' ' + str(sma5_1h)
|
||||
|
||||
last_lost = self.getLastLost(last_candle, pair)
|
||||
|
||||
if buys is None:
|
||||
buys = ''
|
||||
|
||||
max_touch = ''
|
||||
pct_max = self.getPctFirstBuy(pair, last_candle)
|
||||
|
||||
total_counts = str(buys) + '/' + str(sum(pair_data['count_of_buys'] for pair_data in self.pairs.values()))
|
||||
|
||||
dist_max = ''
|
||||
|
||||
last_max = int(self.pairs[pair]['last_max']) if self.pairs[pair]['last_max'] > 1 else round(
|
||||
self.pairs[pair]['last_max'], 3)
|
||||
last_min = int(self.pairs[pair]['last_min']) if self.pairs[pair]['last_min'] > 1 else round(
|
||||
self.pairs[pair]['last_min'], 3)
|
||||
|
||||
color = GREEN if profit > 0 else RED
|
||||
|
||||
profit = str(profit) + '/' + str(round(self.pairs[pair]['max_profit'], 2))
|
||||
|
||||
# 🟢 Dérivée 1 > 0 et dérivée 2 > 0: tendance haussière qui s’accélère.
|
||||
# 🟡 Dérivée 1 > 0 et dérivée 2 < 0: tendance haussière qui ralentit → essoufflement potentiel.
|
||||
# 🔴 Dérivée 1 < 0 et dérivée 2 < 0: tendance baissière qui s’accélère.
|
||||
# 🟠 Dérivée 1 < 0 et dérivée 2 > 0: tendance baissière qui ralentit → possible bottom.
|
||||
self.printLog(
|
||||
f"| {date:<16} |{action:<10} | {pair[0:3]:<3} | {trade_type or '-':<18} |{rate or '-':>9}| {dispo or '-':>6} "
|
||||
f"|{color}{profit or '-':>10}{RESET}| {pct_max or '-':>6} | {round(self.pairs[pair]['max_touch'], 2) or '-':>11} | {last_lost or '-':>12} "
|
||||
f"| {last_max or '-':>7} | {last_min or '-':>7} |{total_counts or '-':>5}|{stake or '-':>7}"
|
||||
f"{round(last_candle['max_rsi_24'], 1) or '-' :>6}|{round(last_candle['rsi_1h'], 1) or '-' :>6}|{round(last_candle['rsi_1d'], 1) or '-' :>6}|"
|
||||
f"{round(last_candle['rtp_1h'] * 100, 0) or '-' :>6}|{round(last_candle['rtp_1d'] * 100, 0) or '-' :>6}|"
|
||||
|
||||
)
|
||||
|
||||
def printLineLog(self):
|
||||
# f"sum1h|sum1d|Tdc|Tdh|Tdd| drv1 |drv|drv_1d|"
|
||||
self.printLog(
|
||||
f"+{'-' * 18}+{'-' * 12}+{'-' * 5}+{'-' * 20}+{'-' * 9}+{'-' * 8}+{'-' * 12}+{'-' * 8}+{'-' * 13}+{'-' * 14}+{'-' * 9}{'-' * 9}+{'-' * 5}+{'-' * 7}+"
|
||||
f"+{'-' * 6}+{'-' * 7}+{'-' * 5}+{'-' * 5}+{'-' * 5}+{'-' * 5}+{'-' * 5}+{'-' * 5}+"
|
||||
)
|
||||
|
||||
def printLog(self, str):
|
||||
if self.config.get('runmode') == 'hyperopt' or self.dp.runmode.value in ('hyperopt'):
|
||||
return;
|
||||
if not self.dp.runmode.value in ('backtest', 'hyperopt', 'lookahead-analysis'):
|
||||
logger.info(str)
|
||||
else:
|
||||
if not self.dp.runmode.value in ('hyperopt'):
|
||||
print(str)
|
||||
|
||||
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
||||
# Add all ta features
|
||||
pair = metadata['pair']
|
||||
short_pair = self.getShortName(pair)
|
||||
self.path = f"user_data/plots/{short_pair}/" + ("valide/" if not self.dp.runmode.value in ('backtest') else '')
|
||||
|
||||
heikinashi = qtpylib.heikinashi(dataframe)
|
||||
dataframe['haopen'] = heikinashi['open']
|
||||
dataframe['haclose'] = heikinashi['close']
|
||||
dataframe['hapercent'] = (dataframe['haclose'] - dataframe['haopen']) / dataframe['haclose']
|
||||
|
||||
dataframe['mid'] = dataframe['open'] + (dataframe['close'] - dataframe['open']) / 2
|
||||
dataframe['sma5'] = dataframe['mid'].ewm(span=5, adjust=False).mean() #dataframe["mid"].rolling(window=5).mean()
|
||||
dataframe['sma5_deriv1'] = 1000 * (dataframe['sma5'] - dataframe['sma5'].shift(1)) / dataframe['sma5'].shift(1)
|
||||
|
||||
dataframe['sma24'] = dataframe['mid'].ewm(span=24, adjust=False).mean()
|
||||
dataframe['sma24_deriv1'] = 1000 * (dataframe['sma24'] - dataframe['sma24'].shift(1)) / dataframe['sma24'].shift(1)
|
||||
|
||||
dataframe['sma60'] = dataframe['mid'].ewm(span=60, adjust=False).mean()
|
||||
dataframe['sma60_deriv1'] = 1000 * (dataframe['sma60'] - dataframe['sma60'].shift(1)) / dataframe['sma60'].shift(1)
|
||||
|
||||
# dataframe[f"sma5_inv"] = (dataframe[f"sma5"].shift(2) >= dataframe[f"sma5"].shift(1)) \
|
||||
# & (dataframe[f"sma5"].shift(1) <= dataframe[f"sma5"])
|
||||
|
||||
dataframe["sma5_sqrt"] = (
|
||||
np.sqrt(np.abs(dataframe["sma5"] - dataframe["sma5"].shift(1)))
|
||||
+ np.sqrt(np.abs(dataframe["sma5"].shift(3) - dataframe["sma5"].shift(1)))
|
||||
)
|
||||
dataframe["sma5_inv"] = (
|
||||
(dataframe["sma5"].shift(2) >= dataframe["sma5"].shift(1))
|
||||
& (dataframe["sma5"].shift(1) <= dataframe["sma5"])
|
||||
& (dataframe["sma5_sqrt"] > 5)
|
||||
)
|
||||
|
||||
dataframe["percent"] = dataframe['mid'].pct_change()
|
||||
dataframe["percent3"] = dataframe['mid'].pct_change(3).rolling(3).mean()
|
||||
dataframe["percent12"] = dataframe['mid'].pct_change(12).rolling(12).mean()
|
||||
dataframe["percent24"] = dataframe['mid'].pct_change(24).rolling(24).mean()
|
||||
|
||||
dataframe['rsi'] = talib.RSI(dataframe['mid'], timeperiod=14)
|
||||
dataframe['max_rsi_12'] = talib.MAX(dataframe['rsi'], timeperiod=12)
|
||||
dataframe['max_rsi_24'] = talib.MAX(dataframe['rsi'], timeperiod=24)
|
||||
dataframe['max5'] = talib.MAX(dataframe['mid'], timeperiod=5)
|
||||
dataframe['min180'] = talib.MIN(dataframe['mid'], timeperiod=180)
|
||||
dataframe['max180'] = talib.MAX(dataframe['mid'], timeperiod=180)
|
||||
dataframe['pct180'] = ((dataframe["mid"] - dataframe['min180'] ) / (dataframe['max180'] - dataframe['min180'] ))
|
||||
|
||||
dataframe = self.rsi_trend_probability(dataframe, short=60, long=360)
|
||||
|
||||
# ################### INFORMATIVE 1h
|
||||
informative = self.dp.get_pair_dataframe(pair=metadata['pair'], timeframe='1h')
|
||||
informative['mid'] = informative['open'] + (informative['close'] - informative['open']) / 2
|
||||
# informative = self.populate1hIndicators(df=informative, metadata=metadata)
|
||||
informative['rsi'] = talib.RSI(informative['mid'], timeperiod=14)
|
||||
informative = self.rsi_trend_probability(informative)
|
||||
# informative = self.calculateRegression(informative, 'mid', lookback=15)
|
||||
dataframe = merge_informative_pair(dataframe, informative, '1m', '1h', ffill=True)
|
||||
|
||||
# ################### INFORMATIVE 1d
|
||||
informative = self.dp.get_pair_dataframe(pair=metadata['pair'], timeframe='1d')
|
||||
informative['mid'] = informative['open'] + (informative['close'] - informative['open']) / 2
|
||||
informative['rsi'] = talib.RSI(informative['mid'], timeperiod=5)
|
||||
informative = self.rsi_trend_probability(informative)
|
||||
# informative = self.calculateRegression(informative, 'mid', lookback=15)
|
||||
dataframe = merge_informative_pair(dataframe, informative, '1m', '1d', ffill=True)
|
||||
|
||||
dataframe['last_price'] = dataframe['close']
|
||||
dataframe['first_price'] = dataframe['close']
|
||||
if self.dp:
|
||||
if self.dp.runmode.value in ('live', 'dry_run'):
|
||||
self.getOpenTrades()
|
||||
|
||||
for trade in self.trades:
|
||||
if trade.pair != pair:
|
||||
continue
|
||||
filled_buys = trade.select_filled_orders('buy')
|
||||
count = 0
|
||||
amount = 0
|
||||
for buy in filled_buys:
|
||||
if count == 0:
|
||||
dataframe['first_price'] = buy.price
|
||||
self.pairs[pair]['first_buy'] = 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
|
||||
count = count + 1
|
||||
amount += buy.price * buy.filled
|
||||
count_buys = count
|
||||
self.pairs[pair]['total_amount'] = amount
|
||||
|
||||
dataframe['absolute_min'] = dataframe['mid'].rolling(1440, min_periods=1).min()
|
||||
dataframe['absolute_max'] = dataframe['mid'].rolling(1440, min_periods=1).max()
|
||||
# steps = (dataframe['absolute_max'] - dataframe['absolute_min']) / (dataframe['absolute_min'] * 0.01)
|
||||
# levels = [dataframe['absolute_min'] * (1 + i / 100) for i in range(1, steps + 1)]
|
||||
#
|
||||
# print(levels)
|
||||
|
||||
# print(f"min={dataframe['absolute_min'].min()} max={dataframe['absolute_max'].max()}")
|
||||
for i in [0, 1, 2, 3]:
|
||||
dataframe[f"lvl_{i}_pct"] = dataframe['absolute_min'] * (1 + 0.01 * i)
|
||||
|
||||
#
|
||||
# absolute_min = dataframe['absolute_min'].min()
|
||||
# absolute_max = dataframe['absolute_max'].max()
|
||||
#
|
||||
# # Écart total
|
||||
# diff = absolute_max - absolute_min
|
||||
#
|
||||
# # Nombre de lignes intermédiaires (1% steps)
|
||||
# steps = int((absolute_max - absolute_min) / (absolute_min * 0.01))
|
||||
#
|
||||
# # Niveaux de prix à 1%, 2%, ..., steps%
|
||||
# levels = [absolute_min * (1 + i / 100) for i in range(1, steps + 1)]
|
||||
# levels = [lvl for lvl in levels if lvl < absolute_max] # évite le dernier niveau exact
|
||||
#
|
||||
# # ajout dans le DataFrame
|
||||
# for i, lvl in enumerate(levels, start=1):
|
||||
# dataframe[f"lvl_{i}_pct"] = lvl
|
||||
|
||||
# # Indices correspondants
|
||||
# indices = [(dataframe['mid'] - lvl).abs().idxmin() for lvl in levels]
|
||||
|
||||
return dataframe
|
||||
|
||||
def getOpenTrades(self):
|
||||
# if len(self.trades) == 0:
|
||||
self.trades = Trade.get_open_trades()
|
||||
return self.trades
|
||||
|
||||
def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
||||
dataframe.loc[
|
||||
(
|
||||
# (dataframe['sma5_inv'] == 1)
|
||||
# (
|
||||
# ((dataframe['pct180'] < 0.5) | (dataframe['sma24_deriv1'] > 0))
|
||||
# |((dataframe['close'] < dataframe['sma24'] ) & (dataframe['sma24_deriv1'] > 0))
|
||||
#
|
||||
# )
|
||||
(dataframe['hapercent'] > 0)
|
||||
& (dataframe['rsi'] < 85)
|
||||
& (dataframe['sma24'] > dataframe['sma60'])
|
||||
# & (
|
||||
# (dataframe['percent3'] <= -0.003)
|
||||
# | (dataframe['percent12'] <= -0.003)
|
||||
# | (dataframe['percent24'] <= -0.003)
|
||||
# )
|
||||
), ['enter_long', 'enter_tag']] = (1, f"future")
|
||||
|
||||
dataframe['test'] = np.where(dataframe['enter_long'] == 1, dataframe['close'] * 1.003, np.nan)
|
||||
|
||||
return dataframe
|
||||
|
||||
def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
||||
|
||||
return dataframe
|
||||
|
||||
# def adjust_stake_amount(self, pair: str, last_candle: DataFrame):
|
||||
# # Calculer le minimum des 14 derniers jours
|
||||
# nb_pairs = len(self.dp.current_whitelist())
|
||||
#
|
||||
# base_stake_amount = self.config.get('stake_amount')
|
||||
#
|
||||
# if True : #self.pairs[pair]['count_of_buys'] == 0:
|
||||
# factor = 1 #65 / min(65, last_candle['rsi_1d'])
|
||||
# # if last_candle['min_max_60'] > 0.04:
|
||||
# # factor = 2
|
||||
#
|
||||
# adjusted_stake_amount = base_stake_amount #max(base_stake_amount / 5, base_stake_amount * factor)
|
||||
# else:
|
||||
# adjusted_stake_amount = self.pairs[pair]['first_amount']
|
||||
#
|
||||
# if self.pairs[pair]['count_of_buys'] == 0:
|
||||
# self.pairs[pair]['first_amount'] = adjusted_stake_amount
|
||||
#
|
||||
# return adjusted_stake_amount
|
||||
|
||||
def adjust_stake_amount(self, pair: str, last_candle: DataFrame):
|
||||
|
||||
ath = max(self.pairs[pair]['last_max'], self.get_last_ath_before_candle(last_candle))
|
||||
|
||||
ath_dist = 100 * (ath - last_candle["mid"]) / ath
|
||||
|
||||
# ath_dist
|
||||
# 0 ==> 1
|
||||
# 20 ==> 1.5
|
||||
# 40 ==> 2
|
||||
# 50 * (1 + (ath_dist / 40))
|
||||
base_stake = self.config.get('stake_amount') * (1 + (ath_dist / 40))
|
||||
|
||||
# Calcule max/min 180
|
||||
low180 = last_candle["min180"]
|
||||
high180 = last_candle["max180"]
|
||||
|
||||
mult = 1 - ((last_candle["mid"] - low180) / (high180 - low180))
|
||||
|
||||
print(f"low={low180} mid={last_candle['mid']} high={high180} mult={mult} ath={ath} ath_dist={round(ath_dist, 2)}" )
|
||||
# base_size = montant de base que tu veux utiliser (ex: stake_amount ou autre)
|
||||
base_size = base_stake # exemple fraction du portefeuille; adapte selon ton code
|
||||
# new stake proportionnel à mult
|
||||
new_stake = base_size #* mult
|
||||
return new_stake
|
||||
|
||||
def adjust_trade_position(self, trade: Trade, current_time: datetime,
|
||||
current_rate: float, current_profit: float, min_stake: float,
|
||||
max_stake: float, **kwargs):
|
||||
# ne rien faire si ordre deja en cours
|
||||
if trade.has_open_orders:
|
||||
# self.printLog("skip open orders")
|
||||
return None
|
||||
if (self.wallets.get_available_stake_amount() < 10): # or trade.stake_amount >= max_stake:
|
||||
return 0
|
||||
|
||||
dataframe, _ = self.dp.get_analyzed_dataframe(trade.pair, self.timeframe)
|
||||
last_candle = dataframe.iloc[-1].squeeze()
|
||||
before_last_candle = dataframe.iloc[-2].squeeze()
|
||||
# prépare les données
|
||||
current_time = current_time.astimezone(timezone.utc)
|
||||
open_date = trade.open_date.astimezone(timezone.utc)
|
||||
dispo = round(self.wallets.get_available_stake_amount())
|
||||
hours_since_first_buy = (current_time - trade.open_date_utc).seconds / 3600.0
|
||||
days_since_first_buy = (current_time - trade.open_date_utc).days
|
||||
hours = (current_time - trade.date_last_filled_utc).total_seconds() / 3600.0
|
||||
count_of_buys = trade.nr_of_successful_entries
|
||||
current_time_utc = current_time.astimezone(timezone.utc)
|
||||
open_date = trade.open_date.astimezone(timezone.utc)
|
||||
days_since_open = (current_time_utc - open_date).days
|
||||
pair = trade.pair
|
||||
profit = trade.calc_profit(current_rate) #round(current_profit * trade.stake_amount, 1)
|
||||
last_lost = self.getLastLost(last_candle, pair)
|
||||
pct_first = 0
|
||||
|
||||
total_counts = sum(
|
||||
pair_data['count_of_buys'] for pair_data in self.pairs.values() if not self.getShortName(pair) == 'BTC')
|
||||
|
||||
if self.pairs[pair]['first_buy']:
|
||||
pct_first = self.getPctFirstBuy(pair, last_candle)
|
||||
|
||||
lim = 0.3
|
||||
if (len(dataframe) < 1):
|
||||
# self.printLog("skip dataframe")
|
||||
return None
|
||||
|
||||
# Dernier prix d'achat réel (pas le prix moyen)
|
||||
last_fill_price = self.pairs[trade.pair]['last_buy'] #trade.open_rate # remplacé juste après ↓
|
||||
|
||||
# if len(trade.orders) > 0:
|
||||
# # On cherche le dernier BUY exécuté
|
||||
# buy_orders = [o for o in trade.orders if o.is_buy and o.status == "closed"]
|
||||
# if buy_orders:
|
||||
# last_fill_price = buy_orders[-1].price
|
||||
|
||||
# baisse relative
|
||||
dca_threshold = 0.0025 * count_of_buys
|
||||
decline = (last_fill_price - current_rate) / last_fill_price
|
||||
increase = - decline
|
||||
|
||||
# if decline >= self.dca_threshold:
|
||||
# # Exemple : on achète 50% du montant du dernier trade
|
||||
# last_amount = buy_orders[-1].amount if buy_orders else 0
|
||||
# stake_amount = last_amount * current_rate * 0.5
|
||||
# return stake_amount
|
||||
|
||||
condition = last_candle['hapercent'] > 0 and last_candle['sma24_deriv1'] > 0
|
||||
limit_buy = 40
|
||||
# or (last_candle['close'] <= last_candle['min180'] and hours > 3)
|
||||
if (decline >= dca_threshold) and condition:
|
||||
try:
|
||||
if self.pairs[pair]['has_gain'] and profit > 0:
|
||||
self.pairs[pair]['force_sell'] = True
|
||||
self.pairs[pair]['previous_profit'] = profit
|
||||
return None
|
||||
|
||||
max_amount = self.config.get('stake_amount') * 2.5
|
||||
stake_amount = min(min(max_amount, self.wallets.get_available_stake_amount()),
|
||||
self.adjust_stake_amount(pair, last_candle))
|
||||
# print(f"profit={profit} previous={self.pairs[pair]['previous_profit']} count_of_buys={trade.nr_of_successful_entries}")
|
||||
if stake_amount > 0:
|
||||
self.pairs[pair]['previous_profit'] = profit
|
||||
trade_type = "Loss " + (last_candle['enter_tag'] if last_candle['enter_long'] == 1 else '')
|
||||
self.pairs[trade.pair]['count_of_buys'] += 1
|
||||
self.pairs[pair]['total_amount'] += stake_amount
|
||||
self.log_trade(
|
||||
last_candle=last_candle,
|
||||
date=current_time,
|
||||
action="🟧 Loss -",
|
||||
dispo=dispo,
|
||||
pair=trade.pair,
|
||||
rate=current_rate,
|
||||
trade_type=trade_type,
|
||||
profit=round(profit, 1),
|
||||
buys=trade.nr_of_successful_entries + 1,
|
||||
stake=round(stake_amount, 2)
|
||||
)
|
||||
|
||||
self.pairs[trade.pair]['last_buy'] = current_rate
|
||||
self.pairs[trade.pair]['max_touch'] = last_candle['close']
|
||||
self.pairs[trade.pair]['last_candle'] = last_candle
|
||||
|
||||
# df = pd.DataFrame.from_dict(self.pairs, orient='index')
|
||||
# colonnes_a_exclure = ['last_candle', 'stop',
|
||||
# 'trade_info', 'last_date', 'expected_profit', 'last_count_of_buys', 'base_stake_amount', 'stop_buy']
|
||||
# df_filtered = df[df['count_of_buys'] > 0].drop(columns=colonnes_a_exclure)
|
||||
# # df_filtered = df_filtered["first_buy", "last_max", "max_touch", "last_sell","last_buy", 'count_of_buys', 'current_profit']
|
||||
#
|
||||
# self.printLog(df_filtered)
|
||||
|
||||
return stake_amount
|
||||
return None
|
||||
except Exception as exception:
|
||||
self.printLog(exception)
|
||||
return None
|
||||
|
||||
if current_profit > dca_threshold and (increase >= dca_threshold and self.wallets.get_available_stake_amount() > 0):
|
||||
try:
|
||||
self.pairs[pair]['previous_profit'] = profit
|
||||
stake_amount = max(20, min(self.wallets.get_available_stake_amount(), self.adjust_stake_amount(pair, last_candle)))
|
||||
if stake_amount > 0:
|
||||
self.pairs[pair]['has_gain'] += 1
|
||||
|
||||
trade_type = 'Gain +' + (last_candle['enter_tag'] if last_candle['enter_long'] == 1 else '')
|
||||
self.pairs[trade.pair]['count_of_buys'] += 1
|
||||
self.pairs[pair]['total_amount'] += stake_amount
|
||||
self.log_trade(
|
||||
last_candle=last_candle,
|
||||
date=current_time,
|
||||
action="🟡 Gain +",
|
||||
dispo=dispo,
|
||||
pair=trade.pair,
|
||||
rate=current_rate,
|
||||
trade_type='Gain',
|
||||
profit=round(profit, 1),
|
||||
buys=trade.nr_of_successful_entries + 1,
|
||||
stake=round(stake_amount, 2)
|
||||
)
|
||||
self.pairs[trade.pair]['last_buy'] = current_rate
|
||||
self.pairs[trade.pair]['max_touch'] = last_candle['close']
|
||||
self.pairs[trade.pair]['last_candle'] = last_candle
|
||||
return stake_amount
|
||||
return None
|
||||
except Exception as exception:
|
||||
self.printLog(exception)
|
||||
return None
|
||||
|
||||
return None
|
||||
|
||||
def custom_exit(self, pair, trade, current_time, current_rate, current_profit, **kwargs):
|
||||
|
||||
dataframe, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe)
|
||||
last_candle = dataframe.iloc[-1].squeeze()
|
||||
last_candle_1h = dataframe.iloc[-13].squeeze()
|
||||
before_last_candle = dataframe.iloc[-2].squeeze()
|
||||
before_last_candle_2 = dataframe.iloc[-3].squeeze()
|
||||
before_last_candle_12 = dataframe.iloc[-13].squeeze()
|
||||
|
||||
expected_profit = self.expectedProfit(pair, last_candle)
|
||||
# print(f"current_time={current_time} current_profit={current_profit} expected_profit={expected_profit}")
|
||||
|
||||
# ----- 1) Charger les variables de trailing pour ce trade -----
|
||||
max_price = self.pairs[pair]['max_touch']
|
||||
|
||||
self.pairs[pair]['last_max'] = max(last_candle['close'], self.pairs[pair]['last_max'])
|
||||
self.pairs[pair]['last_min'] = min(last_candle['close'], self.pairs[pair]['last_min'])
|
||||
self.pairs[pair]['current_trade'] = trade
|
||||
|
||||
count_of_buys = trade.nr_of_successful_entries
|
||||
|
||||
profit = trade.calc_profit(current_rate) #round(current_profit * trade.stake_amount, 1)
|
||||
|
||||
if current_profit > 0:
|
||||
self.pairs[pair]['max_profit'] = max(self.pairs[pair]['max_profit'], profit)
|
||||
# else:
|
||||
# self.pairs[pair]['max_profit'] = 0
|
||||
|
||||
max_profit = self.pairs[pair]['max_profit']
|
||||
|
||||
# if current_profit > 0:
|
||||
# print(f"profit={profit} max_profit={max_profit} current_profit={current_profit}")
|
||||
|
||||
baisse = 0
|
||||
if profit > 0:
|
||||
baisse = 1 - (profit / max_profit)
|
||||
mx = max_profit / 5
|
||||
self.pairs[pair]['count_of_buys'] = count_of_buys
|
||||
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 = (current_time - trade.date_last_filled_utc).total_seconds() / 3600.0
|
||||
minutes = (current_time - trade.date_last_filled_utc).total_seconds() / 60.0
|
||||
|
||||
# ----- 2) Mise à jour du max_price -----
|
||||
self.pairs[pair]['max_touch'] = max(last_candle['close'], self.pairs[pair]['max_touch'])
|
||||
|
||||
# ----- 3) Calcul du profit max atteint -----
|
||||
# profit_max = (max_price - trade.open_rate) / trade.open_rate
|
||||
|
||||
current_trailing_stop_positive = self.trailing_stop_positive
|
||||
current_trailing_only_offset_is_reached = self.trailing_only_offset_is_reached
|
||||
current_trailing_stop_positive_offset = self.trailing_stop_positive_offset
|
||||
|
||||
max_ = last_candle['max180']
|
||||
min_ = last_candle['min180']
|
||||
mid = last_candle['mid']
|
||||
# éviter division par zéro
|
||||
position = (mid - min_) / (max_ - min_)
|
||||
zone = int(position * 3) # 0 à 2
|
||||
|
||||
if zone == 0:
|
||||
current_trailing_stop_positive = self.trailing_stop_positive
|
||||
current_trailing_stop_positive_offset = self.trailing_stop_positive_offset * 2
|
||||
if minutes > 1440:
|
||||
current_trailing_only_offset_is_reached = False
|
||||
current_trailing_stop_positive_offset = self.trailing_stop_positive_offset
|
||||
# if zone == 1:
|
||||
|
||||
# ----- 5) Calcul du trailing stop dynamique -----
|
||||
# Exemple : offset=0.321 => stop à +24.8%
|
||||
|
||||
trailing_stop = max_profit * (1.0 - current_trailing_stop_positive)
|
||||
baisse = 0
|
||||
if max_profit:
|
||||
baisse = (max_profit - profit) / max_profit
|
||||
|
||||
if minutes % 12 == 0:
|
||||
self.log_trade(
|
||||
last_candle=last_candle,
|
||||
date=current_time,
|
||||
action="🟢 CURRENT", #🔴 CURRENT" if self.pairs[pair]['stop'] or last_candle['stop_buying'] else "
|
||||
dispo=dispo,
|
||||
pair=pair,
|
||||
rate=last_candle['close'],
|
||||
trade_type=f"{round(profit, 2)} {round(max_profit, 2)} {round(trailing_stop,2)} {minutes}",
|
||||
profit=round(profit, 2),
|
||||
buys=count_of_buys,
|
||||
stake=0
|
||||
)
|
||||
|
||||
# if last_candle['sma24_deriv1'] > 0 : #and minutes < 180 and baisse < 30: # and last_candle['sma5_deriv1'] > -0.15:
|
||||
# if (minutes < 180):
|
||||
# return None
|
||||
# if (minutes > 1440 and last_candle['sma60_deriv1'] > 0) :
|
||||
# return None
|
||||
|
||||
|
||||
# ----- 4) OFFSET : faut-il attendre de dépasser trailing_stop_positive_offset ? -----
|
||||
if current_trailing_only_offset_is_reached:
|
||||
# Max profit pas atteint ET perte < 2 * current_trailing_stop_positive
|
||||
if max_profit < min(2, current_trailing_stop_positive_offset * (count_of_buys - self.pairs[pair]['has_gain']))\
|
||||
and (max_profit > current_trailing_stop_positive_offset): #2 * current_trailing_stop_positive:
|
||||
return None # ne pas activer le trailing encore
|
||||
# Sinon : trailing actif dès le début
|
||||
|
||||
# ----- 6) Condition de vente -----
|
||||
if 0 < profit <= trailing_stop and last_candle['mid'] < last_candle['sma5']:
|
||||
return f"stop_{count_of_buys}_{self.pairs[pair]['has_gain']}"
|
||||
return None
|
||||
|
||||
def informative_pairs(self):
|
||||
# get access to all pairs available in whitelist.
|
||||
pairs = self.dp.current_whitelist()
|
||||
informative_pairs = [(pair, '1h') for pair in pairs]
|
||||
informative_pairs += [(pair, '1d') for pair in pairs]
|
||||
|
||||
return informative_pairs
|
||||
|
||||
def populate1hIndicators(self, df: pd.DataFrame, metadata: dict) -> pd.DataFrame:
|
||||
|
||||
# --- WEEKLY LEVELS ---
|
||||
# semaine précédente = semaine ISO différente
|
||||
df["week"] = df.index.isocalendar().week
|
||||
df["year"] = df.index.year
|
||||
|
||||
df["weekly_low"] = (
|
||||
df.groupby(["year", "week"])["low"]
|
||||
.transform("min")
|
||||
.shift(1) # décalé -> pas regarder la semaine en cours
|
||||
)
|
||||
df["weekly_high"] = (
|
||||
df.groupby(["year", "week"])["high"]
|
||||
.transform("max")
|
||||
.shift(1)
|
||||
)
|
||||
|
||||
# Définition simple d'une zone de demande hebdo :
|
||||
# bas + 25% de la bougie => modifiable
|
||||
df["weekly_demand_zone_low"] = df["weekly_low"]
|
||||
df["weekly_demand_zone_high"] = df["weekly_low"] * 1.025
|
||||
|
||||
# --- MONTHLY LEVELS ---
|
||||
df["month"] = df.index.month
|
||||
|
||||
df["monthly_low"] = (
|
||||
df.groupby(["year", "month"])["low"]
|
||||
.transform("min")
|
||||
.shift(1) # mois précédent uniquement
|
||||
)
|
||||
df["monthly_high"] = (
|
||||
df.groupby(["year", "month"])["high"]
|
||||
.transform("max")
|
||||
.shift(1)
|
||||
)
|
||||
|
||||
df["monthly_demand_zone_low"] = df["monthly_low"]
|
||||
df["monthly_demand_zone_high"] = df["monthly_low"] * 1.03
|
||||
|
||||
return df
|
||||
|
||||
# ----- SIGNALS SIMPLES POUR EXEMPLE -----
|
||||
|
||||
# def populate_buy_trend(self, df: pd.DataFrame, metadata: dict) -> pd.DataFrame:
|
||||
# df["buy"] = 0
|
||||
#
|
||||
# # Exemple : acheter si le prix tape la zone de demande hebdomadaire
|
||||
# df.loc[
|
||||
# (df["close"] <= df["weekly_demand_zone_high"]) &
|
||||
# (df["close"] >= df["weekly_demand_zone_low"]),
|
||||
# "buy"
|
||||
# ] = 1
|
||||
#
|
||||
# return df
|
||||
#
|
||||
# def populate_sell_trend(self, df: pd.DataFrame, metadata: dict) -> pd.DataFrame:
|
||||
# df["sell"] = 0
|
||||
#
|
||||
# # Exemple : vendre sur retour au weekly_high précédent
|
||||
# df.loc[df["close"] >= df["weekly_high"], "sell"] = 1
|
||||
#
|
||||
# return df
|
||||
|
||||
|
||||
def rsi_trend_probability(self, dataframe, short=6, long=12):
|
||||
dataframe = dataframe.copy()
|
||||
|
||||
dataframe['rsi_short'] = talib.RSI(dataframe['mid'], short)
|
||||
dataframe['rsi_long'] = talib.RSI(dataframe['mid'], long)
|
||||
|
||||
dataframe['cross_soft'] = np.tanh((dataframe['rsi_short'] - dataframe['rsi_long']) / 7)
|
||||
|
||||
dataframe['gap'] = (dataframe['rsi_short'] - dataframe['rsi_long']) / 100
|
||||
dataframe['trend'] = (dataframe['rsi_long'] - 50) / 50
|
||||
|
||||
dataframe['rtp'] = (
|
||||
0.6 * dataframe['cross_soft'] +
|
||||
0.25 * dataframe['gap'] +
|
||||
0.15 * dataframe['trend']
|
||||
).clip(-1, 1)
|
||||
|
||||
return dataframe
|
||||
|
||||
import pandas as pd
|
||||
|
||||
def to_utc_ts(self, x):
|
||||
return pd.to_datetime(x, utc=True)
|
||||
|
||||
# suppose self.btc_ath_history exists (liste de dict)
|
||||
def get_last_ath_before_candle(self, last_candle):
|
||||
candle_date = self.to_utc_ts(last_candle['date']) # ou to_utc_ts(last_candle.name)
|
||||
best = None
|
||||
for a in self.btc_ath_history: #getattr(self, "btc_ath_history", []):
|
||||
ath_date = self.to_utc_ts(a["date"])
|
||||
if ath_date <= candle_date:
|
||||
if best is None or ath_date > best[0]:
|
||||
best = (ath_date, a["price_usd"])
|
||||
return best[1] if best is not None else None
|
||||
|
||||
35
FrictradeLearning.json
Normal file
35
FrictradeLearning.json
Normal file
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"strategy_name": "FrictradeLearning",
|
||||
"params": {
|
||||
"roi": {
|
||||
"0": 10
|
||||
},
|
||||
"stoploss": {
|
||||
"stoploss": -1.0
|
||||
},
|
||||
"trailing": {
|
||||
"trailing_stop": false,
|
||||
"trailing_stop_positive": 0.15,
|
||||
"trailing_stop_positive_offset": 1,
|
||||
"trailing_only_offset_is_reached": true
|
||||
},
|
||||
"max_open_trades": {
|
||||
"max_open_trades": 20
|
||||
},
|
||||
"protection": {
|
||||
"allow_decrease_rate": 0.4,
|
||||
"first_adjust_param": 0.005,
|
||||
"max_steps": 30
|
||||
},
|
||||
"buy": {
|
||||
"hours_force": 44,
|
||||
"indic_1h_force_buy": "sma5_deriv1_1h"
|
||||
},
|
||||
"sell": {
|
||||
"offset_max": 6,
|
||||
"offset_min": 27
|
||||
}
|
||||
},
|
||||
"ft_stratparam_v": 1,
|
||||
"export_time": "2025-12-15 19:03:21.177158+00:00"
|
||||
}
|
||||
2635
FrictradeLearning.py
Normal file
2635
FrictradeLearning.py
Normal file
File diff suppressed because it is too large
Load Diff
25
Genetic.json
Normal file
25
Genetic.json
Normal file
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"strategy_name": "Genetic",
|
||||
"params": {
|
||||
"roi": {
|
||||
"0": 0.21029,
|
||||
"11": 0.05876,
|
||||
"57": 0.02191,
|
||||
"281": 0
|
||||
},
|
||||
"stoploss": {
|
||||
"stoploss": -1.0
|
||||
},
|
||||
"max_open_trades": {
|
||||
"max_open_trades": 80
|
||||
},
|
||||
"trailing": {
|
||||
"trailing_stop": true,
|
||||
"trailing_stop_positive": 0.028,
|
||||
"trailing_stop_positive_offset": 0.105,
|
||||
"trailing_only_offset_is_reached": true
|
||||
}
|
||||
},
|
||||
"ft_stratparam_v": 1,
|
||||
"export_time": "2025-12-04 23:58:24.045587+00:00"
|
||||
}
|
||||
@@ -160,7 +160,7 @@ class Genetic(IStrategy):
|
||||
}
|
||||
|
||||
# Stoploss:
|
||||
stoploss = -0.07693
|
||||
stoploss = -1
|
||||
|
||||
# Optimal ticker interval for the strategy
|
||||
ticker_interval = '2h'
|
||||
@@ -359,4 +359,5 @@ class Genetic(IStrategy):
|
||||
|
||||
def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
||||
|
||||
return dataframe
|
||||
return dataframe
|
||||
|
||||
|
||||
186
GodStra.py
186
GodStra.py
@@ -11,8 +11,13 @@
|
||||
|
||||
# --- Do not remove these libs ---
|
||||
from freqtrade.strategy.interface import IStrategy
|
||||
from datetime import timedelta, datetime
|
||||
from freqtrade.persistence import Trade
|
||||
from freqtrade.strategy import (BooleanParameter, CategoricalParameter, DecimalParameter, stoploss_from_open,
|
||||
IntParameter, IStrategy, merge_informative_pair, informative, stoploss_from_absolute)
|
||||
from pandas import DataFrame
|
||||
# --------------------------------
|
||||
from datetime import timezone, timedelta
|
||||
|
||||
# Add your lib to import here
|
||||
# import talib.abstract as ta
|
||||
@@ -24,6 +29,38 @@ import numpy as np
|
||||
|
||||
|
||||
class GodStra(IStrategy):
|
||||
position_adjustment_enable = True
|
||||
|
||||
columns_logged = False
|
||||
pairs = {
|
||||
pair: {
|
||||
"first_buy": 0,
|
||||
"last_buy": 0.0,
|
||||
"last_min": 999999999999999.5,
|
||||
"last_max": 0,
|
||||
"trade_info": {},
|
||||
"max_touch": 0.0,
|
||||
"last_sell": 0.0,
|
||||
'count_of_buys': 0,
|
||||
'current_profit': 0,
|
||||
'expected_profit': 0,
|
||||
'previous_profit': 0,
|
||||
"last_candle": {},
|
||||
"last_count_of_buys": 0,
|
||||
'base_stake_amount': 0,
|
||||
'stop_buy': False,
|
||||
'last_date': 0,
|
||||
'stop': False,
|
||||
'max_profit': 0,
|
||||
'first_amount': 0,
|
||||
'total_amount': 0,
|
||||
'has_gain': 0,
|
||||
'force_sell': False,
|
||||
'force_buy': False
|
||||
}
|
||||
for pair in ["BTC/USDC", "ETH/USDC", "DOGE/USDC", "XRP/USDC", "SOL/USDC",
|
||||
"BTC/USDT", "ETH/USDT", "DOGE/USDT", "XRP/USDT", "SOL/USDT"]
|
||||
}
|
||||
# 5/66: 9 trades. 8/0/1 Wins/Draws/Losses. Avg profit 21.83%. Median profit 35.52%. Total profit 1060.11476586 USDT ( 196.50Σ%). Avg duration 3440.0 min. Objective: -7.06960
|
||||
# +--------+---------+----------+------------------+--------------+-------------------------------+----------------+-------------+
|
||||
# | Best | Epoch | Trades | Win Draw Loss | Avg profit | Profit | Avg duration | Objective |
|
||||
@@ -67,7 +104,7 @@ class GodStra(IStrategy):
|
||||
trailing_stop_positive_offset = 0.2684
|
||||
trailing_only_offset_is_reached = True
|
||||
# Buy hypers
|
||||
timeframe = '12h'
|
||||
timeframe = '1m'
|
||||
print('Add {\n\t"method": "AgeFilter",\n\t"min_days_listed": 30\n},\n to your pairlists in config (Under StaticPairList)')
|
||||
|
||||
def dna_size(self, dct: dict):
|
||||
@@ -169,3 +206,150 @@ class GodStra(IStrategy):
|
||||
'sell'] = 1
|
||||
|
||||
return dataframe
|
||||
|
||||
def adjust_trade_position(self, trade: Trade, current_time: datetime,
|
||||
current_rate: float, current_profit: float, min_stake: float,
|
||||
max_stake: float, **kwargs):
|
||||
# ne rien faire si ordre deja en cours
|
||||
print('ici')
|
||||
if trade.has_open_orders:
|
||||
# self.printLog("skip open orders")
|
||||
return None
|
||||
if (self.wallets.get_available_stake_amount() < 10): # or trade.stake_amount >= max_stake:
|
||||
return 0
|
||||
|
||||
dataframe, _ = self.dp.get_analyzed_dataframe(trade.pair, self.timeframe)
|
||||
last_candle = dataframe.iloc[-1].squeeze()
|
||||
before_last_candle = dataframe.iloc[-2].squeeze()
|
||||
# prépare les données
|
||||
current_time = current_time.astimezone(timezone.utc)
|
||||
open_date = trade.open_date.astimezone(timezone.utc)
|
||||
dispo = round(self.wallets.get_available_stake_amount())
|
||||
hours_since_first_buy = (current_time - trade.open_date_utc).seconds / 3600.0
|
||||
days_since_first_buy = (current_time - trade.open_date_utc).days
|
||||
hours = (current_time - trade.date_last_filled_utc).total_seconds() / 3600.0
|
||||
count_of_buys = trade.nr_of_successful_entries
|
||||
current_time_utc = current_time.astimezone(timezone.utc)
|
||||
open_date = trade.open_date.astimezone(timezone.utc)
|
||||
days_since_open = (current_time_utc - open_date).days
|
||||
pair = trade.pair
|
||||
profit = trade.calc_profit(current_rate) #round(current_profit * trade.stake_amount, 1)
|
||||
last_lost = self.getLastLost(last_candle, pair)
|
||||
pct_first = 0
|
||||
|
||||
total_counts = sum(
|
||||
pair_data['count_of_buys'] for pair_data in self.pairs.values() if not self.getShortName(pair) == 'BTC')
|
||||
|
||||
if self.pairs[pair]['first_buy']:
|
||||
pct_first = self.getPctFirstBuy(pair, last_candle)
|
||||
|
||||
lim = 0.3
|
||||
if (len(dataframe) < 1):
|
||||
# self.printLog("skip dataframe")
|
||||
return None
|
||||
|
||||
# Dernier prix d'achat réel (pas le prix moyen)
|
||||
last_fill_price = self.pairs[trade.pair]['last_buy'] #trade.open_rate # remplacé juste après ↓
|
||||
|
||||
# if len(trade.orders) > 0:
|
||||
# # On cherche le dernier BUY exécuté
|
||||
# buy_orders = [o for o in trade.orders if o.is_buy and o.status == "closed"]
|
||||
# if buy_orders:
|
||||
# last_fill_price = buy_orders[-1].price
|
||||
|
||||
# baisse relative
|
||||
dca_threshold = 0.0025 * count_of_buys
|
||||
decline = (last_fill_price - current_rate) / last_fill_price
|
||||
increase = - decline
|
||||
|
||||
# if decline >= self.dca_threshold:
|
||||
# # Exemple : on achète 50% du montant du dernier trade
|
||||
# last_amount = buy_orders[-1].amount if buy_orders else 0
|
||||
# stake_amount = last_amount * current_rate * 0.5
|
||||
# return stake_amount
|
||||
|
||||
condition = last_candle['percent'] > 0 #and last_candle['sma24_deriv1'] > 0
|
||||
limit_buy = 40
|
||||
# or (last_candle['close'] <= last_candle['min180'] and hours > 3)
|
||||
if (decline >= dca_threshold) and condition:
|
||||
print('decline')
|
||||
try:
|
||||
if self.pairs[pair]['has_gain'] and profit > 0:
|
||||
self.pairs[pair]['force_sell'] = True
|
||||
self.pairs[pair]['previous_profit'] = profit
|
||||
return None
|
||||
|
||||
max_amount = self.config.get('stake_amount') * 2.5
|
||||
stake_amount = min(min(max_amount, self.wallets.get_available_stake_amount()),
|
||||
self.adjust_stake_amount(pair, last_candle))
|
||||
# print(f"profit={profit} previous={self.pairs[pair]['previous_profit']} count_of_buys={trade.nr_of_successful_entries}")
|
||||
if stake_amount > 0:
|
||||
self.pairs[pair]['previous_profit'] = profit
|
||||
trade_type = "Loss " + (last_candle['enter_tag'] if last_candle['enter_long'] == 1 else '')
|
||||
self.pairs[trade.pair]['count_of_buys'] += 1
|
||||
self.pairs[pair]['total_amount'] += stake_amount
|
||||
# self.log_trade(
|
||||
# last_candle=last_candle,
|
||||
# date=current_time,
|
||||
# action="🟧 Loss -",
|
||||
# dispo=dispo,
|
||||
# pair=trade.pair,
|
||||
# rate=current_rate,
|
||||
# trade_type=trade_type,
|
||||
# profit=round(profit, 1),
|
||||
# buys=trade.nr_of_successful_entries + 1,
|
||||
# stake=round(stake_amount, 2)
|
||||
# )
|
||||
|
||||
self.pairs[trade.pair]['last_buy'] = current_rate
|
||||
self.pairs[trade.pair]['max_touch'] = last_candle['close']
|
||||
self.pairs[trade.pair]['last_candle'] = last_candle
|
||||
|
||||
# df = pd.DataFrame.from_dict(self.pairs, orient='index')
|
||||
# colonnes_a_exclure = ['last_candle', 'stop',
|
||||
# 'trade_info', 'last_date', 'expected_profit', 'last_count_of_buys', 'base_stake_amount', 'stop_buy']
|
||||
# df_filtered = df[df['count_of_buys'] > 0].drop(columns=colonnes_a_exclure)
|
||||
# # df_filtered = df_filtered["first_buy", "last_max", "max_touch", "last_sell","last_buy", 'count_of_buys', 'current_profit']
|
||||
#
|
||||
# self.printLog(df_filtered)
|
||||
|
||||
return stake_amount
|
||||
return None
|
||||
except Exception as exception:
|
||||
self.printLog(exception)
|
||||
return None
|
||||
|
||||
if current_profit > dca_threshold and (increase >= dca_threshold and self.wallets.get_available_stake_amount() > 0):
|
||||
print('increase')
|
||||
|
||||
try:
|
||||
self.pairs[pair]['previous_profit'] = profit
|
||||
stake_amount = max(20, min(self.wallets.get_available_stake_amount(), self.adjust_stake_amount(pair, last_candle)))
|
||||
if stake_amount > 0:
|
||||
self.pairs[pair]['has_gain'] += 1
|
||||
|
||||
trade_type = 'Gain +' + (last_candle['enter_tag'] if last_candle['enter_long'] == 1 else '')
|
||||
self.pairs[trade.pair]['count_of_buys'] += 1
|
||||
self.pairs[pair]['total_amount'] += stake_amount
|
||||
# self.log_trade(
|
||||
# last_candle=last_candle,
|
||||
# date=current_time,
|
||||
# action="🟡 Gain +",
|
||||
# dispo=dispo,
|
||||
# pair=trade.pair,
|
||||
# rate=current_rate,
|
||||
# trade_type='Gain',
|
||||
# profit=round(profit, 1),
|
||||
# buys=trade.nr_of_successful_entries + 1,
|
||||
# stake=round(stake_amount, 2)
|
||||
# )
|
||||
self.pairs[trade.pair]['last_buy'] = current_rate
|
||||
self.pairs[trade.pair]['max_touch'] = last_candle['close']
|
||||
self.pairs[trade.pair]['last_candle'] = last_candle
|
||||
return stake_amount
|
||||
return None
|
||||
except Exception as exception:
|
||||
self.printLog(exception)
|
||||
return None
|
||||
|
||||
return None
|
||||
@@ -14,7 +14,10 @@ import pandas as pd # noqa
|
||||
from pandas import DataFrame
|
||||
from skopt.space import Categorical, Dimension, Integer, Real # noqa
|
||||
|
||||
from freqtrade.optimize.hyperopt_interface import IHyperOpt
|
||||
from freqtrade.strategy import (BooleanParameter, CategoricalParameter, DecimalParameter, stoploss_from_open,
|
||||
IntParameter, IStrategy, merge_informative_pair, informative, stoploss_from_absolute)
|
||||
|
||||
# from freqtrade.optimize.hyperopt_interface import IHyperOpt
|
||||
|
||||
# --------------------------------
|
||||
# Add your lib to import here
|
||||
@@ -52,7 +55,7 @@ GodGenes = ["open", "high", "low", "close", "volume", "volume_adi", "volume_obv"
|
||||
"others_dr", "others_dlr", "others_cr"]
|
||||
|
||||
|
||||
class GodStraHo(IHyperOpt):
|
||||
class GodStraHo(IStrategy):
|
||||
|
||||
@staticmethod
|
||||
def indicator_space() -> List[Dimension]:
|
||||
|
||||
53
GodStraJD.json
Normal file
53
GodStraJD.json
Normal file
@@ -0,0 +1,53 @@
|
||||
{
|
||||
"strategy_name": "GodStraJD",
|
||||
"params": {
|
||||
"roi": {
|
||||
"0": 0.598,
|
||||
"644": 0.166,
|
||||
"3269": 0.115,
|
||||
"7289": 0
|
||||
},
|
||||
"max_open_trades": {
|
||||
"max_open_trades": 80
|
||||
},
|
||||
"buy": {
|
||||
"buy_crossed_indicator0": "WMA-100",
|
||||
"buy_crossed_indicator1": "KAMA-110",
|
||||
"buy_crossed_indicator2": "CDLKICKING-55",
|
||||
"buy_indicator0": "MACD-0-50",
|
||||
"buy_indicator1": "SAREXT-15",
|
||||
"buy_indicator2": "DEMA-12",
|
||||
"buy_operator0": "<R",
|
||||
"buy_operator1": "C",
|
||||
"buy_operator2": "D",
|
||||
"buy_real_num0": 0.7,
|
||||
"buy_real_num1": 0.7,
|
||||
"buy_real_num2": 0.7
|
||||
},
|
||||
"sell": {
|
||||
"sell_crossed_indicator0": "CDLDARKCLOUDCOVER-15",
|
||||
"sell_crossed_indicator1": "CDLHANGINGMAN-6",
|
||||
"sell_crossed_indicator2": "CDLMATHOLD-55",
|
||||
"sell_indicator0": "MEDPRICE-15",
|
||||
"sell_indicator1": "T3-100",
|
||||
"sell_indicator2": "CDLDOJISTAR-12",
|
||||
"sell_operator0": "=R",
|
||||
"sell_operator1": "DT",
|
||||
"sell_operator2": "CA",
|
||||
"sell_real_num0": 0.7,
|
||||
"sell_real_num1": 0.7,
|
||||
"sell_real_num2": 0.6
|
||||
},
|
||||
"stoploss": {
|
||||
"stoploss": -0.122
|
||||
},
|
||||
"trailing": {
|
||||
"trailing_stop": true,
|
||||
"trailing_stop_positive": 0.058,
|
||||
"trailing_stop_positive_offset": 0.097,
|
||||
"trailing_only_offset_is_reached": true
|
||||
}
|
||||
},
|
||||
"ft_stratparam_v": 1,
|
||||
"export_time": "2025-12-04 23:29:46.366351+00:00"
|
||||
}
|
||||
@@ -470,7 +470,7 @@ class GodStraJD(IStrategy):
|
||||
# Stoploss:
|
||||
stoploss = -0.128
|
||||
# Buy hypers
|
||||
timeframe = '4h'
|
||||
timeframe = '1m'
|
||||
|
||||
# Trailing stoploss
|
||||
trailing_stop = True
|
||||
|
||||
@@ -474,7 +474,7 @@ class GodStraJD3_1(IStrategy):
|
||||
# Stoploss:
|
||||
stoploss = -1
|
||||
# Buy hypers
|
||||
timeframe = '4h'
|
||||
timeframe = '1m'
|
||||
|
||||
# Trailing stoploss
|
||||
trailing_stop = True
|
||||
|
||||
@@ -10,7 +10,7 @@ from freqtrade.persistence import Trade
|
||||
from freqtrade.strategy.parameters import CategoricalParameter, DecimalParameter
|
||||
|
||||
from numpy.lib import math
|
||||
from freqtrade.strategy.interface import IStrategy, SellCheckTuple
|
||||
from freqtrade.strategy.interface import IStrategy
|
||||
from pandas import DataFrame
|
||||
|
||||
# --------------------------------
|
||||
|
||||
@@ -668,8 +668,7 @@ class GodStraJD3_4(IStrategy):
|
||||
# # Use default stake amount.
|
||||
# return proposed_stake
|
||||
|
||||
def custom_sell(self, pair: str, trade: 'Trade', current_time: 'datetime', current_rate: float,
|
||||
current_profit: float, **kwargs):
|
||||
def custom_exit(self, pair, trade, current_time, current_rate, current_profit, **kwargs):
|
||||
dataframe, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe)
|
||||
last_candle = dataframe.iloc[-1].squeeze()
|
||||
previous_last_candle = dataframe.iloc[-2].squeeze()
|
||||
@@ -971,8 +970,6 @@ class GodStraJD3_4(IStrategy):
|
||||
if conditions:
|
||||
dataframe.loc[
|
||||
(reduce(lambda x, y: x & y, conditions)
|
||||
# & (dataframe['percent_4h'] > 0)
|
||||
& (dataframe['percent3_4h'] <= 0)
|
||||
),
|
||||
'buy']=1
|
||||
# print(len(dataframe.keys()))
|
||||
|
||||
@@ -10,7 +10,7 @@ from freqtrade.persistence import Trade
|
||||
from freqtrade.strategy.parameters import CategoricalParameter, DecimalParameter, IntParameter
|
||||
|
||||
from numpy.lib import math
|
||||
from freqtrade.strategy.interface import IStrategy, SellCheckTuple
|
||||
from freqtrade.strategy.interface import IStrategy
|
||||
from pandas import DataFrame
|
||||
|
||||
# --------------------------------
|
||||
|
||||
@@ -10,7 +10,7 @@ from freqtrade.persistence import Trade
|
||||
from freqtrade.strategy.parameters import CategoricalParameter, DecimalParameter, IntParameter
|
||||
|
||||
from numpy.lib import math
|
||||
from freqtrade.strategy.interface import IStrategy, SellCheckTuple
|
||||
from freqtrade.strategy.interface import IStrategy
|
||||
from pandas import DataFrame
|
||||
|
||||
# --------------------------------
|
||||
|
||||
@@ -27,7 +27,7 @@ import numpy as np
|
||||
from random import shuffle
|
||||
|
||||
# TODO: this gene is removed 'MAVP' cuz or error on periods
|
||||
import user_data.strategies.custom_indicators as csa
|
||||
# import user_data.strategies.custom_indicators as csa
|
||||
|
||||
all_god_genes = {
|
||||
'Overlap Studies': {
|
||||
|
||||
@@ -86,7 +86,7 @@ class HammerReversalStrategy(IStrategy):
|
||||
}
|
||||
|
||||
stoploss = -1
|
||||
timeframe = '1h'
|
||||
timeframe = '1m'
|
||||
position_adjustment_enable = True
|
||||
columns_logged = False
|
||||
max_entry_position_adjustment = 20
|
||||
|
||||
@@ -220,10 +220,10 @@ class Ishimoku_6(IStrategy):
|
||||
def bot_loop_start(self, **kwargs) -> None:
|
||||
inf_tf = '5m'
|
||||
pairs = self.dp.current_whitelist()
|
||||
print("Calcul des pairs informatives")
|
||||
# print("Calcul des pairs informatives")
|
||||
for pairname in pairs:
|
||||
self.stop_buying[pairname] = True
|
||||
print("Fin Calcul des pairs informatives")
|
||||
# print("Fin Calcul des pairs informatives")
|
||||
|
||||
# def custom_stake_amount(self, pair: str, current_time: datetime, current_rate: float,
|
||||
# proposed_stake: float, min_stake: float, max_stake: float,
|
||||
|
||||
265
Simple.py
Normal file
265
Simple.py
Normal file
@@ -0,0 +1,265 @@
|
||||
# Zeus Strategy: First Generation of GodStra Strategy with maximum
|
||||
# AVG/MID profit in USDT
|
||||
# Author: @Mablue (Masoud Azizi)
|
||||
# github: https://github.com/mablue/
|
||||
# IMPORTANT: INSTALL TA BEFOUR RUN(pip install ta)
|
||||
# freqtrade hyperopt --hyperopt-loss SharpeHyperOptLoss --spaces buy sell roi --strategy Zeus
|
||||
# --- Do not remove these libs ---
|
||||
from datetime import timedelta, datetime
|
||||
from freqtrade.persistence import Trade
|
||||
from freqtrade.strategy import (BooleanParameter, CategoricalParameter, DecimalParameter, stoploss_from_open,
|
||||
IntParameter, IStrategy, merge_informative_pair, informative, stoploss_from_absolute)
|
||||
import pandas as pd
|
||||
import numpy as np
|
||||
from pandas import DataFrame
|
||||
from typing import Optional, Union, Tuple
|
||||
from typing import List
|
||||
|
||||
import logging
|
||||
import configparser
|
||||
from technical import pivots_points
|
||||
# --------------------------------
|
||||
|
||||
# Add your lib to import here test git
|
||||
import ta
|
||||
import talib.abstract as talib
|
||||
import freqtrade.vendor.qtpylib.indicators as qtpylib
|
||||
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__)
|
||||
|
||||
from tabulate import tabulate
|
||||
|
||||
# Couleurs ANSI de base
|
||||
RED = "\033[31m"
|
||||
GREEN = "\033[32m"
|
||||
YELLOW = "\033[33m"
|
||||
BLUE = "\033[34m"
|
||||
MAGENTA = "\033[35m"
|
||||
CYAN = "\033[36m"
|
||||
RESET = "\033[0m"
|
||||
|
||||
|
||||
def pprint_df(dframe):
|
||||
print(tabulate(dframe, headers='keys', tablefmt='psql', showindex=False))
|
||||
|
||||
|
||||
def normalize(df):
|
||||
df = (df - df.min()) / (df.max() - df.min())
|
||||
return df
|
||||
|
||||
"""
|
||||
SMA z-score derivative strategy with trailing exit (large).
|
||||
- timeframe: 1h
|
||||
- sma5, relative derivatives, z-score normalization (rolling z over z_window)
|
||||
- smoothing: ewm(span=5) on z-scores
|
||||
- entry: z_d1_smooth > entry_z1 AND z_d2_smooth > entry_z2
|
||||
- exit: inversion (z_d1_smooth < 0) AND retrace from highest since entry >= trailing_stop
|
||||
"""
|
||||
class Simple(IStrategy):
|
||||
levels = [1, 2, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
|
||||
startup_candle_count = 12 * 24 * 2
|
||||
|
||||
# ROI table:
|
||||
minimal_roi = {
|
||||
"0": 10
|
||||
}
|
||||
stakes = 40
|
||||
|
||||
# Stoploss:
|
||||
stoploss = -1 # 0.256
|
||||
# Custom stoploss
|
||||
use_custom_stoploss = True
|
||||
|
||||
# Buy hypers
|
||||
timeframe = '1h'
|
||||
|
||||
max_open_trades = 5
|
||||
max_amount = 40
|
||||
|
||||
# DCA config
|
||||
position_adjustment_enable = True
|
||||
|
||||
# Parameters (tweakable)
|
||||
z_window = 50 # window for rolling mean/std to compute zscore
|
||||
entry_z1 = 0.1 # threshold on z-score of first derivative
|
||||
entry_z2 = 0.1 # threshold on z-score of second derivative
|
||||
min_volume = 0.0 # minimal volume to accept an entry
|
||||
min_relative_d1 = 1e-6 # clip tiny d1 relative values to reduce noise
|
||||
|
||||
# Trailing parameters for "large" trailing requested
|
||||
trailing_stop_pct = 0.05 # 5% retracement from highest since entry
|
||||
|
||||
# Smoothing for z-scores
|
||||
ewm_span = 5
|
||||
|
||||
# Plot config: price + sma5 + markers + slope/accel subplots
|
||||
plot_config = {
|
||||
"main_plot": {
|
||||
"close": {"color": "blue"},
|
||||
"sma5": {"color": "orange"},
|
||||
},
|
||||
"subplots": {
|
||||
"slope_and_accel": {
|
||||
"z_d1": {"color": "green"},
|
||||
"z_d2": {"color": "red"},
|
||||
}
|
||||
},
|
||||
# Markers (Freqtrade charting supports markers via these keys)
|
||||
"markers": [
|
||||
# buy marker: '^' green when enter_long==1
|
||||
{"type": "buy", "column": "enter_long", "marker": "^", "color": "green", "markersize": 10},
|
||||
# sell marker: 'v' red when exit_long==1
|
||||
{"type": "sell", "column": "exit_long", "marker": "v", "color": "red", "markersize": 10},
|
||||
],
|
||||
}
|
||||
|
||||
def informative_pairs(self):
|
||||
return []
|
||||
|
||||
def _zscore(self, series: pd.Series, window: int) -> pd.Series:
|
||||
mean = series.rolling(window=window, min_periods=3).mean()
|
||||
std = series.rolling(window=window, min_periods=3).std(ddof=0)
|
||||
z = (series - mean) / std
|
||||
z = z.replace([np.inf, -np.inf], np.nan)
|
||||
return z
|
||||
|
||||
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
||||
df = dataframe
|
||||
|
||||
# SMA(5)
|
||||
df['sma5'] = df['close'].rolling(5, min_periods=1).mean()
|
||||
|
||||
# Absolute derivatives
|
||||
df['sma5_d1'] = df['sma5'].diff().rolling(5).mean()
|
||||
df['sma5_d2'] = df['sma5_d1'].diff().rolling(5).mean()
|
||||
|
||||
# Relative derivatives (percentage-like)
|
||||
eps = 1e-9
|
||||
df['sma5_d1_rel'] = df['sma5_d1'] / (df['sma5'].shift(1).replace(0, np.nan) + eps)
|
||||
df['sma5_d2_rel'] = df['sma5_d2'] / (df['sma5'].shift(2).replace(0, np.nan) + eps)
|
||||
|
||||
# Clip micro-noise
|
||||
df.loc[df['sma5_d1_rel'].abs() < self.min_relative_d1, 'sma5_d1_rel'] = 0.0
|
||||
df.loc[df['sma5_d2_rel'].abs() < self.min_relative_d1, 'sma5_d2_rel'] = 0.0
|
||||
|
||||
# Z-scores on relative derivatives
|
||||
df['z_d1'] = self._zscore(df['sma5_d1_rel'], self.z_window)
|
||||
df['z_d2'] = self._zscore(df['sma5_d2_rel'], self.z_window)
|
||||
|
||||
# Smoothing z-scores with EWM to reduce jitter
|
||||
df['z_d1_smooth'] = df['z_d1'].ewm(span=self.ewm_span, adjust=False).mean()
|
||||
df['z_d2_smooth'] = df['z_d2'].ewm(span=self.ewm_span, adjust=False).mean()
|
||||
|
||||
# Prepare marker columns (for plots). They will be filled in populate_entry_trend/populate_exit_trend
|
||||
df['enter_long'] = 0
|
||||
df['exit_long'] = 0
|
||||
|
||||
return df
|
||||
|
||||
def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
||||
df = dataframe.copy()
|
||||
|
||||
# Use last closed candle for signals -> shift(1)
|
||||
cond_entry = (
|
||||
(df['z_d1'] > self.entry_z1) &
|
||||
(df['z_d2'] > self.entry_z2) &
|
||||
(df['volume'].shift(1) > self.min_volume)
|
||||
)
|
||||
|
||||
df.loc[cond_entry, 'enter_long'] = 1
|
||||
# Ensure others are explicitly zero (for clean plotting)
|
||||
df.loc[~cond_entry, 'enter_long'] = 0
|
||||
|
||||
return df
|
||||
|
||||
def custom_exit(self, pair: str, trade: Trade, current_time, current_rate, current_profit, **kwargs) -> \
|
||||
Optional[str]:
|
||||
"""
|
||||
Exit policy (mode C - trailing large):
|
||||
- Must detect inversion: z_d1_smooth < 0 on last closed candle
|
||||
- Compute highest close since trade entry (inclusive)
|
||||
- If price has retraced >= trailing_stop_pct from that highest point and we're in inversion -> exit
|
||||
"""
|
||||
|
||||
df, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe)
|
||||
last = df.iloc[-1].squeeze()
|
||||
|
||||
z1 = last.get('z_d1_smooth', None)
|
||||
if z1 is None:
|
||||
return None
|
||||
|
||||
# Only consider exits when inversion detected (z1 < 0)
|
||||
inversion = (z1 < 0)
|
||||
|
||||
if not inversion:
|
||||
return None
|
||||
|
||||
# If we don't have profit info, be conservative
|
||||
if current_profit is None:
|
||||
return None
|
||||
|
||||
# Determine highest close since entry
|
||||
highest_since_entry = None
|
||||
try:
|
||||
# trade.open_date_utc is available: find rows after that timestamp
|
||||
# df.index is expected to be pd.DatetimeIndex in UTC or local; convert safely
|
||||
if hasattr(trade, 'open_date_utc') and trade.open_date_utc:
|
||||
# pandas comparison: ensure same tz awareness
|
||||
entry_time = pd.to_datetime(trade.open_date_utc)
|
||||
# select rows with index >= entry_time
|
||||
mask = df.index >= entry_time
|
||||
if mask.any():
|
||||
highest_since_entry = df.loc[mask, 'close'].max()
|
||||
# fallback: use trade.open_rate or the max over full df
|
||||
except Exception as e:
|
||||
logger.debug(f"Couldn't compute highest_since_entry from open_date_utc: {e}")
|
||||
|
||||
if highest_since_entry is None:
|
||||
# fallback: use the maximum close in the entire provided dataframe slice
|
||||
highest_since_entry = df['close'].max() if not df['close'].empty else current_rate
|
||||
|
||||
# Calculate retracement ratio from the highest
|
||||
if highest_since_entry and highest_since_entry > 0:
|
||||
retrace = 1.0 - (current_rate / highest_since_entry)
|
||||
else:
|
||||
retrace = 0.0
|
||||
|
||||
# Exit if:
|
||||
# - currently in profit AND
|
||||
# - retracement >= trailing_stop_pct (i.e. price has fallen enough from top since entry) AND
|
||||
# - inversion detected (z1 < 0)
|
||||
if (current_profit > 0) and (retrace >= self.trailing_stop_pct):
|
||||
# Mark the dataframe for plotting (if possible)
|
||||
# Note: freqtrade expects strategies to set exit flags in populate_exit_trend,
|
||||
# but we set exit via custom_exit return reason; plotting will read exit_long if populated.
|
||||
return "zscore"
|
||||
|
||||
# Otherwise, do not exit yet
|
||||
return None
|
||||
|
||||
def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
||||
"""
|
||||
For plotting only: mark exit points where our logic would trigger.
|
||||
This is approximate: we mark an exit when z_d1_smooth < 0 and the price has retraced >= trailing_stop_pct
|
||||
based on the available dataframe window (best-effort).
|
||||
"""
|
||||
df = dataframe
|
||||
# df['exit_long'] = 0
|
||||
#
|
||||
# # compute highest close since each possible entry (best-effort: use rolling max up to current index)
|
||||
# rolling_max = df['close'].cummax()
|
||||
#
|
||||
# # retracement relative to rolling max
|
||||
# retrace = 1.0 - (df['close'] / rolling_max.replace(0, np.nan))
|
||||
#
|
||||
# # mark exits where inversion and retrace >= threshold
|
||||
# cond_exit = (df['z_d1_smooth'] < 0) & (retrace >= self.trailing_stop_pct)
|
||||
# # shift by 0: we mark the candle where the exit condition appears
|
||||
# df.loc[cond_exit, 'exit_long'] = 1
|
||||
|
||||
return df
|
||||
633
Simple_01.py
Normal file
633
Simple_01.py
Normal file
@@ -0,0 +1,633 @@
|
||||
# sma_zscore_trailing_dca.py
|
||||
from freqtrade.strategy.interface import IStrategy
|
||||
from freqtrade.persistence import Trade
|
||||
from pandas import DataFrame
|
||||
import pandas as pd
|
||||
import numpy as np
|
||||
from typing import Optional
|
||||
import logging
|
||||
from datetime import timedelta, datetime
|
||||
import talib.abstract as talib
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
class Simple_01(IStrategy):
|
||||
"""
|
||||
SMA z-score derivative strategy with trailing exit and intelligent DCA (large pullback).
|
||||
- timeframe: 1h
|
||||
- sma5, relative derivatives, z-score normalization (rolling z over z_window)
|
||||
- smoothing: ewm(span=5) on z-scores
|
||||
- entry: z_d1_smooth > entry_z1 AND z_d2_smooth > entry_z2
|
||||
- exit: inversion (z_d1_smooth < 0) AND retrace from highest since entry >= trailing_stop_pct
|
||||
- adjust_trade_position: add to position on controlled pullback (large = 4-6%)
|
||||
"""
|
||||
|
||||
timeframe = "1h"
|
||||
startup_candle_count = 24
|
||||
# Risk mgmt (we handle exit in custom_exit)
|
||||
minimal_roi = {"0": 0.99}
|
||||
stoploss = -0.99
|
||||
use_custom_exit = True
|
||||
position_adjustment_enable = True
|
||||
|
||||
columns_logged = False
|
||||
|
||||
# Parameters
|
||||
z_window = 10 # window for rolling mean/std to compute zscore
|
||||
entry_z1 = 0.1 # threshold on z-score of first derivative
|
||||
entry_z2 = 0 # threshold on z-score of second derivative
|
||||
min_volume = 0.0 # minimal volume to accept an entry
|
||||
min_relative_d1 = 1e-6 # clip tiny d1 relative values to reduce noise
|
||||
|
||||
# Trailing parameters for "large" trailing (exit)
|
||||
trailing_stop_pct = 0.01 # 5% retracement from highest since entry
|
||||
|
||||
# Smoothing for z-scores
|
||||
ewm_span = 5
|
||||
|
||||
# DCA intelligent (adjust_trade_position) parameters for "large" pullback
|
||||
dca_enabled = True
|
||||
# Pullback bounds (large): allow adding when retrace is between 4% and 6%
|
||||
dca_pullback_min = 0.01
|
||||
dca_pullback_max = 0.02
|
||||
# Maximum number of adds per trade (to avoid infinite pyramiding)
|
||||
dca_max_adds = 8
|
||||
# Percentage of base position to add on each reinforcement (50% of original size by default)
|
||||
dca_add_ratio = 0.5
|
||||
# Require momentum still positive to add
|
||||
dca_require_z1_positive = True
|
||||
dca_require_z2_positive = True
|
||||
# Do not add if current_profit < min_profit_to_add (avoid averaging down when deep in loss)
|
||||
min_profit_to_add = -0.02 # allow small loss but not big drawdown
|
||||
|
||||
pairs = {
|
||||
pair: {
|
||||
"first_buy": 0,
|
||||
"last_buy": 0.0,
|
||||
"first_amount": 0.0,
|
||||
"last_min": 999999999999999.5,
|
||||
"last_max": 0,
|
||||
"trade_info": {},
|
||||
"max_touch": 0.0,
|
||||
"last_sell": 0.0,
|
||||
'count_of_buys': 0,
|
||||
'current_profit': 0,
|
||||
'expected_profit': 0,
|
||||
"last_candle": {},
|
||||
"last_trade": None,
|
||||
"last_count_of_buys": 0,
|
||||
'base_stake_amount': 0,
|
||||
'stop_buy': False,
|
||||
'last_date': 0,
|
||||
'stop': False,
|
||||
'max_profit': 0,
|
||||
'last_palier_index': -1,
|
||||
'total_amount': 0,
|
||||
'has_gain': 0,
|
||||
'force_sell': False,
|
||||
'force_buy': False
|
||||
}
|
||||
for pair in ["BTC/USDC", "ETH/USDC", "DOGE/USDC", "XRP/USDC", "SOL/USDC",
|
||||
"BTC/USDT", "ETH/USDT", "DOGE/USDT", "XRP/USDT", "SOL/USDT"]
|
||||
}
|
||||
|
||||
# Plot config
|
||||
plot_config = {
|
||||
"main_plot": {
|
||||
"close": {"color": "blue"},
|
||||
"sma5": {"color": "orange"},
|
||||
},
|
||||
"subplots": {
|
||||
"slope_and_accel": {
|
||||
"z_d1_smooth": {"color": "green"},
|
||||
"z_d2_smooth": {"color": "red"},
|
||||
},
|
||||
"sma_deriv": {
|
||||
"sma5_deriv1_rel": {"color": "green"},
|
||||
"sma5_deriv2_rel": {"color": "red"},
|
||||
},
|
||||
"rsi": {
|
||||
"rsi": {"color": "blue"}
|
||||
}
|
||||
|
||||
},
|
||||
"markers": [
|
||||
{"type": "buy", "column": "enter_long", "marker": "^", "color": "green", "markersize": 10},
|
||||
{"type": "sell", "column": "exit_long", "marker": "v", "color": "red", "markersize": 10},
|
||||
],
|
||||
}
|
||||
|
||||
def informative_pairs(self):
|
||||
return []
|
||||
|
||||
def _zscore(self, series: pd.Series, window: int) -> pd.Series:
|
||||
mean = series.rolling(window=window, min_periods=3).mean()
|
||||
std = series.rolling(window=window, min_periods=3).std(ddof=0)
|
||||
z = (series - mean) / std
|
||||
z = z.replace([np.inf, -np.inf], np.nan)
|
||||
return z
|
||||
|
||||
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
||||
df = dataframe
|
||||
|
||||
# SMA(5)
|
||||
df['sma5'] = df['close'].rolling(5, min_periods=1).mean()
|
||||
|
||||
# Absolute derivatives
|
||||
df['sma5_deriv1'] = df['sma5'].diff()
|
||||
df['sma5_deriv2'] = df['sma5_deriv1'].diff()
|
||||
|
||||
# Relative derivatives (percentage-like)
|
||||
eps = 1e-9
|
||||
df['sma5_deriv1_rel'] = df['sma5_deriv1'] / (df['sma5'].shift(1).replace(0, np.nan) + eps)
|
||||
df['sma5_deriv2_rel'] = df['sma5_deriv2'] / (df['sma5'].shift(2).replace(0, np.nan) + eps)
|
||||
|
||||
# Clip micro-noise
|
||||
df.loc[df['sma5_deriv1_rel'].abs() < self.min_relative_d1, 'sma5_deriv1_rel'] = 0.0
|
||||
df.loc[df['sma5_deriv2_rel'].abs() < self.min_relative_d1, 'sma5_deriv2_rel'] = 0.0
|
||||
|
||||
# Z-scores on relative derivatives
|
||||
df['z_d1'] = self._zscore(df['sma5_deriv1_rel'], self.z_window)
|
||||
df['z_d2'] = self._zscore(df['sma5_deriv2_rel'], self.z_window)
|
||||
|
||||
# Smoothing z-scores with EWM to reduce jitter
|
||||
df['z_d1_smooth'] = df['z_d1'].ewm(span=self.ewm_span, adjust=False).mean()
|
||||
df['z_d2_smooth'] = df['z_d2'].ewm(span=self.ewm_span, adjust=False).mean()
|
||||
|
||||
# Prepare marker columns (for plots)
|
||||
df['enter_long'] = 0
|
||||
df['exit_long'] = 0
|
||||
df['rsi'] = talib.RSI(df['close'], timeperiod=14)
|
||||
df['max_rsi_12'] = talib.MAX(df['rsi'], timeperiod=12)
|
||||
df['min_rsi_12'] = talib.MIN(df['rsi'], timeperiod=12)
|
||||
# self.calculeDerivees(df, 'rsi', horizon=12)
|
||||
|
||||
return df
|
||||
|
||||
def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
||||
df = dataframe
|
||||
|
||||
# Use last closed candle for signals -> shift(1)
|
||||
cond_entry = (
|
||||
(df['z_d1_smooth'] > self.entry_z1) &
|
||||
(df['z_d2_smooth'] > self.entry_z2) &
|
||||
(df['max_rsi_12'] < 70) &
|
||||
(df['volume'] > self.min_volume)
|
||||
)
|
||||
|
||||
df.loc[cond_entry, 'enter_long'] = 1
|
||||
df.loc[~cond_entry, 'enter_long'] = 0
|
||||
|
||||
return df
|
||||
|
||||
def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
||||
df = dataframe
|
||||
# df['exit_long'] = 0
|
||||
#
|
||||
# # compute rolling max (best-effort for plotting)
|
||||
# rolling_max = df['close'].cummax()
|
||||
# retrace = 1.0 - (df['close'] / rolling_max.replace(0, np.nan))
|
||||
#
|
||||
# cond_exit = (df['z_d1_smooth'] < 0) & (retrace >= self.trailing_stop_pct)
|
||||
# df.loc[cond_exit, 'exit_long'] = 1
|
||||
|
||||
return df
|
||||
|
||||
def confirm_trade_exit(self, pair: str, trade: Trade, order_type: str, amount: float, rate: float,
|
||||
time_in_force: str,
|
||||
exit_reason: str, current_time, **kwargs, ) -> bool:
|
||||
# allow_to_sell = (minutes > 30)
|
||||
dataframe, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe)
|
||||
last_candle = dataframe.iloc[-1].squeeze()
|
||||
|
||||
force = self.pairs[pair]['force_sell']
|
||||
allow_to_sell = True #(last_candle['percent'] < 0) #or force
|
||||
|
||||
minutes = int(round((current_time - trade.date_last_filled_utc).total_seconds() / 60, 0))
|
||||
|
||||
if allow_to_sell:
|
||||
self.trades = list()
|
||||
self.pairs[pair]['last_count_of_buys'] = trade.nr_of_successful_entries # self.pairs[pair]['count_of_buys']
|
||||
self.pairs[pair]['last_sell'] = rate
|
||||
self.pairs[pair]['last_trade'] = trade
|
||||
self.pairs[pair]['last_candle'] = last_candle
|
||||
self.trades = list()
|
||||
dispo = round(self.wallets.get_available_stake_amount())
|
||||
print(f"Sell {pair} {current_time} {exit_reason} dispo={dispo} amount={amount} rate={rate} open_rate={trade.open_rate}")
|
||||
self.log_trade(
|
||||
last_candle=last_candle,
|
||||
date=current_time,
|
||||
action="🟥Sell " + str(minutes),
|
||||
pair=pair,
|
||||
trade_type=exit_reason,
|
||||
rate=last_candle['close'],
|
||||
dispo=dispo,
|
||||
profit=round(trade.calc_profit(rate, amount), 2)
|
||||
)
|
||||
self.pairs[pair]['max_profit'] = 0
|
||||
self.pairs[pair]['force_sell'] = False
|
||||
self.pairs[pair]['has_gain'] = 0
|
||||
self.pairs[pair]['current_profit'] = 0
|
||||
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_date'] = current_time
|
||||
self.pairs[pair]['last_palier_index'] = -1
|
||||
self.pairs[pair]['last_trade'] = trade
|
||||
self.pairs[pair]['current_trade'] = None
|
||||
|
||||
return (allow_to_sell) | (exit_reason == 'force_exit')
|
||||
|
||||
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:
|
||||
|
||||
minutes = 0
|
||||
if self.pairs[pair]['last_date'] != 0:
|
||||
minutes = round(int((current_time - self.pairs[pair]['last_date']).total_seconds() / 60))
|
||||
|
||||
dataframe, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe)
|
||||
last_candle = dataframe.iloc[-1].squeeze()
|
||||
last_candle_2 = dataframe.iloc[-2].squeeze()
|
||||
last_candle_3 = dataframe.iloc[-3].squeeze()
|
||||
# val = self.getProbaHausse144(last_candle)
|
||||
|
||||
# allow_to_buy = True #(not self.stop_all) #& (not self.all_down)
|
||||
allow_to_buy = not self.pairs[pair]['stop'] # and val > self.buy_val.value #not last_candle['tendency'] in ('B-', 'B--') # (rate <= float(limit)) | (entry_tag == 'force_entry')
|
||||
|
||||
# force = self.pairs[pair]['force_buy']
|
||||
# if self.pairs[pair]['force_buy']:
|
||||
# self.pairs[pair]['force_buy'] = False
|
||||
# allow_to_buy = True
|
||||
# else:
|
||||
# if not self.should_enter_trade(pair, last_candle, current_time):
|
||||
# allow_to_buy = False
|
||||
|
||||
if allow_to_buy:
|
||||
self.trades = list()
|
||||
self.pairs[pair]['first_buy'] = rate
|
||||
self.pairs[pair]['last_buy'] = rate
|
||||
self.pairs[pair]['max_touch'] = last_candle['close']
|
||||
self.pairs[pair]['last_candle'] = last_candle
|
||||
self.pairs[pair]['count_of_buys'] = 1
|
||||
self.pairs[pair]['current_profit'] = 0
|
||||
self.pairs[pair]['last_palier_index'] = -1
|
||||
self.pairs[pair]['last_max'] = max(last_candle['close'], self.pairs[pair]['last_max'])
|
||||
self.pairs[pair]['last_min'] = min(last_candle['close'], self.pairs[pair]['last_min'])
|
||||
|
||||
dispo = round(self.wallets.get_available_stake_amount())
|
||||
self.printLineLog()
|
||||
|
||||
stake_amount = self.adjust_stake_amount(pair, last_candle)
|
||||
|
||||
self.pairs[pair]['total_amount'] = stake_amount
|
||||
|
||||
self.log_trade(
|
||||
last_candle=last_candle,
|
||||
date=current_time,
|
||||
action=("🟩Buy" if allow_to_buy else "Canceled") + " " + str(minutes),
|
||||
pair=pair,
|
||||
rate=rate,
|
||||
dispo=dispo,
|
||||
profit=0,
|
||||
trade_type=entry_tag,
|
||||
buys=1,
|
||||
stake=round(stake_amount, 2)
|
||||
)
|
||||
|
||||
return allow_to_buy
|
||||
|
||||
def custom_exit(self, pair: str, trade: Trade, current_time, current_rate, current_profit, **kwargs) -> Optional[str]:
|
||||
df, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe)
|
||||
last_candle = df.iloc[-1].squeeze()
|
||||
|
||||
self.pairs[pair]['last_max'] = max(last_candle['close'], self.pairs[pair]['last_max'])
|
||||
self.pairs[pair]['last_min'] = min(last_candle['close'], self.pairs[pair]['last_min'])
|
||||
self.pairs[pair]['current_trade'] = trade
|
||||
count_of_buys = trade.nr_of_successful_entries
|
||||
|
||||
profit = round(current_profit * trade.stake_amount, 1)
|
||||
self.pairs[pair]['max_profit'] = max(self.pairs[pair]['max_profit'], profit)
|
||||
max_profit = self.pairs[pair]['max_profit']
|
||||
baisse = 0
|
||||
if profit > 0:
|
||||
baisse = 100 * abs(max_profit - profit) / max_profit
|
||||
mx = max_profit / 5
|
||||
self.pairs[pair]['count_of_buys'] = count_of_buys
|
||||
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 = (current_time - trade.date_last_filled_utc).total_seconds() / 3600.0
|
||||
|
||||
if hours % 4 == 0:
|
||||
self.log_trade(
|
||||
last_candle=last_candle,
|
||||
date=current_time,
|
||||
action="🔴 CURRENT" if self.pairs[pair]['stop'] else "🟢 CURRENT",
|
||||
dispo=dispo,
|
||||
pair=pair,
|
||||
rate=last_candle['close'],
|
||||
trade_type='',
|
||||
profit=profit,
|
||||
buys='',
|
||||
stake=0
|
||||
)
|
||||
|
||||
z1 = last_candle.get('z_d1_smooth', None)
|
||||
if z1 is None:
|
||||
return None
|
||||
|
||||
if z1 >= 0:
|
||||
return None
|
||||
|
||||
if current_profit is None:
|
||||
return None
|
||||
|
||||
# highest close since entry
|
||||
highest_since_entry = self.pairs[trade.pair]['max_touch']
|
||||
# try:
|
||||
# if hasattr(trade, 'open_date_utc') and trade.open_date_utc:
|
||||
# entry_time = pd.to_datetime(trade.open_date_utc)
|
||||
# mask = df.index >= entry_time
|
||||
# if mask.any():
|
||||
# highest_since_entry = df.loc[mask, 'close'].max()
|
||||
# except Exception as e:
|
||||
# logger.debug(f"Couldn't compute highest_since_entry: {e}")
|
||||
#
|
||||
# if highest_since_entry is None:
|
||||
# highest_since_entry = df['close'].max() if not df['close'].empty else current_rate
|
||||
|
||||
if highest_since_entry and highest_since_entry > 0:
|
||||
retrace = 1.0 - (current_rate / highest_since_entry)
|
||||
else:
|
||||
retrace = 0.0
|
||||
z1 = last_candle.get('z_d1_smooth', None)
|
||||
z2 = last_candle.get('z_d2_smooth', None)
|
||||
|
||||
if (current_profit > 0) and (current_profit >= self.trailing_stop_pct) and last_candle['sma5_deriv1'] < -0.002:
|
||||
return str(count_of_buys) + '_' + "zscore"
|
||||
|
||||
self.pairs[pair]['max_touch'] = max(last_candle['close'], self.pairs[pair]['max_touch'])
|
||||
|
||||
return None
|
||||
|
||||
def adjust_stake_amount(self, pair: str, last_candle: DataFrame):
|
||||
# Calculer le minimum des 14 derniers jours
|
||||
return self.config.get('stake_amount')
|
||||
|
||||
def adjust_trade_position(self, trade: Trade, current_time: datetime,
|
||||
current_rate: float, current_profit: float, min_stake: float,
|
||||
max_stake: float, **kwargs):
|
||||
"""
|
||||
DCA intelligent (mode C - 'large'):
|
||||
- Only add if:
|
||||
* DCA is enabled
|
||||
* number of adds done so far < dca_max_adds
|
||||
* retracement since highest_since_entry is between dca_pullback_min and dca_pullback_max
|
||||
* momentum still positive (z_d1_smooth, z_d2_smooth) if required
|
||||
* current_profit >= min_profit_to_add (avoid averaging down into large loss)
|
||||
- Returns a dict describing the desired order for Freqtrade to place (common format).
|
||||
Example returned dict: {'type': 'market', 'amount': 0.01}
|
||||
"""
|
||||
if not self.dca_enabled:
|
||||
return None
|
||||
pair = trade.pair
|
||||
|
||||
# Basic guards
|
||||
if current_profit is None:
|
||||
current_profit = 0.0
|
||||
|
||||
# Do not add if we're already deeply in loss
|
||||
if current_profit < self.min_profit_to_add:
|
||||
return None
|
||||
|
||||
df, _ = self.dp.get_analyzed_dataframe(trade.pair, self.timeframe)
|
||||
last_candle = df.iloc[-1].squeeze()
|
||||
|
||||
# Compute highest close since entry
|
||||
highest_since_entry = self.pairs[trade.pair]['last_buy']
|
||||
|
||||
last = df.iloc[-1]
|
||||
z1 = last.get('z_d1_smooth', None)
|
||||
z2 = last.get('z_d2_smooth', None)
|
||||
|
||||
# Count how many adds have been done for this trade.
|
||||
# Trade.extra might contain meta; otherwise try trade.tags or use trade.open_rate/amount heuristics.
|
||||
adds_done = trade.nr_of_successful_entries
|
||||
# Calculate retracement since the highest
|
||||
retrace = 0.0
|
||||
if highest_since_entry and highest_since_entry > 0:
|
||||
retrace = (last['close'] - highest_since_entry) / highest_since_entry
|
||||
|
||||
# logger.info(f"{pair} {current_rate} {current_time} {highest_since_entry} add: retrace={retrace:.4f}, adds_done={adds_done} z1={z1} z2={z2}")
|
||||
|
||||
# Enforce momentum requirements if requested
|
||||
if self.dca_require_z1_positive and (z1 is None or z1 <= 0):
|
||||
return None
|
||||
if self.dca_require_z2_positive and (z2 is None or z2 <= 0):
|
||||
return None
|
||||
|
||||
#
|
||||
# try:
|
||||
# meta = getattr(trade, 'meta', None) or {}
|
||||
# adds_done = int(meta.get('adds_done', 0))
|
||||
# except Exception:
|
||||
# adds_done = 0
|
||||
|
||||
if adds_done >= self.dca_max_adds:
|
||||
return None
|
||||
|
||||
# try:
|
||||
# if hasattr(trade, 'open_date_utc') and trade.open_date_utc:
|
||||
# entry_time = pd.to_datetime(trade.open_date_utc)
|
||||
# mask = df.index >= entry_time
|
||||
# if mask.any():
|
||||
# highest_since_entry = df.loc[mask, 'close'].max()
|
||||
# except Exception as e:
|
||||
# logger.debug(f"adjust_trade_position: couldn't compute highest_since_entry: {e}")
|
||||
#
|
||||
# if highest_since_entry is None:
|
||||
# highest_since_entry = df['close'].max() if not df['close'].empty else current_rate
|
||||
|
||||
# Check if retrace is inside the allowed DCA window (large)
|
||||
if ((retrace >= self.dca_pullback_min) and (retrace <= self.dca_pullback_max)):
|
||||
# Determine amount to add: a fraction of the original trade amount
|
||||
# Try to get trade.amount (base asset amount). If not available, fall back to stake percentage
|
||||
add_amount = None
|
||||
try:
|
||||
base_amount = self.config.get('stake_amount')
|
||||
if base_amount:
|
||||
add_amount = base_amount * self.dca_add_ratio
|
||||
else:
|
||||
# Fallback: attempt to compute amount from trade.open_rate and desired quote stake
|
||||
# We'll propose to use a fraction of current rate worth (this is best-effort)
|
||||
add_amount = None
|
||||
except Exception:
|
||||
add_amount = None
|
||||
|
||||
# If we couldn't compute an absolute amount, propose a relative size via a suggested stake (user must map)
|
||||
if add_amount is None:
|
||||
# Return a suggested instruction; adapt according to your freqtrade version.
|
||||
suggested = {
|
||||
'type': 'market',
|
||||
'amount': None, # caller should compute actual amount from stake management
|
||||
'note': f'suggest_add_ratio={self.dca_add_ratio}'
|
||||
}
|
||||
# logger.info(f"{pair} {current_rate} DCA suggestion (no absolute amount): retrace={retrace:.4f}, adds_done={adds_done}")
|
||||
return None
|
||||
|
||||
dispo = round(self.wallets.get_available_stake_amount())
|
||||
trade_type = last_candle['enter_tag'] if last_candle['enter_long'] == 1 else 'pct48'
|
||||
self.pairs[trade.pair]['count_of_buys'] += 1
|
||||
self.pairs[pair]['total_amount'] += add_amount
|
||||
self.log_trade(
|
||||
last_candle=last_candle,
|
||||
date=current_time,
|
||||
action="🟧 Loss -",
|
||||
dispo=dispo,
|
||||
pair=trade.pair,
|
||||
rate=current_rate,
|
||||
trade_type=trade_type,
|
||||
profit=round(current_profit * trade.stake_amount, 1),
|
||||
buys=trade.nr_of_successful_entries + 1,
|
||||
stake=round(add_amount, 2)
|
||||
)
|
||||
|
||||
self.pairs[trade.pair]['last_buy'] = current_rate
|
||||
self.pairs[trade.pair]['max_touch'] = last_candle['close']
|
||||
self.pairs[trade.pair]['last_candle'] = last_candle
|
||||
|
||||
# All checks passed -> create market order instruction
|
||||
# logger.info(f"{pair} {current_rate} {current_time} {highest_since_entry} add: retrace={retrace:.4f}, adds_done={adds_done}, add_amount={add_amount:.8f}")
|
||||
return add_amount
|
||||
|
||||
# Not in allowed retrace window -> no action
|
||||
return None
|
||||
|
||||
def getPctFirstBuy(self, pair, last_candle):
|
||||
return round((last_candle['close'] - self.pairs[pair]['first_buy']) / self.pairs[pair]['first_buy'], 3)
|
||||
|
||||
def getPctLastBuy(self, pair, last_candle):
|
||||
return round((last_candle['close'] - self.pairs[pair]['last_buy']) / self.pairs[pair]['last_buy'], 4)
|
||||
|
||||
def getPct60D(self, pair, last_candle):
|
||||
return round((last_candle['max60'] - last_candle['min60']) / last_candle['max60'], 4)
|
||||
|
||||
def getPctClose60D(self, pair, last_candle):
|
||||
if last_candle['close'] > last_candle['max12']:
|
||||
return 1
|
||||
if last_candle['close'] < last_candle['min12']:
|
||||
return 0
|
||||
return round(
|
||||
(last_candle['close'] - last_candle['min12']) / (last_candle['max12'] - last_candle['min12']), 4)
|
||||
|
||||
|
||||
def printLineLog(self):
|
||||
self.printLog(
|
||||
f"+{'-' * 18}+{'-' * 12}+{'-' * 5}+{'-' * 20}+{'-' * 9}+{'-' * 8}+{'-' * 12}+{'-' * 8}+{'-' * 13}+{'-' * 14}+{'-' * 9}{'-' * 9}+{'-' * 5}+{'-' * 7}+"
|
||||
f"{'-' * 3}"
|
||||
# "+{'-' * 3}+{'-' * 3}
|
||||
f"+{'-' * 6}+{'-' * 7}+{'-' * 5}+{'-' * 5}+{'-' * 5}+{'-' * 5}+{'-' * 5}+{'-' * 5}+"
|
||||
)
|
||||
|
||||
def printLog(self, str):
|
||||
if self.config.get('runmode') == 'hyperopt' or self.dp.runmode.value in ('hyperopt'):
|
||||
return
|
||||
if not self.dp.runmode.value in ('backtest', 'hyperopt', 'lookahead-analysis'):
|
||||
logger.info(str)
|
||||
else:
|
||||
if not self.dp.runmode.value in ('hyperopt'):
|
||||
print(str)
|
||||
|
||||
def log_trade(self, action, pair, date, trade_type=None, rate=None, dispo=None, profit=None, buys=None,
|
||||
stake=None,
|
||||
last_candle=None):
|
||||
# Couleurs ANSI de base
|
||||
RED = "\033[31m"
|
||||
GREEN = "\033[32m"
|
||||
YELLOW = "\033[33m"
|
||||
BLUE = "\033[34m"
|
||||
MAGENTA = "\033[35m"
|
||||
CYAN = "\033[36m"
|
||||
RESET = "\033[0m"
|
||||
|
||||
# Afficher les colonnes une seule fois
|
||||
if self.config.get('runmode') == 'hyperopt' or self.dp.runmode.value in ('hyperopt'):
|
||||
return
|
||||
if self.columns_logged % 10 == 0:
|
||||
self.printLog(
|
||||
f"| {'Date':<16} | {'Action':<10} |{'Pair':<5}| {'Trade Type':<18} |{'Rate':>8} | {'Dispo':>6} | {'Profit':>8} | {'Pct':>6} | {'max_touch':>11} | {'last_lost':>12} | {'last_max':>7}| {'last_max':>7}|{'Buys':>5}| {'Stake':>5} |"
|
||||
f"Tdc|{'val':>6}| RSI |s201d|s5_1d|s5_2d|s51h|s52h"
|
||||
)
|
||||
self.printLineLog()
|
||||
df = pd.DataFrame.from_dict(self.pairs, orient='index')
|
||||
colonnes_a_exclure = ['last_candle', 'last_trade', 'last_palier_index',
|
||||
'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']
|
||||
|
||||
print(df_filtered)
|
||||
|
||||
self.columns_logged += 1
|
||||
date = str(date)[:16] if date else "-"
|
||||
limit = None
|
||||
# if buys is not None:
|
||||
# limit = round(last_rate * (1 - self.fibo[buys] / 100), 4)
|
||||
|
||||
rsi = ''
|
||||
rsi_pct = ''
|
||||
sma5_1d = ''
|
||||
sma5_1h = ''
|
||||
|
||||
sma5 = str(sma5_1d) + ' ' + str(sma5_1h)
|
||||
|
||||
last_lost = '' #self.getLastLost(last_candle, pair)
|
||||
|
||||
if buys is None:
|
||||
buys = ''
|
||||
|
||||
max_touch = '' # round(last_candle['max12'], 1) #round(self.pairs[pair]['max_touch'], 1)
|
||||
pct_max = '' #self.getPctFirstBuy(pair, last_candle)
|
||||
|
||||
total_counts = str(buys) + '/' + str(
|
||||
sum(pair_data['count_of_buys'] for pair_data in self.pairs.values()))
|
||||
|
||||
dist_max = '' #self.getDistMax(last_candle, pair)
|
||||
val = 0 #self.getProbaHausseSma5d(last_candle)
|
||||
|
||||
pct60 = 0 #round(100 * self.getPct60D(pair, last_candle), 2)
|
||||
|
||||
color = GREEN if profit > 0 else RED
|
||||
# color_sma20 = GREEN if last_candle['sma20_deriv1'] > 0 else RED
|
||||
# color_sma5 = GREEN if last_candle['mid_smooth_5_deriv1'] > 0 else RED
|
||||
# color_sma5_2 = GREEN if last_candle['mid_smooth_5_deriv2'] > 0 else RED
|
||||
# color_sma5_1h = GREEN if last_candle['sma5_deriveriv1'] > 0 else RED
|
||||
# color_sma5_2h = GREEN if last_candle['sma5_deriveriv2'] > 0 else RED
|
||||
|
||||
last_max = int(self.pairs[pair]['last_max']) if self.pairs[pair]['last_max'] > 1 else round(
|
||||
self.pairs[pair]['last_max'], 3)
|
||||
last_min = int(self.pairs[pair]['last_min']) if self.pairs[pair]['last_min'] > 1 else round(
|
||||
self.pairs[pair]['last_min'], 3)
|
||||
|
||||
profit = str(profit) + '/' + str(round(self.pairs[pair]['max_profit'], 2))
|
||||
|
||||
# 🟢 Dérivée 1 > 0 et dérivée 2 > 0: tendance haussière qui s’accélère.
|
||||
# 🟡 Dérivée 1 > 0 et dérivée 2 < 0: tendance haussière qui ralentit → essoufflement potentiel.
|
||||
# 🔴 Dérivée 1 < 0 et dérivée 2 < 0: tendance baissière qui s’accélère.
|
||||
# 🟠 Dérivée 1 < 0 et dérivée 2 > 0: tendance baissière qui ralentit → possible bottom.
|
||||
|
||||
# tdc last_candle['tendency_12']
|
||||
self.printLog(
|
||||
f"| {date:<16} |{action:<10} | {pair[0:3]:<3} | {trade_type or '-':<18} |{rate or '-':>9}| {dispo or '-':>6} "
|
||||
f"|{color}{profit or '-':>10}{RESET}| {pct_max or '-':>6} | {round(self.pairs[pair]['max_touch'], 2) or '-':>11} | {last_lost or '-':>12} "
|
||||
f"| {last_max or '-':>7} | {last_min or '-':>7} |{total_counts or '-':>5}|{stake or '-':>7}"
|
||||
f"|{'-':>3}|"
|
||||
f"{round(val, 1) or '-' :>6}|"
|
||||
# f"{round(last_candle['rsi'], 0):>7}|{color_sma20}{round(last_candle['sma20_deriv1'], 2):>5}{RESET}"
|
||||
# f"|{color_sma5}{round(last_candle['mid_smooth_5_deriv1'], 2):>5}{RESET}|{color_sma5_2}{round(last_candle['mid_smooth_5_deriv2'], 2):>5}{RESET}"
|
||||
# f"|{color_sma5_1h}{round(last_candle['sma5_deriveriv1'], 2):>5}{RESET}|{color_sma5_2h}{round(last_candle['sma5_deriveriv2'], 2):>5}{RESET}"
|
||||
# f"|{last_candle['min60']}|{last_candle['max60']}"
|
||||
)
|
||||
@@ -1,7 +1,7 @@
|
||||
import numpy as np
|
||||
import talib.abstract as ta
|
||||
import freqtrade.vendor.qtpylib.indicators as qtpylib
|
||||
import arrow
|
||||
# import arrow
|
||||
|
||||
from freqtrade.strategy import (IStrategy, merge_informative_pair, stoploss_from_open,
|
||||
IntParameter, DecimalParameter, CategoricalParameter)
|
||||
@@ -162,7 +162,7 @@ def SSLChannels(dataframe, length=10, mode='sma'):
|
||||
df['smaLow'] = df['low'].rolling(length).mean()
|
||||
|
||||
df['hlv'] = np.where(df['close'] > df['smaHigh'], 1,
|
||||
np.where(df['close'] < df['smaLow'], -1, np.NAN))
|
||||
np.where(df['close'] < df['smaLow'], -1, np.nan))
|
||||
df['hlv'] = df['hlv'].ffill()
|
||||
|
||||
df['sslDown'] = np.where(df['hlv'] < 0, df['smaHigh'], df['smaLow'])
|
||||
@@ -180,7 +180,7 @@ def SSLChannels_ATR(dataframe, length=7):
|
||||
df['ATR'] = ta.ATR(df, timeperiod=14)
|
||||
df['smaHigh'] = df['high'].rolling(length).mean() + df['ATR']
|
||||
df['smaLow'] = df['low'].rolling(length).mean() - df['ATR']
|
||||
df['hlv'] = np.where(df['close'] > df['smaHigh'], 1, np.where(df['close'] < df['smaLow'], -1, np.NAN))
|
||||
df['hlv'] = np.where(df['close'] > df['smaHigh'], 1, np.where(df['close'] < df['smaLow'], -1, np.nan))
|
||||
df['hlv'] = df['hlv'].ffill()
|
||||
df['sslDown'] = np.where(df['hlv'] < 0, df['smaHigh'], df['smaLow'])
|
||||
df['sslUp'] = np.where(df['hlv'] < 0, df['smaLow'], df['smaHigh'])
|
||||
|
||||
@@ -164,7 +164,7 @@ class Supertrend(IStrategy):
|
||||
df['final_lb'].iat[i] if df[st].iat[i - 1] == df['final_lb'].iat[i - 1] and df['close'].iat[i] >= df['final_lb'].iat[i] else \
|
||||
df['final_ub'].iat[i] if df[st].iat[i - 1] == df['final_lb'].iat[i - 1] and df['close'].iat[i] < df['final_lb'].iat[i] else 0.00
|
||||
# Mark the trend direction up/down
|
||||
df[stx] = np.where((df[st] > 0.00), np.where((df['close'] < df[st]), 'down', 'up'), np.NaN)
|
||||
df[stx] = np.where((df[st] > 0.00), np.where((df['close'] < df[st]), 'down', 'up'), np.nan)
|
||||
|
||||
# Remove basic and final bands from the columns
|
||||
df.drop(['basic_ub', 'basic_lb', 'final_ub', 'final_lb'], inplace=True, axis=1)
|
||||
|
||||
@@ -487,10 +487,10 @@ class Zeus_5_1(IStrategy):
|
||||
def bot_loop_start(self, **kwargs) -> None:
|
||||
inf_tf = '5m'
|
||||
pairs = self.dp.current_whitelist()
|
||||
print("Calcul des pairs informatives")
|
||||
# print("Calcul des pairs informatives")
|
||||
for pairname in pairs:
|
||||
self.stop_buying[pairname] = True
|
||||
print("Fin Calcul des pairs informatives")
|
||||
# print("Fin Calcul des pairs informatives")
|
||||
|
||||
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:
|
||||
|
||||
@@ -491,10 +491,10 @@ class Zeus_5_2(IStrategy):
|
||||
def bot_loop_start(self, **kwargs) -> None:
|
||||
inf_tf = '5m'
|
||||
pairs = self.dp.current_whitelist()
|
||||
print("Calcul des pairs informatives")
|
||||
# print("Calcul des pairs informatives")
|
||||
for pairname in pairs:
|
||||
self.stop_buying[pairname] = True
|
||||
print("Fin Calcul des pairs informatives")
|
||||
# print("Fin Calcul des pairs informatives")
|
||||
|
||||
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:
|
||||
|
||||
@@ -487,10 +487,10 @@ class Zeus_6(IStrategy):
|
||||
def bot_loop_start(self, **kwargs) -> None:
|
||||
inf_tf = '5m'
|
||||
pairs = self.dp.current_whitelist()
|
||||
print("Calcul des pairs informatives")
|
||||
# print("Calcul des pairs informatives")
|
||||
for pairname in pairs:
|
||||
self.stop_buying[pairname] = True
|
||||
print("Fin Calcul des pairs informatives")
|
||||
# print("Fin Calcul des pairs informatives")
|
||||
|
||||
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:
|
||||
|
||||
1610
Zeus_8_1d.py
Normal file
1610
Zeus_8_1d.py
Normal file
File diff suppressed because it is too large
Load Diff
376
Zeus_8_1d_Bilan.txt
Normal file
376
Zeus_8_1d_Bilan.txt
Normal file
@@ -0,0 +1,376 @@
|
||||
BACKTESTING REPORT
|
||||
┏━━━━━━━━━━━┳━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━┓
|
||||
┃ Pair ┃ Trades ┃ Avg Profit % ┃ Tot Profit USDT ┃ Tot Profit % ┃ Avg Duration ┃ Win Draw Loss Win% ┃
|
||||
┡━━━━━━━━━━━╇━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━┩
|
||||
│ DOGE/USDT │ 20 │ 6.58 │ 234.716 │ 7.82 │ 12 days, 21:54:00 │ 20 0 0 100 │
|
||||
│ XRP/USDT │ 29 │ 4.96 │ 198.511 │ 6.62 │ 8 days, 17:43:00 │ 28 0 1 96.6 │
|
||||
│ SOL/USDT │ 23 │ 4.96 │ 159.580 │ 5.32 │ 11 days, 1:29:00 │ 22 0 1 95.7 │
|
||||
│ ETH/USDT │ 26 │ 4.12 │ 155.679 │ 5.19 │ 9 days, 20:48:00 │ 26 0 0 100 │
|
||||
│ BTC/USDT │ 23 │ 2.57 │ 76.047 │ 2.53 │ 10 days, 23:47:00 │ 22 0 1 95.7 │
|
||||
│ TOTAL │ 121 │ 4.59 │ 824.533 │ 27.48 │ 10 days, 12:59:00 │ 118 0 3 97.5 │
|
||||
└───────────┴────────┴──────────────┴─────────────────┴──────────────┴───────────────────┴────────────────────────┘
|
||||
LEFT OPEN TRADES REPORT
|
||||
┏━━━━━━━━━━━┳━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━┓
|
||||
┃ Pair ┃ Trades ┃ Avg Profit % ┃ Tot Profit USDT ┃ Tot Profit % ┃ Avg Duration ┃ Win Draw Loss Win% ┃
|
||||
┡━━━━━━━━━━━╇━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━┩
|
||||
│ ETH/USDT │ 1 │ 3.07 │ 1.533 │ 0.05 │ 2 days, 6:00:00 │ 1 0 0 100 │
|
||||
│ DOGE/USDT │ 1 │ 0.47 │ 0.741 │ 0.02 │ 2 days, 5:00:00 │ 1 0 0 100 │
|
||||
│ BTC/USDT │ 1 │ -0.13 │ -0.065 │ -0.0 │ 2 days, 7:00:00 │ 0 0 1 0 │
|
||||
│ SOL/USDT │ 1 │ -1.47 │ -0.917 │ -0.03 │ 19:00:00 │ 0 0 1 0 │
|
||||
│ XRP/USDT │ 1 │ -4.64 │ -11.192 │ -0.37 │ 54 days, 8:00:00 │ 0 0 1 0 │
|
||||
│ TOTAL │ 5 │ -0.54 │ -9.899 │ -0.33 │ 12 days, 9:00:00 │ 2 0 3 40.0 │
|
||||
└───────────┴────────┴──────────────┴─────────────────┴──────────────┴──────────────────┴────────────────────────┘
|
||||
ENTER TAG STATS
|
||||
┏━━━━━━━━━━━┳━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━┓
|
||||
┃ Enter Tag ┃ Entries ┃ Avg Profit % ┃ Tot Profit USDT ┃ Tot Profit % ┃ Avg Duration ┃ Win Draw Loss Win% ┃
|
||||
┡━━━━━━━━━━━╇━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━┩
|
||||
│ smth_12 │ 121 │ 4.59 │ 824.533 │ 27.48 │ 10 days, 12:59:00 │ 118 0 3 97.5 │
|
||||
│ TOTAL │ 121 │ 4.59 │ 824.533 │ 27.48 │ 10 days, 12:59:00 │ 118 0 3 97.5 │
|
||||
└───────────┴─────────┴──────────────┴─────────────────┴──────────────┴───────────────────┴────────────────────────┘
|
||||
EXIT REASON STATS
|
||||
┏━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━┓
|
||||
┃ Exit Reason ┃ Exits ┃ Avg Profit % ┃ Tot Profit USDT ┃ Tot Profit % ┃ Avg Duration ┃ Win Draw Loss Win% ┃
|
||||
┡━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━┩
|
||||
│ RSI_XRP_5_0_28.43 │ 1 │ 15.15 │ 71.078 │ 2.37 │ 15 days, 4:00:00 │ 1 0 0 100 │
|
||||
│ Drv3_ETH_8_0_34.72 │ 1 │ 6.36 │ 53.262 │ 1.78 │ 125 days, 19:00:00 │ 1 0 0 100 │
|
||||
│ Drv3_DOGE_6_0_46.32 │ 1 │ 10.45 │ 52.528 │ 1.75 │ 47 days, 13:00:00 │ 1 0 0 100 │
|
||||
│ Drv3_DOGE_3_0_26.01 │ 1 │ 21.51 │ 34.730 │ 1.16 │ 6 days, 1:00:00 │ 1 0 0 100 │
|
||||
│ Drv3_DOGE_3_0_39.61 │ 1 │ 14.32 │ 34.062 │ 1.14 │ 11 days, 21:00:00 │ 1 0 0 100 │
|
||||
│ Drv3_ETH_3_0_14.24 │ 1 │ 15.48 │ 26.538 │ 0.88 │ 11 days, 17:00:00 │ 1 0 0 100 │
|
||||
│ Drv3_SOL_2_0_9.03 │ 1 │ 17.25 │ 26.223 │ 0.87 │ 8 days, 1:00:00 │ 1 0 0 100 │
|
||||
│ Drv3_XRP_4_0_19.78 │ 1 │ 9.64 │ 21.919 │ 0.73 │ 9 days, 10:00:00 │ 1 0 0 100 │
|
||||
│ Drv3_SOL_3_0_31.46 │ 1 │ 10.39 │ 20.674 │ 0.69 │ 8 days, 13:00:00 │ 1 0 0 100 │
|
||||
│ Drv3_SOL_4_0_24.35 │ 1 │ 6.46 │ 20.553 │ 0.69 │ 13 days, 8:00:00 │ 1 0 0 100 │
|
||||
│ Drv3_DOGE_4_0_29.59 │ 1 │ 6.68 │ 18.794 │ 0.63 │ 16 days, 21:00:00 │ 1 0 0 100 │
|
||||
│ Drv3_DOGE_2_0_23.33 │ 1 │ 17.89 │ 18.435 │ 0.61 │ 3 days, 20:00:00 │ 1 0 0 100 │
|
||||
│ Drv3_XRP_4_0_34.21 │ 1 │ 7.03 │ 17.503 │ 0.58 │ 12 days, 1:00:00 │ 1 0 0 100 │
|
||||
│ Drv3_ETH_3_0_18.45 │ 1 │ 10.19 │ 16.852 │ 0.56 │ 7 days, 0:00:00 │ 1 0 0 100 │
|
||||
│ Drv3_BTC_8_0_37.83 │ 1 │ 3.12 │ 16.616 │ 0.55 │ 79 days, 11:00:00 │ 1 0 0 100 │
|
||||
│ Drv3_BTC_4_0_12.14 │ 1 │ 6.86 │ 15.212 │ 0.51 │ 16 days, 15:00:00 │ 1 0 0 100 │
|
||||
│ Drv3_DOGE_1_0_19.08 │ 1 │ 18.77 │ 14.063 │ 0.47 │ 4 days, 11:00:00 │ 1 0 0 100 │
|
||||
│ Drv3_XRP_1_0_20.83 │ 1 │ 26.55 │ 13.279 │ 0.44 │ 3 days, 16:00:00 │ 1 0 0 100 │
|
||||
│ Drv3_ETH_3_0_19.63 │ 1 │ 7.04 │ 13.133 │ 0.44 │ 14 days, 0:00:00 │ 1 0 0 100 │
|
||||
│ Drv3_DOGE_3_0_25.43 │ 1 │ 6.43 │ 12.901 │ 0.43 │ 12 days, 17:00:00 │ 1 0 0 100 │
|
||||
│ Drv3_DOGE_1_0_27.27 │ 1 │ 12.06 │ 12.054 │ 0.4 │ 2 days, 6:00:00 │ 1 0 0 100 │
|
||||
│ Drv3_SOL_2_0_67.31 │ 1 │ 11.51 │ 11.807 │ 0.39 │ 3 days, 13:00:00 │ 1 0 0 100 │
|
||||
│ Drv3_XRP_3_0_43.54 │ 1 │ 5.33 │ 11.803 │ 0.39 │ 46 days, 10:00:00 │ 1 0 0 100 │
|
||||
│ Drv3_SOL_1_0_11.11 │ 1 │ 12.28 │ 11.253 │ 0.38 │ 3 days, 16:00:00 │ 1 0 0 100 │
|
||||
│ Drv3_DOGE_4_0_54.81 │ 1 │ 4.36 │ 10.812 │ 0.36 │ 13 days, 15:00:00 │ 1 0 0 100 │
|
||||
│ Drv3_XRP_1_0_34.78 │ 1 │ 16.81 │ 10.484 │ 0.35 │ 2 days, 20:00:00 │ 1 0 0 100 │
|
||||
│ Drv3_DOGE_3_0_26.24 │ 1 │ 6.2 │ 10.401 │ 0.35 │ 7 days, 23:00:00 │ 1 0 0 100 │
|
||||
│ RSI_ETH_1_0_8.93 │ 1 │ 20.52 │ 10.253 │ 0.34 │ 4 days, 22:00:00 │ 1 0 0 100 │
|
||||
│ Drv3_XRP_3_0_32.89 │ 1 │ 6.37 │ 10.247 │ 0.34 │ 6 days, 18:00:00 │ 1 0 0 100 │
|
||||
│ Drv3_SOL_2_0_28.89 │ 1 │ 9.34 │ 9.561 │ 0.32 │ 5 days, 14:00:00 │ 1 0 0 100 │
|
||||
│ RSI_SOL_4_0_40.62 │ 1 │ 2.98 │ 9.471 │ 0.32 │ 10 days, 23:00:00 │ 1 0 0 100 │
|
||||
│ Drv3_XRP_3_0_69.84 │ 1 │ 2.64 │ 9.241 │ 0.31 │ 3 days, 14:00:00 │ 1 0 0 100 │
|
||||
│ Drv3_SOL_3_0_60.36 │ 1 │ 4.38 │ 8.823 │ 0.29 │ 7 days, 10:00:00 │ 1 0 0 100 │
|
||||
│ Drv3_SOL_2_0_47.83 │ 1 │ 8.04 │ 8.420 │ 0.28 │ 3 days, 23:00:00 │ 1 0 0 100 │
|
||||
│ RSI_XRP_1_0_9.78 │ 1 │ 13.26 │ 8.291 │ 0.28 │ 1 day, 10:00:00 │ 1 0 0 100 │
|
||||
│ Drv3_XRP_1_0_33.33 │ 1 │ 15.27 │ 7.630 │ 0.25 │ 3 days, 20:00:00 │ 1 0 0 100 │
|
||||
│ Drv3_ETH_1_0_12.35 │ 1 │ 14.27 │ 7.136 │ 0.24 │ 3 days, 22:00:00 │ 1 0 0 100 │
|
||||
│ Drv3_SOL_1_0_39.42 │ 1 │ 10.17 │ 6.354 │ 0.21 │ 3 days, 15:00:00 │ 1 0 0 100 │
|
||||
│ Drv3_BTC_4_0_17.57 │ 1 │ 2.59 │ 6.081 │ 0.2 │ 15 days, 18:00:00 │ 1 0 0 100 │
|
||||
│ Drv3_BTC_2_0_18.06 │ 1 │ 5.89 │ 5.956 │ 0.2 │ 9 days, 11:00:00 │ 1 0 0 100 │
|
||||
│ Drv3_BTC_1_0_17.14 │ 1 │ 9.45 │ 5.834 │ 0.19 │ 8 days, 2:00:00 │ 1 0 0 100 │
|
||||
│ Drv3_SOL_8_0_81.16 │ 1 │ 0.73 │ 5.508 │ 0.18 │ 107 days, 19:00:00 │ 1 0 0 100 │
|
||||
│ RSI_BTC_5_0_31.25 │ 1 │ 1.93 │ 5.464 │ 0.18 │ 17 days, 20:00:00 │ 1 0 0 100 │
|
||||
│ Drv3_BTC_6_0_30.26 │ 1 │ 1.51 │ 5.343 │ 0.18 │ 31 days, 22:00:00 │ 1 0 0 100 │
|
||||
│ Drv3_DOGE_4_0_83.45 │ 1 │ 1.65 │ 4.730 │ 0.16 │ 11 days, 6:00:00 │ 1 0 0 100 │
|
||||
│ Drv3_XRP_1_0_26.98 │ 1 │ 9.3 │ 4.588 │ 0.15 │ 4 days, 12:00:00 │ 1 0 0 100 │
|
||||
│ Drv3_SOL_1_0_25.0 │ 1 │ 7.26 │ 4.538 │ 0.15 │ 3 days, 7:00:00 │ 1 0 0 100 │
|
||||
│ Drv3_BTC_1_0_20.0 │ 1 │ 8.86 │ 4.432 │ 0.15 │ 5 days, 22:00:00 │ 1 0 0 100 │
|
||||
│ Drv3_XRP_5_0_68.35 │ 1 │ 1.23 │ 4.368 │ 0.15 │ 55 days, 19:00:00 │ 1 0 0 100 │
|
||||
│ Drv3_BTC_1_0_10.64 │ 1 │ 8.42 │ 4.189 │ 0.14 │ 6 days, 23:00:00 │ 1 0 0 100 │
|
||||
│ Drv3_ETH_3_0_60.19 │ 1 │ 2.61 │ 4.110 │ 0.14 │ 4 days, 3:00:00 │ 1 0 0 100 │
|
||||
│ RSI_ETH_3_0_38.98 │ 1 │ 2.1 │ 3.591 │ 0.12 │ 12 days, 8:00:00 │ 1 0 0 100 │
|
||||
│ Drv3_DOGE_1_0_27.66 │ 1 │ 5.48 │ 3.425 │ 0.11 │ 2 days, 16:00:00 │ 1 0 0 100 │
|
||||
│ Drv3_SOL_2_0_43.86 │ 1 │ 2.49 │ 3.220 │ 0.11 │ 4 days, 1:00:00 │ 1 0 0 100 │
|
||||
│ Drv3_ETH_1_0_40.74 │ 1 │ 5.16 │ 3.215 │ 0.11 │ 2 days, 2:00:00 │ 1 0 0 100 │
|
||||
│ Drv3_SOL_1_0_50.77 │ 1 │ 5.12 │ 3.201 │ 0.11 │ 2 days, 12:00:00 │ 1 0 0 100 │
|
||||
│ Drv3_DOGE_7_0_96.68 │ 1 │ 0.29 │ 3.008 │ 0.1 │ 110 days, 6:00:00 │ 1 0 0 100 │
|
||||
│ Drv3_SOL_5_0_82.93 │ 1 │ 0.66 │ 2.808 │ 0.09 │ 38 days, 21:00:00 │ 1 0 0 100 │
|
||||
│ Drv3_XRP_3_0_74.07 │ 1 │ 1.13 │ 2.788 │ 0.09 │ 6 days, 14:00:00 │ 1 0 0 100 │
|
||||
│ Drv3_XRP_3_0_77.5 │ 1 │ 1.35 │ 2.745 │ 0.09 │ 2 days, 16:00:00 │ 1 0 0 100 │
|
||||
│ Drv3_SOL_2_0_57.63 │ 1 │ 2.33 │ 2.489 │ 0.08 │ 5 days, 9:00:00 │ 1 0 0 100 │
|
||||
│ Drv3_XRP_3_0_46.67 │ 1 │ 1.18 │ 2.404 │ 0.08 │ 4 days, 10:00:00 │ 1 0 0 100 │
|
||||
│ Drv3_XRP_1_0_54.0 │ 1 │ 4.34 │ 2.338 │ 0.08 │ 3 days, 3:00:00 │ 1 0 0 100 │
|
||||
│ Drv3_SOL_4_0_76.04 │ 1 │ 0.96 │ 2.254 │ 0.08 │ 13 days, 17:00:00 │ 1 0 0 100 │
|
||||
│ Drv3_BTC_1_0_56.0 │ 1 │ 3.55 │ 2.217 │ 0.07 │ 6 days, 15:00:00 │ 1 0 0 100 │
|
||||
│ Drv3_XRP_1_0_45.95 │ 1 │ 3.99 │ 1.993 │ 0.07 │ 1 day, 5:00:00 │ 1 0 0 100 │
|
||||
│ RSI_ETH_1_0_16.67 │ 1 │ 3.97 │ 1.977 │ 0.07 │ 14:00:00 │ 1 0 0 100 │
|
||||
│ Drv3_ETH_1_0_26.09 │ 1 │ 2.8 │ 1.746 │ 0.06 │ 2 days, 10:00:00 │ 1 0 0 100 │
|
||||
│ Drv3_SOL_2_0_71.93 │ 1 │ 1.52 │ 1.583 │ 0.05 │ 2 days, 11:00:00 │ 1 0 0 100 │
|
||||
│ Drv3_ETH_1_0_11.11 │ 1 │ 3.14 │ 1.565 │ 0.05 │ 2 days, 8:00:00 │ 1 0 0 100 │
|
||||
│ Drv3_DOGE_3_0_27.27 │ 1 │ 0.85 │ 1.557 │ 0.05 │ 12:00:00 │ 1 0 0 100 │
|
||||
│ Drv3_ETH_4_0_79.73 │ 1 │ 0.65 │ 1.509 │ 0.05 │ 6 days, 20:00:00 │ 1 0 0 100 │
|
||||
│ Drv3_ETH_2_0_76.56 │ 1 │ 1.15 │ 1.466 │ 0.05 │ 3 days, 6:00:00 │ 1 0 0 100 │
|
||||
│ Drv3_ETH_1_0_75.0 │ 1 │ 1.75 │ 1.314 │ 0.04 │ 3 days, 14:00:00 │ 1 0 0 100 │
|
||||
│ Drv3_ETH_3_0_73.47 │ 1 │ 0.76 │ 1.289 │ 0.04 │ 20 days, 8:00:00 │ 1 0 0 100 │
|
||||
│ Drv3_XRP_1_0_27.78 │ 1 │ 1.27 │ 1.268 │ 0.04 │ 6:00:00 │ 1 0 0 100 │
|
||||
│ Drv3_XRP_2_0_33.33 │ 1 │ 0.95 │ 1.203 │ 0.04 │ 1 day, 1:00:00 │ 1 0 0 100 │
|
||||
│ Drv3_XRP_2_0_83.58 │ 1 │ 1.12 │ 1.148 │ 0.04 │ 1 day, 16:00:00 │ 1 0 0 100 │
|
||||
│ Drv3_ETH_1_0_54.17 │ 1 │ 2.19 │ 1.097 │ 0.04 │ 1 day, 15:00:00 │ 1 0 0 100 │
|
||||
│ Drv3_BTC_2_0_44.44 │ 1 │ 0.79 │ 1.033 │ 0.03 │ 9 days, 6:00:00 │ 1 0 0 100 │
|
||||
│ Drv3_DOGE_1_0_77.78 │ 1 │ 2.0 │ 0.999 │ 0.03 │ 1 day, 16:00:00 │ 1 0 0 100 │
|
||||
│ Drv3_BTC_1_0_41.18 │ 1 │ 1.93 │ 0.964 │ 0.03 │ 5 days, 6:00:00 │ 1 0 0 100 │
|
||||
│ Drv3_ETH_3_0_85.94 │ 1 │ 0.48 │ 0.944 │ 0.03 │ 14 days, 16:00:00 │ 1 0 0 100 │
|
||||
│ Drv3_XRP_3_0_12.5 │ 1 │ 0.45 │ 0.712 │ 0.02 │ 1 day, 1:00:00 │ 1 0 0 100 │
|
||||
│ Drv3_XRP_1_0_81.58 │ 1 │ 1.12 │ 0.697 │ 0.02 │ 2 days, 7:00:00 │ 1 0 0 100 │
|
||||
│ Drv3_DOGE_1_0_30.0 │ 1 │ 1.1 │ 0.688 │ 0.02 │ 10:00:00 │ 1 0 0 100 │
|
||||
│ Drv3_ETH_3_0_30.0 │ 1 │ 0.42 │ 0.669 │ 0.02 │ 1 day, 6:00:00 │ 1 0 0 100 │
|
||||
│ Drv3_ETH_1_0_0.0 │ 1 │ 1.07 │ 0.666 │ 0.02 │ 4:00:00 │ 1 0 0 100 │
|
||||
│ Drv3_ETH_2_0_72.73 │ 1 │ 0.62 │ 0.631 │ 0.02 │ 1 day, 20:00:00 │ 1 0 0 100 │
|
||||
│ Drv3_XRP_2_0_25.0 │ 1 │ 0.6 │ 0.614 │ 0.02 │ 13:00:00 │ 1 0 0 100 │
|
||||
│ Drv3_ETH_2_0_66.67 │ 1 │ 0.59 │ 0.607 │ 0.02 │ 4 days, 22:00:00 │ 1 0 0 100 │
|
||||
│ Drv3_DOGE_1_0_57.14 │ 2 │ 0.38 │ 0.590 │ 0.02 │ 8:00:00 │ 2 0 0 100 │
|
||||
│ Drv3_SOL_2_0_64.71 │ 1 │ 0.57 │ 0.588 │ 0.02 │ 1 day, 12:00:00 │ 1 0 0 100 │
|
||||
│ Drv3_SOL_2_0_94.95 │ 1 │ 0.36 │ 0.548 │ 0.02 │ 2 days, 5:00:00 │ 1 0 0 100 │
|
||||
│ Drv3_XRP_1_0_28.57 │ 1 │ 0.87 │ 0.545 │ 0.02 │ 3:00:00 │ 1 0 0 100 │
|
||||
│ Drv3_SOL_2_0_28.57 │ 1 │ 0.49 │ 0.506 │ 0.02 │ 1 day, 5:00:00 │ 1 0 0 100 │
|
||||
│ Drv3_BTC_2_0_37.5 │ 1 │ 0.45 │ 0.489 │ 0.02 │ 3 days, 2:00:00 │ 1 0 0 100 │
|
||||
│ Drv3_BTC_1_0_73.68 │ 1 │ 0.94 │ 0.466 │ 0.02 │ 2 days, 18:00:00 │ 1 0 0 100 │
|
||||
│ Drv3_BTC_2_0_76.47 │ 1 │ 0.38 │ 0.397 │ 0.01 │ 15 days, 3:00:00 │ 1 0 0 100 │
|
||||
│ Drv3_BTC_1_0_72.73 │ 1 │ 0.7 │ 0.347 │ 0.01 │ 1 day, 23:00:00 │ 1 0 0 100 │
|
||||
│ Drv3_BTC_1_0_57.14 │ 1 │ 0.64 │ 0.318 │ 0.01 │ 1 day, 14:00:00 │ 1 0 0 100 │
|
||||
│ Drv3_XRP_1_0_85.0 │ 1 │ 0.48 │ 0.298 │ 0.01 │ 2 days, 7:00:00 │ 1 0 0 100 │
|
||||
│ Drv3_ETH_1_0_76.92 │ 1 │ 0.58 │ 0.290 │ 0.01 │ 2 days, 1:00:00 │ 1 0 0 100 │
|
||||
│ Drv3_BTC_1_0_75.0 │ 1 │ 0.45 │ 0.223 │ 0.01 │ 1 day, 15:00:00 │ 1 0 0 100 │
|
||||
│ Drv3_DOGE_1_0_87.5 │ 1 │ 0.32 │ 0.198 │ 0.01 │ 1 day, 11:00:00 │ 1 0 0 100 │
|
||||
│ Drv3_XRP_1_0_80.0 │ 1 │ 0.32 │ 0.196 │ 0.01 │ 1 day, 14:00:00 │ 1 0 0 100 │
|
||||
│ Drv3_BTC_2_0_94.59 │ 1 │ 0.19 │ 0.188 │ 0.01 │ 6 days, 10:00:00 │ 1 0 0 100 │
|
||||
│ Drv3_XRP_1_0_92.0 │ 1 │ 0.35 │ 0.173 │ 0.01 │ 3 days, 2:00:00 │ 1 0 0 100 │
|
||||
│ Drv3_XRP_1_0_92.86 │ 1 │ 0.29 │ 0.147 │ 0.0 │ 1 day, 18:00:00 │ 1 0 0 100 │
|
||||
│ Drv3_ETH_2_0_97.62 │ 1 │ 0.14 │ 0.145 │ 0.0 │ 1 day, 14:00:00 │ 1 0 0 100 │
|
||||
│ Drv3_ETH_2_0_91.67 │ 1 │ 0.14 │ 0.143 │ 0.0 │ 1 day, 0:00:00 │ 1 0 0 100 │
|
||||
│ Drv3_BTC_1_0_85.71 │ 1 │ 0.27 │ 0.133 │ 0.0 │ 2 days, 11:00:00 │ 1 0 0 100 │
|
||||
│ Drv3_SOL_1_0_80.0 │ 1 │ 0.23 │ 0.114 │ 0.0 │ 2 days, 0:00:00 │ 1 0 0 100 │
|
||||
│ Drv3_BTC_2_0_66.67 │ 1 │ 0.11 │ 0.107 │ 0.0 │ 1 day, 0:00:00 │ 1 0 0 100 │
|
||||
│ Drv3_BTC_1_0_90.0 │ 1 │ 0.21 │ 0.104 │ 0.0 │ 1 day, 9:00:00 │ 1 0 0 100 │
|
||||
│ force_exit │ 5 │ -0.54 │ -9.899 │ -0.33 │ 12 days, 9:00:00 │ 2 0 3 40.0 │
|
||||
│ TOTAL │ 121 │ 4.59 │ 824.533 │ 27.48 │ 10 days, 12:59:00 │ 118 0 3 97.5 │
|
||||
└─────────────────────┴───────┴──────────────┴─────────────────┴──────────────┴────────────────────┴────────────────────────┘
|
||||
MIXED TAG STATS
|
||||
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━┳━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━┓
|
||||
┃ Enter Tag ┃ Exit Reason ┃ Trades ┃ Avg Profit % ┃ Tot Profit USDT ┃ Tot Profit % ┃ Avg Duration ┃ Win Draw Loss Win% ┃
|
||||
┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━╇━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━┩
|
||||
│ ('smth_12', 'RSI_XRP_5_0_28.43') │ │ 1 │ 15.15 │ 71.078 │ 2.37 │ 15 days, 4:00:00 │ 1 0 0 100 │
|
||||
│ ('smth_12', 'Drv3_ETH_8_0_34.72') │ │ 1 │ 6.36 │ 53.262 │ 1.78 │ 125 days, 19:00:00 │ 1 0 0 100 │
|
||||
│ ('smth_12', 'Drv3_DOGE_6_0_46.32') │ │ 1 │ 10.45 │ 52.528 │ 1.75 │ 47 days, 13:00:00 │ 1 0 0 100 │
|
||||
│ ('smth_12', 'Drv3_DOGE_3_0_26.01') │ │ 1 │ 21.51 │ 34.730 │ 1.16 │ 6 days, 1:00:00 │ 1 0 0 100 │
|
||||
│ ('smth_12', 'Drv3_DOGE_3_0_39.61') │ │ 1 │ 14.32 │ 34.062 │ 1.14 │ 11 days, 21:00:00 │ 1 0 0 100 │
|
||||
│ ('smth_12', 'Drv3_ETH_3_0_14.24') │ │ 1 │ 15.48 │ 26.538 │ 0.88 │ 11 days, 17:00:00 │ 1 0 0 100 │
|
||||
│ ('smth_12', 'Drv3_SOL_2_0_9.03') │ │ 1 │ 17.25 │ 26.223 │ 0.87 │ 8 days, 1:00:00 │ 1 0 0 100 │
|
||||
│ ('smth_12', 'Drv3_XRP_4_0_19.78') │ │ 1 │ 9.64 │ 21.919 │ 0.73 │ 9 days, 10:00:00 │ 1 0 0 100 │
|
||||
│ ('smth_12', 'Drv3_SOL_3_0_31.46') │ │ 1 │ 10.39 │ 20.674 │ 0.69 │ 8 days, 13:00:00 │ 1 0 0 100 │
|
||||
│ ('smth_12', 'Drv3_SOL_4_0_24.35') │ │ 1 │ 6.46 │ 20.553 │ 0.69 │ 13 days, 8:00:00 │ 1 0 0 100 │
|
||||
│ ('smth_12', 'Drv3_DOGE_4_0_29.59') │ │ 1 │ 6.68 │ 18.794 │ 0.63 │ 16 days, 21:00:00 │ 1 0 0 100 │
|
||||
│ ('smth_12', 'Drv3_DOGE_2_0_23.33') │ │ 1 │ 17.89 │ 18.435 │ 0.61 │ 3 days, 20:00:00 │ 1 0 0 100 │
|
||||
│ ('smth_12', 'Drv3_XRP_4_0_34.21') │ │ 1 │ 7.03 │ 17.503 │ 0.58 │ 12 days, 1:00:00 │ 1 0 0 100 │
|
||||
│ ('smth_12', 'Drv3_ETH_3_0_18.45') │ │ 1 │ 10.19 │ 16.852 │ 0.56 │ 7 days, 0:00:00 │ 1 0 0 100 │
|
||||
│ ('smth_12', 'Drv3_BTC_8_0_37.83') │ │ 1 │ 3.12 │ 16.616 │ 0.55 │ 79 days, 11:00:00 │ 1 0 0 100 │
|
||||
│ ('smth_12', 'Drv3_BTC_4_0_12.14') │ │ 1 │ 6.86 │ 15.212 │ 0.51 │ 16 days, 15:00:00 │ 1 0 0 100 │
|
||||
│ ('smth_12', 'Drv3_DOGE_1_0_19.08') │ │ 1 │ 18.77 │ 14.063 │ 0.47 │ 4 days, 11:00:00 │ 1 0 0 100 │
|
||||
│ ('smth_12', 'Drv3_XRP_1_0_20.83') │ │ 1 │ 26.55 │ 13.279 │ 0.44 │ 3 days, 16:00:00 │ 1 0 0 100 │
|
||||
│ ('smth_12', 'Drv3_ETH_3_0_19.63') │ │ 1 │ 7.04 │ 13.133 │ 0.44 │ 14 days, 0:00:00 │ 1 0 0 100 │
|
||||
│ ('smth_12', 'Drv3_DOGE_3_0_25.43') │ │ 1 │ 6.43 │ 12.901 │ 0.43 │ 12 days, 17:00:00 │ 1 0 0 100 │
|
||||
│ ('smth_12', 'Drv3_DOGE_1_0_27.27') │ │ 1 │ 12.06 │ 12.054 │ 0.4 │ 2 days, 6:00:00 │ 1 0 0 100 │
|
||||
│ ('smth_12', 'Drv3_SOL_2_0_67.31') │ │ 1 │ 11.51 │ 11.807 │ 0.39 │ 3 days, 13:00:00 │ 1 0 0 100 │
|
||||
│ ('smth_12', 'Drv3_XRP_3_0_43.54') │ │ 1 │ 5.33 │ 11.803 │ 0.39 │ 46 days, 10:00:00 │ 1 0 0 100 │
|
||||
│ ('smth_12', 'Drv3_SOL_1_0_11.11') │ │ 1 │ 12.28 │ 11.253 │ 0.38 │ 3 days, 16:00:00 │ 1 0 0 100 │
|
||||
│ ('smth_12', 'Drv3_DOGE_4_0_54.81') │ │ 1 │ 4.36 │ 10.812 │ 0.36 │ 13 days, 15:00:00 │ 1 0 0 100 │
|
||||
│ ('smth_12', 'Drv3_XRP_1_0_34.78') │ │ 1 │ 16.81 │ 10.484 │ 0.35 │ 2 days, 20:00:00 │ 1 0 0 100 │
|
||||
│ ('smth_12', 'Drv3_DOGE_3_0_26.24') │ │ 1 │ 6.2 │ 10.401 │ 0.35 │ 7 days, 23:00:00 │ 1 0 0 100 │
|
||||
│ ('smth_12', 'RSI_ETH_1_0_8.93') │ │ 1 │ 20.52 │ 10.253 │ 0.34 │ 4 days, 22:00:00 │ 1 0 0 100 │
|
||||
│ ('smth_12', 'Drv3_XRP_3_0_32.89') │ │ 1 │ 6.37 │ 10.247 │ 0.34 │ 6 days, 18:00:00 │ 1 0 0 100 │
|
||||
│ ('smth_12', 'Drv3_SOL_2_0_28.89') │ │ 1 │ 9.34 │ 9.561 │ 0.32 │ 5 days, 14:00:00 │ 1 0 0 100 │
|
||||
│ ('smth_12', 'RSI_SOL_4_0_40.62') │ │ 1 │ 2.98 │ 9.471 │ 0.32 │ 10 days, 23:00:00 │ 1 0 0 100 │
|
||||
│ ('smth_12', 'Drv3_XRP_3_0_69.84') │ │ 1 │ 2.64 │ 9.241 │ 0.31 │ 3 days, 14:00:00 │ 1 0 0 100 │
|
||||
│ ('smth_12', 'Drv3_SOL_3_0_60.36') │ │ 1 │ 4.38 │ 8.823 │ 0.29 │ 7 days, 10:00:00 │ 1 0 0 100 │
|
||||
│ ('smth_12', 'Drv3_SOL_2_0_47.83') │ │ 1 │ 8.04 │ 8.420 │ 0.28 │ 3 days, 23:00:00 │ 1 0 0 100 │
|
||||
│ ('smth_12', 'RSI_XRP_1_0_9.78') │ │ 1 │ 13.26 │ 8.291 │ 0.28 │ 1 day, 10:00:00 │ 1 0 0 100 │
|
||||
│ ('smth_12', 'Drv3_XRP_1_0_33.33') │ │ 1 │ 15.27 │ 7.630 │ 0.25 │ 3 days, 20:00:00 │ 1 0 0 100 │
|
||||
│ ('smth_12', 'Drv3_ETH_1_0_12.35') │ │ 1 │ 14.27 │ 7.136 │ 0.24 │ 3 days, 22:00:00 │ 1 0 0 100 │
|
||||
│ ('smth_12', 'Drv3_SOL_1_0_39.42') │ │ 1 │ 10.17 │ 6.354 │ 0.21 │ 3 days, 15:00:00 │ 1 0 0 100 │
|
||||
│ ('smth_12', 'Drv3_BTC_4_0_17.57') │ │ 1 │ 2.59 │ 6.081 │ 0.2 │ 15 days, 18:00:00 │ 1 0 0 100 │
|
||||
│ ('smth_12', 'Drv3_BTC_2_0_18.06') │ │ 1 │ 5.89 │ 5.956 │ 0.2 │ 9 days, 11:00:00 │ 1 0 0 100 │
|
||||
│ ('smth_12', 'Drv3_BTC_1_0_17.14') │ │ 1 │ 9.45 │ 5.834 │ 0.19 │ 8 days, 2:00:00 │ 1 0 0 100 │
|
||||
│ ('smth_12', 'Drv3_SOL_8_0_81.16') │ │ 1 │ 0.73 │ 5.508 │ 0.18 │ 107 days, 19:00:00 │ 1 0 0 100 │
|
||||
│ ('smth_12', 'RSI_BTC_5_0_31.25') │ │ 1 │ 1.93 │ 5.464 │ 0.18 │ 17 days, 20:00:00 │ 1 0 0 100 │
|
||||
│ ('smth_12', 'Drv3_BTC_6_0_30.26') │ │ 1 │ 1.51 │ 5.343 │ 0.18 │ 31 days, 22:00:00 │ 1 0 0 100 │
|
||||
│ ('smth_12', 'Drv3_DOGE_4_0_83.45') │ │ 1 │ 1.65 │ 4.730 │ 0.16 │ 11 days, 6:00:00 │ 1 0 0 100 │
|
||||
│ ('smth_12', 'Drv3_XRP_1_0_26.98') │ │ 1 │ 9.3 │ 4.588 │ 0.15 │ 4 days, 12:00:00 │ 1 0 0 100 │
|
||||
│ ('smth_12', 'Drv3_SOL_1_0_25.0') │ │ 1 │ 7.26 │ 4.538 │ 0.15 │ 3 days, 7:00:00 │ 1 0 0 100 │
|
||||
│ ('smth_12', 'Drv3_BTC_1_0_20.0') │ │ 1 │ 8.86 │ 4.432 │ 0.15 │ 5 days, 22:00:00 │ 1 0 0 100 │
|
||||
│ ('smth_12', 'Drv3_XRP_5_0_68.35') │ │ 1 │ 1.23 │ 4.368 │ 0.15 │ 55 days, 19:00:00 │ 1 0 0 100 │
|
||||
│ ('smth_12', 'Drv3_BTC_1_0_10.64') │ │ 1 │ 8.42 │ 4.189 │ 0.14 │ 6 days, 23:00:00 │ 1 0 0 100 │
|
||||
│ ('smth_12', 'Drv3_ETH_3_0_60.19') │ │ 1 │ 2.61 │ 4.110 │ 0.14 │ 4 days, 3:00:00 │ 1 0 0 100 │
|
||||
│ ('smth_12', 'RSI_ETH_3_0_38.98') │ │ 1 │ 2.1 │ 3.591 │ 0.12 │ 12 days, 8:00:00 │ 1 0 0 100 │
|
||||
│ ('smth_12', 'Drv3_DOGE_1_0_27.66') │ │ 1 │ 5.48 │ 3.425 │ 0.11 │ 2 days, 16:00:00 │ 1 0 0 100 │
|
||||
│ ('smth_12', 'Drv3_SOL_2_0_43.86') │ │ 1 │ 2.49 │ 3.220 │ 0.11 │ 4 days, 1:00:00 │ 1 0 0 100 │
|
||||
│ ('smth_12', 'Drv3_ETH_1_0_40.74') │ │ 1 │ 5.16 │ 3.215 │ 0.11 │ 2 days, 2:00:00 │ 1 0 0 100 │
|
||||
│ ('smth_12', 'Drv3_SOL_1_0_50.77') │ │ 1 │ 5.12 │ 3.201 │ 0.11 │ 2 days, 12:00:00 │ 1 0 0 100 │
|
||||
│ ('smth_12', 'Drv3_DOGE_7_0_96.68') │ │ 1 │ 0.29 │ 3.008 │ 0.1 │ 110 days, 6:00:00 │ 1 0 0 100 │
|
||||
│ ('smth_12', 'Drv3_SOL_5_0_82.93') │ │ 1 │ 0.66 │ 2.808 │ 0.09 │ 38 days, 21:00:00 │ 1 0 0 100 │
|
||||
│ ('smth_12', 'Drv3_XRP_3_0_74.07') │ │ 1 │ 1.13 │ 2.788 │ 0.09 │ 6 days, 14:00:00 │ 1 0 0 100 │
|
||||
│ ('smth_12', 'Drv3_XRP_3_0_77.5') │ │ 1 │ 1.35 │ 2.745 │ 0.09 │ 2 days, 16:00:00 │ 1 0 0 100 │
|
||||
│ ('smth_12', 'Drv3_SOL_2_0_57.63') │ │ 1 │ 2.33 │ 2.489 │ 0.08 │ 5 days, 9:00:00 │ 1 0 0 100 │
|
||||
│ ('smth_12', 'Drv3_XRP_3_0_46.67') │ │ 1 │ 1.18 │ 2.404 │ 0.08 │ 4 days, 10:00:00 │ 1 0 0 100 │
|
||||
│ ('smth_12', 'Drv3_XRP_1_0_54.0') │ │ 1 │ 4.34 │ 2.338 │ 0.08 │ 3 days, 3:00:00 │ 1 0 0 100 │
|
||||
│ ('smth_12', 'Drv3_SOL_4_0_76.04') │ │ 1 │ 0.96 │ 2.254 │ 0.08 │ 13 days, 17:00:00 │ 1 0 0 100 │
|
||||
│ ('smth_12', 'Drv3_BTC_1_0_56.0') │ │ 1 │ 3.55 │ 2.217 │ 0.07 │ 6 days, 15:00:00 │ 1 0 0 100 │
|
||||
│ ('smth_12', 'Drv3_XRP_1_0_45.95') │ │ 1 │ 3.99 │ 1.993 │ 0.07 │ 1 day, 5:00:00 │ 1 0 0 100 │
|
||||
│ ('smth_12', 'RSI_ETH_1_0_16.67') │ │ 1 │ 3.97 │ 1.977 │ 0.07 │ 14:00:00 │ 1 0 0 100 │
|
||||
│ ('smth_12', 'Drv3_ETH_1_0_26.09') │ │ 1 │ 2.8 │ 1.746 │ 0.06 │ 2 days, 10:00:00 │ 1 0 0 100 │
|
||||
│ ('smth_12', 'Drv3_SOL_2_0_71.93') │ │ 1 │ 1.52 │ 1.583 │ 0.05 │ 2 days, 11:00:00 │ 1 0 0 100 │
|
||||
│ ('smth_12', 'Drv3_ETH_1_0_11.11') │ │ 1 │ 3.14 │ 1.565 │ 0.05 │ 2 days, 8:00:00 │ 1 0 0 100 │
|
||||
│ ('smth_12', 'Drv3_DOGE_3_0_27.27') │ │ 1 │ 0.85 │ 1.557 │ 0.05 │ 12:00:00 │ 1 0 0 100 │
|
||||
│ ('smth_12', 'Drv3_ETH_4_0_79.73') │ │ 1 │ 0.65 │ 1.509 │ 0.05 │ 6 days, 20:00:00 │ 1 0 0 100 │
|
||||
│ ('smth_12', 'Drv3_ETH_2_0_76.56') │ │ 1 │ 1.15 │ 1.466 │ 0.05 │ 3 days, 6:00:00 │ 1 0 0 100 │
|
||||
│ ('smth_12', 'Drv3_ETH_1_0_75.0') │ │ 1 │ 1.75 │ 1.314 │ 0.04 │ 3 days, 14:00:00 │ 1 0 0 100 │
|
||||
│ ('smth_12', 'Drv3_ETH_3_0_73.47') │ │ 1 │ 0.76 │ 1.289 │ 0.04 │ 20 days, 8:00:00 │ 1 0 0 100 │
|
||||
│ ('smth_12', 'Drv3_XRP_1_0_27.78') │ │ 1 │ 1.27 │ 1.268 │ 0.04 │ 6:00:00 │ 1 0 0 100 │
|
||||
│ ('smth_12', 'Drv3_XRP_2_0_33.33') │ │ 1 │ 0.95 │ 1.203 │ 0.04 │ 1 day, 1:00:00 │ 1 0 0 100 │
|
||||
│ ('smth_12', 'Drv3_XRP_2_0_83.58') │ │ 1 │ 1.12 │ 1.148 │ 0.04 │ 1 day, 16:00:00 │ 1 0 0 100 │
|
||||
│ ('smth_12', 'Drv3_ETH_1_0_54.17') │ │ 1 │ 2.19 │ 1.097 │ 0.04 │ 1 day, 15:00:00 │ 1 0 0 100 │
|
||||
│ ('smth_12', 'Drv3_BTC_2_0_44.44') │ │ 1 │ 0.79 │ 1.033 │ 0.03 │ 9 days, 6:00:00 │ 1 0 0 100 │
|
||||
│ ('smth_12', 'Drv3_DOGE_1_0_77.78') │ │ 1 │ 2.0 │ 0.999 │ 0.03 │ 1 day, 16:00:00 │ 1 0 0 100 │
|
||||
│ ('smth_12', 'Drv3_BTC_1_0_41.18') │ │ 1 │ 1.93 │ 0.964 │ 0.03 │ 5 days, 6:00:00 │ 1 0 0 100 │
|
||||
│ ('smth_12', 'Drv3_ETH_3_0_85.94') │ │ 1 │ 0.48 │ 0.944 │ 0.03 │ 14 days, 16:00:00 │ 1 0 0 100 │
|
||||
│ ('smth_12', 'Drv3_XRP_3_0_12.5') │ │ 1 │ 0.45 │ 0.712 │ 0.02 │ 1 day, 1:00:00 │ 1 0 0 100 │
|
||||
│ ('smth_12', 'Drv3_XRP_1_0_81.58') │ │ 1 │ 1.12 │ 0.697 │ 0.02 │ 2 days, 7:00:00 │ 1 0 0 100 │
|
||||
│ ('smth_12', 'Drv3_DOGE_1_0_30.0') │ │ 1 │ 1.1 │ 0.688 │ 0.02 │ 10:00:00 │ 1 0 0 100 │
|
||||
│ ('smth_12', 'Drv3_ETH_3_0_30.0') │ │ 1 │ 0.42 │ 0.669 │ 0.02 │ 1 day, 6:00:00 │ 1 0 0 100 │
|
||||
│ ('smth_12', 'Drv3_ETH_1_0_0.0') │ │ 1 │ 1.07 │ 0.666 │ 0.02 │ 4:00:00 │ 1 0 0 100 │
|
||||
│ ('smth_12', 'Drv3_ETH_2_0_72.73') │ │ 1 │ 0.62 │ 0.631 │ 0.02 │ 1 day, 20:00:00 │ 1 0 0 100 │
|
||||
│ ('smth_12', 'Drv3_XRP_2_0_25.0') │ │ 1 │ 0.6 │ 0.614 │ 0.02 │ 13:00:00 │ 1 0 0 100 │
|
||||
│ ('smth_12', 'Drv3_ETH_2_0_66.67') │ │ 1 │ 0.59 │ 0.607 │ 0.02 │ 4 days, 22:00:00 │ 1 0 0 100 │
|
||||
│ ('smth_12', 'Drv3_DOGE_1_0_57.14') │ │ 2 │ 0.38 │ 0.590 │ 0.02 │ 8:00:00 │ 2 0 0 100 │
|
||||
│ ('smth_12', 'Drv3_SOL_2_0_64.71') │ │ 1 │ 0.57 │ 0.588 │ 0.02 │ 1 day, 12:00:00 │ 1 0 0 100 │
|
||||
│ ('smth_12', 'Drv3_SOL_2_0_94.95') │ │ 1 │ 0.36 │ 0.548 │ 0.02 │ 2 days, 5:00:00 │ 1 0 0 100 │
|
||||
│ ('smth_12', 'Drv3_XRP_1_0_28.57') │ │ 1 │ 0.87 │ 0.545 │ 0.02 │ 3:00:00 │ 1 0 0 100 │
|
||||
│ ('smth_12', 'Drv3_SOL_2_0_28.57') │ │ 1 │ 0.49 │ 0.506 │ 0.02 │ 1 day, 5:00:00 │ 1 0 0 100 │
|
||||
│ ('smth_12', 'Drv3_BTC_2_0_37.5') │ │ 1 │ 0.45 │ 0.489 │ 0.02 │ 3 days, 2:00:00 │ 1 0 0 100 │
|
||||
│ ('smth_12', 'Drv3_BTC_1_0_73.68') │ │ 1 │ 0.94 │ 0.466 │ 0.02 │ 2 days, 18:00:00 │ 1 0 0 100 │
|
||||
│ ('smth_12', 'Drv3_BTC_2_0_76.47') │ │ 1 │ 0.38 │ 0.397 │ 0.01 │ 15 days, 3:00:00 │ 1 0 0 100 │
|
||||
│ ('smth_12', 'Drv3_BTC_1_0_72.73') │ │ 1 │ 0.7 │ 0.347 │ 0.01 │ 1 day, 23:00:00 │ 1 0 0 100 │
|
||||
│ ('smth_12', 'Drv3_BTC_1_0_57.14') │ │ 1 │ 0.64 │ 0.318 │ 0.01 │ 1 day, 14:00:00 │ 1 0 0 100 │
|
||||
│ ('smth_12', 'Drv3_XRP_1_0_85.0') │ │ 1 │ 0.48 │ 0.298 │ 0.01 │ 2 days, 7:00:00 │ 1 0 0 100 │
|
||||
│ ('smth_12', 'Drv3_ETH_1_0_76.92') │ │ 1 │ 0.58 │ 0.290 │ 0.01 │ 2 days, 1:00:00 │ 1 0 0 100 │
|
||||
│ ('smth_12', 'Drv3_BTC_1_0_75.0') │ │ 1 │ 0.45 │ 0.223 │ 0.01 │ 1 day, 15:00:00 │ 1 0 0 100 │
|
||||
│ ('smth_12', 'Drv3_DOGE_1_0_87.5') │ │ 1 │ 0.32 │ 0.198 │ 0.01 │ 1 day, 11:00:00 │ 1 0 0 100 │
|
||||
│ ('smth_12', 'Drv3_XRP_1_0_80.0') │ │ 1 │ 0.32 │ 0.196 │ 0.01 │ 1 day, 14:00:00 │ 1 0 0 100 │
|
||||
│ ('smth_12', 'Drv3_BTC_2_0_94.59') │ │ 1 │ 0.19 │ 0.188 │ 0.01 │ 6 days, 10:00:00 │ 1 0 0 100 │
|
||||
│ ('smth_12', 'Drv3_XRP_1_0_92.0') │ │ 1 │ 0.35 │ 0.173 │ 0.01 │ 3 days, 2:00:00 │ 1 0 0 100 │
|
||||
│ ('smth_12', 'Drv3_XRP_1_0_92.86') │ │ 1 │ 0.29 │ 0.147 │ 0.0 │ 1 day, 18:00:00 │ 1 0 0 100 │
|
||||
│ ('smth_12', 'Drv3_ETH_2_0_97.62') │ │ 1 │ 0.14 │ 0.145 │ 0.0 │ 1 day, 14:00:00 │ 1 0 0 100 │
|
||||
│ ('smth_12', 'Drv3_ETH_2_0_91.67') │ │ 1 │ 0.14 │ 0.143 │ 0.0 │ 1 day, 0:00:00 │ 1 0 0 100 │
|
||||
│ ('smth_12', 'Drv3_BTC_1_0_85.71') │ │ 1 │ 0.27 │ 0.133 │ 0.0 │ 2 days, 11:00:00 │ 1 0 0 100 │
|
||||
│ ('smth_12', 'Drv3_SOL_1_0_80.0') │ │ 1 │ 0.23 │ 0.114 │ 0.0 │ 2 days, 0:00:00 │ 1 0 0 100 │
|
||||
│ ('smth_12', 'Drv3_BTC_2_0_66.67') │ │ 1 │ 0.11 │ 0.107 │ 0.0 │ 1 day, 0:00:00 │ 1 0 0 100 │
|
||||
│ ('smth_12', 'Drv3_BTC_1_0_90.0') │ │ 1 │ 0.21 │ 0.104 │ 0.0 │ 1 day, 9:00:00 │ 1 0 0 100 │
|
||||
│ ('smth_12', 'force_exit') │ │ 5 │ -0.54 │ -9.899 │ -0.33 │ 12 days, 9:00:00 │ 2 0 3 40.0 │
|
||||
│ TOTAL │ │ 121 │ 4.59 │ 824.533 │ 27.48 │ 10 days, 12:59:00 │ 118 0 3 97.5 │
|
||||
└────────────────────────────────────┴─────────────┴────────┴──────────────┴─────────────────┴──────────────┴────────────────────┴────────────────────────┘
|
||||
WEEK BREAKDOWN
|
||||
┏━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━┳━━━━━━┳━━━━━━━┳━━━━━━━━┓
|
||||
┃ Week ┃ Tot Profit USDT ┃ Wins ┃ Draws ┃ Losses ┃
|
||||
┡━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━╇━━━━━━╇━━━━━━━╇━━━━━━━━┩
|
||||
│ 06/01/2025 │ 37.217 │ 6 │ 0 │ 0 │
|
||||
│ 13/01/2025 │ 12.464 │ 2 │ 0 │ 0 │
|
||||
│ 20/01/2025 │ 76.722 │ 7 │ 0 │ 0 │
|
||||
│ 27/01/2025 │ 4.684 │ 4 │ 0 │ 0 │
|
||||
│ 03/02/2025 │ 3.577 │ 4 │ 0 │ 0 │
|
||||
│ 10/02/2025 │ 0 │ 0 │ 0 │ 0 │
|
||||
│ 17/02/2025 │ 17.503 │ 1 │ 0 │ 0 │
|
||||
│ 24/02/2025 │ 0 │ 0 │ 0 │ 0 │
|
||||
│ 03/03/2025 │ 71.078 │ 1 │ 0 │ 0 │
|
||||
│ 10/03/2025 │ 9.241 │ 1 │ 0 │ 0 │
|
||||
│ 17/03/2025 │ 4.588 │ 1 │ 0 │ 0 │
|
||||
│ 24/03/2025 │ 2.338 │ 1 │ 0 │ 0 │
|
||||
│ 31/03/2025 │ 0.147 │ 1 │ 0 │ 0 │
|
||||
│ 07/04/2025 │ 0 │ 0 │ 0 │ 0 │
|
||||
│ 14/04/2025 │ 0 │ 0 │ 0 │ 0 │
|
||||
│ 21/04/2025 │ 0 │ 0 │ 0 │ 0 │
|
||||
│ 28/04/2025 │ 16.839 │ 2 │ 0 │ 0 │
|
||||
│ 05/05/2025 │ 0.964 │ 1 │ 0 │ 0 │
|
||||
│ 12/05/2025 │ 78.013 │ 5 │ 0 │ 0 │
|
||||
│ 19/05/2025 │ 6.222 │ 4 │ 0 │ 0 │
|
||||
│ 26/05/2025 │ 19.509 │ 3 │ 0 │ 0 │
|
||||
│ 02/06/2025 │ 0.944 │ 1 │ 0 │ 0 │
|
||||
│ 09/06/2025 │ 0 │ 0 │ 0 │ 0 │
|
||||
│ 16/06/2025 │ 9.2 │ 3 │ 0 │ 0 │
|
||||
│ 23/06/2025 │ 2.131 │ 2 │ 0 │ 0 │
|
||||
│ 30/06/2025 │ 7.723 │ 3 │ 0 │ 0 │
|
||||
│ 07/07/2025 │ 5.149 │ 5 │ 0 │ 0 │
|
||||
│ 14/07/2025 │ 81.049 │ 8 │ 0 │ 0 │
|
||||
│ 21/07/2025 │ 66.176 │ 5 │ 0 │ 0 │
|
||||
│ 28/07/2025 │ 27.276 │ 10 │ 0 │ 0 │
|
||||
│ 04/08/2025 │ 0.788 │ 2 │ 0 │ 0 │
|
||||
│ 11/08/2025 │ 62.555 │ 5 │ 0 │ 0 │
|
||||
│ 18/08/2025 │ 15.647 │ 6 │ 0 │ 0 │
|
||||
│ 25/08/2025 │ 47.927 │ 3 │ 0 │ 0 │
|
||||
│ 01/09/2025 │ 3.201 │ 1 │ 0 │ 0 │
|
||||
│ 08/09/2025 │ 3.22 │ 1 │ 0 │ 0 │
|
||||
│ 15/09/2025 │ 70.772 │ 6 │ 0 │ 0 │
|
||||
│ 22/09/2025 │ 6.969 │ 5 │ 0 │ 0 │
|
||||
│ 29/09/2025 │ 0 │ 0 │ 0 │ 0 │
|
||||
│ 06/10/2025 │ 62.599 │ 6 │ 0 │ 0 │
|
||||
│ 13/10/2025 │ -9.899 │ 2 │ 0 │ 3 │
|
||||
└────────────┴─────────────────┴──────┴───────┴────────┘
|
||||
SUMMARY METRICS
|
||||
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━┓
|
||||
┃ Metric ┃ Value ┃
|
||||
┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━┩
|
||||
│ Backtesting from │ 2025-01-01 00:00:00 │
|
||||
│ Backtesting to │ 2025-10-07 10:00:00 │
|
||||
│ Trading Mode │ Spot │
|
||||
│ Max open trades │ 5 │
|
||||
│ │ │
|
||||
│ Total/Daily Avg Trades │ 121 / 0.43 │
|
||||
│ Starting balance │ 3000 USDT │
|
||||
│ Final balance │ 3824.533 USDT │
|
||||
│ Absolute profit │ 824.533 USDT │
|
||||
│ Total profit % │ 27.48% │
|
||||
│ CAGR % │ 37.39% │
|
||||
│ Sortino │ 11.17 │
|
||||
│ Sharpe │ 5.08 │
|
||||
│ Calmar │ 596.19 │
|
||||
│ SQN │ 6.71 │
|
||||
│ Profit factor │ 68.73 │
|
||||
│ Expectancy (Ratio) │ 6.81 (1.68) │
|
||||
│ Avg. daily profit % │ 0.10% │
|
||||
│ Avg. stake amount │ 155.858 USDT │
|
||||
│ Total trade volume │ 38619.369 USDT │
|
||||
│ │ │
|
||||
│ Best Pair │ XRP/USDT 6.62% │
|
||||
│ Worst Pair │ BTC/USDT 2.53% │
|
||||
│ Best trade │ XRP/USDT 26.55% │
|
||||
│ Worst trade │ XRP/USDT -4.64% │
|
||||
│ Best day │ 76.022 USDT │
|
||||
│ Worst day │ -9.899 USDT │
|
||||
│ Days win/draw/lose │ 75 / 203 / 1 │
|
||||
│ Avg. Duration Winners │ 10 days, 7:44:00 │
|
||||
│ Avg. Duration Loser │ 19 days, 3:20:00 │
|
||||
│ Max Consecutive Wins / Loss │ 116 / 2 │
|
||||
│ Rejected Entry signals │ 0 │
|
||||
│ Entry/Exit Timeouts │ 0 / 0 │
|
||||
│ │ │
|
||||
│ Min balance │ 3008.291 USDT │
|
||||
│ Max balance │ 3835.901 USDT │
|
||||
│ Max % of account underwater │ 0.32% │
|
||||
│ Absolute Drawdown (Account) │ 0.32% │
|
||||
│ Absolute Drawdown │ 12.109 USDT │
|
||||
│ Drawdown high │ 835.901 USDT │
|
||||
│ Drawdown low │ 823.792 USDT │
|
||||
│ Drawdown Start │ 2025-10-07 10:00:00 │
|
||||
│ Drawdown End │ 2025-10-07 10:00:00 │
|
||||
│ Market change │ 2.17% │
|
||||
└─────────────────────────────┴─────────────────────┘
|
||||
|
||||
Backtested 2025-01-01 00:00:00 -> 2025-10-07 10:00:00 | Max open trades : 5
|
||||
STRATEGY SUMMARY
|
||||
┏━━━━━━━━━━━┳━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━┓
|
||||
┃ Strategy ┃ Trades ┃ Avg Profit % ┃ Tot Profit USDT ┃ Tot Profit % ┃ Avg Duration ┃ Win Draw Loss Win% ┃ Drawdown ┃
|
||||
┡━━━━━━━━━━━╇━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━┩
|
||||
│ Zeus_8_1d │ 121 │ 4.59 │ 824.533 │ 27.48 │ 10 days, 12:59:00 │ 118 0 3 97.5 │ 12.109 USDT 0.32% │
|
||||
└───────────┴────────┴──────────────┴─────────────────┴──────────────┴───────────────────┴────────────────────────┴────────────────────┘
|
||||
@@ -8,25 +8,25 @@
|
||||
"stoploss": -1.0
|
||||
},
|
||||
"trailing": {
|
||||
"trailing_stop": false,
|
||||
"trailing_stop_positive": 0.254,
|
||||
"trailing_stop_positive_offset": 0.323,
|
||||
"trailing_stop": true,
|
||||
"trailing_stop_positive": 0.148,
|
||||
"trailing_stop_positive_offset": 0.218,
|
||||
"trailing_only_offset_is_reached": false
|
||||
},
|
||||
"max_open_trades": {
|
||||
"max_open_trades": 80
|
||||
"max_open_trades": 20
|
||||
},
|
||||
"buy": {
|
||||
"buy_horizon_predict_1h": 2
|
||||
},
|
||||
"sell": {
|
||||
"sell_allow_decrease": 0.2
|
||||
},
|
||||
"protection": {
|
||||
"protection_fibo": 9,
|
||||
"protection_percent_buy_lost": 3
|
||||
"mise_factor_buy": 0.01,
|
||||
"pct": 0.029,
|
||||
"pct_inc": 0.0027,
|
||||
"buy_filter_indicator": "rsi5_deriv1_1d",
|
||||
"buy_indicator0": "rsi60_inv_hau",
|
||||
"buy_indicator1": "mid_smooth_48_inv_bas",
|
||||
"buy_indicator2": "sma24_inv_bas_1h",
|
||||
"buy_indicator3": "bb_lowerband3_inv_hau_1h"
|
||||
}
|
||||
},
|
||||
"ft_stratparam_v": 1,
|
||||
"export_time": "2025-05-24 18:29:22.477903+00:00"
|
||||
"export_time": "2026-02-18 16:50:53.773582+00:00"
|
||||
}
|
||||
3753
Zeus_8_3_2_B_4_2.py
3753
Zeus_8_3_2_B_4_2.py
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
35
Zeus_LGBMRegressor.json
Normal file
35
Zeus_LGBMRegressor.json
Normal file
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"strategy_name": "Zeus_LGBMRegressor",
|
||||
"params": {
|
||||
"roi": {
|
||||
"0": 10
|
||||
},
|
||||
"stoploss": {
|
||||
"stoploss": -1
|
||||
},
|
||||
"trailing": {
|
||||
"trailing_stop": true,
|
||||
"trailing_stop_positive": 0.15,
|
||||
"trailing_stop_positive_offset": 0.2,
|
||||
"trailing_only_offset_is_reached": true
|
||||
},
|
||||
"max_open_trades": {
|
||||
"max_open_trades": 80
|
||||
},
|
||||
"buy": {
|
||||
"mise_factor_buy": 0.02,
|
||||
"mises": 2,
|
||||
"ml_prob_buy": -0.25,
|
||||
"pct": 0.012,
|
||||
"pct_inc": 0.001
|
||||
},
|
||||
"sell": {
|
||||
"ml_prob_sell": 0.07
|
||||
},
|
||||
"protection": {
|
||||
|
||||
}
|
||||
},
|
||||
"ft_stratparam_v": 1,
|
||||
"export_time": "2025-11-14 21:34:28.681343+00:00"
|
||||
}
|
||||
106
Zeus_LGBMRegressor.md
Normal file
106
Zeus_LGBMRegressor.md
Normal file
@@ -0,0 +1,106 @@
|
||||
🌟 Paramètres principaux de LGBMRegressor
|
||||
1️⃣ objective='regression'
|
||||
|
||||
But : indique le type de problème à résoudre.
|
||||
|
||||
Ici, tu veux prédire une valeur continue (par ex. un rendement futur, un prix, etc.).
|
||||
|
||||
Autres valeurs possibles :
|
||||
|
||||
'binary' → pour classification 0/1
|
||||
|
||||
'multiclass' → pour plusieurs classes
|
||||
|
||||
'regression_l1' → pour des valeurs continues mais avec perte L1 (moins sensible aux outliers)
|
||||
|
||||
📘 En résumé : ici LightGBM cherche à minimiser l’erreur entre la valeur prédite et la valeur réelle.
|
||||
|
||||
2️⃣ metric='rmse'
|
||||
|
||||
But : indique la métrique utilisée pour évaluer la qualité du modèle.
|
||||
|
||||
'rmse' = Root Mean Squared Error (racine de la moyenne des carrés des erreurs)
|
||||
→ pénalise fortement les grosses erreurs.
|
||||
|
||||
'mae' (Mean Absolute Error) est une alternative plus robuste (moins sensible aux outliers).
|
||||
|
||||
Tu peux aussi utiliser plusieurs métriques : metric=['rmse', 'mae'].
|
||||
|
||||
3️⃣ n_estimators=300
|
||||
|
||||
But : nombre d’arbres de décision à construire.
|
||||
|
||||
Chaque arbre apprend à corriger les erreurs du précédent → c’est le boosting.
|
||||
|
||||
Plus ce nombre est grand :
|
||||
|
||||
Meilleure précision potentielle
|
||||
|
||||
Mais risque de surapprentissage et de lenteur
|
||||
|
||||
Typiquement, on le combine avec un petit learning_rate (comme ici 0.05).
|
||||
|
||||
4️⃣ learning_rate=0.05
|
||||
|
||||
But : contrôle l’intensité avec laquelle chaque nouvel arbre corrige les erreurs.
|
||||
|
||||
Si learning_rate ↓, il faut plus d’arbres (n_estimators ↑) pour converger.
|
||||
|
||||
Typiquement :
|
||||
|
||||
0.1 = standard
|
||||
|
||||
0.05 = prudent (meilleur généralisation)
|
||||
|
||||
0.01 = très lent mais précis
|
||||
|
||||
⚖️ Ce paramètre agit comme un “frein” sur l’apprentissage.
|
||||
|
||||
5️⃣ max_depth=7
|
||||
|
||||
But : profondeur maximale des arbres.
|
||||
|
||||
Plus les arbres sont profonds :
|
||||
|
||||
→ plus le modèle capture des relations complexes
|
||||
|
||||
→ mais risque de surapprentissage
|
||||
|
||||
Valeurs typiques :
|
||||
|
||||
3 à 8 pour éviter le surapprentissage
|
||||
|
||||
-1 = pas de limite
|
||||
|
||||
6️⃣ subsample=0.8
|
||||
|
||||
But : fraction de l’échantillon d’entraînement utilisée pour chaque arbre.
|
||||
|
||||
Exemple :
|
||||
|
||||
0.8 = chaque arbre est entraîné sur 80 % des lignes (tirées aléatoirement).
|
||||
|
||||
Permet :
|
||||
|
||||
de réduire le surapprentissage
|
||||
|
||||
d’accélérer l’entraînement
|
||||
|
||||
Si tu veux des résultats très stables → monte à 1.0
|
||||
Si tu veux plus de diversité entre les arbres → garde entre 0.7 et 0.9.
|
||||
|
||||
7️⃣ colsample_bytree=0.8
|
||||
|
||||
But : fraction de colonnes (features) utilisées pour chaque arbre.
|
||||
|
||||
Comme subsample, mais pour les variables.
|
||||
|
||||
Aide à la régularisation : chaque arbre ne voit pas toutes les colonnes → modèle plus robuste.
|
||||
|
||||
Typiquement entre 0.6 et 1.0.
|
||||
|
||||
8️⃣ random_state=42
|
||||
|
||||
But : fixe la graine aléatoire.
|
||||
|
||||
Permet d’obtenir de
|
||||
2813
Zeus_LGBMRegressor.py
Normal file
2813
Zeus_LGBMRegressor.py
Normal file
File diff suppressed because it is too large
Load Diff
1859
Zeus_TensorFlow.py
Normal file
1859
Zeus_TensorFlow.py
Normal file
File diff suppressed because it is too large
Load Diff
2659
Zeus_TensorFlow_1h.py
Normal file
2659
Zeus_TensorFlow_1h.py
Normal file
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user