1. 为什么用Python做股票分析?

我第一次接触股票数据分析是在2017年,当时还在用Excel手动整理数据,不仅效率低下还经常出错。后来发现Python简直是金融数据分析的神器,特别是Pandas这个库,处理表格数据比Excel快10倍不止。举个例子,用Excel筛选某只股票过去5年涨幅超过5%的交易日,可能要折腾半小时,而用Python只需要3行代码。

Python在金融领域有三大优势:首先是生态丰富,Tushare、AKShare这些免费数据接口可以直接获取股票行情;其次是计算高效,Pandas和NumPy底层用C语言优化过,处理百万行数据毫无压力;最后是可视化强大,Matplotlib和Pyecharts能生成专业级的K线图和趋势图。

提示:新手建议从Tushare Pro开始,免费版每天有500次调用额度,足够个人学习使用。

2. 环境搭建与数据获取

2.1 开发环境配置

我强烈推荐使用Anaconda搭建Python环境,它自带了Jupyter Notebook和所有科学计算库。安装完Anaconda后,在终端执行这几条命令就能搞定依赖:

conda install pandas numpy matplotlib
pip install tushare

遇到过最坑的问题是Tushare的版本兼容性,记得一定要用pip install tushare --upgrade安装最新版。去年有个学员用老版本获取数据总是报错,折腾了两天才发现是接口过期了。

2.2 获取股票数据实战

以贵州茅台(600519)为例,获取历史行情数据只需要4行代码:

import tushare as ts
df = ts.get_k_data('600519', start='2010-01-01')
df.to_csv('maotai.csv')  # 保存到本地
df = pd.read_csv('maotai.csv', index_col='date', parse_dates=True)

这里有个细节要注意:Tushare返回的DataFrame默认带有个无用列"Unnamed: 0",需要用df.drop(columns=['Unnamed: 0'], inplace=True)删除。我见过有人因为这个隐藏列导致后续计算出错,排查了半天。

3. 核心分析技巧

3.1 基础指标计算

计算涨跌幅是分析的基础,但新手常犯两个错误:一是忘记处理除权除息,二是用错计算公式。正确的涨幅计算应该是:

# 当日涨幅 = (收盘价 - 开盘价)/开盘价
df['daily_change'] = (df['close'] - df['open']) / df['open']

# 找涨幅超过3%的交易日
big_rise_days = df[df['daily_change'] > 0.03]

更实用的技巧是用shift()计算环比变化,比如识别跳空低开:

# 开盘价比前日收盘跌超2%
gap_down = df[(df['open'] - df['close'].shift(1))/df['close'].shift(1) < -0.02]

3.2 均线策略实现

双均线策略是量化入门必学的经典策略。5日均线上穿30日均线形成金叉是买入信号,下穿形成死叉是卖出信号。具体实现:

df['ma5'] = df['close'].rolling(5).mean()
df['ma30'] = df['close'].rolling(30).mean()

# 金叉条件:当日ma5>ma30且前日ma5<=ma30
golden_cross = (df['ma5'] > df['ma30']) & (df['ma5'].shift(1) <= df['ma30'].shift(1))

实测中发现,单纯用收盘价计算均线会有滞后性。改进方法是用典型价格(Typical Price):(最高价+最低价+收盘价)/3,这样对市场变化更敏感。

4. 策略回测与优化

4.1 定期投资回测

假设从2010年开始每月定投100股,年底卖出,收益计算如下:

monthly = df.resample('M').first()  # 每月第一个交易日
yearly = df.resample('Y').last()    # 每年最后一个交易日

cost = monthly['open'].sum() * 100 * 12  # 每年买1200股
income = yearly['open'].sum() * 1200     # 每年卖1200股

但这样计算忽略了两个关键点:1) 未实现收益要按当前市值计算 2) 交易手续费。更严谨的做法:

current_value = holdings * df.iloc[-1]['close']
profit = income + current_value - cost - transaction_fee

4.2 参数优化技巧

均线周期不是固定值,需要根据股票特性调整。用网格搜索寻找最优参数:

from itertools import product

results = []
for short, long in product(range(3,10), range(20,60,5)):
    df['signal'] = df['close'].rolling(short).mean() > df['close'].rolling(long).mean()
    # 计算策略收益...
    results.append((short, long, annual_return))

去年我用这个方法优化沪深300ETF的策略,发现7日/55日均线组合的年化收益比传统5日/30日高出2.3%。

5. 进阶分析方向

5.1 多因子选股模型

单一指标容易失效,可以结合多个因子:

  • 估值因子:PE、PB
  • 质量因子:ROE、毛利率
  • 动量因子:20日涨幅、换手率
factors = {
    'pe': get_pe_ratio(),
    'roe': calculate_roe(),
    'momentum': df['close'].pct_change(20)
}

5.2 风险控制模块

没有风控的策略都是耍流氓。建议至少实现:

  • 单日最大回撤止损
  • 仓位动态调整
  • 黑名单机制
# 动态仓位示例
def calculate_position_size(risk_per_trade, stop_loss_pct):
    return risk_per_trade / stop_loss_pct

6. 常见问题解决方案

6.1 数据缺失处理

遇到停牌导致的缺失数据时,不要简单用前值填充。正确做法:

# 向前填充不超过3个交易日
df['close'] = df['close'].fillna(method='ffill', limit=3)

6.2 复权处理

新手最容易忽略的就是复权问题。Tushare获取复权数据:

df = ts.get_k_data('600519', start='2010-01-01', autype='hfq')  # 后复权

如果自己处理复权,记住这个公式:

复权因子 = 当日收盘价 / 当日实际价格
复权价格 = 原始价格 × 复权因子

7. 实战经验分享

我在2019年用Python搭建的第一个策略是双均线+动量突破组合,回测年化有15%,但实盘第一周就亏了7%。教训是:

  1. 没考虑滑点,假设成交价都是开盘价
  2. 忽略了大单冲击成本
  3. 用了未来函数(计算指标时包含了当日数据)

改进后的版本加入了:

  • 实际买卖用VWAP(成交量加权均价)
  • 单笔委托不超过日均成交量5%
  • 严格区分训练集和测试集

现在我的策略开发流程固定为:数据清洗(20%时间)→因子研究(30%)→策略开发(20%)→回测验证(30%)。每个环节都要写单元测试,特别是边界条件比如涨停跌停、停牌等情况。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐