利用文字雲快速瀏覽股市狀況,輕鬆節省下班時間!

看到別人在玩文字雲,手癢也想來玩看看
於是決定寫個程式幫我製作每天台股上市股票的文字雲
讓我可以一眼就看到當前股市狀況
文字雲
本篇都用 Python 來撰寫,因此我們需要先安裝文字雲的套件 word_cloud。
pip install wordcloud
Wordcloud 可以傳入一段文字,然後藉由計算頻率,然後將頻率越高的字的字體放大,讓人一眼就注意到重點。
抓取股票資料
我們這次的目標是要依照股票的漲跌比例來顯示文字雲,也就是說,漲跌幅越高的股票就越明顯。
首先,我們要先去得到當日所有股票上市的資訊,這裡我們使用這支 API 來得到資料
API 回傳的資料是 json 檔案,裡面欄位分別為:
- stat: 查詢結果狀態
- date: 資料日期
- title: 資料標題
- fields: 資料各欄位名稱
- data: 各股票資訊
- 證券代號
- 證券名稱
- 成交股數
- 成交金額
- 開盤價
- 最高價
- 最低價
- 收盤價
- 漲跌價
- 成交筆數
使用 python 取得股票資料,由於我們只需要 data 欄位的資料,因此先轉成 json 格式之後,取得 data 欄位:
import requests
import json
r = requests.get('https://www.twse.com.tw/exchangeReport/STOCK_DAY_ALL?response=json')
data = json.loads(r.text)
stock_dict = data["data"]
計算漲跌幅
接著我們擷取各個股票的漲跌幅資訊,但 API 回傳的資料只有當日的漲跌值,並沒有我們要的漲跌比例,因此我們要自己計算。
$$ 漲跌比例 = 漲跌值 / 昨日收盤 $$ $$ 昨日收盤 = 今日收盤 - 漲跌值 $$
def changeToRatio(s):
try:
close = float(s[7]) # 7: 今日收盤
change = float(s[8]) # 8: 今日漲跌
pre_close = close-change
return change/pre_close
except:
return 0
stock_change_ratio_dict = {} # 每支股票的漲跌比例
stock_change_ratio_abs_dict = {} # 每支股票的漲跌比例取絕對值
for s in stock_dict:
name = s[1] # 1: 股要名稱
stock_change_ratio_dict[name] = changeToRatio(s)
stock_change_ratio_abs_dict[name] = abs(changeToRatio(s))
由上方的公式我們就可以計算漲跌比例了,並且製作 dictionary 來儲存每支股票的漲跌幅。
然而,因為股票的最小單位的緣故,且不同價格區間有著不同的最小單位,這造成了明明股票漲停了,但是計算漲跌比例卻不到漲停板的 10 %。
價格區間 | 最小單位 |
---|---|
0.01 ~ 10 | 0.01 |
10 ~ 50 | 0.05 |
50 ~ 100 | 0.1 |
100 ~ 500 | 0.5 |
500 ~ 1000 | 1 |
> 1000 | 5 |
因此,我們需要針對這部分做調整,我們先用 binary search 找出股票屬於哪個區間,然後找到對應的股票最小單位,並計算出在不超過漲跌停板的 10 % 區間內,最高和最低的價格,其中所有數值都用整數運算,俗話說:「算錢用浮點 遲早被人扁」。
import bisect
import math
def changeToRatio(s):
try:
close = int(float(s[7])*100) # 7: ClosingPrice
change = int(float(s[8])*100) # 8: Change
pre_close = close-change
if pre_close == 0 or close == 0: return 0
section = [1000, 5000, 10000, 50000, 100000]
price_unit = [1, 5, 10, 50, 100, 500]
max_change = math.floor(pre_close*0.1)
if change >= 0:
max_price = pre_close + max_change
step = price_unit[bisect.bisect_right(section, max_price)]
max_change_scaled = max_change//step*step
return math.floor(change/(close-change)*100) if change != max_change_scaled else 10
else:
min_price = pre_close - max_change
step = price_unit[bisect.bisect_right(section, min_price)]
max_change_scaled = -max_change//step*step
return math.ceil(change/(close-change)*100) if change != max_change_scaled else -10
except:
return 0
stock_change_ratio_dict = {} # 每支股票的漲跌比例
stock_change_ratio_abs_dict = {} # 每支股票的漲跌比例取絕對值
for s in stock_dict:
name = s[1] # 1: 股要名稱
stock_change_ratio_dict[name] = changeToRatio(s)
stock_change_ratio_abs_dict[name] = abs(changeToRatio(s))
製作文字雲
最後資料整理完了,我們可以開始製作文字雲了。
由於我們是印出中文字體,因此要自備支援中文的字體,這裡選用的是 Google 提供的字體 Noto Sans Traditional Chinese,大家可以下載下來做使用。
另外我也調整了圖片大小、背景大小和字體大小,如果想要有垂直的自體的話,可以調整 prefer_horizontal
的比例,1.0 代表都是要水平的字。
最後我們可以將圖片輸出成 png 保存下來。
from wordcloud import WordCloud
wc = WordCloud(color_func=color_func, font_path='NotoSansTC-Light.otf', background_color="#080808",
scale=4, margin=3, min_font_size=4, max_font_size=45, prefer_horizontal=1.0)
wc = wc.generate_from_frequencies(stock_change_ratio_abs_dict)
wc.to_image().save('wordcloud.png')
成品:
最後可以依照漲跌幅列出所有股票的資訊:
stock_change_ratio_dict_sort = sorted(stock_change_ratio_dict.items(), key=lambda x: x[1], reverse=True)
for item in stock_change_ratio_dict_sort:
print(f"{item[0]}: {item[1]}%")
Reference
如果你覺得這篇文章有用 可以考慮贊助飲料給大貓咪