ib-api-reloaded / ib_async

Python sync/async framework for Interactive Brokers API (replaces ib_insync)
BSD 2-Clause "Simplified" License
351 stars 57 forks source link

How to determine US cents denominated future contract? #55

Closed andrewyang95 closed 1 month ago

andrewyang95 commented 1 month ago

I am trying to compute future contract nominal size in US dollar, but I am unable to determine if this contract is US cents or US dollar denominated. Are there any fields we can use instead of hard-coding?

I checked contract details: ContractDetails(contract=Contract(secType='FUT', conId=665643542, symbol='YK', lastTradeDateOrContractMonth='20260814', multiplier='1000', exchange='CBOT', currency='USD', localSymbol='XKQ6', tradingClass='XK'), marketName='XK', minTick=0.00125, orderTypes='ACTIVETIM,AD,ADJUST,ALERT,ALGO,ALLOC,AVGCOST,BASKET,BENCHPX,COND,CONDORDER,DAY,DEACT,DEACTDIS,DEACTEOD,GAT,GTC,GTD,GTT,HID,ICE,IOC,LIT,LMT,LTH,MIT,MKT,MKTPROT,MTL,NGCOMB,NONALGO,OCA,PEGBENCH,RFQ,SCALE,SCALERST,SNAPMID,SNAPMKT,SNAPREL,STP,STPLMT,STPPROT,TRAIL,TRAILLIT,TRAILLMT,TRAILMIT,WHATIF', validExchanges='CBOT', priceMagnifier=100, underConId=13393285, longName='Mini Sized Soybean Futures', contractMonth='202608', industry='', category='', subcategory='', timeZoneId='US/Central', tradingHours=';20240728:1900-20240729:0745;20240729:0830-20240729:1320;20240729:1900-20240730:0745;20240730:0830-20240730:1320;20240730:1900-20240731:0745;20240731:0830-20240731:1320;20240731:1900-20240801:0745;20240801:0830-20240801:1320;20240801:1900-20240802:0745;20240802:0830-20240802:1320', liquidHours='20240728:CLOSED;20240729:0830-20240729:1320;20240730:0830-20240730:1320;20240731:0830-20240731:1320;20240801:0830-20240801:1320;20240802:0830-20240802:1320', evRule='', evMultiplier=0, mdSizeMultiplier=1, aggGroup=2147483647, underSymbol='YK', underSecType='IND', marketRuleIds='149', secIdList=[], realExpirationDate='20260814', lastTradeTime='12:01:00', stockType='', minSize=1.0, sizeIncrement=1.0, suggestedSizeIncrement=1.0, cusip='', ratings='', descAppend='', bondType='', couponType='', callable=False, putable=False, coupon=0, convertible=False, maturity='', issueDate='', nextOptionDate='', nextOptionType='', nextOptionPartial=False, notes='')

Quote: Ticker(contract=Contract(secType='FUT', conId=526264570, symbol='YK', lastTradeDateOrContractMonth='20240814', multiplier='1000', exchange='CBOT', currency='USD', localSymbol='XKQ4', tradingClass='XK'), time=datetime.datetime(2024, 7, 28, 15, 2, 11, 847470, tzinfo=datetime.timezone.utc), marketDataType=2, minTick=0.00125, bid=1050.0, bidSize=1.0, ask=1072.0, askSize=1.0, last=1079.375, lastSize=1.0, volume=210.0, open=1114.0, high=1116.25, low=1077.875, close=1116.0, halted=-1.0, ticks=[TickData(time=datetime.datetime(2024, 7, 28, 15, 2, 11, 847470, tzinfo=datetime.timezone.utc), tickType=4, price=1079.375, size=1.0)], bboExchange='40006', snapshotPermissions=3)

None of them contain the actual contract currency unit, which is US-cents, not US dollar.

gnzsnz commented 1 month ago

the multiplier is multiplier='1000' isn't this what you are looking for?

andrewyang95 commented 1 month ago

Multiplier means different thing. To calculate nominal size, I use price x price_to_usd x multipler = 1079 x 0.01 x 1000 .

Since price is in USD cents, how can I programatically get price_to_usd for any future contract?

andrewyang95 commented 1 month ago

ok, I found priceMagnifier=100 hidden in the ContractDetails

gnzsnz commented 1 month ago

@mattsta I would like to suggest to move this issue as a discussion. as this is not a bug, been under discussions will help to give it more visibility.

mattsta commented 1 month ago

Yeah, this is actually a 3 step process I worked through myself recently. We should write an extra help page just about it.

Basically:

you need a Ticker() with minTick for the smallest increment you can trade, but that's not always enough because the price increment is defined per exchange.

The real answer is you need to:

Basically:

mandatory $0.05 or $0.10 prices required

2024-08-09 09:23:47.850 | INFO     | icli.lang:run:724 - [SPXW  240809P05200000] Details: ib_async.contract.ContractDetails(
    contract=ib_async.contract.Contract(
        secType='OPT',
        conId=709107149,
        symbol='SPX',
        lastTradeDateOrContractMonth='20240809',
        strike=5200.0,
        right='P',
        multiplier='100',
        exchange='SMART',
        currency='USD',
        localSymbol='SPXW  240809P05200000',
        tradingClass='SPXW'
    ),
    marketName='SPXW',
    minTick=0.05,
    orderTypes='ACTIVETIM,AD,ADJUST,ALERT,ALGO,ALLOC,AVGCOST,BASKET,COND,CONDORDER,'
        'DAY,DEACT,DEACTDIS,DEACTEOD,DIS,FOK,GAT,GTC,GTD,GTT,HID,ICE,IOC,LIT,'
        'LMT,MIT,MKT,MTL,NGCOMB,NONALGO,OCA,OPENCLOSE,PEGMIDVOL,PEGMKTVOL,'
        'PEGPRMVOL,PEGSRFVOL,POSTONLY,PRICECHK,REL,RELPCTOFS,RELSTK,RTH,SCALE,'
        'SCALERST,SIZECHK,SMARTSTG,SNAPMID,SNAPMKT,SNAPREL,STP,STPLMT,TRAIL,'
        'TRAILLIT,TRAILLMT,TRAILMIT,VOLAT,WHATIF',
    validExchanges='SMART,CBOE,IBUSOPT',
    priceMagnifier=1,
    underConId=416904,
    longName='S&P 500 Stock Index',
    contractMonth='202408',
    industry='Indices',
    category='Broad Range Equity Index',
    subcategory='*',
    timeZoneId='America/New_York',
    tradingHours='20240807:1915-20240808:0815;20240808:0830-20240808:1600;20240808:'
        '1915-20240809:0815;20240809:0830-20240809:1500;20240810:CLOSED;'
        '20240811:CLOSED',
    liquidHours='20240808:0830-20240808:1515;20240809:0830-20240809:1500;20240810:'
        'CLOSED;20240811:CLOSED',
    aggGroup=2,
    underSymbol='SPX',
    underSecType='IND',
    marketRuleIds='110,110,110',
    realExpirationDate='20240809',
    lastTradeTime='16:00:00',
    minSize=1.0,
    sizeIncrement=1.0,
    suggestedSizeIncrement=1.0
)
2024-08-09 09:23:47.852 | INFO     | icli.lang:run:744 - [SPXW  240809P05200000] Exchange Rule Pairs:
{
    (
        ib_async.objects.PriceIncrement(lowEdge=0.0, increment=0.05),
        ib_async.objects.PriceIncrement(lowEdge=3.0, increment=0.1)
    ): ['SMART', 'CBOE', 'IBUSOPT']
}

QQQ, IWM, and SPY allow $0.01 on all exchanges

2024-08-09 09:24:55.388 | INFO     | icli.lang:run:724 - [QQQ   240920C00500000] Details: ib_async.contract.ContractDetails(
    contract=ib_async.contract.Contract(
        secType='OPT',
        conId=675266346,
        symbol='QQQ',
        lastTradeDateOrContractMonth='20240920',
        strike=500.0,
        right='C',
        multiplier='100',
        exchange='SMART',
        currency='USD',
        localSymbol='QQQ   240920C00500000',
        tradingClass='QQQ'
    ),
    marketName='QQQ',
    minTick=0.01,
    orderTypes='ACTIVETIM,AD,ADJUST,ALERT,ALGO,ALLOC,AON,AVGCOST,BASKET,COND,'
        'CONDORDER,DAY,DEACT,DEACTDIS,DEACTEOD,DIS,FOK,GAT,GTC,GTD,GTT,HID,'
        'ICE,IOC,LIT,LMT,MIT,MKT,MTL,NGCOMB,NONALGO,OCA,OPENCLOSE,PAON,'
        'PEGMIDVOL,PEGMKTVOL,PEGPRMVOL,PEGSRFVOL,POSTONLY,PRICECHK,REL,'
        'RELPCTOFS,RELSTK,SCALE,SCALERST,SIZECHK,SMARTSTG,SNAPMID,SNAPMKT,'
        'SNAPREL,STP,STPLMT,TRAIL,TRAILLIT,TRAILLMT,TRAILMIT,VOLAT,WHATIF',
    validExchanges='SMART,AMEX,CBOE,PHLX,PSE,ISE,BOX,BATS,NASDAQOM,CBOE2,NASDAQBX,MIAX,'
        'GEMINI,EDGX,MERCURY,PEARL,EMERALD,MEMX,IBUSOPT',
    priceMagnifier=1,
    underConId=320227571,
    longName='INVESCO QQQ TRUST SERIES 1',
    contractMonth='202409',
    timeZoneId='US/Eastern',
    tradingHours='20240809:0930-20240809:1615;20240810:CLOSED;20240811:CLOSED;20240812:'
        '0930-20240812:1615;20240813:0930-20240813:1615;20240814:0930-'
        '20240814:1615',
    liquidHours='20240809:0930-20240809:1615;20240810:CLOSED;20240811:CLOSED;20240812:'
        '0930-20240812:1615;20240813:0930-20240813:1615;20240814:0930-'
        '20240814:1615',
    aggGroup=2,
    underSymbol='QQQ',
    underSecType='STK',
    marketRuleIds='32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32',
    realExpirationDate='20240920',
    minSize=1.0,
    sizeIncrement=1.0,
    suggestedSizeIncrement=1.0
)
2024-08-09 09:24:55.391 | INFO     | icli.lang:run:744 - [QQQ   240920C00500000] Exchange Rule Pairs:
{
    (
        ib_async.objects.PriceIncrement(lowEdge=0.0, increment=0.01),
    ): [
        'SMART',
        'AMEX',
        'CBOE',
        'PHLX',
        'PSE',
        'ISE',
        'BOX',
        'BATS',
        'NASDAQOM',
        'CBOE2',
        'NASDAQBX',
        'MIAX',
        'GEMINI',
        'EDGX',
        'MERCURY',
        'PEARL',
        'EMERALD',
        'MEMX',
        'IBUSOPT'
    ]
}

other equity options allow $0.01 for all prices on 3 exchanges but require rounding to $0.05 or $0.10 on regular exchanges (depending on if underlying is in the "penny pilot program" or not)

2024-08-09 09:28:50.474 | INFO     | icli.lang:run:724 - [AMD   240920C00160000] Details: ib_async.contract.ContractDetails(
    contract=ib_async.contract.Contract(
        secType='OPT',
        conId=641117476,
        symbol='AMD',
        lastTradeDateOrContractMonth='20240920',
        strike=160.0,
        right='C',
        multiplier='100',
        exchange='SMART',
        currency='USD',
        localSymbol='AMD   240920C00160000',
        tradingClass='AMD'
    ),
    marketName='AMD',
    minTick=0.01,
    orderTypes='ACTIVETIM,AD,ADJUST,ALERT,ALGO,ALLOC,AON,AVGCOST,BASKET,COND,'
        'CONDORDER,DAY,DEACT,DEACTDIS,DEACTEOD,DIS,FOK,GAT,GTC,GTD,GTT,HID,'
        'ICE,IOC,LIT,LMT,MIT,MKT,MTL,NGCOMB,NONALGO,OCA,OPENCLOSE,PAON,'
        'PEGMIDVOL,PEGMKTVOL,PEGPRMVOL,PEGSRFVOL,POSTONLY,PRICECHK,REL,'
        'RELPCTOFS,RELSTK,SCALE,SCALERST,SIZECHK,SMARTSTG,SNAPMID,SNAPMKT,'
        'SNAPREL,STP,STPLMT,TRAIL,TRAILLIT,TRAILLMT,TRAILMIT,VOLAT,WHATIF',
    validExchanges='SMART,AMEX,CBOE,PHLX,PSE,ISE,BOX,BATS,NASDAQOM,CBOE2,NASDAQBX,MIAX,'
        'GEMINI,EDGX,MERCURY,PEARL,EMERALD,MEMX,IBUSOPT',
    priceMagnifier=1,
    underConId=4391,
    longName='ADVANCED MICRO DEVICES',
    contractMonth='202409',
    industry='Technology',
    category='Semiconductors',
    subcategory='Electronic Compo-Semicon',
    timeZoneId='US/Eastern',
    tradingHours='20240809:0930-20240809:1600;20240810:CLOSED;20240811:CLOSED;20240812:'
        '0930-20240812:1600;20240813:0930-20240813:1600;20240814:0930-'
        '20240814:1600',
    liquidHours='20240809:0930-20240809:1600;20240810:CLOSED;20240811:CLOSED;20240812:'
        '0930-20240812:1600;20240813:0930-20240813:1600;20240814:0930-'
        '20240814:1600',
    aggGroup=2,
    underSymbol='AMD',
    underSecType='STK',
    marketRuleIds='32,109,109,109,109,109,109,109,32,109,32,109,109,109,109,109,109,109,'
        '32',
    realExpirationDate='20240920',
    minSize=1.0,
    sizeIncrement=1.0,
    suggestedSizeIncrement=1.0
)
2024-08-09 09:28:50.476 | INFO     | icli.lang:run:744 - [AMD   240920C00160000] Exchange Rule Pairs:
{
    (
        ib_async.objects.PriceIncrement(lowEdge=0.0, increment=0.01),
    ): ['SMART', 'NASDAQOM', 'NASDAQBX', 'IBUSOPT'],
    (
        ib_async.objects.PriceIncrement(lowEdge=0.0, increment=0.01),
        ib_async.objects.PriceIncrement(lowEdge=3.0, increment=0.05)
    ): [
        'AMEX',
        'CBOE',
        'PHLX',
        'PSE',
        'ISE',
        'BOX',
        'BATS',
        'CBOE2',
        'MIAX',
        'GEMINI',
        'EDGX',
        'MERCURY',
        'PEARL',
        'EMERALD',
        'MEMX'
    ]
}

versus one with priceMagnifier too:

here, the official contract is quoted in 0.00025 but IBKR provides quotes and limit order prices 100x higher, so you are quoted in $0.025 and orders must be rounded to the "magnified" contract price instead.

2024-08-09 09:25:33.511 | INFO     | icli.lang:run:724 - [LEQ4] Details: ib_async.contract.ContractDetails(
    contract=ib_async.contract.Contract(
        secType='FUT',
        conId=617184955,
        symbol='LE',
        lastTradeDateOrContractMonth='20240830',
        multiplier='40000',
        exchange='CME',
        currency='USD',
        localSymbol='LEQ4',
        tradingClass='LE'
    ),
    marketName='LE',
    minTick=0.00025,
    orderTypes='ACTIVETIM,AD,ADJUST,ALERT,ALGO,ALLOC,AVGCOST,BASKET,BENCHPX,COND,'
        'CONDORDER,DAY,DEACT,DEACTDIS,DEACTEOD,GAT,GTC,GTD,GTT,HID,ICE,IOC,'
        'LIT,LMT,LTH,MIT,MKT,MKTPROT,MTL,NGCOMB,NONALGO,OCA,PEGBENCH,RFQ,'
        'SCALE,SCALERST,SNAPMID,SNAPMKT,SNAPREL,STP,STPLMT,STPPROT,TRAIL,'
        'TRAILLIT,TRAILLMT,TRAILMIT,WHATIF',
    validExchanges='CME,QBALGO',
    priceMagnifier=100,
    underConId=33221066,
    longName='Live Cattle',
    contractMonth='202408',
    timeZoneId='America/New_York',
    tradingHours='20240809:0830-20240809:1305;20240810:CLOSED;20240811:CLOSED;20240812:'
        '0830-20240812:1305;20240813:0830-20240813:1305;20240814:0830-'
        '20240814:1305',
    liquidHours='20240809:0830-20240809:1305;20240810:CLOSED;20240811:CLOSED;20240812:'
        '0830-20240812:1305;20240813:0830-20240813:1305;20240814:0830-'
        '20240814:1305',
    aggGroup=2147483647,
    underSymbol='LE',
    underSecType='IND',
    marketRuleIds='300,300',
    realExpirationDate='20240830',
    lastTradeTime='13:00:00',
    minSize=1.0,
    sizeIncrement=1.0,
    suggestedSizeIncrement=1.0
)
2024-08-09 09:25:33.512 | INFO     | icli.lang:run:729 - [LEQ4] Extra: icli.futsexchanges.FutureDetail(
    symbol='LE',
    exchange='CME',
    name='Live Cattle',
    size='400 pounds',
    months='GJMQVZ',
    tick=Decimal('0.025'),
    decimals=3,
    valuePerTick='$10'
)
2024-08-09 09:25:33.514 | INFO     | icli.lang:run:744 - [LEQ4] Exchange Rule Pairs:
{
    (
        ib_async.objects.PriceIncrement(lowEdge=0.0, increment=0.00025),
    ): ['CME', 'QBALGO']
}