iT邦幫忙

2021 iThome 鐵人賽

DAY 7
0
永豐金融APIs

深入解析 Shioaji API系列 第 7

Day 07 - Ticks

本篇重點

  • Ticks 介紹及屬性說明
  • 使用 Pandas 將 Ticks 資料轉換為 DataFrame

Ticks 介紹及屬性說明

官方說明文件:https://sinotrade.github.io/tutor/market_data/historical/#ticks-data
所謂的tick,就是看盤軟體中的成交明細資料,而證交所也從2020年3月23日實施逐筆交易,不再是以前盤中每五秒才撮合一次。
Imgur
也因為成交明細的資料會較多,所以Tick資料一次只能抓一個交易日的資料。
api.ticks參數說明

api.ticks(
        contract: BaseContract, #傳入所要抓取ticks資料的Contract
        date: str = dt.date.today().strftime("%Y-%m-%d"), #交易日期,預設為程式執行當下的日期
        query_type: TicksQueryType = TicksQueryType.AllDay, #預設為抓當天一整天的資料
        time_start: typing.Union[str, dt.time] = None, #資料開始時間,預設為None,即不指定開始時間
        time_end: typing.Union[str, dt.time] = None, #資料結束時間,預設為None,即不指定結束時間
        last_cnt: int = 0, #僅回傳最後X筆資料,預設為0,即回傳所有的資料
        timeout: int = 30000, #timeout時間,預設為30000ms
        cb: typing.Callable[[Ticks], None] = None
    )

使用範例如下:

# TicksQueryType.AllDay 抓交易日期全天tick資料
ticks = api.ticks(
    contract=api.Contracts.Stocks["2330"], #指定要抓ticks資料的Contract
    date="2021-09-17", #交易日期
)

若只要抓取交易日期中,特定時間區間的資料,可以在參數中指定開始時間及結束時間,範例如下:

# TicksQueryType.RangeTime 抓交易日期,特定時段tick資料
ticks = api.ticks(
    contract=api.Contracts.Stocks["2330"], #指定要抓ticks資料的Contract
    date="2021-09-17", #交易日期
    query_type=sj.constant.TicksQueryType.RangeTime, #指定QueryType為RangeTime
    time_start="09:10:00", #開始時間
    time_end="09:20:00" #結束時間
)

若只要抓取最後5筆tick資料,範例如下:

# TicksQueryType.LastCount 抓交易日期最後X筆tick資料
last_5_ticks = api.ticks(
    contract=api.Contracts.Stocks["2330"], #指定要抓ticks資料的Contract
    date="2021-09-17", #交易日期
    query_type=sj.constant.TicksQueryType.LastCount, #指定QueryType為LastCount
    last_cnt=5 #指定要抓最後5筆tick資料
)

TicksQueryType,只有AllDay、RangeTime及LastCount這三種,使用方式就如同上面的這三個範例,但請注意這三種方式無法混用,因為api.ticks主要是依照query_type這個參數,去決定要抓哪些資料。
例如:

ticks = api.ticks(
    contract=api.Contracts.Stocks["2330"], #指定要抓ticks資料的Contract
    date="2021-09-17", #交易日期
    query_type=sj.constant.TicksQueryType.RangeTime, #指定QueryType為RangeTime
    time_start="09:10:00", #開始時間
    time_end="09:20:00", #結束時間
    last_cnt=5 #指定要抓最後5筆tick資料,但指定TicksQueryType.RangeTime會忽略此參數
)

因為在query_type這個參數,已經指定QueryType為RangeTime,雖然有指定last_cnt=5,但回傳的資料其實跟第二個範例TicksQueryType.RangeTime一樣。

所回傳的資料為shioaji.data.Ticks物件,屬性說明如下:

屬性 說明
ts [1631889000000000000] 時間戳
close [600.0] 收盤價,即成交價格
volume [57] 成交量
bid_price [600.0] 委買價(買進)
bid_volume [1107] 委買量
ask_price [601.0] 委賣價(賣出)
ask_volume [3] 委賣量

跟之前抓到的資料不同的地方在於,所回傳的資料是一個shioaji.data.Ticks物件而非List,也就是把所有的tick資料存在一個物件中,而物件中的屬性內容為List,用來放每一個tick的資料。
若你用上面的範例並執行print(last_5_ticks),會看到以下的資料內容。

Ticks(
ts=[1631885096148332000, 1631885098755243000, 1631885098967648000, 1631885400000000000, 1631889000000000000],
close=[609.0, 609.0, 608.0, 600.0, 600.0],
volume=[1, 1, 1, 22082, 57],
bid_price=[608.0, 608.0, 608.0, 600.0, 600.0],
bid_volume=[298, 298, 297, 1107, 1107],
ask_price=[609.0, 609.0, 609.0, 601.0, 601.0],
ask_volume=[164, 164, 162, 3, 3])

使用 Pandas 將 Ticks 資料轉換為 DataFrame

使用api.ticks取得資料,若未經過處理,在閱讀上較為困難,此時可以先把tick資料轉換為DataFram。但因為資料內容格式與之前的格式不同,所以在轉換前要先將物件內容先轉換為Dict
程式範例如下:

df = pd.DataFrame({**last_5_ticks}) #先將Ticks物件轉換為Dict,再傳入DataFrame做轉換
df.ts = pd.to_datetime(df.ts) #將原本的ts欄位中的資料,轉換為DateTime格式並回存
print(df) #將DataFrame的資料輸出至console中

在執行print(df)後,原本的資料內容,已變成下列比較方便閱讀的格式

   close  bid_price  ask_volume  ask_price                         ts  bid_volume  volume
0  609.0      608.0         164      609.0 2021-09-17 13:24:56.148332         298       1
1  609.0      608.0         164      609.0 2021-09-17 13:24:58.755243         298       1
2  608.0      608.0         162      609.0 2021-09-17 13:24:58.967648         297       1
3  600.0      600.0           3      601.0 2021-09-17 13:30:00.000000        1107   22082
4  600.0      600.0           3      601.0 2021-09-17 14:30:00.000000        1107      57

上一篇
Day 06 - Snapshots
下一篇
Day 08 - Kbars
系列文
深入解析 Shioaji API30

尚未有邦友留言

立即登入留言