В данной статье мы рассмотрим контракты. Это крайне важная вещь для работы с терминалом, ибо они необходимы для запросов различной информации об активах. Рассмотрим для чего нужны контракты и где они используются.
Что это Contract?
На первый взгляд может показаться, что контракт — это приказ терминалу на открытие сделки. Однако это не так.
Контракт — это специальный объект IBApi.Contract. Он содержит в себе информацию по конкретному торговому инструменту. Используя эту информацию, TWS выбирает отдельный торговый инструмент и проводит с ним операции, которые мы запросили.
Для чего нужны контракты?
Разумеется для запросов TWS. Контракты применяются в запросах, где используется определенный торговый инструмент. Чаще всего — это запрос исторических данных, получение текущих котировок, отправка ордера (изменение или отмена).
Из чего состоит контракт?
Так как контракт — это отдельный класс Python. После создания объекта необходимо назначить его свойства, которые будут понятны TWS. Обязательные свойства, которые необходимы:
- Symbol — тикер актива.
- Security type — тип актива.
- Currency — валюта.
- Exchange — биржа.
Где взять свойства контракта?
Лучший способ понять, как заполнить нужные свойства контракта — это посмотреть в самом TWS.
Откройте TWS. В окне Watchlist (если этого окна нет, откройте его через File -> New Window -> Watchlist) выберите интересующий вас торговый инструмент, нажмите на нём правой кнопкой мыши и в появившемся окне выберите Financial Instrument Info -> Description. Если этого пункта не нашли, то нажмите на значок стрелки внизу меню.
Должно появиться вот такое окно:
Здесь будут видны необходимые данные.
Какие контракты существуют?
Interactive Brokers предоставляет возможность торговать огромным количеством торговых инструментов. Чтобы «дотянуться» до них с помощью своего алгоритма, вы должны понимать, какие типы контрактов возможны и доступны.
Все контракты делятся на две большие группы:
В данной статье мы не будем подробно расписывать каждую группу контрактов, дабы не «раздуть» статью до масштабов энциклопедии. Но вы можете самостоятельно почитать про них по ссылкам выше.
Переходим к работе с кодом
В рамках данной статьи мы создадим контракт и запросим по нему подробную информацию. Начнем с создания контракта, а в конце статьи напишем полноценный алгоритм.
Для создания контракта и дальнейшей работы с ним нам потребуется:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
# импортировать модуль с классом Contract import ibapi.contract # создать объект класса Contract contract1 = ibapi.contract.Contract() # Это будет пример 1 - валютная пара FX contract2 = ibapi.contract.Contract() # Это будет пример 2 - акция # Заполнить атрибуты объекта минимальными данными contract1.symbol = "EUR" # Контракт на валютную пару EUR.GBP contract1.secType = "CASH" contract1.currency = "GBP" contract1.exchange = "IDEALPRO" contract2.symbol = "IBKR" # Контракт на акцию Interactive Brokers contract2.secType = "STK" contract2.currency = "USD" contract2.exchange = "ISLAND" # В API, биржа NASDAQ всегда определяется как ISLAND в поле exchange |
В «боевых» алгоритмах на этом работа с контрактом будет завершена. Далее созданный объект надо будет передавать в необходимый метод, где необходим контракт.
Но в рамках данной статьи, мы продолжим работу с контрактом и напишем алгоритм, который запросит все параметры созданного нами контракта.
Код в студию!
Все детали по созданному контракту запрашиваются у TWS через метод IBApi.EClient.reqContractDetails(). А ответ от TWS возвращается в метод IBApi.EWrapper.contractDetails() и IBApi.EWrapper.contractDetailsEnd().
Следовательно мы создадим свой класс, который будет наследоваться от EWrapper, и перепишем в нем соответствующие методы.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
# Импортируем необходимые библиотеки import ibapi.wrapper import ibapi.client import ibapi.contract # Contract - интересующий сейчас класс import threading import time # модуль времени из стандартной библ-ки Python # Класс-наследник EWrapper class MyWrapper(ibapi.wrapper.EWrapper): # Добавлен инициализатор объекта def __init__(self): self.nvid = 0 # переменная для next valid order id self.con_detail_recive = False # Флаг для полученного контракта # Переписан базовый метод .nextValidId() def nextValidId(self, orderId:int): super().nextValidId(orderId) self.nvid = orderId # записываем значение next valid order id # Метод, который принимает ответ на запрос деталей контракта def contractDetails(self, reqId:int, contractDetails: ibapi.contract.ContractDetails): # Выводим все параметры объекта и их значения for arg in dir(contractDetails): # Обходим все атрибуты объекта contractDetails if not arg.startswith('_'): # Исключаем приватные атрибуты val = getattr(contractDetails, arg) # Значение конкретного атрибута print ("{} = {}".format(arg, val)) # Печатаем атрибут и его значение # Метод, завершающий прием ответа на запрос деталей контракта def contractDetailsEnd(self, reqId:int): self.con_detail_recive = True print("Закончили принимать параметры контракта") # Печатаем статус # Создаем необходимые объекты tws = ibapi.client.EClient(MyWrapper()) # Объект класса Eclient cnt = ibapi.contract.Contract() # Объект класса Contract # Контракт на валютную пару EUR.USD cnt.symbol = "EUR" cnt.secType = "CASH" cnt.currency = "USD" cnt.exchange = "IDEALPRO" tws.connect("127.0.0.1", 7496, 1) # подключаемся к терминалу if tws.isConnected(): # В случе успешного подключения к TWS th = threading.Thread(target=tws.run) # Организовываем поток th.start() # Запускаем потоки while tws.wrapper.nvid == 0: # Пока TWS не прислал Next Valid ID time.sleep(.5) # Спим полсекунды tws.reqContractDetails(tws.wrapper.nvid, cnt) # Запрашиваем все необходимые данные по контракту while not tws.wrapper.con_detail_recive: # Ждем получение ... time.sleep(.2) # ... деталей контракта tws.done = True # Переводим флаг отключения while tws.done: # Ждем пока произойдет ... time.sleep(.2) # ... отключение от TWS print("----- !!!THE END!!! -----") |
Обратите внимание на переписанный метод MyWrapper.contractDetails(). После запроса деталей контракта TWS присылает в него объект contractDetails: ibapi.contract.ContractDetails. Суть метода сводится к тому, чтобы пройтись по всем свойствам данного объекта и вывести их на экран.
Для чего? В целях демонстрации всех полей указанного нами контракта. Возможно при ваших экспериментах вам понадобится что-то из этих данных. Я же, со своей стороны, хочу обратить ваше внимание на такое свойство, как orderTypes. В следующих статьях нам оно пригодится.
Так же обратите внимание на свойство класса MyWrapper.con_detail_recive. Его я ввел в код специально, чтобы отследить, когда контракт будет получен. В своих алгоритмах вы можете его не применять.
Заключение
Контракты — ключевой объект Python, так как участвует в важнейших операциях с TWS (запрос котировок, запрос истории, отправка торговых приказов).
Мы разобрали минимальный набор свойств, необходимых для описания контракта, и посмотрели на все свойства контракта, запросив детали.
Мы не рассмотрели механизм поиска акций на фондовой бирже. Его вы можете освоить самостоятельно, прочитав короткий раздел по ссылке. Для реализации данного механизма у вас должен быть открыт реальный счет в IB и оформлена подписка на данные об акциях.