从零搭建你的Python量化工具箱(一):手把手复现同花顺MACD与RSI,附完整代码与数据验证
从零搭建你的Python量化工具箱一手把手复现同花顺MACD与RSI附完整代码与数据验证第一次接触量化交易时最让人头疼的莫过于看着软件里花花绿绿的指标线却不知道它们是怎么算出来的。作为过来人我清楚地记得自己当年对着同花顺的MACD金叉死叉信号百思不得其解的样子。直到后来用Python亲手实现了这些指标才发现技术分析背后的数学逻辑如此简洁优美。本文将带你用Python从零复现同花顺和通达信中的两个经典指标MACD异同移动平均线和RSI相对强弱指标。不同于市面上大多数教程只给最终代码我们会从数据导入开始逐步拆解每个计算步骤最后还会教你如何与主流交易软件的结果进行逐行比对验证。即使你刚学Python不久跟着这个保姆级教程也能搭建出自己的第一个量化分析工具。1. 环境准备与数据获取1.1 安装必要的Python库在开始之前我们需要三个核心库Pandas数据处理与分析的核心工具NumPy数值计算的基础库Matplotlib可选用于可视化指标线pip install pandas numpy matplotlib提示建议使用Jupyter Notebook进行交互式开发可以实时查看每个步骤的输出结果1.2 获取股票历史数据我们从雅虎财经下载苹果公司AAPL2022年的日线数据作为示例import pandas as pd # 读取CSV文件假设已下载保存为AAPL_2022.csv data pd.read_csv(AAPL_2022.csv, parse_dates[Date], index_colDate) print(data.head())典型的数据结构应包含以下列日期开盘价最高价最低价收盘价成交量2022-01-03182.01182.94177.41177.57981914002. 核心指标函数实现2.1 指数移动平均EMAEMA是MACD指标的基础它对近期价格赋予更高权重。Pandas的ewm方法可以高效计算def calculate_ema(series, window): 计算指数移动平均 :param series: 价格序列通常为收盘价 :param window: 计算窗口 :return: EMA序列 return series.ewm(spanwindow, adjustFalse).mean()验证EMA计算是否正确有个小技巧当窗口足够大时EMA会接近简单移动平均SMA。我们可以用这个特性做交叉验证# 验证EMA(120)是否接近SMA(120) data[EMA_120] calculate_ema(data[Close], 120) data[SMA_120] data[Close].rolling(120).mean() print(data[[EMA_120, SMA_120]].tail())2.2 中国式SMA的特殊实现通达信和同花顺中的SMA计算与常规实现略有不同需要特别注意def calculate_sma_chinese(series, window, weight1): 复现同花顺/通达信的中国式SMA :param series: 价格序列 :param window: 计算窗口 :param weight: 平滑系数默认为1 :return: SMA序列 sma series.rolling(window).mean() # 初始SMA值 for i in range(window, len(series)): sma.iloc[i] (weight * series.iloc[i] (window - weight) * sma.iloc[i-1]) / window return sma注意中国式SMA对初始值敏感建议至少使用120个数据点进行计算以保证精度3. 构建MACD指标系统3.1 DIF与DEA的计算MACD由三个部分组成DIF EMA(12) - EMA(26)DEA DIF的9日EMAMACD柱 (DIF - DEA) * 2def calculate_macd(close_prices, short12, long26, signal9): 完整MACD指标计算 :param close_prices: 收盘价序列 :param short: 短期EMA周期默认12 :param long: 长期EMA周期默认26 :param signal: 信号线周期默认9 :return: (DIF, DEA, MACD柱) dif calculate_ema(close_prices, short) - calculate_ema(close_prices, long) dea calculate_ema(dif, signal) macd (dif - dea) * 2 return dif, dea, macd3.2 与同花顺结果比对验证计算结果是否正确的黄金标准是与专业软件逐行对比# 计算MACD指标 data[DIF], data[DEA], data[MACD] calculate_macd(data[Close]) # 导出结果到CSV与同花顺比对 data[[Close, DIF, DEA, MACD]].to_csv(macd_validation.csv)比对时需要特别注意检查小数点后四位是否一致确认初始值计算是否正确前25个数据点可能无效观察金叉/死叉出现的位置是否吻合4. 实现RSI相对强弱指标4.1 RSI的计算原理RSI的计算分为三步计算每日价格变化Δ 今日收盘 - 昨日收盘分别计算上涨日和下跌日的平均变化RSI 100 × 上涨平均值 / (上涨平均值 下跌平均值)def calculate_rsi(close_prices, window14): 计算相对强弱指数(RSI) :param close_prices: 收盘价序列 :param window: 计算窗口默认14 :return: RSI序列 delta close_prices.diff() gain delta.where(delta 0, 0) loss -delta.where(delta 0, 0) avg_gain gain.rolling(window).mean() avg_loss loss.rolling(window).mean() rs avg_gain / avg_loss return 100 - (100 / (1 rs))4.2 RSI的实战应用技巧在实际交易中RSI有几个关键用法超买超卖信号RSI 70可能超买考虑卖出RSI 30可能超买考虑买入背离信号价格创新高但RSI未创新高 → 顶部背离价格创新低但RSI未创新低 → 底部背离# 标记超买超卖区域 data[RSI] calculate_rsi(data[Close]) data[Overbought] data[RSI] 70 data[Oversold] data[RSI] 305. 指标可视化与策略回测5.1 使用Matplotlib绘制指标线将MACD和RSI在同一图表中展示import matplotlib.pyplot as plt fig, (ax1, ax2) plt.subplots(2, 1, figsize(12, 8)) # 绘制价格和MACD data[Close].plot(axax1, titlePrice with MACD) data[DIF].plot(axax1, labelDIF) data[DEA].plot(axax1, labelDEA) ax1.bar(data.index, data[MACD], colorgray, alpha0.3) ax1.legend() # 绘制RSI data[RSI].plot(axax2, titleRSI) ax2.axhline(70, colorr, linestyle--) ax2.axhline(30, colorg, linestyle--) plt.tight_layout() plt.show()5.2 简单的策略回测框架基于MACD金叉/死叉构建最简单的交易策略# 生成交易信号 data[Signal] 0 data.loc[data[DIF] data[DEA], Signal] 1 # 金叉买入 data.loc[data[DIF] data[DEA], Signal] -1 # 死叉卖出 # 计算策略收益 data[Strategy_Return] data[Signal].shift(1) * data[Close].pct_change() data[Cumulative_Return] (1 data[Strategy_Return]).cumprod()最后提醒一点在实际应用中一定要考虑交易成本和滑点的影响。这个简单策略在历史数据上可能表现不错但真实市场要复杂得多。建议先用模拟账户测试至少3个月再考虑实盘操作。