用 Python 通過雅虎財經(jīng)獲取股票數(shù)據(jù)

自從Yahoo! finance(雅虎財經(jīng))部門停止更新了他們的歷史數(shù)據(jù)API,許多依賴它的程序停止工作。yfinance旨在通過提供一種可靠的、線程化的、Python化的方式從下載歷史股票交易市場數(shù)據(jù)來解決這個問題。掃描本文最下方二維碼獲取全部完整源碼和Jupyter Notebook 文件打包下載。
yfinance是什么?
yfinance 是一個流行的開源庫,由 Ran Aroussi 開發(fā),用于訪問雅虎財經(jīng)上可用的財務(wù)數(shù)據(jù)。
雅虎財經(jīng)提供了大量關(guān)于股票、債券、貨幣和加密貨幣的市場數(shù)據(jù)。它還提供市場新聞、報告和分析,以及其他選項和基本面數(shù)據(jù),使其與一些競爭對手區(qū)分開來。

雅虎財經(jīng)曾經(jīng)有自己的官方 API,但在 2017 年 5 月 15 日,由于數(shù)據(jù)被廣泛濫用,該 API 已停用。
如今,存在一系列非官方 API 和庫來訪問相同的數(shù)據(jù),其中包括 yfinance。
yfinance 的舊名稱是 fix-yahoo-finance,它于 2019 年 5 月 26 日重新命名,同時它進行了修改以解決一些可用性問題。
為了確保向后兼容,fix-yahoo-finance 現(xiàn)在無論如何都會導入和使用 yfinance,但 Ran Aroussi 仍然建議直接安裝和使用 yfinance。在本文中,我們將主要關(guān)注 yfinance 庫。
為什么要使用 yfinance 庫?
?免費?快速輕松地進行設(shè)置?簡單?數(shù)據(jù)粒度高(1min/2min/5min數(shù)據(jù))?直接在 Pandas dataframes/series 中返回數(shù)據(jù)
正如我們剛剛提到的 yfinance 是完全開源和免費的。還有其他方法可以訪問雅虎財經(jīng)數(shù)據(jù),有些是免費的,有些是付費的,一些需要付費的選項有一定的好處,比如確保對解決方案進行一定程度的維護,但我們都喜歡免費!
安裝更容易。yfinance 只有 4 個依賴項,所有這些都隨 Anaconda 一起提供,并且完全安裝在一行代碼中。無需創(chuàng)建帳戶,也無需注冊和使用 API 密鑰!
yfinance 的設(shè)計非常 Pythonic,而且非常精簡。就像為特定的股票代碼創(chuàng)建股票代碼對象一樣簡單,然后只需調(diào)用此對象上的所有方法。像這樣:
import yfinance as yfapple= yf.Ticker("aapl")# show actions (dividends, splits)apple.actions# show dividendsapple.dividends# show splitsapple.splits# + other methods etc.
我們稍后會進一步分解該代碼!
此外,文檔簡明扼要 - 適合在單個頁面上,并且方法名稱非常易于解釋。
數(shù)據(jù)粒度高。yfinance 的一個很酷的功能是您可以獲得高度精煉的數(shù)據(jù),一直到 5 分鐘、3 分鐘甚至 1 分鐘的數(shù)據(jù)!可用的全范圍間隔是:
1m, 2m, 5m, 15m, 30m, 60m, 90m, 1h, 1d, 5d, 1wk, 1mo, 3mo然而,重要的是要注意 1m 數(shù)據(jù)只能檢索最近 7 天的數(shù)據(jù),而任何日內(nèi)(間隔 <1d)數(shù)據(jù)只能檢索最近 60 天。
yfinance 還可以輕松地直接在 padas dataframes 或者 series中返回數(shù)據(jù)。這與訪問 Yahoo Finance 數(shù)據(jù)的一些選項形成對比,在這些選項中,您將獲得需要解析所需特定信息的冗長 JSON,并且必須自己手動轉(zhuǎn)換為dataframes。
yfinance 庫有哪些不足?
?缺乏專業(yè)功能?非官方/不一定維護?可以讓自己限速/列入黑名單
缺乏專門的功能。盡管您可以使用它來獲取大量核心數(shù)據(jù),包括期權(quán)和基本面數(shù)據(jù),但 yfinance 沒有提供一種方法來抓取雅虎財經(jīng)上可用的任何新聞報道/分析。
如果您想構(gòu)建部分依賴于情感分析的模型,這顯然并不理想,因此如果您想要此類數(shù)據(jù),您可能需要查看提供此類數(shù)據(jù)的 RapidAPI。
此外,其他市場數(shù)據(jù)替代品通常包括一些額外內(nèi)容。例如,Alpha Vantage 為您提供了計算各種技術(shù)分析指標的模塊——如果您想使用其中的任何一個構(gòu)建算法,顯然會節(jié)省大量的精力!yfinance 只提供基礎(chǔ)知識。
yfinance 主要調(diào)用 Yahoo Finance 的 API 來收集它的數(shù)據(jù),但它偶爾也會使用 HTML 抓取和 Pandas 表抓取方法來非正式地從 Yahoo Finance 網(wǎng)站上收集一些信息。因此,它的某些方法的功能受雅虎的支配,不會更改其某些頁面的布局或設(shè)計。
順便說一句,數(shù)據(jù)抓取的工作原理是簡單地下載網(wǎng)頁的 HTML 代碼,然后搜索所有 HTML 標簽以找到所需頁面的特定元素。
例如,以下是雅虎財經(jīng) Apple (‘AAPL’) 的歷史數(shù)據(jù)頁面:

如果獲取歷史數(shù)據(jù)HTML的方法是爬取的,那就是在各個div、class、tr標簽等各種ID中查找需要返回的數(shù)據(jù)。
例如,類 ID“Py(10px) Pstart(10px)”指的是填充表格的歷史價格。如果在這種情況下 Yahoo Finance 要更改指向此值的類 ID,則該方法可能會返回完全錯誤的數(shù)據(jù),甚至根本不返回任何數(shù)據(jù)。同樣,這種漏洞并不適用于 yfinance 的所有方法——它們中的大多數(shù)實際上都進行了直接的 API 調(diào)用。
這是一個非官方的解決方案。同樣,因為 yfinance 只是一個人努力工作的結(jié)果,與雅虎財經(jīng)沒有任何關(guān)聯(lián),所以不能保證它是否會被維護。
正如我們已經(jīng)提到的,它確實在 2019 年 5 月 26 日在重命名的同一天進行了重大更新以修復問題,但這并不能保證將來會修復問題。yfinance 已經(jīng)存在一些已知問題,我們將在本文后面重點介紹。
由于 yfinance 會為其中的一些功能抓取數(shù)據(jù),因此您有時會因過多的抓取嘗試而面臨速率受限或被列入黑名單的風險。
總體而言,yfinance 是一個非常適合初學者的選擇。您將能夠直接深入并測試想法,而不會浪費時間對復雜的文檔感到困惑,同時仍然可以訪問大量數(shù)據(jù)!
yfinance的安裝
yfinance 庫的入門非常簡單。它具有以下依賴項:
?pandas >= 0.24?numpy >= 1.15?requests >= 2.21?multitasking >= 0.0.7
這些都是 Anaconda 安裝的標準配置,手動安裝也很容易。之后的安裝yfinance的操作就這么簡單:
pip install yfinance --upgrade --no-cache-dir或者
conda install -c ranaroussi yfinanceLibrary布局
布局本身也很簡單,只有三個模塊:
?yf.Tickers?yf.download?yf.pandas_datareader
幾乎所有的方法都在 Tickers 模塊中。
download模塊用于一次性快速下載多個股票的歷史數(shù)據(jù)。
pandas_datareader 是為了與遺留代碼向后兼容,對新用戶而言我們將忽略它。
用yfinance庫下載歷史數(shù)據(jù)
首先,讓我們將 yfinance 導入為 yf 并為特定代碼(股票)創(chuàng)建一個代碼對象:
import yfinance as yfaapl= yf.Ticker("aapl")aapl
yfinance.Ticker object <AAPL>我們現(xiàn)在都用這個 aapl 股票代碼對象——在其上調(diào)用各種方法。要獲取歷史數(shù)據(jù),可以使用 history() 方法。
它采用以下參數(shù)作為輸入:
?period:要下載的數(shù)據(jù)周期(使用周期參數(shù)或使用start和end),有效周期為:
“1d”、“5d”、“1mo”、“3mo”、“6mo”、“1y”、“2y”、“5y”、“10y”、“ytd”、“max”?interval:數(shù)據(jù)間隔(1m 數(shù)據(jù)僅適用于最近 7 天的數(shù)據(jù),最近 60 天的數(shù)據(jù)間隔 <1d),有效間隔為:
“1m”、“2m”、“5m”、“15m”、“30m”、“60m”、“90m”、“1h”、“1d”、“5d”、“1wk”、“1mo”、“3mo” ”?start:格式為 (yyyy-mm-dd) 或日期時間。?end: 格式為 (yyyy-mm-dd) 或日期時間。?prepost:在結(jié)果中包涵 Pre 和 Post 常規(guī)市場數(shù)據(jù)(默認為 False)- 通常不需要將其從 False 更改。?auto_adjust:自動調(diào)整所有 OHLC(開盤價/最高價/最低價/收盤價)(默認為 True)。?actions:下載股票分紅和股票分割事件 (默認為True)。
您只需更改period(或者start和end)和間隔參數(shù)。
例如,要獲取 Apple 在 02/06/2020 和 07/06/2020(英國格式)之間的 1 分鐘歷史數(shù)據(jù),我們只需使用我們創(chuàng)建并運行的股票代碼對象:
aapl_historical = aapl.history(start="2020-06-02", end="2020-06-07", interval="1m")aapl_historical

多個股票代碼的demo
要一次下載多個股票的歷史數(shù)據(jù),您可以使用download模塊。
它采用與股票代碼上的 history() 方法大致相同的參數(shù),其他參數(shù)如下:
?group_by:按列或股票代碼分組(‘column’/‘ticker’,默認為‘column’)?threads:使用線程進行大規(guī)模下載(True/False/Integer)?proxy:如果要使用代理服務(wù)器下載數(shù)據(jù)的代理 URL(可選,默認為 None)
例如,要一次性獲取 Amazon、Apple 和 Google 的數(shù)據(jù),我們可以運行:
data = yf.download("AMZN AAPL GOOG", start="2017-01-01", end="2017-04-30")data

請注意,未指定間隔的默認值是每日數(shù)據(jù)。
然后,如果我們想按股票代碼而不是開盤價/最高價/最低價/收盤價進行分組,我們可以這樣做:
data = yf.download("AMZN AAPL GOOG", start="2017-01-01",end="2017-04-30", group_by='tickers')data

用 yfinance 庫下載基本數(shù)據(jù)
市盈率
您可以使用 Ticker.info()方法獲得市盈率。
Ticker.info() 返回一個包含有關(guān)股票代碼的廣泛信息的字典,包括摘要描述、員工數(shù)量、市值、交易量、市盈率、股息等 !
要具體獲得市盈率,請在字典中搜索“forwardPE”:
aapl = yf.Ticker("aapl")aapl.info['forwardPE']
22.799461
股息
您也可以使用 info() 獲得年度股息百分比:
aapl.info['dividendRate']3.2800000000000002
如果您想在發(fā)生的日期對每筆股息支付進行細分,您可以使用 Ticker.dividends():
aapl.dividendsDate1987-05-11 0.002141987-08-10 0.002141987-11-17 0.002861988-02-12 0.002861988-05-16 0.00286...2019-05-10 0.770002019-08-09 0.770002019-11-07 0.770002020-02-07 0.770002020-05-08 0.82000Name: Dividends, Length: 67, dtype: float64
一次操作多個股票代碼的基本數(shù)據(jù)
我們可能還想一次獲取一堆股票的基本面數(shù)據(jù),可以嘗試通過特定屬性比較股票代碼!
為此,我們可以首先創(chuàng)建一個我們想要獲取數(shù)據(jù)的股票代碼列表,以及一個空字典來存儲所有數(shù)據(jù)。
我們需要使用 pandas 庫來操作數(shù)據(jù)框:
import pandas as pdtickers_list = ["aapl", "goog", "amzn", "BAC", "BA"] # example listtickers_data= {} # empty dictionary
然后我們循環(huán)遍歷股票行情列表,在每種情況下向我們的字典添加一個鍵值對,其中鍵是股票行情,而值是該股票行情的 info()方法返回的數(shù)據(jù)幀:
for ticker in tickers_list:ticker_object = yf.Ticker(ticker)#convert info() output from dictionary to dataframetemp = pd.DataFrame.from_dict(ticker_object.info, orient="index")temp.reset_index(inplace=True)temp.columns = ["Attribute", "Recent"]# add (ticker, dataframe) to main dictionarytickers_data[ticker] = temptickers_data

然后我們將這個數(shù)據(jù)幀字典組合成一個數(shù)據(jù)幀:
combined_data = pd.concat(tickers_data)combined_data = combined_data.reset_index()combined_data

然后刪除不必要的“l(fā)evel_1”列并清理列名:
del combined_data["level_1"] # clean up unnecessary columncombined_data.columns = ["Ticker", "Attribute", "Recent"] # update column namescombined_data

所以我們現(xiàn)在知道如何將我們想要的多個股票代碼的任何數(shù)據(jù)一次獲取到同一個數(shù)據(jù)幀中!
但是我們?nèi)绾屋p松地通過特定屬性進行比較?
按特定屬性進行比較
實際上很容易,讓我們嘗試使用 info() 中的屬性之一——fullTimeEmployees:
employees = combined_data[combined_data["Attribute"]=="fullTimeEmployees"].reset_index()del employees["index"] # clean up unnecessary columnemployees

所以現(xiàn)在我們有一個只有員工計數(shù)的數(shù)據(jù)框——每個代碼一個條目——我們現(xiàn)在可以按“最近”列排序:
employees_sorted = employees.sort_values('Recent',ascending=False)employees_sorted

顯然,我們的列表中只有 5 個股票代碼,這顯然不是必需的,但如果我們擁有整個市場的股票代碼列表,則可以通過特定屬性快速進行比較,這是一種非常簡單和強大的方法!
您可以輕松地使用這種完全相同的方法來比較您想要的任何屬性!
用 yfinance 庫下載交易數(shù)據(jù)
您可以從 info() 方法中找到市值、成交量和最高價和最低價這三者的數(shù)據(jù)。
市值
要獲得市值,請使用:
aapl.info["marketCap"]1525510701056交易量
要查找當前交易量,請執(zhí)行以下操作:
aapl.info["volume"]8021292如果您想要過去 24 小時的平均交易量,請執(zhí)行以下操作:
aapl.info["averageVolume"]42532806最后,如果您想要過去 10 天的平均交易量:
aapl.info["averageVolume10days"]39594100最高值和最低值
請記住,您可以找到任何時間間隔的高點和低點:
“1m”、“2m”、“5m”、“15m”、“30m”、“60m”、“90m”、“1h”、“1d”、“5d”、“1wk”、“1mo”、“3mo” ”通過使用 history() 方法并調(diào)整間隔,在所需的時間段內(nèi)。
例如,要獲取所有存在的歷史數(shù)據(jù)的每周高點和低點,請使用:
aapl_historical = aapl.history(period="max", interval="1wk")aapl_historical

我們獲得了幾乎40年的數(shù)據(jù),只需要在dataframe后添加下面屬性:
?aapl_historical[“High”]?aapl_historical[“Low”]
依此類推以獲取各個列。或者,您可以使用 info() 獲取以下有用的高點/低點信息:
?dayHigh?dayLow?fiftyTwoWeekHigh?fiftyTwoWeekLow
例如:
aapl.info["fiftyTwoWeekHigh"]354.77用 yfinance 庫下載期權(quán)數(shù)據(jù)
簡而言之,期權(quán)是賦予交易者權(quán)利但沒有義務(wù)在特定日期或之前以特定價格購買(看漲)或出售(看跌)他們所代表的標的資產(chǎn)的合約。
要下載選項數(shù)據(jù),我們可以使用 option_chain() 方法。它將參數(shù)作為輸入:
?date:(YYYY-MM-DD),到期日。如果 None 返回所有期權(quán)數(shù)據(jù)。
并且有 opt.calls 和 opt.puts 方法。
如何獲得到期日期
要獲得特定股票期權(quán)的各種到期日期,就像:
aapl.options
如何獲取對話數(shù)據(jù)
要獲取對話數(shù)據(jù),我們可以執(zhí)行以下操作:
# get option chain calls data for specific expiration dateopt = aapl.option_chain(date='2020-07-24')opt.calls

如何獲得看跌期權(quán)數(shù)據(jù)
要獲取看跌期權(quán)數(shù)據(jù),我們執(zhí)行以下操作:
opt.puts
最后, opts 本身會返回一個包含調(diào)用和將數(shù)據(jù)放在一起的代碼對象。
總結(jié)
正如我們在本文開頭強調(diào)的那樣,yfinance 是一種從雅虎財經(jīng)收集數(shù)據(jù)的非官方抓取解決方案,因此如果雅虎財經(jīng)更改其任何布局,則可能會中斷。
在編寫本指南時發(fā)現(xiàn)了以下問題:
?Tickers,用于同時與多個代碼交互的多個代碼對象,似乎不起作用。我們在“同時具有多個代碼的基本面數(shù)據(jù)”部分中為此提供了一種更手動的解決方法。?財務(wù)、季度財務(wù)、資產(chǎn)負債表、季度資產(chǎn)負債表、現(xiàn)金流、季度現(xiàn)金流、收益、季度收入股票代碼方法不起作用并返回空數(shù)據(jù)幀。這是一個大問題,因為在許多情況下,yfinance 中的其他方法無法替代其中某些方法中的數(shù)據(jù)。
如果您正在構(gòu)建需要任何此類數(shù)據(jù)的東西,例如資產(chǎn)負債表、收入和現(xiàn)金流量表,并且仍然希望免費訪問雅虎財經(jīng)數(shù)據(jù),請查看我們指南 https://algotrading101 示例部分中的 yahoo_fin 庫。com/learn/yahoo-finance-api/ 有獲取所有這些數(shù)據(jù)的工作方法!
作為初學者,yfinance 可以很好地用于構(gòu)建測試應(yīng)用程序,因為它的工作部分非常容易上手和使用。
yfinance 的一個特別長處是 yf.download 的threads參數(shù)在設(shè)置為True時確實允許非常快速地下載多個股票的歷史!

E N D

