From b105b08c9f4fc3bcde8c87ec061aaa0f5f399c0e Mon Sep 17 00:00:00 2001 From: "vn.py" Date: Thu, 14 Mar 2019 09:52:01 +0800 Subject: [PATCH] [Mod]change ibapi to use relative import --- .flake8 | 2 +- vnpy/api/apex/fiddef.py | 34 +++--- vnpy/api/ib/client.py | 24 ++-- vnpy/api/ib/comm.py | 22 ++-- vnpy/api/ib/commission_report.py | 13 ++- vnpy/api/ib/common.py | 4 +- vnpy/api/ib/connection.py | 40 +++---- vnpy/api/ib/contract.py | 16 +-- vnpy/api/ib/decoder.py | 28 ++--- vnpy/api/ib/execution.py | 28 ++--- vnpy/api/ib/order.py | 121 ++++++++++---------- vnpy/api/ib/order_condition.py | 10 +- vnpy/api/ib/order_state.py | 22 ++-- vnpy/api/ib/reader.py | 12 +- vnpy/api/ib/scanner.py | 41 +++---- vnpy/api/ib/softdollartier.py | 6 +- vnpy/api/ib/tag_value.py | 7 +- vnpy/api/ib/ticktype.py | 186 +++++++++++++++---------------- vnpy/api/ib/utils.py | 42 +++---- vnpy/api/ib/wrapper.py | 16 +-- 20 files changed, 327 insertions(+), 347 deletions(-) diff --git a/.flake8 b/.flake8 index 1bc02d11..143e40fd 100644 --- a/.flake8 +++ b/.flake8 @@ -1,5 +1,5 @@ [flake8] -exclude = __pycache__,__init__.py +exclude = __pycache__,__init__.py,ib,talib ignore = E501 line too long, fixed by black W503 line break before binary operator diff --git a/vnpy/api/apex/fiddef.py b/vnpy/api/apex/fiddef.py index 7ef24060..97f2e730 100644 --- a/vnpy/api/apex/fiddef.py +++ b/vnpy/api/apex/fiddef.py @@ -1308,14 +1308,14 @@ FID_RZXYLL = 1807 # 融资信用利率 DT:R FID_RQXYLL = 1808 # 融券信用利率 DT:R FID_RQLL = 1809 # 融券利率 DT:R FID_WYLB = 1810 # 违约类别 DT:I -FID_SQL = 1811 # DT:C +FID_SQL = 1811 # DT:C FID_FILENAME = 1812 # 文件名称 DT:C FID_FILEVERSION = 1813 # 文件版本 DT:C FID_ZJLB_GDH = 1814 # 股东证件类别 DT:I -FID_MEMHEAD = 1815 # DT:C -FID_MEMDATA = 1816 # DT:C -FID_MEMCOUNT = 1817 # DT:C -FID_MEMSIZE = 1818 # DT:C +FID_MEMHEAD = 1815 # DT:C +FID_MEMDATA = 1816 # DT:C +FID_MEMCOUNT = 1817 # DT:C +FID_MEMSIZE = 1818 # DT:C FID_GQZH_ZR = 1819 # 转入股权帐号 DT:C FID_PCCL = 1820 # 平仓策略 DT:I FID_RZXYED = 1821 # 融资信用额度 DT:R @@ -1753,7 +1753,7 @@ FID_MLMC = 3042 # 目录名称 DT:C FID_MLSM = 3043 # 目录说明 DT:C FID_FORMAT = 3044 # 目录格式 DT:C FID_DEFAULT = 3045 # 缺省值 DT:C -FID_DATA = 3046 # DT:C +FID_DATA = 3046 # DT:C FID_JLBZ = 3047 # 记录标志 DT:取值范围 DT:C FID_MBSMS = 3050 # 对方手机号码 DT:C FID_MBMAIL = 3051 # 对方邮件地址 DT:C @@ -2079,13 +2079,13 @@ FID_JJFS = 9058 # 解决方式 DT:C FID_JJGC = 9059 # 解决过程 DT:C FID_CLYS = 9060 # 处理用时 DT:C FID_FSRQ = 9061 # 发生日期 DT:C -FID_WTFL = 9062 # DT:C +FID_WTFL = 9062 # DT:C FID_GROUP = 9063 # 组 DT:C -FID_SECURITY = 9064 # DT:C -FID_GXQ = 9065 # DT:C +FID_SECURITY = 9064 # DT:C +FID_GXQ = 9065 # DT:C FID_CPXX = 9066 # 产品信息 DT:C FID_KHZB = 9067 # 客户总部 DT:C -FID_QYZB = 9068 # DT:C +FID_QYZB = 9068 # DT:C FID_ZJL = 9070 # 总经理 DT:C FID_ZJLDH = 9071 # 总经理电话 DT:C FID_ZJLMAIL = 9072 # 总经理EMAIL DT:C @@ -2405,16 +2405,14 @@ FID_PHYW_CFGSCC = 9612 # 盘后业务成分股市场串 DT:C FID_PHYW_CFGSLC = 9613 # 盘后业务成分股数量串 DT:C FID_PHYW_CFGJEC = 9614 # 盘后业务成分股金额串 DT:C FID_PHYW_HSNODEID = 9615 # 盘后业务恒生节点ID DT:C +FID_QQHYDM = 9378 +FID_QQHYMC = 9379 +FID_QQLX = 9373 +FID_MMFX = 9375 +FID_ZZHBM = 9372 +FID_QQBDBQ = 9377 FID_SBLX = 9616 # 申报类型DT:I FID_ZCCSY = 9800 # 昨持仓使用 FID_MRSY = 9801 # 买入使用 FID_SGSY = 9802 # 申购使用 FID_SHSY = 9803 # 赎回使用 - - -FID_QQHYDM = 9378 -FID_QQHYMC = 9379 -FID_QQLX = 9373 -FID_MMFX = 9375 -FID_QQBDBQ = 9377 -FID_ZZHBM = 9372 \ No newline at end of file diff --git a/vnpy/api/ib/client.py b/vnpy/api/ib/client.py index 6a23c42f..9d60b116 100644 --- a/vnpy/api/ib/client.py +++ b/vnpy/api/ib/client.py @@ -18,18 +18,18 @@ import logging import queue import socket -from ibapi import (decoder, reader, comm) -from ibapi.connection import Connection -from ibapi.message import OUT -from ibapi.common import * # @UnusedWildImport -from ibapi.contract import Contract -from ibapi.order import Order -from ibapi.execution import ExecutionFilter -from ibapi.scanner import ScannerSubscription -from ibapi.comm import (make_field, make_field_handle_empty) -from ibapi.utils import (current_fn_name, BadMessage) -from ibapi.errors import * #@UnusedWildImport -from ibapi.server_versions import * # @UnusedWildImport +from . import (decoder, reader, comm) +from .connection import Connection +from .message import OUT +from .common import * # @UnusedWildImport +from .contract import Contract +from .order import Order +from .execution import ExecutionFilter +from .scanner import ScannerSubscription +from .comm import (make_field, make_field_handle_empty) +from .utils import (current_fn_name, BadMessage) +from .errors import * #@UnusedWildImport +from .server_versions import * # @UnusedWildImport #TODO: use pylint diff --git a/vnpy/api/ib/comm.py b/vnpy/api/ib/comm.py index ebfbf508..e52627ad 100644 --- a/vnpy/api/ib/comm.py +++ b/vnpy/api/ib/comm.py @@ -1,3 +1,6 @@ +from .common import UNSET_INTEGER, UNSET_DOUBLE +import logging +import struct """ Copyright (C) 2018 Interactive Brokers LLC. All rights reserved. This code is subject to the terms and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. @@ -9,11 +12,6 @@ This module has tools for implementing the IB low level messaging. """ -import struct -import logging - -from ibapi.common import UNSET_INTEGER, UNSET_DOUBLE - logger = logging.getLogger(__name__) @@ -48,20 +46,20 @@ def make_field_handle_empty(val) -> str: return make_field(val) -def read_msg(buf:bytes) -> tuple: +def read_msg(buf: bytes) -> tuple: """ first the size prefix and then the corresponding msg payload """ if len(buf) < 4: return (0, "", buf) size = struct.unpack("!I", buf[0:4])[0] logger.debug("read_msg: size: %d", size) if len(buf) - 4 >= size: - text = struct.unpack("!%ds" % size, buf[4:4+size])[0] - return (size, text, buf[4+size:]) + text = struct.unpack("!%ds" % size, buf[4:4 + size])[0] + return (size, text, buf[4 + size:]) else: return (size, "", buf) -def read_fields(buf:bytes) -> tuple: +def read_fields(buf: bytes) -> tuple: if isinstance(buf, str): buf = buf.encode() @@ -69,7 +67,5 @@ def read_fields(buf:bytes) -> tuple: """ msg payload is made of fields terminated/separated by NULL chars """ fields = buf.split(b"\0") - return tuple(fields[0:-1]) #last one is empty; this may slow dow things though, TODO - - - + # last one is empty; this may slow dow things though, TODO + return tuple(fields[0:-1]) diff --git a/vnpy/api/ib/commission_report.py b/vnpy/api/ib/commission_report.py index 74e6d1b7..2d0edcc3 100644 --- a/vnpy/api/ib/commission_report.py +++ b/vnpy/api/ib/commission_report.py @@ -3,19 +3,20 @@ Copyright (C) 2018 Interactive Brokers LLC. All rights reserved. This code is su and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. """ -from ibapi.object_implem import Object -from ibapi import utils +from .object_implem import Object +from . import utils + class CommissionReport(Object): def __init__(self): self.execId = "" - self.commission = 0. + self.commission = 0. self.currency = "" - self.realizedPNL = 0. + self.realizedPNL = 0. self.yield_ = 0. self.yieldRedemptionDate = 0 # YYYYMMDD format def __str__(self): - return "ExecId: %s, Commission: %f, Currency: %s, RealizedPnL: %s, Yield: %s, YieldRedemptionDate: %d" % (self.execId, self.commission, - self.currency, utils.floatToStr(self.realizedPNL), utils.floatToStr(self.yield_), self.yieldRedemptionDate) + return "ExecId: %s, Commission: %f, Currency: %s, RealizedPnL: %s, Yield: %s, YieldRedemptionDate: %d" % (self.execId, self.commission, + self.currency, utils.floatToStr(self.realizedPNL), utils.floatToStr(self.yield_), self.yieldRedemptionDate) diff --git a/vnpy/api/ib/common.py b/vnpy/api/ib/common.py index cc70558c..e50022b5 100644 --- a/vnpy/api/ib/common.py +++ b/vnpy/api/ib/common.py @@ -5,8 +5,8 @@ and conditions of the IB API Non-Commercial License or the IB API Commercial Lic import sys -from ibapi.enum_implem import Enum -from ibapi.object_implem import Object +from .enum_implem import Enum +from .object_implem import Object NO_VALID_ID = -1 diff --git a/vnpy/api/ib/connection.py b/vnpy/api/ib/connection.py index b46281f4..e07f9cfd 100644 --- a/vnpy/api/ib/connection.py +++ b/vnpy/api/ib/connection.py @@ -1,3 +1,8 @@ +from .errors import * # @UnusedWildImport +from .common import * # @UnusedWildImport +import logging +import threading +import socket """ Copyright (C) 2018 Interactive Brokers LLC. All rights reserved. This code is subject to the terms and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. @@ -10,15 +15,7 @@ It allows us to keep some other info along with it. """ -import socket -import threading -import logging - -from ibapi.common import * # @UnusedWildImport -from ibapi.errors import * # @UnusedWildImport - - -#TODO: support SSL !! +# TODO: support SSL !! logger = logging.getLogger(__name__) @@ -31,23 +28,23 @@ class Connection: self.wrapper = None self.lock = threading.Lock() - def connect(self): try: self.socket = socket.socket() - #TODO: list the exceptions you want to catch + # TODO: list the exceptions you want to catch except socket.error: if self.wrapper: - self.wrapper.error(NO_VALID_ID, FAIL_CREATE_SOCK.code(), FAIL_CREATE_SOCK.msg()) + self.wrapper.error( + NO_VALID_ID, FAIL_CREATE_SOCK.code(), FAIL_CREATE_SOCK.msg()) try: self.socket.connect((self.host, self.port)) except socket.error: if self.wrapper: - self.wrapper.error(NO_VALID_ID, CONNECT_FAIL.code(), CONNECT_FAIL.msg()) - - self.socket.settimeout(1) #non-blocking + self.wrapper.error( + NO_VALID_ID, CONNECT_FAIL.code(), CONNECT_FAIL.msg()) + self.socket.settimeout(1) # non-blocking def disconnect(self): self.lock.acquire() @@ -61,19 +58,18 @@ class Connection: finally: self.lock.release() - def isConnected(self): - #TODO: also handle when socket gets interrupted/error + # TODO: also handle when socket gets interrupted/error return self.socket is not None - def sendMsg(self, msg): logger.debug("acquiring lock") self.lock.acquire() logger.debug("acquired lock") if not self.isConnected(): - logger.debug("sendMsg attempted while not connected, releasing lock") + logger.debug( + "sendMsg attempted while not connected, releasing lock") self.lock.release() return 0 try: @@ -90,10 +86,10 @@ class Connection: return nSent - def recvMsg(self): if not self.isConnected(): - logger.debug("recvMsg attempted while not connected, releasing lock") + logger.debug( + "recvMsg attempted while not connected, releasing lock") return b"" try: buf = self._recvAllMsg() @@ -105,7 +101,6 @@ class Connection: return buf - def _recvAllMsg(self): cont = True allbuf = b"" @@ -119,4 +114,3 @@ class Connection: cont = False return allbuf - diff --git a/vnpy/api/ib/contract.py b/vnpy/api/ib/contract.py index 706a17dc..75d90d39 100644 --- a/vnpy/api/ib/contract.py +++ b/vnpy/api/ib/contract.py @@ -1,3 +1,4 @@ +from .object_implem import Object """ Copyright (C) 2018 Interactive Brokers LLC. All rights reserved. This code is subject to the terms and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. @@ -12,9 +13,6 @@ and conditions of the IB API Non-Commercial License or the IB API Commercial Lic """ -from ibapi.object_implem import Object - - (SAME_POS, OPEN_POS, CLOSE_POS, UNKNOWN_POS) = range(4) @@ -30,7 +28,6 @@ class ComboLeg(Object): self.designatedLocation = "" self.exemptCode = -1 - def __str__(self): return ",".join(( str(self.conId), @@ -66,7 +63,8 @@ class Contract(Object): self.right = "" self.multiplier = "" self.exchange = "" - self.primaryExchange = "" # pick an actual (ie non-aggregate) exchange that the contract trades on. DO NOT SET TO SMART. + # pick an actual (ie non-aggregate) exchange that the contract trades on. DO NOT SET TO SMART. + self.primaryExchange = "" self.currency = "" self.localSymbol = "" self.tradingClass = "" @@ -74,12 +72,12 @@ class Contract(Object): self.secIdType = "" # CUSIP;SEDOL;ISIN;RIC self.secId = "" - #combos - self.comboLegsDescrip = "" # type: str; received in open order 14 and up for all combos + # combos + # type: str; received in open order 14 and up for all combos + self.comboLegsDescrip = "" self.comboLegs = None # type: list self.deltaNeutralContract = None - def __str__(self): s = ",".join(( str(self.conId), @@ -201,5 +199,3 @@ class ContractDescription(Object): def __init__(self): self.contract = Contract() self.derivativeSecTypes = None # type: list of strings - - diff --git a/vnpy/api/ib/decoder.py b/vnpy/api/ib/decoder.py index ea52566c..79a1f544 100644 --- a/vnpy/api/ib/decoder.py +++ b/vnpy/api/ib/decoder.py @@ -12,20 +12,20 @@ It will call the corresponding method from the EWrapper so that customer's code import logging -from ibapi import order_condition -from ibapi.message import IN -from ibapi.wrapper import * # @UnusedWildImport -from ibapi.order import OrderComboLeg -from ibapi.contract import ContractDescription -from ibapi.contract import ComboLeg -from ibapi.server_versions import * # @UnusedWildImport -from ibapi.utils import * # @UnusedWildImport -from ibapi.softdollartier import SoftDollarTier -from ibapi.ticktype import * # @UnusedWildImport -from ibapi.tag_value import TagValue -from ibapi.scanner import ScanData -from ibapi.errors import BAD_MESSAGE -from ibapi.common import * # @UnusedWildImport +from . import order_condition +from .message import IN +from .wrapper import * # @UnusedWildImport +from .order import OrderComboLeg +from .contract import ContractDescription +from .contract import ComboLeg +from .server_versions import * # @UnusedWildImport +from .utils import * # @UnusedWildImport +from .softdollartier import SoftDollarTier +from .ticktype import * # @UnusedWildImport +from .tag_value import TagValue +from .scanner import ScanData +from .errors import BAD_MESSAGE +from .common import * # @UnusedWildImport logger = logging.getLogger(__name__) diff --git a/vnpy/api/ib/execution.py b/vnpy/api/ib/execution.py index fabc83d0..e35e6a25 100644 --- a/vnpy/api/ib/execution.py +++ b/vnpy/api/ib/execution.py @@ -4,37 +4,38 @@ and conditions of the IB API Non-Commercial License or the IB API Commercial Lic """ +from .object_implem import Object -from ibapi.object_implem import Object class Execution(Object): def __init__(self): self.execId = "" - self.time = "" - self.acctNumber = "" - self.exchange = "" + self.time = "" + self.acctNumber = "" + self.exchange = "" self.side = "" self.shares = 0. - self.price = 0. + self.price = 0. self.permId = 0 self.clientId = 0 self.orderId = 0 self.liquidation = 0 self.cumQty = 0. self.avgPrice = 0. - self.orderRef = "" - self.evRule = "" + self.orderRef = "" + self.evRule = "" self.evMultiplier = 0. - self.modelCode = "" + self.modelCode = "" self.lastLiquidity = 0 def __str__(self): return "ExecId: %s, Time: %s, Account: %s, Exchange: %s, Side: %s, Shares: %f, Price: %f, PermId: %d, " \ - "ClientId: %d, OrderId: %d, Liquidation: %d, CumQty: %f, AvgPrice: %f, OrderRef: %s, EvRule: %s, " \ - "EvMultiplier: %f, ModelCode: %s, LastLiquidity: %d" % (self.execId, self.time, self.acctNumber, - self.exchange, self.side, self.shares, self.price, self.permId, self.clientId, self.orderId, self.liquidation, - self.cumQty, self.avgPrice, self.orderRef, self.evRule, self.evMultiplier, self.modelCode, self.lastLiquidity) + "ClientId: %d, OrderId: %d, Liquidation: %d, CumQty: %f, AvgPrice: %f, OrderRef: %s, EvRule: %s, " \ + "EvMultiplier: %f, ModelCode: %s, LastLiquidity: %d" % (self.execId, self.time, self.acctNumber, + self.exchange, self.side, self.shares, self.price, self.permId, self.clientId, self.orderId, self.liquidation, + self.cumQty, self.avgPrice, self.orderRef, self.evRule, self.evMultiplier, self.modelCode, self.lastLiquidity) + class ExecutionFilter(Object): @@ -45,6 +46,5 @@ class ExecutionFilter(Object): self.time = "" self.symbol = "" self.secType = "" - self.exchange = "" + self.exchange = "" self.side = "" - diff --git a/vnpy/api/ib/order.py b/vnpy/api/ib/order.py index 0aa703ad..5a7868d0 100644 --- a/vnpy/api/ib/order.py +++ b/vnpy/api/ib/order.py @@ -4,9 +4,9 @@ and conditions of the IB API Non-Commercial License or the IB API Commercial Lic """ -from ibapi.common import UNSET_INTEGER, UNSET_DOUBLE -from ibapi.object_implem import Object -from ibapi.softdollartier import SoftDollarTier +from .common import UNSET_INTEGER, UNSET_DOUBLE +from .object_implem import Object +from .softdollartier import SoftDollarTier # enum Origin (CUSTOMER, FIRM, UNKNOWN) = range(3) @@ -28,67 +28,71 @@ class Order(Object): def __init__(self): self.softDollarTier = SoftDollarTier("", "", "") # order identifier - self.orderId = 0 + self.orderId = 0 self.clientId = 0 - self.permId = 0 + self.permId = 0 # main order fields self.action = "" self.totalQuantity = 0 self.orderType = "" - self.lmtPrice = UNSET_DOUBLE - self.auxPrice = UNSET_DOUBLE + self.lmtPrice = UNSET_DOUBLE + self.auxPrice = UNSET_DOUBLE # extended order fields self.tif = "" # "Time in Force" - DAY, GTC, etc. self.activeStartTime = "" # for GTC orders self.activeStopTime = "" # for GTC orders self.ocaGroup = "" # one cancels all group name - self.ocaType = 0 # 1 = CANCEL_WITH_BLOCK, 2 = REDUCE_WITH_BLOCK, 3 = REDUCE_NON_BLOCK - self.orderRef = "" - self.transmit = True # if false, order will be created but not transmited - self.parentId = 0 # Parent order Id, to associate Auto STP or TRAIL orders with the original order. - self.blockOrder = False - self.sweepToFill = False - self.displaySize = 0 - self.triggerMethod = 0 # 0=Default, 1=Double_Bid_Ask, 2=Last, 3=Double_Last, 4=Bid_Ask, 7=Last_or_Bid_Ask, 8=Mid-point - self.outsideRth = False - self.hidden = False - self.goodAfterTime = "" # Format: 20060505 08:00:00 {time zone} - self.goodTillDate = "" # Format: 20060505 08:00:00 {time zone} - self.rule80A = "" # Individual = 'I', Agency = 'A', AgentOtherMember = 'W', IndividualPTIA = 'J', AgencyPTIA = 'U', AgentOtherMemberPTIA = 'M', IndividualPT = 'K', AgencyPT = 'Y', AgentOtherMemberPT = 'N' - self.allOrNone = False - self.minQty = UNSET_INTEGER #type: int - self.percentOffset = UNSET_DOUBLE # type: float; REL orders only + self.ocaType = 0 # 1 = CANCEL_WITH_BLOCK, 2 = REDUCE_WITH_BLOCK, 3 = REDUCE_NON_BLOCK + self.orderRef = "" + self.transmit = True # if false, order will be created but not transmited + # Parent order Id, to associate Auto STP or TRAIL orders with the original order. + self.parentId = 0 + self.blockOrder = False + self.sweepToFill = False + self.displaySize = 0 + # 0=Default, 1=Double_Bid_Ask, 2=Last, 3=Double_Last, 4=Bid_Ask, 7=Last_or_Bid_Ask, 8=Mid-point + self.triggerMethod = 0 + self.outsideRth = False + self.hidden = False + self.goodAfterTime = "" # Format: 20060505 08:00:00 {time zone} + self.goodTillDate = "" # Format: 20060505 08:00:00 {time zone} + self.rule80A = "" # Individual = 'I', Agency = 'A', AgentOtherMember = 'W', IndividualPTIA = 'J', AgencyPTIA = 'U', AgentOtherMemberPTIA = 'M', IndividualPT = 'K', AgencyPT = 'Y', AgentOtherMemberPT = 'N' + self.allOrNone = False + self.minQty = UNSET_INTEGER # type: int + self.percentOffset = UNSET_DOUBLE # type: float; REL orders only self.overridePercentageConstraints = False self.trailStopPrice = UNSET_DOUBLE # type: float - self.trailingPercent = UNSET_DOUBLE # type: float; TRAILLIMIT orders only + self.trailingPercent = UNSET_DOUBLE # type: float; TRAILLIMIT orders only # financial advisors only - self.faGroup = "" - self.faProfile = "" - self.faMethod = "" - self.faPercentage = "" + self.faGroup = "" + self.faProfile = "" + self.faMethod = "" + self.faPercentage = "" # institutional (ie non-cleared) only - self.designatedLocation = "" #used only when shortSaleSlot=2 - self.openClose = "O" # O=Open, C=Close - self.origin = CUSTOMER # 0=Customer, 1=Firm - self.shortSaleSlot = 0 # type: int; 1 if you hold the shares, 2 if they will be delivered from elsewhere. Only for Action=SSHORT - self.exemptCode = -1 + self.designatedLocation = "" # used only when shortSaleSlot=2 + self.openClose = "O" # O=Open, C=Close + self.origin = CUSTOMER # 0=Customer, 1=Firm + # type: int; 1 if you hold the shares, 2 if they will be delivered from elsewhere. Only for Action=SSHORT + self.shortSaleSlot = 0 + self.exemptCode = -1 # SMART routing only self.discretionaryAmt = 0 - self.eTradeOnly = True - self.firmQuoteOnly = True - self.nbboPriceCap = UNSET_DOUBLE # type: float + self.eTradeOnly = True + self.firmQuoteOnly = True + self.nbboPriceCap = UNSET_DOUBLE # type: float self.optOutSmartRouting = False # BOX exchange orders only - self.auctionStrategy = AUCTION_UNSET # type: int; AUCTION_MATCH, AUCTION_IMPROVEMENT, AUCTION_TRANSPARENT - self.startingPrice = UNSET_DOUBLE # type: float - self.stockRefPrice = UNSET_DOUBLE # type: float - self.delta = UNSET_DOUBLE # type: float + # type: int; AUCTION_MATCH, AUCTION_IMPROVEMENT, AUCTION_TRANSPARENT + self.auctionStrategy = AUCTION_UNSET + self.startingPrice = UNSET_DOUBLE # type: float + self.stockRefPrice = UNSET_DOUBLE # type: float + self.delta = UNSET_DOUBLE # type: float # pegged to stock and VOL orders only self.stockRangeLower = UNSET_DOUBLE # type: float @@ -98,11 +102,11 @@ class Order(Object): self.randomizeSize = False # VOLATILITY ORDERS ONLY - self.volatility = UNSET_DOUBLE # type: float - self.volatilityType = UNSET_INTEGER # type: int # 1=daily, 2=annual + self.volatility = UNSET_DOUBLE # type: float + self.volatilityType = UNSET_INTEGER # type: int # 1=daily, 2=annual self.deltaNeutralOrderType = "" - self.deltaNeutralAuxPrice = UNSET_DOUBLE # type: float - self.deltaNeutralConId = 0 + self.deltaNeutralAuxPrice = UNSET_DOUBLE # type: float + self.deltaNeutralConId = 0 self.deltaNeutralSettlingFirm = "" self.deltaNeutralClearingAccount = "" self.deltaNeutralClearingIntent = "" @@ -110,16 +114,16 @@ class Order(Object): self.deltaNeutralShortSale = False self.deltaNeutralShortSaleSlot = 0 self.deltaNeutralDesignatedLocation = "" - self.continuousUpdate = False - self.referencePriceType = UNSET_INTEGER # type: int; 1=Average, 2 = BidOrAsk + self.continuousUpdate = False + self.referencePriceType = UNSET_INTEGER # type: int; 1=Average, 2 = BidOrAsk # COMBO ORDERS ONLY - self.basisPoints = UNSET_DOUBLE # type: float; EFP orders only + self.basisPoints = UNSET_DOUBLE # type: float; EFP orders only self.basisPointsType = UNSET_INTEGER # type: int; EFP orders only # SCALE ORDERS ONLY - self.scaleInitLevelSize = UNSET_INTEGER # type: int - self.scaleSubsLevelSize = UNSET_INTEGER # type: int + self.scaleInitLevelSize = UNSET_INTEGER # type: int + self.scaleSubsLevelSize = UNSET_INTEGER # type: int self.scalePriceIncrement = UNSET_DOUBLE # type: float self.scalePriceAdjustValue = UNSET_DOUBLE # type: float self.scalePriceAdjustInterval = UNSET_INTEGER # type: int @@ -131,20 +135,21 @@ class Order(Object): self.scaleTable = "" # HEDGE ORDERS - self.hedgeType = "" # 'D' - delta, 'B' - beta, 'F' - FX, 'P' - pair - self.hedgeParam = "" # 'beta=X' value for beta hedge, 'ratio=Y' for pair hedge + self.hedgeType = "" # 'D' - delta, 'B' - beta, 'F' - FX, 'P' - pair + self.hedgeParam = "" # 'beta=X' value for beta hedge, 'ratio=Y' for pair hedge # Clearing info - self.account = "" # IB account - self.settlingFirm = "" - self.clearingAccount = "" #True beneficiary of the order - self.clearingIntent = "" # "" (Default), "IB", "Away", "PTA" (PostTrade) + self.account = "" # IB account + self.settlingFirm = "" + self.clearingAccount = "" # True beneficiary of the order + # "" (Default), "IB", "Away", "PTA" (PostTrade) + self.clearingIntent = "" # ALGO ORDERS ONLY - self.algoStrategy = "" + self.algoStrategy = "" - self.algoParams = None #TagValueList - self.smartComboRoutingParams = None #TagValueList + self.algoParams = None # TagValueList + self.smartComboRoutingParams = None # TagValueList self.algoId = "" diff --git a/vnpy/api/ib/order_condition.py b/vnpy/api/ib/order_condition.py index c28926aa..7c299bd4 100644 --- a/vnpy/api/ib/order_condition.py +++ b/vnpy/api/ib/order_condition.py @@ -4,11 +4,11 @@ and conditions of the IB API Non-Commercial License or the IB API Commercial Lic """ -from ibapi import comm -from ibapi.common import UNSET_DOUBLE -from ibapi.object_implem import Object -from ibapi.enum_implem import Enum -from ibapi.utils import decode +from . import comm +from .common import UNSET_DOUBLE +from .object_implem import Object +from .enum_implem import Enum +from .utils import decode #TODO: add support for Rebate, P/L, ShortableShares conditions diff --git a/vnpy/api/ib/order_state.py b/vnpy/api/ib/order_state.py index 0f8b11b9..87bf3734 100644 --- a/vnpy/api/ib/order_state.py +++ b/vnpy/api/ib/order_state.py @@ -3,23 +3,23 @@ Copyright (C) 2018 Interactive Brokers LLC. All rights reserved. This code is su and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. """ -from ibapi.common import UNSET_DOUBLE +from .common import UNSET_DOUBLE class OrderState: def __init__(self): - self.status= "" + self.status = "" - self.initMarginBefore= "" - self.maintMarginBefore= "" - self.equityWithLoanBefore= "" - self.initMarginChange= "" - self.maintMarginChange= "" - self.equityWithLoanChange= "" - self.initMarginAfter= "" - self.maintMarginAfter= "" - self.equityWithLoanAfter= "" + self.initMarginBefore = "" + self.maintMarginBefore = "" + self.equityWithLoanBefore = "" + self.initMarginChange = "" + self.maintMarginChange = "" + self.equityWithLoanChange = "" + self.initMarginAfter = "" + self.maintMarginAfter = "" + self.equityWithLoanAfter = "" self.commission = UNSET_DOUBLE # type: float self.minCommission = UNSET_DOUBLE # type: float diff --git a/vnpy/api/ib/reader.py b/vnpy/api/ib/reader.py index 9c7c525f..532b9b96 100644 --- a/vnpy/api/ib/reader.py +++ b/vnpy/api/ib/reader.py @@ -1,3 +1,6 @@ +from . import comm +from threading import Thread +import logging """ Copyright (C) 2018 Interactive Brokers LLC. All rights reserved. This code is subject to the terms and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. @@ -11,11 +14,6 @@ It will read the packets from the wire, use the low level IB messaging to remove the size prefix and put the rest in a Queue. """ -import logging -from threading import Thread - -from ibapi import comm - logger = logging.getLogger(__name__) @@ -38,7 +36,7 @@ class EReader(Thread): (size, msg, buf) = comm.read_msg(buf) #logger.debug("resp %s", buf.decode('ascii')) logger.debug("size:%d msg.size:%d msg:|%s| buf:%s|", size, - len(msg), buf, "|") + len(msg), buf, "|") if msg: self.msg_queue.put(msg) @@ -47,5 +45,3 @@ class EReader(Thread): break logger.debug("EReader thread finished") - - diff --git a/vnpy/api/ib/scanner.py b/vnpy/api/ib/scanner.py index 6249fa39..622cef94 100644 --- a/vnpy/api/ib/scanner.py +++ b/vnpy/api/ib/scanner.py @@ -4,12 +4,12 @@ and conditions of the IB API Non-Commercial License or the IB API Commercial Lic """ -from ibapi.object_implem import Object -from ibapi.common import UNSET_INTEGER, UNSET_DOUBLE +from .object_implem import Object +from .common import UNSET_INTEGER, UNSET_DOUBLE class ScanData(Object): - def __init__(self, contract = None, rank = 0, distance = "", benchmark = "", projection = "", legsStr = ""): + def __init__(self, contract=None, rank=0, distance="", benchmark="", projection="", legsStr=""): self.contract = contract self.rank = rank self.distance = distance @@ -18,40 +18,41 @@ class ScanData(Object): self.legsStr = legsStr def __str__(self): - return "Rank: %d, Symbol: %s, SecType: %s, Currency: %s, Distance: %s, Benchmark: %s, Projection: %s, Legs String: %s" % (self.rank, - self.contract.symbol, self.contract.secType, self.contract.currency, self.distance, - self.benchmark, self.projection, self.legsStr) - + return "Rank: %d, Symbol: %s, SecType: %s, Currency: %s, Distance: %s, Benchmark: %s, Projection: %s, Legs String: %s" % (self.rank, + self.contract.symbol, self.contract.secType, self.contract.currency, self.distance, + self.benchmark, self.projection, self.legsStr) + + NO_ROW_NUMBER_SPECIFIED = -1 + class ScannerSubscription(Object): def __init__(self): self.numberOfRows = NO_ROW_NUMBER_SPECIFIED self.instrument = "" self.locationCode = "" - self.scanCode = "" + self.scanCode = "" self.abovePrice = UNSET_DOUBLE self.belowPrice = UNSET_DOUBLE self.aboveVolume = UNSET_INTEGER self.marketCapAbove = UNSET_DOUBLE self.marketCapBelow = UNSET_DOUBLE - self.moodyRatingAbove = "" - self.moodyRatingBelow = "" - self.spRatingAbove = "" - self.spRatingBelow = "" - self.maturityDateAbove = "" - self.maturityDateBelow = "" + self.moodyRatingAbove = "" + self.moodyRatingBelow = "" + self.spRatingAbove = "" + self.spRatingBelow = "" + self.maturityDateAbove = "" + self.maturityDateBelow = "" self.couponRateAbove = UNSET_DOUBLE - self.couponRateBelow = UNSET_DOUBLE + self.couponRateBelow = UNSET_DOUBLE self.excludeConvertible = False self.averageOptionVolumeAbove = UNSET_INTEGER - self.scannerSettingPairs = "" - self.stockTypeFilter = "" - + self.scannerSettingPairs = "" + self.stockTypeFilter = "" def __str__(self): - s = "Instrument: %s, LocationCode: %s, ScanCode: %s" % (self.instrument, self.locationCode, self.scanCode) + s = "Instrument: %s, LocationCode: %s, ScanCode: %s" % ( + self.instrument, self.locationCode, self.scanCode) return s - diff --git a/vnpy/api/ib/softdollartier.py b/vnpy/api/ib/softdollartier.py index 67771dad..99dfe624 100644 --- a/vnpy/api/ib/softdollartier.py +++ b/vnpy/api/ib/softdollartier.py @@ -4,11 +4,11 @@ and conditions of the IB API Non-Commercial License or the IB API Commercial Lic """ -from ibapi.object_implem import Object +from .object_implem import Object + - class SoftDollarTier(Object): - def __init__(self, name = "", val = "", displayName = ""): + def __init__(self, name="", val="", displayName=""): self.name = name self.val = val self.displayName = displayName diff --git a/vnpy/api/ib/tag_value.py b/vnpy/api/ib/tag_value.py index f84ab2d9..2e879ffb 100644 --- a/vnpy/api/ib/tag_value.py +++ b/vnpy/api/ib/tag_value.py @@ -1,3 +1,4 @@ +from .object_implem import Object """ Copyright (C) 2018 Interactive Brokers LLC. All rights reserved. This code is subject to the terms and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. @@ -8,11 +9,9 @@ Simple class mapping a tag to a value. Both of them are strings. They are used in a list to convey extra info with the requests. """ -from ibapi.object_implem import Object - class TagValue(Object): - def __init__(self, tag:str=None, value:str=None): + def __init__(self, tag: str = None, value: str = None): self.tag = str(tag) self.value = str(value) @@ -20,5 +19,3 @@ class TagValue(Object): # this is not only used for Python dump but when encoding to send # so don't change it lightly ! return "%s=%s;" % (self.tag, self.value) - - diff --git a/vnpy/api/ib/ticktype.py b/vnpy/api/ib/ticktype.py index c6224339..f4c09aa4 100644 --- a/vnpy/api/ib/ticktype.py +++ b/vnpy/api/ib/ticktype.py @@ -1,3 +1,4 @@ +from .enum_implem import Enum """ Copyright (C) 2018 Interactive Brokers LLC. All rights reserved. This code is subject to the terms and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. @@ -8,102 +9,97 @@ and conditions of the IB API Non-Commercial License or the IB API Commercial Lic TickType type """ -from ibapi.enum_implem import Enum - # TickType TickType = int TickTypeEnum = Enum("BID_SIZE", - "BID", - "ASK", - "ASK_SIZE", - "LAST", - "LAST_SIZE", - "HIGH", - "LOW", - "VOLUME", - "CLOSE", - "BID_OPTION_COMPUTATION", - "ASK_OPTION_COMPUTATION", - "LAST_OPTION_COMPUTATION", - "MODEL_OPTION", - "OPEN", - "LOW_13_WEEK", - "HIGH_13_WEEK", - "LOW_26_WEEK", - "HIGH_26_WEEK", - "LOW_52_WEEK", - "HIGH_52_WEEK", - "AVG_VOLUME", - "OPEN_INTEREST", - "OPTION_HISTORICAL_VOL", - "OPTION_IMPLIED_VOL", - "OPTION_BID_EXCH", - "OPTION_ASK_EXCH", - "OPTION_CALL_OPEN_INTEREST", - "OPTION_PUT_OPEN_INTEREST", - "OPTION_CALL_VOLUME", - "OPTION_PUT_VOLUME", - "INDEX_FUTURE_PREMIUM", - "BID_EXCH", - "ASK_EXCH", - "AUCTION_VOLUME", - "AUCTION_PRICE", - "AUCTION_IMBALANCE", - "MARK_PRICE", - "BID_EFP_COMPUTATION", - "ASK_EFP_COMPUTATION", - "LAST_EFP_COMPUTATION", - "OPEN_EFP_COMPUTATION", - "HIGH_EFP_COMPUTATION", - "LOW_EFP_COMPUTATION", - "CLOSE_EFP_COMPUTATION", - "LAST_TIMESTAMP", - "SHORTABLE", - "FUNDAMENTAL_RATIOS", - "RT_VOLUME", - "HALTED", - "BID_YIELD", - "ASK_YIELD", - "LAST_YIELD", - "CUST_OPTION_COMPUTATION", - "TRADE_COUNT", - "TRADE_RATE", - "VOLUME_RATE", - "LAST_RTH_TRADE", - "RT_HISTORICAL_VOL", - "IB_DIVIDENDS", - "BOND_FACTOR_MULTIPLIER", - "REGULATORY_IMBALANCE", - "NEWS_TICK", - "SHORT_TERM_VOLUME_3_MIN", - "SHORT_TERM_VOLUME_5_MIN", - "SHORT_TERM_VOLUME_10_MIN", - "DELAYED_BID", - "DELAYED_ASK", - "DELAYED_LAST", - "DELAYED_BID_SIZE", - "DELAYED_ASK_SIZE", - "DELAYED_LAST_SIZE", - "DELAYED_HIGH", - "DELAYED_LOW", - "DELAYED_VOLUME", - "DELAYED_CLOSE", - "DELAYED_OPEN", - "RT_TRD_VOLUME", - "CREDITMAN_MARK_PRICE", - "CREDITMAN_SLOW_MARK_PRICE", - "DELAYED_BID_OPTION", - "DELAYED_ASK_OPTION", - "DELAYED_LAST_OPTION", - "DELAYED_MODEL_OPTION", - "LAST_EXCH", - "LAST_REG_TIME", - "FUTURES_OPEN_INTEREST", - "AVG_OPT_VOLUME", - "DELAYED_LAST_TIMESTAMP", - "SHORTABLE_SHARES", - "NOT_SET") - - - + "BID", + "ASK", + "ASK_SIZE", + "LAST", + "LAST_SIZE", + "HIGH", + "LOW", + "VOLUME", + "CLOSE", + "BID_OPTION_COMPUTATION", + "ASK_OPTION_COMPUTATION", + "LAST_OPTION_COMPUTATION", + "MODEL_OPTION", + "OPEN", + "LOW_13_WEEK", + "HIGH_13_WEEK", + "LOW_26_WEEK", + "HIGH_26_WEEK", + "LOW_52_WEEK", + "HIGH_52_WEEK", + "AVG_VOLUME", + "OPEN_INTEREST", + "OPTION_HISTORICAL_VOL", + "OPTION_IMPLIED_VOL", + "OPTION_BID_EXCH", + "OPTION_ASK_EXCH", + "OPTION_CALL_OPEN_INTEREST", + "OPTION_PUT_OPEN_INTEREST", + "OPTION_CALL_VOLUME", + "OPTION_PUT_VOLUME", + "INDEX_FUTURE_PREMIUM", + "BID_EXCH", + "ASK_EXCH", + "AUCTION_VOLUME", + "AUCTION_PRICE", + "AUCTION_IMBALANCE", + "MARK_PRICE", + "BID_EFP_COMPUTATION", + "ASK_EFP_COMPUTATION", + "LAST_EFP_COMPUTATION", + "OPEN_EFP_COMPUTATION", + "HIGH_EFP_COMPUTATION", + "LOW_EFP_COMPUTATION", + "CLOSE_EFP_COMPUTATION", + "LAST_TIMESTAMP", + "SHORTABLE", + "FUNDAMENTAL_RATIOS", + "RT_VOLUME", + "HALTED", + "BID_YIELD", + "ASK_YIELD", + "LAST_YIELD", + "CUST_OPTION_COMPUTATION", + "TRADE_COUNT", + "TRADE_RATE", + "VOLUME_RATE", + "LAST_RTH_TRADE", + "RT_HISTORICAL_VOL", + "IB_DIVIDENDS", + "BOND_FACTOR_MULTIPLIER", + "REGULATORY_IMBALANCE", + "NEWS_TICK", + "SHORT_TERM_VOLUME_3_MIN", + "SHORT_TERM_VOLUME_5_MIN", + "SHORT_TERM_VOLUME_10_MIN", + "DELAYED_BID", + "DELAYED_ASK", + "DELAYED_LAST", + "DELAYED_BID_SIZE", + "DELAYED_ASK_SIZE", + "DELAYED_LAST_SIZE", + "DELAYED_HIGH", + "DELAYED_LOW", + "DELAYED_VOLUME", + "DELAYED_CLOSE", + "DELAYED_OPEN", + "RT_TRD_VOLUME", + "CREDITMAN_MARK_PRICE", + "CREDITMAN_SLOW_MARK_PRICE", + "DELAYED_BID_OPTION", + "DELAYED_ASK_OPTION", + "DELAYED_LAST_OPTION", + "DELAYED_MODEL_OPTION", + "LAST_EXCH", + "LAST_REG_TIME", + "FUTURES_OPEN_INTEREST", + "AVG_OPT_VOLUME", + "DELAYED_LAST_TIMESTAMP", + "SHORTABLE_SHARES", + "NOT_SET") diff --git a/vnpy/api/ib/utils.py b/vnpy/api/ib/utils.py index be4acfa5..fa392d5b 100644 --- a/vnpy/api/ib/utils.py +++ b/vnpy/api/ib/utils.py @@ -1,3 +1,7 @@ +from .common import UNSET_INTEGER, UNSET_DOUBLE +import inspect +import logging +import sys """ Copyright (C) 2018 Interactive Brokers LLC. All rights reserved. This code is subject to the terms and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. @@ -9,13 +13,6 @@ Collection of misc tools """ -import sys -import logging -import inspect - -from ibapi.common import UNSET_INTEGER, UNSET_DOUBLE - - logger = logging.getLogger(__name__) @@ -37,27 +34,31 @@ class LogFunction(object): def __call__(self, fn): def newFn(origSelf, *args, **kwargs): if logger.getLogger().isEnabledFor(self.logLevel): - argNames = [argName for argName in inspect.getfullargspec(fn)[0] if argName != 'self'] + argNames = [argName for argName in inspect.getfullargspec(fn)[ + 0] if argName != 'self'] logger.log(self.logLevel, - "{} {} {} kw:{}".format(self.text, fn.__name__, - [nameNarg for nameNarg in zip(argNames, args) if nameNarg[1] is not origSelf], kwargs)) + "{} {} {} kw:{}".format(self.text, fn.__name__, + [nameNarg for nameNarg in zip(argNames, args) if nameNarg[1] is not origSelf], kwargs)) fn(origSelf, *args) return newFn -def current_fn_name(parent_idx = 0): - #depth is 1 bc this is already a fn, so we need the caller +def current_fn_name(parent_idx=0): + # depth is 1 bc this is already a fn, so we need the caller return sys._getframe(1 + parent_idx).f_code.co_name def setattr_log(self, var_name, var_value): #import code; code.interact(local=locals()) - logger.debug("%s %s %s=|%s|", self.__class__, id(self), var_name, var_value) + logger.debug("%s %s %s=|%s|", self.__class__, + id(self), var_name, var_value) super(self.__class__, self).__setattr__(var_name, var_value) SHOW_UNSET = True -def decode(the_type, fields, show_unset = False): + + +def decode(the_type, fields, show_unset=False): try: s = next(fields) except StopIteration: @@ -71,7 +72,8 @@ def decode(the_type, fields, show_unset = False): elif type(s) is bytes: return s.decode() else: - raise TypeError("unsupported incoming type " + type(s) + " for desired type 'str") + raise TypeError("unsupported incoming type " + + type(s) + " for desired type 'str") orig_type = the_type if the_type is bool: @@ -84,7 +86,8 @@ def decode(the_type, fields, show_unset = False): elif the_type is int: n = UNSET_INTEGER else: - raise TypeError("unsupported desired type for empty value" + the_type) + raise TypeError( + "unsupported desired type for empty value" + the_type) else: n = the_type(s) else: @@ -96,7 +99,6 @@ def decode(the_type, fields, show_unset = False): return n - def ExerciseStaticMethods(klass): import types @@ -108,8 +110,6 @@ def ExerciseStaticMethods(klass): print(var()) print() + def floatToStr(val): - return str(val) if val != UNSET_DOUBLE else ""; - - - + return str(val) if val != UNSET_DOUBLE else "" diff --git a/vnpy/api/ib/wrapper.py b/vnpy/api/ib/wrapper.py index 47869df8..8973cdb8 100644 --- a/vnpy/api/ib/wrapper.py +++ b/vnpy/api/ib/wrapper.py @@ -21,14 +21,14 @@ server and client. import logging -from ibapi.common import * # @UnusedWildImport -from ibapi.utils import * # @UnusedWildImport -from ibapi.contract import (Contract, ContractDetails, DeltaNeutralContract) -from ibapi.order import Order -from ibapi.order_state import OrderState -from ibapi.execution import Execution -from ibapi.ticktype import * # @UnusedWildImport -from ibapi.commission_report import CommissionReport +from .common import * # @UnusedWildImport +from .utils import * # @UnusedWildImport +from .contract import (Contract, ContractDetails, DeltaNeutralContract) +from .order import Order +from .order_state import OrderState +from .execution import Execution +from .ticktype import * # @UnusedWildImport +from .commission_report import CommissionReport logger = logging.getLogger(__name__)