{
 "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": [
       "<IB connected to 127.0.0.1:7497 clientId=13>"
      ]
     },
     "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
}
