Загрузка котировок с сайта Yahoo Finance

Использование Chart API для получения дневных и минутных котировок

Сайт Yahoo Finance бесплатно предоставляет информацию по основным финансовым рынкам, новости компаний, аналитику, а также котировки (как правило, с задержкой) большинства торговых инструментов: акций и валют.

Откроем в любом браузере страницу Internet по адресу

http://chartapi.finance.yahoo.com/instrument/1.0/AAPL/chartdata;type=quote;range=1d/csv/.

Получим минутные котировки AAPL за последние сутки (за это отвечает параметр range=1d):

uri:/instrument/1.0/AAPL/chartdata;type=quote;range=1d/csv/
ticker:aapl
Company-Name:Apple Inc.
Exchange-Name:NMS
unit:MIN
timezone:EST
currency:USD
gmtoffset:-18000
previous_close:109.7300
Timestamp:1418653800,1418677200
labels:1418655600,1418659200,1418662800,1418666400,1418670000,1418673600,1418677200
values:Timestamp,close,high,low,open,volume
close:107.1800,111.5284
high:107.4100,111.6000
low:106.3500,111.4300
open:107.2200,111.5200
volume:100,2002600
1418653859,111.1801,111.4900,110.7000,110.7000,2002600
1418653919,111.3400,111.4500,111.1800,111.1800,277300
1418653979,111.1400,111.3397,111.0000,111.2800,423800
1418654039,111.4610,111.4852,111.1400,111.1402,267300
1418654040,111.4900,111.5000,111.3700,111.4610,349000
...

Раскрывающийся список тикеров с автопродолжением можно найти на странице с адресом in.finance.yahoo.com/lookup.

Для диапазона, превышающего один день, сервер Yahoo Finance выдаст данные со старшего таймфрейма, например, 5-минутного.

Если в строке адреса задать параметр range в месяцах (m) или годах (y), например:

http://chartapi.finance.yahoo.com/instrument/1.0/MSFT/chartdata;type=quote;range=1y/csv/,

то будут получены ежедневные котировки (в данном случае котировки MSFT за последний год):

uri:/instrument/1.0/MSFT/chartdata;type=quote;range=1y/csv/
ticker:msft
Company-Name:Microsoft Corporation
Exchange-Name:NMS
unit:DAY
timestamp:
first-trade:19860313
last-trade:20141215
currency:USD
previous_close_price:36.6900
Date:20131216,20141215
labels:20131216,20140102,20140203,20140303,20140401,20140501,20140602,20140701,20140801,20140902,20141001,20141103,20141201
values:Date,close,high,low,open,volume
close:34.9800,49.6100
high:35.8800,50.0500
low:34.6300,49.3900
open:34.7300,49.7400
volume:14243000,202522400
20131216,36.8900,37.0000,36.5400,36.7300,31734200
20131217,36.5200,37.1100,36.3300,36.9400,45687700
20131218,36.5800,36.6000,35.5300,36.3600,63192100
20131219,36.2500,36.5500,36.0800,36.5100,34160100
20131220,36.8000,36.9300,36.1900,36.2000,62649100
...

Внутридневные котировки валют предоставляются сервером Yahoo Finance практически без задержки, а котировки акций задержаны на 15 минут. В дневных данных последним будет вчерашний бар.

Теперь попробуем отправить на сервер Yahoo Finance аналогичный запрос средствами Python. Для начальных экспериментов с программами на языке Python удобно использовать IPython Notebook.

from urllib2 import urlopen # Импортировали библиотеку для работы с адресами и запросами Internet.
ticker1 = "EURUSD=X"  # Тикер валютной пары EUR/USD.
range1 = "1y"  # 1 год.
# Строка адреса с параметрами:
url = "http://chartapi.finance.yahoo.com/instrument/1.0/"+ticker1+"/chartdata;type=quote;range="+range1+"/csv/"
text1 = urllib2.urlopen(url).read() # Получили текстовые данные с сервера.
text2 = text1.split('\n')           # Разделили на строки.

Необходимо выполнить разбор полученного текста и сформировать набор числовых данных, пригодных для использования в программе для отображения графиков и/или тестирования торговых стратегий.

Нам потребуется переменная для хранения номера текущего состояния анализатора текста, переменная для номера режима (0 – для минутных котировок, 1 – для дневных) и счётчик баров/свечей:

state = 0  # Номер состояния.
mode = 0   # Номер режима (1 - дневные данные, 2 - минутные).
count = 0  # Счётчик баров.

Кроме того, мы хотим записать полученные котировки в текстовый файл:

import csv                          # Модуль для работы с файлами CSV.
filename = "d:/Temp/EURUSD-D1.csv"  # Имя файла для записи котировок.
writer1 = csv.writer(open(filename, 'wb'), delimiter=',', quotechar='', quoting=csv.QUOTE_NONE)

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

import locale # Для перевода строковых данных в числовые.

def parse2values(t): # Функция для разбора строки, которая содержит два значения, разделённых запятой.
    s = t.split(',')      # Разделили строку на подстроки, разделённые запятой.
    a = locale.atof(s[0]) # Преобразовали в число первую подстроку.
    b = locale.atof(s[1]) # Преобразовали в число вторую подстроку.
    return [a, b]

Организуем цикл для перебора строк, содержащихся в полученных с сервера текстовых данных:

import datetime # Для работы с датой и временем.
data = [] # Здесь будем накапливать числовые данные.
for line in text2:  # Для каждой строки.
    # print(line+"\n")  # Вывод строки на экран (для отладки).
    if state == 0 and line[0:5] == "Date:":  # Обработка строки, начинающейся со слова "Date:".
        mode = 1
        state = 1

    if state == 0 and line[0:10] == "Timestamp:": # Обработка строки, начинающейся со слова "Timestamp:".
        mode = 2
        state = 1

    if state == 1 and line[0:7] == "values:":
        state = 2
        if state == 2:
            if line[0:7] == "values:":  # Обработка строки, начинающейся со слова "values:".
                pass
            elif line[0:6] == "close:": # Обработка строки, начинающейся со слова "close:".
                closeMax, closeMin = parse2values(line[6:])
            elif line[0:5] == "high:":  # Обработка строки, начинающейся со слова "high:".
                highMax, highMin = parse2values(line[5:])
            elif line[0:4] == "low:":   # Обработка строки, начинающейся со слова "low:".
                lowMax, lowMin = parse2values(line[4:])
            elif line[0:5] == "open:":  # Обработка строки, начинающейся со слова "open:".
                openMax, openMin = parse2values(line[5:])
            elif line[0:7] == "volume:": # Обработка строки, начинающейся со слова "volume:".
                volumeMax, volumeMin = parse2values(line[7:])
            else:
                state = 3

    if state == 3:
        valuesStr = line.split(',')     # Выделение подстрок, разделённых запятыми.
        if len(valuesStr) == 6:         # Если найдена строка с котировками (из 6 элементов).
            dateStr = valuesStr[0]      # Первый элемент - дата и, возможно, время.
            if mode == 1:               # Только дата.
                dt1 = datetime.datetime.strptime(dateStr, '%Y%m%d')
                fstr = "%Y-%m-%d"       # Строка формата для даты.
            else:                       # Дата и время.
                dt1 = datetime.datetime.fromtimestamp(int(dateStr))
                fstr = "%Y-%m-%d %H:%M" # Строка формата для даты и времени.

            # Преобразуем строковые данные в числовые:
            close1 = locale.atof(valuesStr[1]) # Цена закрытия бара.
            high1 = locale.atof(valuesStr[2])  # Максимальная цена бара.
            low1 = locale.atof(valuesStr[3])   # Минимальная цена бара.
            open1 = locale.atof(valuesStr[4])  # Цена открытия бара.
            vol1 = locale.atof(valuesStr[5])   # Объём.
            print(dt1.strftime(fstr) + " : %6.4f, %6.4f, %6.4f, %6.4f, %d" % (close1, high1, low1, open1, vol1)) # Вывели на экран.
            data.append([dt1, open1, high1, low1, close1, vol1]) # Добавили запись с котировками.

            # Запишем очередную строку в файл CSV в формате "Дата,Время,Открытие,Максимум,Минимум,Закрытие,Объём":
            writer1.writerow([dt1.date().strftime("%Y-%m-%d"), dt1.time().strftime("%H:%M"), open1 , high1, low1, close1, vol1])
            # (для дневных данных время будет нулевым).

            count += 1 # Счётчик баров.

        else: # Если больше нет котировок.
            state = -1 # Конец.

    if state < 0:
        break  # Прервали цикл.

print(data) # Вывели на экран.

После того, как мы по шагам исследовали процесс загрузки данных с сервера Yahoo Finance, можно оформить текст программы в виде отдельных функций, которые потом будет удобно использовать для получения котировок. Предлагаем это читателю в качестве упражнения. Как образец можно взять реализацию функции DataReader из пакета pandas.io.data.

Загрузчик дневных котировок Yahoo Finance из библиотеки pandas

В библиотеке pandas.io.data для скачивания дневных данных с сайта Yahoo Finance (и не только) имеется функция DataReader. В новых версиях пакета функция DataReader перенесена в отдельный пакет pandas_datareader.data.

# Для старых версия пакета pandas:
# from pandas.io.data import DataReader

# Для новых версий pandas (начиная с версии 0.17.0):
from pandas_datareader.data import DataReader

import datetime
symbol = "^GSPC"  # Код финансового инструмента на сайте Yahoo Finance (индекс S&P500).
start_date = datetime.datetime(2013, 7, 1) # Начальная дата - 1 июля 2013.
end_date = datetime.datetime(2014, 4, 30)  # Конечная дата - 30 апреля 2014.
ts1 = DataReader(symbol, "yahoo", start_date, end_date) # Отправили запрос на сервер и получили данные.
print(ts1.head(3)) # Вывели первые три строки полученных данных.
print(ts1.tail(2)) # Вывели последние две строки.

Получим:

               Open     High      Low    Close      Volume  Adj Close
Date
2013-07-01  1609.78  1626.61  1609.78  1614.96  3104690000    1614.96
2013-07-02  1614.29  1624.26  1606.77  1614.08  3317130000    1614.08
2013-07-03  1611.48  1618.97  1604.57  1615.41  1966050000    1615.41

[3 rows x 6 columns]
               Open    High      Low    Close      Volume  Adj Close
Date
2014-04-29  1870.78  1880.6  1870.78  1878.33  3647820000    1878.33
2014-04-30  1877.10  1885.2  1872.69  1883.95  3779230000    1883.95

[2 rows x 6 columns]

В каждой строке показана дата (столбец Date) в формате год-месяц-день; цена открытия (Open); максимальная (High) и минимальная цена (Low), достигнутая за данный день; цена закрытия (Close); биржевой объём (Volume) и скорректированная цена закрытия (Adjusted Close). Последний столбец учитывает разделение акций и выплату дивидендов; для индексов и валют значения в последнем столбце совпадают со значениями в столбце Close.

Для доступа к каждой строке таблицы можно использовать метод ix, например:

print ts1.ix['2014-03-10']
Open         1.877860e+03
High         1.877870e+03
Low          1.867040e+03
Close        1.877170e+03
Volume       3.021350e+09
Adj Close    1.877170e+03
Name: 2014-03-10 00:00:00, dtype: float64

Полученные данные могут быть использованы для построения графиков или тестирования торговых стратегий (об этом в следующих разделах).

Загрузчик дневных котировок Yahoo Finance из библиотеки matplotlib

В модуле matplotlib.finance имеются функции quotes_historical_yahoo_ochl и quotes_historical_yahoo_ohlc, предназначенные для загрузки дневных котировок с сайта Yahoo Finance.

Функцию quotes_historical_yahoo ещё можно встретить в старых программах, но использовать её больше не рекомендуется.

Пример простой программы, которая скачивает котировки AAPL и отображает их на графике:

import matplotlib.pyplot as plt
from matplotlib.finance import quotes_historical_yahoo_ochl, candlestick_ochl
from matplotlib.dates import YearLocator, MonthLocator, DateFormatter
import datetime

date1 = datetime.date(2012, 1, 1)     # Начальная дата.
date2 = datetime.date(2014, 12, 31)   # Конечная дата.

years = YearLocator()    # Ежегодная сетка.
months = MonthLocator()  # Ежемесячная сетка.
yearsFmt = DateFormatter('%Y')  # Форматная строка для оси абсцисс (только год).

quotes = quotes_historical_yahoo_ochl('AAPL', date1, date2) # Получили котировки.
if len(quotes) == 0:   # Если ничего не получено.
    raise SystemExit

# dates = [q[0] for q in quotes]    # Можно выделить только даты
# closes = [q[2] for q in quotes]   # и только цены закрытия.

fig, ax = plt.subplots()            # Создали график.
# ax.plot_date(dates, closes, '-', color='b')   # Линия по ценам закрытия.
candlestick_ochl(ax, quotes, width=0.6, colorup='g', colordown='r') # Свечной график.

ax.xaxis.set_major_locator(years)      # Установили шаг делений по оси абсцисс
ax.xaxis.set_major_formatter(yearsFmt) # и формат надписей.
ax.xaxis.set_minor_locator(months)
ax.autoscale_view()

# Функция для форматирования текущей ординаты в строке состояния:
def price(x):
    return '$%1.2f'%x

ax.fmt_xdata = DateFormatter('%Y-%m-%d')  # Формат для текущей абсциссы в строке состояния.
ax.fmt_ydata = price                      # Формат для текущей ординаты в строке состояния.
ax.grid(True)                             # Показывать сетку.

fig.autofmt_xdate()
plt.show()
../_images/YahooMatplotlib1.png

Рис. 1. График в виде японских свечей, построенный с помощью библиотеки matplotlib (слева — исходный вид; справа — фрагмент, увеличенный с помощью кнопок управления графиком)


Теги: Python




Комментарии

Комментариев пока нет.

* Обязательные поля
(Не публикуется)
 
Жирный Курсив Подчеркнутый Перечеркнутый Степень Индекс Код PHP Код Кавычки Вставить линию Вставить маркированный список Вставить нумерованный список Вставить ссылку Вставить e-mail Вставить изображение Вставить видео
 
Улыбка Печаль Удивление Смех Злость Язык Возмущение Ухмылка Подмигнуть Испуг Круто Скука Смущение Несерьёзно Шокирован
 
1000
Captcha
Refresh
 
Введите код:
 
Запомнить информацию введенную в поля формы.