Python量化交易入门:从数据获取到策略回测完整指南

monster
1
2026-07-22

最近一直在折腾量化交易这块,从数据获取到策略回测踩了不少坑。Python凭借其丰富的数据科学生态(pandas、numpy、matplotlib),加上各种现成的量化库,确实是最适合入门量化的语言。这篇文章就系统的整理一下怎么用Python从零开始搭建一套量化交易工具链。从数据获取到策略编写,再到回测验证,一条龙安排明白。

一、环境准备:搭建量化开发环境

做量化交易第一步就是环境搭建。Python的量化生态非常成熟,下面这些库是必备的:

  • pandas:数据处理的核心,DataFrame是量化分析的基础数据结构

  • numpy:数值计算,矩阵运算效率极高

  • matplotlib / mplfinance:数据可视化,画K线图必备

  • akshare / baostock:A股数据获取,免费且覆盖全面

  • backtrader:业界最流行的回测框架

直接pip一把梭:

pip install pandas numpy matplotlib mplfinance akshare backtrader tushare

建议在虚拟环境里安装,避免跟其他项目的依赖打架。创建虚拟环境也很简单:

python -m venv quant_env
# Windows激活
quant_envScriptsactivate
# macOS/Linux激活
source quant_env/bin/activate

二、数据获取:从哪里拿数据

做量化最头疼的事情之一就是数据源。以前都得花钱买数据,现在好多了,Python生态有几个非常好用的免费数据源。

使用 akshare 获取A股数据

akshare 是我用得比较多的库,接口丰富,覆盖了股票、基金、期货、外汇等各类数据:

import akshare as ak
import pandas as pd

# 获取A股个股历史行情(日K)
stock_zh_a_hist_df = ak.stock_zh_a_hist(
    symbol="000001",    # 股票代码
    period="daily",     # 日线
    start_date="20240101",
    end_date="20240701",
    adjust="qfq"        # 前复权
)
print(stock_zh_a_hist_df.head())

使用 baostock 获取数据

baostock 是另一个不错的免费数据源,数据质量稳定:

import baostock as bs
import pandas as pd

# 登录
lg = bs.login()
# 获取沪深300日K线数据
rs = bs.query_history_k_data_plus(
    "sh.600000",
    "date,code,open,high,low,close,volume,amount",
    start_date='2024-01-01',
    end_date='2024-07-01',
    frequency="d",
    adjustflag="2"  # 前复权
)
data_list = []
while (rs.error_code == '0') and rs.next():
    data_list.append(rs.get_row_data())
result = pd.DataFrame(data_list, columns=rs.fields)
bs.logout()

两个库各有优劣,akshare 接口更丰富但偶尔会因网站改版出问题,baostock 更稳定但数据种类少一些。建议两个都装上,哪个好用用哪个。

三、编写第一个策略:双均线策略

数据拿到了,接下来写一个经典的量化策略——双均线策略(Golden Cross)。

核心逻辑很简单:当短期均线上穿长期均线时买入(金叉),当短期均线下穿长期均线时卖出(死叉)。这是趋势跟踪的经典玩法。

import pandas as pd
import numpy as np

def double_ma_strategy(df, short_window=5, long_window=20):
    """
    双均线策略
    :param df: 包含close列的DataFrame
    :param short_window: 短期均线窗口
    :param long_window: 长期均线窗口
    :return: 带信号的DataFrame
    """
    data = df.copy()
    
    # 计算短期和长期移动平均线
    data['MA_short'] = data['close'].rolling(window=short_window).mean()
    data['MA_long'] = data['close'].rolling(window=long_window).mean()
    
    # 生成信号
    data['signal'] = 0
    # 当短期均线 > 长期均线时 signal = 1(买入)
    data.loc[data['MA_short'] > data['MA_long'], 'signal'] = 1
    # 当短期均线 < 长期均线时 signal = -1(卖出)
    data.loc[data['MA_short'] < data['MA_long'], 'signal'] = -1
    
    # 计算持仓变化(只有信号变化时才交易)
    data['position'] = data['signal'].diff()
    
    return data

# 使用示例
# 假设已经从akshare获取了股票数据
result = double_ma_strategy(stock_zh_a_hist_df)
print(result[['close', 'MA_short', 'MA_long', 'signal', 'position']].tail(10))

四、回测验证:策略到底赚不赚钱

策略写出来了,不能直接拿去实盘,得先回测看看历史表现。自己写一个简单的回测引擎也不难:

def backtest(df, initial_capital=100000, trade_size=100):
    """
    简单的回测函数
    :param df: 包含signal列的DataFrame
    :param initial_capital: 初始资金
    :param trade_size: 每次交易股数
    """
    data = df.copy()
    capital = initial_capital
    position = 0  # 持仓数量
    portfolio_values = []
    
    for i in range(len(data)):
        price = data.iloc[i]['close']
        signal = data.iloc[i]['position']
        
        # 买入信号(从0变成1)
        if signal == 1 and position == 0:
            buy_amount = trade_size
            cost = buy_amount * price
            if capital >= cost:
                position = buy_amount
                capital -= cost
                
        # 卖出信号(从1变成-1)
        elif signal == -1 and position > 0:
            capital += position * price
            position = 0
        
        # 记录每日总资产
        total = capital + position * price
        portfolio_values.append(total)
    
    data['portfolio_value'] = portfolio_values
    final_value = capital + position * data.iloc[-1]['close']
    total_return = (final_value - initial_capital) / initial_capital * 100
    
    print(f"初始资金: {initial_capital}")
    print(f"最终资产: {final_value:.2f}")
    print(f"总收益率: {total_return:.2f}%")
    
    return data

使用 backtrader 专业回测

自己写回测练手可以,但真要分析策略表现,还是用 backtrader 这种专业框架更靠谱。backtrader 内置了收益率、夏普比率、最大回撤等指标:

import backtrader as bt

class DoubleMAStrategy(bt.Strategy):
    params = (('short_period', 5), ('long_period', 20))
    
    def __init__(self):
        self.short_ma = bt.indicators.SMA(
            self.data.close, period=self.params.short_period)
        self.long_ma = bt.indicators.SMA(
            self.data.close, period=self.params.long_period)
    
    def next(self):
        if not self.position:
            # 金叉买入
            if self.short_ma[0] > self.long_ma[0]:
                self.buy(size=100)
        else:
            # 死叉卖出
            if self.short_ma[0] < self.long_ma[0]:
                self.sell(size=100)

# 运行回测
cerebro = bt.Cerebro()
cerebro.addstrategy(DoubleMAStrategy)

# 加载数据(需要先转换成backtrader的格式)
data = bt.feeds.PandasData(dataname=stock_zh_a_hist_df)
cerebro.adddata(data)
cerebro.broker.setcash(100000.0)

print(f'初始资金: {cerebro.broker.getvalue():.2f}')
cerebro.run()
print(f'最终资金: {cerebro.broker.getvalue():.2f}')
cerebro.plot()

五、可视化分析:一图胜千言

回测做完了,看看图表更直观。用 mplfinance 画K线和均线:

import mplfinance as mpf

# 准备数据(需要符合mplfinance的格式)
plot_df = stock_zh_a_hist_df.copy()
plot_df.index = pd.to_datetime(plot_df['date'])
plot_df.columns = [c.lower() for c in plot_df.columns]

# 添加均线
ap = [
    mpf.make_addplot(result['MA_short'], color='blue', width=0.8),
    mpf.make_addplot(result['MA_long'], color='red', width=0.8),
]

# 画K线
mpf.plot(
    plot_df[-60:],  # 最近60个交易日
    type='candle',
    style='charles',
    title='双均线策略K线图',
    ylabel='价格',
    addplot=ap,
    volume=True
)

六、总结

这篇文章从环境搭建、数据获取、策略编写、回测验证到可视化分析,走完了一个量化交易的完整流程。总结几个关键点:

  • 数据是基础:akshare 和 baostock 对个人开发者来说足够用,免费且稳定

  • 从简单策略开始:双均线虽然经典但已经能跑通整个流程,后续可以尝试更复杂的策略

  • 一定要回测:任何策略在实盘之前都要经过严格的回测验证,backtrader 是好帮手

  • 控制风险:量化交易不是印钞机,回测好看不代表实盘能赚,仓位管理和风控同样重要

量化交易的路很长,这篇文章只是带你入了门。后续可以深入的方向还有很多:多因子模型、机器学习策略、期权定价、高频交易等等。如果对某个方向感兴趣,后面可以单独开文章聊。

动物装饰