量化交易30天
本系列文章是紀錄一位量化交易新手的學習過程,除了基礎的Python語法不說明,其他金融相關的東西都會一步步地說明,希望讓更多想學習量化交易但是沒有學過相關金融知識的朋友們,透過這系列的文章,能夠對量化交易略知一二,也歡迎量化交易的高手們多多交流。
學會了券商的報價及下單功能之後呢,這篇想來測試一下,假設我今天有一個策略,那我要怎麼將券商即時報價資料,導入寫好的策略裡面,然後產生訊號,一直到完成下單。
做回測的時候,通常會使用一包歷史資料集,但是實際要下單的時候,程式寫起來會非常不同,特別是如果想用分k資料做交易,那從接收到報價,資料運算,一直到觸發策略到下單,這個運算時間必須要越短越好,才能夠符合策略邏輯,所以不會像之前回測的時候存一個很大的dataframe,然後再加減乘除,通常只存必要的資料就好。
之前Day6的時候有寫到RSI指標,這次就要使用RSI來做交易,只是這次用的價格是每一分鐘的收盤價。這次的策略會用RSI12小於30買進,大於70賣出的這個簡單的方式交易,參數的部份都可以調整,這邊只是做一個範例。
這邊為了讓報價跳得快一些,因此選擇近月台股指數期貨做為標的,所以合約的部份如下:
contracts = [api.Contracts.Futures['TXFJ0']]
跟之前RSI計算公式比起來相對簡單,因為我們只需要運算最近12分鐘的RSI值就好。
def RSI(close, period=12):
# 整理資料
Close = close[-13:]
Chg = Close - Close.shift(1)
Chg_pos = pd.Series(index=Chg.index, data=Chg[Chg>0])
Chg_pos = Chg_pos.fillna(0)
Chg_neg = pd.Series(index=Chg.index, data=-Chg[Chg<0])
Chg_neg = Chg_neg.fillna(0)
# 計算平均漲跌幅度
up_mean = np.mean(Chg_pos.values[-12:])
down_mean = np.mean(Chg_neg.values[-12:])
# 計算 RSI
if (up_mean + down_mean > 0):
rsi = 100 * up_mean / ( up_mean + down_mean )
else:
rsi = -1
return rsi
之前的RSI用的資料頻率是天,之前RSI12就代表用過去12天的收盤價來計算,那現在要用分鐘為計算頻率,所以RSI12就是用過去12分鐘的收盤價來計算。
那就產生一個問題:根本還沒收盤怎麼會有收盤價?其實這個收盤不是真正的收盤,它會是前一分鐘內最後一筆交易的成交價。舉例來說:假設台指期早上9:01~9:02共成交五筆,價格分別是12400、12401、12402、12401、12402,那9:02分抓到的最後一筆交易價格就是12402。
從Shioaji提供的報價功能,有兩種方法可以取得每一分鐘內最後一筆交易價格:
兩種方法比較起來,我覺得snapshot會比較方便,因為我只需要每分鐘呼叫一次就好,不用去收每一筆資料。
下面程式碼中,假設碰到RSI12的觸發點(30、70)就執行買進賣出,固定帳上只能有庫存一個單位(一口),因為這次是先測試,就只印出買賣時間及價位,實際上要下單的話,要將print的部分改成下單的程式碼。
In
# 初始化 close series
import pandas as pd
import numpy as np
import time
from datetime import datetime
minute_close = pd.Series()
stock = 0
# 紀錄前12個close
for i in range(0,12):
snapshots = api.snapshots(contracts)
minute_close = minute_close.append(pd.Series(
[snapshots[0].close],
index=[pd.to_datetime(snapshots[0].ts, unit='ns')]
))
time.sleep(60)
# 開始算RSI
for i in range(0,700):
# 抓snapshot
snapshots = api.snapshots(contracts)
# 存到分k收盤價的series
minute_close = minute_close.append(pd.Series(
[snapshots[0].close],
index=[pd.to_datetime(snapshots[0].ts, unit='ns')]
))
# 計算rsi
rsi = RSI(minute_close)
# 觸發訊號判斷
if rsi <= 30 and rsi >= 0 and stock == 0:
now = datetime.now()
current_time = now.strftime("%H:%M:%S")
print("Current Time =", current_time, "BUY AT ", snapshots[0].close)
stock += 1
if rsi >= 70 and stock == 1:
now = datetime.now()
current_time = now.strftime("%H:%M:%S")
print("Current Time =", current_time, "SELL AT ", snapshots[0].close)
stock -= 1
time.sleep(60)
Out
Current Time = 17:44:38 BUY AT 12419.0
Current Time = 17:55:39 SELL AT 12425.0
Current Time = 18:30:41 BUY AT 12443.0
Current Time = 18:56:43 SELL AT 12452.0
Current Time = 19:07:44 BUY AT 12448.0
Current Time = 19:29:46 SELL AT 12452.0
Current Time = 19:42:47 BUY AT 12450.0
Current Time = 20:05:49 SELL AT 12460.0
Current Time = 21:03:53 BUY AT 12470.0
Current Time = 21:23:54 SELL AT 12479.0
Current Time = 21:45:56 BUY AT 12447.0
Current Time = 22:19:59 SELL AT 12458.0
Current Time = 22:38:01 BUY AT 12441.0
Current Time = 23:04:03 SELL AT 12439.0
Current Time = 23:22:04 BUY AT 12435.0
Current Time = 23:40:06 SELL AT 12455.0
Current Time = 00:05:08 BUY AT 12440.0
Current Time = 00:34:10 SELL AT 12442.0
Current Time = 01:02:13 BUY AT 12443.0
Current Time = 01:23:14 SELL AT 12449.0
Current Time = 02:03:18 BUY AT 12456.0
Current Time = 02:15:19 SELL AT 12465.0
Current Time = 03:03:23 BUY AT 12457.0
Current Time = 04:01:27 SELL AT 12463.0
Current Time = 04:31:30 BUY AT 12456.0
Current Time = 04:43:31 SELL AT 12465.0
Current Time = 04:54:32 BUY AT 12457.0
Current Time = 04:59:32 SELL AT 12474.0
上面這邊大概是從下午5點多開始跑,跑到早上5點,買賣來回14次,總獲利點數116點,這次範例用一個簡單易懂的策略去跑完這個流程,學習接收報價到下單的程式碼撰寫。
本篇總結
這篇從接收報價、觸發策略,一直到執行買賣,算是把shioaji這個API實際運用在交易了,下一篇要跳到另外一個主題,討論投資組合的部份,因為剛開始規劃量化交易的內容時,有把統計學、金融理論以及投資組合也涵蓋在內,也是可以用Python來做分析,請繼續收看囉。
P.S.
如果大家對於量化交易有興趣的話,我自己有上過以下這門課,課程內容從串接股市資料API、儲存至資料庫、將自己的策略轉化成程式碼、自動下單,並且可以把整個流程自動化,每天早上執行一次,一整天就不用看盤了,覺得是蠻實戰的,可以參考看看。
筆者 Sean
奈米戶投資人 / Python愛用者
喜歡用Python玩轉金融數據,從個股基本面、技術面、籌碼面相關資料,一直到總體經濟數據,都是平常接觸到的素材;對於投資,除了研究歷史數據,也喜歡瞭解市場上大家在玩些什麼。