{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "Option chains\n", "=======" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "scrolled": true }, "outputs": [ { "data": { "text/plain": [ "" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from ib_insync import *\n", "util.startLoop()\n", "\n", "ib = IB()\n", "ib.connect('127.0.0.1', 7497, clientId=12)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Suppose we want to find the options on the SPX, with the following conditions:\n", "\n", "* Use the next three monthly expiries;\n", "* Use strike prices within +- 20 dollar of the current SPX value;\n", "* Use strike prices that are a multitude of 5 dollar." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "To get the current market value, first create a contract for the underlyer (the S&P 500 index):" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[Index(conId=416904, symbol='SPX', exchange='CBOE', currency='USD', localSymbol='SPX')]" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "spx = Index('SPX', 'CBOE')\n", "ib.qualifyContracts(spx)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "To avoid issues with market data permissions, we'll use delayed data:" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "ib.reqMarketDataType(4)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Then get the ticker. Requesting a ticker can take up to 11 seconds." ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "Ticker(contract=Index(conId=416904, symbol='SPX', exchange='CBOE', currency='USD', localSymbol='SPX'), time=datetime.datetime(2019, 12, 31, 16, 58, 32, 252008, tzinfo=datetime.timezone.utc), last=3216.19, lastSize=0, high=3225.1, low=3212.03, close=3221.29, ticks=[TickData(time=datetime.datetime(2019, 12, 31, 16, 58, 32, 252008, tzinfo=datetime.timezone.utc), tickType=4, price=3216.19, size=0), TickData(time=datetime.datetime(2019, 12, 31, 16, 58, 32, 252008, tzinfo=datetime.timezone.utc), tickType=6, price=3225.1, size=0), TickData(time=datetime.datetime(2019, 12, 31, 16, 58, 32, 252008, tzinfo=datetime.timezone.utc), tickType=7, price=3212.03, size=0), TickData(time=datetime.datetime(2019, 12, 31, 16, 58, 32, 252008, tzinfo=datetime.timezone.utc), tickType=9, price=3221.29, size=0)])" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "[ticker] = ib.reqTickers(spx)\n", "ticker" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Take the current market value of the ticker:" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "3221.29" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "spxValue = ticker.marketPrice()\n", "spxValue" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The following request fetches a list of option chains:" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
exchangeunderlyingConIdtradingClassmultiplierexpirationsstrikes
0SMART416904SPX100[20200116, 20200220, 20200319, 20200416, 20200...[100.0, 200.0, 300.0, 400.0, 500.0, 600.0, 650...
1CBOE416904SPXW100[20191231, 20200103, 20200106, 20200108, 20200...[1000.0, 1100.0, 1150.0, 1200.0, 1225.0, 1250....
2SMART416904SPXW100[20191231, 20200103, 20200106, 20200108, 20200...[1000.0, 1100.0, 1150.0, 1200.0, 1225.0, 1250....
3CBOE416904SPX100[20200116, 20200220, 20200319, 20200416, 20200...[100.0, 200.0, 300.0, 400.0, 500.0, 600.0, 650...
\n", "
" ], "text/plain": [ " exchange underlyingConId tradingClass multiplier \\\n", "0 SMART 416904 SPX 100 \n", "1 CBOE 416904 SPXW 100 \n", "2 SMART 416904 SPXW 100 \n", "3 CBOE 416904 SPX 100 \n", "\n", " expirations \\\n", "0 [20200116, 20200220, 20200319, 20200416, 20200... \n", "1 [20191231, 20200103, 20200106, 20200108, 20200... \n", "2 [20191231, 20200103, 20200106, 20200108, 20200... \n", "3 [20200116, 20200220, 20200319, 20200416, 20200... \n", "\n", " strikes \n", "0 [100.0, 200.0, 300.0, 400.0, 500.0, 600.0, 650... \n", "1 [1000.0, 1100.0, 1150.0, 1200.0, 1225.0, 1250.... \n", "2 [1000.0, 1100.0, 1150.0, 1200.0, 1225.0, 1250.... \n", "3 [100.0, 200.0, 300.0, 400.0, 500.0, 600.0, 650... " ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "chains = ib.reqSecDefOptParams(spx.symbol, '', spx.secType, spx.conId)\n", "\n", "util.df(chains)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "These are four option chains that differ in ``exchange`` and ``tradingClass``. The latter is 'SPX' for the monthly and 'SPXW' for the weekly options. Note that the weekly expiries are disjoint from the monthly ones, so when interested in the weekly options the monthly options can be added as well.\n", "\n", "In this case we're only interested in the monthly options trading on SMART:" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "OptionChain(exchange='SMART', underlyingConId='416904', tradingClass='SPX', multiplier='100', expirations=['20200116', '20200220', '20200319', '20200416', '20200514', '20200618', '20200917', '20201015', '20201119', '20201217', '20210114', '20210318', '20210617', '20211216', '20221215'], strikes=[100.0, 200.0, 300.0, 400.0, 500.0, 600.0, 650.0, 700.0, 750.0, 800.0, 850.0, 900.0, 950.0, 1000.0, 1050.0, 1100.0, 1150.0, 1200.0, 1225.0, 1250.0, 1275.0, 1300.0, 1325.0, 1350.0, 1375.0, 1400.0, 1425.0, 1450.0, 1475.0, 1500.0, 1525.0, 1550.0, 1575.0, 1600.0, 1625.0, 1650.0, 1675.0, 1700.0, 1725.0, 1750.0, 1775.0, 1800.0, 1825.0, 1850.0, 1875.0, 1900.0, 1925.0, 1950.0, 1975.0, 2000.0, 2025.0, 2050.0, 2075.0, 2090.0, 2100.0, 2110.0, 2120.0, 2125.0, 2130.0, 2140.0, 2150.0, 2160.0, 2170.0, 2175.0, 2180.0, 2190.0, 2200.0, 2210.0, 2220.0, 2225.0, 2230.0, 2240.0, 2250.0, 2260.0, 2270.0, 2275.0, 2280.0, 2290.0, 2300.0, 2310.0, 2320.0, 2325.0, 2330.0, 2340.0, 2350.0, 2360.0, 2370.0, 2375.0, 2380.0, 2390.0, 2395.0, 2400.0, 2405.0, 2410.0, 2415.0, 2420.0, 2425.0, 2430.0, 2435.0, 2440.0, 2445.0, 2450.0, 2455.0, 2460.0, 2465.0, 2470.0, 2475.0, 2480.0, 2485.0, 2490.0, 2495.0, 2500.0, 2505.0, 2510.0, 2515.0, 2520.0, 2525.0, 2530.0, 2535.0, 2540.0, 2545.0, 2550.0, 2555.0, 2560.0, 2565.0, 2570.0, 2575.0, 2580.0, 2585.0, 2590.0, 2595.0, 2600.0, 2605.0, 2610.0, 2615.0, 2620.0, 2625.0, 2630.0, 2635.0, 2640.0, 2645.0, 2650.0, 2655.0, 2660.0, 2665.0, 2670.0, 2675.0, 2680.0, 2685.0, 2690.0, 2695.0, 2700.0, 2705.0, 2710.0, 2715.0, 2720.0, 2725.0, 2730.0, 2735.0, 2740.0, 2745.0, 2750.0, 2755.0, 2760.0, 2765.0, 2770.0, 2775.0, 2780.0, 2785.0, 2790.0, 2795.0, 2800.0, 2805.0, 2810.0, 2815.0, 2820.0, 2825.0, 2830.0, 2835.0, 2840.0, 2845.0, 2850.0, 2855.0, 2860.0, 2865.0, 2870.0, 2875.0, 2880.0, 2885.0, 2890.0, 2895.0, 2900.0, 2905.0, 2910.0, 2915.0, 2920.0, 2925.0, 2930.0, 2935.0, 2940.0, 2945.0, 2950.0, 2955.0, 2960.0, 2965.0, 2970.0, 2975.0, 2980.0, 2985.0, 2990.0, 2995.0, 3000.0, 3005.0, 3010.0, 3015.0, 3020.0, 3025.0, 3030.0, 3035.0, 3040.0, 3045.0, 3050.0, 3055.0, 3060.0, 3065.0, 3070.0, 3075.0, 3080.0, 3085.0, 3090.0, 3095.0, 3100.0, 3105.0, 3110.0, 3115.0, 3120.0, 3125.0, 3130.0, 3135.0, 3140.0, 3145.0, 3150.0, 3155.0, 3160.0, 3165.0, 3170.0, 3175.0, 3180.0, 3185.0, 3190.0, 3195.0, 3200.0, 3205.0, 3210.0, 3215.0, 3220.0, 3225.0, 3230.0, 3235.0, 3240.0, 3245.0, 3250.0, 3255.0, 3260.0, 3265.0, 3270.0, 3275.0, 3280.0, 3285.0, 3290.0, 3295.0, 3300.0, 3305.0, 3310.0, 3315.0, 3320.0, 3325.0, 3330.0, 3335.0, 3340.0, 3345.0, 3350.0, 3355.0, 3360.0, 3365.0, 3370.0, 3375.0, 3380.0, 3385.0, 3390.0, 3395.0, 3400.0, 3405.0, 3410.0, 3415.0, 3420.0, 3425.0, 3430.0, 3435.0, 3440.0, 3445.0, 3450.0, 3455.0, 3460.0, 3465.0, 3470.0, 3475.0, 3480.0, 3490.0, 3500.0, 3510.0, 3520.0, 3525.0, 3530.0, 3540.0, 3550.0, 3560.0, 3575.0, 3600.0, 3625.0, 3650.0, 3700.0, 3750.0, 3800.0, 3850.0, 3900.0, 3950.0, 4000.0, 4050.0, 4100.0, 4200.0, 4300.0, 4400.0, 4500.0, 4600.0])" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "chain = next(c for c in chains if c.tradingClass == 'SPX' and c.exchange == 'SMART')\n", "chain" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "What we have here is the full matrix of expirations x strikes. From this we can build all the option contracts that meet our conditions:" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "48" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "strikes = [strike for strike in chain.strikes\n", " if strike % 5 == 0\n", " and spxValue - 20 < strike < spxValue + 20]\n", "expirations = sorted(exp for exp in chain.expirations)[:3]\n", "rights = ['P', 'C']\n", "\n", "contracts = [Option('SPX', expiration, strike, right, 'SMART', tradingClass='SPX')\n", " for right in rights\n", " for expiration in expirations\n", " for strike in strikes]\n", "\n", "contracts = ib.qualifyContracts(*contracts)\n", "len(contracts)" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "Option(conId=384688665, symbol='SPX', lastTradeDateOrContractMonth='20200116', strike=3205.0, right='P', multiplier='100', exchange='SMART', currency='USD', localSymbol='SPX 200117P03205000', tradingClass='SPX')" ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "contracts[0]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now to get the market data for all options in one go:" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "Ticker(contract=Option(conId=384688665, symbol='SPX', lastTradeDateOrContractMonth='20200116', strike=3205.0, right='P', multiplier='100', exchange='SMART', currency='USD', localSymbol='SPX 200117P03205000', tradingClass='SPX'), time=datetime.datetime(2019, 12, 31, 16, 58, 41, 258764, tzinfo=datetime.timezone.utc), bid=28.1, bidSize=260, ask=28.5, askSize=75, last=26.2, lastSize=1, volume=17, high=29.15, low=26.2, close=26.65, bidGreeks=OptionComputation(impliedVol=0.12479434613887233, delta=-0.4467205699460659, optPrice=28.100000381469727, pvDividend=3.171605793435112, gamma=0.004541203481480199, vega=2.7584286390644355, theta=-0.9351184483257037, undPrice=3216.19), askGreeks=OptionComputation(impliedVol=0.1273924345982469, delta=-0.44758003325183715, optPrice=28.5, pvDividend=3.171605793435112, gamma=0.004449873325559049, vega=2.759225320523277, theta=-0.956080972911877, undPrice=3216.19), lastGreeks=OptionComputation(impliedVol=0.1121163044425008, delta=-0.441885782487882, optPrice=26.200000762939453, pvDividend=3.171605793435112, gamma=0.005046062232473765, vega=2.7537040141291262, theta=-0.8328175501618498, undPrice=3216.19), modelGreeks=OptionComputation(impliedVol=0.12597515955300287, delta=-0.44711612427890945, optPrice=30.020053965440823, pvDividend=3.171605793435112, gamma=0.004499237656712854, vega=2.7587969178159018, theta=-0.9446458451581966, undPrice=3216.19))" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "tickers = ib.reqTickers(*contracts)\n", "\n", "tickers[0]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The option greeks are available from the ``modelGreeks`` attribute, and if there is a bid, ask resp. last price available also from ``bidGreeks``, ``askGreeks`` and ``lastGreeks``. For streaming ticks the greek values will be kept up to date to the current market situation." ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [], "source": [ "ib.disconnect()" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.7.5" } }, "nbformat": 4, "nbformat_minor": 4 }