Descarga de varias acciones a la vez desde yahoo finance python

dieciséis

Tengo una pregunta sobre la función de yahoo finance utilizando el lector de datos pandas. Estoy usando desde hace meses una lista con tickers de acciones y la ejecuto en las siguientes líneas:

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)

Desde ayer me aparece el error "IndexError: lista de índice fuera de rango", que aparece sólo si trato de obtener varias acciones.

¿Ha cambiado algo en los últimos días que deba considerar o tiene una mejor solución para mi problema?

14

Actualizado el 2021-01-19

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

Respuesta original

Si lee la documentación de Pandas DataReader , emitieron una depreciación inmediata en varias API de fuentes de datos, una de las cuales es Yahoo! Finanzas.

v0.6.0 (January 24, 2018)

Immediate deprecation of Yahoo!, Google Options and Quotes and EDGAR. The end points behind these APIs have radically changed and the existing readers require complete rewrites. In the case of most Yahoo! data the endpoints have been removed. PDR would like to restore these features, and pull requests are welcome.

Este podría ser el culpable de por qué ha estado obteniendo IndexError's (o cualquier otro error que normalmente no existe).


Sin embargo, hay otro paquete de Python cuyo objetivo es arreglar el soporte para Yahoo! Finance for Pandas DataReader, puede encontrar ese paquete aquí:

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

Según su documentación:

Yahoo! finance has decommissioned their historical data API, causing many programs that relied on it to stop working.

fix-yahoo-finance offers a temporary fix to the problem by scraping the data from Yahoo! finance using and return a Pandas DataFrame/Panel in the same format as pandas_datareader’s get_data_yahoo().

By basically “hijacking” pandas_datareader.data.get_data_yahoo() method, fix-yahoo-finance’s implantation is easy and only requires to import fix_yahoo_finance into your code.

Todo lo que necesita agregar es esto:

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)

O incluso sin la necesidad de 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)
1
  • ¿Es posible cambiar el intervalo de tiempo / frecuencia / intervalo de los datos que se devuelven? Necesito un precio de cierre de 90 millones. 14 mar a las 13:00
7

Puede usar el nuevo módulo Python YahooFinancials con pandas para hacer esto. YahooFinancials está bien construido y obtiene sus datos procesando el objeto del almacén de datos presente en cada página web de Yahoo Finance, por lo que es rápido y no depende de la antigua API descontinuada ni de un controlador web como lo hace un raspador. Los datos se devuelven como JSON y puede extraer tantas acciones como desee a la vez pasando una lista de tickers de acciones / índices para inicializar la clase YahooFinancials.

$ pip instalar yahoofinancials

Ejemplo de uso:

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

Ejemplo de datos de varias acciones a la vez (devuelve una lista de objetos JSON para cada ticker):

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')

Ejemplo de salida JSON:

Código:

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

Devolución de 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"
    }
}
4
  • Me pregunto: ¿cuál es el problema con el uso de un "controlador web"? (Ni siquiera estoy seguro de cuál es la definición de "controlador web"). Debido a que su módulo está raspando páginas web, necesita una forma de descargar estas páginas. 10/07/2018 a las 22:36
  • 1
    También debe agregar que si comienza a usar este módulo, espera que se mantenga o está listo para mantenerlo si es necesario . De hecho, Yahoo Financial podría cambiar la estructura de sus páginas web cualquier día, lo que podría requerir una modificación del código de raspado del módulo. 10/07/2018 a las 22:38
  • Acordado. Tbh estoy listo para mantener el código al menos para mi uso personal si es necesario. Está muy bien armado. El encargado de mantenimiento ha abordado algunos problemas y los ha cerrado para que no parezca ausente. Yahoo Finance parece haber tenido una implementación masiva de nuevas aplicaciones web cuando cerraron su API. Además de eso, los campos parecen ser directamente de la base de datos. No parece que cambien los nombres de los campos en el corto plazo y los cambios de la interfaz no afectarán el módulo a menos que cambien el marco de la aplicación web que están usando. Las bases de datos generalmente solo se cambian en las versiones principales.
    alt777
    10 de julio de 2018 a las 23:47
  • Además, los controladores web son agradables, no me malinterpretes. Amo el selenio + fantasma. Sin embargo, es más probable que cambien los componentes de la GUI renderizados que desecha que las variables del almacén de datos en general y una solución de cambio de nombre para un campo de base de datos renombrado (muy raro) suele ser más fácil de implementar que escribir código nuevo para interactuar y desechar una nueva parte de la aplicación. Además, esta solución es más rápida que obtener los datos de un raspador web de mi experiencia. Especialmente cuando se trata de datos que solo puede eliminar mediante botones de paginación a través del controlador web. Sospecho que este módulo estará bien con solo correcciones menores durante ~ 3 años
    alt777
    10 de julio de 2018 a las 23:52
0

Prueba este sencillo código

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
0

yahoo_finance ya no se puede utilizar desde que Yahoo cambió el formato, fix_yahoo_finance es lo suficientemente bueno para descargar datos. Sin embargo, para analizar necesitará otras bibliotecas, aquí está el ejemplo de trabajo simple:


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()

para obtener una explicación del código, puede visitar https://medium.com/@gerrysabar/charting-stocks-price-from-yahoo-finance-using-fix-yahoo-finance-library-6b690cac5447