【译】Python 金融:算法交易 (5)评估交易策略

本文翻译自2018年最热门的Python金融教程 Python For Finance: Algorithmic Trading

本教程由以下五部分内容构成:

本文是该教程的最后一部分。


改进交易策略

你已经成功地实现了一个简单的交易策略,并使用 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),它是一段时间内的恒定回报率。换言之,该比率告诉你在投资期结束时,你真正获得的收益。可以这么来计算,首先将投资最后的价值(EV)除以最初的价值(BV)。然后对该比值求 1/n 幂次,这里 n 是投资的期数。最后将上面的结果减去 1,就得到了复合年增长率。

也许使用公式来说明会更清楚:

(EV / BV)^{1/n} - 1

注意,在下方的代码框中,考虑的是天数,所以将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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,117评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,328评论 1 293
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,839评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,007评论 0 206
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,384评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,629评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,880评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,593评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,313评论 1 243
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,575评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,066评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,392评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,052评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,082评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,844评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,662评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,575评论 2 270

推荐阅读更多精彩内容