Yahoo Finance URL no funciona

He estado usando la siguiente URL para recuperar datos históricos de yahoo finance desde hace bastante tiempo, pero dejó de funcionar a partir de ayer.

https://ichart.finance.yahoo.com/table.csv?s=SPY

Al navegar a este sitio, dice:

Regresamos en seguida…

Gracias por su paciencia.

Nuestros ingenieros están trabajando rápidamente para resolver el problema.

Sin embargo, dado que este problema aún existe desde ayer, ¿estoy empezando a pensar que suspendieron este servicio?

Mi búsqueda SO solo me indicó este tema , que estaba relacionado con https, aunque …

¿Alguien más está experimentando este problema? ¿Como puedo resolver este problema? ¿Ofrecen un acceso diferente a sus datos históricos?

Parece que han comenzado a agregar una cookie obligatoria, pero puede recuperarla con bastante facilidad, por ejemplo:

GET https://uk.finance.yahoo.com/quote/AAPL/history 

Responde con el encabezado en el formulario:

 set-cookie:B=xxxxxxxx&b=3&s=qf; expires=Fri, 18-May-2018 00:00:00 GMT; path=/; domain=.yahoo.com 

Debería poder leer esto y adjuntarlo a su solicitud .csv :

 GET https://query1.finance.yahoo.com/v7/finance/download/AAPL?period1=1492524105&period2=1495116105&interval=1d&events=history&crumb=tO1hNZoUQeQ cookie: B=xxxxxxxx&b=3&s=qf; 

Tenga en cuenta el parámetro de consulta de crumb , esto parece corresponder a su cookie de alguna manera. Su mejor opción es scrape esto de la respuesta HTML a su solicitud GET inicial. Dentro de esa respuesta, puede hacer una búsqueda de "CrumbStore":\{"crumb":"(?[^"]+)"\} regulares para: "CrumbStore":\{"crumb":"(?[^"]+)"\} y extraer el grupo de migajas de migajas.

Parece que una vez que tienes ese valor de crumb puedes usarlo con la misma cookie en cualquier símbolo / ticker para el próximo año, lo que significa que no deberías tener que hacer el scrape demasiada frecuencia.


Para obtener las cotizaciones actuales solo cargue:

https://query1.finance.yahoo.com/v8/finance/chart/AAPL?interval=2m

Con:

  • AAPL sustituido con su ticker de acciones
  • intervalo uno de [1m, 2m, 5m, 15m, 30m, 60m, 90m, 1h, 1d, 5d, 1wk, 1mo, 3mo]
  • period1 consulta de period1 opcional con la fecha de inicio de su rango de época eg period1=1510340760
  • period2 consulta de period2 opcional con la fecha de finalización del intervalo de epoch, por ejemplo, period2=1510663712

Logré calcular una clase .NET para obtener un token válido (cookie y migmb) de Yahoo Finance

Para obtener una biblioteca de API completa en la obtención de datos históricos del nuevo Yahoo Finance, puede visitar YahooFinanceAPI en Github

Aquí está la clase para agarrar la galleta y la miga

Token.cs

 using System; using System.Diagnostics; using System.Net; using System.IO; using System.Text.RegularExpressions; namespace YahooFinanceAPI { ///  /// Class for fetching token (cookie and crumb) from Yahoo Finance /// Copyright Dennis Lee /// 19 May 2017 /// ///  public class Token { public static string Cookie { get; set; } public static string Crumb { get; set; } private static Regex regex_crumb; ///  /// Refresh cookie and crumb value Yahoo Fianance ///  /// Stock ticker symbol ///  public static bool Refresh(string symbol = "SPY") { try { Token.Cookie = ""; Token.Crumb = ""; string url_scrape = "https://finance.yahoo.com/quote/{0}?p={0}"; //url_scrape = "https://finance.yahoo.com/quote/{0}/history" string url = string.Format(url_scrape, symbol); HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url); request.CookieContainer = new CookieContainer(); request.Method = "GET"; using (HttpWebResponse response = (HttpWebResponse)request.GetResponse()) { string cookie = response.GetResponseHeader("Set-Cookie").Split(';')[0]; string html = ""; using (Stream stream = response.GetResponseStream()) { html = new StreamReader(stream).ReadToEnd(); } if (html.Length < 5000) return false; string crumb = getCrumb(html); html = ""; if (crumb != null) { Token.Cookie = cookie; Token.Crumb = crumb; Debug.Print("Crumb: '{0}', Cookie: '{1}'", crumb, cookie); return true; } } } catch (Exception ex) { Debug.Print(ex.Message); } return false; } ///  /// Get crumb value from HTML ///  /// HTML code ///  private static string getCrumb(string html) { string crumb = null; try { //initialize on first time use if (regex_crumb == null) regex_crumb = new Regex("CrumbStore\":{\"crumb\":\"(?.+?)\"}", RegexOptions.CultureInvariant | RegexOptions.Compiled, TimeSpan.FromSeconds(5)); MatchCollection matches = regex_crumb.Matches(html); if (matches.Count > 0) { crumb = matches[0].Groups["crumb"].Value; } else { Debug.Print("Regex no match"); } //prevent regex memory leak matches = null; } catch (Exception ex) { Debug.Print(ex.Message); } GC.Collect(); return crumb; } } } 

Actualizado 1 jun 17
créditos a @ Ed0906
modificar el patrón regex de migas a Regex("CrumbStore\":{\"crumb\":\"(?.+?)\"}"

Yahoo ha ido a la interfaz de Reactjs, lo que significa que si analiza los encabezados de solicitud del cliente al back-end, puede obtener el JSON real que usan para llenar las tiendas del lado del cliente.

Hospedadores:

  • query1.finance.yahoo.com HTTP / 1.0
  • query2.finance.yahoo.com HTTP / 1.1 ( diferencia entre HTTP / 1.0 y HTTP / 1.1 )

Si planea usar un proxy o conexiones persistentes, use query2.finance.yahoo.com . Pero a los fines de esta publicación, el host utilizado para las URL de ejemplo no implica nada sobre la ruta con la que se está utilizando.


Datos Fundamentales

  • /v10/finance/quoteSummary/AAPL?modules= (Lista completa de módulos a continuación)

(sustituya su símbolo por: AAPL)

Entradas para ?modules= consulta:

  • modules = [ 'assetProfile', 'incomeStatementHistory', 'incomeStatementHistoryQuarterly', 'balanceSheetHistory', 'balanceSheetHistoryQuarterly', 'cashflowStatementHistory', 'cashflowStatementHistoryQuarterly', 'defaultKeyStatistics', 'financialData', 'calendarEvents', 'secFilings', 'recommendationTrend', 'upgradeDowngradeHistory', 'institutionOwnership', 'fundOwnership', 'majorDirectHolders', 'majorHoldersBreakdown', 'insiderTransactions', 'insiderHolders', 'netSharePurchaseActivity', 'earnings', 'earningsHistory', 'earningsTrend', 'industryTrend', 'indexTrend', 'sectorTrend' ]

URL de ejemplo:

  • https://query1.finance.yahoo.com/v10/finance/quoteSummary/AAPL?modules=assetProfile%2CearningsHistory

Consultando por : assetProfile and earningsHistory

El %2C es la representación hexadecimal de , y debe insertarse entre cada módulo que solicite. detalles sobre el bit de encoding hexadecimal (si le importa)


Contratos de opciones

  • /v7/finance/options/AAPL (vencimiento actual)
  • /v7/finance/options/AAPL?date=1579219200 (expiración del 17 de enero de 2020)

URL de ejemplo:

  • https://query2.yahoo.finance.com/v7/finance/options/AAPL (caducidad actual)
  • https://query2.yahoo.finance.com/v7/finance/options/AAPL?date=1579219200 (expiración del 17 de enero de 2020)

Cualquier expiración futura válida representada como una marca de tiempo UNIX se puede usar en la consulta ?date= . Si consulta la fecha de vencimiento actual, la respuesta JSON contendrá una lista de todos los vencimientos válidos que se pueden usar en la consulta ?date= . (Aquí hay una publicación que explica la conversión de fechas legibles por humanos a la marca de tiempo de Unix en Python)


Precio

  • /v8/finance/chart/AAPL?symbol=AAPL&period1=0&period2=9999999999&interval=3mo

Intervalos:

  • &interval=3mo 3 meses, retrocediendo hasta la fecha inicial de negociación.
  • &interval=1d 1 día, retrocediendo hasta la fecha de negociación inicial.
  • &interval=5m 5 minuets, retrocediendo 80 (ish) días.
  • &interval=1m 1 minuet, retrocediendo 4-5 días.

Qué tan atrás puede ir con cada intervalo es un poco confuso y parece inconsistente. Mi suposición es que internamente yahoo está contando en los días de negociación y mi enfoque ingenuo no contabilizaba las vacaciones. Aunque eso es una suposición e YMMV.

period1= : representación de fecha y hora de unix de la fecha en la que desea comenzar . Los valores por debajo de la fecha de negociación inicial se redondearán hasta la fecha de negociación inicial.

period2= : representación de fecha y hora de unix de la fecha en la que desea finalizar . Los valores superiores a la última fecha de negociación se redondearán a la marca de tiempo más reciente disponible.

Nota: Si realiza una consulta con un period1= (fecha de inicio) demasiado lejano para el intervalo que ha elegido, yahoo devolverá los precios en el intervalo 3mo , independientemente del intervalo que haya solicitado.

Agregar datos de mercado previos y posteriores

&includePrePost=true

Agregar dividendos y splits

&events=div%2Csplit

URL de ejemplo:

  • https://query1.finance.yahoo.com/v8/finance/chart/AAPL?symbol=AAPL&period1=0&period2=9999999999&interval=1d&includePrePost=true&events=div%2Csplit

La solicitud anterior devolverá todos los datos de precios para ticker AAPL en un intervalo de 1 día, incluidos los datos previos y posteriores al mercado, así como los dividendos y splits.

Nota: los valores utilizados en la URL de ejemplo de precio para period1= & period2= son para demostrar el comportamiento de redondeo respectivo de cada entrada.

En este foro: https://forums.yahoo.net/t5/Yahoo-Finance-help/Is-Yahoo-Finance-API-broken/td-p/250503/page/3

Nixon dijo:

Hola a todos: esta función fue descontinuada por el equipo de Finanzas y no reintroducirán esa funcionalidad.

La URL para descargar datos históricos ahora es algo como esto:

https://query1.finance.yahoo.com/v7/finance/download/SPY?period1=1492449771&period2=1495041771&interval=1d&events=history&crumb=9GaimFhz.WU

Tenga en cuenta que la URL anterior no funcionará para usted ni para nadie más. Obtendrás algo como esto:

 { "finance": { "error": { "code": "Unauthorized", "description": "Invalid cookie" } } } 

Parece que Yahoo ahora está utilizando algunos hash para evitar que las personas accedan a los datos como lo hizo usted. La URL varía con cada sesión, por lo que es muy probable que ya no pueda hacer esto con una URL fija.

Tendrá que hacer un desguace para obtener la URL correcta de la página principal, por ejemplo:

https://finance.yahoo.com/quote/SPY/history?p=SPY

Para los amantes de las pitones, actualicé el yahooFinance.py en la biblioteca de tradingWithPython.

También hay un cuaderno de ejemplos basado en los consejos de Ed0906, que demuestra cómo obtener los datos paso a paso. Véalo en

Estoy en el mismo barco. Llegar allí lentamente. El enlace de descarga en la página de precios históricos aún funciona. Así que agregué la extensión de cookies de exportación a firefox, inicié sesión en yahoo, vacié las cookies. Usé el valor de migajas de la sesión interactiva y pude recuperar valores. Aquí hay parte de un script de prueba de Perl que funcionó.

 use Time::Local; # create unix time variables for start and end date values: 1/1/2014 thru 12/31/2017 $p1= timelocal(0,0,0,1,0,114); $p2= timelocal(0,0,0,31,11,117); $symbol = 'AAPL'; # create variable for string to be executed as a system command # cookies.txt exported from firefox # crumb variable retrieved from yahoo download data link $task = "wget --load-cookies cookies.txt --no-check-certificate -T 30 -O $symbol.csv \"https://query1.finance.yahoo.com/v7/finance/download/$symbol?period1=$p1&period2=$p2&interval=1d&events=history&crumb=7WhHVu5N4e3\" "; #show what we're executing print $task; # execute system command using backticks `$task`; #output is AAPL.csv 

Tomará un tiempo para automatizar lo que hago. Afortunadamente, yahoo simplificará o dará alguna orientación si realmente pretende que las personas lo usen.

Para los amantes de Java.

Puede acceder a sus cookies desde una URLConnection de esta manera.

  // "https://finance.yahoo.com/quote/SPY"; URLConnection con = url.openConnection(); ... for (Map.Entry> entry : con.getHeaderFields().entrySet()) { if (entry.getKey() == null || !entry.getKey().equals("Set-Cookie")) continue; for (String s : entry.getValue()) { // store your cookie ... } } 

ahora puedes buscar la migaja en el sitio de yahoo:

 String crumb = null; InputStream inStream = con.getInputStream(); InputStreamReader irdr = new InputStreamReader(inStream); BufferedReader rsv = new BufferedReader(irdr); Pattern crumbPattern = Pattern.compile(".*\"CrumbStore\":\\{\"crumb\":\"([^\"]+)\"\\}.*"); String line = null; while (crumb == null && (line = rsv.readLine()) != null) { Matcher matcher = crumbPattern.matcher(line); if (matcher.matches()) crumb = matcher.group(1); } rsv.close(); 

y finalmente, configurar la cookie

 String quoteUrl = "https://query1.finance.yahoo.com/v7/finance/download/IBM?period1=1493425217&period2=1496017217&interval=1d&events=history&crumb=" + crumb ... List cookies = cookieStore.get(key); if (cookies != null) { for (String c: cookies) con.setRequestProperty("Cookie", c); } ... con.connect(); 

Ejemplo PHP completamente funcional, basado en esta publicación y fonts relacionadas:

 function readYahoo($symbol, $tsStart, $tsEnd) { preg_match('"CrumbStore\":{\"crumb\":\"(?.+?)\"}"', file_get_contents('https://uk.finance.yahoo.com/quote/' . $symbol), $crumb); // can contain \uXXXX chars if (!isset($crumb['crumb'])) return 'Crumb not found.'; $crumb = json_decode('"' . $crumb['crumb'] . '"'); // \uXXXX to UTF-8 foreach ($http_response_header as $header) { if (0 !== stripos($header, 'Set-Cookie: ')) continue; $cookie = substr($header, 14, strpos($header, ';') - 14); // after 'B=' } // cookie looks like "fkjfom9cj65jo&b=3&s=sg" if (!isset($cookie)) return 'Cookie not found.'; $fp = fopen('https://query1.finance.yahoo.com/v7/finance/download/' . $symbol . '?period1=' . $tsStart . '&period2=' . $tsEnd . '&interval=1d' . '&events=history&crumb=' . $crumb, 'rb', FALSE, stream_context_create(array('http' => array('method' => 'GET', 'header' => 'Cookie: B=' . $cookie)))); if (FALSE === $fp) return 'Can not open data.'; $buffer = ''; while (!feof($fp)) $buffer .= implode(',', fgetcsv($fp, 5000)) . PHP_EOL; fclose($fp); return $buffer; } 

Uso :

 $csv = readYahoo('AAPL', mktime(0, 0, 0, 6, 2, 2017), mktime(0, 0, 0, 6, 3, 2017)); 

Encontré otro sitio yahoo que no requiere cookies, pero genera salida de jason: https://query1.finance.yahoo.com/v7/finance/chart/YHOO?range=2y&interval=1d&indicators=quote&includeTimestamps=true

se señaló desde aquí: https://www.stock-data-solutions.com/kb/how-to-load-historical-prices-from-yahoo-finance-to-excel.htm

Como resultó, parecen soportar los parámetros ‘perod1’ y ‘period2’ (en tiempo de Unix) que podrían usarse en lugar del ‘intervalo’.

 String quoteSite = "https://query1.finance.yahoo.com/v7/finance/chart/" + symbolName + "?" + "period1=" + period1 + "&period2=" + period2 + "&interval=1d&indicators=quote&includeTimestamps=true"; 

Y el siguiente analiza a Jason por mí:

 JSONObject topObj = new JSONObject(inp); Object error = topObj.getJSONObject("chart").get("error"); if (!error.toString().equals("null")) { System.err.prinltn(error.toString()); return null; } JSONArray results = topObj.getJSONObject("chart").getJSONArray("result"); if (results == null || results.length() != 1) { return null; } JSONObject result = results.getJSONObject(0); JSONArray timestamps = result.getJSONArray("timestamp"); JSONObject indicators = result.getJSONObject("indicators"); JSONArray quotes = indicators.getJSONArray("quote"); if (quotes == null || quotes.length() != 1) { return null; } JSONObject quote = quotes.getJSONObject(0); JSONArray adjcloses = indicators.getJSONArray("adjclose"); if (adjcloses == null || adjcloses.length() != 1) { return null; } JSONArray adjclose = adjcloses.getJSONObject(0).getJSONArray("adjclose"); JSONArray open = quote.getJSONArray("open"); JSONArray close = quote.getJSONArray("close"); JSONArray high = quote.getJSONArray("high"); JSONArray low = quote.getJSONArray("low"); JSONArray volume = quote.getJSONArray("volume"); 

Soy el autor de este servicio

Información básica aquí

Precios diarios

Debe estar familiarizado con los servicios RESTFUL.

https://quantprice.herokuapp.com/api/v1.1/scoop/day?tickers=MSFT&date=2017-06-09

Precios históricos

Debes proporcionar un rango de fechas:

https://quantprice.herokuapp.com/api/v1.1/scoop/period?tickers=MSFT&begin=2012-02-19&end=2012-02-20

Si no proporciona inicio ni finalización, usará la fecha más temprana o actual:

https://quantprice.herokuapp.com/api/v1.1/scoop/period?tickers=MSFT&begin=2012-02-19

Tickers múltiples

Puedes simplemente poner comas por separado:

https://quantprice.herokuapp.com/api/v1.1/scoop/period?tickers=IBM,MSFT&begin=2012-02-19

Límite de tarifa

Todas las solicitudes tienen una tarifa limitada a 10 solicitudes por hora. Si desea registrarse para obtener una API de acceso completo, envíeme DM en twitter. Recibirá una clave API para agregar a la URL.

Estamos configurando una cuenta de Paypal para la suscripción paga sin tarifas.

Lista de tickers disponibles

https://github.com/robomotic/valueviz/blob/master/scoop_tickers.csv

También estoy trabajando para proporcionar datos fundamentales y datos de la compañía de EDGAR. Aclamaciones.

VBA

Aquí hay algunas funciones de VBA que descargan y extraen el par de cookies / migas y las devuelven en una Collection , y luego las usan para descargar el contenido del archivo csv para un código en particular.

El proyecto que lo contiene debe tener una referencia a la biblioteca ‘Microsoft XML, v6.0’ agregada (la otra versión también podría estar bien con algunos cambios menores en el código).

 Sub Test() Dim X As Collection Set X = FindCookieAndCrumb() Debug.Print X!cookie Debug.Print X!crumb Debug.Print YahooRequest("AAPL", DateValue("31 Dec 2016"), DateValue("30 May 2017"), X) End Sub Function FindCookieAndCrumb() As Collection ' Tools - Reference : Microsoft XML, v6.0 Dim http As MSXML2.XMLHTTP60 Dim cookie As String Dim crumb As String Dim url As String Dim Pos1 As Long Dim X As String Set FindCookieAndCrumb = New Collection Set http = New MSXML2.ServerXMLHTTP60 url = "https://finance.yahoo.com/quote/MSFT/history" http.Open "GET", url, False ' http.setProxy 2, "https=127.0.0.1:8888", "" ' http.setRequestHeader "Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8" ' http.setRequestHeader "Accept-Encoding", "gzip, deflate, sdch, br" ' http.setRequestHeader "Accept-Language", "en-ZA,en-GB;q=0.8,en-US;q=0.6,en;q=0.4" http.setRequestHeader "User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36" http.send X = http.responseText Pos1 = InStr(X, "CrumbStore") X = Mid(X, Pos1, 44) X = Mid(X, 23, 44) Pos1 = InStr(X, """") X = Left(X, Pos1 - 1) FindCookieAndCrumb.Add X, "Crumb" '====================================== X = http.getResponseHeader("set-cookie") Pos1 = InStr(X, ";") X = Left(X, Pos1 - 1) FindCookieAndCrumb.Add X, "Cookie" End Function Function YahooRequest(ShareCode As String, StartDate As Date, EndDate As Date, CookieAndCrumb As Collection) As String ' Tools - Reference : Microsoft XML, v6.0 Dim http As MSXML2.XMLHTTP60 Dim cookie As String Dim crumb As String Dim url As String Dim UnixStartDate As Long Dim UnixEndDate As Long Dim BaseDate As Date Set http = New MSXML2.ServerXMLHTTP60 cookie = CookieAndCrumb!cookie crumb = CookieAndCrumb!crumb BaseDate = DateValue("1 Jan 1970") If StartDate = 0 Then StartDate = BaseDate UnixStartDate = (StartDate - BaseDate) * 86400 UnixEndDate = (EndDate - BaseDate) * 86400 url = "https://query1.finance.yahoo.com/v7/finance/download/" & ShareCode & "?period1=" & UnixStartDate & "&period2=" & UnixEndDate & "&interval=1d&events=history&crumb=" & crumb http.Open "GET", url, False http.setRequestHeader "Cookie", cookie http.send YahooRequest = http.responseText End Function 

Pitón

Usé este código para obtener cookies (copiado de fix-yahoo-finance ):

 def get_yahoo_crumb_cookie(): """Get Yahoo crumb cookie value.""" res = requests.get('https://finance.yahoo.com/quote/SPY/history') yahoo_cookie = res.cookies['B'] yahoo_crumb = None pattern = re.compile('.*"CrumbStore":\{"crumb":"(?P[^"]+)"\}') for line in res.text.splitlines(): m = pattern.match(line) if m is not None: yahoo_crumb = m.groupdict()['crumb'] return yahoo_cookie, yahoo_crumb 

entonces este código para obtener respuesta:

 cookie, crumb = get_yahoo_crumb_cookie() params = { 'symbol': stock.symbol, 'period1': 0, 'period2': int(time.time()), 'interval': '1d', 'crumb': crumb, } url_price = 'https://query1.finance.yahoo.com/v7/finance/download/{symbol}' response = requests.get(url_price, params=params, cookies={'B': cookie}) 

Esto también se ve bien http://blog.bradlucas.com/posts/2017-06-03-yahoo-finance-quote-download-python/

Utilicé un script php usando fopen () para acceder a los datos financieros, aquí están los fragmentos que modifiqué para que vuelva a funcionar:

Crear las marcas de tiempo para la fecha de inicio y la fecha de finalización:

 $timestampStart = mktime(0,0,0,$startMonth,$startDay,$startYear); $timestampEnd = mktime(0,0,0,$endMonth,$endDay,$endYear); 

Forzar fopen () para enviar la cookie requerida con los valores codificados:

 $cookie="YourCookieTakenFromYahoo"; $opts = array( 'http'=>array( 'method'=>"GET", 'header'=>"Accept-language: en\r\n" . "Cookie: B=".$cookie."\r\n" ) ); $context = stream_context_create($opts); 

Use fopen () para obtener el archivo csv:

 $ticker="TickerSymbol"; $crumb="CrumbValueThatMatchesYourCookieFromYahoo"; $handle = fopen("https://query1.finance.yahoo.com/v7/finance/download/".$ticker."?period1=".$timestampStart."&period2=".$timestampEnd."&interval=1d&events=history&crumb=".$crumb."", "r", false, $context); 

Ahora puedes hacer toda la magia que hiciste antes en este ciclo while:

 while (!feof($handle) ) { $line_of_text = fgetcsv($handle, 5000); } 

Asegúrese de establecer sus propios valores para $ticker , $crumb y $cookie en los fragmentos de arriba. Sigue el enfoque de Ed0906 sobre cómo recuperar $crumb y $cookie .

Para aquellos usuarios de Excel / VBA, he utilizado las sugerencias anteriores para desarrollar un método de VBA para extraer los precios históricos del sitio web actualizado de Yahoo. Los fragmentos de código clave se enumeran a continuación y también proporcioné mi libro de pruebas.

Primero una solicitud para obtener los valores de Migajas y Galletas antes de intentar extraer los datos de Yahoo por los precios.

 Dim strUrl As String: strUrl = "https://finance.yahoo.com/lookup?s=%7B0%7D" 'Symbol lookup used to set the values Dim objRequest As WinHTTP.WinHttpRequest Set objRequest = New WinHttp.WinHttpRequest With objRequest .Open "GET", strUrl, True .setRequestHeader "Content-Type", "application/x-www-form-urlencoded; charset=UTF-8" .send .waitForResponse strCrumb = strExtractCrumb(.responseText) strCookie = Split(.getResponseHeader("Set-Cookie"), ";")(0) End With 

Consulte el siguiente enlace de Extracto de precio histórico de Yahoo a mi sitio web para obtener un archivo de muestra y más detalles sobre el método que he usado para extraer los precios de seguridad históricos del sitio web de Yahoo.

Yo estaba en el mismo bote. Logré obtener el CSV descargado de Yahoo con algún código franco vb.net que hice de partes de Google, SOF y algunos rasguños en la cabeza.

Sin embargo, descubrí Intrinio (búscalo), me registré y mi cuenta gratuita me permite obtener 500 llamadas de datos históricos por día, con muchos más datos y mucha más precisión que Yahoo. Reescribí mi código para la API de Intrinio, y estoy feliz como una almeja.

Por cierto, no trabajo ni tengo nada que ver con Intrinio, pero me salvaron muchísimo …

Hay una solución que he encontrado que funciona bien. Por favor mira mi publicación:

Yahoo Finance API / URL no funciona: solución de Python para Pandas DataReader donde seguí los pasos en https://pypi.python.org/pypi/fix-yahoo-finance para: $ pip install fix_yahoo_finance –upgrade –no-cache -dir (y también actualizado pandas_datareader para estar seguro) y probado bien:

 from pandas_datareader import data as pdr import fix_yahoo_finance data = pdr.get_data_yahoo('BHP.AX', start='2017-04-23', end='2017-05-24') 

También tenga en cuenta que el orden de las últimas 2 columnas de datos es ‘Ajus Cerrar’ y ‘Volumen’ por lo que para mi propósito, he restablecido las columnas al orden original:

 cols = ['Date', 'Open', 'High', 'Low', 'Close', 'Volume', 'Adj Close'] data = data.reindex(columns=cols) 

En realidad, no necesita hacer 2 solicitudes para obtener datos de Yahoo. Uso este enlace https://ca.finance.yahoo.com/quote/AAAP/history?period1=1474000669&period2=1505536669&interval=1d&filter=history&frequency=1d

Puede tomar la cookie de esto, pero en su lugar incluye esa información para su cita histórica en formato Json. Después de descargar la página, elimino los datos de Json. Guarda una solicitud de url

Javascript

Encuentra cookies;

 match = document.cookie.match(new RegExp('B=([^;]+)')); alert (match[1]); 

Encontrar migajas

 i=document.body.innerHTML.search("CrumbStore") if (i>=0) alert (document.body.innerHTML.substr(i+22,11)) 

Encontrar migajas para dispositivos móviles;

 i=document.body.innerHTML.search('USER={\"crumb\":'); if (i>=0) alert(document.body.innerHTML.substr(i+15,11)); 

y probablemente sea mejor esperar a que la página (por ejemplo, https://finance.yahoo.com/quote/goog ) se cargue primero, puedes verificarlo;

 document.readyState 

Un enfoque alternativo a los mencionados hasta ahora (Yahoo, Google e Intrinio) es obtener los datos históricos de Alpha Vantage de forma gratuita. Su servicio web ofrece precios de acciones ajustados a diario, diarios y más de 50 indicadores técnicos. Incluso entregan directamente a Excel, también gratis, a través de Deriscope. (Soy el autor de este último)

Para Python 3 los usuarios cambian a

url = ‘ https://query1.finance.yahoo.com/v7/finance/download/AAAP?period1=1494605670&period2=1495815270&interval=1d&events=history&crumb=IJ.ilcJlkrZ

de

url = ‘ https://chartapi.finance.yahoo.com/instrument/1.0/AAAP/chartdata;type=quote;range=10d/csv/

y

response = request.urlopen (url) a response = requests.get (url, cookies = {‘B’: cookie}) datos en response.text

el formato de datos es totalmente diferente, pero al menos funciona bien por ahora

Es posible obtener datos actuales e históricos de google finance api . Funciona muy bien para mi

He combinado algunas de las ideas anteriores que manejan la actualización de miga / cookie, específicamente de @Dennis, y he creado una clase de vb.net que se puede llamar así:

 Dim f = Await YahooFinanceFactory.CreateAsync Dim items1 = Await f.GetHistoricalDataAsync("SPY", #1/1/2018#) Dim items2 = Await f.GetHistoricalDataAsync("^FTSE", #1/1/2018#) 

La clase en sí está aquí:

 Imports System.Net Imports System.Net.Http Imports System.Text.RegularExpressions Namespace YahooFinance Public Class YahooHistoryPrice Public Property [Date] As DateTime Public Property Open As Double Public Property High As Double Public Property Low As Double Public Property Close As Double Public Property Volume As Double Public Property AdjClose As Double End Class Public Class YahooFinanceFactory Public Property Cookie As String Public Property Crumb As String Public Property CrumbUrl As String = "https://finance.yahoo.com/quote/{0}?p={0}" Public Property DownloadUrl As String = "https://query1.finance.yahoo.com/v7/finance/download/{0}?period1={1}&period2={2}&interval=1d&events={3}&crumb={4}" Public Property Timeout As Integer = 5 Public Property NoRefreshRetries As Integer = 10 Public Property NoDownloadRetries As Integer = 10 Private Property Regex_crumb As Regex Public Shared Async Function CreateAsync(Optional noRefreshRetries As Integer = 10, Optional noDownloadRetries As Integer = 10, Optional timeout As Integer = 5, Optional crumbUrl As String = "https://finance.yahoo.com/quote/{0}?p={0}", Optional downloadUrl As String = "https://query1.finance.yahoo.com/v7/finance/download/{0}?period1={1}&period2={2}&interval=1d&events={3}&crumb={4}") As Task(Of YahooFinanceFactory) Return Await (New YahooFinanceFactory With { .NoRefreshRetries = noRefreshRetries, .NoDownloadRetries = noDownloadRetries, .Timeout = timeout, .CrumbUrl = crumbUrl, .DownloadUrl = downloadUrl }).RefreshAsync() End Function Public Async Function GetHistoricalDataAsync(symbol As String, dateFrom As Date) As Task(Of IEnumerable(Of YahooHistoryPrice)) Dim count As Integer = 0 If Not IsValid Then Throw New Exception("Invalid YahooFinanceFactory instance") End If Dim csvData = Await GetRawAsync(symbol, dateFrom, Now).ConfigureAwait(False) If csvData IsNot Nothing Then Return ParsePrice(csvData) End If Return Array.Empty(Of YahooHistoryPrice) End Function Public Async Function GetRawAsync(symbol As String, start As DateTime, [end] As DateTime) As Task(Of String) Dim count = 0 While count < NoDownloadRetries Try Dim cookies = New CookieContainer cookies.Add(New Cookie("B", If(Cookie.StartsWith("B="), Cookie.Substring(2), Cookie), "/", ".yahoo.com")) Using handler = New HttpClientHandler With {.CookieContainer = cookies} Using client = New HttpClient(handler) With {.Timeout = TimeSpan.FromSeconds(Timeout)} Dim httpResponse = Await client.GetAsync(GetDownloadUrl(symbol, start)).ConfigureAwait(False) Return Await httpResponse.Content.ReadAsStringAsync End Using End Using Catch ex As Exception If count >= NoDownloadRetries - 1 Then Throw End If End Try count += 1 End While Throw New Exception("Retries exhausted") End Function Private Function ParsePrice(ByVal csvData As String) As IEnumerable(Of YahooHistoryPrice) Dim lst = New List(Of YahooHistoryPrice) Dim rows = csvData.Split(Convert.ToChar(10)) For i = 1 To rows.Length - 1 Dim row = rows(i) If String.IsNullOrEmpty(row) Then Continue For End If Dim cols = row.Split(","c) If cols(1) = "null" Then Continue For End If Dim itm = New YahooHistoryPrice With {.Date = DateTime.Parse(cols(0)), .Open = Convert.ToDouble(cols(1)), .High = Convert.ToDouble(cols(2)), .Low = Convert.ToDouble(cols(3)), .Close = Convert.ToDouble(cols(4)), .AdjClose = Convert.ToDouble(cols(5))} If cols(6) <> "null" Then itm.Volume = Convert.ToDouble(cols(6)) End If lst.Add(itm) Next Return lst End Function Public ReadOnly Property IsValid() As Boolean Get Return Not String.IsNullOrWhiteSpace(Cookie) And Not String.IsNullOrWhiteSpace(Crumb) End Get End Property Public Function GetDownloadUrl(symbol As String, dateFrom As Date, Optional eventType As String = "history") As String Return String.Format(DownloadUrl, symbol, Math.Round(DateTimeToUnixTimestamp(dateFrom), 0), Math.Round(DateTimeToUnixTimestamp(Now.AddDays(-1)), 0), eventType, Crumb) End Function Public Function GetCrumbUrl(symbol As String) As String Return String.Format(Me.CrumbUrl, symbol) End Function Public Function DateTimeToUnixTimestamp(dateTime As DateTime) As Double Return (dateTime.ToUniversalTime() - New DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc)).TotalSeconds End Function Private Async Function RefreshAsync(Optional symbol As String = "SPY") As Task(Of YahooFinanceFactory) Dim count = 0 While count < NoRefreshRetries And Not IsValid Try Using client = New HttpClient With {.Timeout = TimeSpan.FromSeconds(Timeout)} Dim httpResponse = Await client.GetAsync(GetCrumbUrl(symbol)).ConfigureAwait(False) Me.Cookie = httpResponse.Headers.First(Function(f) f.Key = "Set-Cookie").Value.FirstOrDefault?.Split(";"c)(0) Dim html = Await httpResponse.Content.ReadAsStringAsync Me.Crumb = GetCrumb(html) If Crumb IsNot Nothing Then Return Me End If End Using Catch ex As Exception If count >= NoRefreshRetries - 1 Then Cookie = "" Crumb = "" Throw End If End Try count += 1 End While Cookie = "" Crumb = "" Throw New Exception("Could not refresh YahooFinanceFactory") End Function Private Function GetCrumb(html As String) As String Dim crumb As String = Nothing If Regex_crumb Is Nothing Then Regex_crumb = New Regex("CrumbStore"":{""crumb"":""(?.+?)""}", RegexOptions.CultureInvariant Or RegexOptions.Compiled, TimeSpan.FromSeconds(5)) End If Dim matches As MatchCollection = Regex_crumb.Matches(html) If matches.Count > 0 Then crumb = matches(0).Groups("crumb").Value crumb = System.Text.RegularExpressions.Regex.Unescape(crumb) Else Throw New Exception("Regex no match") End If Return crumb End Function End Class End Namespace