Блог им. Albus

Качаем котировки с Финама

Недавно начал учить язык программирования Python. Жаль, что я к нему приступил в 36 лет, а не в 16. Он прекрасно подходит для анализа исторических данных. Выкладываю скрипт, который заходит на сайт финама, скачивает оттуда котировки акций и записывает их в файл quotes.txt. Для того, чтобы всё работало, должен быть установлен Питон https://www.python.org/.
---
В интернете есть информация, как качать котировки с Финама не вручную, а с помощью скрипта. Вот эти статьи. Ими я пользовался при написании своего кода:
Программный сбор данных о котировках
Загрузка котировок валют с сайта finam.ru
Дополнительно пришлось хорошенько поработать головой, чтобы адаптировать эту информацию для моих нужд. Там кое-что устарело и коды авторов потребовали доработки. Также в моём скрипте вы найдёте цифровые символы, которые соответствуют каждой акции. Например Алроса лежит на сайте финама под цифрой 81820.
Дополнительные библиотеки не нужны, всё должно работать сразу без дополнительных правок.
Я снабдил код описанием, чтобы было понятно в какой строчке что происходит.
Главная задача скрипта — составить строку вида 
export.finam.ru/SBER_20170101_20171231.csv?market=0&em=3&code=SBER&apply=0&df=1&mf=0&yf=2017&from=2017-01-01&dt=31&mt=11&yt=2017&to=2017-12-31&p=7&f=SBER_20170101_20171231&e=.csv&cn=SBER&dtf=1&tmf=1&MSOR=0&mstime=on&mstimever=1&sep=1&sep2=1&datf=1&at=1
она улетит на сервер финама, и в ответ прилетит файл с нужными котировками.
Вот какая информация в нём будет:
Качаем котировки с Финама
Скачать код скрипта:
https://yadi.sk/i/Iaz5EvbovXei3A
Можно не качать, а скопировать отсюда:
from urllib.parse import urlencode
from urllib.request import urlopen
from datetime import datetime
#пользовательские переменные
ticker="SBER" #задаём тикер
period=7 # задаём период. Выбор из: 'tick': 1, 'min': 2, '5min': 3, '10min': 4, '15min': 5, '30min': 6, 'hour': 7, 'daily': 8, 'week': 9, 'month': 10
start = "01.01.2017" #с какой даты начинать тянуть котировки
end = "31.12.2017" #финальная дата, по которую тянуть котировки
########
periods={'tick': 1, 'min': 2, '5min': 3, '10min': 4, '15min': 5, '30min': 6, 'hour': 7, 'daily': 8, 'week': 9, 'month': 10}
print ("ticker="+ticker+"; period="+str(period)+"; start="+start+"; end="+end)
#каждой акции Финам присвоил цифровой код:
tickers={'ABRD':82460,'AESL':181867,'AFKS':19715,'AFLT':29,'AGRO':399716,'AKRN':17564,'ALBK':82616,'ALNU':81882,'ALRS':81820,'AMEZ':20702,'APTK':13855,'AQUA':35238,'ARMD':19676,'ARSA':19915,'ASSB':16452,'AVAN':82843,'AVAZ':39,'AVAZP':40,'BANE':81757,'BANEP':81758,'BGDE':175840,'BISV':35242,'BISVP':35243,'BLNG':21078,'BRZL':81901,'BSPB':20066,'CBOM':420694,'CHEP':20999,'CHGZ':81933,'CHKZ':21000,'CHMF':16136,'CHMK':21001,'CHZN':19960,'CLSB':16712,'CLSBP':16713,'CNTL':21002,'CNTLP':81575,'DASB':16825,'DGBZ':17919,'DIOD':35363,'DIXY':18564,'DVEC':19724,'DZRD':74744,'DZRDP':74745,'ELTZ':81934,'ENRU':16440,'EPLN':451471,'ERCO':81935,'FEES':20509,'FESH':20708,'FORTP':82164,'GAZA':81997,'GAZAP':81998,'GAZC':81398,'GAZP':16842,'GAZS':81399,'GAZT':82115,'GCHE':20125,'GMKN':795,'GRAZ':16610,'GRNT':449114,'GTLC':152876,'GTPR':175842,'GTSS':436120,'HALS':17698,'HIMC':81939,'HIMCP':81940,'HYDR':20266,'IDJT':388276,'IDVP':409486,'IGST':81885,'IGST03':81886,'IGSTP':81887,'IRAO':20516,'IRGZ':9,'IRKT':15547,'ISKJ':17137,'JNOS':15722,'JNOSP':15723,'KAZT':81941,'KAZTP':81942,'KBSB':19916,'KBTK':35285,'KCHE':20030,'KCHEP':20498,'KGKC':83261,'KGKCP':152350,'KLSB':16329,'KMAZ':15544,'KMEZ':22525,'KMTZ':81903,'KOGK':20710,'KRKN':81891,'KRKNP':81892,'KRKO':81905,'KRKOP':81906,'KROT':510,'KROTP':511,'KRSB':20912,'KRSBP':20913,'KRSG':15518,'KSGR':75094,'KTSB':16284,'KTSBP':16285,'KUBE':522,'KUNF':81943,'KUZB':83165,'KZMS':17359,'KZOS':81856,'KZOSP':81857,'LIFE':74584,'LKOH':8,'LNTA':385792,'LNZL':21004,'LNZLP':22094,'LPSB':16276,'LSNG':31,'LSNGP':542,'LSRG':19736,'LVHK':152517,'MAGE':74562,'MAGEP':74563,'MAGN':16782,'MERF':20947,'MFGS':30,'MFGSP':51,'MFON':152516,'MGNT':17086,'MGNZ':20892,'MGTS':12984,'MGTSP':12983,'MGVM':81829,'MISB':16330,'MISBP':16331,'MNFD':80390,'MOBB':82890,'MOEX':152798,'MORI':81944,'MOTZ':21116,'MRKC':20235,'MRKK':20412,'MRKP':20107,'MRKS':20346,'MRKU':20402,'MRKV':20286,'MRKY':20681,'MRKZ':20309,'MRSB':16359,'MSNG':6,'MSRS':16917,'MSST':152676,'MSTT':74549,'MTLR':21018,'MTLRP':80745,'MTSS':15523,'MUGS':81945,'MUGSP':81946,'MVID':19737,'NAUK':81992,'NFAZ':81287,'NKHP':450432,'NKNC':20100,'NKNCP':20101,'NKSH':81947,'NLMK':17046,'NMTP':19629,'NNSB':16615,'NNSBP':16616,'NPOF':81858,'NSVZ':81929,'NVTK':17370,'ODVA':20737,'OFCB':80728,'OGKB':18684,'OMSH':22891,'OMZZP':15844,'OPIN':20711,'OSMP':21006,'OTCP':407627,'PAZA':81896,'PHOR':81114,'PHST':19717,'PIKK':18654,'PLSM':81241,'PLZL':17123,'PMSB':16908,'PMSBP':16909,'POLY':175924,'PRFN':83121,'PRIM':17850,'PRIN':22806,'PRMB':80818,'PRTK':35247,'PSBR':152320,'QIWI':181610,'RASP':17713,'RBCM':74779,'RDRB':181755,'RGSS':181934,'RKKE':20321,'RLMN':152677,'RLMNP':388313,'RNAV':66644,'RODNP':66693,'ROLO':181316,'ROSB':16866,'ROSN':17273,'ROST':20637,'RSTI':20971,'RSTIP':20972,'RTGZ':152397,'RTKM':7,'RTKMP':15,'RTSB':16783,'RTSBP':16784,'RUAL':414279,'RUALR':74718,'RUGR':66893,'RUSI':81786,'RUSP':20712,'RZSB':16455,'SAGO':445,'SAGOP':70,'SARE':11,'SAREP':24,'SBER':3,'SBERP':23,'SELG':81360,'SELGP':82610,'SELL':21166,'SIBG':436091,'SIBN':2,'SKYC':83122,'SNGS':4,'SNGSP':13,'STSB':20087,'STSBP':20088,'SVAV':16080,'SYNG':19651,'SZPR':22401,'TAER':80593,'TANL':81914,'TANLP':81915,'TASB':16265,'TASBP':16266,'TATN':825,'TATNP':826,'TGKA':18382,'TGKB':17597,'TGKBP':18189,'TGKD':18310,'TGKDP':18391,'TGKN':18176,'TGKO':81899,'TNSE':420644,'TORS':16797,'TORSP':16798,'TRCN':74561,'TRMK':18441,'TRNFP':1012,'TTLK':18371,'TUCH':74746,'TUZA':20716,'UCSS':175781,'UKUZ':20717,'UNAC':22843,'UNKL':82493,'UPRO':18584,'URFD':75124,'URKA':19623,'URKZ':82611,'USBN':81953,'UTAR':15522,'UTII':81040,'UTSY':419504,'UWGN':414560,'VDSB':16352,'VGSB':16456,'VGSBP':16457,'VJGZ':81954,'VJGZP':81955,'VLHZ':17257,'VRAO':20958,'VRAOP':20959,'VRSB':16546,'VRSBP':16547,'VSMO':15965,'VSYD':83251,'VSYDP':83252,'VTBR':19043,'VTGK':19632,'VTRS':82886,'VZRZ':17068,'VZRZP':17067,'WTCM':19095,'WTCMP':19096,'YAKG':81917,'YKEN':81766,'YKENP':81769,'YNDX':388383,'YRSB':16342,'YRSBP':16343,'ZHIV':181674,'ZILL':81918,'ZMZN':556,'ZMZNP':603,'ZVEZ':82001}
FINAM_URL = "http://export.finam.ru/"# сервер, на который стучимся
market = 0 #можно не задавать. Это рынок, на котором торгуется бумага. Для акций работает с любой цифрой. Другие рынки не проверял.
#Делаем преобразования дат:
start_date = datetime.strptime(start, "%d.%m.%Y").date()
start_date_rev=datetime.strptime(start, '%d.%m.%Y').strftime('%Y%m%d')
end_date = datetime.strptime(end, "%d.%m.%Y").date()
end_date_rev=datetime.strptime(end, '%d.%m.%Y').strftime('%Y%m%d')
#Все параметры упаковываем в единую структуру. Здесь есть дополнительные параметры, кроме тех, которые заданы в шапке. См. комментарии внизу:
params = urlencode([
					('market', market), #на каком рынке торгуется бумага
					('em', tickers[ticker]), #вытягиваем цифровой символ, который соответствует бумаге.
					('code', ticker), #тикер нашей акции
					('apply',0), #не нашёл что это значит. 
					('df', start_date.day), #Начальная дата, номер дня (1-31)
					('mf', start_date.month - 1), #Начальная дата, номер месяца (0-11)
					('yf', start_date.year), #Начальная дата, год
					('from', start_date), #Начальная дата полностью
					('dt', end_date.day), #Конечная дата, номер дня	
					('mt', end_date.month - 1), #Конечная дата, номер месяца
					('yt', end_date.year), #Конечная дата, год
					('to', end_date), #Конечная дата
					('p', period), #Таймфрейм
					('f', ticker+"_" + start_date_rev + "_" + end_date_rev), #Имя сформированного файла
					('e', ".csv"), #Расширение сформированного файла
					('cn', ticker), #ещё раз тикер акции	
					('dtf', 1), #В каком формате брать даты. Выбор из 5 возможных. См. страницу https://www.finam.ru/profile/moex-akcii/sberbank/export/
					('tmf', 1), #В каком формате брать время. Выбор из 4 возможных.
					('MSOR', 0), #Время свечи (0 - open; 1 - close)	
					('mstime', "on"), #Московское время	
					('mstimever', 1), #Коррекция часового пояса	
					('sep', 1), #Разделитель полей	(1 - запятая, 2 - точка, 3 - точка с запятой, 4 - табуляция, 5 - пробел)
					('sep2', 1), #Разделитель разрядов
					('datf', 1), #Формат записи в файл. Выбор из 6 возможных.
					('at', 1)]) #Нужны ли заголовки столбцов
url = FINAM_URL + ticker+"_" + start_date_rev + "_" + end_date_rev + ".csv?" + params #урл составлен!
print("Стучимся на Финам по ссылке: "+url)
txt=urlopen(url).readlines() #здесь лежит огромный массив данных, прилетевший с Финама.
local_file = open('quotes.txt', "w") #задаём файл, в который запишем котировки.
for line in txt: #записываем свечи строку за строкой. 
	local_file.write(line.strip().decode( "utf-8" )+'\n')	
local_file.close()
print("Готово. Проверьте файл quotes.txt в папке где лежит скрипт")

П.С. 1. Напомню, что вручную котировки с Финама качаются здесь: https://www.finam.ru/profile/moex-akcii/sberbank/export/
П
.С. 2. Скрипт отправляет на Финам такую же строку, которую вы видите в «загрузках», когда качаете котировки вручную. Скрипт воспроизводит точно такой же адрес.
Скриншот файла, скачанного вручную без скрипта:
Качаем котировки с Финама
★90 | ₽ 236
У меня ребёнок начал учить питон в 7 лет.
Частная школа.
Хочет написать свою игру.
Максим Барбашин, у меня ещё в 90-е был советский компьютер, который в качестве монитора использовал ламповый телевизор. Я там кодил на бейсике (рисовал фигуры из линий, зная нотную грамоту, задавал мелодии типа Yesterday). Но с тех пор всё забыл и много лет не возвращался.

Albus (Игорь Китаев), 
Он у меня еще unity изучает.
Это все-таки больше подходит для ребенка.
Заинтересовался VR.
Я говорю, не знаю, чем тебе помочь.
Даже школ не нашел в стране, где могут этому научить.

Максим Барбашин, помогите ему сфокусироваться на чем-то одном. Unity подойдет. VR — это мертвая тема. Там нужно еще минимум пару витков (предыдущий был в конце 90-х). 
bstone, 
Была новогодняя елка в хай-тек стиле.
Дед Мороз в виде робота, VR Снегурочка и все такое.
Смотрю, мой ребенок круги вокруг ноута нарезает.
Он увидел знакомый интерфейс unity и решил выяснить подробности.
Снегурочку удалось спасти…
Albus (Игорь Китаев), Кворум 128? Тоже с него начинал.
Albus (Игорь Китаев), и у меня до сих пор лежит на антресолях, еще рабочий! :D
Shadow, я скучаю по тем стареньким играм, которые загружались с магнитофонных кассет :)
Albus (Игорь Китаев), встречал эмуляторы ZX Spectrum на просторах интернета, а также образы игр и программ к ним. При желании можно установить такой набор на Windows или Android-планшет и поностальгировать. :)))

P.S.: Для эстетов предусмотрен режим загрузки «в реальном времени» — с ожиданием по несколько минут и звуковым сопровождением из шипения, с бегающими полосками на экране… ))))
Albus (Игорь Китаев), да было дело)))
Атари до сих пор у родителей где то лежит в полном боекомплекте )), Синклер тоже с ним же)
на Атари  тоже было можно кодить )
спасибо за пост, коллега!)
Shadow, 
Наверное, стоит как антиквариат?
Максим Барбашин, к сожалению, теперь только пыль собирает. )))) А также рядом с ним пара джойстиков и несколько кассет с играми. )))) Полный комплект, только по причине морального устаревания использовать его нет никакого смысла. Оставлю потомкам — показать, на чем раньше дедушки работали. :D
Максим Барбашин, нафига ребенку в 7 программирование? Кодера эникейшика хотите вырастить? Пусть фундаментальные науки изучает, в начальной школе то уж точно.
Dmitry, полагаю что программирование так же развивает мозг ребенка, как изучение иностранного языка для общения. Учитывая то, что он в будущем сможет применять полученные знания, если выучит конечно, и зарабатывать на этом уже в школьные годы, то навык явно не лишний)
Friendly Deep Space, да и спекулировать акциями можно учить с 7 лет. Мозг отлично развивает. Но всему свое время. В школе надо учить математику, физику, языки и т.д. А прикладные знания на то и прикладные.
Dmitry, не совсем корректное сравнение имхо) Программирование это инструмент, причем универсальный) А спекулирование акциями это спекулирование акциями.
Friendly Deep Space, чем он универсальный? Тут речь даже не про основы алгоритмизации и т.д. А про изучение конкретного языка/платформы, очень прикладные знания. Причем быстро устаревающие.
Dmitry, 
Современные дети учатся включать компьютер быстрее,
чем начинают ходить.
Это полезно для развития системного и логического мышления.
Тем более,
это очень простые игры,
которые не сильно отличаются от обычных электронных игр, в которые играют дети.

www.youtube.com/watch?v=OnPXWwNVmLI&index=3&list=PLAHRa_lxEV7CmapCAH5N3TkNpck3F6TCI

А вот физику и математику маленькому ребенку еще рано
Максим Барбашин, физику — да, а арифметика — это раздел математики. Так что в самый раз. Ну вообще на вкус и цвет как говориться. Главное чтоб вам и вашему ребенку нравилось.
Dmitry, 
Просто если ребенок от природы эмоциональный,
программирование помогает научить его порядку, структурированию мыслей, разбивать задачу на этапы.
Есть стимул к изучению английского,
ребенок видит, что ему реально нужны знания.
И в той же математике.
Кроме того, есть социальный аспект.
Таким детям бывает сложно поддерживать коммуникации.
А тут он в своей среде, проще найти друзей.
Максим Барбашин, если ребенок эмоциональный, может ему лучше зайдут эмоциональные сферы? Танцы, музыка, литература, театр? Нет?
SergeyEgorov, 
Так ребенку надо научиться управлять своими эмоциями.
В принципе, подходят и шахматы,
но это на любителя.
Максим Барбашин, совершенно верно. Мне вот было насрать на школу, пока я не понял в 6-м классе, что мне нужна математика и английский, чтобы продвинуться дальше в программировании. А чуть позже еще стало очевидно, что те же правила русского языка прекрасно систематизируются, как любая другая документация.

Положительная обратная связь, короче. Главная чтобы была внутренняя мотивация и желание. Просто сидеть в школе без этого гораздо менее эффективно.
«Плюсануть» пока не могу. Ловите мой вербальный ПЛЮС!
avatar

OnlyHuman

Автор идеи на хабре явно «перехимичил». id, code, названия инструментов лежат вот тут www.finam.ru/scripts/export.js практически в готовом виде. Т.е. парсить HTML вобще не нужно.
avatar

ivanovr

Спасибо. Хоть код и грязноват, идея рабочая. Только зачем скидывать в файл? Анализировать тоже в питоне например через pandas. Или хотите потом оффлайн работать с данными? И сдается мне что некоторые параметры необязательные — странно выглядит даты и тикер дважды. Попробуйте найти минимальный набор
Uncle Fedor, такая строчка улетает на сервер финама, когда вы качаете котировки вручную. Это попытка воспроизвести её. 

… и дальше в этой строке СБЕР будет третий раз.
Albus (Игорь Китаев),
Советую освоить оператор %, с его помощью можно заменить
url = FINAM_URL + ticker+"_" + start_date_rev + "_" + end_date_rev + ".csv?" + params
url = ( 'http://export.finam.ru/%s_%s.csv?%s' % ( ticker,
start_date_rev,
end_date_rev, params ) )

скобки поставил чтобы показать как список параметров указать в несколько строчек.


tranquility, спасибо. Освою :)
Uncle Fedor, сам pandas не пользовался, но мне кажется для новичка имело бы смысл сначала научиться пользоваться numpy, там для загрузки-выгрузки данных есть функции loadtxt и savetxt, этого в принципе достаточно. Ту же json структуру можно при необходимости реализовать при помощи списков и словарей. А потом уже когда научишься такое делать, можно и готовыми решениями воспользоваться, которые в том же pandas имеются.
tranquility, скорее наооборот — лучше учить pandas. numpy нужно если вы реализуете достаточно сложные математические алгоритмы, в остальных случаях pandas и удобнее, и вполне достаточно. Pandas изначально написал человек, который работал в квант фонде AQR. Ну и padas.DataFrame имеет атрибут values, который хранит представление в виде массива numpy, если вдруг потребуется.
главное не язык а сам алгоритм
а зачем всё это? 
avatar

HUKS

HUKS, для прогона вашей стратегии на исторических данных. 
Albus (Игорь Китаев), следующие посты будут посвящены написанию тестера стратегий написанных в qlua скриптах? ;)
tranquility, хочу выпустить обновлённую версию этого робота.
smart-lab.ru/blog/458269.php
но не знаю что туда добавить.
Albus (Игорь Китаев), понятно. Сам что-то разочаровался в кластерном анализе, хотя кучу всего на С++ сделал для него. Но ничего, может, потом пригодится, как порой получается.
А я, наверное, как будет время, тут опубликую код для визуализации свечных графиков на питоне, в рамках, так сказать, питоновского просвещения общественности))
Albus (Игорь Китаев), Эллиот все проверил)
Albus (Игорь Китаев), ))))) так же я думал много лет назад))) пытался «прогнать… стратегию на исторических данных» Ха-ха-ха! Тогда мы использовали Metastock (он и сейчас стоит на одном из моих компьютеров). однако, все это, к сожалению для вас — не работает!) Особенно тогда, когда вы переходите к большим счетам — когда вы торгуете не 1-2 контрактами, а 1000-2000 контрактов (наример RTS) и более, тогда все эти стратегии, которые вы прогнали «на исторических данных» превращаются в пыль...)))
Я делал аналогичную задачу в Excel. Но примерно год назад все перестало работать, ибо вроде как финам рубанул всех сторонних. Теперь получается, все снова заработало. Надо бы проверить. 
Носорог, год назад у него адрес сервера изменился. 
Носорог, у вас скорее всего этот сервер http://195.128.78.52
а надо новый: http://export.finam.ru/
Albus (Игорь Китаев), спасибо!
Московский Лоссбой, под питон написано много скриптов, анализирующих опционы. Так что дело нужное. Питон тем и славится: работает медленно по сравнению с Си и Си++, но под него уже есть куча готового кода. Копипасти и работай.
Albus (Игорь Китаев), если пользоваться numpy (как раз касается обработки табличных данных), то разницу с С++ особо и не заметишь. Есть, но мизерная какая-то, причем не всегда в пользу последнего))
Albus (Игорь Китаев), несколько дней на «каникулах» убил на аналогичную задачу! Где ж вы были, хотя бы на недельку раньше?))
Можете поделиться ссылками на скрипты, анализирующие опционы?
Московский Лоссбой, в питоне все просто делается, главное начать. Если есть хоть какие-то навыки программирования, это несложно сделать будет. Потом кайфовать будете от осознания как легко реализовали то, на что потратили бы часы и дни делая это же на фортране. Для начала хотя бы установите питон себе и запустите этот скрипт Игоря, а дальше все само завертится, вот увидите!)
Московский Лоссбой, 
Да справишься.
Есть книжки — раскраски для детей 7 лет.
Московский Лоссбой, 
Только не забудь приготовить цветные карандаши.
И резинку.
Московский Лоссбой, 
Резинка нужна, чтобы стирать!
А не то, о чем ты подумал.
Стоп.
А что ты планировал делать с карандашом?
Мой вариант — загрузка напрямую с биржи в асинхронном режиме https://github.com/WLM1ke/aiomoex
Михаил, в разделе «открытие сессии» опечатка: «В конце работы для высвобождения ресурсов сессия должна быть закрыта вызовом метода closed.»
Исправить на close
ivanovr, исправил.
Игорь, как поживает Ваш друг с которым вы одно время плотно пытались развить сайт торговых роботов? Вы с ним ещё дружите, или разсорились по политическим мотивам?
avatar

Aleks778

Aleks778, он по прежнему программист, но от торговых роботов стал очень далёк.
Из украинских друзей и бывших коллег я ни с кем не поссорился. Но некоторые из них расфрендились на фейсбуке. Конфликт на этой почве был только один. Киевский друг сильно-сильно на меня гнал (диалог был в чате фейсбука), я отвечал миролюбиво, но он всё равно меня забанил. Через несколько месяцев я ему написал по электронке доброжелательное письмо на день рождения, но он не ответил... 
Можно еще и так:

с помощью Jatotrader

Albus, а у тебя нет случайно идентификаторов всех финамовских эмитентов с ММВБ, которые используются для строки запроса:… txt?market=1&em=795&code=GMKN&a…
Дмитрий Иванов, идентификаторы всех акции есть внутри этого скрипта.
Albus (Игорь Китаев), В очередной раз спасибо за проделанную работу. Статья значительно ускорила решение аналогичной задачи!
Albus (Игорь Китаев), еще раз спасибо — обновил свой макрос в Excel.

Возможно, пропущены:
473181 DSKY
491944 FIVE
А как качать старые фьючерсные контракты?


....все тэги
UPDONW