Обход Pandas DataReader для финансов Google

Я ежедневно извлекаю исторические данные по большому количеству акций и ETF. Quandl имеет довольно хорошее бесплатное покрытие акций США, но у них нет исторических данных по ETF, поэтому я использую Google API в качестве резервной копии для Quandl.

Недавнее «обновление» финансов Google не оставило мне отличной альтернативы, поэтому я пытаюсь применить работу Брэда Соломона (спасибо, Брэд, ссылка ниже) к списку символов. Предположим, это маловероятно без цикла, учитывая, что он создает URL-адреса. Любые умные идеи приветствуются.

Связанный вопрос: Почему pandas_datareader для Google не работает ?

Спасибо.


person MJS    schedule 04.12.2017    source источник
comment
Проблема с Github находится здесь, если вы хотите ее отслеживать. Я никогда не участвовал в разработке пакета, но постараюсь сделать несколько запросов на включение в эти выходные.   -  person Brad Solomon    schedule 05.12.2017


Ответы (1)


Под капотом pandas-datareader перебирает каждый переданный вами символ и делает http-запросы один за другим.

Вот функция, которая делает это в базовом классе, от которого наследуются классы, связанные с google и yahoo: _ 1_.

Магия в том, что они добавляются к списку, а затем объединяются в pandas Panel.

Однако я хотел бы отметить, что Panel устарела, и вы можете получить ту же функциональность в DataFrame с помощью MultiIndex, структуры, которая технически двумерна, но на практике воспроизводит более высокие размерности.

Итак, вот основные моменты того, что вы могли сделать, ниже. Обратите внимание, что я пропускаю многие функции, встроенные в сам пакет, например синтаксический анализ дат строки на datetime.

import datetime
from io import StringIO

import requests
from pandas.io.common import urlencode
import pandas as pd

BASE = 'http://finance.google.com/finance/historical'


def get_params(sym, start, end):
    params = {
        'q': sym,
        'startdate': start.strftime('%Y/%m/%d'),
        'enddate': end.strftime('%Y/%m/%d'),
        'output': "csv"
    }
    return params


def build_url(sym, start, end):
    params = get_params(sym, start, end)
    return BASE + '?' + urlencode(params)


def get_one_data(sym, start=None, end=None):
    if not start:
        start = datetime.datetime(2010, 1, 1)
    if not end:
        end = datetime.datetime.today()
    url = build_url(sym, start, end)
    data = requests.get(url).text
    return pd.read_csv(StringIO(data), index_col='Date',
                       parse_dates=True).sort_index()


def get_multiple(sym, start=None, end=None, return_type='Panel'):
    if isinstance(sym, str):
        return get_one_data(sym, start=start, end=end)
    elif isinstance(sym, (list, tuple, set)):
        res = {}
        for s in sym:
            res[s] = get_one_data(s, start, end)
        # The actual module also implements a 'passed' and 'failed'
        #     check here and also using chunking to get around
        #     data retreival limits (I believe)

    if return_type.lower() == 'panel':
        return pd.Panel(res).swapaxes('items', 'minor')
    elif return_type.lower() == 'mi':  # MultiIndex DataFrame
        return pd.concat((res), axis=1)

Пример:

syms = ['AAPL', 'GE']
data = get_multiple(syms, return_type='mi')

# Here's how you would filter down to Close prices
#   on MultiIndex columns
data.xs('Close', axis=1, level=1) 

              AAPL     GE
Date                     
2010-01-04   30.57  15.45
2010-01-05   30.63  15.53
2010-01-06   30.14  15.45
2010-01-07   30.08  16.25
2010-01-08   30.28  16.60
...
person Brad Solomon    schedule 04.12.2017
comment
Спасибо, Брэд, хорошее понимание. Несмотря на недостатки, я обнаружил, что панели работают быстрее, чем многоиндексированные dfs для больших наборов данных. Надеюсь, что xarray быстро созреет. Цени свое время. - person MJS; 05.12.2017