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

本文翻譯自2018年最熱門的Python金融教程 Python For Finance: Algorithmic Trading。

本教程由以下五部分內容構成:

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


改進交易策略

你已經成功地實現了一個簡單的交易策略,并使用 Pandas、ZipLine 和 Quantopian 進行了回溯測試??梢哉f你已入門了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閱讀 227,401評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,011評論 3 413
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,263評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,543評論 1 307
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,323評論 6 404
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,874評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 42,968評論 3 439
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,095評論 0 286
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,605評論 1 331
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,551評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,720評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,242評論 5 355
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 43,961評論 3 345
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,358評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,612評論 1 280
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,330評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,690評論 2 370

推薦閱讀更多精彩內容