11、基差交易的量化实现:Python环境搭建、数据接口、Tushare、Wind、基差计算函数、回测框架搭建

好,咱们直接进入正题。前面聊了那么多基差交易的逻辑和策略,现在该动手了。量化实现这件事,说白了就是把你的交易想法翻译成代码,让机器替你跑。我个人习惯是先把环境搭利索了,再谈别的。你想想看,地基没打牢,上面盖多高都白搭。

11.1 Python环境搭建——别小看这一步

我见过太多人,一上来就pip install这个那个,结果版本冲突搞得头大。嗯,这里要注意:量化交易对环境的稳定性要求极高。你跑回测的时候,今天能跑通,明天因为某个库升级了就跑不通,这谁受得了?

我的推荐方案:

  • Python 3.8 或 3.9(别追新,稳定第一)
  • Anaconda 管理虚拟环境
  • 核心库:numpy, pandas, matplotlib, scipy, statsmodels
  • 数据接口:tushare, WindPy(Wind Python接口)

我曾经在一个项目里,因为用了Python 3.11,结果某个回测框架的依赖库死活装不上。折腾了两天,最后老老实实退回3.9。所以我的建议是:用conda创建独立环境,每个策略项目一个环境,互不干扰。

# 创建虚拟环境
conda create -n basis_trading python=3.9

# 激活环境
conda activate basis_trading

# 安装核心库
pip install numpy pandas matplotlib scipy statsmodels

# 安装数据接口
pip install tushare
pip install WindPy  # 需要先安装Wind客户端

小技巧:把依赖写进requirements.txt,方便复现。我每次项目结束都会更新这个文件,算是给自己留个后路。

11.2 数据接口——Tushare vs Wind

数据是量化交易的血液。没有数据,你写再多代码都是空中楼阁。国内做商品期货基差交易,常用的数据源就两个:Tushare(免费)Wind(付费)

对比项 Tushare Wind
费用 免费(部分接口需积分) 付费(机构常用)
数据覆盖 股票、期货、基金等 全市场,含深度数据
速度 中等(有调用频率限制) 快(本地客户端)
适合场景 个人研究、小规模回测 机构实盘、高频策略

我个人习惯是:研究阶段用Tushare,因为免费、方便,数据质量也够用。但如果你要跑实盘,或者需要期货的逐笔成交数据,那Wind是绕不开的。我曾经在Tushare上拉过螺纹钢的日线数据,发现某几天数据缺失,查了半天是接口限流导致的。从那以后,关键数据我都会用Wind做二次校验。

Tushare 数据获取示例

import tushare as ts

# 设置token(在tushare官网注册获取)
ts.set_token('your_token_here')
pro = ts.pro_api()

# 获取螺纹钢期货日线数据
df = pro.fut_daily(
    ts_code='RB2401.SHF',  # 合约代码
    start_date='20230101',
    end_date='20231231',
    fields='trade_date,open,high,low,close,vol'
)

print(df.head())

Wind 数据获取示例

from WindPy import w

# 启动Wind接口
w.start()

# 获取螺纹钢期货日线数据
data = w.wsd(
    "RB2401.SHF",           # 合约代码
    "open,high,low,close,volume",  # 指标
    "2023-01-01",           # 开始日期
    "2023-12-31",           # 结束日期
    "Fill=Previous"         # 填充方式
)

# 转为DataFrame
import pandas as pd
df = pd.DataFrame(data.Data, index=data.Fields, columns=data.Times).T
print(df.head())

注意:Wind接口需要先安装Wind金融终端并登录。如果没装,会报错。我第一次用的时候忘了这茬,debug了半天才发现是客户端没开。

11.3 基差计算函数——核心逻辑就这几行

基差 = 期货价格 - 现货价格。听起来简单,但实际计算时有很多细节。比如:合约月份怎么选? 主力合约怎么判断? 现货数据用哪个?

我一般这样处理:

  • 期货价格:取主力合约的收盘价(成交量最大的合约)
  • 现货价格:取对应的商品指数或现货报价
  • 基差率:基差 / 现货价格 × 100%
def calculate_basis(future_price, spot_price):
    """
    计算基差和基差率
    :param future_price: 期货价格
    :param spot_price: 现货价格
    :return: 基差, 基差率
    """
    basis = future_price - spot_price
    basis_rate = basis / spot_price * 100
    return basis, basis_rate

# 示例
future = 3800  # 螺纹钢期货价格
spot = 3750    # 螺纹钢现货价格
basis, rate = calculate_basis(future, spot)
print(f"基差: {basis:.2f}, 基差率: {rate:.2f}%")

避坑指南:我曾经在计算基差时,直接用不同月份的合约价格去算,结果基差波动大得离谱。后来才发现,必须用同一交割月份的合约,或者用主力连续合约。否则算出来的基差没有意义。

11.4 回测框架搭建——从零开始写一个轻量级框架

回测框架不需要多复杂,能跑通你的策略逻辑就行。我见过有人用现成的回测库(比如backtrader、zipline),但说实话,对于基差交易这种特定场景,自己写一个轻量级框架反而更灵活

核心组件就三个:

  1. 数据模块:加载历史数据,处理缺失值
  2. 策略模块:定义开平仓信号
  3. 回测引擎:模拟交易,计算收益
import pandas as pd
import numpy as np

class BasisBacktest:
    def __init__(self, data, initial_capital=1000000):
        self.data = data          # 包含期货、现货价格的数据框
        self.capital = initial_capital
        self.position = 0         # 持仓方向:1多头,-1空头,0空仓
        self.trades = []          # 交易记录
    
    def generate_signals(self, threshold=2.0):
        """
        生成交易信号
        当基差率超过阈值时开仓,回归时平仓
        """
        signals = []
        for i in range(len(self.data)):
            basis_rate = self.data.loc[i, 'basis_rate']
            
            if basis_rate > threshold and self.position != -1:
                signals.append(-1)  # 做空基差(卖期货买现货)
            elif basis_rate < -threshold and self.position != 1:
                signals.append(1)   # 做多基差(买期货卖现货)
            else:
                signals.append(0)   # 持仓不变或空仓
        self.data['signal'] = signals
        return self.data
    
    def run_backtest(self):
        """
        执行回测
        """
        self.data['returns'] = self.data['future_price'].pct_change()
        self.data['strategy_returns'] = self.data['signal'].shift(1) * self.data['returns']
        self.data['cumulative_returns'] = (1 + self.data['strategy_returns']).cumprod()
        self.data['equity'] = self.capital * self.data['cumulative_returns']
        return self.data

# 使用示例
# 假设data已经包含future_price, spot_price, basis_rate
bt = BasisBacktest(data)
bt.generate_signals(threshold=2.0)
result = bt.run_backtest()
print(result[['trade_date', 'equity']].tail())

我的经验:回测框架里一定要加滑点手续费。我刚开始做回测时没考虑这些,结果实盘一跑,收益直接腰斩。后来在框架里加了千分之二的滑点,才跟实盘对得上。

11.5 知识体系总览

下面这张图,是我自己梳理的基差交易量化实现的全流程。你照着这个路径走,基本不会迷路。

基差交易量化实现全流程 第一步:环境搭建 Python 3.9 + Anaconda + 核心库(numpy, pandas, matplotlib) 第二步:数据接口 Tushare(免费研究) → Wind(机构实盘) 第三步:基差计算 基差 = 期货价格 - 现货价格 → 基差率 = 基差 / 现货价格 × 100% 第四步:回测框架 数据模块 → 策略模块(信号生成) → 回测引擎(收益计算) 第五步:结果分析 收益率、最大回撤、夏普比率 → 优化参数 → 实盘部署 注:每一步都建议做数据校验,避免垃圾进垃圾出

这张图把整个流程串起来了。你从环境搭建开始,一步步走到结果分析,中间每一步都有坑,但踩过去就是成长。我个人觉得,回测框架那一步最考验功力,因为你要把交易逻辑翻译成代码,还要考虑滑点、手续费这些现实因素。

最后说一句:量化实现不是一蹴而就的事。我刚开始写回测框架时,代码又臭又长,跑一次要半小时。后来慢慢优化,现在一个策略从数据到回测结果,5分钟搞定。你只要坚持写,也会越来越顺。


公众号:蓝海数据掘金营,微信deep3321