
2026年重磅升级已全面落地!欢迎加入专注财经数据与量化投研的【数据科学实战】知识星球!您将获取持续更新的《财经数据宝典》与《量化投研宝典》,双典协同提供系统化指引;星球内含 350 篇以上独有高质量文章,深度覆盖策略开发、因子分析、风险管理等核心领域,内容基本每日更新;同步推出的「量化因子专题教程」系列(含完整可运行代码与实战案例),系统详解因子构建、回测与优化全流程,并实现日更迭代。我们持续扩充独家内容资源,全方位赋能您的投研效率与专业成长。无论您是量化新手还是资深研究者,这里都是助您少走弯路、事半功倍的理想伙伴,携手共探数据驱动的投资未来!
在量化交易中,如何从嘈杂的市场数据中提取出真正有价值的趋势信号,一直是交易者和研究人员关注的核心问题。传统的移动平均线(MA)虽然简单易用,但往往存在滞后性强、噪声过滤不够等问题。
本文将介绍一种基于拉普拉斯变换(Laplace Transform)思想的趋势滤波器,它借鉴了数字信号处理(DSP)中的低通滤波原理,能够在抑制短期噪声的同时保留价格的底层趋势。我们将以 PLTR(Palantir Technologies)股票为例,用 Python 完整实现这一策略,并通过回测和样本外测试评估其表现。
拉普拉斯趋势滤波器的核心思想是:用指数衰减的方式对历史价格加权,越近的价格权重越大,越远的价格权重越小。这与指数加权移动平均(EWMA)在实践中非常相似,但它从连续时间的拉普拉斯变换出发进行离散化推导,具有更清晰的信号处理理论背景。
其关键参数是衰减率 s:
s 值越大:响应越快,平滑效果越弱,适合短周期交易s 值越小:响应越慢,平滑效果越强,适合长周期投资递推公式如下:
以下是拉普拉斯趋势滤波器的核心实现代码:
import numpy as npdef laplace_price(price, s=0.05): """ 离散拉普拉斯变换近似滤波器 参数: price: 价格序列(数组或 Series) s: 衰减率,值越大记忆越短(响应越快) 返回: L: 滤波后的平滑趋势序列 """ alpha = 1 - np.exp(-s) # 将衰减率转换为离散权重 L = np.zeros(len(price)) L[0] = price[0] # 初始值设为第一个价格 for t in range(1, len(price)): # 递推更新:当前价格加权 + 上一步滤波值加权 L[t] = alpha * price[t] + (1 - alpha) * L[t - 1] return L该策略的核心思路分为三步:
以下以短周期(2025-07-01 至 2026-01-23)为例:
import pandas as pdimport numpy as np# 假设 df 是包含 OHLC 数据的 DataFrame,索引为日期# df 的列包括:Open、High、Low、Close# 第一步:应用拉普拉斯滤波器(s=0.09 适合短周期)df["laplace"] = laplace_price(df["Close"].values, s=0.09)# 第二步:计算滤波值的一阶差分(即趋势斜率)df["laplace_slope"] = df["laplace"].diff()# 第三步:生成多头信号# 条件 1:收盘价高于滤波趋势线# 条件 2:滤波趋势线斜率为正(上升趋势)df["long_signal"] = ( (df["Close"] > df["laplace"]) & (df["laplace_slope"] > 0))# 将布尔信号转为持仓标记(1 = 持仓,0 = 空仓)df["position"] = df["long_signal"].astype(int)# 第四步:标记入场和出场时机df["entry"] = (df["position"] == 1) & (df["position"].shift(1) == 0) # 从空仓变为持仓df["exit"] = (df["position"] == 0) & (df["position"].shift(1) == 1) # 从持仓变为空仓要点说明:该策略只在价格处于上升趋势且位于趋势线上方时才入场,有效过滤了横盘震荡和虚假突破。
以下代码计算策略的每日收益和累计收益,并与买入持有(Buy & Hold)基准进行对比:
import numpy as np# 设定交易成本(每次交易 0.1%)transaction_cost = 0.001# 计算每日收益率df["daily_return"] = df["Close"].pct_change().fillna(0)# 策略每日收益(仅在持仓时获取收益)df["strategy_return"] = df["daily_return"] * df["position"]# 检测交易发生的时点(入场或出场)df["trade"] = df["position"].diff().abs()# 扣除交易成本df["strategy_return_tc"] = df["strategy_return"] - df["trade"] * transaction_cost# 计算累计收益df["cum_strategy_tc"] = (1 + df["strategy_return_tc"]).cumprod() # 策略(含成本)df["cum_buy_hold"] = (1 + df["daily_return"]).cumprod() # 买入持有基准# 输出总收益对比total_return_strategy = df["cum_strategy_tc"].iloc[-1] - 1total_return_bh = df["cum_buy_hold"].iloc[-1] - 1print(f"策略总收益(含交易成本):{total_return_strategy:.2%}")print(f"买入持有总收益:{total_return_bh:.2%}")import numpy as np# --- 年化收益率(CAGR) ---days = len(df)annual_factor = 252 / dayscagr_strategy = (1 + total_return_strategy) ** annual_factor - 1cagr_bh = (1 + total_return_bh) ** annual_factor - 1# --- 年化波动率 ---vol_strategy = df["strategy_return_tc"].std() * np.sqrt(252)vol_bh = df["daily_return"].std() * np.sqrt(252)# --- 夏普比率(假设无风险利率为 0) ---sharpe_strategy = cagr_strategy / vol_strategysharpe_bh = cagr_bh / vol_bh# --- 最大回撤 ---def max_drawdown(cum_returns): """计算最大回撤""" roll_max = cum_returns.cummax() # 滚动最高点 drawdown = (cum_returns - roll_max) / roll_max # 回撤比例 return drawdown.min()mdd_strategy = max_drawdown(df["cum_strategy_tc"])mdd_bh = max_drawdown(df["cum_buy_hold"])# 打印结果print("=== 策略绩效指标 ===")print(f"总收益:{total_return_strategy:.2%}")print(f"年化收益率:{cagr_strategy:.2%}")print(f"年化波动率:{vol_strategy:.2%}")print(f"夏普比率:{sharpe_strategy:.2f}")print(f"最大回撤:{mdd_strategy:.2%}")print("\n=== 买入持有绩效指标 ===")print(f"总收益:{total_return_bh:.2%}")print(f"年化收益率:{cagr_bh:.2%}")print(f"年化波动率:{vol_bh:.2%}")print(f"夏普比率:{sharpe_bh:.2f}")print(f"最大回撤:{mdd_bh:.2%}")原文中短周期(约 7 个月)的回测结果如下:
长周期(约 5 年)的回测结果如下:
从数据可以看出,拉普拉斯策略在收益、波动率和最大回撤三个维度上均优于买入持有。
回测结果虽然亮眼,但可能存在过拟合风险。为了更客观地评估策略的泛化能力,原文还进行了样本外测试:将数据按时间分为训练集(In-Sample)和测试集(Out-of-Sample),策略参数仅在训练集上确定,然后在测试集上运行并评估。
# 按时间比例划分训练集和测试集split_ratio = 0.69split_index = int(len(df) * split_ratio)# 训练集(In-Sample)df_is = df.iloc[:split_index].copy()# 测试集(Out-of-Sample)df_oos = df.iloc[split_index:].copy()# 在测试集上应用滤波器(参数 s 在训练集上确定)s_opt = 0.99 # 可在训练集上优化得到df_oos["laplace"] = laplace_price(df_oos["Close"], s=s_opt)# 计算斜率df_oos["laplace_slope"] = df_oos["laplace"].diff()# 生成持仓信号df_oos["position"] = 0df_oos.loc[ (df_oos["Close"] > df_oos["laplace"]) & (df_oos["laplace_slope"] > 0), "position"] = 1# 延迟一天执行,避免前瞻偏差df_oos["position"] = df_oos["position"].shift(1).fillna(0)短周期样本外测试结果:
结果表明,策略在未见过的数据上依然表现优异,收益更高、波动更低、回撤更小。
衰减率 s 是策略中最核心的超参数,不同的 s 值适用于不同的交易周期:
注意:
s值并非固定不变,建议结合 Walk-Forward Optimization(WFO,步进前向优化)方法进行动态调整。
优点:
需要注意的问题:
本文介绍了一种基于拉普拉斯变换的趋势跟踪交易策略。该策略的核心是一个带衰减记忆的低通滤波器,通过递推公式将嘈杂的价格数据转化为平滑的趋势信号,再结合趋势斜率生成交易信号。
在 PLTR 股票上的实测结果表明,无论是短周期还是长周期,该策略在总收益、夏普比率和最大回撤等关键指标上均优于简单的买入持有策略,且样本外测试同样验证了策略的有效性。
不过,正如原文所强调的,任何回测结果都不能直接等同于未来表现。该策略的收益高度依赖于少数大趋势行情,实际部署前需要进行更全面的 Walk-Forward Optimization(步进前向优化)验证,并充分考虑不同市场环境下的适应性。
对于 Python 量化交易的学习者来说,这个案例是一个很好的起点——它涵盖了信号滤波、策略构建、回测框架和样本外验证等核心环节,代码结构清晰,易于扩展和改进。
加入专注于财经数据与量化投研的知识星球【数据科学实战】,获取本文完整研究解析、代码实现细节。
2026年全面升级已落地!【数据科学实战】知识星球核心权益如下:
星球已沉淀丰富内容生态——涵盖量化文章专题教程库、因子日更系列、高频数据集、AKQuant和PyBroker实战课程、专家深度分享与实时答疑服务。无论您是初探量化的学习者,还是深耕领域的从业者,这里都是助您少走弯路、高效成长的理想平台。诚邀加入,共探数据驱动的投资未来!
好文推荐
1. 用 Python 打造股票预测系统:Transformer 模型教程(一)
2. 用 Python 打造股票预测系统:Transformer 模型教程(二)
3. 用 Python 打造股票预测系统:Transformer 模型教程(三)
4. 用 Python 打造股票预测系统:Transformer 模型教程(完结)
6. YOLO 也能预测股市涨跌?计算机视觉在股票市场预测中的应用
9. Python 量化投资利器:Ridge、Lasso 和 Elastic Net 回归详解
好书推荐