Статья о загрузке внутридневных котировок от поставщика данных IQFeed на языке Python опубликована в блоге www.quantstart.com. DTN IQFeed - популярный вендор, поставляющий данные со многих американских и европейских рынков по широкому спектру инструментов. Тем трейдерам, кто практикует алгоритмическую торговлю на зарубежных площадках или использует данные с них для поиска корреляций с российскими активами, будет очень полезен нижеследующий перевод.
С IQFeed возможно получение данных через сокет соединение к локальному серверу IQLink, который предоставляется при создании аккаунта у этого поставщика данных. В этой статье мы будем использовать потоковое сокет соединение на языке программирования Python для буферизации данных и создадим файл CSV с внутридневной маркет датой для американских акций.
Python сокет соединение с IQFeed
Мы предполагаем, что вы уже имеете аккаунт на IQFeed. Если еще нет, то возможно получение двухнедельного бесплатного испытательного периода при регистрации. После подписки на необходимые вам биржевые площадки и требуемый уровень дискретизации данных, вам будет предложена загрузка IQLink Launcher. Этот инструмент работает только под Windows, но может быть запущен и на Mac или Linux под WINE (с небольшим количеством настроек). При запуске IQLink появляется диалог, представленный на рисунке в заглавии статьи.
Нажатие кнопки "Start IQLink" запустит сервер. Вам будет предложено ввести логин и пароль. Когда сервер будет запущен, необходимо создать потоковое сокет соединение к локальному порту (9100 задан по умолчанию). Затем вы сможете посылать сообщения через этот сокет и получать данные в режиме буферизации.
Первая задача - создать файл iqfeed.py и загрузить системную библиотеку и библиотеку сокетов:
# iqfeed.py import sys import socket
За буферизацию данных отвечает функция read_historical_data_socket. В качестве параметров в нее предаются сокет объект и число байтов для буфера чтения. Эта функция просто преобразует последний полученный пакет данных в строку и возвращает ее когда получена строка "!ENDMSG!" ( то есть когда буфер достиг конца данных):
# iqfeed.py def read_historical_data_socket(sock, recv_buffer=4096): """ Чтение информации из сокета в буфер, размер которого равен 4096 байтов Параметры: sock - объект сокет recv_buffer - Количество байтов для чтения за один раз """ buffer = "" data = "" while True: data = sock.recv(recv_buffer) buffer += data # Проверка прихода конца сообщения if "!ENDMSG!" in buffer: break # Удаление строки конца сообщения buffer = buffer[:-12] return buffer
Сокет должен присоединяться к локальной машине через порт 9100. Для примера мы собираемся загрузить данные для четырех акций:SPY, AAPL, GOOG и AMZN с начала 2014 года до настоящего времени.
IQFeed принимает сообщения в следующем формате: CMD,SYM,[options]\n
Мы будем использовать для примера следующее сообщение: "HIT,GOOG,60,20140101 075000,,,093000,160000,1\n" . Это запрос на получение исторических данных (HIT) для тикера GOOG c шагом один раз в 60 секунд (то есть минутные бары), с 07:50:00 1 января 2014 года до настоящего времени (т.е до вчерашнего дня). Данные фильтруются для представления только в диапазоне с 9:30:00 до 16:00:00, который является временем торговой сессии NYSE, используются новые данные.
Первая задача это определить хост, порт и тикеры для получения. Каждый из 4 тикеров добавляется в цикле конструирования сообщения. Затем открывается сокет. AF_INET определяет пару (хост,порт), которая нужна для соединения. SOCK_STREAM устанавливает, что сокет должен быть потоковым.
Когда сокет открыт, сообщение послано и исторические данные загружены в буфер, после сокет закрывается. Все окончания строк удаляются и данные записываются в файл "sym.csv" в ту же директорию. где находится код, и "sym" означает символ тикера:
# iqfeed.py if __name__ == "__main__": # Задаем хост, порт и символы для получения host = "127.0.0.1" # Localhost port = 9100 # Historical data socket port syms = ["SPY", "AAPL", "GOOG", "AMZN"] # Зашружаем каждый тикер на диск for sym in syms: print "Downloading symbol: %s..." % sym # Конструируем сообщение для IQFeed для получения данных message = "HIT,%s,60,20140101 075000,,,093000,160000,1\n" % sym # Открываем потоковый сокет к IQFeed серверу локально sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.connect((host, port)) # Отсылаем запрос на данные # сообщение и буфер данных sock.sendall(message) data = read_historical_data_socket(sock) sock.close # Удаляем все окончания строк # разделитель - запятая для каждой записи data = "".join(data.split("\r")) data = data.replace(",\n","\n")[:-1] # Пишем поток данных на диск f = open("%s.csv" % sym, "w") f.write(data) f.close()
Получаемый формат данных следующий:
[YYYY-MM-DD HH:mm:SS],[OPEN],[LOW],[HIGH],[CLOSE],[VOLUME],[OPEN INTEREST]
Типичный набор данных в файле должен быть такой:
2012-01-03 09:31:00,30.6400,30.5000,30.6400,30.5100,6128,6128 2012-01-03 09:32:00,30.5600,30.4900,30.4900,30.5600,6528,400 2012-01-03 09:33:00,30.5000,30.5000,30.5000,30.5000,6672,144 2012-01-03 09:34:00,30.3800,30.3400,30.3400,30.3500,8423,1751 2012-01-03 09:35:00,30.5300,30.5300,30.5300,30.5300,8623,200 2012-01-03 09:36:00,30.6400,30.5500,30.5500,30.6400,9423,800 2012-01-03 09:37:00,30.6500,30.6500,30.6500,30.6500,10329,906 2012-01-03 09:38:00,30.6900,30.6600,30.6900,30.6600,12329,2000 2012-01-03 09:39:00,30.7200,30.6400,30.6500,30.7200,13729,1400 2012-01-03 09:40:00,30.7500,30.6900,30.7200,30.7500,17029,3300
Данные поставляются за достаточно большое период в смысле доступности по годам. Загрузка может занять некоторое время, если вы запрашиваете много тикеров за пять лет и более. Если вы хотите загружать не только данные по акциям, то обратитесь к списку символов IQFeed. Очевидно, что вы должны подписаться на соответствующую площадку для получения запрашиваемых данных.
Обратите внимание, что внутридневные данные, поставляемые IQFeed не адаптированы к корпоративным действиям, таким, как дивиденты и сплиты. Вам нужно будет самим позаботиться об их учете в ваших тестах.
Hi uralpro, I see you liked my article, well, I'm glad, but next time please specify the direct link to the article where you took the material to avoid misunderstanding.
Hi, Michael, thanks for your remark, I correct the link to your article.
Seems Michael is watching only how articles are used. I replied to 2 or 3 his emails asking for articles or additional information for the site. But didnt get any answer