零基础玩转量化交易:用Python+Supermind实现你的第一个自动交易策略

第一次听说量化交易时,我盯着屏幕上那些复杂的数学公式和代码直发懵——这玩意儿真的适合普通投资者吗?直到有一天,我用Python写出了一个简单的双均线策略,看着它自动执行买卖操作并生成收益曲线时,那种"原来我也能做到"的成就感简直难以形容。今天,就让我们抛开那些晦涩的理论,直接从最实用的代码入手,带你体验量化交易的魅力。

1. 准备工作:搭建你的量化工具箱

在开始编写策略前,我们需要准备好三样工具:Python环境、Supermind账号和必要的代码库。别担心,即使你昨天才安装Python,跟着下面的步骤也能顺利完成。

1.1 Python环境配置

推荐使用Anaconda来管理Python环境,它能帮你轻松处理各种依赖关系。安装完成后,创建一个专用于量化交易的虚拟环境:

conda create -n quant python=3.8
conda activate quant

接着安装量化交易必备的几个库:

pip install pandas numpy matplotlib requests

提示:如果遇到网络问题,可以尝试使用国内镜像源,例如加上 -i https://pypi.tuna.tsinghua.edu.cn/simple

1.2 Supermind平台注册与API获取

  1. 访问Supermind官网完成注册
  2. 进入"开发者中心"申请API Key
  3. 记录下你的 API Key Secret Key (这些信息后续会用到)

Supermind提供了丰富的金融数据接口,包括:

数据类型 覆盖范围 更新频率
股票行情 沪深A股、ETF 实时
财务数据 资产负债表、利润表等 季度
行业指数 申万一级/二级行业 每日
衍生品数据 股指期货、期权 实时

1.3 连接Supermind API

让我们先测试API连接是否正常。创建一个 sm_api.py 文件,写入以下代码:

import requests
import json

def get_token():
    url = "https://api.supermind.com/v1/auth/token"
    headers = {"Content-Type": "application/json"}
    data = {
        "api_key": "你的API_KEY",
        "secret_key": "你的SECRET_KEY"
    }
    response = requests.post(url, headers=headers, data=json.dumps(data))
    return response.json()["data"]["token"]

# 测试获取上证指数数据
def get_sh_index(token):
    url = "https://api.supermind.com/v1/quote/kline"
    params = {
        "symbol": "000001.SH",
        "start_time": "2023-01-01",
        "end_time": "2023-12-31",
        "frequency": "1d"
    }
    headers = {"Authorization": f"Bearer {token}"}
    response = requests.get(url, headers=headers, params=params)
    return response.json()

if __name__ == "__main__":
    token = get_token()
    data = get_sh_index(token)
    print(data[:2])  # 打印前两条数据

运行这个脚本,如果看到返回了上证指数的K线数据,说明环境配置成功!

2. 双均线策略:量化交易的"Hello World"

在量化领域,双均线策略就像编程界的"Hello World"——简单却蕴含精髓。它的逻辑非常直观:当短期均线上穿长期均线时买入,下穿时卖出。

2.1 策略逻辑解析

假设我们选择:

  • 短期均线(快线):5日均线
  • 长期均线(慢线):20日均线

策略信号生成规则:

  1. 当5日均线从下方穿过20日均线(金叉),买入信号
  2. 当5日均线从上方穿过20日均线(死叉),卖出信号
  3. 其余时间保持现有仓位

为什么这个策略有效?因为它本质上捕捉的是趋势的形成和反转。当短期均线向上突破长期均线,往往意味着新趋势的开始;反之则可能预示趋势结束。

2.2 获取并处理股票数据

让我们先获取一只股票的历史数据并进行均线计算。以贵州茅台(600519.SH)为例:

import pandas as pd

def calculate_ma(data):
    """计算均线指标"""
    df = pd.DataFrame(data)
    df['date'] = pd.to_datetime(df['trade_date'])
    df.set_index('date', inplace=True)
    df['ma5'] = df['close'].rolling(5).mean()
    df['ma20'] = df['close'].rolling(20).mean()
    return df.dropna()

# 假设data是从API获取的K线数据
maotai_data = get_stock_data("600519.SH", "2022-01-01", "2023-12-31") 
maotai_df = calculate_ma(maotai_data)

2.3 策略信号生成

现在我们来编写信号生成的代码:

def generate_signals(df):
    """生成交易信号"""
    df['signal'] = 0  # 0表示无信号,1表示买入,-1表示卖出
    
    # 金叉:5日均线上穿20日均线
    df.loc[(df['ma5'].shift(1) <= df['ma20'].shift(1)) & 
           (df['ma5'] > df['ma20']), 'signal'] = 1
    
    # 死叉:5日均线下穿20日均线
    df.loc[(df['ma5'].shift(1) >= df['ma20'].shift(1)) & 
           (df['ma5'] < df['ma20']), 'signal'] = -1
    
    return df

signals_df = generate_signals(maotai_df)
print(signals_df[['close', 'ma5', 'ma20', 'signal']].tail(10))

这段代码会在符合条件的位置标记1(买入)或-1(卖出),其余时间为0。

3. 回测:验证策略的有效性

策略写好了,但它真的能赚钱吗?我们需要通过历史数据来回测它的表现。

3.1 回测框架搭建

一个完整的回测需要包含以下几个部分:

  1. 初始资金设置
  2. 交易手续费计算
  3. 仓位管理
  4. 收益率计算
def backtest(df, initial_capital=100000, commission=0.0003):
    """策略回测"""
    position = 0  # 持仓数量
    cash = initial_capital  # 现金
    portfolio_value = [initial_capital]  # 组合价值记录
    
    for i in range(1, len(df)):
        current_price = df.iloc[i]['close']
        signal = df.iloc[i]['signal']
        
        # 执行买入信号
        if signal == 1 and position == 0:
            position = cash // current_price
            cash -= position * current_price * (1 + commission)
        
        # 执行卖出信号
        elif signal == -1 and position > 0:
            cash += position * current_price * (1 - commission)
            position = 0
        
        # 记录当日组合价值
        daily_value = cash + position * current_price
        portfolio_value.append(daily_value)
    
    df['portfolio'] = portfolio_value
    df['returns'] = df['portfolio'].pct_change()
    return df

3.2 回测结果分析

让我们运行回测并可视化结果:

import matplotlib.pyplot as plt

result_df = backtest(signals_df)

plt.figure(figsize=(12, 8))
plt.plot(result_df.index, result_df['close'] / result_df['close'].iloc[0], label='贵州茅台')
plt.plot(result_df.index, result_df['portfolio'] / result_df['portfolio'].iloc[0], label='策略收益')
plt.plot(result_df.index, result_df['ma5'] / result_df['ma5'].iloc[0], label='5日均线', alpha=0.5)
plt.plot(result_df.index, result_df['ma20'] / result_df['ma20'].iloc[0], label='20日均线', alpha=0.5)
plt.legend()
plt.title('双均线策略回测结果')
plt.show()

通过对比策略收益和股票本身收益,我们可以直观看到策略的表现。此外,还可以计算一些关键指标:

def calculate_metrics(df):
    """计算策略评价指标"""
    total_return = df['portfolio'].iloc[-1] / df['portfolio'].iloc[0] - 1
    annual_return = (1 + total_return) ** (252/len(df)) - 1
    volatility = df['returns'].std() * np.sqrt(252)
    sharpe_ratio = annual_return / volatility
    
    max_portfolio = df['portfolio'].cummax()
    drawdown = (df['portfolio'] - max_portfolio) / max_portfolio
    max_drawdown = drawdown.min()
    
    return {
        "总收益率": total_return,
        "年化收益率": annual_return,
        "波动率": volatility,
        "夏普比率": sharpe_ratio,
        "最大回撤": max_drawdown
    }

metrics = calculate_metrics(result_df)
for k, v in metrics.items():
    print(f"{k}: {v:.2%}")

4. 策略优化与进阶思考

基础策略跑通了,但你可能已经发现了一些问题:交易信号过于频繁?在某些市场环境下表现不佳?这正是量化交易最有意思的部分——不断优化和改进。

4.1 常见优化方向

  1. 参数优化
    • 尝试不同的均线组合(如10/30、5/60)
    • 使用网格搜索寻找最优参数
from itertools import product

def optimize_ma(df, short_range, long_range):
    results = []
    for short, long in product(short_range, long_range):
        if short >= long:
            continue
            
        temp_df = df.copy()
        temp_df['ma_short'] = temp_df['close'].rolling(short).mean()
        temp_df['ma_long'] = temp_df['close'].rolling(long).mean()
        
        # 生成信号和回测(代码略)
        # ...
        
        metrics = calculate_metrics(temp_df)
        metrics.update({'short': short, 'long': long})
        results.append(metrics)
    
    return pd.DataFrame(results).sort_values('夏普比率', ascending=False)

# 测试5-30日的各种组合
optimization_results = optimize_ma(maotai_data, range(5, 11), range(20, 31))
print(optimization_results.head())
  1. 过滤假信号

    • 加入成交量过滤(如成交量需大于20日均量)
    • 加入波动率过滤(如ATR指标)
  2. 仓位管理

    • 动态调整仓位大小
    • 加入止损止盈机制

4.2 策略组合与风险管理

单一策略往往难以适应所有市场环境。成熟的量化交易者通常会:

  • 同时运行多个不相关策略
  • 根据市场状态调整策略权重
  • 严格控制单策略最大回撤

一个简单的多策略组合示例:

strategies = {
    '双均线': signals_df,
    '动量策略': momentum_df,
    '均值回归': mean_reversion_df
}

portfolio_weights = {'双均线': 0.5, '动量策略': 0.3, '均值回归': 0.2}
combined_returns = sum(df['returns'] * weight for df, weight in zip(strategies.values(), portfolio_weights.values()))

4.3 实盘前的最后检查

在将策略投入实盘前,务必进行:

  1. 样本外测试 :使用回测期间之后的数据验证
  2. 参数稳定性测试 :检查最优参数是否在不同时间段都有效
  3. 交易成本测试 :考虑滑点、手续费等实际成本
  4. 极端行情测试 :模拟股灾、熔断等特殊市场环境
def stress_test(df, crash_dates):
    """极端行情测试"""
    for date in crash_dates:
        crash_period = df[df.index >= date].iloc[:10]  # 检查崩盘后10天表现
        drawdown = (crash_period['portfolio'].min() - crash_period['portfolio'].iloc[0]) / crash_period['portfolio'].iloc[0]
        print(f"{date} 市场下跌期间策略回撤: {drawdown:.2%}")

第一次看到自己的策略在历史数据上产生交易信号时,那种感觉就像看着自己组装的小车终于能跑起来一样兴奋。记得最早我测试的一个简单策略,在2015年股灾期间竟然成功避免了大部分下跌,那一刻我突然明白为什么专业机构如此依赖量化方法。当然,后来也遇到过策略失效的时候,但正是这些经历让我学会了永远要有备选方案。

更多推荐