在前一篇測試中, 我們撰寫了一個自訂模組 twstock_data.py, 其中的 download() 函式模仿 yfinance.download() 透過 twstock 模組取得最近 45 天的台股量價資料, 回傳格式也是仿新版 yfinance 的雙層欄位的 DataFrame, 參考 :
本篇則是要擴充 twstock_data.py 模組, 添加如下實用函式 :
- available_range(stock) : 傳回指定股票的可用日期範圍
- available_ranges(stocks) : 傳回多支股票 (串列) 的可用日期範圍 (串列)
- latest_close(stock) : 指定股票的最新收盤價
程式碼修改如下 :
# twstock_data.py
import twstock
import pandas as pd
from datetime import datetime
def download(stocks, start=None, end=None):
"""
模擬 yfinance.download(),使用 twstock 抓取台股資料
stocks: '0050.tw' 或 ['0050.tw','0056.tw'], '0050' 或 ['0050','0056']
start, end: 'YYYY-MM-DD' 字串
回傳 DataFrame,欄位結構完全模擬 yfinance (MultiIndex: Price, Ticker)
"""
if isinstance(stocks, str): # 判斷標的是單支或多支股票
stocks=[stocks] # 若是單支則將其放入串列
all_data=[] # 儲存所有價量資料的串列
for stock_code in stocks: # 走訪所有標的
code=stock_code.replace('.tw', '').replace('.TW','') # 去除 tw/TW
stock=twstock.Stock(code) # 建立 Stock 物件
# 收集資料
data=[] # 儲存打包後的股票價量資料的串列
for date, o, h, l, c, v in zip(stock.date, stock.open, stock.high, stock.low, stock.close, stock.capacity): # 打包成 tuple 後存入串列, 最後轉成 DataFrame
data.append((date, o, h, l, c, v, c)) # 最後一個 c 當 Adj Close
df=pd.DataFrame(data, columns=['Date','Open','High','Low','Close','Volume','Adj Close'])
df.set_index('Date', inplace=True) # 設定索引
# 篩選日期
if start: # 有傳入起始日期
start_date=datetime.strptime(start, '%Y-%m-%d')
df=df[df.index >= start_date]
if end: # 有傳入結束日期
end_date=datetime.strptime(end, '%Y-%m-%d')
df=df[df.index <= end_date]
# 建立 MultiIndex 欄位 (Price, Ticker)
df.columns=pd.MultiIndex.from_product([df.columns, [stock_code.upper()]], names=["Price", "Ticker"])
all_data.append(df)
# 合併多檔股票
result=pd.concat(all_data, axis=1).sort_index(axis=1, level=0)
return result
def available_range(stock):
"""回傳單支股票可用日期範圍"""
code=stock.replace('.tw', '').replace('.TW','')
st=twstock.Stock(code)
return st.date[0], st.date[-1]
def available_ranges(stocks):
"""回傳多支股票的可用日期範圍 dict"""
if isinstance(stocks, str):
code=stocks.replace('.tw', '').replace('.TW','')
stocks=[code]
result={}
for s in stocks:
code=s.replace('.tw', '').replace('.TW','')
st=twstock.Stock(code)
result[s]=(st.date[0], st.date[-1])
return result
def latest_close(stock):
"""回傳最新收盤價"""
code=stock.replace('.tw', '').replace('.TW','')
st=twstock.Stock(code)
return st.price[-1]
在互動環境測試如下 :
>>> import twstock_data as td
呼叫 available_range() 傳入單一股票會傳回起訖日期的 datetime 物件 tuple :
>>> td.available_range('0050.tw')
(datetime.datetime(2025, 8, 15, 0, 0), datetime.datetime(2025, 9, 26, 0, 0))
呼叫 available_ranges() 傳入多支股票串列會傳回各標的之起訖日期字典 :
>>> td.available_ranges(['0050.tw', '2330.tw'])
{'0050.tw': (datetime.datetime(2025, 8, 15, 0, 0), datetime.datetime(2025, 9, 26, 0, 0)), '2330.tw': (datetime.datetime(2025, 8, 15, 0, 0), datetime.datetime(2025, 9, 26, 0, 0))}
呼叫 latest_close() 傳入單一股票會傳回最近之收盤價 :
>>> td.latest_close('0050.tw')
57.25
依據上面 available_range() 的起訖日期下載價量資料 :
>>> df=td.download('0050.tw', start='2025-08-15', end='2025-09-26')
>>> df
Price Adj Close Close High Low Open Volume
Ticker 0050.TW 0050.TW 0050.TW 0050.TW 0050.TW 0050.TW
Date
2025-08-15 53.15 53.15 53.30 52.80 53.15 55175623
2025-08-18 53.30 53.30 53.35 52.80 52.95 48004775
2025-08-19 53.20 53.20 53.30 53.05 53.30 31232902
2025-08-20 51.70 51.70 52.60 51.50 52.55 241376498
2025-08-21 52.00 52.00 52.10 51.75 51.75 76525276
2025-08-22 51.75 51.75 52.10 51.65 52.05 47853232
2025-08-25 52.70 52.70 52.95 52.35 52.45 64451775
2025-08-26 52.75 52.75 52.85 52.30 52.55 42402036
2025-08-27 53.00 53.00 53.15 52.90 53.00 91463591
2025-08-28 52.50 52.50 52.90 52.50 52.80 61856984
2025-08-29 52.50 52.50 52.95 52.50 52.80 37614042
2025-09-01 52.00 52.00 52.45 51.75 52.15 82748402
2025-09-02 52.00 52.00 52.50 51.95 52.30 34866736
2025-09-03 51.95 51.95 52.20 51.75 51.90 41247523
2025-09-04 52.30 52.30 52.70 52.25 52.55 38611419
2025-09-05 52.85 52.85 52.90 52.65 52.70 38976905
2025-09-08 53.35 53.35 53.55 53.25 53.40 61781569
2025-09-09 53.90 53.90 53.95 53.50 53.55 57948913
2025-09-10 54.95 54.95 55.00 54.40 54.40 75585424
2025-09-11 55.45 55.45 55.90 55.25 55.55 87937880
2025-09-12 56.00 56.00 56.00 55.70 55.75 59101728
2025-09-15 56.00 56.00 56.05 55.80 56.00 56031630
2025-09-16 56.75 56.75 56.85 56.15 56.15 65388179
2025-09-17 56.35 56.35 56.60 56.25 56.60 70590054
2025-09-18 56.95 56.95 56.95 56.25 56.50 45899106
2025-09-19 57.00 57.00 57.10 56.60 57.00 74098514
2025-09-22 57.40 57.40 57.40 56.75 57.00 59170020
2025-09-23 58.45 58.45 58.60 57.85 57.85 92241987
2025-09-24 58.40 58.40 58.95 58.10 58.70 95128957
2025-09-25 58.20 58.20 58.40 58.00 58.35 59962136
2025-09-26 57.25 57.25 57.90 56.85 57.90 170962034
>>>
可見最近一個交易日 9/26 的收盤價確實是 57.25.
沒有留言 :
張貼留言