Source code for rtstock.utils

"""
Utility functions.

This module contains utility functions to gather information
from Yahoo Finance.
"""

from __future__ import unicode_literals
import datetime
import json
import os

try:
    # Python 3
    from urllib.request import urlopen, quote, urlretrieve
except ImportError:
    # Python 2
    from urllib2 import urlopen, quote
    from urllib import urlretrieve

from .error import RequestError


def __validate_list(list_to_validate):
    """Validate list."""
    if not type(list_to_validate) is list:
        raise TypeError(
            "List expected, " +
            type(list_to_validate).__name__ + " found."
        )


def __validate_dates(start_date, end_date):
    """Validate if a date string.

    Validate if a string is a date on yyyy-mm-dd format and it the
    period between them is less than a year.
    """
    try:
        start_date = datetime.datetime.strptime(start_date, '%Y-%m-%d')
        end_date = datetime.datetime.strptime(end_date, '%Y-%m-%d')
    except ValueError:
        raise ValueError("Incorrect data format, should be yyyy-mm-dd")
    if (end_date - start_date).days > 366:
        raise ValueError("The difference between start and end date " +
                         "should be less than or equal to 366 days.")
    if (end_date - start_date).days < 0:
        raise ValueError("End date cannot be before start date.")


def __yahoo_request(query):
    """Request Yahoo Finance information.

    Request information from YQL.
    `Check <http://goo.gl/8AROUD>`_ for more information on YQL.
    """
    query = quote(query)
    url = 'https://query.yahooapis.com/v1/public/yql?q=' + query + \
        '&format=json&env=store://datatables.org/alltableswithkeys'

    response = urlopen(url).read()

    return json.loads(response.decode('utf-8'))['query']['results']


[docs]def request_quotes(tickers_list, selected_columns=['*']): """Request Yahoo Finance recent quotes. Returns quotes information from YQL. The columns to be requested are listed at selected_columns. Check `here <http://goo.gl/8AROUD>`_ for more information on YQL. >>> request_quotes(['AAPL'], ['Name', 'PreviousClose']) { 'PreviousClose': '95.60', 'Name': 'Apple Inc.' } :param table: Table name. :type table: string :param tickers_list: List of tickers that will be returned. :type tickers_list: list of strings :param selected_columns: List of columns to be returned, defaults to ['*'] :type selected_columns: list of strings, optional :returns: Requested quotes. :rtype: json :raises: TypeError, TypeError """ __validate_list(tickers_list) __validate_list(selected_columns) query = 'select {cols} from yahoo.finance.quotes where symbol in ({vals})' query = query.format( cols=', '.join(selected_columns), vals=', '.join('"{0}"'.format(s) for s in tickers_list) ) response = __yahoo_request(query) if not response: raise RequestError('Unable to process the request. Check if the ' + 'columns selected are valid.') if not type(response['quote']) is list: return [response['quote']] return response['quote']
[docs]def request_historical(ticker, start_date, end_date): """Get stock's daily historical information. Returns a dictionary with Adj Close, Close, High, Low, Open and Volume, between the start_date and the end_date. Is start_date and end_date were not provided all the available information will be retrieved. Information provided by YQL platform. Check `here <http://goo.gl/8AROUD>`_ for more information on YQL. .. warning:: Request limited to a period not greater than 366 days. Use download_historical() to download the full historical data. >>> request_historical('AAPL', '2016-03-01', '2016-03-02') [ { 'Close': '100.75', 'Low': '99.639999', 'High': '100.889999', 'Adj_Close': '100.140301', 'Date': '2016-03-02', 'Open': '100.510002', 'Volume': '33169600' }, { 'Close': '100.529999', 'Low': '97.419998', 'High': '100.769997', 'Adj_Close': '99.921631', 'Date': '2016-03-01', 'Open': '97.650002', 'Volume': '50407100' } ] :param start_date: Start date :type start_date: string on the format of "yyyy-mm-dd" :param end_date: End date :type end_date: string on the format of "yyyy-mm-dd" :returns: Daily historical information. :rtype: list of dictionaries """ __validate_dates(start_date, end_date) cols = ['Date', 'Open', 'High', 'Low', 'Close', 'Volume', 'Adj_Close'] query = 'select {cols} from yahoo.finance.historicaldata ' + \ 'where symbol in ("{ticker}") and startDate = "{start_date}" ' + \ 'and endDate = "{end_date}"' query = query.format( cols=', '.join(cols), ticker=ticker, start_date=start_date, end_date=end_date ) response = __yahoo_request(query) if not response: raise RequestError('Unable to process the request. Check if the ' + 'stock ticker used is a valid one.') if not type(response['quote']) is list: return [response['quote']] return response['quote']
[docs]def download_historical(tickers_list, output_folder): """Download historical data from Yahoo Finance. Downloads full historical data from Yahoo Finance as CSV. The following fields are available: Adj Close, Close, High, Low, Open and Volume. Files will be saved to output_folder as <ticker>.csv. :param tickers_list: List of tickers that will be returned. :type tickers_list: list of strings :param output_folder: Output folder path :type output_folder: string """ __validate_list(tickers_list) for ticker in tickers_list: file_name = os.path.join(output_folder, ticker + '.csv') with open(file_name, 'wb') as f: base_url = 'http://real-chart.finance.yahoo.com/table.csv?s=' try: urlopen(base_url + ticker) urlretrieve(base_url + ticker, f.name) except: os.remove(file_name) raise RequestError('Unable to process the request. Check if ' + ticker + ' is a valid stock ticker')