目錄

廣告 AD

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

看到別人在玩文字雲,手癢也想來玩看看

於是決定寫個程式幫我製作每天台股上市股票的文字雲

讓我可以一眼就看到當前股市狀況

廣告 AD

本篇都用 Python 來撰寫,因此我們需要先安裝文字雲的套件 word_cloud

bash

pip install wordcloud

Wordcloud 可以傳入一段文字,然後藉由計算頻率,然後將頻率越高的字的字體放大,讓人一眼就注意到重點。

我們這次的目標是要依照股票的漲跌比例來顯示文字雲,也就是說,漲跌幅越高的股票就越明顯。

首先,我們要先去得到當日所有股票上市的資訊,這裡我們使用這支 API 來得到資料

API 回傳的資料是 json 檔案,裡面欄位分別為:

  • stat: 查詢結果狀態
  • date: 資料日期
  • title: 資料標題
  • fields: 資料各欄位名稱
  • data: 各股票資訊
    • 證券代號
    • 證券名稱
    • 成交股數
    • 成交金額
    • 開盤價
    • 最高價
    • 最低價
    • 收盤價
    • 漲跌價
    • 成交筆數

使用 python 取得股票資料,由於我們只需要 data 欄位的資料,因此先轉成 json 格式之後,取得 data 欄位:

python

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 回傳的資料只有當日的漲跌值,並沒有我們要的漲跌比例,因此我們要自己計算。

$$ 漲跌比例 = 漲跌值 / 昨日收盤 $$ $$ 昨日收盤 = 今日收盤 - 漲跌值 $$

python

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 ~ 100.01
10 ~ 500.05
50 ~ 1000.1
100 ~ 5000.5
500 ~ 10001
> 10005

因此,我們需要針對這部分做調整,我們先用 binary search 找出股票屬於哪個區間,然後找到對應的股票最小單位,並計算出在不超過漲跌停板的 10 % 區間內,最高和最低的價格,其中所有數值都用整數運算,俗話說:「算錢用浮點 遲早被人扁」。

python

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 保存下來。

python

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_wordcloud

最後可以依照漲跌幅列出所有股票的資訊:

python

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]}%")

廣告 AD