Заголовок обязывает перейти непосредственно к программному коду… Но, думаю, все же необходима вводная часть. А зачем, собственно, это нужно?

Эффективные действия на бирже связаны с тщательным анализом происходящего на рынке. Что кроется за динамикой цифр, котировок?

Отсутствие такого анализа, либо сумбурное принятие решений по сделке может привести к потерям. Мне не раз приходилось наблюдать за тем, как люди принимали решения — правильные… или не правильные — в дилинговом зале брокерской конторы.

Дилинговые залы брокерских контор… там существует своя, особая атмосфера. Атмосфера общения, обмена опытом, эмоциями. Мне нравятся дилинговые залы. По тому как человек входит в сделку, трейдеров можно разделить на две группы. Я буду говорить о тех, чей результат, как правило, печален. И таких трейдеров — большинство. Итак — описываю процесс входа в рынок трейдера соответствующей группы. В дилинговый зал вбегает мужчина лет 20-60 выкрикивает: «Куда идем?! Вверх?! Вниз?!» Со стороны встречающих слышаться неоднозначные выкрики «Вверх! Вниз!» Новоприбывший присоединяется к наиболее громко крикнувшей группе и… делает ТЫЦ. ТЫЦ по кнопке покупки или продажи. Все. Теперь человек в рынке. С этого момента он рискует своими деньгами. С этого момента трейдер не похож на трейдера. Он похож на болельщика. Вувузела в руках такого трейдера, думаю, была бы уместным инструментом торговли.


И теперь он уже в составе группы переживает, и со стоном воспринимает все движения рынка. А на новостях получает такой всплеск адреналина, который парням, карабкающимся по склонам горных хребтов, может только сниться.

Результат таких сделок вполне предсказуем. Но… есть ли более счастливый исход? Конечно. И связан он с анализом данных котировок. Как получить эти данные? Как получить эти данные в больших объемах? Как здорово, что есть такая замечательная компания «ФИНАМ» и их интернет-ресурс finam.ru! Сервера «ФИНАМ» предоставляют замечательную возможность — скачивать котировки, например вот по такой форме (например):



Однако, таким образом предоставляется возможность скачать лишь один файл за одну загрузку. А что если мы хотим получить больше данных для анализа? Гораздо больше? Практически по всем инструментам! По всем периодам! Это даст богатейшие возможности для анализа данных. Оу… возможно ли такое? Ответ: да возможно.

Пока же определимся с перечнем бумаг (инструментов), а также с основными принципиальными моментами, которые позволят нам получить данные о котировках. Перечень бумаг (инструментов) которые предоставляться компанией «ФИНАМ» будем брать отсюда:



Эта страница интересна для нас тем, что на ней есть, во-первых, большая часть инструментов которые дает «ФИНАМ»; во-вторых, веб-ссылки, по которым можно перейти непосредственно на страницу каждой ценной бумаги (инструмента).

Ссылки имеют следующий вид:

www.finam.ru/profile/moex-akcii/polymetal-international-plc/export
www.finam.ru/profile/moex-akcii/pllc-yandex-n-v/export
www.finam.ru/profile/moex-akcii/alrosa-ao/export

Пропарсив соответствующую станицу получим файл ссылок. Теперь мы знаем где «живут» инструменты. Файл можете скачать по этой ссылке. Зачем нам место жительства каждого инструмента? Этот параметр нам еще пригодится. Запаситесь терпением. Пока имеем ссылки по 6131 бумаге (инструменту).

Что требует сервер «ФИНАМ»? Какие параметры для получения данных? Давайте попробуем получить один файл, и посмотрим параметры запроса. Скачивая котировки компании Polymetal, имею вот такой GET запрос:
__http://export.finam.ru/POLY_170620_170623.txt?market=1&em=175924&code=POLY&apply=0&df=20&mf=5&yf=2017&from=20.06.2017&dt=23&
mt=5&yt=2017&to=23.06.2017&p=8&f=POLY_170620_170623&e=.txt&cn=POLY&dtf=1&tmf=1&
MSOR=1&mstime=on&mstimever=1&sep=1&sep2=1&datf=1&at=1

Среди всего перечня хотелось бы акцентировать внимание на параметрах em, market, code. Параметр em следует понимать как индекс, своеобразную метку бумаги (инструмента). Если мы хотим скачивать не один инструмент, а массив данных по нескольким бумагам (инструментам) мы должны знать em каждого из них. Переменная market говорит о том, где вращается данная бумага (инструмент) – на каком рынке? Маркетов много: МосБиржа топ***, МосБиржа пифы***, МосБиржа облигации***, Расписки и т.д. Параметр code – это символьная переменная по инструменту.

Итак, для получения файла котировок нам нужно добыть эти три параметра: em и market и code. По всем бумагам (инструментам). Вопрос — где их взять? Ответ: вспоминаем о файле со ссылками. В файле есть, например, такая ссылка:

www.finam.ru/profile/moex-akcii/polymetal-international-plc/export

Зайдем на нее и в исходном коде страницы увидим то, что нам нужно — в элементах javascript сидят наши искомые параметры, которые относятся к данной бумаге (инструменту):

Finam.IssuerProfile.Main.issue = {"quote": {"id": 175924, "code": "POLY", "fullUrl": "moex-akcii/polymetal-international-plc", "title": "Polymetal", "decp": 1, "testDriveEnabled": false, "market": {"id": 1, "title": "МосБиржа акции", "volumeEnabled": true},"info": {"decp": 1, "last": 680, "pchange": 1.87266, "change": 12.50001, "bid": null, "ask": null, "open": 668, "high": 686, "low": 666, "close": 667.5, "volume": 53037, "date": "05.07.2017 18:47:18", "weekMin": 653.5, "weekMax": 688, "monthMin": 653.5, "monthMax": 753, "yearMin": 572, "yearMax": 1009.5,"currency": "руб.","volumeCode": "шт."},"
/*…тут еще куча важных параметров, но они нам не нужны …*/
 175924, "url": "/profile/moex-akcii/polymetal-international-plc/secondary/", }, "corporativeEvents": {"quote": 175924, "url": "/profile/moex-akcii/polymetal-international-plc/corporate/", }, "blogsAndGraphs": {"quote": 175924, "url": "__http://whotrades.com/markets/instrument/polymetal-international-plc", "count": "1", "pageSize": 1, "pageNumber": 1, "pagesCount": 1}}};

Заметим, что в данном кусочке кода id — это и есть em; имеется параметр code, а также параметры маркета – id и его русскоязычное название. Данный кусок кода с вариациями присутствует у каждого бумаги (инструмента). Сходим, например, на:

www.finam.ru/profile/moex-akcii/pllc-yandex-n-v/export
www.finam.ru/profile/moex-akcii/alrosa-ao/export

и увидим все то же самое. Теперь, думаю, общая цепочка получения данных понятна: в цикле перебираем ссылки, где живут отдельные бумаги (инструменты). Парсим кусочки javascript, собирая параметры em, market и code для каждой позиции. Имея на руках эти данные, можем программно заходить на сервер «ФИНАМ» и получать файлы котировок. Осталось дело за техникой исполнения.

Чем будем парсить? Парсить будем, используя Java. И… из всех велосипедов я выбираю тот, который стоит у меня в гараже. А именно Jsoup. Хотя можно было бы использовать и htmlunit.



Небольшое уточнение. При парсинге страницы мною были получены также данные – русскоязычное название бумаги (1) и раздел, в который «ФИНАМ» определили данную бумагу (инструмент) (2). Таким образом, на входе парсера имеется три файла. Напомню, имеем 6131 позиций — бумаг (инструментов). Всю эту информацию, а также результаты парсинга объединим в один файл. Код парсера можно скачать по этой ссылке.

В результате выполнения имеем файл function_parameters.csv. Каждая строка файла при построчном считывании может использоваться как перечень параметров для функции обращения к серверу «ФИНАМ» за котировками. Файл function_parameters.csv можно скачать по этой ссылке.

Для того чтобы написать функцию обращения к серверу «ФИНАМ» (а писать мы будем ее на Python), еще раз рассмотрим параметры GET запроса:
__http://export.finam.ru/POLY_170620_170623.txt?market=1&em=175924&code=POLY&apply=0&df=20&mf=5&yf=2017&from=20.06.2017&dt=23&
mt=5&yt=2017&to=23.06.2017&p=8&f=POLY_170620_170623&e=.txt&cn=POLY&dtf=1&tmf=1&
MSOR=1&mstime=on&mstimever=1&sep=1&sep2=1&datf=1&at=1

POLY_170620_170623 – очевидно, что данная строка представляет параметр code, а также временные характеристики.

.txt – расширение файла; расширение упоминается в параметре e; при написании функции следует помнить об этом нюансе.

Примем также во внимание содержимое исходного кода страницы типа www.finam.ru/profile/moex-akcii/gazprom/export внутри тэга form (где name=«exportdata»). Характеризуем показатели.

market, em, code – об этих параметрах, упоминал ранее, при обращении к функции их значения будут приниматься из файла.
df, mf, yf, from, dt, mt, yt, to – это параметры времени.
p — период котировок (тики, 1 мин., 5 мин., 10 мин., 15 мин., 30 мин., 1 час, 1 день, 1 неделя, 1 месяц)
e – расширение получаемого файла; возможны варианты — .txt либо .csv
dtf — формат даты (1 — ггггммдд, 2 — ггммдд, 3 — ддммгг, 4 — дд/мм/гг, 5 — мм/дд/гг)
tmf — формат времени (1 — ччммсс, 2 — ччмм, 3 — чч: мм: сс, 4 — чч: мм)
MSOR — выдавать время (0 — начала свечи, 1 — окончания свечи)
mstimever — выдавать время (НЕ московское — mstimever=0; московское — mstime='on', mstimever='1')
sep — параметр разделитель полей (1 — запятая (,), 2 — точка (.), 3 — точка с запятой (;), 4 — табуляция (»), 5 — пробел ( ))
sep2 — параметр разделитель разрядов (1 — нет, 2 — точка (.), 3 — запятая (,), 4 — пробел ( ), 5 — кавычка ('))
datf — Перечень получаемых данных (#1 — TICKER, PER, DATE, TIME, OPEN, HIGH, LOW, CLOSE, VOL; #2 — TICKER, PER, DATE, TIME, OPEN, HIGH, LOW, CLOSE; #3 — TICKER, PER, DATE, TIME, CLOSE, VOL; #4 — TICKER, PER, DATE, TIME, CLOSE; #5 — DATE, TIME, OPEN, HIGH, LOW, CLOSE, VOL; #6 — DATE, TIME, LAST, VOL, ID, OPER).
at — добавлять заголовок в файл (0 — нет, 1 — да)

После того, как определен перечень параметров, а также установлены источники получаемых данных, пишем вот такую функцию получения котировок. На примере одной бумаги – полюбившегося Polymetal.

# -*- coding: utf-8 -*-
"""
Created on Sat Jun 24 01:46:38 2017

@author: optimusqp
"""
import urllib


code='POLY';
e='.txt';
market='1'
em='175924';
e='.txt';
p='3';
yf='2017';
yt='2017';
month_start='05';
day_start='20';
month_end='06';
day_end='20';
dtf='1';
tmf='1';
MSOR='1';
mstimever='0'
sep='1';
sep2='3';
datf='1';
at='1';


year_start=yf[2:];
year_end=yt[2:];
mf=(int(month_start.replace('0','')))-1;
mt=(int(month_end.replace('0','')))-1;
df=(int(day_start.replace('0','')))-1;
dt=(int(day_end.replace('0','')))-1;


def quotes(code,year_start,month_start,day_start,year_end,month_end,day_end,e,market,em,df,mf,yf,dt,mt,yt,p,dtf,tmf,MSOR,mstimever,sep,sep2,datf,at):
    
    page = urllib.urlopen('http://export.finam.ru/'+str(code)+'_'+str(year_start)+str(month_start)+str(day_start)+'_'+str(year_end)+str(month_end)+str(day_end)+str(e)+'?market='+str(market)+'&em='+str(em)+'&code='+str(code)+'&apply=0&df='+str(df)+'&mf='+str(mf)+'&yf='+str(yf)+'&from='+str(day_start)+'.'+str(month_start)+'.'+str(yf)+'&dt='+str(dt)+'&mt='+str(mt)+'&yt='+str(yt)+'&to='+str(day_end)+'.'+str(month_end)+'.'+str(yt)+'&p='+str(p)+'&f='+str(code)+'_'+str(year_start)+str(month_start)+str(day_start)+'_'+str(year_end)+str(month_end)+str(day_end)+'&e='+str(e)+'&cn='+str(code)+'&dtf='+str(dtf)+'&tmf='+str(tmf)+'&MSOR='+str(MSOR)+'&mstimever='+str(mstimever)+'&sep='+str(sep)+'&sep2='+str(sep2)+'&datf='+str(datf)+'&at='+str(at))
    f = open("company_quotes.txt", "w")
    content = page.read()
    f.write(content)
    f.close()

qq = quotes(code,year_start,month_start,day_start,year_end,month_end,day_end,e,market,em,df,mf,yf,dt,mt,yt,p,dtf,tmf,MSOR,mstimever,sep,sep2,datf,at)

Код функции можно скачать также по этой ссылке.

Что дальше? Теперь возможно использовать данную функцию в цикле по имеющимся у нас позициям. Всего имеем, напомню, 6131 позицию. Из файла function_parameters.csv подгружаем параметры, указываем дату, выбираем нужный формат. И, используя данный код, не забудьте о правилах хорошего тона – поставьте задержку в пару секунд в итерацию цикла, дабы не перегружать сервер-источник.

Данных для анализа рынка, думаю, у вас будет предостаточно. Искренне надеюсь, что клиентов у компании «ФИНАМ» после написания данной статьи только прибавится!
Поделиться с друзьями
-->

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


  1. Merlen_Gross
    09.07.2017 17:09
    +2

    Как развидеть код? Искренне прошу автора научиться пользоваться либо format(), либо urlencode() для форматирования ссылок. И эта функция (ради функции) с огромным количеством параметров… Могу предположить, что автор не часто пишет на Python, но страданий от этого меньше не стало.


    1. optimusqp
      09.07.2017 17:22
      -2

      Я все же думаю что функцией пользоваться удобнее. «На вкус и цвет», как говорится.


      1. Crandel
        09.07.2017 22:31

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


        mf=(int(month_start.replace('0','')))-1;
        mt=(int(month_end.replace('0','')))-1;
        df=(int(day_start.replace('0','')))-1;
        dt=(int(day_end.replace('0','')))-1;


  1. lovermann
    09.07.2017 18:05
    +5

    Я вообще не понял, о чём эта статья. О том, как написать парсер нужных данных? Мы делаем это плюс-минус регулярно. Каких-то мегаинтересных идей или подходов я так увидеть и не мог. Ну, парсер и парсер… Кстати, не понял, почему в заголовке и в первом абзаце такой упор именно на котировки. Это обычные данные и далее в статье становится понятно, что вместо котировок могло быть что угодно. Или я чего-то не уловил?


    1. optimusqp
      09.07.2017 19:04
      -1

      Кому то нужны такие данные. Благодаря этой статье человек их получит. То что вы их делаете — это здорово. Задача не в том чтобы вас удивить, а научить тех кто хотел бы получить данные таким образом.


  1. yarric
    09.07.2017 18:22
    +1

    Почему бы не использовать готовые сервисы вроде Quandl с API и всеми делами?


    1. optimusqp
      09.07.2017 19:10

      Наверно можно. Вопрос вкуса, привычки к определенным инструментам )


      1. yarric
        09.07.2017 20:13

        Ну удобнее и быстрее же получается.


        1. optimusqp
          09.07.2017 20:19

          Ок, открываем ссылку здесь: http://i-intellect.ru/data-sources/1285/
          Там написано следующее:
          Quandl – это открытая платформа, которая обеспечивает доступ к более чем 9 миллионам бесплатных наборов данных. Quandl не обеспечивает внутридневные ценовые данные в режиме реального времени, но имеет огромное количество статистических и экономических данных из любой точки мира. Приведенный ЗДЕСЬ подход позволяет получить эти данные. Согласны?


          1. yarric
            09.07.2017 21:04

            Quandl я привёл как пример, кроме него есть ещё немало других. Честно говоря заходя в эту статью надеялся для себя узнать о других подобных сервисах с API.


            1. optimusqp
              09.07.2017 21:22

              Я так полагаю что критика должна быть конструктивной. Вы привели в пример Quandl. Сказали что он быстрее и удобней. Я привел аргументы почему это не так. Верно?


              1. yarric
                09.07.2017 22:36

                Быстрее и удобнее в плане написания клиентов. Впрочем по скорости доступа, скорее всего, тоже быстрее, чем парсинг такой ручной CSV.


    1. solver
      09.07.2017 20:20

      Покажете готовый сервис «с API и всеми делами», с данными бирж РФ?

      P.S. В ответе на этот вопрос и кроется суть проблемы.


      1. sshikov
        09.07.2017 21:47
        +2

        А что собственно за проблема? Те, кому на самом деле нужно торговать на бирже, так или иначе подключены к ней с целью заводить сделки. Частью большинства торговых терминалов является сервис, о котором вы спрашиваете. С API и всеми делами. Ну т.е. например, QUIK (quik), от той же компании ФИНАМ, чтоб далеко не ходить.

        Всех бирж РФ? Ну это вряд ли. Насколько я знаю, единого API не существует в природе. Лучшее на что можно рассчитывать — что данные от всех бирж будут приходить в одном формате, типа FIX/FixML.

        А то что тут описано, это какой-то самописный велосипед, непонятно для чего нужный.

        Брать котировки со страницы ФИНАМ? Хм. Даже для инструментов, которые там есть, вам никто ничего не гарантирует, потому что вы — не пользователь, а просто никто. Ни по качеству данных, ни по своевременности их предоставления нет никаких гарантий ровным счетом. Даже более того — если не регистрироваться, то вы будете видеть котировки с задержкой 15 минут.

        Это во-первых. Во-вторых, там четко написано, что источник данных — например московская биржа (*** Данные предоставлены ПАО Московская Биржа. Перераспространение информации только с разрешения Московской Биржи). Т.е., мы еще и лицензию потенциально нарушаем, а?

        И не проще в таком случае с сайта биржи и брать информацию, благо она там есть?

        В общем, тут описан подход, который ничуть не менее странный, чем принятие решений на основе «интуиции».


        1. optimusqp
          10.07.2017 01:26
          -1

          Ок. По пунктам:
          Квик — это продукт компании ARQA Technologies, не ФИНАМ.
          К сожалению Квик не обладает способностью выдавать котировки в том виде, в котором можно сделать, используя инструментарий данной статьи нужном объеме. Квик нужен для другого.
          Цель данной статьи — получение котировки по БОЛЬШОМУ количеству инструментов за довольно короткое время.
          Сколько вы будете делать это в КВИКЕ? Ну… можно конечно использовать Lua (даю вам подсказку). Но вы же говорите о Квике — верно? А точнее QLUA. Но получение большого количества данных связано определенно с автоматизацией этих потоков. А у QLUA такой же богатый статистический инструментарий библиотек как и у питона? Нет?
          На информацию по котировкам СО ВСЕХ БИРЖ РФ — об этом в тексте статьи не слова. Прочитайте внимательно, что вы пытаетесь критиковать.
          Если вы считаете это самописным велосипедом — пишите свой. Никто не заставляет вас применять инструменты описанные здесь. Флаг в руки, как говорится.
          Далее…
          Даже если мы получаем данные с задержкой в 15 минут — это не мешает нам анализировать информацию по часовикам. Верно?
          Мы абсолютно ничего не нарушаем. Информация в открытом доступе. Вы не знали этого?
          Спасибо за ваше «в общем» только аргументы ваши… довольно шаткие…
          И не мешало бы более уважительно относиться к собеседнику.


          1. sshikov
            10.07.2017 10:19
            +1

            Я нигде не говорил, что QUIK это продукт финама.

            Мы прекрасно получаем уже много лет котировки через QUIK. С Московской биржи. В полностью автоматическом режиме. Наверное, десятки тысяч инструментов примерно, порядка миллионов котировок в день (я точно не мерял).

            QUIK не для этого? Ну да, ну да. Расскажите это человеку, чья работа много лет состояла в том, чтобы обеспечивать трейдеров маркет данными.


        1. solver
          10.07.2017 09:54
          -3

          Почитайте что-ли к чему относился мой камент…
          Повторю для дислектиков.
          Вопрос:
          Почему бы не использовать готовые сервисы вроде Quandl с API и всеми делами?
          Ответ:
          Потому, что для РФ нет готовых сервисов «вроде Quandl с API и всеми делами».
          Везде есть какие-то проблемы и ограничения, которые делают этот процесс ничуть не удобнее описанного в статье.


  1. optimusqp
    10.07.2017 01:20
    -1

    Ок. По пунктам:
    Квик — это продукт компании ARQA Technologies, не ФИНАМ.
    К сожалению Квик не обладает способностью выдавать котировки в том виде, в котором можно сделать, используя инструментарий данной статьи нужном объеме. Квик нужен для другого.
    Цель данной статьи — получение котировки по БОЛЬШОМУ количеству инструментов за довольно короткое время.
    Сколько вы будете делать это в КВИКЕ? Ну… можно конечно использовать Lua (даю вам подсказку). Но вы же говорите о Квике — верно? А точнее QLUA. Но получение большого количества данных связано определенно с автоматизацией этих потоков. А у QLUA такой же богатый статистический инструментарий библиотек как и у питона? Нет?
    На информацию по котировкам СО ВСЕХ БИРЖ РФ — об этом в тексте статьи не слова. Прочитайте внимательно, что вы пытаетесь критиковать.
    Если вы считаете это самописным велосипедом — пишите свой. Никто не заставляет вас применять инструменты описанные здесь. Флаг в руки, как говорится.
    Далее…
    Даже если мы получаем данные с задержкой в 15 минут — это не мешает нам анализировать информацию почасовикам. Верно?
    Мы абсолютно ничего не нарушаем. Информация в открытом доступе. Вы не знали этого?
    Спасибо за ваше «в общем» только аргументы ваши… довольно шаткие…
    И не мешало бы более уважительно относиться к собеседнику.


    1. lazywicked
      10.07.2017 02:51

      есть старый готовый сервис — quotes-updater


      1. optimusqp
        10.07.2017 02:55
        -1

        Да, хорошая штуковина. Но… есть один важный момент. В данной же статье описана ФУНКЦИЯ. Которая при получении данных может с легкостью быть преобразована в нечто большее чем просто скачивание. Возможность обрабатывать данные на лету, до записи в файл… Ну вы понимаете о чем я ;)


  1. darkslave
    10.07.2017 10:40
    +2

    Внесу в дискуссию свою лепту.
    1. У ММВБ есть открытое api для доступа к котировкам и историческим данным.
    Но, к сожалению, по бесплатной подписке котировки идут с задержкой, а исторические данные ограничены.
    А подписка для получения онлайн котировок стоит весьма ощутимо для начинающего трейдера.
    2. Бесплатных api для доступа к котировкам ММВБ увы нет и, скорее всего, не будет, поскольку распространение торговых данных ограничено копирайтом ММВБ.
    3. Для получения онлайн котировок можно использовать FIX протокол, если торговая система имеет такую возможность. Quik предоставляет доступ через FIX, но этот протокол должен поддерживаться и брокером, через которого трейдер выходит на биржу. Опять же, увы, но чуть более чем никто из брокеров не поддерживает FIX протокол.
    4. Еще вариантом экспорта онлайн котировок может служить мост из терминала в свою систему. Например, тот же Quik предоставляет экспорт по DDE/ODBC, или же можно написать простенький скрипт на QLua, который отсылает данные по сокетам. Самый большой минус такого экспорта — инструменты для экспорта должны быть выбраны вручную.
    P.S.: Люди возмущены отсутствием читаемости и гибкости кода, и я с ними солидарен. Сам писал такой экспорт данных. По сути, функция должна принимать в качестве аргументов только то, что ей необходимо знать. А ей необходимо знать только: код эмитента, шаг времени, период дат для выгрузки. Все остальные параметры являются служебными и их стоит скрыть от прикладного программиста.


    1. optimusqp
      10.07.2017 10:47
      +1

      Респект за комментарий.