从Yahoo Finance一次下载多只股票

18

我有一个关于使用pandas数据读取器的Yahoo Finance功能的问题。我现在已经使用了几个月的股票代码列表,并在以下行中执行:

import pandas_datareader as pdr
import datetime

stocks = ["stock1","stock2",....]
start = datetime.datetime(2012,5,31)
end = datetime.datetime(2018,3,1)

f = pdr.DataReader(stocks, 'yahoo',start,end)

从昨天开始,我一直遇到错误"IndexError: list index out of range",只有在我尝试获取多个股票时才会出现。

最近有什么变化需要考虑吗?或者您有更好的解决方案来解决我的问题吗?

5个回答

16

截至2021年1月19日更新

tickers = ['msft', 'aapl', 'intc', 'tsm', 'goog', 'amzn', 'fb', 'nvda']
df = pdr.DataReader(tickers, data_source='yahoo', start='2017-01-01', end='2020-09-28')

原始答案

如果你仔细阅读Pandas DataReader的文档,你会发现他们对多个数据源API进行了立即弃用,其中之一就是Yahoo! Finance。

v0.6.0(2018年1月24日)

立即弃用Yahoo!Google OptionsQuotes以及EDGAR。 这些API背后的端点已经发生了根本性的变化,现有的读取器需要完全重写。在大多数Yahoo!数据的情况下,端点已被删除。PDR希望恢复这些功能,并欢迎拉取请求。

这可能是你一直收到IndexError(或其他通常不存在的错误)的原因。


然而,还有另一个 Python 包的目标是修复 Pandas DataReader 对 Yahoo! Finance 的支持,你可以在这里找到那个包:

https://pypi.python.org/pypi/fix-yahoo-finance

根据其文档:

Yahoo! finance已停用其历史数据API,导致很多依赖它的程序停止工作。

fix-yahoo-finance通过从Yahoo!finance中抓取数据并返回与pandas_datareaderget_data_yahoo()相同格式的Pandas DataFrame/Panel来提供临时解决方案。

通过基本上“劫持”pandas_datareader.data.get_data_yahoo()方法,只需要将fix_yahoo_finance导入您的代码即可轻松实现fix-yahoo-finance的实施。

你所需要添加的就是这个:

from pandas_datareader import data as pdr
import fix_yahoo_finance as yf

yf.pdr_override() 

stocks = ["stock1","stock2", ...]
start = datetime.datetime(2012,5,31)
end = datetime.datetime(2018,3,1)

f = pdr.get_data_yahoo(stocks, start=start, end=end)

或者不使用Pandas DataReader:

import fix_yahoo_finance as yf

stocks = ["stock1","stock2", ...]
start = datetime.datetime(2012,5,31)
end = datetime.datetime(2018,3,1)
data = yf.download(stocks, start=start, end=end)

能否更改返回的数据的时间框架/频率/间隔?我需要90分钟的收盘价。 - Bidstrup
当使用Pandas Datareader从Yahoo Finance获取股票数据时,出现错误“TypeError:string indices must be integers”,已经得到解决。详情请参见[https://dev59.com/ylEG5IYBdhLWcg3wHEJo]。 - Trenton McKinney

7
您可以使用新的Python YahooFinancials模块与pandas一起完成此操作。YahooFinancials构建良好,通过哈希化每个Yahoo Finance网页中存在的数据存储对象来获取数据,因此速度快,并且不依赖于旧的已停用api或像爬虫那样的Web驱动程序。数据以JSON格式返回,并且您可以通过传递股票/指数代号列表来初始化YahooFinancials Class并一次性提取尽可能多的股票。 $ pip install yahoofinancials
用法示例:
from yahoofinancials import YahooFinancials
import pandas as pd

# Select Tickers and stock history dates
ticker = 'AAPL'
ticker2 = 'MSFT'
ticker3 = 'INTC'
index = '^NDX'
freq = 'daily'
start_date = '2012-10-01'
end_date = '2017-10-01'


# Function to clean data extracts
def clean_stock_data(stock_data_list):
    new_list = []
    for rec in stock_data_list:
        if 'type' not in rec.keys():
            new_list.append(rec)
    return new_list

# Construct yahoo financials objects for data extraction
aapl_financials = YahooFinancials(ticker)
mfst_financials = YahooFinancials(ticker2)
intl_financials = YahooFinancials(ticker3)
index_financials = YahooFinancials(index)

# Clean returned stock history data and remove dividend events from price history
daily_aapl_data = clean_stock_data(aapl_financials
                                     .get_historical_stock_data(start_date, end_date, freq)[ticker]['prices'])
daily_msft_data = clean_stock_data(mfst_financials
                                     .get_historical_stock_data(start_date, end_date, freq)[ticker2]['prices'])
daily_intl_data = clean_stock_data(intl_financials
                                     .get_historical_stock_data(start_date, end_date, freq)[ticker3]['prices'])
daily_index_data = index_financials.get_historical_stock_data(start_date, end_date, freq)[index]['prices']
stock_hist_data_list = [{'NDX': daily_index_data}, {'AAPL': daily_aapl_data}, {'MSFT': daily_msft_data},
                        {'INTL': daily_intl_data}]


# Function to construct data frame based on a stock and it's market index
def build_data_frame(data_list1, data_list2, data_list3, data_list4):
    data_dict = {}
    i = 0
    for list_item in data_list2:
        if 'type' not in list_item.keys():
            data_dict.update({list_item['formatted_date']: {'NDX': data_list1[i]['close'], 'AAPL': list_item['close'],
                                                            'MSFT': data_list3[i]['close'],
                                                            'INTL': data_list4[i]['close']}})
            i += 1
    tseries = pd.to_datetime(list(data_dict.keys()))
    df = pd.DataFrame(data=list(data_dict.values()), index=tseries,
                      columns=['NDX', 'AAPL', 'MSFT', 'INTL']).sort_index()
    return df

一次性获取多只股票的数据示例(返回每个代码的JSON对象列表):

from yahoofinancials import YahooFinancials

tech_stocks = ['AAPL', 'MSFT', 'INTC']
bank_stocks = ['WFC', 'BAC', 'C']

yahoo_financials_tech = YahooFinancials(tech_stocks)
yahoo_financials_banks = YahooFinancials(bank_stocks)

tech_cash_flow_data_an = yahoo_financials_tech.get_financial_stmts('annual', 'cash')
bank_cash_flow_data_an = yahoo_financials_banks.get_financial_stmts('annual', 'cash')

banks_net_ebit = yahoo_financials_banks.get_ebit()
tech_stock_price_data = tech_cash_flow_data.get_stock_price_data()
daily_bank_stock_prices = yahoo_financials_banks.get_historical_stock_data('2008-09-15', '2017-09-15', 'daily')

JSON输出示例:

代码:

yahoo_financials = YahooFinancials('WFC')
print(yahoo_financials.get_historical_stock_data("2017-09-10", "2017-10-10", "monthly"))

JSON返回:

{
    "WFC": {
        "prices": [
            {
                "volume": 260271600,
                "formatted_date": "2017-09-30",
                "high": 55.77000045776367,
                "adjclose": 54.91999816894531,
                "low": 52.84000015258789,
                "date": 1506830400,
                "close": 54.91999816894531,
                "open": 55.15999984741211
            }
        ],
        "eventsData": [],
        "firstTradeDate": {
            "date": 76233600,
            "formatted_date": "1972-06-01"
        },
        "isPending": false,
        "timeZone": {
            "gmtOffset": -14400
        },
        "id": "1mo15050196001507611600"
    }
}

只是好奇:使用“Web驱动程序”有什么问题吗?(我甚至不确定“Web驱动程序”的定义是什么)。因为您的模块正在抓取网页,所以需要一种下载这些页面的方法。 - Gabriel Devillers
1
另外,您应该添加以下内容:如果您开始使用此模块,则希望它得到维护,或者准备好在需要时进行维护。事实上,雅虎财经可能随时更改其网页结构,这可能需要修改模块爬取代码。 - Gabriel Devillers
同意。说实话,如果需要的话,我准备至少为我的个人使用维护代码。它真的很好地组合在一起。维护者已经解决了一些问题并关闭了它们,所以他看起来不缺席。雅虎财经似乎在关闭其API时进行了大规模的新Web应用程序部署。除此之外,这些字段似乎直接来自数据库。我不认为他们会很快更改字段名称,前端更改也不会影响该模块,除非他们更改正在使用的Web应用程序框架。数据库通常只在主要版本中更改。 - alt777
同时,网络驱动程序也很好,不要误解我的意思。我喜欢Selenium + Phantom。然而,你所抓取的渲染GUI组件更有可能发生变化,而数据存储变量通常不会。对于重命名数据库字段的名称更改解决方案(非常罕见),通常比编写与新应用程序部分交互和抓取的新代码更容易实现。从我的经验来看,这种解决方案比通过网页爬虫获取数据更快。特别是当它是通过网络驱动程序的分页按钮才能抓取的数据时。我猜想,这个模块在未来三年内只需要进行小修补就可以了。 - alt777

0
from yahoofinancials import YahooFinancials

assets = ['TSLA', 'MSFT', 'FB']

yahoo_financials = YahooFinancials(assets)

data = yahoo_financials.get_historical_price_data(start_date='2019-01-01', 
                                                  end_date='2019-12-31', 
                                                  time_interval='weekly')

prices_df = pd.DataFrame({
    a: {x['formatted_date']: x['adjclose'] for x in data[a]['prices']} for a in assets})

prices_df

结果:

enter image description here


0
watchlist=["stock1","stock2".......]
closing_price=pd.DataFrame()
symbols=[]

for i in watchlist:
    Result=wb.DataReader(i,start='05-1-20', end='05-20-20',data_source='yahoo')
    closing_price=closing_price.append(Result)        
    symbols.append(i)
    print("Generating Closing price for",i)  
  
closing_price["SYMBOL"]=symbols
print("closing_price"

0

yahoo_finance不再可用,因为雅虎已更改格式,fix_yahoo_finance足以下载数据。但是,要解析数据,您需要其他库。

import numpy as np #python library for scientific computing
import pandas as pd #python library for data manipulation and analysis
import matplotlib.pyplot as plt #python library for charting
import fix_yahoo_finance as yf #python library to scrape data from yahoo finance
from pandas_datareader import data as pdr #extract data from internet sources into pandas data frame

yf.pdr_override()

data = pdr.get_data_yahoo(‘^DJI’, start=”2006–01–01")
data2 = pdr.get_data_yahoo(“MSFT”, start=”2006–01–01")
data3 = pdr.get_data_yahoo(“AAPL”, start=”2006–01–01")
data4 = pdr.get_data_yahoo(“BB.TO”, start=”2006–01–01")

ax = (data[‘Close’] / data[‘Close’].iloc[0] * 100).plot(figsize=(15, 6))
(data2[‘Close’] / data2[‘Close’].iloc[0] * 100).plot(ax=ax, figsize=(15,6))
(data3[‘Close’] / data3[‘Close’].iloc[0] * 100).plot(ax=ax, figsize=(15,6))
(data4[‘Close’] / data5[‘Close’].iloc[0] * 100).plot(ax=ax, figsize=(15,6))

plt.legend([‘Dow Jones’, ‘Microsoft’, ‘Apple’, ‘Blackberry’], loc=’upper left’)
plt.show()

访问 使用fix-yahoo-finance库绘制Yahoo财经中股票价格的代码解释


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接