透過永豐證券 API 找出短線交易潛力股
BY PJ.
-2025 年 4 月 30 日
(最後更新於: 2025 年 5 月 10 日)
對於短期交易者來說,股票的成交量
和股價波動
是最重要的參考指標。透過程式,我們可以快速、方便地自動統整
要觀察的股票清單。本文將介紹如何使用永豐證券的 API,抓取近期成交量大且股價波動高的股票,並篩選出適合短線交易的股票。
永豐API(Shioaji)說明
- 開戶並申請
首先需要在永豐證券開戶並申請 API,流程可參考: API開戶及申請流程
完成申請後,會獲得 api_key
和 secret_key
。
- API 登入
使用 API管理 取得的 api_key
和 secret_key
,登入Shioaji。
import shioaji as sj
api = sj.Shioaji(simulation=True) # 使用模擬環境即可
api.login(
api_key="your_api_key",
secret_key="your_secret_key",
receive_window=60000
)
* 取得股價和成交量資料
假設我們要查詢某支股票(以 2330 為例)的 30 天股價和成交量資料,可以使用kbar函數
來抓取。
相關函數可參考:永豐Python API參考文件
import datetime
import pandas as pd
# 設定查詢的起始日和結束日
start_date = (datetime.datetime.now() - datetime.timedelta(days=30)).strftime('%Y-%m-%d')
end_date = datetime.datetime.now().strftime('%Y-%m-%d')
kbars = api.kbars(
contract=api.Contracts.Stocks['2330'],
start=start_date,
end=end_date,
)
df = pd.DataFrame({**kbars})
df.ts = pd.to_datetime(df.ts)
df['year'] = df['ts'].dt.year
df['month'] = df['ts'].dt.month
df['day'] = df['ts'].dt.day
print(df.head(5)) # 顯示前五筆資料
完整程式碼 - 篩選股票
我們會篩選出近期成交量大、股價波動大
的股票,並排除 ETF
,作為短線交易的觀察清單。以下是篩選股票的完整程式碼:
我們分別建立兩個 Python 檔案:main.py 和 history.py ,負責登入 API 和處理股票資料。
main.py
import shioaji as sj
import history
# 登入永豐證券 API
api = sj.Shioaji(simulation=True)
api.login(
api_key="your_api_key",
secret_key="your_secret_key",
receive_window=60000
)
# 執行篩選過程並將結果存為 Excel 檔案
hty = history.history_stock(api)
history_data = hty.return_df()
history_data.to_excel("stock.xlsx", index=False)
history.py
import pandas as pd
import datetime
import numpy as np
class history_stock:
def __init__(self, api):
self.api = api
# 篩選股票價格範圍
self.low_price = 100.5
self.high_price = 139
# 查詢開始日和結束日
search_days = 30
self.start_date = (datetime.datetime.now() - datetime.timedelta(days=search_days)).strftime('%Y-%m-%d')
self.end_date = datetime.datetime.now().strftime('%Y-%m-%d')
# 取得可當日沖銷的股票清單
self.total_stock()
# 計算各股開、高、收、低價及成交均量
self.update_data()
# 篩選符合條件的股票
self.condition()
def total_stock(self):
item_name = []
item_code = []
for item in self.api.Contracts.Stocks.TSE:
if item['day_trade'] == 'Yes': # 篩選可當日沖銷的股票
item_name.append(item['name'])
item_code.append(item['code'])
self.history_df = pd.DataFrame({'name': item_name, 'symbol': item_code})
self.history_df['avg_volume'] = ''
self.history_df['high'] = ''
self.history_df['low'] = ''
self.history_df['open'] = ''
self.history_df['close'] = ''
self.history_df['price_change'] = ''
def update_data(self):
for i in self.history_df.index:
avg_volume, High, Low, Open, Close = self.kbar(self.history_df['symbol'].iloc[i], self.start_date, self.end_date)
self.history_df['avg_volume'].iloc[i] = avg_volume
self.history_df['high'].iloc[i] = High
self.history_df['low'].iloc[i] = Low
self.history_df['open'].iloc[i] = Open
self.history_df['close'].iloc[i] = Close
if Low is None:
self.history_df['price_change'].iloc[i] = None
else:
self.history_df['price_change'].iloc[i] = (High - Low) / Low
return self.history_df
def kbar(self, symbol, start_date, end_date):
kbars = self.api.kbars(
contract=self.api.Contracts.Stocks[symbol],
start=start_date,
end=end_date,
)
df = pd.DataFrame({**kbars})
df.ts = pd.to_datetime(df.ts)
df['year'] = df['ts'].dt.year
df['month'] = df['ts'].dt.month
df['day'] = df['ts'].dt.day
if len(df) == 0:
return None, None, None, None, None
else:
High = df.groupby(['year', 'month', 'day']).max()['High'].iloc[-1] # 最近一日最高價
Low = df.groupby(['year', 'month', 'day']).min()['Low'].iloc[-1] # 最近一日最低價
df.sort_values(by=['year', 'month', 'day', 'ts'], ascending=[False, False, False, True], inplace=True)
Open = df['Open'].iloc[0]
df.sort_values(by=['year', 'month', 'day', 'ts'], ascending=[False, False, False, False], inplace=True)
Close = df['Close'].iloc[0]
df = df.groupby(['year', 'month', 'day'])[['Volume']].sum()
return (sum(df['Volume']) / len(df)), High, Low, Open, Close
def condition(self):
# 篩選成交量大於 1000 和股價變動幅度大於 2% 的股票
self.history_df = self.history_df.loc[np.logical_and(self.history_df.avg_volume >= 1000, self.history_df.price_change >= 0.02)]
self.history_df = self.history_df[self.history_df.symbol.astype(str).str.len() == 4] # 移除 ETF
# 篩選股價在設定範圍內的股票
price_series = self.history_df['close'].astype(float)
price_range = np.logical_and(price_series >= self.low_price, price_series <= self.high_price)
self.history_df = self.history_df[price_range]
# 按照成交量排序
self.history_df.sort_values(by="avg_volume", ascending=False, inplace=True)
def return_df(self):
return self.history_df
產生結果
你可以在每天 1:30 收盤後執行這段程式,來計算次日需要觀察的股票,篩選出的股票會保存在 stock.xlsx 中。
也可以根據自己的需求,調整股價範圍
、成交量
和股價變動幅度
等條件。
後續分析
下篇文章我將示範如何基於這份觀察清單,透過永豐 API 取得即時的 tick 資料,找出盤中出現內外盤大量成交
的股票,這是日內交易非常重要的指標。
#程式交易 #日內交易 #短線交易 #永豐證券 #Shioaji #股價波動 #成交量 #API交易 #股市策略 #股市分析 #量化交易 #台股