{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Ordering\n", "\n", "\n", "## Warning: This notebook will place live orders\n", "\n", "Use a paper trading account (during market hours).\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=13)\n", "# util.logToConsole()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Create a contract and a market order:" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "contract = Forex('EURUSD')\n", "ib.qualifyContracts(contract)\n", "\n", "order = LimitOrder('SELL', 20000, 1.11)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "placeOrder will place the order order and return a ``Trade`` object right away (non-blocking):" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "trade = ib.placeOrder(contract, order)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "``trade`` contains the order and everything related to it, such as order status, fills and a log.\n", "It will be live updated with every status change or fill of the order." ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "scrolled": true }, "outputs": [ { "data": { "text/plain": [ "[TradeLogEntry(time=datetime.datetime(2019, 12, 31, 17, 19, 7, 96198, tzinfo=datetime.timezone.utc), status='PendingSubmit', message=''),\n", " TradeLogEntry(time=datetime.datetime(2019, 12, 31, 17, 19, 7, 283531, tzinfo=datetime.timezone.utc), status='PreSubmitted', message=''),\n", " TradeLogEntry(time=datetime.datetime(2019, 12, 31, 17, 19, 7, 323689, tzinfo=datetime.timezone.utc), status='PreSubmitted', message='Fill 20000.0@1.12245'),\n", " TradeLogEntry(time=datetime.datetime(2019, 12, 31, 17, 19, 7, 323689, tzinfo=datetime.timezone.utc), status='Filled', message='')]" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "ib.sleep(1)\n", "trade.log" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "``trade`` will also available from ``ib.trades()``:" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [], "source": [ "assert trade in ib.trades()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Likewise for ``order``:" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [], "source": [ "assert order in ib.orders()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now let's create a limit order with an unrealistic limit:" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "Trade(contract=Forex('EURUSD', conId=12087792, exchange='IDEALPRO', localSymbol='EUR.USD', tradingClass='EUR.USD'), order=LimitOrder(orderId=23, clientId=13, action='BUY', totalQuantity=20000, lmtPrice=0.05), orderStatus=OrderStatus(orderId=0, status='PendingSubmit', filled=0, remaining=0, avgFillPrice=0.0, permId=0, parentId=0, lastFillPrice=0.0, clientId=0, whyHeld='', mktCapPrice=0.0, lastLiquidity=0), fills=[], log=[TradeLogEntry(time=datetime.datetime(2019, 12, 31, 17, 19, 8, 149188, tzinfo=datetime.timezone.utc), status='PendingSubmit', message='')])" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "limitOrder = LimitOrder('BUY', 20000, 0.05)\n", "limitTrade = ib.placeOrder(contract, limitOrder)\n", "\n", "limitTrade" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "``status`` will change from \"PendingSubmit\" to \"Submitted\":" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [], "source": [ "ib.sleep(1)\n", "assert limitTrade.orderStatus.status == 'Submitted'" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [], "source": [ "assert limitTrade in ib.openTrades()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let's modify the limit price and resubmit:" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "Trade(contract=Forex('EURUSD', conId=12087792, exchange='IDEALPRO', localSymbol='EUR.USD', tradingClass='EUR.USD'), order=LimitOrder(orderId=23, clientId=13, permId=1710981560, action='BUY', totalQuantity=20000.0, lmtPrice=0.1, auxPrice=0.0, tif='DAY', ocaType=3, trailStopPrice=1.05, volatilityType=0, deltaNeutralOrderType='None', referencePriceType=0, account='DU772802', clearingIntent='IB', adjustedOrderType='None', cashQty=0.0, dontUseAutoPriceForHedge=True), orderStatus=OrderStatus(orderId=0, status='Submitted', filled=0.0, remaining=20000.0, avgFillPrice=0.0, permId=1710981560, parentId=0, lastFillPrice=0.0, clientId=13, whyHeld='', mktCapPrice=0.0, lastLiquidity=0), fills=[], log=[TradeLogEntry(time=datetime.datetime(2019, 12, 31, 17, 19, 8, 149188, tzinfo=datetime.timezone.utc), status='PendingSubmit', message=''), TradeLogEntry(time=datetime.datetime(2019, 12, 31, 17, 19, 8, 249250, tzinfo=datetime.timezone.utc), status='Submitted', message=''), TradeLogEntry(time=datetime.datetime(2019, 12, 31, 17, 19, 9, 176924, tzinfo=datetime.timezone.utc), status='Submitted', message='Modify')])" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "limitOrder.lmtPrice = 0.10\n", "\n", "ib.placeOrder(contract, limitOrder)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "And now cancel it:" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "Trade(contract=Forex('EURUSD', conId=12087792, exchange='IDEALPRO', localSymbol='EUR.USD', tradingClass='EUR.USD'), order=LimitOrder(orderId=23, clientId=13, permId=1710981560, action='BUY', totalQuantity=20000.0, lmtPrice=0.1, auxPrice=0.0, tif='DAY', ocaType=3, trailStopPrice=1.05, volatilityType=0, deltaNeutralOrderType='None', referencePriceType=0, account='DU772802', clearingIntent='IB', adjustedOrderType='None', cashQty=0.0, dontUseAutoPriceForHedge=True), orderStatus=OrderStatus(orderId=0, status='PendingCancel', filled=0.0, remaining=20000.0, avgFillPrice=0.0, permId=1710981560, parentId=0, lastFillPrice=0.0, clientId=13, whyHeld='', mktCapPrice=0.0, lastLiquidity=0), fills=[], log=[TradeLogEntry(time=datetime.datetime(2019, 12, 31, 17, 19, 8, 149188, tzinfo=datetime.timezone.utc), status='PendingSubmit', message=''), TradeLogEntry(time=datetime.datetime(2019, 12, 31, 17, 19, 8, 249250, tzinfo=datetime.timezone.utc), status='Submitted', message=''), TradeLogEntry(time=datetime.datetime(2019, 12, 31, 17, 19, 9, 176924, tzinfo=datetime.timezone.utc), status='Submitted', message='Modify'), TradeLogEntry(time=datetime.datetime(2019, 12, 31, 17, 19, 9, 183117, tzinfo=datetime.timezone.utc), status='PendingCancel', message='')])" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "ib.cancelOrder(limitOrder)" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[TradeLogEntry(time=datetime.datetime(2019, 12, 31, 17, 19, 8, 149188, tzinfo=datetime.timezone.utc), status='PendingSubmit', message=''),\n", " TradeLogEntry(time=datetime.datetime(2019, 12, 31, 17, 19, 8, 249250, tzinfo=datetime.timezone.utc), status='Submitted', message=''),\n", " TradeLogEntry(time=datetime.datetime(2019, 12, 31, 17, 19, 9, 176924, tzinfo=datetime.timezone.utc), status='Submitted', message='Modify'),\n", " TradeLogEntry(time=datetime.datetime(2019, 12, 31, 17, 19, 9, 183117, tzinfo=datetime.timezone.utc), status='PendingCancel', message='')]" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "limitTrade.log" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "placeOrder is not blocking and will not wait on what happens with the order.\n", "To make the order placement blocking, that is to wait until the order is either\n", "filled or canceled, consider the following:" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "CPU times: user 5.87 ms, sys: 486 µs, total: 6.35 ms\n", "Wall time: 163 ms\n" ] } ], "source": [ "%%time\n", "order = MarketOrder('BUY', 100)\n", "\n", "trade = ib.placeOrder(contract, order)\n", "while not trade.isDone():\n", " ib.waitOnUpdate()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "What are our positions?" ] }, { "cell_type": "code", "execution_count": 14, "metadata": { "scrolled": true }, "outputs": [ { "data": { "text/plain": [ "[Position(account='DU772802', contract=Stock(conId=9579970, symbol='IWM', exchange='ARCA', currency='USD', localSymbol='IWM', tradingClass='IWM'), position=600.0, avgCost=149.368),\n", " Position(account='DU772802', contract=Forex('USDCHF', conId=12087820, localSymbol='USD.CHF', tradingClass='USD.CHF'), position=20.0, avgCost=0.98545),\n", " Position(account='DU772802', contract=Forex('EURUSD', conId=12087792, localSymbol='EUR.USD', tradingClass='EUR.USD'), position=165700.0, avgCost=1.1247148664589277),\n", " Position(account='DU772802', contract=Stock(conId=265598, symbol='AAPL', exchange='NASDAQ', currency='USD', localSymbol='AAPL', tradingClass='NMS'), position=2551.0, avgCost=187.1202698)]" ] }, "execution_count": 14, "metadata": {}, "output_type": "execute_result" } ], "source": [ "ib.positions()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "What's the total of commissions paid today?" ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "11.607050000000001" ] }, "execution_count": 15, "metadata": {}, "output_type": "execute_result" } ], "source": [ "sum(fill.commissionReport.commission for fill in ib.fills())" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "whatIfOrder can be used to see the commission and the margin impact of an order without actually sending the order:" ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "OrderState(status='PreSubmitted', initMarginBefore='188130.0', maintMarginBefore='188130.0', equityWithLoanBefore='1126836.45', initMarginChange='0.0', maintMarginChange='0.0', equityWithLoanChange='-1.790000000037253', initMarginAfter='188130.0', maintMarginAfter='188130.0', equityWithLoanAfter='1126834.66', commission=1.7857, minCommission=1.7976931348623157e+308, maxCommission=1.7976931348623157e+308, commissionCurrency='EUR', warningText='', completedTime='', completedStatus='')" ] }, "execution_count": 16, "metadata": {}, "output_type": "execute_result" } ], "source": [ "order = MarketOrder('SELL', 20000)\n", "ib.whatIfOrder(contract, order)" ] }, { "cell_type": "code", "execution_count": 17, "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 }