Skip to content

Instantly share code, notes, and snippets.

@lebedov
Last active February 20, 2024 09:44
Show Gist options
  • Star 49 You must be signed in to star a gist
  • Fork 27 You must be signed in to fork a gist
  • Save lebedov/f09030b865c4cb142af1 to your computer and use it in GitHub Desktop.
Save lebedov/f09030b865c4cb142af1 to your computer and use it in GitHub Desktop.
Retrieve intraday stock data from Google Finance.
#!/usr/bin/env python
"""
Retrieve intraday stock data from Google Finance.
"""
import csv
import datetime
import re
import pandas as pd
import requests
def get_google_finance_intraday(ticker, period=60, days=1):
"""
Retrieve intraday stock data from Google Finance.
Parameters
----------
ticker : str
Company ticker symbol.
period : int
Interval between stock values in seconds.
days : int
Number of days of data to retrieve.
Returns
-------
df : pandas.DataFrame
DataFrame containing the opening price, high price, low price,
closing price, and volume. The index contains the times associated with
the retrieved price values.
"""
uri = 'http://www.google.com/finance/getprices' \
'?i={period}&p={days}d&f=d,o,h,l,c,v&df=cpct&q={ticker}'.format(ticker=ticker,
period=period,
days=days)
page = requests.get(uri)
reader = csv.reader(page.content.splitlines())
columns = ['Open', 'High', 'Low', 'Close', 'Volume']
rows = []
times = []
for row in reader:
if re.match('^[a\d]', row[0]):
if row[0].startswith('a'):
start = datetime.datetime.fromtimestamp(int(row[0][1:]))
times.append(start)
else:
times.append(start+datetime.timedelta(seconds=period*int(row[0])))
rows.append(map(float, row[1:]))
if len(rows):
return pd.DataFrame(rows, index=pd.DatetimeIndex(times, name='Date'),
columns=columns)
else:
return pd.DataFrame(rows, index=pd.DatetimeIndex(times, name='Date'))
@bsc1280
Copy link

bsc1280 commented Feb 28, 2018

Hi

I have to download last 10 year price data at hourly intervals. I tried trying the link below with
i= 2600 (2600 seconds or 1 hour)
p=10Y or 2500d

https://finance.google.com/finance/getprices?q=LHA&p=10Y&i=3600&f=d,c,h,l,o,v

please can you help me find out how to down hourly data for last 10 year for a stock
thanks!

@ninovasc
Copy link

Here some adjusts in URL, columns order and a "main" call:

#!/usr/bin/env python 
"""
Retrieve intraday stock data from Google Finance.
"""
import sys
import csv
import datetime
import re

import pandas as pd
import requests

def get_google_finance_intraday(ticker, exchange, period=60, days=1):
    """
    Retrieve intraday stock data from Google Finance.
    Parameters
    ----------
    ticker : str
        Company ticker symbol
    exchange : str
        Exchange of ticker
    period : int
        Interval between stock values in seconds.
    days : int
        Number of days of data to retrieve.
    Returns
    -------
    df : pandas.DataFrame
        DataFrame containing the opening price, high price, low price,
        closing price, and volume. The index contains the times associated with
        the retrieved price values.
    """

    uri = 'https://www.google.com/finance/getprices' \
          '?i={period}&p={days}d&f=d,o,h,l,c,v&q={ticker}&x={exchange}'.format(ticker=ticker,
                                                                          period=period,
                                                                          days=days,
                                                                          exchange=exchange)
    page = requests.get(uri)
    reader = csv.reader(page.content.splitlines())
    columns = ['Close', 'High', 'Low', 'Open', 'Volume']
    rows = []
    times = []
    for row in reader:
        if re.match('^[a\d]', row[0]):
            if row[0].startswith('a'):
                start = datetime.datetime.fromtimestamp(int(row[0][1:]))
                times.append(start)
            else:
                times.append(start+datetime.timedelta(seconds=period*int(row[0])))
            rows.append(map(float, row[1:]))
    if len(rows):
        return pd.DataFrame(rows, index=pd.DatetimeIndex(times, name='Date'),
                            columns=columns)
    else:
        return pd.DataFrame(rows, index=pd.DatetimeIndex(times, name='Date'))

if __name__ == '__main__':
    if len(sys.argv) == 1:
        print("\nUsage: google_financial_intraday.py EXCHANGE SYMBOL\n\n")
    else:
        exchange = sys.argv[1]
        ticker = sys.argv[2]
        print("--------------------------------------------------")
        print("Processing %s" % ticker)
        print get_google_finance_intraday(ticker,exchange,60,2)
        print("--------------------------------------------------")

@simonskok
Copy link

Hi guys, thanks for your great work! I wrote a similar function for fetching the intraday google data in R, but as of today the URL is no longer responding, as it directs to the normal google finance website and not to the one with the data table. Any idea whether the API is deprecated or has the URL just changed? Anyone familiar with the new URL?

@Excelnabb
Copy link

Hi, I have the same problem as simonskok, the URL seems to been stopped working, is the URL changed or does google have stopped their API?

@nebaz
Copy link

nebaz commented Aug 3, 2018

Yes, Google has bloked this api. Do you know any similar online api?

@christ-2
Copy link

christ-2 commented Aug 6, 2018

Same experience here also, damn!! I have yet to find confirmation from google that the API is discontinued. nebaz how do you know google has blocked this API?

@kongaraman
Copy link

same for me as well, but i found below yahoo link working for 1minute

https://query1.finance.yahoo.com/v7/finance/chart/RADICO.NS?&interval=1m

needs to convert to python code, can some one help to get datetime, open, high, low,close,vol values from this

@giogio02
Copy link

giogio02 commented Aug 8, 2018

Well, with the file $f you get from Yahoo, I wrote a script that uses an old version of gawk and"jq" (maybe json2csv would have been easier..)
You can modify it to change columns and to remove "empty minutes"...

cat $f | jq -r '[.[] | {result:
 [.result[].timestamp,
 .result[].indicators.quote[].close,
 .result[].indicators.quote[].high,
 .result[].indicators.quote[].low,
 .result[].indicators.quote[].open,
 .result[].indicators.quote[].volume
 | @csv] } ] '  | gawk -F"," ' BEGIN {
        nrec=1
}
NF > 2 {
        gsub(/\"/,"")
        for(i=1; i<=NF; i++)
        arr[nrec, i] = $i
        tt=NF
        nrec++
}
END {
        for (t=1;t < tt; t++)
        {
        printf "%d,", arr[1,t]
        for (v=2;v < 6; v++)
                printf "%7.3f,", arr[v,t]
        printf "%d\n", arr[6,t]
        }
}'

Then to convert the timestamp $1 in HH:MM:SS, using variables h, m, s:

s=$(date +%s)
let re=s%86400
let midn=s-re-7200 (that's for my timezone ;-) , modify it using date +%z)

                ds=$1-midn             
                h=ds/3600;
                hre=ds % 3600
                m=hre/60
                s=hre % 60

@carly11
Copy link

carly11 commented Aug 9, 2018

Here is a script that pulls 60 minute data from yahoo. Copy the contents below into python2.x file. Pass the symbol as the variable. You can change the data interval at the line on bottom of the code.

import requests
import pandas as pd
import arrow
from dateutil.parser import parse
from dateutil.tz import gettz
import datetime
from pprint import pprint
import urllib,time,datetime
import sys

symbol1 = sys.argv[1]
symbolname = symbol1
symbol1 = symbol1.upper()

def get_quote_data(symbol='iwm', data_range='1d', data_interval='60m'):
res = requests.get('https://query1.finance.yahoo.com/v8/finance/chart/{symbol}?range={data_range}&interval={data_interval}'.format(**locals()))
data = res.json()
body = data['chart']['result'][0]
dt = datetime.datetime
dt = pd.Series(map(lambda x: arrow.get(x).to('EST').datetime.replace(tzinfo=None), body['timestamp']), name='dt')
df = pd.DataFrame(body['indicators']['quote'][0], index=dt)
dg = pd.DataFrame(body['timestamp'])
return df.loc[:, ('open', 'high', 'low', 'close', 'volume')]

q = jpy5m = get_quote_data(symbol1, '2d', ' 60m')
print q

@kongaraman
Copy link

Thanks carly11, very smart code

Modified your code to Python3.65 and made small changes

`import requests
import pandas as pd
import arrow
import datetime

def get_quote_data(symbol='SBIN.NS', data_range='1d', data_interval='1m'):
res = requests.get('https://query1.finance.yahoo.com/v8/finance/chart/{symbol}?range={data_range}&interval={data_interval}'.format(**locals()))
data = res.json()
body = data['chart']['result'][0]
dt = datetime.datetime
dt = pd.Series(map(lambda x: arrow.get(x).to('EST').datetime.replace(tzinfo=None), body['timestamp']), name='Datetime')
df = pd.DataFrame(body['indicators']['quote'][0], index=dt)
dg = pd.DataFrame(body['timestamp'])

return df.loc[:, ('open', 'high', 'low', 'close', 'volume')]

data = get_quote_data('SBIN.NS', '1d', '1m')
data.dropna(inplace=True) #removing NaN rows
print(data)`

When i changed EST to IST (Indian standard time) it throws an error as "ParserError: Could not parse timezone expression "IST" "

Do you have anyidea so that it reflect datetime column correctly

@kongaraman
Copy link

I am able to change to Indian standard time by using 'Asia/Calcutta'. Referred this from link https://raw.githubusercontent.com/SpiRaiL/timezone/master/timezone.py

Modified code which now works for IST is:

import requests
import pandas as pd
import arrow
import datetime

def get_quote_data(symbol='SBIN.NS', data_range='1d', data_interval='1m'):
    res = requests.get('https://query1.finance.yahoo.com/v8/finance/chart/{symbol}?range={data_range}&interval={data_interval}'.format(**locals()))
    data = res.json()
    body = data['chart']['result'][0]    
    dt = datetime.datetime
    dt = pd.Series(map(lambda x: arrow.get(x).to('Asia/Calcutta').datetime.replace(tzinfo=None), body['timestamp']), name='Datetime')
    df = pd.DataFrame(body['indicators']['quote'][0], index=dt)
    dg = pd.DataFrame(body['timestamp'])
    
    return df.loc[:, ('open', 'high', 'low', 'close', 'volume')]

data = get_quote_data('SBIN.NS', '1d', '1m')
data.dropna(inplace=True) #removing NaN rows
print(data)

@kongaraman
Copy link

import requests
import pandas as pd
import arrow
import datetime

def get_quote_data(symbol='SBIN.NS', data_range='1d', data_interval='1m'):
    res = requests.get('https://query1.finance.yahoo.com/v8/finance/chart/{symbol}?range={data_range}&interval={data_interval}'.format(**locals()))
    data = res.json()
    body = data['chart']['result'][0]    
    dt = datetime.datetime
    dt = pd.Series(map(lambda x: arrow.get(x).to('Asia/Calcutta').datetime.replace(tzinfo=None), body['timestamp']), name='Datetime')
    df = pd.DataFrame(body['indicators']['quote'][0], index=dt)
    dg = pd.DataFrame(body['timestamp'])    
    df = df.loc[:, ('open', 'high', 'low', 'close', 'volume')]
    df.dropna(inplace=True)     #removing NaN rows
    df.columns = ['OPEN', 'HIGH','LOW','CLOSE','VOLUME']    #Renaming columns in pandas
    
    return df

data = get_quote_data('KPIT.NS', '1d', '1m')
print(data)

@carly11
Copy link

carly11 commented Aug 10, 2018

Does anyone know why yahoo does not provide 30 minute data? I know that 1, 15, 60 work fine but not 30m.

@Rajasekaran1976
Copy link

how do you get 1, 15, 60 minute data from yahoo?

@carly11
Copy link

carly11 commented Aug 10, 2018

using the script posted just before my question.

@ynagendra
Copy link

The code above by kongaraman is wonderful. thanks for posting.

@kongaraman
Copy link

Thanks ynagendra

@kongaraman
Copy link

I noticed that yahoo data is not constant. For 1 minute, i observed that data gives differently for the same time period.

When i run the above python code, it should be the same for data, as long as i run any number of times.

Can someone have idea on this? Also this data is not exactly matching to actual exchange data.

I am not sure, why there is a difference. If anybody have idea then please post your comments.

@kongaraman
Copy link

Observed that there are many empty values while extracting data.

So i used df.dropna(inplace=True) #removing NaN rows

Infact the above line is not needed. We need to get good quality data, which is missing from above link.

@sanjayubs
Copy link

import requests
import pandas as pd
import arrow
import datetime

def get_quote_data(symbol='SBIN.NS', data_range='1d', data_interval='1m'):
    res = requests.get('https://query1.finance.yahoo.com/v8/finance/chart/{symbol}?range={data_range}&interval={data_interval}'.format(**locals()))
    data = res.json()
    body = data['chart']['result'][0]    
    dt = datetime.datetime
    dt = pd.Series(map(lambda x: arrow.get(x).to('Asia/Calcutta').datetime.replace(tzinfo=None), body['timestamp']), name='Datetime')
    df = pd.DataFrame(body['indicators']['quote'][0], index=dt)
    dg = pd.DataFrame(body['timestamp'])    
    df = df.loc[:, ('open', 'high', 'low', 'close', 'volume')]
    df.dropna(inplace=True)     #removing NaN rows
    df.columns = ['OPEN', 'HIGH','LOW','CLOSE','VOLUME']    #Renaming columns in pandas
    
    return df

data = get_quote_data('KPIT.NS', '1d', '1m')
print(data)

Hi,
I am getting error ModuleNotFoundError: No module named 'arrow'. I have installed arrow module, still it throws this error

@bertrandobi
Copy link

Thanks for great ideas.
I tried to apply kongaraman function on a list of stock tickers. when i pplied a for loop, i got the follwing error:

TypeError: 'NoneType' object has no attribute 'getitem'

@rkolagatla
Copy link

HI All,
The yahoo finance API seems to be stuck at March 28th 2019 and not returning any data post that. I am trying to import data for the NIFTYBANK NSE Index and also tried for other stocks as well. Are others also facing the same problem and can anyone suggest some alternatives for 1minute Data Provider for NSE Stocks.
Thanks,
Rajesh

@peter4apple
Copy link

Hi.
Was anyone able to get hourly information on stock prices, either individual or by S&P?

@aspiringguru
Copy link

seems to have stopped working, now isnt returning anything - could be me of course

URL is http://www.google.com/finance/getprices?i=60&p=1d&f=d,o,h,l,c,v&df=cpct&q=VOD&x=LON
Empty DataFrame
Columns: []
Index: []
done

when I run that URL in the browser, it thinks I'm a bot and shuts me down, any way around that please ?

ta

that url failed for me as well.

We're sorry...
... but your computer or network may be sending automated queries. To protect our users, we can't process your request right now.

@earlcharles1
Copy link

import requests
import pandas as pd
import arrow
import datetime

def get_quote_data(symbol='SBIN.NS', data_range='1d', data_interval='1m'):
    res = requests.get('https://query1.finance.yahoo.com/v8/finance/chart/{symbol}?range={data_range}&interval={data_interval}'.format(**locals()))
    data = res.json()
    body = data['chart']['result'][0]    
    dt = datetime.datetime
    dt = pd.Series(map(lambda x: arrow.get(x).to('Asia/Calcutta').datetime.replace(tzinfo=None), body['timestamp']), name='Datetime')
    df = pd.DataFrame(body['indicators']['quote'][0], index=dt)
    dg = pd.DataFrame(body['timestamp'])    
    df = df.loc[:, ('open', 'high', 'low', 'close', 'volume')]
    df.dropna(inplace=True)     #removing NaN rows
    df.columns = ['OPEN', 'HIGH','LOW','CLOSE','VOLUME']    #Renaming columns in pandas
    
    return df

data = get_quote_data('KPIT.NS', '1d', '1m')
print(data)

Works great, but is there a way to save this data to a CSV file?

@lebedov
Copy link
Author

lebedov commented Nov 25, 2020

import requests
import pandas as pd
import arrow
import datetime

def get_quote_data(symbol='SBIN.NS', data_range='1d', data_interval='1m'):
    res = requests.get('https://query1.finance.yahoo.com/v8/finance/chart/{symbol}?range={data_range}&interval={data_interval}'.format(**locals()))
    data = res.json()
    body = data['chart']['result'][0]    
    dt = datetime.datetime
    dt = pd.Series(map(lambda x: arrow.get(x).to('Asia/Calcutta').datetime.replace(tzinfo=None), body['timestamp']), name='Datetime')
    df = pd.DataFrame(body['indicators']['quote'][0], index=dt)
    dg = pd.DataFrame(body['timestamp'])    
    df = df.loc[:, ('open', 'high', 'low', 'close', 'volume')]
    df.dropna(inplace=True)     #removing NaN rows
    df.columns = ['OPEN', 'HIGH','LOW','CLOSE','VOLUME']    #Renaming columns in pandas
    
    return df

data = get_quote_data('KPIT.NS', '1d', '1m')
print(data)

Works great, but is there a way to save this data to a CSV file?

data.to_csv('output.csv')

@adgestars007
Copy link

adgestars007 commented Nov 27, 2020

To sum up this string..
Step 1: Install python: https://www.python.org/downloads/
Step 2: Install panda: pip install panda
Step 3: Save this code:
'
import requests
import pandas as pd
import arrow
import datetime

def get_quote_data(symbol='SBIN.NS', data_range='1d', data_interval='1m'):
res = requests.get('https://query1.finance.yahoo.com/v8/finance/chart/{symbol}?range={data_range}&interval={data_interval}'.format(**locals()))
data = res.json()
body = data['chart']['result'][0]
dt = datetime.datetime
dt = pd.Series(map(lambda x: arrow.get(x).to('Asia/Calcutta').datetime.replace(tzinfo=None), body['timestamp']), name='Datetime')
df = pd.DataFrame(body['indicators']['quote'][0], index=dt)
dg = pd.DataFrame(body['timestamp'])

return df.loc[:, ('open', 'high', 'low', 'close', 'volume')]

data = get_quote_data('SBIN.NS', '5d', '1m')
data.dropna(inplace=True) #removing NaN rows
print(data)
data.to_csv('output.csv')
'
Step 4: Drag the saved python file to CMD and an output CSV will be saved.

@atulsahire
Copy link

what is the symbol for NIFTY50 data

@syedshahab698
Copy link

what is the symbol for NIFTY50 data

Yahoo finance symbol for nifty 50 = '^NSEI'

@sairam18814
Copy link

import requests
import pandas as pd
import arrow
import datetime

def get_quote_data(symbol , data_range='1d', data_interval='1m'):
res = requests.get('https://query1.finance.yahoo.com/v8/finance/chart/{symbol}?range={data_range}&interval={data_interval}'.format(**locals()))
data = res.json()
body = data['chart']['result'][0]
dt = datetime.datetime
dt = pd.Series(map(lambda x: arrow.get(x).to('Asia/Calcutta').datetime.replace(tzinfo=None), body['timestamp']), name='Datetime')
df = pd.DataFrame(body['indicators']['quote'][0], index=dt)
dg = pd.DataFrame(body['timestamp'])
df = df.loc[:, ('open', 'high', 'low', 'close', 'volume')]
df.dropna(inplace=True)
df.columns = ['OPEN', 'HIGH','LOW','CLOSE','VOLUME']

return df

for s in symbol:
data = get_quote_data(s,'1d','1m')
data.to_csv(s.strip(".NS")+'.csv')

this is for multiple stock symbols

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment