Загрузка котировок валют с сайта finam.ru

Откроем страницу в Internet по адресу www.finam.ru, войдём в раздел Теханализ и выберем слева внизу пункт Экспорт котировок.

Попадём на страницу с адресом www.finam.ru/analysis/profile0000300007/. Выберем вверху из раскрывающегося списка раздел Мировые валюты, а справа – GBP/USD; остальные настройки – как показано на рис.1 (поставим диапазон дат из недалёкого прошлого, иначе можем получить сообщение об ошибке).

../_images/FinamQuotes-01.png

Рис. 1. Загрузка котировок с сайта finam.ru

Нажмём кнопку Получить файл внизу. Подтвердим загрузку файла (если появится диалог с вопросом). Откроем менеджер загрузок (во многих браузерах для этого достаточно нажать комбинацию клавиш Ctrl+J) и с помощью правой кнопки мыши скопируем в буфер адрес загруженного файла. Должно получиться что-то вроде этого:

http://195.128.78.52/GBPUSD_141201_141206.csv?market=5&em=86&code=GBPUSD&df=1&mf=11&yf=2014&from=01.12.2014&dt=6&mt=11&yt=2014&to=06.12.2014&p=2&f=GBPUSD_141201_141206&e=.csv&cn=GBPUSD&dtf=1&tmf=3&MSOR=1&mstime=on&mstimever=1&sep=3&sep2=1&datf=5&at=1

Здесь сначала указан IP адрес сервера finam.ru, далее после символа слеш идёт имя файла с расширением .csv, а затем, после знака вопроса – параметры в формате:

имяПараметра = значение

Параметры запроса разделены символом &. Порядок следования параметров имеет значение для сервера finam.ru.

Имя параметра Назначение Пример
market Номер рынка 5
em Номер инструмента 86
code Тикер инструмента GBPUSD
df Начальная дата, номер дня (1-31) 1
mf Начальная дата, номер месяца (0-11) 11
yf Начальная дата, год 2014
from Начальная дата 01.12.2014
dt Конечная дата, номер дня 6
mt Конечная дата, номер месяца 11
yt Конечная дата, год 2014
to Конечная дата 06.12.2014
f Имя сформированного файла GBPUSD_141201_141206
p Таймфрейм 2
e Расширение сформированного файла .csv
cn Имя контракта GBPUSD
dtf Номер формата дат 1
tmf Номер формата времени 3
MSOR Время свечи (0 - open; 1 - close) 1
mstime Московское время on
mstimever Коррекция часового пояса 1
sep Разделитель полей 3
sep2 Разделитель разрядов 1
datf Формат записи в файл 5
at Нужны ли заголовки столбцов 1

Месяцы нумеруются, начиная с 0; дни – с 1. Если в форме поставить галочку Московское время, то в запросе появится параметр mstime=on, если не поставить – данный параметр будет отсутствовать. Аналогично для параметра at – он появится в строке запроса, только если поставить галочку Добавить заголовок файла. Параметр p для тиковых данных должен быть равен 1; для минуток – 2; для 5-минуток – 3; 10-минуток – 4; ... ; для часового таймфрейма – 7; дневного – 8; недельного – 9; месячного – 10. Для тиковых данных параметр datf лучше всего задавать равным 11, для всех остальных таймфреймов – 5. Параметр market (рынок) для мировых индексов равен 6, для мировых валют – 5, для фьючерсов США – 7, для фьючерсов ФОРТС – 14 (но эксперименты показали, что данный параметр может принимать любое значение, полученный результат от этого не изменяется).

Теперь попробуем отправить на сервер finam.ru тот же самый запрос средствами Python:

from urllib2 import urlopen # Импортировали библиотеку для работы с адресами и запросами Internet.
url = "http://195.128.78.52/GBPUSD_141201_141206.csv?market=5&em=86&code=GBPUSD&df=1&mf=11&yf=2014&from=01.12.2014&dt=6&mt=11&yt=2014&to=06.12.2014&p=2&f=GBPUSD_141201_141206&e=.csv&cn=GBPUSD&dtf=1&tmf=3&MSOR=1&mstime=on&mstimever=1&sep=3&sep2=1&datf=5&at=1"
f = urlopen(url)   # Открыли соединение.
data1 = f.read()   # Прочитали данные.
f.close()          # Закрыли соединение.

Выведем на экран полученные данные:

print(data1[:500]) # Первые 500 символов полученных данных.
<DATE>;<TIME>;<OPEN>;<HIGH>;<LOW>;<CLOSE>;<VOL>
20141201;00:01:00;1.5652000;1.5652000;1.5652000;1.5652000;1
20141201;00:02:00;1.5652000;1.5652000;1.5652000;1.5652000;2
20141201;00:03:00;1.5652000;1.5652000;1.5651000;1.5652000;6
20141201;00:04:00;1.5651000;1.5653000;1.5651000;1.5652000;18
20141201;00:05:00;1.5652000;1.5652000;1.5652000;1.5652000;2
20141201;00:06:00;1.5652000;1.5652000;1.5651000;1.5652000;4
20141201;00:07:00;1.5652000;1.5652000;1.5652000;1.5652000;1
20141201;00:08:00;1.565

После изучения формата получаемых данных, мы можем использовать стандартный парсер, чтобы выделить значения в отдельных столбцах и упаковать их в объект DataFrame:

from pandas import DataFrame, read_csv  # Чтобы упаковать результат в стандартный DataFrame.
data = read_csv(url, header=0, index_col=0, parse_dates={'Date&Time': [0, 1]}, sep=';').sort_index()
data.columns = ['' + i for i in ['Open', 'High', 'Low', 'Close', 'Volume']] # Заголовки столбцов

from pandas import set_option
set_option('display.max_columns', 50) # Кол-во колонок
set_option('display.width', 500)      # и ширина поля вывода
                                      # (чтобы при выводе не переносило широкие таблицы).

print(data.head())  # Вывели первые строки набора данных.

Получили:

                       Open    High     Low   Close  Volume
Date&Time
2014-12-01 00:01:00  1.5652  1.5652  1.5652  1.5652       1
2014-12-01 00:02:00  1.5652  1.5652  1.5652  1.5652       2
2014-12-01 00:03:00  1.5652  1.5652  1.5651  1.5652       6
2014-12-01 00:04:00  1.5651  1.5653  1.5651  1.5652      18
2014-12-01 00:05:00  1.5652  1.5652  1.5652  1.5652       2

К сожалению, тиковые данные для валют finam.ru не предоставляет.

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

Для этого будем использовать функцию urlencode из пакета urllib:

from urllib import urlencode
from datetime import datetime
periods = {'tick': 1, 'min': 2, '5min': 3, '10min': 4, '15min': 5, '30min': 6, 'hour': 7, 'daily': 8, 'week': 9, 'month': 10}
FINAM_URL = "http://195.128.78.52/table.csv?"
market = 5
start_date_str = "01.12.2014"
end_date_str = "06.12.2014"
start_date = datetime.strptime(start_date_str, "%d.%m.%Y").date()
end_date = datetime.strptime(end_date_str, "%d.%m.%Y").date()
period = 2
symbol_code = 86
symbol = "GBPUSD"
# Формируем строку с параметрами запроса:
params = urlencode([('market', 5), ('em', symbol_code), ('code', symbol),
                   ('df', start_date.day), ('mf', start_date.month - 1), ('yf', start_date.year),
                   ('from', start_date_str),
                   ('dt', end_date.day), ('mt', end_date.month - 1), ('yt', end_date.year),
                   ('to', end_date_str),
                   ('p', period), ('f', "table"), ('e', ".csv"), ('cn', symbol),
                   ('dtf', 1), ('tmf', 3), ('MSOR', 1), ('mstime', "on"), ('mstimever', 1),
                   ('sep', 3), ('sep2', 1), ('datf', 5), ('at', 1)])

url = FINAM_URL + params # Полная строка адреса со всеми параметрами.
# Соединяемся с сервером, получаем данные и выполняем их разбор:
data = read_csv(url, header=0, index_col=0, parse_dates={'Date&Time': [0, 1]}, sep=';').sort_index()
data.columns = ['' + i for i in ['Open', 'High', 'Low', 'Close', 'Volume']] # Заголовки столбцов
print(data.head())

Получили:

                         Open    High     Low   Close  Volume
Date&Time
2014-12-01  00:01:00   1.5652  1.5652  1.5652  1.5652       1
2014-12-01  00:02:00   1.5652  1.5652  1.5652  1.5652       2
2014-12-01  00:03:00   1.5652  1.5652  1.5651  1.5652       6
2014-12-01  00:04:00   1.5651  1.5653  1.5651  1.5652      18
2014-12-01  00:05:00   1.5652  1.5652  1.5652  1.5652       2

Осталось только выяснить, как узнать номер инструмента. Список всех тикеров доступен по адресу www.finam.ru/cache/icharts/icharts.js:

finam_symbols = urlopen('http://www.finam.ru/cache/icharts/icharts.js').readlines()
print(finam_symbols)
["var aEmitentIds = [15765,15997,16167,16288,16289,22832,15289,15016,15017,
15405,15952,18203,15330,15018,17342,18619,16601,17947,17946,392,390,1007,389,413,419,393,391,1008,15739,385,386,384,15305,15494,
...
...
'b68','b75','b76'];rn",
'var aEmitentNames = ['RTS.!AK1M','RTS.SGMLG','RTS.-RUR','RTS.TAGRG','RTS.TAGRPG',
...
xefxf0xeexecxfbxf8xebxe5xedxedxeexf1xf2xfc','xc8xedxe2xe5xf1xf2xe8xf6xe8xe8 xe2 IT'];rn',
"var aEmitentCodes = ['!AK1M','SGMLG','-RUR','TAGRG','TAGRPG','!ATE1','RTS.!CMLZ','!CMPZ','RTS.!DCNU','!DTMR',
'RTS.!GBKL','!GKCN','!HL56','!INEC','!INST','!KFKR','!KOSM','!LMLK','!MMSP','RTS.!MZHK','RTS.!PPRT','!RFRT',
'!TGMK','!TISH','!ZDMP','!ZMLK','#BRUT','#KVAS','#KVASG','#PYRA','#PYRAG','#RTSX','#TEST','#UMOR',
,'','','','','','','','','','','','','','','','','',''];rn",
'var aEmitentMarkets = [20,18,18,18,18,20,18,20,18,32,18,20,20,20,20,32,20,
...
-1,-1,-1,-1,-1,-1,-1,-1,-1];rn',
"var aEmitentDecp = {15765:4,15997:4,16167:4,16288:4,16289:4,22832:4,15289:4,15016:4,15017:4,16663:4,15019:4,18877:4,16934:4,
...
'b57':0,'b62':0,'b59':0,'b61':0,'b63':0,'b71':0,'b68':0,'b75':0,'b76':0};rn",
"var aDataFormatStrs = ['TICKER, PER, DATE, TIME, OPEN, HIGH, LOW, CLOSE, VOL',
...
TIME, LAST, VOL','DATE, TIME, LAST','DATE, TIME, LAST, VOL, ID'];rn", 'rn',
'var aEmitentChild = [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
...
0,1,1,0,0,0,0,1,1,1,0,1,1,0,0];']

Здесь мы прочитали длинный список идентификаторов aEmitentIds, названий aEmitentNames и кодов aEmitentCodes. Нам потребуется первый и третий (точнее, нулевой и второй):

str_id = str(finam_symbols[0])
str_code = str(finam_symbols[2])

Пробежим по списку кодов и найдём соответствующий номер:

start = str(str_code).find("[\'") + 2
end = str_code.find("\']")
names = str_code[start : end].split('\',\'')
ids = str_id[str_id.find('[') + 1 : str_id.find(']')].split(',')
if symbol in names: # Если искомый тикер symbol имеется в списке names.
    k = 0
    for i, name in enumerate(names):
        if name == symbol:
            k = i
            break
    symbol_code = ids[k]
    print(symbol_code)
else:
    raise Exception("%s not found\r\n" % symbol)

Получили:

86

Теперь мы можем по строке тикера узнать номер инструмента.

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


Теги: Python




Комментарии (3)

Вы просматриваете: FinamDownloader
Facebookdel.icio.usStumbleUponDiggGoogle+Twitter
Gravatar
ProfiTraders говорит...
> номера тикеров по акциям не правильно ищутся.
> Например GAZP выдается 16827, на сайте же он под номером 16842

Поэтому и название "Загрузка котировок валют".
Если загружать всё, что возможно, то надо ещё немного помучиться.
Ведь нужен ещё номер маркета.
На курсах мы полный вариант рассматриваем.
10th January 2017 11:48am
Gravatar
Иван говорит...
Отличная статья. Но есть одно но: номера тикеров по акциям не правильно ищутся. Например GAZP выдается 16827, на сайте же он под номером 16842
9th January 2017 1:30pm
Gravatar
Павел говорит...
Спасибо за статью! Давно хотел сделать простенькое обновление данных на компьютере с финама, всё руки не доходили. Сэкономил кучу времени.
16th July 2015 3:13am
Страница 1 из 1

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