python使用pandas进行量化回测

  • Post category:Python

下面是使用Python和Pandas进行量化回测的完整攻略:

1. 策略开发与回测

1.1 策略设计

要实现量化回测,首先需要确定一个交易策略。通常的交易策略包括均线策略、机器学习策略、套利策略等等。这里以简单的均线策略为例:

当股价在短期均线(如5日均线)上方时买入(做多),在长期均线(如20日均线)下方时卖出(平仓)。

1.2 数据获取与处理

获取股票数据可以使用Tushare库等工具。这里以Tushare获取股票数据为例:

import tushare as ts

df = ts.get_k_data('600519', start='2018-01-01', end='2019-12-31', ktype='D')
df.to_csv('600519.csv')

上面的代码将获取贵州茅台(股票代码为600519)的每日行情数据并保存到文件中。

得到股票数据后,需要计算短期均线和长期均线:

import pandas as pd

df = pd.read_csv('600519.csv', index_col='date', parse_dates=True)
df['sma5'] = df['close'].rolling(5).mean()
df['sma20'] = df['close'].rolling(20).mean()

上面的代码使用Pandas计算了5日和20日的简单移动平均线。

1.3 完成回测

得到均线数据后,就可以开始回测了。回测通常是用历史数据来模拟交易过程。这里以简单的逐日回测为例:

import numpy as np

# 初始化资本为10万元
capital = 100000
# 定义交易费用万分之二
fee_rate = 0.0002

# 开始逐日回测
for i in range(20, len(df)):
    # 计算当日的信号
    signal = 1 if df['sma5'][i] > df['sma20'][i] else 0

    # 检查是否可以交易
    if i == 20:
        can_trade = True
    else:
        last_signal = 1 if df['sma5'][i-1] > df['sma20'][i-1] else 0
        can_trade = signal != last_signal

    # 若可以交易,则进行交易
    if can_trade:
        if signal == 1:
            # 买入
            shares = np.floor(capital * (1-fee_rate) / df['close'][i])
            capital -= shares * df['close'][i] * (1+fee_rate)

        else:
            # 卖出
            capital += shares * df['close'][i] * (1-fee_rate)
            shares = 0

# 计算回测结果
result = capital - 100000
print(result)

上面的代码模拟了在每日收盘时根据均线交易的过程,并计算出了回测结果。

2. 示例

下面给出另一个使用Python和Pandas进行量化回测的示例。该示例实现了一个协整配对交易策略,用来对农产品期货的交易进行回测。

2.1 策略设计

协整配对交易策略的基本思路是寻找两个价格之间的协整关系,即它们之间长期的均衡点。当价格偏离该均衡点时,就会出现交易机会。

具体实现中,可以使用ADF检验或OLS(最小二乘)建模等方式找到价格间的协整关系。然后,可以在两个价格之间设置一个阈值,当二者的差值超过该阈值时进行交易。这里讲轻微差异改为动用的就是认为跌到一定点就买入不过落实情况需要进行修改。

2.2 数据获取与处理

首先需要获取合适的期货交易数据。这里使用Tushare提供的API获取豆粕和豆油的期货合约数据:

import tushare as ts

df_m = ts.get_k_data('M1905', start='2018-01-01', end='2019-12-31', ktype='D')
df_y = ts.get_k_data('Y1905', start='2018-01-01', end='2019-12-31', ktype='D')
df_m.to_csv('M1905.csv')
df_y.to_csv('Y1905.csv')

得到合约数据后,可以使用Pandas将它们合并成一个DataFrame,并计算它们的价格差值:

import pandas as pd

df_m = pd.read_csv('M1905.csv', index_col='date', parse_dates=True)[['close']]
df_y = pd.read_csv('Y1905.csv', index_col='date', parse_dates=True)[['close']]
df = pd.merge(df_m, df_y, left_index=True, right_index=True)
df.columns = ['m', 'y']
df['spread'] = df['m'] - df['y']

上面的代码将豆粕和豆油期货的价格合并成一个DataFrame,并计算了它们的价差。

2.3 完成回测

得到价差后,就可以开始回测了。这里使用简单的逐日回测框架:

import numpy as np

# 初始化资本为10万元
capital = 100000
# 定义交易费用万分之二
fee_rate = 0.0002
# 定义交易阈值为10元
threshold = 10

# 开始逐日回测
for i in range(1, len(df)):
    # 计算当日的信号
    spread = df['spread'][i]
    if spread > threshold:
        signal = 1
    elif spread < -threshold:
        signal = -1
    else:
        signal = 0

    # 检查是否可以交易
    if i == 1:
        can_trade = True
    else:
        last_signal = 1 if df['spread'][i-1] > threshold else (-1 if df['spread'][i-1] < -threshold else 0)
        can_trade = signal != last_signal

    # 若可以交易,则进行交易
    if can_trade:
        if signal == 1:
            # 买入豆油,卖出豆粕
            shares = np.floor(capital * (1-fee_rate) / df['y'][i])
            capital -= shares * df['y'][i] * (1+fee_rate)
            shares_m = np.floor(shares * df['m'][i] / df['y'][i])
            capital += shares_m * df['m'][i] * (1-fee_rate)

        elif signal == -1:
            # 卖出豆油,买入豆粕
            shares = np.floor(capital * (1-fee_rate) / df['m'][i])
            capital -= shares * df['m'][i] * (1+fee_rate)
            shares_y = np.floor(shares * df['y'][i] / df['m'][i])
            capital += shares_y * df['y'][i] * (1-fee_rate)

# 计算回测结果
result = capital - 100000
print(result)

上面的代码模拟了在每日收盘时根据价差交易的过程,并计算出了回测结果。

以上就是两个使用Python和Pandas进行量化回测的示例。通过这些示例,我们可以了解到如何使用Pandas进行数据处理和计算,以及如何使用Python进行逐日回测。