用 Python 通过雅虎财经获取股票数据
自从Yahoo! finance(雅虎财经)部门停止更新了他们的历史数据API,许多依赖它的程序停止工作。yfinance旨在通过提供一种可靠的、线程化的、Python化的方式从下载历史股票交易市场数据来解决这个问题。扫描本文最下方二维码获取全部完整源码和Jupyter Notebook 文件打包下载。
yfinance是什么?
yfinance 是一个流行的开源库,由 Ran Aroussi 开发,用于访问雅虎财经上可用的财务数据。
雅虎财经提供了大量关于股票、债券、货币和加密货币的市场数据。它还提供市场新闻、报告和分析,以及其他选项和基本面数据,使其与一些竞争对手区分开来。
雅虎财经曾经有自己的官方 API,但在 2017 年 5 月 15 日,由于数据被广泛滥用,该 API 已停用。
如今,存在一系列非官方 API 和库来访问相同的数据,其中包括 yfinance。
yfinance
的旧名称是 fix-yahoo-finance
,它于 2019 年 5 月 26 日重新命名,同时它进行了修改以解决一些可用性问题。
为了确保向后兼容,fix-yahoo-finance
现在无论如何都会导入和使用 yfinance,但 Ran Aroussi 仍然建议直接安装和使用 yfinance。在本文中,我们将主要关注 yfinance 库。
为什么要使用 yfinance 库?
•免费•快速轻松地进行设置•简单•数据粒度高(1min/2min/5min数据)•直接在 Pandas dataframes/series 中返回数据
正如我们刚刚提到的 yfinance 是完全开源和免费的。还有其他方法可以访问雅虎财经数据,有些是免费的,有些是付费的,一些需要付费的选项有一定的好处,比如确保对解决方案进行一定程度的维护,但我们都喜欢免费!
安装更容易。yfinance 只有 4 个依赖项,所有这些都随 Anaconda 一起提供,并且完全安装在一行代码中。无需创建帐户,也无需注册和使用 API 密钥!
yfinance 的设计非常 Pythonic,而且非常精简。就像为特定的股票代码创建股票代码对象一样简单,然后只需调用此对象上的所有方法。像这样:
import yfinance as yf
apple= yf.Ticker("aapl")
# show actions (dividends, splits)
apple.actions
# show dividends
apple.dividends
# show splits
apple.splits
# + other methods etc.
我们稍后会进一步分解该代码!
此外,文档简明扼要 - 适合在单个页面上,并且方法名称非常易于解释。
数据粒度高。yfinance 的一个很酷的功能是您可以获得高度精炼的数据,一直到 5 分钟、3 分钟甚至 1 分钟的数据!可用的全范围间隔是:
1m, 2m, 5m, 15m, 30m, 60m, 90m, 1h, 1d, 5d, 1wk, 1mo, 3mo
然而,重要的是要注意 1m 数据只能检索最近 7 天的数据,而任何日内(间隔 <1d)数据只能检索最近 60 天。
yfinance 还可以轻松地直接在 padas dataframes 或者 series中返回数据。这与访问 Yahoo Finance 数据的一些选项形成对比,在这些选项中,您将获得需要解析所需特定信息的冗长 JSON,并且必须自己手动转换为dataframes。
yfinance 库有哪些不足?
•缺乏专业功能•非官方/不一定维护•可以让自己限速/列入黑名单
缺乏专门的功能。尽管您可以使用它来获取大量核心数据,包括期权和基本面数据,但 yfinance 没有提供一种方法来抓取雅虎财经上可用的任何新闻报道/分析。
如果您想构建部分依赖于情感分析的模型,这显然并不理想,因此如果您想要此类数据,您可能需要查看提供此类数据的 RapidAPI
。
此外,其他市场数据替代品通常包括一些额外内容。例如,Alpha Vantage 为您提供了计算各种技术分析指标的模块——如果您想使用其中的任何一个构建算法,显然会节省大量的精力!yfinance 只提供基础知识。
yfinance 主要调用 Yahoo Finance 的 API 来收集它的数据,但它偶尔也会使用 HTML 抓取和 Pandas 表抓取方法来非正式地从 Yahoo Finance 网站上收集一些信息。因此,它的某些方法的功能受雅虎的支配,不会更改其某些页面的布局或设计。
顺便说一句,数据抓取的工作原理是简单地下载网页的 HTML 代码,然后搜索所有 HTML 标签以找到所需页面的特定元素。
例如,以下是雅虎财经 Apple (‘AAPL’) 的历史数据页面:
如果获取历史数据HTML的方法是爬取的,那就是在各个div
、class
、tr
标签等各种ID中查找需要返回的数据。
例如,类 ID“Py(10px) Pstart(10px)”
指的是填充表格的历史价格。如果在这种情况下 Yahoo Finance 要更改指向此值的类 ID,则该方法可能会返回完全错误的数据,甚至根本不返回任何数据。同样,这种漏洞并不适用于 yfinance 的所有方法——它们中的大多数实际上都进行了直接的 API 调用。
这是一个非官方的解决方案。同样,因为 yfinance 只是一个人努力工作的结果,与雅虎财经没有任何关联,所以不能保证它是否会被维护。
正如我们已经提到的,它确实在 2019 年 5 月 26 日在重命名的同一天进行了重大更新以修复问题,但这并不能保证将来会修复问题。yfinance 已经存在一些已知问题,我们将在本文后面重点介绍。
由于 yfinance 会为其中的一些功能抓取数据,因此您有时会因过多的抓取尝试而面临速率受限或被列入黑名单的风险。
总体而言,yfinance 是一个非常适合初学者的选择。您将能够直接深入并测试想法,而不会浪费时间对复杂的文档感到困惑,同时仍然可以访问大量数据!
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 yfinance
Library
布局
布局本身也很简单,只有三个模块:
•yf.Tickers•yf.download•yf.pandas_datareader
几乎所有的方法都在 Tickers
模块中。
download
模块用于一次性快速下载多个股票的历史数据。
pandas_datareader
是为了与遗留代码向后兼容,对新用户而言我们将忽略它。
用yfinance库下载历史数据
首先,让我们将 yfinance 导入为 yf 并为特定代码(股票)创建一个代码对象:
import yfinance as yf
aapl= yf.Ticker("aapl")
aapl
yfinance.Ticker object <AAPL>
我们现在都用这个 aapl 股票代码对象——在其上调用各种方法。要获取历史数据,可以使用 history()
方法。
它采用以下参数作为输入:
•period
:要下载的数据周期(使用周期参数或使用start
和end
),有效周期为:
“1d”、“5d”、“1mo”、“3mo”、“6mo”、“1y”、“2y”、“5y”、“10y”、“ytd”、“max”
•interval
:数据间隔(1m 数据仅适用于最近 7 天的数据,最近 60 天的数据间隔 <1d),有效间隔为:
“1m”、“2m”、“5m”、“15m”、“30m”、“60m”、“90m”、“1h”、“1d”、“5d”、“1wk”、“1mo”、“3mo” ”
•start
:格式为 (yyyy-mm-dd) 或日期时间。•end
: 格式为 (yyyy-mm-dd) 或日期时间。•prepost
:在结果中包涵 Pre
和 Post
常规市场数据(默认为 False)- 通常不需要将其从 False 更改。•auto_adjust
:自动调整所有 OHLC(开盘价/最高价/最低价/收盘价)(默认为 True)。•actions
:下载股票分红和股票分割事件 (默认为True
)。
您只需更改period
(或者start
和end
)和间隔参数。
例如,要获取 Apple 在 02/06/2020 和 07/06/2020(英国格式)之间的 1 分钟历史数据,我们只需使用我们创建并运行的股票代码对象:
aapl_historical = aapl.history(start="2020-06-02", end="2020-06-07", interval="1m")
aapl_historical
多个股票代码的demo
要一次下载多个股票的历史数据,您可以使用download
模块。
它采用与股票代码上的 history()
方法大致相同的参数,其他参数如下:
•group_by
:按列或股票代码分组(‘column’/‘ticker’
,默认为‘column’
)•threads
:使用线程进行大规模下载(True/False/Integer
)•proxy
:如果要使用代理服务器下载数据的代理 URL(可选,默认为 None)
例如,要一次性获取 Amazon、Apple 和 Google 的数据,我们可以运行:
data = yf.download("AMZN AAPL GOOG", start="2017-01-01", end="2017-04-30")
data
请注意,未指定间隔的默认值是每日数据。
然后,如果我们想按股票代码而不是开盘价/最高价/最低价/收盘价进行分组,我们可以这样做:
data = yf.download("AMZN AAPL GOOG", start="2017-01-01",
end="2017-04-30", group_by='tickers')
data
用 yfinance 库下载基本数据
市盈率
您可以使用 Ticker.info()
方法获得市盈率。
Ticker.info()
返回一个包含有关股票代码的广泛信息的字典,包括摘要描述、员工数量、市值、交易量、市盈率、股息等 !
要具体获得市盈率,请在字典中搜索“forwardPE”
:
aapl = yf.Ticker("aapl")
aapl.info['forwardPE']
22.799461
股息
您也可以使用 info()
获得年度股息百分比:
aapl.info['dividendRate']
3.2800000000000002
如果您想在发生的日期对每笔股息支付进行细分,您可以使用 Ticker.dividends()
:
aapl.dividends
Date
1987-05-11 0.00214
1987-08-10 0.00214
1987-11-17 0.00286
1988-02-12 0.00286
1988-05-16 0.00286
...
2019-05-10 0.77000
2019-08-09 0.77000
2019-11-07 0.77000
2020-02-07 0.77000
2020-05-08 0.82000
Name: Dividends, Length: 67, dtype: float64
一次操作多个股票代码的基本数据
我们可能还想一次获取一堆股票的基本面数据,可以尝试通过特定属性比较股票代码!
为此,我们可以首先创建一个我们想要获取数据的股票代码列表,以及一个空字典来存储所有数据。
我们需要使用 pandas 库来操作数据框:
import pandas as pd
tickers_list = ["aapl", "goog", "amzn", "BAC", "BA"] # example list
tickers_data= {} # empty dictionary
然后我们循环遍历股票行情列表,在每种情况下向我们的字典添加一个键值对,其中键是股票行情,而值是该股票行情的 info()
方法返回的数据帧:
for ticker in tickers_list:
ticker_object = yf.Ticker(ticker)
#convert info() output from dictionary to dataframe
temp = pd.DataFrame.from_dict(ticker_object.info, orient="index")
temp.reset_index(inplace=True)
temp.columns = ["Attribute", "Recent"]
# add (ticker, dataframe) to main dictionary
tickers_data[ticker] = temp
tickers_data
然后我们将这个数据帧字典组合成一个数据帧:
combined_data = pd.concat(tickers_data)
combined_data = combined_data.reset_index()
combined_data
然后删除不必要的“level_1”列并清理列名:
del combined_data["level_1"] # clean up unnecessary column
combined_data.columns = ["Ticker", "Attribute", "Recent"] # update column names
combined_data
所以我们现在知道如何将我们想要的多个股票代码的任何数据一次获取到同一个数据帧中!
但是我们如何轻松地通过特定属性进行比较?
按特定属性进行比较
实际上很容易,让我们尝试使用 info()
中的属性之一——fullTimeEmployees
:
employees = combined_data[combined_data["Attribute"]=="fullTimeEmployees"].reset_index()
del employees["index"] # clean up unnecessary column
employees
所以现在我们有一个只有员工计数的数据框——每个代码一个条目——我们现在可以按“最近”列排序:
employees_sorted = employees.sort_values('Recent',ascending=False)
employees_sorted
显然,我们的列表中只有 5 个股票代码,这显然不是必需的,但如果我们拥有整个市场的股票代码列表,则可以通过特定属性快速进行比较,这是一种非常简单和强大的方法!
您可以轻松地使用这种完全相同的方法来比较您想要的任何属性!
用 yfinance 库下载交易数据
您可以从 info()
方法中找到市值、成交量和最高价和最低价这三者的数据。
市值
要获得市值,请使用:
aapl.info["marketCap"]
1525510701056
交易量
要查找当前交易量,请执行以下操作:
aapl.info["volume"]
8021292
如果您想要过去 24 小时的平均交易量,请执行以下操作:
aapl.info["averageVolume"]
42532806
最后,如果您想要过去 10 天的平均交易量:
aapl.info["averageVolume10days"]
39594100
最高值和最低值
请记住,您可以找到任何时间间隔的高点和低点:
“1m”、“2m”、“5m”、“15m”、“30m”、“60m”、“90m”、“1h”、“1d”、“5d”、“1wk”、“1mo”、“3mo” ”
通过使用 history()
方法并调整间隔,在所需的时间段内。
例如,要获取所有存在的历史数据的每周高点和低点,请使用:
aapl_historical = aapl.history(period="max", interval="1wk")
aapl_historical
我们获得了几乎40年的数据,只需要在dataframe后添加下面属性:
•aapl_historical[“High”]
•aapl_historical[“Low”]
依此类推以获取各个列。或者,您可以使用 info()
获取以下有用的高点/低点信息:
•dayHigh
•dayLow
•fiftyTwoWeekHigh
•fiftyTwoWeekLow
例如:
aapl.info["fiftyTwoWeekHigh"]
354.77
用 yfinance 库下载期权数据
简而言之,期权是赋予交易者权利但没有义务在特定日期或之前以特定价格购买(看涨)或出售(看跌)他们所代表的标的资产的合约。
要下载选项数据,我们可以使用 option_chain()
方法。它将参数作为输入:
•date
:(YYYY-MM-DD),到期日。如果 None 返回所有期权数据。
并且有 opt.calls
和 opt.puts
方法。
如何获得到期日期
要获得特定股票期权的各种到期日期,就像:
aapl.options
如何获取对话数据
要获取对话数据,我们可以执行以下操作:
# get option chain calls data for specific expiration date
opt = aapl.option_chain(date='2020-07-24')
opt.calls
如何获得看跌期权数据
要获取看跌期权数据,我们执行以下操作:
opt.puts
最后, opts
本身会返回一个包含调用和将数据放在一起的代码对象。
总结
正如我们在本文开头强调的那样,yfinance
是一种从雅虎财经收集数据的非官方抓取解决方案,因此如果雅虎财经更改其任何布局,则可能会中断。
在编写本指南时发现了以下问题:
•Tickers,用于同时与多个代码交互的多个代码对象,似乎不起作用。我们在“同时具有多个代码的基本面数据”部分中为此提供了一种更手动的解决方法。•财务、季度财务、资产负债表、季度资产负债表、现金流、季度现金流、收益、季度收入股票代码方法不起作用并返回空数据帧。这是一个大问题,因为在许多情况下,yfinance 中的其他方法无法替代其中某些方法中的数据。
如果您正在构建需要任何此类数据的东西,例如资产负债表、收入和现金流量表,并且仍然希望免费访问雅虎财经数据,请查看我们指南 https://algotrading101 示例部分中的 yahoo_fin
库。com/learn/yahoo-finance-api/ 有获取所有这些数据的工作方法!
作为初学者,yfinance 可以很好地用于构建测试应用程序,因为它的工作部分非常容易上手和使用。
yfinance 的一个特别长处是 yf.download
的threads
参数在设置为True
时确实允许非常快速地下载多个股票的历史!
E N D