不借助三方平台自主搭建量化回测系统 ——以海龟交易策略为例
更多精彩内容,欢迎关注公众号:数量技术宅,也可添加技术宅个人微信号:sljsz01,与我交流。
三方平台与自主系统的优劣势对比
在编写量化策略回测时,可以选择使用三方平台(第三方量化平台)或自主平台(自己编写代码)两种方式。它们各自有一些优劣势,下面是它们的对比:
三方平台:
优势:
-
简单易用: 大多数三方平台都提供了用户友好的界面和可视化工具,使得策略的构建和回测过程相对容易上手,即使对编程不熟悉的人也可以使用。
-
快速回测: 三方平台通常会优化回测引擎,使回测的速度更快,尤其是针对大规模数据进行回测时,可以节省大量时间。
-
数据和资料库: 大多数三方平台会提供包括历史市场数据、财务数据和交易数据等在内的资料库,无需自行采集数据,极大地简化了数据处理流程。
-
社区和支持: 常用的三方平台拥有活跃的用户社区和技术支持团队,您可以在这里交流经验、寻求帮助,解决问题更加方便。
劣势:
-
有限的灵活性: 三方平台的功能和策略构建方法通常受到平台本身的限制,可能无法实现某些较为复杂的量化策略。
-
数据安全性: 使用三方平台需要将您的交易数据和策略上传到平台服务器,涉及到数据安全和隐私问题,可能会让一些用户感到担忧。
-
成本: 尽管一些三方平台提供免费版,但更强大的功能和服务可能需要付费订阅,长期来看可能会增加成本。
自主平台:
优势:
-
灵活性: 使用自主平台编写代码,您可以完全控制策略的逻辑和实现方式,没有受到第三方平台功能的限制,能够实现更加复杂和个性化的策略。
-
数据控制: 在自主平台上,您可以控制自己的数据,不需要将数据上传到第三方服务器,有更好的数据隐私和安全控制。
-
学习机会: 自主编写代码让您更深入了解量化交易的原理和编程技能,有助于提高技术水平和理解市场。
劣势:
-
技术要求: 对编程和量化金融知识要求较高,需要具备相应的技术能力和知识储备,可能不太适合初学者。
-
复杂性: 自主编写代码意味着需要从头开始搭建回测框架、处理数据、设计策略等,工作量相对较大,可能耗费更多的时间。
-
回测速度: 自主编写的代码在效率上可能不如经过优化的三方平台,尤其在处理大规模数据时。
总的来说,如果对编程不熟悉或者只是想尝试简单的策略朋友,使用三方平台可能更为方便快捷。但是,如果有一定的编程技能,并且希望实现更复杂的量化策略,或者更关注数据隐私和自由度,则自主平台更适合。本期文章,我们就将以海龟交易策略为例,手把手教大家不借助三方平台(除数据源)完全自主搭建一个简单的Python回测系统,堪称量化小白用户的“保姆级教程”。
自主回测系统数据源
在国内市场,有几个常用的量化策略回测数据源,这些数据源提供了历史市场数据和财务数据,供量化投资者用于回测和研究策略。以下是一些常见的中国市场量化策略回测数据源:
-
Wind(万得): Wind是中国知名的金融数据服务提供商,它提供广泛的金融市场数据,包括股票、债券、期货、指数等数据,同时还提供财务数据、宏观经济数据和新闻等信息。Wind的数据覆盖范围广泛,是中国量化投资者的重要数据来源之一。
-
通达信: 通达信是中国股票市场上广泛使用的一种股票交易软件,它也提供历史市场数据供回测使用。通达信的数据通常包含股票的价格、交易量、财务指标等信息。
-
聚宽(JoinQuant): 聚宽是一家为量化投资者提供数据服务的公司,它提供了丰富的股票、基金、期货等市场的历史数据和实时数据。聚宽还提供Python编程接口,方便投资者使用Python进行量化策略回测和交易。
-
掘金量化(JQData): 掘金量化是另一家专注于量化投资数据服务的公司,提供了股票、期货、指数等市场的历史数据,同时也提供了Python编程接口,方便用户进行自主量化研究和回测。
为降低关注文章朋友的学习成本,本文就将选择免费版Tushare数据源,获取沪深300指数的历史数据。安装免费版Tushare库,以及历史K线数据获取详细介绍,可以参考我们的历史文章:。具体获取数据的代码只需要两行完成:
import tushare as ts # 获取hs300指数从2015年初到最新的历史数据 df = ts.get_k_data('hs300', start='2015-01-01')
交易策略回测主函数
# 定义海龟交易策略函数 def turtle_trading(stock_data): # 计算20日突破价格 stock_data['20d_high'] = pd.Series.rolling(stock_data['high'], window=20, center=False).max() stock_data['20d_low'] = pd.Series.rolling(stock_data['low'], window=20, center=False).min() stock_data['20d_close'] = pd.Series.rolling(stock_data['close'], window=20, center=False).mean() stock_data['prev_20d_high'] = stock_data['20d_high'].shift(1) stock_data['prev_20d_low'] = stock_data['20d_low'].shift(1) stock_data['prev_20d_close'] = stock_data['20d_close'].shift(1) stock_data['buy_signal'] = (stock_data['close'] > stock_data['prev_20d_high']) & (stock_data['prev_20d_close'] <= stock_data['prev_20d_high']) stock_data['sell_signal'] = (stock_data['close'] < stock_data['prev_20d_low']) & (stock_data['prev_20d_close'] >= stock_data['prev_20d_low']) # 计算持仓状态 stock_data['position'] = None stock_data.loc[stock_data['buy_signal'], 'position'] = 1 stock_data.loc[stock_data['sell_signal'], 'position'] = 0 stock_data['position'].fillna(method='ffill', inplace=True) # 计算每日收益率 stock_data['daily_return'] = stock_data['close'].pct_change() * stock_data['position'].shift(1) # 计算累计收益率 stock_data['cum_return'] = (1 + stock_data['daily_return']).cumprod() return stock_data
海龟交易策略是一种趋势跟随策略,其主要思想是利用历史股价的突破来产生买入和卖出信号。代码对应解锁如下:
-
-
记录前一个交易日的20日突破价格:通过将
20d_high
、20d_low
和20d_close
的值向后平移一天,记录为prev_20d_high
、prev_20d_low
和prev_20d_close
。 -
产生买入和卖出信号:买入信号为当日收盘价大于前一个交易日的
prev_20d_high
且前一个交易日的收盘价小于等于prev_20d_high
;卖出信号为当日收盘价小于前一个交易日的prev_20d_low
且前一个交易日的收盘价大于等于prev_20d_low
。 -
计算持仓状态:根据买入和卖出信号,确定每日的持仓状态,用1表示买入,0表示卖出。
-
计算每日收益率:根据持仓状态和当日收盘价计算每日的收益率。
-
计算累计收益率:将每日收益率累乘,得到累计收益率。
此外,该函数中使用了pandas的滚动计算和位运算,涉及了数据的平移、填充等操作,所以输入的stock_data
DataFrame数据需要包含至少以下列:'high'(最高价)、'low'(最低价)、'close'(收盘价)。当然,这只是一个简单的海龟交易策略示例,实际应用中可能需要更多的调整和改进,例如加入风险控制、手续费和滑点等因素。
接下来是函数调用模块,通过读取数据、调用函数,进行回测:
# 读取数据 df.set_index('date', inplace=True) df.index = pd.to_datetime(df.index) # 回测海龟交易策略 df = turtle_trading(df)
首先将DataFrame的索引设置为日期,并将日期列转换为Datetime类型。接下来,调用了之前定义的turtle_trading
函数,对DataFrame执行了海龟交易策略的回测操作。
其中,df
是包含股票数据的DataFrame,按照之前提供的海龟交易策略函数turtle_trading
的定义,函数会在df
中增加一些列来表示策略信号和回测结果,包括买入信号(buy_signal
)、卖出信号(sell_signal
)、持仓状态(position
回测过程是基于历史数据执行的,因此需要确保df
中包含足够的历史股票数据来进行回测。回测的结果将会存储在df
中,可以通过查看增加的列来了解策略在历史数据上的表现。
计算回测指标
执行完回测,下一步我们需要做的是分析这个策略的表现,这个分析过程主要是通过计算回测指标进行评价:
# 计算回测指标 annual_return = (df['cum_return'][-1]) ** (252/len(df.index)) - 1 daily_return = df['daily_return'].mean() daily_volatility = df['daily_return'].std() sharpe_ratio = (annual_return - 0.03) / daily_volatility max_drawdown = (df['cum_return'].max() - df['cum_return'].min()) / df['cum_return'].max() print('年化收益率:{:.2%}'.format(annual_return)) print('日均收益率:{:.2%}'.format(daily_return)) print('日收益率波动率:{:.2%}'.format(daily_volatility)) print('夏普比率:{:.2f}'.format(sharpe_ratio)) print('最大回撤:{:.2%}'.format(max_drawdown))
年化收益率(Annual Return): 表示策略在一年内实现的平均每日收益率。根据回测结果的累计收益率,将其指数化到一年的时间跨度内,通过以下公式计算:
annual_return = (cum_return[-1]) ** (252 / len(df.index)) - 1
日均收益率(Daily Return): 表示策略在回测期间的平均每日收益率。计算方式为每日收益率的简单平均。
daily_return = df['daily_return'].mean()
daily_volatility = df['daily_return'].std()
sharpe_ratio = (annual_return - 0.03) / daily_volatility
假设无风险利率为3%,这里将其减去后再除以波动率。
最大回撤(Max Drawdown):
max_drawdown = (cum_return.max() - cum_return.min()) / cum_return.max()
输出回测图
最后一步,我们将此前回测得到的结果,采用可视化的方式展现处理,即输出回测图模块:
# 输出回测图 import matplotlib.pyplot as plt plt.plot(df['cum_return']) plt.title('Turtle Trading Strategy Backtest') plt.xlabel('Date') plt.ylabel('Cumulative Return') plt.show()
这段代码使用matplotlib库输出了回测图,展示了海龟交易策略的累计收益曲线。我们来解释一下代码的功能:
-
plt.plot(df['cum_return'])
:通过plt.plot()
函数绘制累计收益曲线,df['cum_return']
是策略回测中计算的累计收益率的数据列。 -
-
plt.xlabel('Date')
:设置X轴的标签为"Date",即日期。 -
plt.ylabel('Cumulative Return')
:设置Y轴的标签为"Cumulative Return",即累计收益率。 -
plt.show()
:显示绘制的回测图。
运行此段代码将在图形窗口中显示海龟交易策略的累计收益曲线。通过该曲线(下图),您可以直观地看到策略的收益变化情况,以及可能的峰值和谷底。请注意,该图表只是回测结果的可视化展示,不能代替对策略的全面分析和评估。
以及在回测指标计算模块计算得到的回测指标数值,同样在运行过程中将其打印出来:
到这里,我们就完成了一个简单自主搭建的海龟交易策略回测系统,它包括回测数据获取、回测函数构建与调用、回测指标计算,以及输出回测图,四个主要步骤。电脑前的你,Get到回测系统的设计小技能了吗?