手把手教你用Python复刻‘双紫擒龙’量化指标(附完整源码与回测)

张开发
2026/4/5 4:55:52 15 分钟阅读

分享文章

手把手教你用Python复刻‘双紫擒龙’量化指标(附完整源码与回测)
手把手教你用Python复刻‘双紫擒龙’量化指标附完整源码与回测在量化交易领域技术指标的神秘面纱常常让初学者望而却步。今天我们将用Python彻底拆解这个名为双紫擒龙的指标从数据获取到可视化回测完整呈现一个量化策略的开发闭环。不同于直接展示晦涩的公式我们会用可运行的代码和直观的图表让你真正理解这个指标的计算逻辑和实际效果。1. 环境准备与数据获取在开始之前确保你的Python环境已经安装以下必要库pip install pandas numpy matplotlib yfinance ta-lib注意TA-Lib的安装可能需要额外步骤。Windows用户可以直接下载预编译版本Mac用户可通过brew安装。我们将使用yfinance获取历史数据。这里以苹果公司(AAPL)的日线数据为例import yfinance as yf def fetch_data(ticker, start_date, end_date): data yf.download(ticker, startstart_date, endend_date) return data[[Open, High, Low, Close]] # 获取2020-2023年AAPL数据 aapl_data fetch_data(AAPL, 2020-01-01, 2023-12-31)2. 指标核心逻辑解析原始公式虽然复杂但可以分解为几个关键组成部分趋势线计算基于25日均线的变形支撑/压力系统使用EMA和双重MA构建信号触发条件结合价格突破与动量指标让我们用Python逐步实现这些组件2.1 趋势线计算def calculate_trend(data, window25): # 计算双重移动平均 ma_h data[High].rolling(window).mean() ma_l data[Low].rolling(window).mean() # 趋势线公式 trend ma_l.rolling(window).mean() - (ma_h.rolling(window).mean() - ma_l.rolling(window).mean()) return trend2.2 支撑与压力系统def calculate_support_resistance(data): # 支撑线20日价格中值的EMA support ((data[Open] data[Close])/2).ewm(span20).mean() # 压力线双重MA计算 ma_h_25 data[High].rolling(25).mean() resistance (ma_h_25.rolling(25).mean() - ma_l_25.rolling(25).mean()) ma_h_25.rolling(25).mean() return support, resistance3. 完整指标实现现在我们将所有组件整合成一个完整的指标类class DoubleDragonIndicator: def __init__(self, data): self.data data.copy() def calculate_all(self): # 计算趋势线 self.data[trend] calculate_trend(self.data) # 计算支撑压力 self.data[support], self.data[resistance] calculate_support_resistance(self.data) # 计算动量信号 self._calculate_momentum() # 生成交易信号 self._generate_signals() return self.data def _calculate_momentum(self): # 动量计算逻辑 price_diff self.data[Close].diff() abs_diff price_diff.abs() self.data[momentum] 100 * price_diff.rolling(6).mean().rolling(6).mean() / \ abs_diff.rolling(6).mean().rolling(6).mean() def _generate_signals(self): # 生成买入信号 self.data[buy_signal] ( (self.data[momentum].rolling(2).min() self.data[momentum].rolling(7).min()) (self.data[momentum].rolling(2).apply(lambda x: (x 0).sum()) 1) (self.data[momentum] self.data[momentum].rolling(2).mean()) ) # 生成突破信号 self.data[breakout] ( (self.data[Close].shift(1) self.data[resistance].shift(1)) (self.data[Close] self.data[resistance]) (self.data[Close]/self.data[Close].shift(1) 1.04) )4. 可视化与回测4.1 指标可视化让我们创建一个直观的图表展示指标效果import matplotlib.pyplot as plt def plot_indicator(data): plt.figure(figsize(15,8)) # 绘制价格 plt.plot(data.index, data[Close], labelPrice, colorblack, alpha0.5) # 绘制趋势线 plt.plot(data.index, data[trend], labelTrend, colorred, linewidth2) # 绘制支撑压力 plt.plot(data.index, data[support], --, labelSupport, colorcyan) plt.plot(data.index, data[resistance], --, labelResistance, coloryellow) # 标记信号 buy_signals data[data[buy_signal]] plt.scatter(buy_signals.index, buy_signals[Low]*0.98, marker^, colorgreen, labelBuy Signal) breakout_signals data[data[breakout]] plt.scatter(breakout_signals.index, breakout_signals[High]*1.02, markerv, colormagenta, labelBreakout) plt.legend() plt.title(Double Dragon Indicator) plt.show()4.2 简单回测框架让我们实现一个基本的回测逻辑def backtest(data, initial_capital10000): position 0 capital initial_capital portfolio [] for i in range(len(data)): # 买入逻辑 if data[buy_signal].iloc[i] and position 0: position capital / data[Close].iloc[i] capital 0 # 卖出逻辑 elif data[breakout].iloc[i] and position 0: capital position * data[Close].iloc[i] position 0 # 记录每日净值 if position 0: portfolio.append(position * data[Close].iloc[i]) else: portfolio.append(capital) return portfolio5. 策略优化与改进建议基础实现虽然完整但仍有改进空间参数优化尝试不同的移动平均窗口如20/50/100测试不同的动量计算周期风险控制加入止损机制设置仓位管理规则信号过滤结合成交量过滤假突破添加波动率指标确认信号强度优化后的动量计算示例def enhanced_momentum(data, short_window6, long_window12): price_diff data[Close].diff() abs_diff price_diff.abs() # 双重平滑 short_ma price_diff.rolling(short_window).mean().rolling(short_window).mean() long_ma abs_diff.rolling(long_window).mean().rolling(long_window).mean() return 100 * short_ma / long_ma6. 实际应用中的注意事项在实盘使用这个指标时有几个关键点需要牢记市场环境适应性趋势指标在单边市中表现良好但在震荡市中可能产生过多假信号数据质量确保使用的历史数据已经过复权处理特别是对于股票数据交易成本回测时要考虑手续费、滑点等实际交易成本一个更稳健的信号生成方法def robust_signal_generation(data): # 要求连续两天确认信号 data[confirmed_buy] data[buy_signal].rolling(2).sum() 2 # 突破信号需要成交量配合 data[volume_ma] data[Volume].rolling(20).mean() data[confirmed_breakout] data[breakout] (data[Volume] data[volume_ma]) return data完整代码已经展示了如何从零构建这个指标系统。在实际操作中建议先用模拟账户测试一段时间确认策略表现符合预期后再考虑实盘应用。

更多文章