量化交易實(shí)踐篇(2)—— Quantopian策略實(shí)現(xiàn)初體驗(yàn)

這篇帶大家按照官方入門指南來體驗(yàn)下Quantopian的魅力,文章中會涉及到一些平臺中常用的API房午,大家可以先有個初步印象,用的時候再去查文檔即可。文章最后會實(shí)現(xiàn)一個簡單的均值回歸的策略昧互,好了,寬客動手不動口,開始我們的旅程伟桅!

Quantopian

交易算法框架

在Quantopian中敞掘,交易算法是一段Python腳本,其中包含了幾個關(guān)鍵的函數(shù)

  1. initialize()
    程序啟動時調(diào)用的函數(shù)楣铁,用于處理啟動時需要的一次性邏輯玖雁,需要context(上下文對象)作為輸入。
    context是一個增強(qiáng)的Python字典盖腕,用于存儲回測或交易中的一些狀態(tài)與有效數(shù)據(jù)赫冬,它作為算法中的共享區(qū)域浓镜,在各個函數(shù)中均可訪問其內(nèi)容(使用context.鍵值的方式)。
  2. handle_data()
    按照自定義的周期劲厌,定時調(diào)用膛薛,一般在其中處理當(dāng)前周期中需要處理的訂單,context與data是函數(shù)的兩個參數(shù)脊僚。
    data是用于存放一些API方法的對象相叁。
  3. before_trading_start()
    每交易日開盤前調(diào)用的函數(shù),通常用于選定當(dāng)天待交易的股票辽幌,入?yún)⑴chandle_data一樣增淹,也為context與data兩個對象。

一個最基礎(chǔ)的算法框架如下:

def initialize(context):
    # 啟動后需要處理的一次性邏輯
def handle_data(context, data):
    # 定時執(zhí)行乌企,處理當(dāng)前周期中待處理訂單
def before_trading_start(context, data):
    # 開盤前執(zhí)行虑润,選定當(dāng)天待交易股票

整體框架基本可以模擬了我們平日里的交易操作,很容易理解加酵。對于框架有初步了解后拳喻,我們再繼續(xù)前進(jìn)一小步,如何獲購買一只股票呢猪腕?首先我們要獲取到這只股票

獲取證券信息

平臺提供了sid()函數(shù)冗澈,這個函數(shù)會根據(jù)輸入返回一只股票在平臺中的唯一ID,且是始終不變的陋葡。
比如你想獲取到蘋果公司的股票亚亲,只需要在代碼區(qū)域調(diào)用sid函數(shù),并在入?yún)⒗镙斎牍善焙喎QAAPL腐缤,編輯器就會智能地給出相應(yīng)提示捌归。


獲取代碼

獲取之后一般都會存放到context對象中,供之后的邏輯使用

def initialize(context):
    context.aapl = sid(24)
def handle_data(context, data):
    print context.aapl

下單

下單平臺提供了幾種不同的函數(shù)岭粤,這個點(diǎn)后續(xù)再展開詳述惜索,這篇文章我們以order_target_percent()這個為例進(jìn)行說明,order_target_percent函數(shù)需要兩個參數(shù)剃浇,sid(證券ID)與target_percent(投資比例巾兆,分母為可用頭寸)
**注:
可用頭寸=現(xiàn)金賬戶+敞口頭寸(open position)
敞口頭寸應(yīng)該為當(dāng)日買賣差價
**
如果用可用頭寸的50%去做多蘋果,代碼如下

order_target_percent(sid(24), 0.50)

而如果用可用頭寸的50%去做空偿渡,代碼如下

order_target_percent(sid(24), -0.50)

獲取證券信息

在下單前臼寄,策略可能需要根據(jù)歷史及當(dāng)前該證券的信息進(jìn)行分析,data對象提供了幾個快捷的函數(shù)供使用溜宽。

  1. data.current() 獲取當(dāng)前信息
    需要兩個參數(shù)吉拳,第一個參數(shù)為證券sid或一個證券sid列表,第二個參數(shù)為你需要的信息字段适揉,目前支持的有價格(price)留攒、開盤價(open)煤惩、收盤價(close)、最高價(high)炼邀、最低價(low)與交易量(volume)魄揉。
    例如:
data.current(sid(24), 'price') #獲取蘋果的當(dāng)前價格
data.current([sid(24), sid(46631)], 'price') 獲取蘋果與谷歌的當(dāng)前股價
data.current([sid(24), sid(46631)], ['low', 'high'])獲取蘋果與谷歌截止當(dāng)前的最高最低價
  1. data.can_trade() 該證券能否交易
    需要傳入證券sid或證券sid列表
  2. data.history() 獲取歷史信息
    在current參數(shù)的基礎(chǔ)上增加了回看窗口大小(lookback window length)及回看頻率(lookback frequency)的參數(shù)
hist = data.history(sid(24), 'price', 10, '1d')#獲取蘋果過去十天的價格,頻率為每天
mean_price = hist.mean()
#注:獲取歷史價格的時候拭宁,會先返回當(dāng)前的價格洛退,及前9天的日中收盤價,所以如果你希望獲取前十天的均價杰标,先取11天兵怯,然后丟棄掉最新的一條。
data.history(sid(8554), 'price', 11, '1d')[:-1].mean()

注: data.current()與data.history()返回的均為pandas的DataFrame結(jié)構(gòu)腔剂,pandas這個python科學(xué)庫后續(xù)會專門一系列說明

自定義調(diào)度

可以根據(jù)自己需要的周期媒区,靈活地定義自己需要的定時處理邏輯函數(shù),參數(shù)中包含自定義函數(shù)名掸犬、日期規(guī)則與實(shí)踐規(guī)則袜漩,

#在每周第一天開盤后一小時,已目前可用的10%買入蘋果股票湾碎。
def initialize(context):
    context.aapl = sid(24)
    schedule_function(func=open_positions, 
    data_rules=date_rules.week_start(), 
    time_rules=time_rules.market_open(hours=1)

def open_positions(context, data):
    order_target_percent(context.aapl, 0.10)

查詢當(dāng)前持倉

Quantopian在context中內(nèi)置了portfolio對象宙攻,持倉存儲在context.portfolio.positions中,positions可以看做sid為鍵介褥,Postion對象為值的一個字典粘优。我們可以使用for...in語法進(jìn)行循環(huán)處理:

#清盤所有持倉
for security in context.portfolio.positions:
  order_target_percent(security, 0)

繪制變量

平臺提供了record()方法幫助你將自己關(guān)注的變量繪制成時間序列圖,可以方便的監(jiān)控關(guān)心的變量呻顽。

def initialize(context):
    context.aapl = sid(24)
    schedule_function(record_vars, date_rules.every_day(), time_rules.market_close())

def record_vars(context, data):
    long_count = 0
    short_count = 0
    for position in context.portfolio.positions.itervalues():
        if position.amount > 0:
            long_count += 1
        if position.amount < 0:
            short_count += 1
    # 繪制圖表
    record(num_long=long_count, num_short=short_count)

重新編譯算法后,可直觀地展現(xiàn)每日收盤空頭/多頭的時間序列圖丹墨。


繪制

滑點(diǎn)與傭金

滑點(diǎn)與傭金都屬于交易成本的范疇廊遍,對于算法的實(shí)際表現(xiàn)影響很大

  1. 滑點(diǎn)
    滑點(diǎn)表示由于下單(尤其是大單)對于股價潛在的影響,會導(dǎo)致實(shí)際成交比預(yù)期差的情況贩挣,平臺中集成了多種滑點(diǎn)的策略喉前,下面為默認(rèn)的策略:
# 假設(shè)過去幾分鐘內(nèi)交易量為1000時,限制每次只能下1000*0.025=25的單王财,系統(tǒng)會根據(jù)這個值進(jìn)行拆單
set_slippage(slippage.VolumeShareSlippage(volume_limit=0.025, price_impact=0.1))
  1. 傭金
    可以根據(jù)真實(shí)經(jīng)紀(jì)商的情況設(shè)置傭金費(fèi)率及最小費(fèi)用卵迂。
set_commission(commission.PerShare(cost=0.0075, min_trade_cost=1))

訂單管理

因?yàn)橛唵位径疾皇羌纯坛山坏模耶?dāng)前未成交訂單對于后續(xù)的策略執(zhí)行也有很大的指導(dǎo)意義绒净,所以訂單管理的功能也是至關(guān)重要的见咒。
get_open_orders()函數(shù)幫助我們獲取當(dāng)前已下但尚未成交的訂單

 open_orders = get_open_orders()
 if context.xtl not in open_orders and data.can_trade(context.xtl):
        order_target_percent(context.xtl, 1.0)

動手均值回歸策略

好了,把之前所有的內(nèi)容整合起來挂疆,我們很容易就能實(shí)現(xiàn)一個簡單的均值回歸策略改览。均值回歸策略可以簡單的理解為短期的均值會有一定波動下翎,但隨時間一定會逐步與長期均值趨同。
我們就來實(shí)現(xiàn)這樣一個策略:
如果一個股票10天移動平均高于了其30天移動平均值宝当,我們則認(rèn)為股價一定會下跌视事,反之亦然。

def initialize(context):
    #初始化證券池
    context.security_list = [sid(5061), sid(7792), sid(1941), sid(24556), sid(1746)]

    # 自定義調(diào)度:每周第一交易日開盤時重新計算并執(zhí)行組合重新配置
    schedule_function(rebalance,
                      date_rules.week_start(days_offset=0),
                      time_rules.market_open())

def compute_weights(context, data):
    #計算10日與30日均值
    hist = data.history(context.security_list, 'price', 30, '1d')
    prices_10 = hist[-10:]
    prices_30 = hist
    sma_10 = prices_10.mean()
    sma_30 = prices_30.mean()
    # 加權(quán)計算
    raw_weights = (sma_30 - sma_10) / sma_30
    normalized_weights = raw_weights / raw_weights.abs().sum()
    return normalized_weights

def rebalance(context, data):
    # 重置權(quán)重
    weights = compute_weights(context, data)
    # 組合重新分配
    for security in context.security_list:
        if data.can_trade(security):
            order_target_percent(security, weights[security])

這一篇到這里就結(jié)束了庆揩,是不是覺得很容易上手呢俐东?建議大家去官方教程里克隆策略,自己上手跑一跑订晌,對于量化交易會更有體會虏辫。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市腾仅,隨后出現(xiàn)的幾起案子乒裆,更是在濱河造成了極大的恐慌,老刑警劉巖推励,帶你破解...
    沈念sama閱讀 216,544評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件鹤耍,死亡現(xiàn)場離奇詭異,居然都是意外死亡验辞,警方通過查閱死者的電腦和手機(jī)稿黄,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,430評論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來跌造,“玉大人杆怕,你說我怎么就攤上這事】翘埃” “怎么了陵珍?”我有些...
    開封第一講書人閱讀 162,764評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長违施。 經(jīng)常有香客問我互纯,道長,這世上最難降的妖魔是什么磕蒲? 我笑而不...
    開封第一講書人閱讀 58,193評論 1 292
  • 正文 為了忘掉前任留潦,我火速辦了婚禮,結(jié)果婚禮上辣往,老公的妹妹穿的比我還像新娘兔院。我一直安慰自己,他們只是感情好站削,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,216評論 6 388
  • 文/花漫 我一把揭開白布坊萝。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪屹堰。 梳的紋絲不亂的頭發(fā)上肛冶,一...
    開封第一講書人閱讀 51,182評論 1 299
  • 那天,我揣著相機(jī)與錄音扯键,去河邊找鬼睦袖。 笑死,一個胖子當(dāng)著我的面吹牛荣刑,可吹牛的內(nèi)容都是我干的馅笙。 我是一名探鬼主播,決...
    沈念sama閱讀 40,063評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼董习,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了爱只?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,917評論 0 274
  • 序言:老撾萬榮一對情侶失蹤恬试,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后训柴,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,329評論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡幻馁,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,543評論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了仗嗦。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片膘滨。...
    茶點(diǎn)故事閱讀 39,722評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡吏祸,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出钩蚊,到底是詐尸還是另有隱情,我是刑警寧澤蹈矮,帶...
    沈念sama閱讀 35,425評論 5 343
  • 正文 年R本政府宣布砰逻,位于F島的核電站,受9級特大地震影響泛鸟,放射性物質(zhì)發(fā)生泄漏蝠咆。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,019評論 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望刚操。 院中可真熱鬧闸翅,春花似錦、人聲如沸菊霜。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,671評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽鉴逞。三九已至记某,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間构捡,已是汗流浹背液南。 一陣腳步聲響...
    開封第一講書人閱讀 32,825評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留勾徽,地道東北人滑凉。 一個月前我還...
    沈念sama閱讀 47,729評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像喘帚,于是被迫代替她去往敵國和親畅姊。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,614評論 2 353

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