本文翻译自2018年最热门的Python金融教程 Python For Finance: Algorithmic Trading。
本教程由以下五部分内容构成:
- Python金融入门
- 常见的金融分析方法
- 简单的动量策略开发
- 回溯测试策略
- 评估交易策略
本文是该教程的最后一部分。
改进交易策略
你已经成功地实现了一个简单的交易策略,并使用 Pandas、ZipLine 和 Quantopian 进行了回溯测试。可以说你已入门了Python交易分析。然而,当你完成交易策略的编码和回测,并不意味着工作的完成;可能还需要改进策略。有多种算法可以用来持续地改进模型,比如K均值、k最近邻(KNN)、分类或回归树,以及遗传算法。这将是今后DataCamp教程的内容。
除了可以使用其它算法之外,还可以通过使用多家公司的股票构建投资组合来改进策略。策略中仅有一家公司往往没有太大意义。在评估移动均线交叉策略时,你还会看到这一点。其他可以做的就是使用风险管理框架或事件驱动的回溯测试来减轻之前提到的前视偏差。
评估移动均线交叉策略
即使改进了交易策略,也不意味着工作到此为止。使用 Pandas 能够轻松地计算相关指标来进一步评估你的简单交易策略。首先,使用夏普比率来了解你的投资组合回报,是否是你决定进行明智投资或承担高风险的事实结果。
当然,最理想的情况是,回报可观而投资的额外风险尽可能低。夏普比率是收益率和额外风险的比率,因此它的值越高越好。通常,该比率大于1时能被投资者接受,2是非常好的,3就是极好的了。
让我们来看看该算法是如何实现的!
在开始之前,先获取 apple 公司的股票数据,参考本教程的第一部分:基础入门。
# 获取apple公司股票数据
import pandas_datareader as pdr
import datetime
aapl = pdr.get_data_yahoo('AAPL',
start=datetime.datetime(2006, 10, 1),
end=datetime.datetime(2012, 1, 1))
然后是创建均线交叉策略,参考本教程的第三部分:用Python构建交易策略。
# 导入pandas,numpy
import pandas as pd
import numpy as np
# 初始化短期和长期窗口
short_window = 40
long_window = 100
# 初始化 `signals` 数据框,增加 `signal` 列
signals = pd.DataFrame(index=aapl.index)
signals['signal'] = 0.0
# 创建短期简单移动均值
signals['short_mavg'] = aapl['Close'] \
.rolling(window=short_window, min_periods=1, center=False) \
.mean()
# 创建长期简单移动均值
signals['long_mavg'] = aapl['Close'] \
.rolling(window=long_window, min_periods=1, center=False) \
.mean()
# 生成信号
signals['signal'][short_window:] = np.where(signals['short_mavg'][short_window:]
> signals['long_mavg'][short_window:], 1.0, 0.0)
# 生成交易命令
signals['positions'] = signals['signal'].diff()
接下来回测交易策略,参考本教程第四部分:回测交易策略。
# 设置初始资金
initial_capital= float(100000.0)
# 创建数据框 `positions`
positions = pd.DataFrame(index=signals.index).fillna(0.0)
# 当signal为1时,买入100股
positions['AAPL'] = 100*signals['signal']
# 用拥有的价值初始化 portfolio
portfolio = positions.multiply(aapl['Adj Close'], axis=0)
# 存储股票数目的差值
pos_diff = positions.diff()
# 在 portfolio 中增加 `holdings` 列
portfolio['holdings'] = (positions.multiply(aapl['Adj Close'], axis=0)) \
.sum(axis=1)
# 在 portfolio 中增加`cash`列
portfolio['cash'] = initial_capital \
- (pos_diff.multiply(aapl['Adj Close'], axis=0)) \
.sum(axis=1).cumsum()
# 在 portfolio 中增加`total`列
portfolio['total'] = portfolio['cash'] + portfolio['holdings']
# 在 portfolio 中增加`returns` 列
portfolio['returns'] = portfolio['total'].pct_change()
下面开始对策略进行评估。
# 从策略中提取收益率
returns = portfolio['returns']
# 计算年化的夏普比率
sharpe_ratio = np.sqrt(252) * (returns.mean() / returns.std())
# 输出夏普比率
print(sharpe_ratio)
0.7244202796907433
注意在本教程中,夏普比率的定义忽略了无风险利率。另外,通常不单独考虑一只股票的夏普比率,一般将多只股票进行比较。解决该问题最好的方法是使用来自其他公司的更多数据,扩展最初的交易策略。
接下来,还可以计算最大回撤率(Maximum Drawdown),它用于测量在投资组合价值中,在下一次峰值来到之前,最高点和最低点之间的最大单次下降。换言之,该值代表了基于某个策略的投资组合风险。
import matplotlib.pyplot as plt
# 定义交易日的移动窗口
window = 252
# 为每一天计算过去时间窗口中最大回撤率
rolling_max = aapl['Adj Close'].rolling(window, min_periods=1).max()
daily_drawdown = aapl['Adj Close']/rolling_max - 1.0
# 计算最小的(负值)每日回撤率
max_daily_drawdown = daily_drawdown.rolling(window, min_periods=1).min()
# 绘图
daily_drawdown.plot()
max_daily_drawdown.plot()
# 显示绘图
plt.show()
注意设置 min_periods
的值为 1
,这是为了使开始的252天也具有扩展的窗口。
其次是复合年增长率(CAGR),它是一段时间内的恒定回报率。换言之,该比率告诉你在投资期结束时,你真正获得的收益。可以这么来计算,首先将投资最后的价值()除以最初的价值()。然后对该比值求 幂次,这里 是投资的期数。最后将上面的结果减去 ,就得到了复合年增长率。
也许使用公式来说明会更清楚:
注意,在下方的代码框中,考虑的是天数,所以将1调整为365天(等价于1年)。
# Get the number of days in `aapl`
days = (aapl.index[-1] - aapl.index[0]).days
# Calculate the CAGR
cagr = ((((aapl['Adj Close'][-1]) / aapl['Adj Close'][1])) ** (365.0/days)) - 1
# Print the CAGR
print(cagr)
0.3823444961078535
除了这两项指标,还有许多其他指标可以考虑,比如收益分布、交易水平指标,等等。
接下来呢?
干的漂亮,你已经学完了这篇Python金融入门教程!虽然有了一定基础,但仍有许多知识等待你来发现。从 DataCamp 的 Intro to Python for Finance 课程开始学习更多的基础知识吧。
Yves Hilpisch 的 《Python For Finance》一书对具备金融背景却不熟悉Python的读者是非常好的一本书。 Michael Heydt 的《Mastering Pandas for Data Science》也非常推荐给想学习Python金融的读者。同时也请查阅 Quantstart文章 中的算法交易入门指南,以及金融Python编程这一完整系列。
如果你对继续使用R语言进行金融分析更感兴趣,可以考虑参加 DataCamp 的 Quantitative Analyst with R 学习路径。同时,请继续关注我们关于使用Python进行金融分析的第二篇文章,并查看本教程的 Jupyter notebook。