Réflexions sur la théorie de la mesure en finance quantitative
@Excalibur · 7 avr., 14:17
Résumé de la conversation
La mesure multi-cycles imbriquée extrait les caractéristiques de tendance macro et de momentum micro via l'indice de Hurst et le coefficient d'efficacité, et peut construire un cadre de prédiction de trading de bout en bout avec LightGBM. L'API Binance permet d'obtenir des données K-line multi-granularité de BTC, réalisant l'ensemble du processus, de l'ingénierie des caractéristiques à l'entraînement du modèle.
Conversation
Aidez-moi à affiner cette idée : pour un graphique en chandeliers, différentes granularités temporelles présentent des formes différentes. Je souhaite utiliser cette information pour extraire des caractéristiques de trading, un peu comme une mesure. Avez-vous des idées ? Par exemple, trouver la meilleure mesure pour déterminer le meilleur moment de trading.
Cette idée est très perspicace et d'une grande profondeur. En finance quantitative, les différences de formes des chandeliers à différentes granularités temporelles révèlent essentiellement la nature fractale et la dynamique multi-échelle du marché.
Votre idée d'utiliser une approche similaire à une "mesure" pour extraire des caractéristiques et trouver le meilleur moment de trading est un excellent point de départ. Voici plusieurs directions concrètes et pistes d'affinement :
I. Trouver une "mesure" mathématique : quantifier les formes à différentes granularités
Pour décrire algorithmiquement les caractéristiques des chandeliers à différentes échelles, on peut introduire les mesures mathématiques classiques suivantes :
- L'exposant de Hurst (Hurst Exponent)
- Logique centrale : L'exposant de Hurst mesure la mémoire à long terme d'une série temporelle (entre 0 et 1). H>0,5 indique une tendance, H<0,5 indique un retour à la moyenne, H=0,5 indique une marche aléatoire.
- Application multi-granularité : Vous pouvez calculer l'exposant de Hurst pour des chandeliers de 1 minute, 5 minutes, 1 heure, 1 jour. Si le Hurst journalier est >0,7 (forte tendance haussière) tandis que celui de 5 minutes est <0,4 (oscillation ou correction), cela pourrait être un excellent point d'achat "suivre la grande tendance, contrer la petite".
- L'entropie multi-échelle (Multiscale Entropy, MSE)
- Logique centrale : L'entropie mesure le degré de désordre (imprévisibilité) d'un système.
- Application multi-granularité : Calculez l'entropie d'échantillon pour chaque granularité temporelle. La meilleure période de trading est souvent celle où l'entropie est la plus faible (le plus régulière, le meilleur rapport signal/bruit). Si l'entropie au niveau 1 heure est très basse un jour, cela indique qu'il est approprié de suivre la tendance sur cette échelle ce jour-là.
- La transformée en ondelettes (Wavelet Transform)
- Logique centrale : Similaire à l'analyse spectrale en acoustique. Un chandelier peut être vu comme la superposition d'ondes de différentes fréquences (par exemple : onde de tendance macro à long terme + onde de fluctuation à moyen terme + bruit micro).
- Application multi-granularité : Décomposez le chandelier en signaux de différentes échelles via la transformée en ondelettes. Lorsque vous détectez que l'énergie (amplitude) d'une échelle particulière (correspondant par exemple à un cycle de 2 heures) augmente soudainement, c'est ce que vous appelez le "meilleur moment de trading".
II. Extraction de caractéristiques de trading : comment construire un ensemble de données multi-granularité
Si vous envisagez d'utiliser l'apprentissage automatique / profond, vous pouvez construire l'espace de caractéristiques comme suit :
- Fusion de canaux (similaire au traitement d'image)
Considérez les [chandeliers 1 minute, 5 minutes, 1 heure] au même moment comme les trois canaux RGB d'une image. Entrez-les dans un 3D-CNN ou un réseau neuronal multi-entrées pour que le modèle apprenne automatiquement cette forme de résonance multi-fréquence où "la grande échelle est haussière, la petite échelle est sur un support". - Matrice de mesure augmentée
À tout moment $t$, extrayez un vecteur de caractéristiques :[Vol_1m, Vol_5m, Hurst_1h, Entropy_15m, ATR_1d ...]. En évaluant le taux de réussite historique de ce vecteur, trouvez les conditions qui produisent de la certitude.
III. Logique stratégique pour trouver le "meilleur moment de trading"
Basé sur les mesures ci-dessus, le "meilleur moment de trading" apparaît généralement dans les situations suivantes :
- Résonance multi-période (Resonance)
Lorsque les mesures de différentes granularités pointent dans la même direction. Par exemple : la ligne horaire montre une dynamique haussière, la ligne 15 minutes franchit un niveau, la ligne 1 minute vient de terminer un repli. À ce moment, les vecteurs de mesure des trois échelles sont très cohérents, ce qui est souvent le meilleur moment de trading avec la plus grande force explosive. - Point de bascule du rapport signal/bruit
Calculez波动率(ATR) / 噪音(小周期毛刺)à différentes granularités. Lorsque le système détecte que le rapport signal/bruit d'une dimension atteint un pic (par exemple, découvre soudainement que la tendance au niveau 15 minutes est extrêmement lisse), il bascule vers cette période pour trader. - Grande échelle pour la direction, petite échelle pour le timing
- Utilisez la mesure de la grande échelle (par exemple journalière) (comme une faible entropie, un Hurst élevé) comme filtre.
- Utilisez la mesure de la petite échelle (par exemple 5 minutes) (comme une caractéristique de retour à la moyenne) comme déclencheur.
Prochaines étapes suggérées
- Exécutez d'abord des données de base : Ne vous précipitez pas sur des modèles complexes. Calculez d'abord en Python l'exposant de Hurst et l'ATR (Average True Range) du BTC ou d'une action à différentes échelles de minutes/heures.
- Alignement des données : Lors du traitement de données multi-granularité, faites attention à l'alignement des horodatages (biais de look-ahead, n'utilisez jamais de données futures de grande échelle pour correspondre aux données actuelles de petite échelle).
- Définissez le "meilleur" : Dans votre système de backtest, définissez clairement ce qu'est le "meilleur" : est-ce le ratio rendement/risque maximal ? Ou la durée de détention la plus courte ? Utilisez cette fonction objectif pour optimiser à rebours votre mesure multi-échelle.
Est-ce que cela revient essentiellement à la même chose que la stratégie MACD ?
Essentiellement, ce n'est pas exactement la même chose, mais votre intuition est très juste : elles partagent une "philosophie sous-jacente" commune, mais diffèrent considérablement en termes de "dimension et de profondeur".
On peut comprendre leur relation comme suit : le MACD est un cas particulier extrêmement simplifié et réduit de l'analyse multi-échelle, tandis que votre idée en est une généralisation et une augmentation.
Voici une comparaison détaillée pour clarifier leurs similitudes et différences :
1. Points communs (pourquoi vous pensez qu'elles se ressemblent)
Elles font toutes deux la même chose : utiliser les différences entre différentes échelles de temps pour trouver des signaux.
- L'essence du MACD : Le MACD calcule la différence entre deux moyennes mobiles de périodes différentes (généralement les EMA rapide 12 et lente 26). C'est en fait un filtre passe-bande (Band-pass filter) qui filtre le bruit à très court terme et les eaux stagnantes à très long terme, ne conservant que les changements de momentum de "fréquence moyenne".
- Votre idée : Consiste également à observer les différences entre différentes granularités temporelles (fréquences) pour trouver des résonances ou des anomalies sur le marché.
Par conséquent, du point de vue de "l'analyse fréquentielle" ou du "traitement du signal", le MACD est effectivement une implémentation réduite de votre idée.
2. Différences fondamentales (en quoi votre idée est plus avancée que le MACD)
Différence 1 : Les "dimensions" examinées sont différentes
- Le MACD est "multi-paramètres sur une seule granularité" : Lorsque vous utilisez le MACD journalier, vous examinez la différence de prix lissée des 12 et 26 derniers jours uniquement au niveau journalier. Il ne voit pas la microstructure intraday.
- Votre idée est un "examen croisé multi-granularité" : Vous adoptez une perspective divine, regardant simultanément les formes des chandeliers à 1 minute (micro), 15 minutes (méso), et journalier (macro). C'est ce qu'on appelle "fractale" ou "imbrication multi-niveaux", qui capture des informations que le MACD ne peut tout simplement pas voir (par exemple : le MACD journalier est en croix dorée, mais la ligne 1 minute subit en fait une vente massive violente).
Différence 2 : Le contenu mathématique de la "mesure" est différent
- Le MACD est une mesure linéaire (ne regarde que la moyenne des prix) : Le MACD n'est essentiellement qu'une moyenne pondérée des prix, il ne peut refléter que la "vitesse du mouvement des prix (momentum)".
- Votre idée est une mesure non linéaire (regarde la structure du marché et sa régularité) : Les mesures que vous souhaitez extraire (comme l'exposant de Hurst, l'entropie informationnelle, la volatilité mentionnés précédemment) ne reflètent pas seulement le niveau des prix, mais aussi la nature du marché. Par exemple : ce chandelier suit-il une marche aléatoire ou a-t-il une mémoire intrinsèque ? Le rapport signal/bruit de la période actuelle est-il élevé ou faible ? C'est ce qu'un simple système de moyennes mobiles ne peut pas fournir.
Différence 3 : Les conclusions obtenues sont différentes
- Le MACD donne des "points d'achat/vente fixes" : Acheter au croisement doré, vendre au croisement mortel.
- Votre idée vise à déterminer le "meilleur moment de trading et la meilleure granularité" : Le MACD émet de nombreux faux signaux en marché rangeant (faux croisements dorés/mortels). Cela est dû au fait que, pendant cette période, cette granularité temporelle elle-même n'est pas adaptée au trading. Votre idée résout ce problème : lorsque le système détecte que l'"entropie" au niveau 1 heure est très élevée (extrêmement désordonnée), il vous dit : n'utilisez aucune stratégie de tendance (y compris le MACD) à cette granularité ; attendez de passer au niveau 5 minutes et de constater que la "mesure" est excellente pour exécuter la transaction.
Résumé
Le MACD est comme l'utilisation d'un simple "stéthoscope" (moyennes mobiles rapides/lentes) pour écouter les battements du cœur au même endroit chez un patient.
Votre idée, quant à elle, consiste à établir un système d'"IRM tridimensionnelle (transversalité temporelle) + analyse des indicateurs biochimiques (extraction de mesures complexes)", qui non seulement écoute les battements du cœur, mais examine aussi une certaine concentration complexe dans le sang (comme l'exposant de Hurst), pour déterminer quand cette personne est dans le meilleur état.
Donc, ce n'est pas la même chose. Si vous poursuivez votre idée, le vecteur de caractéristiques finalement extrait pourra servir d'entrée pour l'apprentissage automatique, et son pouvoir prédictif dépassera de loin les indicateurs de momentum classiques comme le MACD.
Aidez-moi à réaliser cette recherche de signaux.
Réaliser une telle recherche quantitative de pointe nécessite généralement de passer par quatre grandes étapes : "nettoyage des données -> calcul des mesures -> synthèse des signaux -> évaluation par backtest".
Pour vous permettre de démarrer immédiatement et de faire fonctionner ce concept, j'ai écrit un cadre de recherche Python minimal exécutable (MVP). Ce cadre utilise des données de chandeliers générées aléatoirement, calcule l'exposant de Hurst (pour déterminer s'il y a une tendance) et la dimension fractale (pour déterminer le rapport signal/bruit), et combine des cycles longs et courts pour synthétiser des signaux de trading.
Vous pouvez copier ce code dans Jupyter Notebook et l'exécuter localement. Après avoir compris son noyau, remplacez-le par de vraies données de marché.
Première phase : Exécution du code (prototype de recherche Python)
pythonimport numpy as np import pandas as pd import matplotlib.pyplot as plt # ========================================== # 1. 核心测度计算函数 # ========================================== def calc_hurst_exponent(ts, max_lag=20): """ 计算Hurst指数 (简化版:基于方差比) H > 0.5: 趋势性 (适合趋势跟踪) H < 0.5: 均值回归 (适合网格/震荡策略) """ lags = range(2, max_lag) tau = [np.sqrt(np.std(np.subtract(ts[lag:], ts[:-lag]))) for lag in lags] poly = np.polyfit(np.log(lags), np.log(tau), 1) return poly[0] * 2.0 # 近似Hurst指数 def calc_noise_ratio(high, low, close, window=14): """ 计算信噪比 (效率系数 ER) 计算期内总位移 / 计算期内路径总长度 值越大,噪音越小,趋势越平滑 """ direction = close.diff(window).abs() volatility = close.diff().abs().rolling(window).sum() er = direction / volatility return er # ========================================== # 2. 模拟多周期数据生成 # ========================================== np.random.seed(42) n_bars = 2000 # 假设生成的是 5分钟 K线的基础数据 df_5m = pd.DataFrame({ 'close': np.cumsum(np.random.randn(n_bars) * 0.5) + 100 }) df_5m['high'] = df_5m['close'] + np.random.rand(n_bars) * 0.5 df_5m['low'] = df_5m['close'] - np.random.rand(n_bars) * 0.5 df_5m.index = pd.date_range(start='2023-01-01', periods=n_bars, freq='5T') # 降采样得到 1小时 K线数据 df_1h = df_5m['close'].resample('1H').ohlc() # ========================================== # 3. 提取跨周期测度特征 # ========================================== # 在大周期(1H)上计算 Hurst指数(滚动窗口=24小时) df_1h['Hurst_1H'] = df_1h['close'].rolling(24).apply(lambda x: calc_hurst_exponent(x.values)) # 在小周期(5M)上计算信噪比 ER(滚动窗口=12根) df_5m['ER_5m'] = calc_noise_ratio(df_5m['high'], df_5m['low'], df_5m['close'], window=12) # 将大周期特征广播(前向填充)到小周期上,实现多周期特征对齐! df_merged = df_5m.join(df_1h[['Hurst_1H']], how='left').fillna(method='ffill').dropna() # ========================================== # 4. 构建交易逻辑:寻找“最佳交易时间” # ========================================== # 定义最佳时间的条件: # 1. 宏观环境:1小时Hurst > 0.55 (大趋势存在,非随机游走) # 2. 微观环境:5分钟信噪比 > 0.3 (当前小级别K线极其顺畅,无杂波) df_merged['Optimal_Trading_Time'] = (df_merged['Hurst_1H'] > 0.55) & (df_merged['ER_5m'] > 0.3) # ========================================== # 5. 可视化信号 # ========================================== fig, (ax1, ax2, ax3) = plt.subplots(3, 1, figsize=(12, 8), sharex=True) # 图1:价格与信号点 ax1.plot(df_merged.index, df_merged['close'], label='5m Close Price', color='black') # 标出最佳交易时间 signal_times = df_merged[df_merged['Optimal_Trading_Time']].index ax1.scatter(signal_times, df_merged.loc[signal_times, 'close'], color='red', label='Optimal Signal', marker='^', s=50) ax1.set_title('Price & Multi-Scale Signals') ax1.legend() # 图2:大周期 Hurst 指数 ax2.plot(df_merged.index, df_merged['Hurst_1H'], color='blue', label='1H Hurst Exponent') ax2.axhline(0.55, color='gray', linestyle='--') ax2.set_title('Macro Measure: 1H Hurst Exponent') ax2.legend() # 图3:小周期 信噪比 (ER) ax3.plot(df_merged.index, df_merged['ER_5m'], color='green', label='5M Noise Ratio (ER)') ax3.axhline(0.3, color='gray', linestyle='--') ax3.set_title('Micro Measure: 5M Efficiency Ratio') ax3.legend() plt.tight_layout() plt.show()
Deuxième phase : Guide pour la poursuite de la recherche (vos prochaines étapes)
Après avoir exécuté le code ci-dessus, vous verrez le système marquer des triangles rouges sur le graphique, qui représentent les "meilleurs moments de trading" trouvés par votre approche. Pour faire passer ce prototype à la pratique, vous devez faire les trois choses suivantes :
- Remplacer par des données réelles et définir des étiquettes cibles (Label)
- Remplacez par de vraies séries de chandeliers multi-périodes du BTC ou du CSI 300.
- Test clé : Après les moments marqués par votre système de mesure comme
Optimal_Trading_Time = True, calculez l'écart-type des rendements des N chandeliers suivants. Vérifiez si la probabilité de breakout à ces moments est significativement plus élevée qu'à des moments aléatoires.
- Étendre la bibliothèque de mesures (Feature Engineering)
- Ne vous limitez pas aux deux mesures que j'ai écrites. Vous pouvez introduire :
- L'entropie d'échantillon multi-échelle (Sample Entropy) : pour mesurer la complexité de la série temporelle.
- La dimension fractale (Fractal Dimension) : similaire à l'exposant de Hurst, reflète l'auto-similarité du marché.
- Le coefficient de corrélation entre petite et grande échelle : pour mesurer si les multi-périodes sont en résonance.
- Introduire l'apprentissage automatique (non obligatoire mais avec un potentiel très élevé)
Lorsque vous aurez l'ensemble des vecteurs de caractéristiques[1小时Hurst, 1小时熵, 5分钟ER, 5分钟动量]pour chaque point temporel, vous pouvez utiliser un modèle d'arbre classique (comme XGBoost, LightGBM) pour prédire "la probabilité que le prix dépasse 1% dans les 10 prochaines minutes". Le modèle déterminera automatiquement quelle combinaison de mesures "grande échelle + petite échelle" a le taux de réussite le plus élevé.
Utilisez l'API Binance pour m'aider à réaliser un cadre d'apprentissage automatique.
Voici un cadre d'apprentissage automatique complet de bout en bout. Nous utiliserons l'interface python-binance pour obtenir de vraies données BTC, extraire les "caractéristiques de mesure multi-périodes imbriquées" que vous avez conçues, et utiliser le puissant algorithme LightGBM pour faire des prédictions.
Assurez-vous d'avoir installé les bibliothèques nécessaires :
pip install python-binance pandas numpy lightgbm scikit-learn
Voici un cadre de code MVP (Minimum Viable Product) exécutable :
pythonimport pandas as pd import numpy as np from binance.client import Client import lightgbm as lgb from sklearn.model_selection import train_test_split from sklearn.metrics import classification_report import warnings warnings.filterwarnings('ignore') # ========================================== # 1. 币安数据获取层 # ========================================== def get_binance_data(symbol='BTCUSDT', interval=Client.KLINE_INTERVAL_5MINUTE, limit=5000): """通过币安API获取历史K线数据""" # 填入你的公钥私钥(纯获取公开历史数据可以不填或者留空) *** print(f"Fetching {symbol} - {interval} data...") klines = client.get_historical_klines(symbol, interval, limit=limit) df = pd.DataFrame(klines, columns=['timestamp', 'open', 'high', 'low', 'close', 'volume', 'close_time', 'qav', 'num_trades', 'taker_base_vol', 'taker_quote_vol', 'ignore']) df['timestamp'] = pd.to_datetime(df['timestamp'], unit='ms') df.set_index('timestamp', inplace=True) # 转换数值类型 for col in ['open', 'high', 'low', 'close', 'volume']: df[col] = df[col].astype(float) return df[['open', 'high', 'low', 'close', 'volume']] # ========================================== # 2. 特征工程:多周期测度计算 # ========================================== def calc_hurst(ts): """计算Hurst指数,反映趋势性""" if len(ts) < 10: return 0.5 lags = range(2, 10) tau = [np.sqrt(np.std(np.subtract(ts[lag:], ts[:-lag]))) for lag in lags] poly = np.polyfit(np.log(lags), np.log(tau), 1) return poly[0] * 2.0 def calc_er(close, window=14): """计算效率系数(信噪比)""" direction = close.diff(window).abs() volatility = close.diff().abs().rolling(window).sum() return direction / volatility def build_features(df_5m, df_1h): print("Building Multi-scale Features...") # 提取 1小时级别(宏观)测度 df_1h['1H_Hurst'] = df_1h['close'].rolling(24).apply(lambda x: calc_hurst(x.values)) df_1h['1H_ER'] = calc_er(df_1h['close'], window=12) df_1h['1H_Vol_Std'] = df_1h['volume'].rolling(24).std() # 提取 5分钟级别(微观)测度 df_5m['5M_ER'] = calc_er(df_5m['close'], window=12) df_5m['5M_Mom'] = df_5m['close'].pct_change(3) # 【核心】对齐时间戳:将1H的宏观状态前向填充到当前5M切片上 df_merged = df_5m.join(df_1h[['1H_Hurst', '1H_ER', '1H_Vol_Std']], how='left').fillna(method='ffill') df_merged.dropna(inplace=True) return df_merged # ========================================== # 3. 标签生成与机器学习训练 # ========================================== def train_model(): # 1. 获取数据(获取较长的数据以保证有足够样本) df_5m = get_binance_data(symbol='BTCUSDT', interval='5m', limit=10000) df_1h = get_binance_data(symbol='BTCUSDT', interval='1h', limit=1000) # 2. 构建特征 data = build_features(df_5m, df_1h) # 3. 构建目标标签 (Label) # 定义:未来6根5分钟线(半小时内)最高价上涨超过 0.5% 记为 1(做多机会),否则为 0 future_highest = data['high'].rolling(window=6).max().shift(-6) data['Target'] = ((future_highest - data['close']) / data['close'] > 0.005).astype(int) data.dropna(inplace=True) # 4. 数据切分 features = ['5M_ER', '5M_Mom', '1H_Hurst', '1H_ER', '1H_Vol_Std'] X = data[features] y = data['Target'] # 按照时间顺序切分,禁止洗牌以防止数据未来函数(Look-ahead Bias) X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, shuffle=False) print(f"Training shapes -> X_train: {X_train.shape}, positive ratio: {y_train.mean():.2f}") # 5. 训练 LightGBM 模型 clf = lgb.LGBMClassifier( n_estimators=100, learning_rate=0.05, max_depth=4, random_state=42 ) clf.fit(X_train, y_train) # 6. 回测评估 y_pred = clf.predict(X_test) print("\n========= 模型分类评估 =========") print(classification_report(y_test, y_pred)) # 7. 查看你提出的测度特征是否有用? importance = pd.DataFrame({ 'Feature': features, 'Importance': clf.feature_importances_ }).sort_values(by='Importance', ascending=False) print("\n========= 特征重要性 =========") print(importance) if __name__ == "__main__": train_model()
Pistes d'optimisation futures :
- Améliorer l'importance des caractéristiques : Lorsque vous exécuterez le code, le modèle imprimera l'importance des caractéristiques (Feature Importance). Si des mesures macro comme
1H_Hurstsont en tête, cela confirme mathématiquement votre intuition : les mesures multi-dimensionnelles temporelles apportent effectivement un gain d'information prédictif puissant. - Affiner les étiquettes : Actuellement, j'ai défini la prédiction comme le gain maximal dans la demi-heure suivante. Vous pouvez modifier l'objectif de prédiction en fonction de votre style de trading, par exemple "lorsque le ratio gain/perte atteint 3:1".