Scripts calcul hyperopt multiple
This commit is contained in:
@@ -33,44 +33,67 @@ if 'close' not in df.columns or 'timestamp' not in df.columns:
|
|||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
# --- paramètres ---
|
# --- paramètres ---
|
||||||
SMOOTH_WIN = 5 # EMA pour lisser la pente
|
SMOOTH_WIN = 10 # EMA pour lisser la pente
|
||||||
NUM_TOP = 3 # nombre de segments à garder par classe
|
NUM_TOP = 1 # nombre de segments à garder par classe
|
||||||
|
|
||||||
# --- charger les données ---
|
# --- charger les données ---
|
||||||
df['timestamp'] = pd.to_datetime(df['timestamp'], errors='coerce')
|
df['timestamp'] = pd.to_datetime(df['timestamp'], errors='coerce')
|
||||||
|
|
||||||
|
# filtrer uniquement 2024 et 2025
|
||||||
|
df = df[df['timestamp'].dt.year.isin([2024, 2025])]
|
||||||
|
|
||||||
# --- calcul SMA14 ---
|
# --- calcul SMA14 ---
|
||||||
df['sma14'] = ta.trend.sma_indicator(df['close'], 14)
|
df['sma'] = talib.SMA(df, timeperiod=20) #ta.trend.sma_indicator(df['close'], 14)
|
||||||
|
|
||||||
# --- pente brute ---
|
# --- pente brute ---
|
||||||
df['slope'] = df['sma14'].diff()
|
df['slope'] = df['sma'].diff()
|
||||||
|
|
||||||
# --- lissage EMA ---
|
# --- lissage EMA ---
|
||||||
df['slope_smooth'] = df['slope'].ewm(span=SMOOTH_WIN, adjust=False).mean()
|
df['slope_smooth'] = df['slope'].ewm(span=SMOOTH_WIN, adjust=False).mean()
|
||||||
|
|
||||||
|
#df["slope_smooth"] = savgol_filter(df["slope_smooth"], window_length=21, polyorder=3)
|
||||||
|
|
||||||
# --- normalisation relative ---
|
# --- normalisation relative ---
|
||||||
df['slope_norm'] = df['slope_smooth'] / df['close']
|
df['slope_norm'] = df['slope_smooth'] / df['close']
|
||||||
df['slope_norm'].fillna(0, inplace=True)
|
# df['slope_norm'].fillna(0, inplace=True)
|
||||||
|
df['slope_norm'] = df['slope_norm'].fillna(0)
|
||||||
|
|
||||||
|
|
||||||
# --- classification dynamique via quantiles ---
|
# --- classification dynamique via quantiles ---
|
||||||
q = df['slope_norm'].quantile([0.07, 0.21, 0.35, 0.65, 0.79, 0.93]).values
|
|
||||||
q1, q2, q3, q4, q5, q6 = q
|
q = df['slope_norm'].quantile([0.125, 0.375, 0.625, 0.875]).values
|
||||||
|
q1, q2, q3, q4 = q
|
||||||
|
|
||||||
def classify(v):
|
def classify(v):
|
||||||
if v <= q1:
|
if v <= q1:
|
||||||
return 'BR3'
|
|
||||||
elif v <= q2:
|
|
||||||
return 'BR2'
|
return 'BR2'
|
||||||
elif v <= q3:
|
elif v <= q2:
|
||||||
return 'BR1'
|
return 'BR1'
|
||||||
elif v <= q4:
|
elif v <= q3:
|
||||||
return 'RG'
|
return 'RG'
|
||||||
elif v <= q5:
|
elif v <= q4:
|
||||||
return 'BU1'
|
return 'BU1'
|
||||||
elif v <= q6:
|
|
||||||
return 'BU2'
|
|
||||||
else:
|
else:
|
||||||
return 'BU3'
|
return 'BU2'
|
||||||
|
|
||||||
|
# q = df['slope_norm'].quantile([0.7, 0.21, 0.35, 0.65, 0.79, 0.93]).values
|
||||||
|
# q1, q2, q3, q4, q5, q6 = q
|
||||||
|
#
|
||||||
|
# def classify(v):
|
||||||
|
# if v <= q1:
|
||||||
|
# return 'BR3'
|
||||||
|
# elif v <= q2:
|
||||||
|
# return 'BR2'
|
||||||
|
# elif v <= q3:
|
||||||
|
# return 'BR1'
|
||||||
|
# elif v <= q4:
|
||||||
|
# return 'RG'
|
||||||
|
# elif v <= q5:
|
||||||
|
# return 'BU1'
|
||||||
|
# elif v <= q6:
|
||||||
|
# return 'BU2'
|
||||||
|
# else:
|
||||||
|
# return 'BU3'
|
||||||
|
|
||||||
df['trend_class'] = df['slope_norm'].apply(classify)
|
df['trend_class'] = df['slope_norm'].apply(classify)
|
||||||
|
|
||||||
@@ -100,7 +123,7 @@ if trend is not None and start_idx is not None:
|
|||||||
|
|
||||||
# --- extraire les 5 plus longs segments par classe ---
|
# --- extraire les 5 plus longs segments par classe ---
|
||||||
top_segments_by_class = {}
|
top_segments_by_class = {}
|
||||||
for cls in ['BR3','BR2','BR1','RG','BU1','BU2','BU3']:
|
for cls in ['BR2','BR1','RG','BU1','BU2']:
|
||||||
cls_segments = [(t,s,e) for t,s,e in segments if t==cls]
|
cls_segments = [(t,s,e) for t,s,e in segments if t==cls]
|
||||||
# calcul de la durée
|
# calcul de la durée
|
||||||
cls_segments = [(t,s,e,(e-s).total_seconds()) for t,s,e in cls_segments]
|
cls_segments = [(t,s,e,(e-s).total_seconds()) for t,s,e in cls_segments]
|
||||||
|
|||||||
72
tools/read_trends.py
Normal file
72
tools/read_trends.py
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
import os
|
||||||
|
import json
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
def load_params_tree(base_path="user_data/strategies/params/"):
|
||||||
|
base = Path(base_path)
|
||||||
|
params_tree = {}
|
||||||
|
if not base.exists():
|
||||||
|
raise FileNotFoundError(f"Base path '{base_path}' not found.")
|
||||||
|
|
||||||
|
for pair_dir in base.iterdir():
|
||||||
|
if not pair_dir.is_dir():
|
||||||
|
continue
|
||||||
|
pair = pair_dir.name # ex : BTC-USDT
|
||||||
|
params_tree.setdefault(pair, {})
|
||||||
|
|
||||||
|
for trend_dir in pair_dir.iterdir():
|
||||||
|
if not trend_dir.is_dir():
|
||||||
|
continue
|
||||||
|
trend = trend_dir.name # ex : bull / bear / range
|
||||||
|
params_tree[pair].setdefault(trend, [])
|
||||||
|
|
||||||
|
for file in trend_dir.glob("*-hyperopt_result.json"):
|
||||||
|
filename = file.name
|
||||||
|
|
||||||
|
# Extraire START et END
|
||||||
|
try:
|
||||||
|
prefix = filename.replace("-hyperopt_result.json", "")
|
||||||
|
start, end = prefix.split("-", 1) # split en 2
|
||||||
|
except Exception:
|
||||||
|
start = None
|
||||||
|
end = None
|
||||||
|
|
||||||
|
# Lire le JSON
|
||||||
|
try:
|
||||||
|
with open(file, "r") as f:
|
||||||
|
content = json.load(f)
|
||||||
|
except Exception as err:
|
||||||
|
content = {"error": str(err)}
|
||||||
|
|
||||||
|
params_tree[pair][trend].append({
|
||||||
|
"start": start,
|
||||||
|
"end": end,
|
||||||
|
"file": str(file),
|
||||||
|
"content": content,
|
||||||
|
})
|
||||||
|
|
||||||
|
return params_tree
|
||||||
|
|
||||||
|
def getTrend(data, pair, trend, space, param):
|
||||||
|
return data[pair][trend][0]['content']['params'][space][param]
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
data = load_params_tree("user_data/strategies/params/")
|
||||||
|
# print(data)
|
||||||
|
# Test affichage minimal
|
||||||
|
for pair, trends in data.items():
|
||||||
|
for trend, entries in trends.items():
|
||||||
|
if entries:
|
||||||
|
indic_5m = getTrend(data, pair, trend, 'buy', 'indic_5m')
|
||||||
|
indic_deriv1_5m = getTrend(data, pair, trend, 'buy', 'indic_deriv1_5m')
|
||||||
|
indic_deriv2_5m = getTrend(data, pair, trend, 'buy', 'indic_deriv2_5m')
|
||||||
|
|
||||||
|
indic_5m_sell = getTrend(data, pair, trend, 'sell', 'indic_5m_sell')
|
||||||
|
indic_deriv1_5m_sell = getTrend(data, pair, trend, 'sell', 'indic_deriv1_5m_sell')
|
||||||
|
indic_deriv2_5m_sell = getTrend(data, pair, trend, 'sell', 'indic_deriv2_5m_sell')
|
||||||
|
|
||||||
|
print(f"{pair} -> {trend} -> {indic_5m} {indic_deriv1_5m} {indic_deriv2_5m} {indic_5m_sell} {indic_deriv1_5m_sell} {indic_deriv2_5m_sell}")
|
||||||
|
# for entry in entries:
|
||||||
|
# print(entry)
|
||||||
@@ -47,10 +47,10 @@ while read -r PAIR; do
|
|||||||
continue
|
continue
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ "$START" < "2024-09-01" ]]; then
|
# if [[ "$START" < "2024-09-01" ]]; then
|
||||||
echo "TOO OLD $START"
|
# echo "TOO OLD $START"
|
||||||
continue
|
# continue
|
||||||
fi
|
# fi
|
||||||
|
|
||||||
TIMERANGE="${START//-/}-${END//-/}"
|
TIMERANGE="${START//-/}-${END//-/}"
|
||||||
echo "Running hyperopt for $PAIR $REGIME with timerange $TIMERANGE"
|
echo "Running hyperopt for $PAIR $REGIME with timerange $TIMERANGE"
|
||||||
@@ -63,7 +63,7 @@ while read -r PAIR; do
|
|||||||
|
|
||||||
# COLUMNS=200 LINES=40 script -q -c "
|
# COLUMNS=200 LINES=40 script -q -c "
|
||||||
|
|
||||||
freqtrade hyperopt --strategy $STRATEGIE --config user_data/config.json --hyperopt-loss OnlyProfitHyperOptLoss --timerange $TIMERANGE --timeframe 5m --spaces sell buy protection --pair $converted -e 80 -j7
|
freqtrade hyperopt --strategy $STRATEGIE --config user_data/config.json --hyperopt-loss OnlyProfitHyperOptLoss --timerange $TIMERANGE --timeframe 5m --spaces sell buy --pair $converted -e 80 -j7 --print-all
|
||||||
|
|
||||||
echo "Saved hyperopt output to $OUTPUT_JSON"
|
echo "Saved hyperopt output to $OUTPUT_JSON"
|
||||||
|
|
||||||
|
|||||||
41
tools/statistique/ewm.py
Normal file
41
tools/statistique/ewm.py
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
import pandas as pd
|
||||||
|
import numpy as np
|
||||||
|
import matplotlib.pyplot as plt
|
||||||
|
|
||||||
|
np.random.seed(42)
|
||||||
|
|
||||||
|
# Générer 100 valeurs simulant un prix réel avec fluctuations
|
||||||
|
t = np.arange(100)
|
||||||
|
trend = np.sin(t/10) * 2 # tendance ondulante
|
||||||
|
noise = np.random.randn(100) * 0.5 # bruit
|
||||||
|
prices = 50 + trend + noise # prix centré autour de 50
|
||||||
|
|
||||||
|
df = pd.DataFrame({"price": prices})
|
||||||
|
|
||||||
|
# Rolling simple sur 5 périodes
|
||||||
|
df["rolling5"] = df["price"].rolling(5).mean()
|
||||||
|
|
||||||
|
# EMA plus réactive (span=5)
|
||||||
|
# EMA5 standard
|
||||||
|
df["ema5"] = df["price"].ewm(span=5, adjust=False).mean()
|
||||||
|
|
||||||
|
# EMA5 “lissée” avec double application
|
||||||
|
df["ema5_smooth"] = df["price"].ewm(span=5, adjust=False).mean().ewm(span=5, adjust=False).mean()
|
||||||
|
|
||||||
|
|
||||||
|
# EMA plus lissée (span=20)
|
||||||
|
df["ema20"] = df["price"].ewm(span=20, adjust=False).mean()
|
||||||
|
|
||||||
|
# Plot
|
||||||
|
plt.figure(figsize=(12,6))
|
||||||
|
plt.plot(df["price"], label="Prix", color='black', alpha=0.6)
|
||||||
|
plt.plot(df["rolling5"], label="Rolling 5", linestyle="--", color='blue')
|
||||||
|
plt.plot(df["ema5"], label="EMA 5", color='red')
|
||||||
|
plt.plot(df["ema5_smooth"], label="EMA 5S", color='blue')
|
||||||
|
plt.plot(df["ema20"], label="EMA 20", color='green')
|
||||||
|
plt.title("Rolling vs Exponential Moving Average (prix réaliste)")
|
||||||
|
plt.xlabel("Période")
|
||||||
|
plt.ylabel("Prix")
|
||||||
|
plt.legend()
|
||||||
|
plt.grid(True)
|
||||||
|
plt.show()
|
||||||
27
tools/statistique/savgol.py
Normal file
27
tools/statistique/savgol.py
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
import pandas as pd
|
||||||
|
import numpy as np
|
||||||
|
import matplotlib.pyplot as plt
|
||||||
|
from scipy.interpolate import make_interp_spline
|
||||||
|
from scipy.signal import savgol_filter
|
||||||
|
|
||||||
|
np.random.seed(42)
|
||||||
|
|
||||||
|
# Générer 100 valeurs simulant un prix réel avec fluctuations
|
||||||
|
t = np.arange(100)
|
||||||
|
trend = np.sin(t/10) * 2 # tendance ondulante
|
||||||
|
noise = np.random.randn(100) * 0.5 # bruit
|
||||||
|
prices = 50 + trend + noise # prix centré autour de 50
|
||||||
|
|
||||||
|
df = pd.DataFrame({"price": prices})
|
||||||
|
|
||||||
|
df["ema5"] = df["price"].ewm(span=5, adjust=False).mean()
|
||||||
|
# ATTENTION cela regarde dans le futur
|
||||||
|
df["ema5_savgol"] = savgol_filter(df["ema5"], window_length=21, polyorder=3)
|
||||||
|
|
||||||
|
# Plot
|
||||||
|
# fenetre=21 points, poly order 3
|
||||||
|
plt.plot(df["price"], alpha=0.5, label="Prix")
|
||||||
|
plt.plot(df["ema5_savgol"], label="EMA5 lissée Savitzky-Golay", color="red")
|
||||||
|
plt.legend()
|
||||||
|
plt.show()
|
||||||
|
|
||||||
35
tools/statistique/spline.py
Normal file
35
tools/statistique/spline.py
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
import pandas as pd
|
||||||
|
import numpy as np
|
||||||
|
import matplotlib.pyplot as plt
|
||||||
|
from scipy.interpolate import make_interp_spline
|
||||||
|
|
||||||
|
np.random.seed(42)
|
||||||
|
|
||||||
|
# Générer 100 valeurs simulant un prix réel avec fluctuations
|
||||||
|
t = np.arange(100)
|
||||||
|
trend = np.sin(t/10) * 2 # tendance ondulante
|
||||||
|
noise = np.random.randn(100) * 0.5 # bruit
|
||||||
|
prices = 50 + trend + noise # prix centré autour de 50
|
||||||
|
|
||||||
|
df = pd.DataFrame({"price": prices})
|
||||||
|
|
||||||
|
df["ema5"] = df["price"].ewm(span=5, adjust=False).mean()
|
||||||
|
|
||||||
|
x = np.arange(len(df))
|
||||||
|
y = df["ema5"].values
|
||||||
|
|
||||||
|
# Créer une nouvelle série de points x plus dense
|
||||||
|
x_smooth = np.linspace(x.min(), x.max(), 300)
|
||||||
|
|
||||||
|
# Spline (B-spline)
|
||||||
|
spl = make_interp_spline(x, y, k=3) # k=3 pour cubic spline
|
||||||
|
y_smooth = spl(x_smooth)
|
||||||
|
|
||||||
|
# Plot
|
||||||
|
plt.figure(figsize=(12,6))
|
||||||
|
plt.plot(df["price"], label="Prix", alpha=0.5, color="black")
|
||||||
|
plt.plot(df["ema5"], label="EMA 5", color='blue')
|
||||||
|
plt.plot(x_smooth, y_smooth, label="EMA5 lissée Bézier", color="red")
|
||||||
|
plt.title("EMA5 très lisse avec spline")
|
||||||
|
plt.legend()
|
||||||
|
plt.show()
|
||||||
Reference in New Issue
Block a user