
2026年重磅升级已全面落地!欢迎加入专注财经数据与量化投研的【数据科学实战】知识星球!您将获取持续更新的《财经数据宝典》与《量化投研宝典》,双典协同提供系统化指引;星球内含300篇以上独有高质量文章,深度覆盖策略开发、因子分析、风险管理等核心领域,内容基本每日更新;同步推出的「量化因子专题教程」系列(含完整可运行代码与实战案例),系统详解因子构建、回测与优化全流程,并实现日更迭代。我们持续扩充独家内容资源,全方位赋能您的投研效率与专业成长。无论您是量化新手还是资深研究者,这里都是助您少走弯路、事半功倍的理想伙伴,携手共探数据驱动的投资未来!
你有没有想过,核反应堆模拟、地震余震、雪崩和股市崩盘之间有什么共同点?
答案是:它们都遵循可测量的混沌与秩序规律。
大多数交易者仍在使用 MACD、RSI 等传统技术分析指标,但这些指标太"拥挤"了——如果它们真能让人稳定赚钱,那每个人都该是富翁了。
最近,一篇来自量化研究者的文章引起了广泛关注。他从统计物理学、量子力学、随机微积分、信息论甚至地震学中汲取灵感,开发了 8 个创新的量化指标(本文介绍前 4 个),并在 TradingView 上免费发布。令人惊讶的是,对冲基金主动联系他,表示正在使用这些指标。
本文将为你解读这 4 个指标背后的核心原理,并提供 Python 实现案例,帮助你用代码理解量化交易的前沿思维。
传统的风险价值(VaR)假设市场收益率服从正态(高斯)分布,但现实中市场经常出现"肥尾"现象——即极端暴涨或暴跌的概率远高于正态分布的预测。
EVaR 使用了非广延统计力学中的 Tsallis 熵,通过 q-指数函数来捕捉这种肥尾行为:
当 q → 1 时,退化为标准指数分布;当 q ≠ 1 时,能捕捉到"黑天鹅"级别的幂律尾部。
该指标根据当前的风险水平自动调整仓位大小:高风险时期缩减仓位,低风险环境下扩大仓位。这对于杠杆管理非常实用。
import numpy as np
import pandas as pd
def tsallis_q_exponential(x, q):
"""计算 Tsallis q-指数函数"""
if q == 1:
return np.exp(x)
base = 1 + (1 - q) * x
# 确保底数为正,避免无效计算
base = np.maximum(base, 1e-10)
return base ** (1 / (1 - q))
def calculate_evar(returns, q=1.5, lookback=100, confidence=0.95):
"""
计算基于 Tsallis 熵的 EVaR(Entropic Value at Risk)
参数:
returns: 收益率序列
q: Tsallis 参数,控制肥尾程度,q > 1 表示肥尾
lookback: 回看窗口长度
confidence: 置信水平
"""
evar_values = []
for i in range(lookback, len(returns)):
# 取回看窗口内的收益率数据
window = returns[i - lookback:i]
# 计算窗口内的均值和标准差
mu = np.mean(window)
sigma = np.std(window)
if sigma == 0:
evar_values.append(0)
continue
# 使用 q-指数分布计算分位数作为风险度量
# 通过 Tsallis 分布逼近尾部风险
z_score = np.percentile(window, (1 - confidence) * 100)
# q-调整后的风险值:肥尾修正
q_adjustment = tsallis_q_exponential(-abs(z_score / sigma), q)
evar = abs(z_score) * q_adjustment
evar_values.append(evar)
return evar_values
def position_sizing(evar_values, max_risk=0.02, account_size=10000):
"""
根据 EVaR 动态调整仓位大小
参数:
evar_values: EVaR 风险值序列
max_risk: 单笔最大风险比例(默认 2%)
account_size: 账户总资金
"""
positions = []
for evar in evar_values:
if evar > 0:
# 风险越高,仓位越小
position_pct = min(max_risk / evar, 1.0)
else:
position_pct = 1.0
positions.append(position_pct * account_size)
return positions
# ===== 案例演示 =====
np.random.seed(42)
# 模拟带有肥尾特征的收益率数据(t 分布比正态分布更接近真实市场)
simulated_returns = np.random.standard_t(df=4, size=500) * 0.01
evar = calculate_evar(simulated_returns, q=1.5, lookback=100)
positions = position_sizing(evar)
print(f"最新 EVaR 风险值:{evar[-1]:.4f}")
print(f"建议仓位金额:${positions[-1]:.2f}(总资金 $10,000)")
print(f"仓位占比:{positions[-1] / 10000 * 100:.1f}%")想象一堆沙子:你不断往上加沙粒,到了某个临界点,多加一粒就会触发雪崩。
金融市场的运作方式类似。如果价格持续上涨而没有回调,"市场雪崩"的概率就会增大。
该指标应用了物理学家 Per Bak 的自组织临界性(SOC)理论,通过测量价格回撤的幂律指数 α 来判断市场是处于稳定态还是临界态:
α 值的含义如下:
当指标发出临界信号时,应考虑减少风险敞口,因为高波动或"雪崩"可能即将到来。
import numpy as np
def detect_drawdowns(prices, threshold=0.005):
"""
检测价格序列中的回撤事件
参数:
prices: 价格序列
threshold: 最小回撤幅度阈值(默认 0.5%)
返回:
回撤幅度列表
"""
drawdowns = []
peak = prices[0]
for price in prices:
if price > peak:
peak = price # 更新历史最高点
else:
# 计算从最高点的回撤幅度
dd = (peak - price) / peak
if dd >= threshold:
drawdowns.append(dd)
return drawdowns
def estimate_alpha_log_binning(drawdowns, num_bins=15):
"""
使用对数分箱法估计幂律指数 α
参数:
drawdowns: 回撤幅度列表
num_bins: 对数分箱数量
返回:
幂律指数 α
"""
if len(drawdowns) < 10:
return None
drawdowns = np.array(drawdowns)
# 创建对数间隔的分箱边界
log_bins = np.logspace(
np.log10(drawdowns.min()),
np.log10(drawdowns.max()),
num_bins + 1
)
# 统计每个箱中的频次
counts, edges = np.histogram(drawdowns, bins=log_bins)
# 取每个箱的中心点(对数尺度)
bin_centers = (edges[:-1] + edges[1:]) / 2
# 过滤掉空箱
mask = counts > 0
log_x = np.log10(bin_centers[mask])
log_y = np.log10(counts[mask])
# 线性回归拟合幂律指数(斜率的负值即为 α)
if len(log_x) < 2:
return None
coeffs = np.polyfit(log_x, log_y, 1)
alpha = -coeffs[0]
return alpha
def classify_regime(alpha):
"""根据 α 值判断市场所处的临界状态"""
if alpha is None:
return "数据不足"
elif alpha >= 2.8:
return "🟢 高斯区域(稳定):大幅波动罕见"
elif alpha >= 1.8:
return "🟡 过渡区域:正在接近临界状态"
elif alpha >= 1.0:
return "🟠 临界区域:崩盘概率增大"
else:
return "🔴 超临界区域:系统极度脆弱,红色警报"
# ===== 案例演示 =====
np.random.seed(42)
# 模拟一段先涨后跌的价格走势
uptrend = np.cumsum(np.random.uniform(0.1, 0.5, 200)) + 100
downtrend = uptrend[-1] + np.cumsum(np.random.uniform(-0.6, 0.1, 100))
prices = np.concatenate([uptrend, downtrend])
drawdowns = detect_drawdowns(prices)
alpha = estimate_alpha_log_binning(drawdowns)
print(f"检测到的回撤事件数量:{len(drawdowns)}")
print(f"估计的幂律指数 α:{alpha:.2f}")
print(f"市场状态:{classify_regime(alpha)}")传统移动平均线有一个根本矛盾:越平滑就越滞后。小波分析能同时在多个频率分量上分解价格信号,解决了这一难题。
该指标使用的是 Mexican Hat(Ricker)小波,其数学形式为负高斯曲线的归一化二阶导数:
这个函数的形状像一顶墨西哥帽(宽边草帽),因此得名。它借鉴了音频工程和图像处理中的去噪技术,在滤除噪声的同时保留有意义的价格信号。
import numpy as np
def mexican_hat_wavelet(t):
"""
Mexican Hat(Ricker)小波函数
参数:
t: 时间变量
返回:
小波函数值
"""
return (1 - t ** 2) * np.exp(-t ** 2 / 2)
def causal_wavelet_filter(prices, scale=10):
"""
因果小波趋势滤波器(仅使用历史数据,无未来函数)
参数:
prices: 价格序列
scale: 小波尺度参数,越大越平滑
返回:
滤波后的趋势线
"""
n = len(prices)
filtered = np.zeros(n)
for i in range(n):
total_weight = 0
weighted_sum = 0
# 只回看过去的数据点(因果性)
lookback = min(i, scale * 4)
for j in range(lookback + 1):
# 归一化时间变量
t = j / scale
# 计算小波权重(取绝对值作为权重,保证因果性)
w = abs(mexican_hat_wavelet(t)) * np.exp(-t / 2)
weighted_sum += w * prices[i - j]
total_weight += w
if total_weight > 0:
filtered[i] = weighted_sum / total_weight
return filtered
def adaptive_wavelet_filter(prices, base_scale=10, vol_lookback=20):
"""
自适应因果小波滤波器:根据波动率自动调整尺度
参数:
prices: 价格序列
base_scale: 基础小波尺度
vol_lookback: 波动率回看窗口
返回:
自适应滤波后的趋势线
"""
returns = np.diff(np.log(prices)) # 对数收益率
n = len(prices)
filtered = np.zeros(n)
filtered[0] = prices[0]
for i in range(1, n):
# 计算局部波动率
start = max(0, i - vol_lookback)
local_vol = np.std(returns[start:i]) if i > start else 0.01
# 高波动时增大尺度(更平滑),低波动时减小尺度(更灵敏)
median_vol = np.median(np.abs(returns[start:i])) if i > start else 0.01
adaptive_scale = int(base_scale * (local_vol / max(median_vol, 1e-10)))
adaptive_scale = max(3, min(adaptive_scale, base_scale * 3))
# 应用因果小波滤波
total_weight = 0
weighted_sum = 0
lookback = min(i, adaptive_scale * 4)
for j in range(lookback + 1):
t = j / adaptive_scale
w = abs(mexican_hat_wavelet(t)) * np.exp(-t / 2)
weighted_sum += w * prices[i - j]
total_weight += w
filtered[i] = weighted_sum / total_weight if total_weight > 0 else prices[i]
return filtered
# ===== 案例演示 =====
np.random.seed(42)
# 模拟带噪声的趋势价格数据
t = np.arange(500)
trend = 100 + 0.05 * t + 10 * np.sin(t / 50) # 真实趋势
noise = np.random.normal(0, 2, 500) # 市场噪声
prices = trend + noise
# 对比不同方法
sma_20 = np.convolve(prices, np.ones(20) / 20, mode='same') # 20 日简单移动平均
wavelet_trend = adaptive_wavelet_filter(prices, base_scale=10)
print("=== 最近 5 个交易日对比 ===")
print(f"{'日期':<8} {'原始价格':<12} {'SMA(20)':<12} {'小波滤波':<12}")
for i in range(-5, 0):
print(f"Day {500+i:<4} {prices[i]:<12.2f} {sma_20[i]:<12.2f} {wavelet_trend[i]:<12.2f}")大多数指标试图预测方向,而这个指标预测的是时间。
如果你设定了止损和止盈价位,在接下来的 24 小时内触及它们的概率是多少?48 小时呢?
该指标基于随机微积分中的首次穿越时间(First Passage Time,FPT)理论。它假设价格服从几何布朗运动,然后通过统计模拟估算触达目标价格的时间分布。
import numpy as np
def first_passage_time_simulation(
current_price,
target_up,
target_down,
mu,
sigma,
num_simulations=10000,
max_bars=252
):
"""
通过蒙特卡洛模拟估算首次穿越时间分布
参数:
current_price: 当前价格
target_up: 上方目标价(止盈)
target_down: 下方目标价(止损)
mu: 年化收益率(漂移项)
sigma: 年化波动率
num_simulations: 模拟次数
max_bars: 最大模拟步数(交易日)
返回:
上方首次穿越时间列表、下方首次穿越时间列表
"""
dt = 1 / 252 # 每个交易日的时间增量
up_times = [] # 记录触及上方目标的时间
down_times = [] # 记录触及下方目标的时间
for _ in range(num_simulations):
price = current_price
for bar in range(1, max_bars + 1):
# 几何布朗运动模拟
random_shock = np.random.normal(0, 1)
price *= np.exp((mu - 0.5 * sigma ** 2) * dt + sigma * np.sqrt(dt) * random_shock)
# 检查是否触及目标价
if price >= target_up:
up_times.append(bar)
break
elif price <= target_down:
down_times.append(bar)
break
return up_times, down_times
def analyze_fpt_results(up_times, down_times, num_simulations, max_bars):
"""
分析首次穿越时间的模拟结果
参数:
up_times: 上方穿越时间列表
down_times: 下方穿越时间列表
num_simulations: 总模拟次数
max_bars: 最大模拟步数
"""
up_prob = len(up_times) / num_simulations * 100
down_prob = len(down_times) / num_simulations * 100
neither_prob = 100 - up_prob - down_prob
print("=" * 50)
print("首次穿越时间分布分析结果")
print("=" * 50)
print(f"触及止盈的概率:{up_prob:.1f}%")
print(f"触及止损的概率:{down_prob:.1f}%")
print(f"在 {max_bars} 个交易日内均未触及的概率:{neither_prob:.1f}%")
print()
if up_times:
up_arr = np.array(up_times)
print(f"--- 止盈触达时间分布 ---")
print(f" 中位数:{np.median(up_arr):.0f} 个交易日")
print(f" 25 分位:{np.percentile(up_arr, 25):.0f} 个交易日")
print(f" 75 分位:{np.percentile(up_arr, 75):.0f} 个交易日")
if down_times:
down_arr = np.array(down_times)
print(f"--- 止损触达时间分布 ---")
print(f" 中位数:{np.median(down_arr):.0f} 个交易日")
print(f" 25 分位:{np.percentile(down_arr, 25):.0f} 个交易日")
print(f" 75 分位:{np.percentile(down_arr, 75):.0f} 个交易日")
# 给出交易建议
print()
if up_prob > down_prob:
print("📈 交易建议:概率偏向止盈方向,该交易值得考虑。")
elif down_prob > up_prob:
print("📉 交易建议:止损触发概率更高,建议谨慎或调整止盈止损比。")
else:
print("⚖️ 交易建议:上下概率接近,无明显方向性优势。")
# ===== 案例演示 =====
np.random.seed(42)
current_price = 25000 # 假设当前纳斯达克 100 指数价格
target_up = 27500 # 止盈目标:+10%
target_down = 22500 # 止损目标:-10%
annual_return = 0.10 # 假设年化漂移率 10%
annual_volatility = 0.20 # 假设年化波动率 20%
num_sims = 10000 # 模拟次数
max_days = 252 # 最多模拟一年
print(f"当前价格:{current_price}")
print(f"止盈目标:{target_up}(+{(target_up/current_price-1)*100:.0f}%)")
print(f"止损目标:{target_down}({(target_down/current_price-1)*100:.0f}%)")
print(f"模拟次数:{num_sims}")
print()
up_times, down_times = first_passage_time_simulation(
current_price, target_up, target_down,
annual_return, annual_volatility,
num_sims, max_days
)
analyze_fpt_results(up_times, down_times, num_sims, max_days)本文介绍了 4 个从物理学和数学前沿领域借鉴而来的量化交易指标:
第一,EVaR 指标——基于 Tsallis 熵的风险度量,解决了传统 VaR 低估尾部风险的致命缺陷,能够根据风险水平动态调整仓位。
第二,自组织临界性指标——源自 Per Bak 的沙堆模型,通过幂律指数 α 判断市场是否处于崩盘前的临界状态,堪称市场雪崩的早期预警系统。
第三,自适应因果小波趋势滤波器——借鉴了音频处理和图像识别中的小波理论,用一个指标同时展示多时间尺度的趋势,且能根据波动率自动调节灵敏度。
第四,首次穿越时间分布——不预测方向而预测时间,帮助交易者量化"止盈和止损哪个更有可能先被触发",从概率层面优化交易决策。
这些指标的共同特点是:它们不假设市场是正态分布、随机行走或波动率恒定的。相反,它们拥抱市场的复杂性和肥尾特征,用自然科学的规律去理解金融世界。
作为 Python 学习者,理解这些指标不仅能拓宽你在量化金融领域的视野,更能锻炼你将跨学科数学模型转化为可运行代码的能力。这正是量化交易的核心竞争力所在。
2026年全面升级已落地!【数据科学实战】知识星球核心权益如下:
星球已沉淀丰富内容生态——涵盖量化文章专题教程库、因子日更系列、高频数据集、PyBroker实战课程、专家深度分享与实时答疑服务。无论您是初探量化的学习者,还是深耕领域的从业者,这里都是助您少走弯路、高效成长的理想平台。诚邀加入,共探数据驱动的投资未来!
好文推荐
1. 用 Python 打造股票预测系统:Transformer 模型教程(一)
2. 用 Python 打造股票预测系统:Transformer 模型教程(二)
3. 用 Python 打造股票预测系统:Transformer 模型教程(三)
4. 用 Python 打造股票预测系统:Transformer 模型教程(完结)
6. YOLO 也能预测股市涨跌?计算机视觉在股票市场预测中的应用