Блог им. dataserverdeveloper

Как качать историю котировок (пример на Python, IQFeed)

   IQFeed -  это не самый дешёвый (но и не самый дорогой) провайдер исторических (и real-time) данных финансовых бирж и разнообразных trading venues. Со своими плюсами и минусами.

   В этой короткой статье расскажу, как закачать исторические данные из IQFeed при минимальном знании языка Python.

   Disclosure: я заинтересованное лицо, хоть и не в коммерческом смысле, т.к. ищу тех с кем можно расшарить сервис IQFeed вскладчину. См. подробнее: smart-lab.ru/blog/439522.php

   Из плюсов IQFeed – вполне сносное API для доступа к данным (уступающее по простоте RESTful сервисам, но минус REST – крайне низкая производительность, тяжело качать более или менее объёмные данные). Огромный выбор (акции, фьючерсы, опционы...). Минусы -тики только 180 дней (по SPY, кстати, это примерно 2.5GB). Adjusted данных по акциям нет.

   Скачивание сводится к формированию запроса -“хочу такие-то данные с такой-то по такую-то дату”. Запрос — это текстовая строка, отправленная в канал коммуникации (сокет).

   Вот примеры строки запроса на интрадей (минутки): «HIT,SPY,60,20160226 093000,20170226 160000,,093000,160000,1,,»

   Расшифровка: дайте интрадей (HIT), по SPY, с барами в 60 секунд (т.е. минутки), с 20160226 093000 (YYYYMMDD HHMMSS), по 20170226 160000, без ограничения кол-ва выдаваемых строк, в торговую сессию с 093000 по 160000 (т.е. без extra-hours), с “прямой” (от старого к новому) сортировкой по датам (1),  без RequestID, без DATAPOINTSPERSEND.

   Формально запрос выглядит так:

HTT,SYMBOL,BEGINDATE BEGINTIME,ENDDATE ENDTIME,MAXDATAPOINTS,BEGINFILTERTIME,ENDFILTERTIME,DIRECTION,REQUESTID,DATAPOINTSPERSEND<CR><LF>

 

   <CR><LF> это перевод строки “по-windowsовски” (\r\n). Говорю специально для тех, кто работает на Linux.

   Запрос нужно послать на предварительно открытый сокет localhost:9100 или 127.0.0.1:9100 (под Linux может иметь значение), на котором “висит” работающий клиент IQFeed (в Windows запустить вручную через IQLink Launcher), а дальше вычитывать с него порции (блоки) данных (формат текстовый, кстати там не OHLC, а HLOC) соединяя вместе. Чтение производить до появления слова “!ENDMSG!” к конце очередного блока.

Грубо говоря – всё. Это минимально достаточный набор действий.

Попробуем сделать это на Python:

import sys
import socket

def read_historical_data_socket(sock, fname, recv_buffer=4096):

    buffer = ""
    data = ""
    cont=True
    while cont:
        buffer = sock.recv(recv_buffer).decode('ascii')
        data += buffer
        if "!ENDMSG!" in data[-12:]:
            data = data[:-12]
            cont=False

        firstlines=buffer.split("\n",2)
        if len(firstlines)>1:
            sys.stdout.write("Download progress(%s): %s   \r" % (fname,firstlines[1][0:19]) )
            sys.stdout.flush()
        
    data = "".join(data.split("\r"))
    data = data.replace(",\n","\n")[:-1]
    
    f = open(fname, "w")
    f.write(data)
    f.close()
    return

if __name__ == "__main__":

    host = "127.0.0.1"
    port = 9100
    syms = ["SPY", "AAPL", "GOOG", "AMZN"]
    for sym in syms:
        message = "HIT,%s,60,20140101 000000,20160101 000000,,,,1\n" % sym
        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        sock.connect((host, port))

        sock.sendall(message.encode())
        read_historical_data_socket(sock,"%s.csv" % sym)
        sock.close

        sys.stdout.write("Downloaded symbol: %s                          " % sym)
        sys.stdout.flush()

    print

Собственно – всё. Пример  проверен и на Linux (Python 2.7.12) и на Windows (Python 3.5.4).
Примечания:
   Из недостатков скрипта — всё сначала закачивается в память. Тому есть причины: логика работы с сокетом — в получении равномерно нарезанных порций данных (4096 байт по умолчанию). Но сообщение !ENDMSG! может прийтись на границу двух блоков, потому быть «разрезанным» и при последовательном чтении с записью в файл (write-append block by block) просто неотдетектироваться. Для сохранения в файл on-the-fly без больших затрат памяти, нужна слегка усложнённая логика с хранением предыдущего считанного блока и детектом !ENDMSG! в них обоих сразу (в их конкатенации). Это усложняет скрипт. Для минуток особо морочиться не нужно (в худшем случае сотни мегабайт). Кроме того, нужно удалять запятые с конца строк (сделано) и реформатировать сами строки под конкретную программу ТА (не сделано).
   На Linux скрипт работает хорошо.
   И ещё. Не забывайте, что клиент IQFeed вылетает по timeout inactivity. Т.е. запустив клиент IQConnect, через IQLink, и потом поигравшись с скриптом вы долго можете мучиться с «неработающим сокетом», а причина банальна — iqfeed клиент закрылся по timeout inactivity (не пользовались долго).  

4.9К | ★10



Пользователь запретил комментарии к топику.

Читайте на SMART-LAB:
Фото
💼 Подведем итоги 2025 года и поделимся планами на будущее
Друзья, 7 апреля в 18:00 мы раскроем результаты деятельности за 2025 год: опубликуем итоговую консолидированную финансовую и управленческую...
Облигации на пальцах: как устроен главный инструмент инвестора
Если у вас все еще нет облигаций в портфеле — вы либо неверно инвестируете, либо не совсем понимаете, зачем они нужны и по какому принципу...
Фото
Каждый инвестор желает знать, где сидит доходность? Взгляд Goldman Sachs на инвестиции до конца года
Если вы инвестируете свой капитал на фондовом рынке, то каждый год легко может принести вам как большие потери, так и несметные богатства....
Фото
Башнефть: есть шанс на переоценку, но нужно запастись терпением. Прогноз сошелся с фактом в высокой точностью, ищем инвест идею
Башнефть отчиталась по МСФО за 2025 год — внимание, квартальных отчетов в прошлом году не было вообще! Традицицинно сравниваем прогноз...

теги блога Ромирес

....все тэги



UPDONW
Новый дизайн