交易策略回测

本文的目标是描述如何在Python中对基于技术指标的策略进行回测。我将具体使用基于布林带(Bollinger Bands)的策略来生成信号和仓位。

交易策略回测
一键发币: SUI | SOL | BNB | ETH | BASE | ARB | OP | POLYGON | AVAX | FTM | OK

本文的目标是描述如何在Python中对基于技术指标的策略进行回测。我将具体使用基于布林带(Bollinger Bands)的策略来生成信号和仓位。

0、策略描述

在调整后的收盘价上创建20天(±2个标准差)的布林带。当价格从顶部穿过下轨时买入,并持有直到价格从下方穿过上轨的下一次。当价格从下方穿过上轨时卖出,并持有直到价格从顶部穿过下轨的下一次。

以下是创建自己的回测代码的步骤:

  1. 导入必要的库
  2. 下载OHLCV数据(开盘价、最高价、最低价、收盘价、成交量)
  3. 计算每日收益
  4. 创建基于策略的数据列
  5. 创建策略指标
  6. 创建信号和仓位
  7. 分析结果

1、导入必要的库

# Ignore printing all warnings
warnings.filterwarnings('ignore')

# Importing necessary libraries
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import yfinance as yf
import pyfolio as pf
import datetime as dt
import pandas_datareader.data as web
import os
import warnings

# print all outputs
from IPython.core.interactiveshell import InteractiveShell
InteractiveShell.ast_node_interactivity = "all"

2、下载OHLCV数据

我使用雅虎财经的Python API——yfinance获取数据。有许多资源可以用来获取历史数据以回测你的策略。

# downloading historical necessary data for backtesting and analysis
_start = dt.date(2015,1,2)
_end = dt.date(2020,4,30)
ticker = 'MSFT'
df = yf.download(ticker, start = _start, end = _end)
[*********************100%***********************]  1 of 1 completed

3、计算每日收益

此步骤计算每日收益,以便与买入并持有的策略进行比较。买入并持有的策略成为基准或比较策略的标准。换句话说,它检查策略是否比简单地购买并持有股票表现更好。一个好的策略本质上应该优于买入并持有的策略。

# calculating buy and hold strategy returns
df['bnh_returns'] = np.log(df['Adj Close']/df['Adj Close'].shift(1))
df.head(3)

4、创建基于策略的数据列

下一步是创建指标以生成策略条件。对于布林带策略,涉及20日移动平均线、20日移动平均线的标准差、标准差的上轨和下轨。[ma20, std, upper_band, lower_band]

# creating bollinger band indicators
df['ma20'] = df['Adj Close'].rolling(window=20).mean()
df['std'] = df['Adj Close'].rolling(window=20).std()
df['upper_band'] = df['ma20'] + (2 * df['std'])
df['lower_band'] = df['ma20'] - (2 * df['std'])
df.drop(['Open','High','Low'],axis=1,inplace=True,errors='ignore')
df.tail(5)

5、创建策略指标

这是创建策略最关键的一步。它包括:

  • 根据策略生成长线和短线信号
  • 将零值替换为向前填充,以生成长线和短线仓位
  • 将仓位向后移动一天,表示从当天收盘价到次日收盘价的回报计算

信号本质上是指需要采取的操作的指示器(即买入或卖出)。仓位是你在买入或卖出后所保持的状态(即做多或做空)。

# BUY condition
df['signal'] = np.where((df['Adj Close'] < df['lower_band']) &
                        (df['Adj Close'].shift(1) >=       df['lower_band']),1,0)

# SELL condition
df['signal'] = np.where( (df['Adj Close'] > df['upper_band']) &
                          (df['Adj Close'].shift(1) <= df['upper_band']),-1,df['signal'])
# creating long and short positions 
df['position'] = df['signal'].replace(to_replace=0, method='ffill')

# shifting by 1, to account of close price return calculations
df['position'] = df['position'].shift(1)

# calculating stretegy returns
df['strategy_returns'] = df['bnh_returns'] * (df['position'])

df.tail(5)

6、创建信号和仓位

下一步是比较策略表现的累计收益。

这涉及将仓位与每日收益逐元素相乘。

# comparing buy & hold strategy / bollinger bands strategy returns
print("Buy and hold returns:",df['bnh_returns'].cumsum()[-1])
print("Strategy returns:",df['strategy_returns'].cumsum()[-1])

# plotting strategy historical performance over time
df[['bnh_returns','strategy_returns']] = df[['bnh_returns','strategy_returns']].cumsum()
df[['bnh_returns','strategy_returns']].plot(grid=True, figsize=(12, 8))
买入并持有的收益:1.4441301364703079  
策略收益:0.3712255745848457  

<AxesSubplot:xlabel='日期'>

7、分析结果

为了这个步骤,我使用了pyfolio。Pyfolio是一个用于金融投资组合绩效和风险分析的Python库。

pf.create_simple_tear_sheet(df['strategy_returns'].diff())
pyfolio结果

8、评论

pyfolio的结果不言自明。

在历史数据上的“布林带”策略并未优于买入并持有的策略。买入并持有的累计每日收益相当于初始投资的1.44倍,而布林带策略的收益仅相当于初始投资的0.37倍。

出于显而易见的原因,即使回测结果很好,也不应将策略投入实战。存在各种风险,例如未考虑交易成本和股价动量。

通过检查不同策略参数下的收益,还可以优化策略的表现。

可以结合其他技术指标来创建信号,以降低风险并提高性能。实盘策略应实施止损和紧急关闭开关以防策略失控。

此代码片段可以在github找到。


原文链接:Algorithmic Trading - Backtesting a strategy in pytho

DefiPlot翻译整理,转载请标明出处

免责声明:本站资源仅用于学习目的,也不应被视为投资建议,读者在采取任何行动之前应自行研究并对自己的决定承担全部责任。
通过 NowPayments 打赏