# 最強 AI 投資分析 (旗標, 施威銘, 2024)
# Python 股票 x ETF 量化交易 (博碩, 劉承彥, 2022)
本篇先來測試 FinMind 的 API, 此資料庫以台股為主, 包含個股盤後, 三大法人與融資融券等資料, 加入會員可獲得每小時 600 次免費請求額度 (不夠用的話再付費加入贊助方案), 參考 :
先來申請會員帳號 :
1. 註冊 FinMind 帳號 :
連線 FinMind API 網址 :
按右上角的 "登入/註冊" 超連結 :
填寫 User ID, E-mail (只接受 Gmail, Yahoo 與 icloud 信箱) 與密碼按 "註冊" 鈕即可 :
FinMind 會寄一封認證信到信箱, 開啟後按 "VERIFY EMAIL" 鈕 :
認證成功會導引至登入頁面 :
登入成功後會顯示使用者資訊頁面 :
可見免費會員有每小時 600 次的 API 呼叫額度, 將 API Token 金鑰複製到記事本中保存備用. 也可以複製到工作目錄下的一個隱藏檔 .env 中並取一個名稱例如 FinMind_TOKEN, 這樣做可以避免範例程式分享到 GitHub 時不小心洩漏 :
使用時可用 dotenv 或 python-decouple 等模組取出特定名稱之金鑰, 例如 dotenv 使用時要搭配 os 模組, 鑰先匯入 os 模組與 dotenv.load_dotenv 函式 :
import os
from dotenv import load_dotenv
先用 load_dotenv() 載入環境變數後再用 os.environ.get() 取出指定名稱之金鑰 :
load_dotenv()
token=os.environ.get('FinMind_TOKEN')
參考 :
2. 安裝 FinMind 套件 :
使用 pip install FinMind 指令安裝 :
D:\python\test>pip install FinMind
Collecting FinMind
Downloading FinMind-1.6.9-py3-none-any.whl.metadata (7.4 kB)
Requirement already satisfied: pandas>=1.1.5 in c:\users\tony1\appdata\roaming\python\python310\site-packages (from FinMind) (2.0.3)
Requirement already satisfied: numpy>=1.19.5 in c:\users\tony1\appdata\roaming\python\python310\site-packages (from FinMind) (1.24.3)
Requirement already satisfied: requests>=2.23.0 in c:\users\tony1\appdata\roaming\python\python310\site-packages (from FinMind) (2.31.0)
Requirement already satisfied: pydantic>=1.6.1 in c:\users\tony1\appdata\roaming\python\python310\site-packages (from FinMind) (2.5.3)
Collecting ta~=0.5.25 (from FinMind)
Downloading ta-0.5.25.tar.gz (20 kB)
Preparing metadata (setup.py) ... done
Collecting pytest>=6.2.2 (from FinMind)
Downloading pytest-8.3.2-py3-none-any.whl.metadata (7.5 kB)
Requirement already satisfied: lxml>=4.6.3 in c:\users\tony1\appdata\roaming\python\python310\site-packages (from FinMind) (4.9.3)
Collecting pyecharts>=1.9.0 (from FinMind)
Downloading pyecharts-2.0.6-py3-none-any.whl.metadata (1.3 kB)
Requirement already satisfied: ipython>=7.16.1 in c:\users\tony1\appdata\roaming\python\python310\site-packages (from FinMind) (8.15.0)
Collecting loguru>=0.5.3 (from FinMind)
Downloading loguru-0.7.2-py3-none-any.whl.metadata (23 kB)
Requirement already satisfied: setuptools>=49.2.1 in c:\users\tony1\appdata\local\programs\thonny\lib\site-packages (from FinMind) (65.5.0)
Requirement already satisfied: aiohttp>=3.7.4.post0 in c:\users\tony1\appdata\roaming\python\python310\site-packages (from FinMind) (3.9.1)
Requirement already satisfied: flask>=2.0.1 in c:\users\tony1\appdata\roaming\python\python310\site-packages (from FinMind) (2.3.3)
Requirement already satisfied: importlib-metadata>=4.8.1 in c:\users\tony1\appdata\roaming\python\python310\site-packages (from FinMind) (6.8.0)
Requirement already satisfied: attrs>=17.3.0 in c:\users\tony1\appdata\roaming\python\python310\site-packages (from aiohttp>=3.7.4.post0->FinMind) (23.1.0)
Requirement already satisfied: multidict<7.0,>=4.5 in c:\users\tony1\appdata\roaming\python\python310\site-packages (from aiohttp>=3.7.4.post0->FinMind) (6.0.4)
Requirement already satisfied: yarl<2.0,>=1.0 in c:\users\tony1\appdata\roaming\python\python310\site-packages (from aiohttp>=3.7.4.post0->FinMind) (1.9.4)
Requirement already satisfied: frozenlist>=1.1.1 in c:\users\tony1\appdata\roaming\python\python310\site-packages (from aiohttp>=3.7.4.post0->FinMind) (1.4.1)
Requirement already satisfied: aiosignal>=1.1.2 in c:\users\tony1\appdata\roaming\python\python310\site-packages (from aiohttp>=3.7.4.post0->FinMind) (1.3.1)
Requirement already satisfied: async-timeout<5.0,>=4.0 in c:\users\tony1\appdata\roaming\python\python310\site-packages (from aiohttp>=3.7.4.post0->FinMind) (4.0.3)
Requirement already satisfied: Werkzeug>=2.3.7 in c:\users\tony1\appdata\roaming\python\python310\site-packages (from flask>=2.0.1->FinMind) (2.3.7)
Requirement already satisfied: Jinja2>=3.1.2 in c:\users\tony1\appdata\roaming\python\python310\site-packages (from flask>=2.0.1->FinMind) (3.1.2)
Requirement already satisfied: itsdangerous>=2.1.2 in c:\users\tony1\appdata\roaming\python\python310\site-packages (from flask>=2.0.1->FinMind) (2.1.2)
Requirement already satisfied: click>=8.1.3 in c:\users\tony1\appdata\roaming\python\python310\site-packages (from flask>=2.0.1->FinMind) (8.1.7)
Requirement already satisfied: blinker>=1.6.2 in c:\users\tony1\appdata\roaming\python\python310\site-packages (from flask>=2.0.1->FinMind) (1.6.2)
Requirement already satisfied: zipp>=0.5 in c:\users\tony1\appdata\roaming\python\python310\site-packages (from importlib-metadata>=4.8.1->FinMind) (3.17.0)
Requirement already satisfied: backcall in c:\users\tony1\appdata\roaming\python\python310\site-packages (from ipython>=7.16.1->FinMind) (0.2.0)
Requirement already satisfied: decorator in c:\users\tony1\appdata\roaming\python\python310\site-packages (from ipython>=7.16.1->FinMind) (5.1.1)
Requirement already satisfied: jedi>=0.16 in c:\users\tony1\appdata\local\programs\thonny\lib\site-packages (from ipython>=7.16.1->FinMind) (0.18.2)
Requirement already satisfied: matplotlib-inline in c:\users\tony1\appdata\roaming\python\python310\site-packages (from ipython>=7.16.1->FinMind) (0.1.6)
Requirement already satisfied: pickleshare in c:\users\tony1\appdata\roaming\python\python310\site-packages (from ipython>=7.16.1->FinMind) (0.7.5)
Requirement already satisfied: prompt-toolkit!=3.0.37,<3.1.0,>=3.0.30 in c:\users\tony1\appdata\roaming\python\python310\site-packages (from ipython>=7.16.1->FinMind) (3.0.39)
Requirement already satisfied: pygments>=2.4.0 in c:\users\tony1\appdata\roaming\python\python310\site-packages (from ipython>=7.16.1->FinMind) (2.16.1)
Requirement already satisfied: stack-data in c:\users\tony1\appdata\roaming\python\python310\site-packages (from ipython>=7.16.1->FinMind) (0.6.2)
Requirement already satisfied: traitlets>=5 in c:\users\tony1\appdata\roaming\python\python310\site-packages (from ipython>=7.16.1->FinMind) (5.9.0)
Requirement already satisfied: exceptiongroup in c:\users\tony1\appdata\roaming\python\python310\site-packages (from ipython>=7.16.1->FinMind) (1.1.3)
Requirement already satisfied: colorama in c:\users\tony1\appdata\local\programs\thonny\lib\site-packages (from ipython>=7.16.1->FinMind) (0.4.6)
Collecting win32-setctime>=1.0.0 (from loguru>=0.5.3->FinMind)
Downloading win32_setctime-1.1.0-py3-none-any.whl.metadata (2.3 kB)
Requirement already satisfied: python-dateutil>=2.8.2 in c:\users\tony1\appdata\roaming\python\python310\site-packages (from pandas>=1.1.5->FinMind) (2.8.2)
Requirement already satisfied: pytz>=2020.1 in c:\users\tony1\appdata\roaming\python\python310\site-packages (from pandas>=1.1.5->FinMind) (2023.3)
Requirement already satisfied: tzdata>=2022.1 in c:\users\tony1\appdata\roaming\python\python310\site-packages (from pandas>=1.1.5->FinMind) (2023.3)
Requirement already satisfied: annotated-types>=0.4.0 in c:\users\tony1\appdata\roaming\python\python310\site-packages (from pydantic>=1.6.1->FinMind) (0.5.0)
Requirement already satisfied: pydantic-core==2.14.6 in c:\users\tony1\appdata\roaming\python\python310\site-packages (from pydantic>=1.6.1->FinMind) (2.14.6)
Requirement already satisfied: typing-extensions>=4.6.1 in c:\users\tony1\appdata\roaming\python\python310\site-packages (from pydantic>=1.6.1->FinMind) (4.9.0)
Collecting prettytable (from pyecharts>=1.9.0->FinMind)
Downloading prettytable-3.11.0-py3-none-any.whl.metadata (30 kB)
Collecting simplejson (from pyecharts>=1.9.0->FinMind)
Downloading simplejson-3.19.3-cp310-cp310-win_amd64.whl.metadata (3.2 kB)
Collecting iniconfig (from pytest>=6.2.2->FinMind)
Downloading iniconfig-2.0.0-py3-none-any.whl.metadata (2.6 kB)
Requirement already satisfied: packaging in c:\users\tony1\appdata\roaming\python\python310\site-packages (from pytest>=6.2.2->FinMind) (23.1)
Collecting pluggy<2,>=1.5 (from pytest>=6.2.2->FinMind)
Downloading pluggy-1.5.0-py3-none-any.whl.metadata (4.8 kB)
Requirement already satisfied: tomli>=1 in c:\users\tony1\appdata\local\programs\thonny\lib\site-packages (from pytest>=6.2.2->FinMind) (2.0.1)
Requirement already satisfied: charset-normalizer<4,>=2 in c:\users\tony1\appdata\roaming\python\python310\site-packages (from requests>=2.23.0->FinMind) (3.2.0)
Requirement already satisfied: idna<4,>=2.5 in c:\users\tony1\appdata\roaming\python\python310\site-packages (from requests>=2.23.0->FinMind) (3.4)
Requirement already satisfied: urllib3<3,>=1.21.1 in c:\users\tony1\appdata\local\programs\thonny\lib\site-packages (from requests>=2.23.0->FinMind) (1.26.19)
Requirement already satisfied: certifi>=2017.4.17 in c:\users\tony1\appdata\roaming\python\python310\site-packages (from requests>=2.23.0->FinMind) (2023.7.22)
Requirement already satisfied: parso<0.9.0,>=0.8.0 in c:\users\tony1\appdata\local\programs\thonny\lib\site-packages (from jedi>=0.16->ipython>=7.16.1->FinMind) (0.8.3)
Requirement already satisfied: MarkupSafe>=2.0 in c:\users\tony1\appdata\roaming\python\python310\site-packages (from Jinja2>=3.1.2->flask>=2.0.1->FinMind) (2.1.3)
Requirement already satisfied: wcwidth in c:\users\tony1\appdata\roaming\python\python310\site-packages (from prompt-toolkit!=3.0.37,<3.1.0,>=3.0.30->ipython>=7.16.1->FinMind) (0.2.6)
Requirement already satisfied: six>=1.5 in c:\users\tony1\appdata\local\programs\thonny\lib\site-packages (from python-dateutil>=2.8.2->pandas>=1.1.5->FinMind) (1.16.0)
Requirement already satisfied: executing>=1.2.0 in c:\users\tony1\appdata\roaming\python\python310\site-packages (from stack-data->ipython>=7.16.1->FinMind) (1.2.0)
Requirement already satisfied: asttokens>=2.1.0 in c:\users\tony1\appdata\local\programs\thonny\lib\site-packages (from stack-data->ipython>=7.16.1->FinMind) (2.2.1)
Requirement already satisfied: pure-eval in c:\users\tony1\appdata\roaming\python\python310\site-packages (from stack-data->ipython>=7.16.1->FinMind) (0.2.2)
Downloading FinMind-1.6.9-py3-none-any.whl (60 kB)
Downloading loguru-0.7.2-py3-none-any.whl (62 kB)
Downloading pyecharts-2.0.6-py3-none-any.whl (149 kB)
Downloading pytest-8.3.2-py3-none-any.whl (341 kB)
Downloading pluggy-1.5.0-py3-none-any.whl (20 kB)
Downloading win32_setctime-1.1.0-py3-none-any.whl (3.6 kB)
Downloading iniconfig-2.0.0-py3-none-any.whl (5.9 kB)
Downloading prettytable-3.11.0-py3-none-any.whl (28 kB)
Downloading simplejson-3.19.3-cp310-cp310-win_amd64.whl (75 kB)
Building wheels for collected packages: ta
Building wheel for ta (setup.py) ... done
Created wheel for ta: filename=ta-0.5.25-py3-none-any.whl size=24873 sha256=69a2fe129c272c3311e7e8d4901588f3879c96f19fae839ff215e5fb37a4b56f
Stored in directory: c:\users\tony1\appdata\local\pip\cache\wheels\d4\bd\c4\0dda911b5461ee856352cd8c9e16472229bb51c95e74b74c08
Successfully built ta
Installing collected packages: win32-setctime, simplejson, prettytable, pluggy, iniconfig, pytest, pyecharts, loguru, ta, FinMind
Successfully installed FinMind-1.6.9 iniconfig-2.0.0 loguru-0.7.2 pluggy-1.5.0 prettytable-3.11.0 pyecharts-2.0.6 pytest-8.3.2 simplejson-3.19.3 ta-0.5.25 win32-setctime-1.1.0
檢視版本 :
>>> import FinMind
>>> FinMind.__version__
'1.6.9'
因為呼叫 FinMind API 會傳回 Pandas 的 DataFrame, 而在 Colab 中顯示 DataFrame 較美觀, 所以我也在 Colab 安裝 FinMind, 只是 pip 指令前須加驚嘆號 ! :
!pip install FinMind
用 dir() 檢視 FinMind 套件 :
>>> dir(FinMind)
['__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__path__', '__spec__', '__version__', '_version', 'crawler', 'data', 'indicators', 'schema', 'strategies', 'utility']
用自訂模組 Members 的 list_members() 檢視 FinMind 套件 :
>>> list_members(FinMind)
crawler <class 'module'>
data <class 'module'>
indicators <class 'module'>
schema <class 'module'>
strategies <class 'module'>
utility <class 'module'>
可見此套件由 6 個模組構成, 呼叫 FinMind API 用到的是 data 模組下的 DataLoader 類別 :
>>> dir(FinMind.data)
['DataLoader', 'DataSubscriber', 'FinMindApi', 'FutureAndOption', 'Stock', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__path__', '__spec__', 'data_loader', 'data_subscriber', 'finmind_api']
>>> list_members(FinMind.data)
DataLoader <class 'type'>
DataSubscriber <class 'type'>
FinMindApi <class 'type'>
FutureAndOption <class 'enum.EnumMeta'>
Stock <class 'enum.EnumMeta'>
data_loader <class 'module'>
data_subscriber <class 'module'>
finmind_api <class 'module'>
3. 建立 DataLoader 物件呼叫 API :
呼叫 FinMind API 需建立 DataLoader 物件, 先從 FinMind.data 模組匯入 DataLoader 類別 :
from FinMind.data import DataLoader
然後呼叫其建構子建立 DataLoader 物件 :
data_loader=DataLoader()
例如 :
>>> from FinMind.data import DataLoader
>>> data_loader=DataLoader()
>>> type(data_loader)
<class 'FinMind.data.data_loader.DataLoader'>
用自訂模組 Members 的 list_members() 檢視 DataLoader 物件 :
>>> list_members(data_loader)
api_version <class 'str'>
feature <class 'FinMind.data.data_loader.Feature'>
get_data <class 'method'>
get_datalist <class 'method'>
get_taiwan_futures_snapshot <class 'method'>
get_taiwan_options_snapshot <class 'method'>
get_taiwan_stock_tick_snapshot <class 'method'>
login <class 'method'>
login_by_token <class 'method'>
taiwan_daily_short_sale_balances <class 'method'>
taiwan_futopt_daily_info <class 'method'>
taiwan_futopt_tick_info <class 'method'>
taiwan_futopt_tick_realtime <class 'method'>
taiwan_futures_daily <class 'method'>
taiwan_futures_dealer_trading_volume_daily <class 'method'>
taiwan_futures_institutional_investors <class 'method'>
taiwan_futures_snapshot <class 'method'>
taiwan_futures_tick <class 'method'>
taiwan_option_daily <class 'method'>
taiwan_option_dealer_trading_volume_daily <class 'method'>
taiwan_option_institutional_investors <class 'method'>
taiwan_option_tick <class 'method'>
taiwan_options_snapshot <class 'method'>
taiwan_securities_trader_info <class 'method'>
taiwan_stock_10year <class 'method'>
taiwan_stock_balance_sheet <class 'method'>
taiwan_stock_bar <class 'method'>
taiwan_stock_book_and_trade <class 'method'>
taiwan_stock_capital_reduction_reference_price <class 'method'>
taiwan_stock_cash_flows_statement <class 'method'>
taiwan_stock_convertible_bond_daily <class 'method'>
taiwan_stock_convertible_bond_daily_overview <class 'method'>
taiwan_stock_convertible_bond_info <class 'method'>
taiwan_stock_convertible_bond_institutional_investors <class 'method'>
taiwan_stock_daily <class 'method'>
taiwan_stock_daily_adj <class 'method'>
taiwan_stock_day_trading <class 'method'>
taiwan_stock_delisting <class 'method'>
taiwan_stock_dividend <class 'method'>
taiwan_stock_dividend_result <class 'method'>
taiwan_stock_financial_statement <class 'method'>
taiwan_stock_government_bank_buy_sell <class 'method'>
taiwan_stock_holding_shares_per <class 'method'>
taiwan_stock_info <class 'method'>
taiwan_stock_info_with_warrant <class 'method'>
taiwan_stock_institutional_investors <class 'method'>
taiwan_stock_institutional_investors_total <class 'method'>
taiwan_stock_margin_purchase_short_sale <class 'method'>
taiwan_stock_margin_purchase_short_sale_total <class 'method'>
taiwan_stock_margin_short_sale_suspension <class 'method'>
taiwan_stock_market_value <class 'method'>
taiwan_stock_month_revenue <class 'method'>
taiwan_stock_news <class 'method'>
taiwan_stock_per_pbr <class 'method'>
taiwan_stock_securities_lending <class 'method'>
taiwan_stock_shareholding <class 'method'>
taiwan_stock_tick <class 'method'>
taiwan_stock_tick_snapshot <class 'method'>
taiwan_stock_total_return_index <class 'method'>
taiwan_total_exchange_margin_maintenance <class 'method'>
translation <class 'method'>
tse <class 'method'>
us_stock_info <class 'method'>
us_stock_price <class 'method'>
這些 DataLoader 物件的方法就是所謂的 API, 使用者可以透過呼叫這些方法從 FinMind 資料庫下載台股資訊. 目前 FinMind 總共提供 55 種台股資料集可供查詢, 含括基本面, 技術面, 籌碼面, 新聞面, 與即時資料等, 每種資料集的 API 用法參考 :
常用的 API 摘要如下表 :
DataLoader 物件常用方法 | 說明 |
login_by_token() | 傳入金鑰登入 FinMind 帳戶, 參數 : api_token |
taiwan_stock_daily() | 台股收盤資料, 參數 : stock_id, start_date, end_date |
taiwan_stock_daily_adj() | 還原權息股價, 參數 : stock_id, start_date, end_date |
taiwan_stock_financial_statement() | 個股損益表, 參數 : stock_id, start_date |
taiwan_stock_cash_flows_statement() | 個股現金流量表, 參數 : stock_id, start_date |
taiwan_stock_balance_sheet() | 個股資產負債表, 參數 : stock_id, start_date |
taiwan_stock_institutional_invenstors() | 法人進出資訊, 參數 : stock_id, start_date, end_date |
taiwan_stock_shareholding() | 外資持股表, 參數 : stock_id, start_date, end_date |
taiwan_stock_month_revenue() | 個股月營收表, 參數 : stock_id, start_date |
taiwan_stock_info() | 台股總覽, 參數 : 無 |
其中最常用的是查詢每日收盤資料的 API : taiwan_stock_daily() 與 taiwan_stock_daily_adj(), 差別是後者的收盤價是還原權息的. 不過 taiwan_stock_daily_adj() 這個 API 並未開放給免費帳戶使用, 必須付費加入贊助帳戶才能呼叫.
但是, 呼叫這些 API 前必須先呼叫 login_by_token() 方法並傳入金鑰 (參數 api_token) 登入帳戶才行. 我們先利用 dotenv 模組從 .env 檔取出金鑰 :
>>> import os
>>> from dotenv import load_dotenv
>>> load_dotenv()
True
>>> token=os.environ.get('FinMind_TOKEN')
>>> print(token)
'金鑰在此'
然後呼叫 DataLoader 物件的 login_by_token() 並傳入關鍵字參數 api_token=金鑰進行認證 :
>>> data_loader.login_by_token(api_token=token)
參考官方文件 :
如果沒有出現錯誤表示登入成功 (傳回 None), 這樣就可以呼叫其他 API 了, 例如呼叫 taiwan_stock_daily() 可取得盤後資料, 此方法須傳入三個參數 :
- stock_id : 股票代號 (字串), 例如 '0050'
- start_date : 起始日期, 可以是日期字串例如 '2024-08-17' 或 datatime 物件
- end_date : 結束日期, 可以是日期字串例如 '2024-08-17' 或 datatime 物件
例如取得近一個月的日收盤資料, 起訖日期可以直接傳入日期字串 '2024-07-18' 與 '2024-08-17', 也可以傳入 datetime 物件, 下面用 datime 模組的 date 與 timedelta 類別來處理起訖日期 :
>>> from datetime import date, timedelta
>>> stock_id='0050'
>>> end_date=date.today()
>>> end_date
datetime.date(2024, 8, 17)
>>> start_date=end_date - timedelta(days=30) # 前 30 日之 datetime 物件
>>> start_date
datetime.date(2024, 7, 18)
將此三個參數傳入 taiwan_stock_daily() 會傳回指定區間之每日盤後資料的 DataFrame :
>>> data=data_loader.taiwan_stock_daily(
stock_id=stock_id,
start_date=start_date,
end_date=end_date)
2024-08-17 23:48:34.329 | INFO | FinMind.data.finmind_api:get_data:125 - download TaiwanStockPrice, data_id: 0050
>>> type(data)
<class 'pandas.core.frame.DataFrame'>
>>> data
date stock_id Trading_Volume ... close spread Trading_turnover
0 2024-07-18 0050 19796818 ... 190.60 -3.50 39463
1 2024-07-19 0050 18436231 ... 186.25 -4.35 43183
2 2024-07-22 0050 23474914 ... 180.70 -5.55 48514
3 2024-07-23 0050 13180830 ... 186.30 5.60 18100
4 2024-07-26 0050 29164975 ... 179.00 -7.30 61517
5 2024-07-29 0050 10574343 ... 180.60 1.60 16228
6 2024-07-30 0050 14007149 ... 180.60 0.00 22564
7 2024-07-31 0050 9530148 ... 180.85 0.25 12645
8 2024-08-01 0050 14525195 ... 184.00 3.15 14649
9 2024-08-02 0050 32816025 ... 174.70 -9.30 68966
10 2024-08-05 0050 61002329 ... 158.75 -15.95 111467
11 2024-08-06 0050 65342352 ... 167.50 8.75 54758
12 2024-08-07 0050 32751044 ... 174.15 6.65 29003
13 2024-08-08 0050 26852782 ... 170.55 -3.60 29484
14 2024-08-09 0050 24121860 ... 175.85 5.30 21088
15 2024-08-12 0050 18188036 ... 178.05 2.20 18552
16 2024-08-13 0050 11257895 ... 178.50 0.45 12862
17 2024-08-14 0050 19282599 ... 180.75 2.25 16415
18 2024-08-15 0050 12003834 ... 179.35 -1.40 16847
19 2024-08-16 0050 13980972 ... 183.40 4.05 17837
[20 rows x 10 columns]
檢視 DataFrame 的 columns 屬性 (欄位) 可知它有 10 個欄位 :
>>> data.columns
Index(['date', 'stock_id', 'Trading_Volume', 'Trading_money', 'open', 'max', 'min', 'close', 'spread', 'Trading_turnover'], dtype='object')
這比 yfinance 傳回的欄位還多, 但要進行技術分析其實只要 "OHLCV (開高低收量)" 這 5 個欄位即可. 其次, 最高價與最低價用的是 max 與 min, 而非常見的 high 與 low. 另外, 欄位名稱大部分是小寫開頭, 所以如果要用 backtest 做回測的話須調整為大寫字母開頭 (像 yfinance 那樣).
這 10 個欄位說明如下表 :
欄位 | 說明 |
date | 日期 (字串) |
stock_id | 股票代號 (整數) |
Trading_Volumn | 成交股數 (整數) |
Trading_money | 成交金額 (字串) |
open | 開盤價 (浮點數) |
max | 最高價 (浮點數) |
min | 最低價 (浮點數) |
close | 收盤價 (浮點數) |
spread | 漲跌價 (浮點數) |
Trading_turnover | 成交筆數 (整數) |
用 info() 方法查詢各欄位資料型態 :
>>> data.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 20 entries, 0 to 19
Data columns (total 10 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 date 20 non-null object
1 stock_id 20 non-null object
2 Trading_Volume 20 non-null int64
3 Trading_money 20 non-null int64
4 open 20 non-null float64
5 max 20 non-null float64
6 min 20 non-null float64
7 close 20 non-null float64
8 spread 20 non-null float64
9 Trading_turnover 20 non-null int64
dtypes: float64(5), int64(3), object(2)
memory usage: 1.7+ KB
這時去查看 FinMind 的使用者資訊, 會顯示已使用 API 呼叫 1 次 :
免費帳戶如果呼叫 taiwan_stock_daily_adj() 會 400 錯誤訊息 :
>>> data=data_loader.taiwan_stock_daily_adj(
stock_id='0050',
start_date='2024-07-18',
end_date='2024-08-17')
2024-08-18 15:05:03.943 | INFO | FinMind.data.finmind_api:get_data:125 - download TaiwanStockPriceAdj, data_id: 0050
2024-08-18 15:05:04.089 | ERROR | FinMind.data.finmind_api:request_get:43 - {'dataset': <Dataset.TaiwanStockPriceAdj: 'TaiwanStockPriceAdj'>, 'data_id': '0050', 'stock_id': '', 'start_date': '2024-07-18', 'end_date': '2024-08-17', 'user_id': '', 'password':
... (略) ...
Exception: {"msg":"Your level is register. Please update your user level. Detail information:https://finmindtrade.com/analysis/#/Sponsor/sponsor","status":400}
此 API 未開放給免費帳戶使用, 需付費成為贊助帳戶才能呼叫.
4. 繪製 K 線圖 :
接下來我們可以用 mplfinance 套件來繪製上面從 FinMind 取得的盤後資料之 K 線圖, 但在繪圖之前必須對傳回的 DataFrame 物件做一些調整以符合 mplfinance 套件之要求.
首先 mplfinance 要求做為 X 軸的 date 欄位之資料型態必須是 Timestamp 型別, 而且 date 欄位必須設為列索引, 如上所示 FinMind 傳回的 DataFrame 之 date 欄位型態為字串 (Object), 因此必須利用 Pandas 的 to_datetime() 函式將 date 欄位由日期字串 'YYYY-mm-dd' 轉成一個 Timestamp 物件 :
>>> data['date']=pd.to_datetime(data['date'])
>>> type(data['date'][0])
<class 'pandas._libs.tslibs.timestamps.Timestamp'>
然後呼叫 DataFrame 物件的 set_index() 方法將其設為列索引 (index) :
>>> data=data.set_index(data['date'])
其次是 mplfinance 要求 OHLCV 欄位名稱必須為首字母大寫 Open, High, Low, Close, 與 Volumn (即與 yfinance 的欄位名稱一致) 才能繪製 K 線圖, 這可以用 DataFrame 物件的 rename() 方法並傳入前後欄位名稱組成的字典給 columns 參數來修改 :
>>> columns={'open': 'Open',
'max': 'High',
'min': 'Low',
'close': 'Close',
'Trading_Volume': 'Volume'} # 舊: 新欄位名稱對映字典
>>> data=data.rename(columns=columns)
>>> data
date stock_id Trading_Volume Trading_money Open High Low Close spread Trading_turnover
date
2024-07-18 2024-07-18 0050 19796818 3754498885 188.60 190.90 188.20 190.60 -3.50 39463
2024-07-19 2024-07-19 0050 18436231 3456363627 188.75 189.00 186.20 186.25 -4.35 43183
2024-07-22 2024-07-22 0050 23474914 4268806758 185.40 185.40 180.05 180.70 -5.55 48514
2024-07-23 2024-07-23 0050 13180830 2437876621 183.70 186.30 183.70 186.30 5.60 18100
2024-07-26 2024-07-26 0050 29164975 5210021472 178.05 179.45 177.10 179.00 -7.30 61517
2024-07-29 2024-07-29 0050 10574343 1915739406 181.80 182.00 179.95 180.60 1.60 16228
2024-07-30 2024-07-30 0050 14007149 2507019649 179.25 181.30 177.50 180.60 0.00 22564
2024-07-31 2024-07-31 0050 9530148 1715165757 178.85 181.15 178.60 180.85 0.25 12645
2024-08-01 2024-08-01 0050 14525195 2671260519 185.00 185.10 182.70 184.00 3.15 14649
2024-08-02 2024-08-02 0050 32816025 5798178503 178.15 178.90 174.70 174.70 -9.30 68966
2024-08-05 2024-08-05 0050 61002329 9893076101 166.65 166.65 158.40 158.75 -15.95 111467
2024-08-06 2024-08-06 0050 65342352 10883521675 167.30 170.40 160.80 167.50 8.75 54758
2024-08-07 2024-08-07 0050 32751044 5650132811 169.85 174.75 169.00 174.15 6.65 29003
2024-08-08 2024-08-08 0050 26852782 4585081468 171.05 172.40 169.00 170.55 -3.60 29484
2024-08-09 2024-08-09 0050 24121860 4242663929 175.00 176.90 174.50 175.85 5.30 21088
2024-08-12 2024-08-12 0050 18188036 3246767115 177.25 179.80 177.25 178.05 2.20 18552
2024-08-13 2024-08-13 0050 11257895 2010945566 179.30 179.50 178.00 178.50 0.45 12862
2024-08-14 2024-08-14 0050 19282599 3487274230 180.35 181.85 179.95 180.75 2.25 16415
2024-08-15 2024-08-15 0050 12003834 2160883722 180.60 181.00 179.05 179.35 -1.40 16847
2024-08-16 2024-08-16 0050 13980972 2561360342 183.00 183.65 182.35 183.40 4.05 17837
接下來就可以用 mplfinance 來繪製 K 線圖了, 首先要匯入 mplfinance 套件 :
import mplfinance as mpf
然後呼叫其 plot() 函式並傳入具有 "開高低收量 (OHLCV)" 欄位的 DataFrame 即可 :
mpf.plot(data [, type='candle', title, style=style, volume=True, mav=None, xrotation=0, savefig])
參數說明如下 :
- type : K 線類型, 台日股市的蠟燭圖 (陰陽線) 要設為 'candle'.
- style : 用來指定自訂樣式物件.
- volume : 用來設定是否要在 K 線圖下方同時顯示成交量 (預設為 False).
- nav : 用來設定要顯示幾日均線, 可傳入整數 (例如 3) 或整數串列 (例如 [3, 5, 7])
- xrotation : 日期 (X 軸 date 欄位) 旋轉角度, 預設 0
- savefig : 儲存之 png 檔名 (含路徑)
由於 mplfinance 預設樣式為美式 K 線, 所以需要用自訂樣式來調整為台股樣式, 首先要將 K 棒的漲跌顏色設成漲紅跌綠 :
>>> color=mpf.make_marketcolors(up='red', down='green', inherit=True)
然後為了讓標題可顯示中文, 設定字型物件為微軟正黑體 :
>>> font={'font.family': 'Microsoft JhengHei'}
然後將 color 與 font 傳入 make_mpf_style() 函式來建立自訂樣式物件 :
>>> style=mpf.make_mpf_style(base_mpf_style='default', marketcolors=color, rc=font)
這樣就可以呼叫 plot() 來繪製 K 線圖了 :
>>> mpf.plot(data, type='candle', title='台灣五十(0050)', style=style)
這樣就會畫出 K 線圖了 :
傳入 mav=[3, 5, 7] 可在 K 線圖上繪製 3, 5 7 日均線; 傳入 volume=True 會在底下添加成交量值條圖, 例如 :
>>> mpf.plot(data, type='candle', title='台灣五十(0050)', style=style, mav=[3, 5, 7], volume=True)
關於 mplfinance 用法參考 :
沒有留言:
張貼留言