【譯】Python 金融:算法交易 (3)用Python構(gòu)建交易策略

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

本教程由以下五部分內(nèi)容構(gòu)成:

本文是該教程的第三部分庸追。


既然你已對數(shù)據(jù)做了初步分析,那么是時(shí)候創(chuàng)建你的第一個(gè)交易策略了劈愚。但在深入研究之前,為什么不先來了解一些最常用的交易策略呢?下面簡短的介紹琢锋,無疑會讓你更容易開始交易策略的開發(fā)绎秒。

常見的交易策略

你應(yīng)該還記得在本教程開篇的介紹中浦妄,我們講了交易策略是在市場上做多或做空的既定計(jì)劃,但不僅限于此见芹,你還有更多的信息沒有真正掌握剂娄。一般來說,有兩種常見的交易策略:動量策略(momentum strategy)和回歸策略(reversion strategy)玄呛。

第一種是動量策略阅懦,也被稱為背離(divergence)或趨勢(trend)交易。當(dāng)遵循該策略時(shí)把鉴,你相信數(shù)值會沿著當(dāng)前的方向繼續(xù)移動故黑。也就是說你相信股票具有慣性,即有上升或下降的趨勢庭砍,能被你發(fā)現(xiàn)并利用场晶。

這一策略的實(shí)例包括移動均線交叉策略(moving average crossover)、雙均線交叉策略(dual moving average crossover)和海龜交易策略(turtle trading)怠缸。

  • 移動均線交叉是指資產(chǎn)的價(jià)格從移動均線的一側(cè)移動到了另一側(cè)诗轻。這一交叉代表了動量的改變,可以作為進(jìn)入或退出市場的決策點(diǎn)揭北。在本教程的后面你會學(xué)到量化交易中使用該策略的入門級案例扳炬。
  • 雙均線交叉發(fā)生在短期均線與長期均線交叉處吏颖。這一信號被用來識別在短期均線上的變化。買入信號發(fā)生在短期均線從下方上升超越長期均線時(shí)恨樟,而賣出信號則由短期均線從上方下降越過長期均線而觸發(fā)半醉。
  • 海龜交易是一個(gè)眾所周知的趨勢跟蹤策略,最初是由理查德·丹尼斯教授給大家的劝术。它的基本策略是以20天高點(diǎn)買入期貨缩多,并在20天低點(diǎn)賣出。

第二種是回歸策略养晋,也被稱為收斂(convergence)或循環(huán)(cycle)交易衬吆。這一策略相信數(shù)值的運(yùn)動最終會逆轉(zhuǎn)。這可能有點(diǎn)抽象绳泉,讓我們來舉個(gè)例子逊抡。在均值回歸策略(mean reversion strategy)中,你確信股價(jià)會回到它的均值零酪,當(dāng)它偏離均值時(shí)就可以利用這一點(diǎn)來做決策冒嫡。

聽起來已經(jīng)很實(shí)用了,對吧蛾娶?

除了均值回歸策略以外灯谣,另一個(gè)例子是與之相似的配對交易均值回歸(pairs trading mean-reversion)。均值回歸策略的基本思想是股價(jià)會回到其均值蛔琅,而配對交易策略對此進(jìn)行了擴(kuò)展胎许,認(rèn)為如果能識別出兩只高度相關(guān)的股票,當(dāng)其中之一偏離了與另一方的相關(guān)性罗售,兩者價(jià)格差的改變就能作為交易的信號辜窑。這意味著如果這兩只股票的相關(guān)性下降,那么可以做空價(jià)格較高的股票寨躁。高價(jià)格的股票最終會回到其均值穆碎,所以它應(yīng)該被賣出。另一方面职恳,做多低價(jià)格的股票所禀,因?yàn)殡S著相關(guān)性恢復(fù)正常,其價(jià)格將會上升放钦。

除了這兩種最常用的策略色徘,還有其他你偶爾可能會碰上的策略,比如預(yù)測策略操禀,它試圖基于某些歷史因素預(yù)測股票在隨后一段時(shí)間內(nèi)的方向和價(jià)值褂策。還有高頻交易策略(HFT),它利用了亞毫秒市場的微觀結(jié)構(gòu)來做決策。

這都是今后的樂章了斤寂,現(xiàn)在讓我們聚焦于開發(fā)你的第一個(gè)交易策略耿焊。

一個(gè)簡單的交易策略

正如上面所述,你將從量化交易的“hello world”:移動均線交叉策略開始遍搞。你將要開發(fā)的策略很簡單:對時(shí)間序列創(chuàng)建兩個(gè)獨(dú)立的簡單移動均值(Simple Moving Averages, SMA)罗侯,它們具有不同的回望周期,比如40天和100天尾抑。如果短期移動均值超過了長期移動均值歇父,那么就做多;如果長期移動均值超過了短期移動均值再愈,那么就退出。

記住當(dāng)做多時(shí)护戳,你認(rèn)為股價(jià)會上漲翎冲,并且將來會以更高的價(jià)格賣出(=買入信號);當(dāng)賣空時(shí)媳荒,你賣出你的股票抗悍,希望將來以更低的價(jià)格買回并實(shí)現(xiàn)盈利(=賣出信號)。

當(dāng)你剛開始的時(shí)候钳枕,這一簡單的策略可能看起來相當(dāng)復(fù)雜缴渊。但是讓我們一步一步來:

  • 首先,定義兩個(gè)不同的回望周期:一個(gè)短期窗口和一個(gè)長期窗口鱼炒。設(shè)置兩個(gè)變量衔沼,并對每一個(gè)變量賦值一個(gè)整數(shù)。一定要讓短期窗口的值小于長期窗口的值昔瞧。
  • 接著指蚁,創(chuàng)建一個(gè)空的數(shù)據(jù)框 signals,并確保復(fù)制了aapl 數(shù)據(jù)的索引自晰,以便能開始計(jì)算 aapl 數(shù)據(jù)每日的買賣信號凝化。
  • 在空的 signals 數(shù)據(jù)框中創(chuàng)建一列名為 signal 的數(shù)據(jù),并將其每一行的數(shù)值初始化為 0.0酬荞。
  • 做好了準(zhǔn)備工作后搓劫,是時(shí)候在各自的時(shí)間窗口上創(chuàng)建短期和長期的簡單移動均值了。使用 rolling() 函數(shù)開始滑動窗口計(jì)算:在該函數(shù)中混巧,設(shè)置 window 枪向、 min_periodcenter 參數(shù)。在實(shí)際中牲剃,窗口大小window 分別設(shè)置為 short_windowlong_window遣疯。min_period 設(shè)為 1,作為窗口中觀測量的最小值。center 的值為 False缠犀,這樣標(biāo)簽就不會設(shè)置在窗口的中心数苫。接著,不要忘了在其后連接 mean() 函數(shù)以便能計(jì)算滾動均值辨液。
  • 當(dāng)計(jì)算了短期和長期窗口的均值后虐急,你應(yīng)該在短期移動均線與長期移動均線交叉處創(chuàng)建信號,但這僅針對大于最短移動均值窗口的時(shí)期滔迈。在Python中止吁,這對應(yīng)著如下條件不等式:signals['short_mavg'][short_window:] > signals['long_mavg'][short_window:]。注意加上 [short_window:] 是為了遵守條件“僅針對大于最短移動均值窗口的時(shí)期”燎悍。當(dāng)上述條件不等式為真時(shí)敬惦,signal 列中的初值 0.0 將被替換為 1.0。 這樣一個(gè)“信號”就產(chǎn)生了谈山。如果條件不等式為假俄删,將繼續(xù)保留原始值0.0,也沒有信號產(chǎn)生奏路。使用 NumPy 中的 where() 函數(shù)來設(shè)置這一條件不等式畴椰。就像你剛才讀到的那樣,將這一結(jié)果賦值給變量 signals['signal'][short_window]鸽粉,因?yàn)槲覀儍H想針對大于最短移動均值窗口的時(shí)期創(chuàng)建信號斜脂。
  • 最后,計(jì)算信號的差值触机,從而生成實(shí)際的交易訂單帚戳。換句話說,在 signals 數(shù)據(jù)框的 positions 這一列中威兜,你將能區(qū)分多頭和空頭頭寸销斟,無論是買入或賣出股票。

嘗試下方的代碼:

# 導(dǎo)入apple公司股票數(shù)據(jù)
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))
# 導(dǎo)入pandas,numpy
import pandas as pd
import numpy as np

# 初始化短期和長期窗口
short_window = 40
long_window = 100

# 初始化 `signals` 數(shù)據(jù)框椒舵,增加 `signal` 列
signals = pd.DataFrame(index=aapl.index)
signals['signal'] = 0.0

# 創(chuàng)建短期簡單移動均值
signals['short_mavg'] = aapl['Close'].rolling(window=short_window, min_periods=1, center=False).mean()

# 創(chuàng)建長期簡單移動均值
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()

# 輸出`signals`
print(signals)
            signal  short_mavg  long_mavg  positions
Date                                                
2006-10-02     0.0   10.694285  10.694285        NaN
2006-10-03     0.0   10.638571  10.638571        0.0
2006-10-04     0.0   10.681905  10.681905        0.0
2006-10-05     0.0   10.683928  10.683928        0.0
2006-10-06     0.0   10.667714  10.667714        0.0
2006-10-09     0.0   10.666667  10.666667        0.0
2006-10-10     0.0   10.649184  10.649184        0.0
2006-10-11     0.0   10.625714  10.625714        0.0
2006-10-12     0.0   10.639683  10.639683        0.0
2006-10-13     0.0   10.647429  10.647429        0.0
2006-10-16     0.0   10.658701  10.658701        0.0
2006-10-17     0.0   10.654881  10.654881        0.0
2006-10-18     0.0   10.654286  10.654286        0.0
2006-10-19     0.0   10.699286  10.699286        0.0
2006-10-20     0.0   10.747429  10.747429        0.0
2006-10-23     0.0   10.803036  10.803036        0.0
2006-10-24     0.0   10.848655  10.848655        0.0
2006-10-25     0.0   10.894206  10.894206        0.0
2006-10-26     0.0   10.938797  10.938797        0.0
2006-10-27     0.0   10.966214  10.966214        0.0
2006-10-30     0.0   10.991088  10.991088        0.0
2006-10-31     0.0   11.017987  11.017987        0.0
2006-11-01     0.0   11.030621  11.030621        0.0
2006-11-02     0.0   11.041131  11.041131        0.0
2006-11-03     0.0   11.046857  11.046857        0.0
2006-11-06     0.0   11.059945  11.059945        0.0
2006-11-07     0.0   11.076296  11.076296        0.0
2006-11-08     0.0   11.101378  11.101378        0.0
2006-11-09     0.0   11.129113  11.129113        0.0
2006-11-10     0.0   11.153952  11.153952        0.0
...            ...         ...        ...        ...
2011-11-17     1.0   56.485857  54.946829        0.0
2011-11-18     1.0   56.381000  55.005257        0.0
2011-11-21     1.0   56.259000  55.052886        0.0
2011-11-22     1.0   56.177750  55.100386        0.0
2011-11-23     1.0   56.070536  55.125471        0.0
2011-11-25     1.0   55.974107  55.142343        0.0
2011-11-28     1.0   55.955536  55.169371        0.0
2011-11-29     1.0   55.950536  55.188643        0.0
2011-11-30     1.0   55.985179  55.228929        0.0
2011-12-01     1.0   56.019750  55.277757        0.0
2011-12-02     1.0   56.063786  55.323014        0.0
2011-12-05     1.0   56.146679  55.373357        0.0
2011-12-06     1.0   56.154322  55.410543        0.0
2011-12-07     1.0   56.114322  55.432386        0.0
2011-12-08     1.0   56.073143  55.452114        0.0
2011-12-09     1.0   56.020250  55.461714        0.0
2011-12-12     1.0   55.912536  55.468214        0.0
2011-12-13     1.0   55.801179  55.461800        0.0
2011-12-14     1.0   55.651000  55.435643        0.0
2011-12-15     1.0   55.580715  55.400686        0.0
2011-12-16     1.0   55.529679  55.384157        0.0
2011-12-19     1.0   55.491607  55.370429        0.0
2011-12-20     1.0   55.456536  55.378243        0.0
2011-12-21     1.0   55.451822  55.377814        0.0
2011-12-22     1.0   55.444500  55.391586        0.0
2011-12-23     1.0   55.439643  55.406957        0.0
2011-12-27     0.0   55.445286  55.448614       -1.0
2011-12-28     0.0   55.437643  55.490072        0.0
2011-12-29     0.0   55.468393  55.564229        0.0
2011-12-30     0.0   55.495500  55.608500        0.0

[1323 rows x 4 columns]

不是很難蚂踊,對吧?輸出 signals 數(shù)據(jù)框并檢查其結(jié)果笔宿。這里重要的是要掌握該數(shù)據(jù)框中 positionssignal 這兩列的含義犁钟。當(dāng)你繼續(xù)下去時(shí),會發(fā)現(xiàn)這一點(diǎn)變得非常重要泼橘。

當(dāng)你花時(shí)間去理解該交易策略的結(jié)果時(shí)涝动,可以用 Matplotlib 將短期和長期的移動均線,以及買入和賣出的信號炬灭,快速繪制在圖中醋粟。

# 導(dǎo)入`pyplot` 模塊 
import matplotlib.pyplot as plt

# 初始化圖形
fig = plt.figure(figsize=(12,8))

# 增加子圖并設(shè)置y軸標(biāo)簽
ax1 = fig.add_subplot(111,  ylabel='Price in $')

# 繪制收盤價(jià)曲線
aapl['Close'].plot(ax=ax1, color='r', lw=2.)

# 繪制短期和長期移動均線
signals[['short_mavg', 'long_mavg']].plot(ax=ax1, lw=2.)

# 繪制買入信號
ax1.plot(signals.loc[signals.positions == 1.0].index, 
         signals.short_mavg[signals.positions == 1.0],
         '^', markersize=10, color='m')
         
# 繪制賣出信號
ax1.plot(signals.loc[signals.positions == -1.0].index, 
         signals.short_mavg[signals.positions == -1.0],
         'v', markersize=10, color='k')
         
# 顯示做圖
plt.show()

結(jié)果很酷,不是嗎?

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末米愿,一起剝皮案震驚了整個(gè)濱河市厦凤,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌育苟,老刑警劉巖较鼓,帶你破解...
    沈念sama閱讀 216,496評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異违柏,居然都是意外死亡博烂,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,407評論 3 392
  • 文/潘曉璐 我一進(jìn)店門漱竖,熙熙樓的掌柜王于貴愁眉苦臉地迎上來禽篱,“玉大人,你說我怎么就攤上這事闲孤∽患叮” “怎么了?”我有些...
    開封第一講書人閱讀 162,632評論 0 353
  • 文/不壞的土叔 我叫張陵讼积,是天一觀的道長。 經(jīng)常有香客問我脚仔,道長勤众,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,180評論 1 292
  • 正文 為了忘掉前任鲤脏,我火速辦了婚禮们颜,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘猎醇。我一直安慰自己窥突,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,198評論 6 388
  • 文/花漫 我一把揭開白布硫嘶。 她就那樣靜靜地躺著阻问,像睡著了一般。 火紅的嫁衣襯著肌膚如雪沦疾。 梳的紋絲不亂的頭發(fā)上称近,一...
    開封第一講書人閱讀 51,165評論 1 299
  • 那天,我揣著相機(jī)與錄音哮塞,去河邊找鬼刨秆。 笑死,一個(gè)胖子當(dāng)著我的面吹牛忆畅,可吹牛的內(nèi)容都是我干的衡未。 我是一名探鬼主播,決...
    沈念sama閱讀 40,052評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼缓醋!你這毒婦竟也來了如失?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,910評論 0 274
  • 序言:老撾萬榮一對情侶失蹤改衩,失蹤者是張志新(化名)和其女友劉穎岖常,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體葫督,經(jīng)...
    沈念sama閱讀 45,324評論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡竭鞍,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,542評論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了橄镜。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片偎快。...
    茶點(diǎn)故事閱讀 39,711評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖洽胶,靈堂內(nèi)的尸體忽然破棺而出晒夹,到底是詐尸還是另有隱情,我是刑警寧澤姊氓,帶...
    沈念sama閱讀 35,424評論 5 343
  • 正文 年R本政府宣布丐怯,位于F島的核電站,受9級特大地震影響翔横,放射性物質(zhì)發(fā)生泄漏读跷。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,017評論 3 326
  • 文/蒙蒙 一禾唁、第九天 我趴在偏房一處隱蔽的房頂上張望效览。 院中可真熱鬧,春花似錦荡短、人聲如沸丐枉。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,668評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽瘦锹。三九已至,卻和暖如春烫映,著一層夾襖步出監(jiān)牢的瞬間沼本,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,823評論 1 269
  • 我被黑心中介騙來泰國打工锭沟, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留抽兆,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,722評論 2 368
  • 正文 我出身青樓族淮,卻偏偏與公主長得像辫红,于是被迫代替她去往敵國和親凭涂。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,611評論 2 353

推薦閱讀更多精彩內(nèi)容

  • 運(yùn)用三遍閱讀法贴妻,在2小時(shí)內(nèi)閱讀完《加速》切油,并閱讀書中某一個(gè)片段,用RIA法進(jìn)行拆解輸出名惩。 一澎胡、閱讀時(shí)間記錄和分析 ...
    度半32閱讀 161評論 0 0
  • 你來我往一起玩,氣氛熱烈不孤單娩鹉。 但愿今生長相伴攻谁,冬天來到也溫暖。
    蠻力閱讀 418評論 3 7
  • 三十歲弯予,曾經(jīng)是一個(gè)那么遙遠(yuǎn)的年齡戚宦,在2011年,他悄悄的來了锈嫩,來的讓我措手不及受楼,難以接受。 回想青蔥歲月里呼寸,什么也...
    做不一樣的我閱讀 367評論 0 0