我這幾天在測試 Plotly 套件, 想要用它來畫 K 線圖, 欲使用 yfinance 取得股價資料時卻發現居然出現錯誤, 我就拿之前 yfinance 筆記中的程式碼來測試, 發現一樣會丟出 JSONDecodeError 錯誤 :
>>> import yfinance as yf
import pandas as pd
import mplfinance as mpf
df=yf.download('0050.tw', start='2024-07-01', end='2024-08-21')
[*********************100%%**********************] 1 of 1 completed
1 Failed download:
['0050.TW']: JSONDecodeError('Expecting value: line 1 column 1 (char 0)')
我改用美股代號也是一樣 :
>>> yf.download('AAPL', start='2024-07-01', end='2024-08-21')
[*********************100%%**********************] 1 of 1 completed
1 Failed download:
['AAPL']: JSONDecodeError('Expecting value: line 1 column 1 (char 0)')
Empty DataFrame
Columns: [Open, High, Low, Close, Adj Close, Volume]
Index: []
搜尋谷歌發現不是只有我遇到, 原來是 yfinance 有改版, 舊的 yfinance (我的是 v0.2.41) 下載資料會出錯, 解決辦法就是升版, 參考 :
1. 更新 yfinance 套件 :
用 pip install 指令加 -U 參數更新版本 :
D:\python\test>pip install yfinance -U
Requirement already satisfied: yfinance in c:\users\tony1\appdata\roaming\python\python310\site-packages (0.2.41)
Collecting yfinance
Downloading yfinance-0.2.63-py2.py3-none-any.whl.metadata (5.8 kB)
Requirement already satisfied: pandas>=1.3.0 in c:\users\tony1\appdata\roaming\python\python310\site-packages (from yfinance) (2.0.3)
Requirement already satisfied: numpy>=1.16.5 in c:\users\tony1\appdata\roaming\python\python310\site-packages (from yfinance) (1.24.3)
Requirement already satisfied: requests>=2.31 in c:\users\tony1\appdata\roaming\python\python310\site-packages (from yfinance) (2.31.0)
Requirement already satisfied: multitasking>=0.0.7 in c:\users\tony1\appdata\roaming\python\python310\site-packages (from yfinance) (0.0.11)
Requirement already satisfied: platformdirs>=2.0.0 in c:\users\tony1\appdata\local\programs\thonny\lib\site-packages (from yfinance) (3.10.0)
Requirement already satisfied: pytz>=2022.5 in c:\users\tony1\appdata\roaming\python\python310\site-packages (from yfinance) (2023.3)
Requirement already satisfied: frozendict>=2.3.4 in c:\users\tony1\appdata\roaming\python\python310\site-packages (from yfinance) (2.4.4)
Requirement already satisfied: peewee>=3.16.2 in c:\users\tony1\appdata\roaming\python\python310\site-packages (from yfinance) (3.17.6)
Requirement already satisfied: beautifulsoup4>=4.11.1 in c:\users\tony1\appdata\local\programs\thonny\lib\site-packages (from yfinance) (4.12.3)
Collecting curl_cffi>=0.7 (from yfinance)
Downloading curl_cffi-0.11.4-cp39-abi3-win_amd64.whl.metadata (14 kB)
Requirement already satisfied: protobuf>=3.19.0 in c:\users\tony1\appdata\local\programs\thonny\lib\site-packages (from yfinance) (5.28.1)
Collecting websockets>=13.0 (from yfinance)
Downloading websockets-15.0.1-cp310-cp310-win_amd64.whl.metadata (7.0 kB)
Requirement already satisfied: soupsieve>1.2 in c:\users\tony1\appdata\roaming\python\python310\site-packages (from beautifulsoup4>=4.11.1->yfinance) (2.4.1)
Requirement already satisfied: cffi>=1.12.0 in c:\users\tony1\appdata\local\programs\thonny\lib\site-packages (from curl_cffi>=0.7->yfinance) (1.15.1)
Collecting certifi>=2024.2.2 (from curl_cffi>=0.7->yfinance)
Downloading certifi-2025.6.15-py3-none-any.whl.metadata (2.4 kB)
Requirement already satisfied: pycparser in c:\users\tony1\appdata\local\programs\thonny\lib\site-packages (from cffi>=1.12.0->curl_cffi>=0.7->yfinance) (2.21)
Requirement already satisfied: python-dateutil>=2.8.2 in c:\users\tony1\appdata\roaming\python\python310\site-packages (from pandas>=1.3.0->yfinance) (2.8.2)
Requirement already satisfied: tzdata>=2022.1 in c:\users\tony1\appdata\roaming\python\python310\site-packages (from pandas>=1.3.0->yfinance) (2023.3)
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.3.0->yfinance) (1.16.0)
Requirement already satisfied: charset-normalizer<4,>=2 in c:\users\tony1\appdata\roaming\python\python310\site-packages (from requests>=2.31->yfinance) (3.2.0)
Requirement already satisfied: idna<4,>=2.5 in c:\users\tony1\appdata\roaming\python\python310\site-packages (from requests>=2.31->yfinance) (3.4)
Requirement already satisfied: urllib3<3,>=1.21.1 in c:\users\tony1\appdata\local\programs\thonny\lib\site-packages (from requests>=2.31->yfinance) (1.26.19)
Downloading yfinance-0.2.63-py2.py3-none-any.whl (118 kB)
Downloading curl_cffi-0.11.4-cp39-abi3-win_amd64.whl (1.6 MB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 1.6/1.6 MB 2.6 MB/s eta 0:00:00
Downloading certifi-2025.6.15-py3-none-any.whl (157 kB)
Downloading websockets-15.0.1-cp310-cp310-win_amd64.whl (176 kB)
Installing collected packages: websockets, certifi, curl_cffi, yfinance
Attempting uninstall: websockets
Found existing installation: websockets 10.4
Uninstalling websockets-10.4:
Successfully uninstalled websockets-10.4
Attempting uninstall: certifi
Found existing installation: certifi 2023.7.22
Uninstalling certifi-2023.7.22:
Successfully uninstalled certifi-2023.7.22
Attempting uninstall: yfinance
Found existing installation: yfinance 0.2.41
Uninstalling yfinance-0.2.41:
Successfully uninstalled yfinance-0.2.41
Successfully installed certifi-2025.6.15 curl_cffi-0.11.4 websockets-11.0.3 yfinance-0.2.63
可見已升到最新的 v.0.2.63, 其實升到 v.2.0.54 以上就不會出錯了.
升版後就能正常下載了 (會出現一個警告, 但不影響資料取得) :
>>> import yfinance as yf
import pandas as pd
import mplfinance as mpf
df=yf.download('0050.tw', start='2024-07-01', end='2024-08-21')
<stdin>:4: FutureWarning: YF.download() has changed argument auto_adjust default to True
[*********************100%***********************] 1 of 1 completed
>>> df
Price Close High Low Open Volume
Ticker 0050.TW 0050.TW 0050.TW 0050.TW 0050.TW
Date
2024-07-01 183.120392 184.543350 182.776912 183.071321 7319803
2024-07-02 181.893707 183.267595 181.059552 182.482510 5444336
2024-07-03 184.101746 184.101746 182.924111 184.101746 6478757
2024-07-04 188.910370 189.057567 187.045806 187.045806 12644207
2024-07-05 188.223419 189.253842 187.978081 189.008504 9733333
2024-07-08 194.160614 194.798487 188.272499 188.321554 17352467
2024-07-09 193.964325 196.319580 191.805352 193.768057 15488789
2024-07-10 194.651291 194.700347 191.363754 193.277388 7168611
2024-07-11 198.969238 199.018309 196.270519 196.908392 9796730
2024-07-12 192.688583 194.651289 192.345104 194.504077 14158267
2024-07-15 193.032043 194.405946 192.443241 193.964325 9790185
2024-07-16 194.166367 196.287050 193.327949 193.870453 13255538
2024-07-17 191.453857 193.821132 190.960674 193.722490 14489778
2024-07-18 188.001572 188.297470 185.634282 186.028837 17880013
2024-07-19 183.710876 186.423386 183.661555 186.176794 16453910
2024-07-22 178.236526 182.872449 177.595394 182.872449 21211846
2024-07-23 183.760193 183.760193 181.195632 181.195632 12527079
2024-07-26 176.559708 177.003570 174.685616 175.622662 25906618
2024-07-29 178.137909 179.518817 177.496761 179.321546 9946264
2024-07-30 178.137909 178.828363 175.080165 176.806307 13107381
2024-07-31 178.384491 178.680389 176.165165 176.411757 9078554
2024-08-01 181.491547 182.576556 180.209266 182.477914 14061699
2024-08-02 172.318329 176.461068 172.318329 175.721292 29706815
2024-08-05 156.585785 164.378079 156.240550 164.378079 55577204
2024-08-06 165.216492 168.076950 158.607835 165.019221 63140961
2024-08-07 171.775833 172.367659 166.696048 167.534466 31824740
2024-08-08 168.224915 170.049685 166.696043 168.718098 25841105
2024-08-09 173.452667 174.488341 172.121066 172.614249 23353756
2024-08-12 175.622665 177.348808 174.833569 174.833569 17571739
2024-08-13 176.066528 177.052895 175.573345 176.855625 10858460
2024-08-14 178.285858 179.370868 177.496761 177.891317 18714319
2024-08-15 176.904953 178.532453 176.609040 178.137912 11481647
2024-08-16 180.899719 181.146311 179.864046 180.505178 13205915
2024-08-19 181.146317 182.182005 180.653133 180.998367 9280593
2024-08-20 181.244949 182.675179 181.195628 182.083367 10784876
注意, 改版後預設不會顯示 Close Adj 欄位, Close 欄位就是已調整權值後的收盤價 Close Adj. 因為新版的 API 有修改, download() 的 auto_adjust 參數預設值為 True, 亦即 Close 欄位就是 Close Adj, 這就是上面出現的警告 "FutureWarning: YF.download() has changed argument auto_adjust default to True" 所提示的. 只要下載時明確指定 auto_adjust 之值就不會出現警語了, 例如 :
>>> df=yf.download('0050.tw', start='2024-07-01', end='2024-08-21', auto_adjust=True)
[*********************100%***********************] 1 of 1 completed
>>> df
Price Close High Low Open Volume
Ticker 0050.TW 0050.TW 0050.TW 0050.TW 0050.TW
Date
2024-07-01 45.692062 46.047118 45.606358 45.679818 29279212
2024-07-02 45.385979 45.728790 45.177841 45.532896 21777344
2024-07-03 45.936928 45.936928 45.643085 45.936928 25915028
2024-07-04 47.136772 47.173501 46.671528 46.671528 50576828
2024-07-05 46.965366 47.222477 46.904150 47.161260 38933332
2024-07-08 48.446808 48.605969 46.977610 46.989850 69409868
2024-07-09 48.397835 48.985516 47.859130 48.348862 61955156
2024-07-10 48.569241 48.581481 47.748937 48.226425 28674444
2024-07-11 49.646652 49.658896 48.973270 49.132431 39186920
2024-07-12 48.079510 48.569242 47.993805 48.532510 56633068
2024-07-15 48.165207 48.508022 48.018289 48.397829 39160740
2024-07-16 48.201942 48.728404 47.993805 48.128482 53022152
2024-07-17 47.528557 48.116235 47.406124 48.091746 57959112
2024-07-18 46.671528 46.744985 46.083846 46.181795 71520052
2024-07-19 45.606358 46.279740 45.594114 46.218523 65815640
2024-07-22 44.247345 45.398216 44.088183 45.398216 84847384
2024-07-23 45.618599 45.618599 44.981945 44.981945 50108316
2024-07-26 43.831074 43.941263 43.365829 43.598451 103626472
2024-07-29 44.222866 44.565677 44.063701 44.516705 39785056
2024-07-30 44.222866 44.394272 43.463779 43.892295 52429524
2024-07-31 44.284081 44.357537 43.733131 43.794348 36314216
2024-08-01 45.055408 45.324763 44.737081 45.300275 56246796
2024-08-02 42.778149 43.806587 42.778149 43.622937 118827260
2024-08-05 38.872536 40.806979 38.786831 40.806979 222308816
2024-08-06 41.015114 41.725225 39.374510 40.966141 252563844
2024-08-07 42.643475 42.790396 41.382414 41.590552 127298960
2024-08-08 41.761955 42.214956 41.382412 41.884388 103364420
2024-08-09 43.059750 43.316856 42.729179 42.851612 93415024
2024-08-12 43.598454 44.026970 43.402560 43.402560 70286956
2024-08-13 43.708641 43.953507 43.586208 43.904535 43433840
2024-08-14 44.259594 44.528948 44.063700 44.161649 74857276
2024-08-15 43.916782 44.320810 43.843322 44.222865 45926588
2024-08-16 44.908485 44.969702 44.651379 44.810540 52823660
2024-08-19 44.969704 45.226814 44.847270 44.932975 37122372
2024-08-20 44.994190 45.349246 44.981946 45.202328 43139504
可見警語消失了, 傳回的 DataFrame 除索引外只有五欄資料, Close 欄位是已還原權息之收盤價.
如果想取得未還原權息之收盤價, 則要傳入 auto_adjust=False, 例如 :
>>> df=yf.download('0050.tw', start='2024-07-01', end='2024-08-21', auto_adjust=False)
[*********************100%***********************] 1 of 1 completed
>>> df
Price Adj Close Close High Low Open Volume
Ticker 0050.TW 0050.TW 0050.TW 0050.TW 0050.TW 0050.TW
Date
2024-07-01 45.692062 46.650002 47.012501 46.562500 46.637501 29279212
2024-07-02 45.385979 46.337502 46.687500 46.125000 46.487499 21777344
2024-07-03 45.936928 46.900002 46.900002 46.599998 46.900002 25915028
2024-07-04 47.136772 48.125000 48.162498 47.650002 47.650002 50576828
2024-07-05 46.965366 47.950001 48.212502 47.887501 48.150002 38933332
2024-07-08 48.446808 49.462502 49.625000 47.962502 47.974998 69409868
2024-07-09 48.397835 49.412498 50.012501 48.862499 49.362499 61955156
2024-07-10 48.569241 49.587502 49.599998 48.750000 49.237499 28674444
2024-07-11 49.646652 50.687500 50.700001 50.000000 50.162498 39186920
2024-07-12 48.079510 49.087502 49.587502 49.000000 49.549999 56633068
2024-07-15 48.165207 49.174999 49.525002 49.025002 49.412498 39160740
2024-07-16 48.201942 49.212502 49.750000 49.000000 49.137501 53022152
2024-07-17 47.528557 48.525002 49.125000 48.400002 49.099998 57959112
2024-07-18 46.671528 47.650002 47.724998 47.049999 47.150002 71520052
2024-07-19 45.606358 46.562500 47.250000 46.549999 47.187500 65815640
2024-07-22 44.247345 45.174999 46.349998 45.012501 46.349998 84847384
2024-07-23 45.618599 46.575001 46.575001 45.924999 45.924999 50108316
2024-07-26 43.831074 44.750000 44.862499 44.275002 44.512501 103626472
2024-07-29 44.222866 45.150002 45.500000 44.987499 45.450001 39785056
2024-07-30 44.222866 45.150002 45.325001 44.375000 44.812500 52429524
2024-07-31 44.284081 45.212502 45.287498 44.650002 44.712502 36314216
2024-08-01 45.055408 46.000000 46.275002 45.674999 46.250000 56246796
2024-08-02 42.778149 43.674999 44.724998 43.674999 44.537498 118827260
2024-08-05 38.872536 39.687500 41.662498 39.599998 41.662498 222308816
2024-08-06 41.015114 41.875000 42.599998 40.200001 41.825001 252563844
2024-08-07 42.643475 43.537498 43.687500 42.250000 42.462502 127298960
2024-08-08 41.761955 42.637501 43.099998 42.250000 42.762501 103364420
2024-08-09 43.059750 43.962502 44.224998 43.625000 43.750000 93415024
2024-08-12 43.598454 44.512501 44.950001 44.312500 44.312500 70286956
2024-08-13 43.708641 44.625000 44.875000 44.500000 44.825001 43433840
2024-08-14 44.259594 45.187500 45.462502 44.987499 45.087502 74857276
2024-08-15 43.916782 44.837502 45.250000 44.762501 45.150002 45926588
2024-08-16 44.908485 45.849998 45.912498 45.587502 45.750000 52823660
2024-08-19 44.969704 45.912498 46.174999 45.787498 45.875000 37122372
2024-08-20 44.994190 45.937500 46.299999 45.924999 46.150002 43139504
可見除索引外有六欄資料, 比傳入 auto_adjust=True 多了一個 Adj Close 欄位 (還原權息之收盤價), 而 Close 欄位則是未還原權息之收盤價.
2. 從多層欄位 DataFrame 取得單層價量資料 :
觀察上面新版 yfinance API 傳回的 DataFrame 可知與舊版的格式不同 (明顯地多了 Ticker 列), 新版的傳回值改用多層欄位 (MultiIndex), 可表示多種維度的資訊使資料結構更有層次, 這對例如分群統計與交叉分析等應用場景的資料處理非常方便, 對於 yfinance 金融資料而言則是可同時下載多檔股票的價格資料, 此功能若使用舊版的單層欄位來做, 欄位名稱會變得很長, 或需要人工加前綴處理,
多層欄位 (MultiIndex) 的第一層是價量資料欄位 (例如 Open, Close, High, Low 等), 第二層是股票代號 (例如 0050.TW), 當下載單一股票後, 檢視傳回值的 columns 屬性可知其值為一個 MultiIndex 物件 (一種 Pandas 的 Index 物件) :
>>> df=yf.download('0050.tw', start='2024-07-01', end='2024-08-21', auto_adjust=False)
[*********************100%***********************] 1 of 1 completed
>>> df.columns
MultiIndex([('Adj Close', '0050.TW'),
( 'Close', '0050.TW'),
( 'High', '0050.TW'),
( 'Low', '0050.TW'),
( 'Open', '0050.TW'),
( 'Volume', '0050.TW')],
names=['Price', 'Ticker'])
可見多層欄位相當於是 tuple 的 list, 此處因為是下載單一股票, 所以第二層的股票代號均為 0050.TW. 同時下載多支股票只要將股票代號以 list 傳入 yf.download() 的第一參數即可 :
>>> df=yf.download(['0050.tw', '0056.tw'], start='2024-07-01', end='2024-08-21', auto_adjust=False)
[*********************100%***********************] 2 of 2 completed
>>> df
Price Adj Close Close ... Open Volume
Ticker 0050.TW 0056.TW 0050.TW ... 0056.TW 0050.TW 0056.TW
Date ...
2024-07-01 45.692062 35.880264 46.650002 ... 41.419998 29279212 68378646
2024-07-02 45.385979 35.663326 46.337502 ... 41.290001 21777344 70261055
... (略) ...
可見股價資料會分層排列, 上層是價量資料欄位, 下層是股票代號 (Ticker 名稱), 檢查 df.columns 屬性即知 :
>>> df.columns
MultiIndex([('Adj Close', '0050.TW'),
('Adj Close', '0056.TW'),
( 'Close', '0050.TW'),
( 'Close', '0056.TW'),
( 'High', '0050.TW'),
( 'High', '0056.TW'),
( 'Low', '0050.TW'),
( 'Low', '0056.TW'),
( 'Open', '0050.TW'),
( 'Open', '0056.TW'),
( 'Volume', '0050.TW'),
( 'Volume', '0056.TW')],
names=['Price', 'Ticker'])
新版 yfinance 傳回的多層欄位 df 資料無法直接丟給 mplfinance 套件去繪製 K 線圖, 必須將傳回值改回單層欄位 (只有價量欄位) 才行, 方法是利用 MultiIndex 物件的 map() 方法遍歷它的類串列元素 (都是 tuple), 然後取出以 lambda 函式取出 tuple 中的第一個元素 (即價量欄位名稱) :
>>> df.columns=df.columns.map(lambda x: x[0])
>>> df.columns
Index(['Adj Close', 'Close', 'High', 'Low', 'Open', 'Volume'], dtype='object')
這樣便將多層欄位改成單層的價量欄位了 :
>>> df.head()
Adj Close Close High Low Open Volume
Date
2024-07-01 45.692062 46.650002 47.012501 46.562500 46.637501 29279212
2024-07-02 45.385979 46.337502 46.687500 46.125000 46.487499 21777344
2024-07-03 45.936928 46.900002 46.900002 46.599998 46.900002 25915028
2024-07-04 47.136772 48.125000 48.162498 47.650002 47.650002 50576828
2024-07-05 46.965366 47.950001 48.212502 47.887501 48.150002 38933332
這個調整後的 df 就可以丟給 mplfinance 繪製 K 線圖了 :
>>> import mplfinance as mpf
>>> color=mpf.make_marketcolors(up='red', down='green', inherit=True)
>>> font={'font.family': 'Microsoft JhengHei'}
>>> style=mpf.make_mpf_style(base_mpf_style='default', marketcolors=color, rc=font)
>>> mpf.plot(df, type='candle', title='台灣五十(0050)', style=style)
也可以用之前寫的 kbar 模組來簡化程式碼 :
>>> import kbar
>>> kb=kbar.KBar(df)
>>> kb.plot()
結果與上圖是一樣的.
參考 :

沒有留言 :
張貼留言