iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 20
1
AI & Data

量化交易30天系列 第 20

量化交易30天 Day20 - 串接券商API做交易(七) 接收即時報價到觸發策略訊號

  • 分享至 

  • xImage
  •  

量化交易30天
本系列文章是紀錄一位量化交易新手的學習過程,除了基礎的Python語法不說明,其他金融相關的東西都會一步步地說明,希望讓更多想學習量化交易但是沒有學過相關金融知識的朋友們,透過這系列的文章,能夠對量化交易略知一二,也歡迎量化交易的高手們多多交流。

學會了券商的報價及下單功能之後呢,這篇想來測試一下,假設我今天有一個策略,那我要怎麼將券商即時報價資料,導入寫好的策略裡面,然後產生訊號,一直到完成下單。

做回測的時候,通常會使用一包歷史資料集,但是實際要下單的時候,程式寫起來會非常不同,特別是如果想用分k資料做交易,那從接收到報價,資料運算,一直到觸發策略到下單,這個運算時間必須要越短越好,才能夠符合策略邏輯,所以不會像之前回測的時候存一個很大的dataframe,然後再加減乘除,通常只存必要的資料就好。

範例策略

之前Day6的時候有寫到RSI指標,這次就要使用RSI來做交易,只是這次用的價格是每一分鐘的收盤價。這次的策略會用RSI12小於30買進,大於70賣出的這個簡單的方式交易,參數的部份都可以調整,這邊只是做一個範例。

標的選擇

這邊為了讓報價跳得快一些,因此選擇近月台股指數期貨做為標的,所以合約的部份如下:

contracts = [api.Contracts.Futures['TXFJ0']]

RSI計算公式

跟之前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

Snapshot使用

之前的RSI用的資料頻率是天,之前RSI12就代表用過去12天的收盤價來計算,那現在要用分鐘為計算頻率,所以RSI12就是用過去12分鐘的收盤價來計算。

那就產生一個問題:根本還沒收盤怎麼會有收盤價?其實這個收盤不是真正的收盤,它會是前一分鐘內最後一筆交易的成交價。舉例來說:假設台指期早上9:01~9:02共成交五筆,價格分別是12400、12401、12402、12401、12402,那9:02分抓到的最後一筆交易價格就是12402。

從Shioaji提供的報價功能,有兩種方法可以取得每一分鐘內最後一筆交易價格:

  1. 訂閱tick數據:等於是每一筆tick資料都收,抓每分鐘最後一筆去紀錄交易價格即可。
  2. Snapshot:每分鐘去抓一次Snapshot,它會自動抓取最後一筆交易價格。

兩種方法比較起來,我覺得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玩轉金融數據,從個股基本面、技術面、籌碼面相關資料,一直到總體經濟數據,都是平常接觸到的素材;對於投資,除了研究歷史數據,也喜歡瞭解市場上大家在玩些什麼。


上一篇
量化交易30天 Day19 - 串接券商API做交易(六) 讀懂委託及成交回報訊息
下一篇
量化交易30天 Day21 - 投資組合概念(一) 報酬與風險
系列文
量化交易30天30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言