Source code for ib_insync.order

from eventkit import Event

from .objects import Object, SoftDollarTier
from .util import UNSET_DOUBLE, UNSET_INTEGER

__all__ = (
    'Trade OrderStatus Order '
    'LimitOrder MarketOrder StopOrder StopLimitOrder '
    'OrderCondition ExecutionCondition MarginCondition TimeCondition '
    'PriceCondition PercentChangeCondition VolumeCondition').split()


[docs]class Trade(Object): """ Trade keeps track of an order, its status and all its fills. Events: * ``statusEvent`` (trade: :class:`.Trade`) * ``modifyEvent`` (trade: :class:`.Trade`) * ``fillEvent`` (trade: :class:`.Trade`, fill: :class:`.Fill`) * ``commissionReportEvent`` (trade: :class:`.Trade`, fill: :class:`.Fill`, commissionReport: :class:`.CommissionReport`) * ``filledEvent`` (trade: :class:`.Trade`) * ``cancelEvent`` (trade: :class:`.Trade`) * ``cancelledEvent`` (trade: :class:`.Trade`) """ events = ( 'statusEvent', 'modifyEvent', 'fillEvent', 'commissionReportEvent', 'filledEvent', 'cancelEvent', 'cancelledEvent') defaults = dict( contract=None, order=None, orderStatus=None, fills=None, log=None ) __slots__ = tuple(defaults.keys()) + events + ('__dict__',) def __init__(self, *args, **kwargs): Object.__init__(self, *args, **kwargs) self.statusEvent = Event('statusEvent') self.modifyEvent = Event('modifyEvent') self.fillEvent = Event('fillEvent') self.commissionReportEvent = Event('commissionReportEvent') self.filledEvent = Event('filledEvent') self.cancelEvent = Event('cancelEvent') self.cancelledEvent = Event('cancelledEvent')
[docs] def isActive(self): """ True if eligible for execution, false otherwise. """ return self.orderStatus.status in OrderStatus.ActiveStates
[docs] def isDone(self): """ True if completely filled or cancelled, false otherwise. """ return self.orderStatus.status in OrderStatus.DoneStates
[docs] def filled(self): """ Number of shares filled. """ fills = self.fills if self.contract.secType == 'BAG': # don't count fills for the leg contracts fills = [f for f in fills if f.contract.secType == 'BAG'] return sum(f.execution.shares for f in fills)
[docs] def remaining(self): """ Number of shares remaining to be filled. """ return self.order.totalQuantity - self.filled()
[docs]class OrderStatus(Object): defaults = dict( orderId=0, status='', filled=0, remaining=0, avgFillPrice=0.0, permId=0, parentId=0, lastFillPrice=0.0, clientId=0, whyHeld='', mktCapPrice=0.0, lastLiquidity=0 ) __slots__ = defaults.keys() PendingSubmit = 'PendingSubmit' PendingCancel = 'PendingCancel' PreSubmitted = 'PreSubmitted' Submitted = 'Submitted' ApiPending = 'ApiPending' ApiCancelled = 'ApiCancelled' Cancelled = 'Cancelled' Filled = 'Filled' Inactive = 'Inactive' DoneStates = {'Filled', 'Cancelled', 'ApiCancelled'} ActiveStates = {'PendingSubmit', 'ApiPending', 'PreSubmitted', 'Submitted'}
[docs]class Order(Object): """ Order for trading contracts. https://interactivebrokers.github.io/tws-api/available_orders.html """ defaults = dict( orderId=0, clientId=0, permId=0, action='', totalQuantity=0.0, orderType='', lmtPrice=UNSET_DOUBLE, auxPrice=UNSET_DOUBLE, tif='', activeStartTime='', activeStopTime='', ocaGroup='', ocaType=0, orderRef='', transmit=True, parentId=0, blockOrder=False, sweepToFill=False, displaySize=0, triggerMethod=0, outsideRth=False, hidden=False, goodAfterTime='', goodTillDate='', rule80A='', allOrNone=False, minQty=UNSET_INTEGER, percentOffset=UNSET_DOUBLE, overridePercentageConstraints=False, trailStopPrice=UNSET_DOUBLE, trailingPercent=UNSET_DOUBLE, faGroup='', faProfile='', faMethod='', faPercentage='', designatedLocation='', openClose="O", origin=0, shortSaleSlot=0, exemptCode=-1, discretionaryAmt=0, eTradeOnly=True, firmQuoteOnly=True, nbboPriceCap=UNSET_DOUBLE, optOutSmartRouting=False, auctionStrategy=0, startingPrice=UNSET_DOUBLE, stockRefPrice=UNSET_DOUBLE, delta=UNSET_DOUBLE, stockRangeLower=UNSET_DOUBLE, stockRangeUpper=UNSET_DOUBLE, randomizePrice=False, randomizeSize=False, volatility=UNSET_DOUBLE, volatilityType=UNSET_INTEGER, deltaNeutralOrderType='', deltaNeutralAuxPrice=UNSET_DOUBLE, deltaNeutralConId=0, deltaNeutralSettlingFirm='', deltaNeutralClearingAccount='', deltaNeutralClearingIntent='', deltaNeutralOpenClose='', deltaNeutralShortSale=False, deltaNeutralShortSaleSlot=0, deltaNeutralDesignatedLocation='', continuousUpdate=False, referencePriceType=UNSET_INTEGER, basisPoints=UNSET_DOUBLE, basisPointsType=UNSET_INTEGER, scaleInitLevelSize=UNSET_INTEGER, scaleSubsLevelSize=UNSET_INTEGER, scalePriceIncrement=UNSET_DOUBLE, scalePriceAdjustValue=UNSET_DOUBLE, scalePriceAdjustInterval=UNSET_INTEGER, scaleProfitOffset=UNSET_DOUBLE, scaleAutoReset=False, scaleInitPosition=UNSET_INTEGER, scaleInitFillQty=UNSET_INTEGER, scaleRandomPercent=False, scaleTable='', hedgeType='', hedgeParam='', account='', settlingFirm='', clearingAccount='', clearingIntent='', algoStrategy='', algoParams=None, smartComboRoutingParams=None, algoId='', whatIf=False, notHeld=False, solicited=False, modelCode='', orderComboLegs=None, orderMiscOptions=None, referenceContractId=0, peggedChangeAmount=0.0, isPeggedChangeAmountDecrease=False, referenceChangeAmount=0.0, referenceExchangeId='', adjustedOrderType='', triggerPrice=UNSET_DOUBLE, adjustedStopPrice=UNSET_DOUBLE, adjustedStopLimitPrice=UNSET_DOUBLE, adjustedTrailingAmount=UNSET_DOUBLE, adjustableTrailingUnit=0, lmtPriceOffset=UNSET_DOUBLE, conditions=None, conditionsCancelOrder=False, conditionsIgnoreRth=False, extOperator='', softDollarTier=None, cashQty=UNSET_DOUBLE, mifid2DecisionMaker='', mifid2DecisionAlgo='', mifid2ExecutionTrader='', mifid2ExecutionAlgo='', dontUseAutoPriceForHedge=False, isOmsContainer=False, discretionaryUpToLimitPrice=False, autoCancelDate='', filledQuantity=UNSET_DOUBLE, refFuturesConId=0, autoCancelParent=False, shareholder='', imbalanceOnly=False, routeMarketableToBbo=False, parentPermId=0, usePriceMgmtAlgo=False) __slots__ = defaults.keys() def __init__(self, *args, **kwargs): Object.__init__(self, *args, **kwargs) if not self.conditions: self.conditions = [] if not self.softDollarTier: self.softDollarTier = SoftDollarTier() def __repr__(self): attrs = self.nonDefaults() if self.__class__ is not Order: attrs.pop('orderType', None) clsName = self.__class__.__name__ kwargs = ', '.join(f'{k}={v!r}' for k, v in attrs.items()) return f'{clsName}({kwargs})' __str__ = __repr__ def __eq__(self, other): return self is other def __hash__(self): return id(self)
[docs]class LimitOrder(Order): __slots__ = () def __init__(self, action, totalQuantity, lmtPrice, **kwargs): Order.__init__( self, orderType='LMT', action=action, totalQuantity=totalQuantity, lmtPrice=lmtPrice, **kwargs)
[docs]class MarketOrder(Order): __slots__ = () def __init__(self, action, totalQuantity, **kwargs): Order.__init__( self, orderType='MKT', action=action, totalQuantity=totalQuantity, **kwargs)
[docs]class StopOrder(Order): __slots__ = () def __init__(self, action, totalQuantity, stopPrice, **kwargs): Order.__init__( self, orderType='STP', action=action, totalQuantity=totalQuantity, auxPrice=stopPrice, **kwargs)
[docs]class StopLimitOrder(Order): __slots__ = () def __init__(self, action, totalQuantity, lmtPrice, stopPrice, **kwargs): Order.__init__( self, orderType='STP LMT', action=action, totalQuantity=totalQuantity, lmtPrice=lmtPrice, auxPrice=stopPrice, **kwargs)
[docs]class OrderCondition(Object): __slots__ = ()
[docs] @staticmethod def createClass(condType): d = { 1: PriceCondition, 3: TimeCondition, 4: MarginCondition, 5: ExecutionCondition, 6: VolumeCondition, 7: PercentChangeCondition} return d[condType]
def __repr__(self): clsName = self.__class__.__qualname__ kwargs = ', '.join(f'{k}={v!r}' for k, v in self.dict().items()) return f'{clsName}({kwargs})'
[docs] def And(self): self.conjunction = 'a' return self
[docs] def Or(self): self.conjunction = 'o' return self
[docs]class PriceCondition(OrderCondition): defaults = dict( condType=1, conjunction='a', isMore=True, price=0.0, conId=0, exch='', triggerMethod=0) __slots__ = defaults.keys()
[docs]class TimeCondition(OrderCondition): defaults = dict( condType=3, conjunction='a', isMore=True, time='') __slots__ = defaults.keys()
[docs]class MarginCondition(OrderCondition): defaults = dict( condType=4, conjunction='a', isMore=True, percent=0) __slots__ = defaults.keys()
[docs]class ExecutionCondition(OrderCondition): defaults = dict( condType=5, conjunction='a', secType='', exch='', symbol='') __slots__ = defaults.keys()
[docs]class VolumeCondition(OrderCondition): defaults = dict( condType=6, conjunction='a', isMore=True, volume=0, conId=0, exch='') __slots__ = defaults.keys()
[docs]class PercentChangeCondition(OrderCondition): defaults = dict( condType=7, conjunction='a', isMore=True, changePercent=0.0, conId=0, exch='') __slots__ = defaults.keys()