你是否思考过,如何使用Python从零构建一个接近实盘的专业量化交易系统?本文将深入解析一套基于Vortex指标的多资产趋势捕捉策略组合系统(Vortex Trend Capture Portfolio)。该系统在2025年1月至12月的回测中,将25万美元初始资金增长至44.6万美元,总收益率达78.58%,而同期比特币基准则下跌了6.69%。我们将拆解其从数据获取、信号生成到风险管理的完整架构,助你掌握构建健壮量化策略的核心技能。
系统架构概览
整个系统采用模块化设计,分为四个可独立替换与优化的层级:
- 数据层:负责通过CCXT库连接交易所(如Binance),下载多交易对的OHLCV数据,并返回为Pandas DataFrame格式。
- 执行层:模拟真实交易摩擦,包括手续费、滑点以及券商规则,使回测更贴近实盘。
- 信号层:策略核心,结合Vortex指标交叉、SMA趋势过滤器与ATR波动率过滤器生成交易信号,并采用ATR追踪止损进行出场管理。
- 投资组合层:负责跟踪权益、回撤、资产权重与贡献度,支持风险平价、波动率目标等多种仓位管理方式。
核心代码实现
1. 执行配置
使用Pydantic定义交易执行的配置参数,确保类型安全与参数验证:
from pydantic import BaseModel, Field
class ExecutionConfig(BaseModel):
# 初始资金
initial_cash: float = Field(100_000.0, description="起始资金")
# 券商手续费,例如 0.001 表示千分之一
commission: float = Field(0.001, description="券商手续费")
# 预估滑点,例如 0.0005 表示万分之五
slippage: float = Field(0.0005, description="预估滑点")
# 是否在资金不足时拒绝订单
check_submit: bool = Field(False, description="资金不足时拒绝订单")
在实际量化研究中,合理估计手续费和滑点是策略从理论走向可部署的关键一步。
2. 策略核心参数
params = (
("vortex_period", 30), # Vortex 指标周期,控制趋势检测灵敏度
("long_term_ma_period", 30), # 长期均线周期,用于趋势过滤
("atr_period", 7), # ATR 周期,用于波动率估计
("atr_threshold", 0.1), # ATR 阈值,过滤高波动环境
("atr_stop_multiplier", 2.0), # ATR 止损倍数,决定止损距离
("max_positions", 6), # 最大持仓数量,控制分散度
("risk_per_trade", 0.05), # 单笔交易风险比例,占权益的 5%
("min_size", 0.1), # 最小交易数量
("allow_shorts", True), # 是否允许做空
("log", False), # 是否输出日志
)
3. 为每个资产创建指标
在多资产策略中,需为每个数据源分别创建和管理指标状态。
def __init__(self):
# 使用字典存储每个资产的状态和指标
self.order = {} # 订单状态
self.vortex = {} # Vortex 指标
self.long_term_ma = {} # 长期均线
self.atr = {} # 平均真实波幅(ATR)
self.vortex_cross = {} # Vortex 交叉信号
self.stop_price = {} # 止损价格
# 遍历所有数据源,为每个资产创建指标
for d in self.datas:
self.order[d] = None
# 创建 Vortex 指标
self.vortex[d] = bt.indicators.Vortex(d, period=self.p.vortex_period)
# 创建简单移动平均线
self.long_term_ma[d] = bt.indicators.SimpleMovingAverage(
d, period=self.p.long_term_ma_period
)
# 创建 ATR 指标
self.atr[d] = bt.indicators.AverageTrueRange(d, period=self.p.atr_period)
# 创建 Vortex 交叉信号
self.vortex_cross[d] = bt.indicators.CrossOver(
self.vortex[d].lines.vi_plus,
self.vortex[d].lines.vi_minus
)
self.stop_price[d] = None
4. ATR风险仓位计算
基于波动率动态调整仓位大小,是风险管理的核心。
def _atr_risk_size(self, d):
# 获取当前账户权益
equity = self.broker.getvalue()
# 获取当前 ATR 值
atr = float(self.atr[d][0])
# 获取当前收盘价
close = float(d.close[0])
# 防止除零错误
if atr <= 0 or close <= 0:
return 0
# 计算每单位的风险金额(止损距离)
risk_per_unit = atr * float(self.p.atr_stop_multiplier)
if risk_per_unit <= 0:
return 0
# 计算目标风险金额
target_risk = equity * float(self.p.risk_per_trade)
# 计算仓位大小:确保触发止损时损失不超过目标风险
size = int(target_risk / risk_per_unit)
return size
该函数逻辑清晰:先根据ATR确定单笔交易的潜在亏损幅度,再反推仓位,确保任何单笔损失都在预设的风险预算内。
5. 交易信号生成
def next(self):
for d in self.datas:
# 确保有足够的历史数据
if len(d) < max(self.p.vortex_period, self.p.long_term_ma_period, self.p.atr_period):
continue
# 如果有未完成的订单,跳过
if self.order[d]:
continue
pos = self.getposition(d)
close = float(d.close[0])
# 空仓时寻找入场机会
if pos.size == 0:
# 检查是否达到最大持仓数量
if self._open_positions_count() >= int(self.p.max_positions):
continue
# 波动率稳定性过滤:ATR 占价格的比例不能太高
is_stable = (float(self.atr[d][0]) / close) < float(self.p.atr_threshold)
# 宏观趋势判断
is_macro_uptrend = close > float(self.long_term_ma[d][0])
is_macro_downtrend = close < float(self.long_term_ma[d][0])
# Vortex 交叉信号
is_buy_signal = self.vortex_cross[d][0] > 0
is_sell_signal = self.vortex_cross[d][0] < 0
# 计算仓位大小
size = self._atr_risk_size(d)
# 做多条件:稳定 + 上升趋势 + 买入信号
if is_stable and is_macro_uptrend and is_buy_signal:
self.order[d] = self.buy(data=d, size=size)
# 做空条件:稳定 + 下降趋势 + 卖出信号
elif self.p.allow_shorts and is_stable and is_macro_downtrend and is_sell_signal:
self.order[d] = self.sell(data=d, size=size)
6. ATR追踪止损
追踪止损机制让利润奔跑,同时严格控制下行风险。
# 多头持仓的追踪止损逻辑
if pos.size > 0:
atr = float(self.atr[d][0])
m = float(self.p.atr_stop_multiplier)
# 初始化最高价追踪
if self.highest_price_since_entry[d] is None:
self.highest_price_since_entry[d] = float(d.high[0])
self.stop_price[d] = float(d.close[0]) - atr * m
# 更新最高价,止损价只能上移不能下移
self.highest_price_since_entry[d] = max(
float(self.highest_price_since_entry[d]),
float(d.high[0]),
)
new_stop = float(self.highest_price_since_entry[d]) - atr * m
self.stop_price[d] = max(float(self.stop_price[d]), new_stop)
# 触发止损
if close < float(self.stop_price[d]):
self.order[d] = self.close(data=d)
7. 运行回测
# 配置执行参数
my_config = ExecutionConfig(
initial_cash=250_000, # 初始资金 25 万美元
commission=0.001, # 手续费千分之一
slippage=0.0005 # 滑点万分之五
)
# 运行回测
run_backtest(
StrategyClass=VortexTrendCapturePortfolio,
tickers=[
"BTC/USDC", "ETH/USDC", "SOL/USDC", "BNB/USDC", "XRP/USDC",
"ADA/USDC", "DOGE/USDC", "AVAX/USDC", "LINK/USDC", "LTC/USDC"
],
start="2025-01-01",
end="2025-12-20",
exec_config=my_config,
benchmark_ticker="btc-usd",
sizer_class=RiskParityVolTargetSizer,
do_report=True,
)
回测结果分析
该策略在2025年的回测中表现如下:
- 投资组合表现:初始资金25万美元,最终权益44.6万美元,总收益率78.58%,年化收益率82.21%,年化波动率59.00%,夏普比率1.39,最大回撤30.56%。
- 基准表现:比特币同期下跌6.69%,夏普比率为负0.20。
策略在熊市中仍能盈利,主要得益于以下几个核心机制:
- 允许做空,双向捕捉趋势。
- 宏观趋势过滤,避免逆势交易。
- ATR波动率过滤,规避极端市场环境。
- ATR追踪止损,在锁定利润的同时有效控制亏损。
总结
本文详细拆解了一个专业级多资产趋势交易系统的构建过程。该系统的核心价值在于其模块化设计,各层级(数据、执行、信号、组合)可独立优化与替换。通过ATR进行动态仓位管理与风险控制,结合追踪止损机制保护资本、让利润奔跑,再辅以多资产分散配置,共同构成了一个较为健壮的策略框架。
对于正在学习Python量化的开发者而言,这是一个极佳的学习案例。建议从理解每个模块的功能与代码入手,尝试修改参数、调整过滤条件,逐步构建并优化属于自己的交易系统。最后需谨记,历史回测结果不代表未来表现,实盘部署前务必进行充分的样本外测试与严格的风险管理。