{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "## Building The Environment\n", "<sub>UirĂ¡ Caiado. Aug 19, 2016<sub>\n", "\n", "### My Goal, For Now" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Here I will build the environment where my agent will be trained. As it is a pretty complicated task, I created this notebook just to explore some options. Test an automated strategy is something pretty difficult, to tell the truth. There are some issues that I could talk about: historical prices are just one path from a stochastic process, the presence of the strategy on the market could change it etc.\n", "\n", "However, would be interesting if the solution explored in my capstone could capture some aspect of the real structure of the markets. So, I will build an environment that will use historical data, but I will build it in a \"agent-based model\" fashion. Probably I will not do that to this project, but this structure can be useful for some future projects that I intend to do after completing this one.\n", "\n", "I will use TAQ data from Bloomberg; It consists of 'level I' data from the PETR4 Brazilian Stock. I will explain about all these terms and data in my \"official\" project; here I just intend to share my experiments in a less formal way. Level I data is the information of the first queue of order book (bid and ask), and trades that have been made (TAQ is an acronym for Trade and Quote). It alone is not enough to create an order book, but I will try to do that. If I complete this task, I could exclude the historical data and include some random agents to build a Monte Carlo of the order book, for example. I will try to build it upon the codes for the SmartCab project. Instead of the gridlike world, my world will be discrete, but an order book." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Exploring The Data\n", "\n", "So, let's start looking at the data that I have available. It is data from the last 19 days from PETR4 stock from Brazilian BMFBovespa. I choose this share because it is on of the most active stocks in our market, but still the data produced is manageable (60 to 90 thousands of rows by day)." ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "20160725.csv:\t117,170 rows\t4.66 MB\n", "20160726.csv:\t105,898 rows\t4.20 MB\n", "20160727.csv:\t131,058 rows\t5.22 MB\n", "20160728.csv:\t117,286 rows\t4.65 MB\n", "20160729.csv:\t145,368 rows\t5.79 MB\n", "20160801.csv:\t114,815 rows\t4.57 MB\n", "20160802.csv:\t113,642 rows\t4.51 MB\n", "20160803.csv:\t142,283 rows\t5.69 MB\n", "20160804.csv:\t144,832 rows\t5.78 MB\n", "20160805.csv:\t117,901 rows\t4.70 MB\n", "20160808.csv:\t93,502 rows\t3.70 MB\n", "20160809.csv:\t86,078 rows\t3.41 MB\n", "20160810.csv:\t112,320 rows\t4.46 MB\n", "20160811.csv:\t153,925 rows\t6.16 MB\n", "20160812.csv:\t154,212 rows\t6.17 MB\n", "20160815.csv:\t114,955 rows\t4.57 MB\n", "20160816.csv:\t111,913 rows\t4.45 MB\n", "20160817.csv:\t122,047 rows\t4.86 MB\n", "20160818.csv:\t90,024 rows\t3.56 MB\n", "==========================================\n", "TOTAL\t\t19 files\t91.09 MB\n", "\t\t2,289,229 rows\n", "Wall time: 4.54 s\n" ] } ], "source": [ "import zipfile\n", "s_fname = \"data/petr4_0725_0818.zip\"\n", "archive = zipfile.ZipFile(s_fname, 'r')\n", "def foo():\n", " f_total = 0.\n", " f_tot_rows = 0.\n", " for i, x in enumerate(archive.infolist()):\n", " f_total += x.file_size/ 1024.**2\n", " for num_rows, row in enumerate(archive.open(x)):\n", " f_tot_rows += 1\n", " print \"{}:\\t{:,.0f} rows\\t{:0.2f} MB\".format(x.filename, num_rows + 1, x.file_size/ 1024.**2)\n", " print '=' * 42\n", " print \"TOTAL\\t\\t{} files\\t{:0.2f} MB\".format(i+1,f_total)\n", " print \"\\t\\t{:0,.0f} rows\".format(f_tot_rows)\n", "\n", "%time foo()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Ok, all files together have 91 MB. It is not too much actually. Maybe I could try to get more data later. Well, let's read one of them." ] }, { "cell_type": "code", "execution_count": 63, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "<div>\n", "<table border=\"1\" class=\"dataframe\">\n", " <thead>\n", " <tr style=\"text-align: right;\">\n", " <th></th>\n", " <th>Date</th>\n", " <th>Type</th>\n", " <th>Price</th>\n", " <th>Size</th>\n", " </tr>\n", " </thead>\n", " <tbody>\n", " <tr>\n", " <th>0</th>\n", " <td>2016-08-18 10:09:09</td>\n", " <td>TRADE</td>\n", " <td>12.80</td>\n", " <td>1000</td>\n", " </tr>\n", " <tr>\n", " <th>1</th>\n", " <td>2016-08-18 10:09:09</td>\n", " <td>BID</td>\n", " <td>12.80</td>\n", " <td>15900</td>\n", " </tr>\n", " <tr>\n", " <th>2</th>\n", " <td>2016-08-18 10:09:09</td>\n", " <td>ASK</td>\n", " <td>12.81</td>\n", " <td>2900</td>\n", " </tr>\n", " <tr>\n", " <th>3</th>\n", " <td>2016-08-18 10:09:09</td>\n", " <td>ASK</td>\n", " <td>12.81</td>\n", " <td>7900</td>\n", " </tr>\n", " <tr>\n", " <th>4</th>\n", " <td>2016-08-18 10:09:09</td>\n", " <td>BID</td>\n", " <td>12.80</td>\n", " <td>20900</td>\n", " </tr>\n", " </tbody>\n", "</table>\n", "</div>" ], "text/plain": [ " Date Type Price Size\n", "0 2016-08-18 10:09:09 TRADE 12.80 1000\n", "1 2016-08-18 10:09:09 BID 12.80 15900\n", "2 2016-08-18 10:09:09 ASK 12.81 2900\n", "3 2016-08-18 10:09:09 ASK 12.81 7900\n", "4 2016-08-18 10:09:09 BID 12.80 20900" ] }, "execution_count": 63, "metadata": {}, "output_type": "execute_result" } ], "source": [ "import pandas as pd\n", "df = pd.read_csv(archive.open(x), index_col=0, parse_dates=['Date'])\n", "df.head()" ] }, { "cell_type": "code", "execution_count": 64, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "08/18/2016\n", "Type\n", "ASK 32843\n", "BID 32116\n", "TRADE 25064\n", "Name: Date, dtype: int64\n" ] } ], "source": [ "print \"{:%m/%d/%Y}\".format(df.Date[0])\n", "print df.groupby('Type').count()['Date']" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "As it is a \"Trade And quotes\" file, I was already expecting that there was the same number os Bid and Ask rows in the file. Well... it wasn't a problem to read this file. Well, I will read this file row by row now and include the prices in a binomial tree (the structure I intend to use to keep the order book). Let's see how long it takes." ] }, { "cell_type": "code", "execution_count": 65, "metadata": { "collapsed": true }, "outputs": [], "source": [ "from bintrees import FastRBTree" ] }, { "cell_type": "code", "execution_count": 77, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "time to iterate the rows:\n", "CPU times: user 9.15 s, sys: 114 ms, total: 9.27 s\n", "Wall time: 9.22 s\n" ] } ], "source": [ "def foo():\n", " for idx, row in df.iterrows():\n", " pass\n", "\n", "print \"time to iterate the rows:\"\n", "%time foo()" ] }, { "cell_type": "code", "execution_count": 78, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "time to insert everything in binary trees:\n", "CPU times: user 15.6 s, sys: 317 ms, total: 15.9 s\n", "Wall time: 15.8 s\n" ] } ], "source": [ "def foo():\n", " bid_tree = FastRBTree()\n", " ask_tree = FastRBTree()\n", " for idx, row in df.iterrows():\n", " if row.Type == 'BID':\n", " bid_tree.insert(row['Price'], row['Size'])\n", " elif row.Type == 'ASK':\n", " ask_tree.insert(row['Price'], row['Size'])\n", "\n", "print \"time to insert everything in binary trees:\"\n", "%time foo()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "It is not excelent, but it is ok for now. I will see how bad it will be when I include all the logic needed. Now, let's visualize the prices on that day" ] }, { "cell_type": "code", "execution_count": 85, "metadata": { "collapsed": false }, "outputs": [ { "data": { "image/png": "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\nLYQQQti4/wKEqR2IkFlwXgAAAABJRU5ErkJggg==\n", "text/plain": [ "<matplotlib.figure.Figure at 0x11ae00890>" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "df_aux = df[df.Type == 'TRADE'].Price\n", "df_aux.index = df[df.Type == 'TRADE'].Date\n", "ax = df_aux.plot()\n", "ax.set_title(\"Price fluctuation of PETR4\\n\");" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Know what, let's visualize the prices of all days. I will plot the cumulated returns of this series" ] }, { "cell_type": "code", "execution_count": 27, "metadata": { "collapsed": false }, "outputs": [], "source": [ "import pandas as pd\n", "\n", "df_all = None\n", "\n", "for i, x in enumerate(archive.infolist()):\n", " df = pd.read_csv(archive.open(x), index_col=0, parse_dates=['Date'])\n", " ts_date = df.Date[0].date()\n", " df.Date = [\"{:%H:%M:%S}\".format(x) for x in df.Date]\n", " df = df[df.Type == \"TRADE\"]\n", " df = pd.DataFrame(df.groupby('Date').last()['Price'])\n", " if i == 0:\n", " df_all = df.copy()\n", " df_all.columns = [ts_date] \n", " else:\n", " df_aux = df.copy()\n", " df_aux.columns = [ts_date]\n", " df_all = df_all.join(df_aux)\n", "df_all.index = pd.to_datetime(df_all.index)\n", "df_all = df_all.fillna(method='ffill')\n", "df_all = df_all.dropna()" ] }, { "cell_type": "code", "execution_count": 61, "metadata": { "collapsed": false }, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "<matplotlib.figure.Figure at 0x7f5c08128e50>" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "import numpy as np\n", "df_logrtn = np.log(df_all/df_all.shift())\n", "df_logrtn = df_logrtn[[(x.hour*60 + x.minute) < (16*60 + 55) for x in df_logrtn.index]]\n", "ax = df_logrtn.cumsum().plot(legend=False)\n", "ax.set_title('Cumulative Log-Returns of PETR4 in 19 different days\\n', fontsize=16)\n", "ax.set_ylabel('Return');" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Interesting, isn't it?! It looks like the output of a Monte Carlo simulation. Well, the simulator that I will build should produce exactly this output." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Pre-processing The Data\n", "\n", "There is a problem using this data to do a simulation: the order of events. As there is just the first line of the order book, when happened a trade that filled more than an price level at once, I won't have the order in the second price level in my structure to be filled. So, I need to create it beforehand. To do so, I need to preprocess the dataset, so I can include this event. What I will do is sum up the trades that happend in sequence and include a new rows between the sequences to preper the dataset.\n" ] }, { "cell_type": "code", "execution_count": 104, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "run in 46.55 seconds\n" ] } ], "source": [ "import qtrader.preprocess as preprocess\n", "s_fname = \"data/petr4_0725_0818.zip\"\n", "preprocess.make_zip_file(s_fname)" ] }, { "cell_type": "markdown", "metadata": { "collapsed": true }, "source": [ "Now, let's check if I keep the same traded quantity in all files" ] }, { "cell_type": "code", "execution_count": 28, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "19 files has the same number of trades\n", "0 files has DIFFERENT number of trades\n" ] } ], "source": [ "import zipfile\n", "import pandas as pd\n", "s_fname = \"data/petr4_0725_0818.zip\"\n", "archive = zipfile.ZipFile(s_fname, 'r')\n", "\n", "\n", "f_total = 0.\n", "i_same = 0\n", "i_different = 0\n", "for i, x in enumerate(archive.infolist()):\n", " s_fname = 'data/petr4_0725_0818_2/' + x.filename\n", " df = pd.read_csv(archive.open(x), index_col=0, parse_dates=['Date'])\n", " df2 = pd.read_csv(s_fname, index_col=0, parse_dates=['Date'])\n", " f_all = (df.ix[df.Type=='TRADE', 'Price'] * df.ix[df.Type=='TRADE', 'Size']).sum()\n", " f_all2 = (df2.ix[df2.Type=='TRADE', 'Price'] * df2.ix[df2.Type=='TRADE', 'Size']).sum()\n", " if f_all == f_all2:\n", " i_same += 1\n", " else:\n", " i_different += 1\n", "\n", "print \"{} files has the same number of trades\".format(i_same)\n", "print \"{} files has DIFFERENT number of trades\".format(i_different)\n", " " ] }, { "cell_type": "markdown", "metadata": { "collapsed": true }, "source": [ "Nice. I am going to use this files in the next steps." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Building an Order book\n", "\n", "I imagine a structure where my environment is an order book that operates in discrete time steps. At each time step, it allows randomly the agents (at each step) to take new actions. Then, the Environment updates the order book according to these messages.\n", "\n", "At the beginning of each time step, all agent see the same state of the order book. Some of them will try to execute orders at the same price, for example, and the environment will accept just this kind of message while there are orders to be filled at that particular price. After that, It should distribute all the new states to the agents.\n", "\n", "It also should keep the prices organized and, inside each price, should follow the orders arranged by \"arrival time\". Always that an agent grow his quantity of an existing order, it should be moved to the end of the queue on that price. The message that the agent should send to the environment should be something like that\n", "\n", "```\n", "{'instrumento_symbol': 'PETR4',\n", " 'agent_id': 10,\n", " 'order_entry_step': 15,\n", " 'order_status': 'New'\n", " 'last_order_id': 11,\n", " 'order_id': 11,\n", " 'order_side': 'BID',\n", " 'agressor_indicator': 'Neutral',\n", " 'order_price': 12.11,\n", " 'total_qty_order': 100,\n", " 'traded_qty_order': 0}\n", " ```\n", " \n", "The limit order book will be ordered first by price and then by arrival. So, my first class should be the order itself. The second class should be the price level (that is a group of orders). The third one, the side of the book (a collection of Price Levels). Finally, the order book (the bid and ask side). So, now I need to create all the structure that handle these interations. If should receive an order and answer to the environment if it was acepted , the new ID, and, if there was a trade, the informations about the trade so the environment can update the state of the agents. I need a list of prices and another of orders. Oh... and a list of agents that have a list of their current orders on the market, but it is something handle by the environment. So, let's do that. First, let's implement the order structure." ] }, { "cell_type": "code", "execution_count": 13, "metadata": { "collapsed": false }, "outputs": [], "source": [ "# example of message\n", "d_msg = {'instrumento_symbol': 'PETR4',\n", " 'agent_id': 10,\n", " 'order_entry_step': 15,\n", " 'order_status': 'New',\n", " 'last_order_id': 0,\n", " 'order_id': 0,\n", " 'order_side': 'BID',\n", " 'order_price': 12.11,\n", " 'total_qty_order': 100,\n", " 'traded_qty_order': 0}" ] }, { "cell_type": "code", "execution_count": 90, "metadata": { "collapsed": true }, "outputs": [], "source": [ "class Order(object):\n", " '''\n", " A representation of a single Order\n", " '''\n", " def __init__(self, d_msg):\n", " '''\n", " Instantiate a Order object. Save all parameter as attributes\n", " :param d_msg: dictionary.\n", " '''\n", " # keep data extract from file\n", " self.d_msg = d_msg.copy()\n", " self.d_msg['org_total_qty_order'] = self.d_msg['total_qty_order']\n", " f_q1 = self.d_msg['total_qty_order']\n", " f_q2 = self.d_msg['traded_qty_order']\n", " self.d_msg['total_qty_order'] = f_q1 - f_q2\n", " self.order_id = d_msg['order_id']\n", " self.last_order_id = d_msg['last_order_id']\n", " self.name = \"{:07d}\".format(d_msg['order_id'])\n", " self.main_id = self.order_id\n", "\n", " def __str__(self):\n", " '''\n", " Return the name of the Order\n", " '''\n", " return self.name\n", "\n", " def __repr__(self):\n", " '''\n", " Return the name of the Order\n", " '''\n", " return self.name\n", "\n", " def __eq__(self, other):\n", " '''\n", " Return if a Order has equal order_id from the other\n", " :param other: Order object. Order to be compared\n", " '''\n", " return self.order_id == other.order_id\n", "\n", " def __ne__(self, other):\n", " '''\n", " Return if a Order has different order_id from the other\n", " :param other: Order object. Order to be compared\n", " '''\n", " return not self.__eq__(other)\n", "\n", " def __hash__(self):\n", " '''\n", " Allow the Order object be used as a key in a hash table. It is used by\n", " dictionaries\n", " '''\n", " return self.order_id.__hash__()\n", "\n", " def __getitem__(self, s_key):\n", " '''\n", " Allow direct access to the inner dictionary of the object\n", " :param i_index: integer. index of the l_legs attribute list\n", " '''\n", " return self.d_msg[s_key]" ] }, { "cell_type": "code", "execution_count": 91, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "My id is 0 and the price is 12.11\n", "The string representation of the order is 0000000\n" ] } ], "source": [ "my_order = Order(d_msg)\n", "print \"My id is {} and the price is {:0.2f}\".format(my_order['order_id'], my_order['order_price'])\n", "print \"The string representation of the order is {}\".format(my_order)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "If the ID is zero, I will consider as the new order. Well... now I need to organize orders at the same price by arrival time and update its IDs. Also, if an existing order increases the quantity, should have been marked with a new ID. If the quantity decreases, it should keep the same place on the queue. So, the price level need to know what is the last general ID used by the Order Book:" ] }, { "cell_type": "code", "execution_count": 94, "metadata": { "collapsed": true }, "outputs": [], "source": [ "from bintrees import FastRBTree\n", "\n", "class PriceLevel(object):\n", " '''\n", " A representation of a Price level in the book\n", " '''\n", " def __init__(self, f_price):\n", " '''\n", " A representation of a PriceLevel object\n", " '''\n", " self.f_price = f_price\n", " self.i_qty = 0\n", " self.order_tree = FastRBTree()\n", "\n", " def add(self, order_aux):\n", " '''\n", " Insert the information in the tree using the info in order_aux. Return\n", " is should delete the Price level or not\n", " :param order_aux: Order Object. The Order message to be updated\n", " '''\n", " # check if the order_aux price is the same of the self\n", " if order_aux['order_price'] != self.f_price:\n", " raise DifferentPriceException\n", " elif order_aux['order_status'] == 'limit':\n", " self.order_tree.insert(order_aux.main_id, order_aux)\n", " self.i_qty += int(order_aux['total_qty_order'])\n", " # check if there is no object in the updated tree (should be deleted)\n", " return self.order_tree.count == 0\n", "\n", " def delete(self, i_last_id, i_old_qty):\n", " '''\n", " Delete the information in the tree using the info in order_aux. Return\n", " is should delete the Price level or not\n", " :param i_last_id: Integer. The previous secondary order id\n", " :param i_old_qty: Integer. The previous order qty\n", " '''\n", " # check if the order_aux price is the same of the self\n", " try:\n", " self.order_tree.remove(i_last_id)\n", " self.i_qty -= i_old_qty\n", " except KeyError:\n", " raise DifferentPriceException\n", " # check if there is no object in the updated tree (should be deleted)\n", " return self.order_tree.count == 0\n", "\n", " def __str__(self):\n", " '''\n", " Return the name of the PriceLevel\n", " '''\n", " return '{:,.0f}'.format(self.i_qty)\n", "\n", " def __repr__(self):\n", " '''\n", " Return the name of the PriceLevel\n", " '''\n", " return '{:,.0f}'.format(self.i_qty)\n", "\n", " def __eq__(self, other):\n", " '''\n", " Return if a PriceLevel has equal price from the other\n", " :param other: PriceLevel object. PriceLevel to be compared\n", " '''\n", " # just to make sure that there is no floating point discrepance\n", " f_aux = other\n", " if not isinstance(other, float):\n", " f_aux = other.f_price\n", " return abs(self.f_price - f_aux) < 1e-4\n", "\n", " def __gt__(self, other):\n", " '''\n", " Return if a PriceLevel has a gerater price from the other.\n", " Bintrees uses that to compare nodes\n", " :param other: PriceLevel object. PriceLevel to be compared\n", " '''\n", " # just to make sure that there is no floating point discrepance\n", " f_aux = other\n", " if not isinstance(other, float):\n", " f_aux = other.f_price\n", " return (f_aux - self.f_price) > 1e-4\n", "\n", " def __lt__(self, other):\n", " '''\n", " Return if a Order has smaller order_id from the other. Bintrees uses\n", " that to compare nodes\n", " :param other: Order object. Order to be compared\n", " '''\n", " f_aux = other\n", " if not isinstance(other, float):\n", " f_aux = other.f_price\n", " return (f_aux - self.f_price) < -1e-4\n", "\n", " def __ne__(self, other):\n", " '''\n", " Return if a Order has different order_id from the other\n", " :param other: Order object. Order to be compared\n", " '''\n", " return not self.__eq__(other)\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [ "my_order = Order(d_msg)" ] }, { "cell_type": "code", "execution_count": 97, "metadata": { "collapsed": false }, "outputs": [], "source": [ "# create different orders at the same price\n", "d_msg1 = d_msg.copy()\n", "d_msg1['order_id'] = 1\n", "order1 = Order(d_msg1)\n", "d_msg2 = d_msg.copy()\n", "d_msg2['order_id'] = 2\n", "order2 = Order(d_msg2)\n", "d_msg3 = d_msg.copy()\n", "d_msg3['order_id'] = 3\n", "order3 = Order(d_msg3)" ] }, { "cell_type": "code", "execution_count": 111, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "False" ] }, "execution_count": 111, "metadata": {}, "output_type": "execute_result" } ], "source": [ "my_price = PriceLevel(d_msg['order_price'])\n", "my_price.add(order1)\n", "my_price.add(order2)\n", "my_price.add(order3)" ] }, { "cell_type": "code", "execution_count": 112, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "There is 300 shares at 12.11\n", "the orders in the book are: {1: 0000001, 2: 0000002, 3: 0000003}\n" ] } ], "source": [ "print \"There is {} shares at {:.2f}\".format(my_price, my_price.f_price)\n", "print 'the orders in the book are: {}'.format(dict(my_price.order_tree))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Ok. Now, let's delete two of them" ] }, { "cell_type": "code", "execution_count": 113, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "There is 100 shares at 12.11\n", "the orders in the book are: {3: 0000003}\n" ] } ], "source": [ "my_price.delete(1, 100)\n", "my_price.delete(2, 100)\n", "print \"There is {} shares at {:.2f}\".format(my_price, my_price.f_price)\n", "print 'the orders in the book are: {}'.format(dict(my_price.order_tree))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "I will let to the Environment handle the IDs, so the order book just need to keep the data ordered. Now, I am going to implement the Book side (a collection of Price levels) and the Limit Order Book (a collection of BookSide). You can see the final implementation on the file `book.py`." ] }, { "cell_type": "code", "execution_count": 22, "metadata": { "collapsed": false }, "outputs": [], "source": [ "import qtrader.book as book; reload(book);" ] }, { "cell_type": "code", "execution_count": 23, "metadata": { "collapsed": false }, "outputs": [], "source": [ "my_book = book.LimitOrderBook('PETR4')" ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "collapsed": false }, "outputs": [], "source": [ "d_msg0 = {'agent_id': 10,\n", " 'instrumento_symbol': 'PETR4',\n", " 'last_order_id': 0,\n", " 'order_entry_step': 15,\n", " 'order_id': 0,\n", " 'order_price': 12.12,\n", " 'order_side': 'ASK',\n", " 'order_status': 'New',\n", " 'total_qty_order': 400,\n", " 'traded_qty_order': 0,\n", " 'agressor_indicator': 'Neutral'}\n", "\n", "\n", "d_msg1 = {'agent_id': 10,\n", " 'instrumento_symbol': 'PETR4',\n", " 'last_order_id': 0,\n", " 'order_entry_step': 15,\n", " 'order_id': 1,\n", " 'order_price': 12.11,\n", " 'order_side': 'BID',\n", " 'order_status': 'New',\n", " 'total_qty_order': 100,\n", " 'traded_qty_order': 0,\n", " 'agressor_indicator': 'Neutral'}\n", "\n", "d_msg2 = {'agent_id': 10,\n", " 'instrumento_symbol': 'PETR4',\n", " 'last_order_id': 0,\n", " 'order_entry_step': 15,\n", " 'order_id': 2,\n", " 'order_price': 12.11,\n", " 'order_side': 'BID',\n", " 'order_status': 'New',\n", " 'total_qty_order': 100,\n", " 'traded_qty_order': 0,\n", " 'agressor_indicator': 'Neutral'}\n", "\n", "d_msg3 = {'agent_id': 10,\n", " 'instrumento_symbol': 'PETR4',\n", " 'last_order_id': 0,\n", " 'order_entry_step': 15,\n", " 'order_id': 3,\n", " 'order_price': 12.10,\n", " 'order_side': 'BID',\n", " 'order_status': 'New',\n", " 'total_qty_order': 200,\n", " 'traded_qty_order': 0,\n", " 'agressor_indicator': 'Neutral'}\n", "\n", "d_msg4 = {'agent_id': 10,\n", " 'instrumento_symbol': 'PETR4',\n", " 'last_order_id': 0,\n", " 'order_entry_step': 15,\n", " 'order_id': 4,\n", " 'order_price': 12.10,\n", " 'order_side': 'BID',\n", " 'order_status': 'New',\n", " 'total_qty_order': 100,\n", " 'traded_qty_order': 0,\n", " 'agressor_indicator': 'Neutral'}\n", "\n", "d_msg5 = {'agent_id': 10,\n", " 'instrumento_symbol': 'PETR4',\n", " 'last_order_id': 0,\n", " 'order_entry_step': 15,\n", " 'order_id': 3,\n", " 'order_price': 12.10,\n", " 'order_side': 'BID',\n", " 'order_status': 'Replaced',\n", " 'total_qty_order': 100,\n", " 'traded_qty_order': 0,\n", " 'agressor_indicator': 'Neutral'}\n", "\n", "d_msg6 = {'agent_id': 10,\n", " 'instrumento_symbol': 'PETR4',\n", " 'last_order_id': 0,\n", " 'order_entry_step': 15,\n", " 'order_id': 1,\n", " 'order_price': 12.11,\n", " 'order_side': 'BID',\n", " 'order_status': 'Filled',\n", " 'total_qty_order': 100,\n", " 'traded_qty_order': 0,\n", " 'agressor_indicator': 'Passive'}" ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "<div>\n", "<table border=\"1\" class=\"dataframe\">\n", " <thead>\n", " <tr style=\"text-align: right;\">\n", " <th></th>\n", " <th>qBid</th>\n", " <th>Bid</th>\n", " <th>Ask</th>\n", " <th>qAsk</th>\n", " </tr>\n", " </thead>\n", " <tbody>\n", " <tr>\n", " <th>0</th>\n", " <td>200</td>\n", " <td>12.11</td>\n", " <td>12.12</td>\n", " <td>400</td>\n", " </tr>\n", " <tr>\n", " <th>1</th>\n", " <td>300</td>\n", " <td>12.10</td>\n", " <td>NaN</td>\n", " <td>NaN</td>\n", " </tr>\n", " </tbody>\n", "</table>\n", "</div>" ], "text/plain": [ " qBid Bid Ask qAsk\n", "0 200 12.11 12.12 400\n", "1 300 12.10 NaN NaN" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# include several orders\n", "my_book.update(d_msg0)\n", "my_book.update(d_msg1)\n", "my_book.update(d_msg2)\n", "my_book.update(d_msg3)\n", "my_book.update(d_msg4)\n", "my_book.get_n_top_prices(5)" ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "<div>\n", "<table border=\"1\" class=\"dataframe\">\n", " <thead>\n", " <tr style=\"text-align: right;\">\n", " <th></th>\n", " <th>qBid</th>\n", " <th>Bid</th>\n", " <th>Ask</th>\n", " <th>qAsk</th>\n", " </tr>\n", " </thead>\n", " <tbody>\n", " <tr>\n", " <th>0</th>\n", " <td>200</td>\n", " <td>12.11</td>\n", " <td>12.12</td>\n", " <td>400</td>\n", " </tr>\n", " <tr>\n", " <th>1</th>\n", " <td>200</td>\n", " <td>12.10</td>\n", " <td>NaN</td>\n", " <td>NaN</td>\n", " </tr>\n", " </tbody>\n", "</table>\n", "</div>" ], "text/plain": [ " qBid Bid Ask qAsk\n", "0 200 12.11 12.12 400\n", "1 200 12.10 NaN NaN" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# test cancelation\n", "my_book.update(d_msg5)\n", "my_book.get_n_top_prices(5)" ] }, { "cell_type": "code", "execution_count": 8, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "FastRBTree({3: 0000003, 4: 0000004})" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# checking if the order of Ids are OK\n", "x = my_book.book_bid.price_tree.get(12.10)\n", "x.order_tree" ] }, { "cell_type": "code", "execution_count": 9, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "<div>\n", "<table border=\"1\" class=\"dataframe\">\n", " <thead>\n", " <tr style=\"text-align: right;\">\n", " <th></th>\n", " <th>qBid</th>\n", " <th>Bid</th>\n", " <th>Ask</th>\n", " <th>qAsk</th>\n", " </tr>\n", " </thead>\n", " <tbody>\n", " <tr>\n", " <th>0</th>\n", " <td>100</td>\n", " <td>12.11</td>\n", " <td>12.12</td>\n", " <td>400</td>\n", " </tr>\n", " <tr>\n", " <th>1</th>\n", " <td>200</td>\n", " <td>12.10</td>\n", " <td>NaN</td>\n", " <td>NaN</td>\n", " </tr>\n", " </tbody>\n", "</table>\n", "</div>" ], "text/plain": [ " qBid Bid Ask qAsk\n", "0 100 12.11 12.12 400\n", "1 200 12.10 NaN NaN" ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# test a trade\n", "my_book.update(d_msg6)\n", "my_book.get_n_top_prices(5)" ] }, { "cell_type": "code", "execution_count": 10, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "{'n_order_ask': 1, 'n_order_bid': 3, 'n_price_ask': 1, 'n_price_bid': 2}" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "my_book.get_basic_stats()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Ok, everything looks right. Let's play with some real data now." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Create the Planner\n", "\n", "I want to build a structure that I could simulate with any kind of data: real data, \"semi-real\" data and artificial data. Using artificial data, I could allow the agent change the environment. The other two option, I would just replay the market. The first one, I would need \"level II\" data, that is not easily acquired, and it is harder to handle. The second one, I would use just \"level I\" data, which some vendors provide, like Bloomberg. However, there are just the grouped data of the best- bid and offer.\n", "\n", "For now, what I need is a framework to interact with the book and a planner (maybe). This planner won't do anything if we are using the artificial market, just return the actions of each agent. If it is historical data, It should take the data and translate to the Environment as actions of each agent. So, my environment could update the order book using just the messages dicionaries and update each agent if that message was acepted or not. I guess that the role of the Environment should be update each agent with informations that them could use to build their states and rewards. The planner should handle the \"macro-behaviour\" of each agent (like, know something about the true price, etc).\n", "\n", "So, let's come back to the data that was explored at the begining of this notebook. the first thing that I should do is to do a basic reshape on the data to make it work with my book." ] }, { "cell_type": "code", "execution_count": 8, "metadata": { "collapsed": false }, "outputs": [], "source": [ "import zipfile\n", "s_fname = \"data/petr4_0725_0818.zip\"\n", "archive = zipfile.ZipFile(s_fname, 'r')\n", "\n", "f_total = 0.\n", "for i, x in enumerate(archive.infolist()):\n", " f_total += x.file_size/ 1024.**2\n", " for num_rows, row in enumerate(archive.open(x)):\n", " pass" ] }, { "cell_type": "code", "execution_count": 9, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "<div>\n", "<table border=\"1\" class=\"dataframe\">\n", " <thead>\n", " <tr style=\"text-align: right;\">\n", " <th></th>\n", " <th>Date</th>\n", " <th>Type</th>\n", " <th>Price</th>\n", " <th>Size</th>\n", " </tr>\n", " </thead>\n", " <tbody>\n", " <tr>\n", " <th>0</th>\n", " <td>2016-08-18 10:09:09</td>\n", " <td>TRADE</td>\n", " <td>12.80</td>\n", " <td>1000</td>\n", " </tr>\n", " <tr>\n", " <th>1</th>\n", " <td>2016-08-18 10:09:09</td>\n", " <td>BID</td>\n", " <td>12.80</td>\n", " <td>15900</td>\n", " </tr>\n", " <tr>\n", " <th>2</th>\n", " <td>2016-08-18 10:09:09</td>\n", " <td>ASK</td>\n", " <td>12.81</td>\n", " <td>2900</td>\n", " </tr>\n", " <tr>\n", " <th>3</th>\n", " <td>2016-08-18 10:09:09</td>\n", " <td>ASK</td>\n", " <td>12.81</td>\n", " <td>7900</td>\n", " </tr>\n", " <tr>\n", " <th>4</th>\n", " <td>2016-08-18 10:09:09</td>\n", " <td>BID</td>\n", " <td>12.80</td>\n", " <td>20900</td>\n", " </tr>\n", " </tbody>\n", "</table>\n", "</div>" ], "text/plain": [ " Date Type Price Size\n", "0 2016-08-18 10:09:09 TRADE 12.80 1000\n", "1 2016-08-18 10:09:09 BID 12.80 15900\n", "2 2016-08-18 10:09:09 ASK 12.81 2900\n", "3 2016-08-18 10:09:09 ASK 12.81 7900\n", "4 2016-08-18 10:09:09 BID 12.80 20900" ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "import pandas as pd\n", "df = pd.read_csv(archive.open(x), index_col=0, parse_dates=['Date'])\n", "df.head(5)" ] }, { "cell_type": "markdown", "metadata": { "collapsed": true }, "source": [ "Something that I need to take into account is that the book didn't start before the first BID or ASK, that both are related to the aggregated best bid and ask, and TRADE can be an aggression on either side. As I want to make a book with multiple queues, I will keep the orders on the book and just modify it when the price returns to that level. So, before decrease the BID or increase the ASK, I should check if I have an order for that price and modify it before cancel the better price. Also, I know that the TRADE flag can be a cross order, something that I don't want to account for. I also want to keep track of the changes on the best queue of the order book and the trades separated." ] }, { "cell_type": "code", "execution_count": 9, "metadata": { "collapsed": false }, "outputs": [], "source": [ "def translate_row(idx, row, i_order_id):\n", " '''\n", " '''\n", " if row.Type != 'TRADE' and row['Size'] > 100:\n", " d_rtn = {'agent_id': 10,\n", " 'instrumento_symbol': 'PETR4',\n", " 'new_order_id': i_order_id + 1,\n", " 'order_entry_step': idx,\n", " 'order_id': i_order_id + 1,\n", " 'order_price': row['Price'],\n", " 'order_side': row.Type,\n", " 'order_status': 'New',\n", " 'total_qty_order': row['Size'],\n", " 'traded_qty_order': 0,\n", " 'agressor_indicator': 'Neutral'}\n", " return i_order_id + 1, d_rtn" ] }, { "cell_type": "code", "execution_count": 10, "metadata": { "collapsed": false }, "outputs": [], "source": [ "# test the structure\n", "import qtrader.book as book; reload(book);\n", "my_book = book.LimitOrderBook('PETR4')\n", "for idx, row in df.iterrows():\n", " i_id = my_book.i_last_order_id\n", " t_rtn = translate_row(idx, row, i_id)\n", " if t_rtn:\n", " my_book.i_last_order_id = t_rtn[0]\n", " my_book.update(t_rtn[1])\n", " if idx == 1000:\n", " break" ] }, { "cell_type": "code", "execution_count": 11, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "<div>\n", "<table border=\"1\" class=\"dataframe\">\n", " <thead>\n", " <tr style=\"text-align: right;\">\n", " <th></th>\n", " <th>qBid</th>\n", " <th>Bid</th>\n", " <th>Ask</th>\n", " <th>qAsk</th>\n", " </tr>\n", " </thead>\n", " <tbody>\n", " <tr>\n", " <th>0</th>\n", " <td>1,200</td>\n", " <td>12.88</td>\n", " <td>12.80</td>\n", " <td>2,000</td>\n", " </tr>\n", " <tr>\n", " <th>1</th>\n", " <td>2,625,400</td>\n", " <td>12.87</td>\n", " <td>12.81</td>\n", " <td>144,800</td>\n", " </tr>\n", " <tr>\n", " <th>2</th>\n", " <td>1,712,600</td>\n", " <td>12.86</td>\n", " <td>12.82</td>\n", " <td>281,100</td>\n", " </tr>\n", " <tr>\n", " <th>3</th>\n", " <td>1,957,300</td>\n", " <td>12.85</td>\n", " <td>12.83</td>\n", " <td>1,169,900</td>\n", " </tr>\n", " <tr>\n", " <th>4</th>\n", " <td>94,600</td>\n", " <td>12.84</td>\n", " <td>12.84</td>\n", " <td>396,200</td>\n", " </tr>\n", " </tbody>\n", "</table>\n", "</div>" ], "text/plain": [ " qBid Bid Ask qAsk\n", "0 1,200 12.88 12.80 2,000\n", "1 2,625,400 12.87 12.81 144,800\n", "2 1,712,600 12.86 12.82 281,100\n", "3 1,957,300 12.85 12.83 1,169,900\n", "4 94,600 12.84 12.84 396,200" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "my_book.get_n_top_prices(5)" ] }, { "cell_type": "code", "execution_count": 12, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "{'n_order_ask': 295, 'n_order_bid': 290, 'n_price_ask': 10, 'n_price_bid': 10}" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "my_book.get_basic_stats()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Well... I would say that I need to handle better this orders. I need to cancel them to the bid and don't cross each other. So... Also, note the quantity on each price. It is not feasable. I need that the function knows the book. Let's see." ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "collapsed": true }, "outputs": [], "source": [ "def translate_row(idx, row, my_book):\n", " '''\n", " '''\n", " l_msg = []\n", " if row.Type != 'TRADE' and row['Size'] % 100 == 0:\n", " # recover the best price\n", " f_best_price = my_book.get_best_price(row.Type)\n", " i_order_id = my_book.i_last_order_id + 1\n", " # check if there is orders in the row price\n", " obj_ordtree = my_book.get_orders_by_price(row.Type, row['Price'])\n", " if obj_ordtree:\n", " # cant present more than 2 orders (mine and market)\n", " assert len(obj_ordtree) <= 2, 'More than two offers'\n", " # get the first order\n", " obj_order = obj_ordtree.nsmallest(1)[0][1]\n", " # check if should cancel the best price\n", " b_cancel = False\n", " if row.Type == 'BID' and row['Price'] < f_best_price:\n", " # check if the price in the row in smaller\n", " obj_ordtree2 = my_book.get_orders_by_price(row.Type)\n", " best_order = obj_ordtree2.nsmallest(1)[0][1]\n", " d_rtn = best_order.d_msg\n", " d_rtn['order_status'] = 'Canceled'\n", " l_msg.append(d_rtn.copy())\n", " elif row.Type == 'ASK' and row['Price'] > f_best_price:\n", " obj_ordtree2 = my_book.get_orders_by_price(row.Type)\n", " best_order = obj_ordtree2.nsmallest(1)[0][1]\n", " d_rtn = best_order.d_msg\n", " d_rtn['order_status'] = 'Canceled'\n", " l_msg.append(d_rtn.copy())\n", "\n", " \n", " \n", " # replace the current order\n", " i_old_id = obj_order.main_id\n", " i_new_id = obj_order.main_id\n", " if row['Size'] > obj_order['total_qty_order']:\n", " i_new_id = my_book.i_last_order_id + 1\n", " d_rtn = obj_order.d_msg\n", " d_rtn['order_status'] = 'Canceled'\n", " l_msg.append(d_rtn.copy())\n", "\n", "\n", " # Replace the order\n", " d_rtn = {'agent_id': 10,\n", " 'instrumento_symbol': 'PETR4',\n", " 'order_id': i_old_id,\n", " 'order_entry_step': idx,\n", " 'new_order_id': i_new_id,\n", " 'order_price': row['Price'],\n", " 'order_side': row.Type,\n", " 'order_status': 'Replaced',\n", " 'total_qty_order': row['Size'],\n", " 'traded_qty_order': 0,\n", " 'agressor_indicator': 'Neutral'}\n", " l_msg.append(d_rtn.copy())\n", " else: \n", " # if the price is not still in the book, include a new order\n", " d_rtn = {'agent_id': 10,\n", " 'instrumento_symbol': 'PETR4',\n", " 'order_id': my_book.i_last_order_id + 1,\n", " 'order_entry_step': idx,\n", " 'new_order_id': my_book.i_last_order_id + 1,\n", " 'order_price': row['Price'],\n", " 'order_side': row.Type,\n", " 'order_status': 'New',\n", " 'total_qty_order': row['Size'],\n", " 'traded_qty_order': 0,\n", " 'agressor_indicator': 'Neutral'}\n", " l_msg.append(d_rtn)\n", " return l_msg" ] }, { "cell_type": "code", "execution_count": 10, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "'It took 27.90 seconds to process 90,023 rows'" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# test the structure\n", "import qtrader.book as book; reload(book);\n", "import pprint\n", "import time\n", "f_start = time.time()\n", "my_book = book.LimitOrderBook('PETR4')\n", "self = my_book\n", "for idx, row in df.iterrows():\n", " l_msg = translate_row(idx, row, my_book)\n", " if l_msg:\n", " for msg in l_msg:\n", " my_book.update(msg)\n", "# if idx == 10000:\n", "# break\n", "\"It took {:0.2f} seconds to process {:0,.0f} rows\".format(time.time() - f_start, idx + 1)" ] }, { "cell_type": "code", "execution_count": 11, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "{'n_order_ask': 8, 'n_order_bid': 18, 'n_price_ask': 8, 'n_price_bid': 18}" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "my_book.get_basic_stats()" ] }, { "cell_type": "code", "execution_count": 51, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "<div>\n", "<table border=\"1\" class=\"dataframe\">\n", " <thead>\n", " <tr style=\"text-align: right;\">\n", " <th></th>\n", " <th>qBid</th>\n", " <th>Bid</th>\n", " <th>Ask</th>\n", " <th>qAsk</th>\n", " </tr>\n", " </thead>\n", " <tbody>\n", " <tr>\n", " <th>0</th>\n", " <td>50,600</td>\n", " <td>12.95</td>\n", " <td>12.96</td>\n", " <td>130,000</td>\n", " </tr>\n", " <tr>\n", " <th>1</th>\n", " <td>159,200</td>\n", " <td>12.94</td>\n", " <td>12.97</td>\n", " <td>62,400</td>\n", " </tr>\n", " <tr>\n", " <th>2</th>\n", " <td>8,700</td>\n", " <td>12.93</td>\n", " <td>12.98</td>\n", " <td>34,600</td>\n", " </tr>\n", " <tr>\n", " <th>3</th>\n", " <td>74,000</td>\n", " <td>12.92</td>\n", " <td>12.99</td>\n", " <td>28,100</td>\n", " </tr>\n", " <tr>\n", " <th>4</th>\n", " <td>9,700</td>\n", " <td>12.91</td>\n", " <td>13.00</td>\n", " <td>65,900</td>\n", " </tr>\n", " <tr>\n", " <th>5</th>\n", " <td>13,900</td>\n", " <td>12.90</td>\n", " <td>13.01</td>\n", " <td>31,900</td>\n", " </tr>\n", " <tr>\n", " <th>6</th>\n", " <td>45,400</td>\n", " <td>12.89</td>\n", " <td>13.02</td>\n", " <td>10,300</td>\n", " </tr>\n", " <tr>\n", " <th>7</th>\n", " <td>69,900</td>\n", " <td>12.88</td>\n", " <td>13.03</td>\n", " <td>119,300</td>\n", " </tr>\n", " <tr>\n", " <th>8</th>\n", " <td>123,000</td>\n", " <td>12.87</td>\n", " <td>NaN</td>\n", " <td>NaN</td>\n", " </tr>\n", " <tr>\n", " <th>9</th>\n", " <td>21,900</td>\n", " <td>12.86</td>\n", " <td>NaN</td>\n", " <td>NaN</td>\n", " </tr>\n", " <tr>\n", " <th>10</th>\n", " <td>33,000</td>\n", " <td>12.85</td>\n", " <td>NaN</td>\n", " <td>NaN</td>\n", " </tr>\n", " <tr>\n", " <th>11</th>\n", " <td>161,100</td>\n", " <td>12.84</td>\n", " <td>NaN</td>\n", " <td>NaN</td>\n", " </tr>\n", " <tr>\n", " <th>12</th>\n", " <td>53,800</td>\n", " <td>12.83</td>\n", " <td>NaN</td>\n", " <td>NaN</td>\n", " </tr>\n", " <tr>\n", " <th>13</th>\n", " <td>58,400</td>\n", " <td>12.82</td>\n", " <td>NaN</td>\n", " <td>NaN</td>\n", " </tr>\n", " <tr>\n", " <th>14</th>\n", " <td>12,700</td>\n", " <td>12.81</td>\n", " <td>NaN</td>\n", " <td>NaN</td>\n", " </tr>\n", " <tr>\n", " <th>15</th>\n", " <td>40,200</td>\n", " <td>12.80</td>\n", " <td>NaN</td>\n", " <td>NaN</td>\n", " </tr>\n", " <tr>\n", " <th>16</th>\n", " <td>44,900</td>\n", " <td>12.79</td>\n", " <td>NaN</td>\n", " <td>NaN</td>\n", " </tr>\n", " <tr>\n", " <th>17</th>\n", " <td>64,500</td>\n", " <td>12.78</td>\n", " <td>NaN</td>\n", " <td>NaN</td>\n", " </tr>\n", " </tbody>\n", "</table>\n", "</div>" ], "text/plain": [ " qBid Bid Ask qAsk\n", "0 50,600 12.95 12.96 130,000\n", "1 159,200 12.94 12.97 62,400\n", "2 8,700 12.93 12.98 34,600\n", "3 74,000 12.92 12.99 28,100\n", "4 9,700 12.91 13.00 65,900\n", "5 13,900 12.90 13.01 31,900\n", "6 45,400 12.89 13.02 10,300\n", "7 69,900 12.88 13.03 119,300\n", "8 123,000 12.87 NaN NaN\n", "9 21,900 12.86 NaN NaN\n", "10 33,000 12.85 NaN NaN\n", "11 161,100 12.84 NaN NaN\n", "12 53,800 12.83 NaN NaN\n", "13 58,400 12.82 NaN NaN\n", "14 12,700 12.81 NaN NaN\n", "15 40,200 12.80 NaN NaN\n", "16 44,900 12.79 NaN NaN\n", "17 64,500 12.78 NaN NaN" ] }, "execution_count": 51, "metadata": {}, "output_type": "execute_result" } ], "source": [ "my_book.get_n_top_prices(100)" ] }, { "cell_type": "markdown", "metadata": { "collapsed": true }, "source": [ "It is looking right, but I still need to treat Trades. Let's do it. As I know that some trades are cross orders (it is not passing through the book), I will pre-process the data to exclude them, so my simulator will just handle data that relevant." ] }, { "cell_type": "code", "execution_count": 21, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "<div>\n", "<table border=\"1\" class=\"dataframe\">\n", " <thead>\n", " <tr style=\"text-align: right;\">\n", " <th></th>\n", " <th>Date</th>\n", " <th>Type</th>\n", " <th>Price</th>\n", " <th>Size</th>\n", " </tr>\n", " </thead>\n", " <tbody>\n", " <tr>\n", " <th>0</th>\n", " <td>2016-08-18 10:09:09</td>\n", " <td>TRADE</td>\n", " <td>12.80</td>\n", " <td>1000</td>\n", " </tr>\n", " <tr>\n", " <th>1</th>\n", " <td>2016-08-18 10:09:09</td>\n", " <td>BID</td>\n", " <td>12.80</td>\n", " <td>15900</td>\n", " </tr>\n", " <tr>\n", " <th>2</th>\n", " <td>2016-08-18 10:09:09</td>\n", " <td>ASK</td>\n", " <td>12.81</td>\n", " <td>2900</td>\n", " </tr>\n", " <tr>\n", " <th>3</th>\n", " <td>2016-08-18 10:09:09</td>\n", " <td>ASK</td>\n", " <td>12.81</td>\n", " <td>7900</td>\n", " </tr>\n", " <tr>\n", " <th>4</th>\n", " <td>2016-08-18 10:09:09</td>\n", " <td>BID</td>\n", " <td>12.80</td>\n", " <td>20900</td>\n", " </tr>\n", " </tbody>\n", "</table>\n", "</div>" ], "text/plain": [ " Date Type Price Size\n", "0 2016-08-18 10:09:09 TRADE 12.80 1000\n", "1 2016-08-18 10:09:09 BID 12.80 15900\n", "2 2016-08-18 10:09:09 ASK 12.81 2900\n", "3 2016-08-18 10:09:09 ASK 12.81 7900\n", "4 2016-08-18 10:09:09 BID 12.80 20900" ] }, "execution_count": 21, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df.head()" ] }, { "cell_type": "code", "execution_count": 47, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "number of cross-orders: 26\n", "CPU times: user 21.5 s, sys: 706 ms, total: 22.2 s\n", "Wall time: 21.7 s\n" ] } ], "source": [ "def foo():\n", " best_bid = None\n", " best_ask = None\n", " i_num_cross = 0\n", " l_cross = []\n", " for idx, row in df.iterrows():\n", " if row.Size % 100 == 0:\n", " if row.Type == 'BID':\n", " best_bid = row.copy()\n", " elif row.Type == 'ASK':\n", " best_ask = row.copy()\n", " else:\n", " if not isinstance(best_bid, type(None)):\n", " if row.Price == best_bid.Price:\n", " if row.Size > best_bid.Size:\n", " # print 'cross-bid', idx\n", " i_num_cross += 1\n", " l_cross.append(idx)\n", "\n", " if not isinstance(best_ask, type(None)):\n", " if row.Price == best_ask.Price:\n", " if row.Size > best_ask.Size:\n", " # print 'cross-ask', idx\n", " i_num_cross += 1\n", " l_cross.append(idx)\n", " print \"number of cross-orders: {:.0f}\".format(i_num_cross)\n", " return l_cross\n", "\n", "%time l_cross = foo()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "I guess that I will not need to treat that. Just need to ignores trades that there are not enough in the book to filled them. Let´s first start by building an object to read the data files so I don't need to load all the data to a dataframe before translating the rows to the order book." ] }, { "cell_type": "code", "execution_count": 34, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Time to iterate the files: 32.37\n" ] } ], "source": [ "import qtrader.matching_engine as matching_engine; reload(matching_engine);\n", "import qtrader.book as book; reload(book);\n", "import time\n", "s_fname = \"data/petr4_0725_0818.zip\"\n", "my_test = matching_engine.BloombergMatching(None, \"PETR4\", 200, s_fname)\n", "f_start = time.time()\n", "for i in xrange(my_test.max_nfiles):\n", " for d_data in my_test:\n", " pass\n", "print \"Time to iterate the files: {:0.2f}\".format(time.time() - f_start)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Hm... I was reading all the files in 6 seconds before.... It looks bad, isn't it? Let's translate the messages and update the books using the last function implemented and process the trades." ] }, { "cell_type": "code", "execution_count": 103, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Time to iterate the files: 249.52\n" ] } ], "source": [ "import qtrader.matching_engine as matching_engine; reload(matching_engine);\n", "import qtrader.book as book; reload(book);\n", "import time\n", "s_fname = \"data/petr4_0725_0818_2.zip\"\n", "my_test = matching_engine.BloombergMatching(None, \"PETR4\", 200, s_fname)\n", "f_start = time.time()\n", "\n", "for i in xrange(my_test.max_nfiles):\n", " quit = False\n", " while True:\n", " try:\n", " l_msg = my_test.next()\n", " except StopIteration:\n", " quit = True\n", " finally:\n", " if quit:\n", " break\n", "# break\n", "print \"Time to iterate the files: {:0.2f}\".format(time.time() - f_start)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "... Yeh... There is some changes to do before conclude it. I need to make the translator handle multiple orders. It is handling multiple messages just in Trades, not when there are limit orders. I am not sure if I will use multiple agents by price, but I need to handle more than one agent anyway because the agent that I intend to create. But know what, before implement it, I guess that it is better to introduce the last peace of this study: the environment" ] }, { "cell_type": "code", "execution_count": 54, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "<div>\n", "<table border=\"1\" class=\"dataframe\">\n", " <thead>\n", " <tr style=\"text-align: right;\">\n", " <th></th>\n", " <th>qBid</th>\n", " <th>Bid</th>\n", " <th>Ask</th>\n", " <th>qAsk</th>\n", " </tr>\n", " </thead>\n", " <tbody>\n", " <tr>\n", " <th>0</th>\n", " <td>2,000</td>\n", " <td>12.01</td>\n", " <td>12.03</td>\n", " <td>36,000</td>\n", " </tr>\n", " <tr>\n", " <th>1</th>\n", " <td>800</td>\n", " <td>12.00</td>\n", " <td>12.04</td>\n", " <td>71,600</td>\n", " </tr>\n", " <tr>\n", " <th>2</th>\n", " <td>37,900</td>\n", " <td>11.99</td>\n", " <td>12.05</td>\n", " <td>20,400</td>\n", " </tr>\n", " <tr>\n", " <th>3</th>\n", " <td>97,000</td>\n", " <td>11.98</td>\n", " <td>12.06</td>\n", " <td>23,100</td>\n", " </tr>\n", " <tr>\n", " <th>4</th>\n", " <td>45,100</td>\n", " <td>11.97</td>\n", " <td>12.07</td>\n", " <td>27,900</td>\n", " </tr>\n", " </tbody>\n", "</table>\n", "</div>" ], "text/plain": [ " qBid Bid Ask qAsk\n", "0 2,000 12.01 12.03 36,000\n", "1 800 12.00 12.04 71,600\n", "2 37,900 11.99 12.05 20,400\n", "3 97,000 11.98 12.06 23,100\n", "4 45,100 11.97 12.07 27,900" ] }, "execution_count": 54, "metadata": {}, "output_type": "execute_result" } ], "source": [ "my_test.my_book.get_n_top_prices(5)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Finally, the Environment\n", "\n", "My environment should know what is the best bid and best price at each iteration, and keep a list of the trades that have happened. Each agent could have multiple orders at each time. However, I will allow the most of them to handle a single order at each time to simplify my problem. Each agent should receive some variables that it could use to compose its inner-state at each time step. Also, should be given the reward if it is the case. As I probably should test what kind of reward it receives, maybe the environment should pass just a dictionary of variables, and the agent decides what it will use as state and what it will use as the reward... and what it will not use at all.\n", "\n", "As I stated before, my order matching still has a important limitation. It assumes that all price levels have just a single order, and it will not be the case, as my agent will interact with the environment. I could even include more orders at each price level... but I guess that I will keep it \"simple\" (it is not simple, already).\n", "\n", "Something that I will have to take care is that, as I dealing with historical data (and I wnat to keep it in that way), I will need to make my translator to modify the order book to acomodate the order of my agent. My agent will always use the minimum quantity possible, so I need to discount it when my agent include an order in any price (and decrease it when the agent cancel that order). I also will have an agent that will have all order of the market (and that will perform the trades). So, let's start by just instantiating an environment and set the initial agents to a simulation" ] }, { "cell_type": "code", "execution_count": 60, "metadata": { "collapsed": false }, "outputs": [], "source": [ "import qtrader.book as book; reload(book);\n", "import qtrader.matching_engine as matching_engine; reload(matching_engine);\n", "import qtrader.environment as environment; reload(environment);\n", "import pprint" ] }, { "cell_type": "code", "execution_count": 61, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "{11: {'Ask': 0.0, 'Bid': 0.0, 'Position': 0, 'qAsk': 0, 'qBid': 0},\n", " 10: {'Ask': 0.0, 'Bid': 0.0, 'Position': 0, 'qAsk': 0, 'qBid': 0}}\n" ] } ], "source": [ "e = environment.Environment()\n", "a = e.create_agent(environment.Agent)\n", "e.set_primary_agent(a)\n", "pprint.pprint(dict(e.agent_states))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Ok, now let's try to simulate the order book, as before" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "import qtrader.book as book; reload(book);\n", "import qtrader.matching_engine as matching_engine; reload(matching_engine);\n", "import qtrader.environment as environment; reload(environment);\n", "import pprint\n", "import time\n", "s_fname = \"data/petr4_0725_0818_2.zip\"\n", "my_env = environment.Environment()\n", "f_start = time.time()\n", "\n", "for i in xrange(my_env.order_matching.max_nfiles):\n", " quit = False\n", " my_env.reset()\n", " while True:\n", " try:\n", " l_msg = my_env.step()\n", " except StopIteration:\n", " quit = True\n", " finally:\n", " if quit:\n", " break\n", "\n", "print \"Time to iterate the files: {:0.2f}\".format(time.time() - f_start)\n" ] }, { "cell_type": "markdown", "metadata": { "collapsed": true }, "source": [ "More than 5 minutes to read all files. Well, if you think, there are more than 2 million rows in total. It implies that there are more than 2 million times that my agent will receive something from the environment. So, maybe it is not so bad. Maybe I should even restrict the number of steps inside a particular file, so I could use the remain data to perform a back test. By the way, it is not a problem that I intend to address here. For now, my goal is just building the world where I can include agents to interact. It is already pretty complicated so far. Let's keep moving. Now, I will make the agent to sense the world and receive a reward by their actions. One of the measued that I want to include is the order flow imbalance that I will explain better in the main notebook. For now, the form of the measure is:\n", "\n", "$$e_n = \\mathbb{1}_{P_{n}^{B} \\geq P_{n-1}^{B}} q^{B}_{n} - \\mathbb{1}_{P_{n}^{B} \\leq P_{n-1}^{B}} q^{B}_{n-1} + \\mathbb{1}_{P_{n}^{A} \\leq P_{n-1}^{A}} q^{A}_{n} + \\mathbb{1}_{P_{n}^{A} \\geq P_{n-1}^{A}} q^{A}_{n-1}$$\n", "\n", "Where $A$ in related to the ask side, $B$ to the Bid side, $n$ to the current observation and $n-1$ to the last one. $\\mathbb{1}$ is an [Indicator](https://en.wikipedia.org/wiki/Indicator_function) function and $P$ is the price and $q$, the quantity. I will also hold the value of this variables in chunck of 10 seconds. So, let's see" ] }, { "cell_type": "code", "execution_count": 211, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Environment.reset(): Trial set up to use 20160725.csv file\n", "ZombieAgent.update(): position = 0, inputs = {'qAsk': 0, 'spread': 0, 'qAggr': 0, 'qTraded': 0, 'midPrice': 0.0, 'deltaMid': 0.0, 'qOfi': 0, 'qBid': 0}, action = BEST_BID, reward = 0.0\n", "ZombieAgent.update(): position = 0, inputs = {'qAsk': 51800, 'spread': 1, 'qAggr': 0, 'qTraded': 0, 'midPrice': 11.98, 'deltaMid': 0.0, 'qOfi': 0.0, 'qBid': 6100}, action = BEST_OFFER, reward = 0.0\n", "ZombieAgent.update(): position = 0, inputs = {'qAsk': 56800, 'spread': 1, 'qAggr': 0, 'qTraded': 0, 'midPrice': 11.98, 'deltaMid': 0.0, 'qOfi': 0.0, 'qBid': 6100}, action = None, reward = 0.0\n", "ZombieAgent.update(): position = 0, inputs = {'qAsk': 56800, 'spread': 1, 'qAggr': 0, 'qTraded': 0, 'midPrice': 11.98, 'deltaMid': 0.0, 'qOfi': 0.0, 'qBid': 6100}, action = BEST_OFFER, reward = 0.0\n", "ZombieAgent.update(): position = 0, inputs = {'qAsk': 56900, 'spread': 1, 'qAggr': 0, 'qTraded': 0, 'midPrice': 11.98, 'deltaMid': 0.0, 'qOfi': 0.0, 'qBid': 6100}, action = None, reward = 0.0\n", "ZombieAgent.update(): position = 0, inputs = {'qAsk': 56900, 'spread': 1, 'qAggr': 0, 'qTraded': 0, 'midPrice': 11.98, 'deltaMid': 0.0, 'qOfi': 0.0, 'qBid': 6100}, action = BEST_OFFER, reward = 0.0\n", "ZombieAgent.update(): position = 0, inputs = {'qAsk': 57000, 'spread': 1, 'qAggr': 0, 'qTraded': 0, 'midPrice': 11.98, 'deltaMid': 0.0, 'qOfi': 0.0, 'qBid': 6100}, action = None, reward = 0.0\n", "ZombieAgent.update(): position = 0, inputs = {'qAsk': 57000, 'spread': 1, 'qAggr': 0, 'qTraded': 0, 'midPrice': 11.98, 'deltaMid': 0.0, 'qOfi': 0.0, 'qBid': 6100}, action = BEST_OFFER, reward = 0.0\n", "ZombieAgent.update(): position = 0, inputs = {'qAsk': 55600, 'spread': 1, 'qAggr': 0, 'qTraded': 0, 'midPrice': 11.98, 'deltaMid': 0.0, 'qOfi': 1400.0, 'qBid': 6100}, action = BEST_OFFER, reward = 0.0\n", "ZombieAgent.update(): position = 0, inputs = {'qAsk': 55600, 'spread': 1, 'qAggr': 0, 'qTraded': 0, 'midPrice': 11.98, 'deltaMid': 0.0, 'qOfi': 6400.0, 'qBid': 11100}, action = None, reward = 0.0\n", "ZombieAgent.update(): position = 0, inputs = {'qAsk': 55600, 'spread': 1, 'qAggr': 0, 'qTraded': 0, 'midPrice': 11.98, 'deltaMid': 0.0, 'qOfi': 6400.0, 'qBid': 11100}, action = BEST_BID, reward = 0.0\n", "ZombieAgent.update(): position = -1000.0, inputs = {'qAsk': 54600, 'spread': 1, 'qAggr': 1000.0, 'qTraded': 1000.0, 'midPrice': 11.98, 'deltaMid': 0.0, 'qOfi': 7400.0, 'qBid': 11100}, action = SELL, reward = 0.0\n", "ZombieAgent.update(): position = 0.0, inputs = {'qAsk': 54600, 'spread': 1, 'qAggr': 1000.0, 'qTraded': 1000.0, 'midPrice': 11.98, 'deltaMid': 0.0, 'qOfi': 7400.0, 'qBid': 11100}, action = BUY, reward = 0.0\n", "ZombieAgent.update(): position = 0.0, inputs = {'qAsk': 54600, 'spread': 1, 'qAggr': 1000.0, 'qTraded': 1000.0, 'midPrice': 11.98, 'deltaMid': 0.0, 'qOfi': 7400.0, 'qBid': 11100}, action = BEST_OFFER, reward = 0.0\n", "Time to iterate the files: 0.01\n" ] } ], "source": [ "import qtrader.book as book; reload(book);\n", "import qtrader.matching_engine as matching_engine; reload(matching_engine);\n", "import qtrader.environment as environment; reload(environment);\n", "import pprint\n", "import time\n", "s_fname = \"data/petr4_0725_0818_2.zip\"\n", "my_env = environment.Environment()\n", "f_start = time.time()\n", "\n", "for i in xrange(my_env.order_matching.max_nfiles):\n", " quit = False\n", " my_env.reset()\n", " while True:\n", " try:\n", "# if my_env.order_matching.idx == 6:\n", "# if my_env.order_matching.i_nrow == 107410:\n", "# raise NotImplementedError\n", " if my_env.order_matching.i_nrow > 9:\n", " break\n", " l_msg = my_env.step()\n", " except StopIteration:\n", " quit = True\n", " finally:\n", " if quit:\n", " break\n", " break\n", "print \"Time to iterate the files: {:0.2f}\".format(time.time() - f_start)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now, I need to calculate the reward. Both the inputs from environment and the reward is something that I will need to explore in the main notebook. For now, the reward will be just the PnL from the last step to this step. Porblably I will penalize the agent to keep orders in the order book later. Just to make it \"pays the risk\". For now, let's see:" ] }, { "cell_type": "code", "execution_count": 215, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Environment.reset(): Trial set up to use 20160725.csv file\n", "ZombieAgent.update(): position = 0, inputs = {'qAsk': 0, 'spread': 0, 'qAggr': 0, 'qTraded': 0, 'midPrice': 0.0, 'deltaMid': 0.0, 'qOfi': 0, 'qBid': 0}, action = BEST_BID, reward = 0.0\n", "ZombieAgent.update(): position = 0, inputs = {'qAsk': 51800, 'spread': 1, 'qAggr': 0, 'qTraded': 0, 'midPrice': 11.98, 'deltaMid': 0.0, 'qOfi': 0.0, 'qBid': 6100}, action = BEST_OFFER, reward = 0.0\n", "ZombieAgent.update(): position = 0, inputs = {'qAsk': 56800, 'spread': 1, 'qAggr': 0, 'qTraded': 0, 'midPrice': 11.98, 'deltaMid': 0.0, 'qOfi': 0.0, 'qBid': 6100}, action = None, reward = 0.0\n", "ZombieAgent.update(): position = 0, inputs = {'qAsk': 56800, 'spread': 1, 'qAggr': 0, 'qTraded': 0, 'midPrice': 11.98, 'deltaMid': 0.0, 'qOfi': 0.0, 'qBid': 6100}, action = BEST_OFFER, reward = 0.0\n", "ZombieAgent.update(): position = 0, inputs = {'qAsk': 56900, 'spread': 1, 'qAggr': 0, 'qTraded': 0, 'midPrice': 11.98, 'deltaMid': 0.0, 'qOfi': 0.0, 'qBid': 6100}, action = None, reward = 0.0\n", "ZombieAgent.update(): position = 0, inputs = {'qAsk': 56900, 'spread': 1, 'qAggr': 0, 'qTraded': 0, 'midPrice': 11.98, 'deltaMid': 0.0, 'qOfi': 0.0, 'qBid': 6100}, action = BEST_OFFER, reward = 0.0\n", "ZombieAgent.update(): position = 0, inputs = {'qAsk': 57000, 'spread': 1, 'qAggr': 0, 'qTraded': 0, 'midPrice': 11.98, 'deltaMid': 0.0, 'qOfi': 0.0, 'qBid': 6100}, action = None, reward = 0.0\n", "ZombieAgent.update(): position = 0, inputs = {'qAsk': 57000, 'spread': 1, 'qAggr': 0, 'qTraded': 0, 'midPrice': 11.98, 'deltaMid': 0.0, 'qOfi': 0.0, 'qBid': 6100}, action = BEST_OFFER, reward = 0.0\n", "ZombieAgent.update(): position = 0, inputs = {'qAsk': 55600, 'spread': 1, 'qAggr': 0, 'qTraded': 0, 'midPrice': 11.98, 'deltaMid': 0.0, 'qOfi': 1400.0, 'qBid': 6100}, action = BEST_OFFER, reward = 0.0\n", "ZombieAgent.update(): position = 0, inputs = {'qAsk': 55600, 'spread': 1, 'qAggr': 0, 'qTraded': 0, 'midPrice': 11.98, 'deltaMid': 0.0, 'qOfi': 6400.0, 'qBid': 11100}, action = None, reward = 0.0\n", "ZombieAgent.update(): position = 0, inputs = {'qAsk': 55600, 'spread': 1, 'qAggr': 0, 'qTraded': 0, 'midPrice': 11.98, 'deltaMid': 0.0, 'qOfi': 6400.0, 'qBid': 11100}, action = BEST_BID, reward = 0.0\n", "ZombieAgent.update(): position = -1000.0, inputs = {'qAsk': 54600, 'spread': 1, 'qAggr': 1000.0, 'qTraded': 1000.0, 'midPrice': 11.98, 'deltaMid': 0.0, 'qOfi': 7400.0, 'qBid': 11100}, action = SELL, reward = -4.19\n", "ZombieAgent.update(): position = 0.0, inputs = {'qAsk': 54600, 'spread': 1, 'qAggr': 1000.0, 'qTraded': 1000.0, 'midPrice': 11.98, 'deltaMid': 0.0, 'qOfi': 7400.0, 'qBid': 11100}, action = BUY, reward = -4.19\n", "ZombieAgent.update(): position = 0.0, inputs = {'qAsk': 54600, 'spread': 1, 'qAggr': 1000.0, 'qTraded': 1000.0, 'midPrice': 11.98, 'deltaMid': 0.0, 'qOfi': 7400.0, 'qBid': 11100}, action = BEST_OFFER, reward = 0.0\n", "Time to iterate the files: 0.01\n" ] } ], "source": [ "import qtrader.book as book; reload(book);\n", "import qtrader.matching_engine as matching_engine; reload(matching_engine);\n", "import qtrader.environment as environment; reload(environment);\n", "import pprint\n", "import time\n", "s_fname = \"data/petr4_0725_0818_2.zip\"\n", "my_env = environment.Environment()\n", "f_start = time.time()\n", "\n", "for i in xrange(my_env.order_matching.max_nfiles):\n", " quit = False\n", " my_env.reset()\n", " while True:\n", " try:\n", "# if my_env.order_matching.idx == 6:\n", "# if my_env.order_matching.i_nrow == 107410:\n", "# raise NotImplementedError\n", " if my_env.order_matching.i_nrow > 9:\n", " break\n", " l_msg = my_env.step()\n", " except StopIteration:\n", " quit = True\n", " finally:\n", " if quit:\n", " break\n", " break\n", "print \"Time to iterate the files: {:0.2f}\".format(time.time() - f_start)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "It is pretty bad. It between 8 to 12 minutes to run, depending on the machine used. Well, I will try to optimize it later. Now, it is time to make the part that I was avoiding at all costs =). I need to allow a random agent interact with this world and receives whatever need to receive. I will need to improve my translator for doing that (at this point, my agent can not change too much what have happened). Also, I will not print out the updates in Zombie agent, but just in my learning agent, that will happen to be updated just once per second (from the simulation, not from real time). First, let's allow the environment to deal with multiple orders by price and trades when the prices cross each other." ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "collapsed": false }, "outputs": [], "source": [ "import qtrader.book as book; reload(book);\n", "import qtrader.matching_engine as matching_engine; reload(matching_engine);\n", "import qtrader.environment as environment; reload(environment);\n", "import qtrader.agent as agent; reload(agent);\n", "import qtrader.simulator as simulator; reload(simulator);" ] }, { "cell_type": "code", "execution_count": 20, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Simulator.run(): Trial 1\n", "Environment.reset(): Trial set up to use 20160725.csv file\n", "Environment.step(): Market closed at 16:30:00! Trial aborted.\n", "Simulator.run(): Trial 2\n", "Environment.reset(): Trial set up to use 20160726.csv file\n", "Environment.step(): Market closed at 16:30:00! Trial aborted.\n", "Simulator.run(): Trial 3\n", "Environment.reset(): Trial set up to use 20160727.csv file\n", "id: 118756, date: 2016-07-27 16:18:07\n", " qBid Bid Ask qAsk\n", "0 100 11.65 11.65 9,000\n", "1 77,200 11.64 11.66 78,300\n", "2 8,000 11.63 11.67 29,500\n", "3 72,300 11.62 11.68 38,700\n", "4 79,300 11.61 11.69 94,100\n", "\n", "corrected\n", " qBid Bid Ask qAsk\n", "0 77,200 11.64 11.65 8,900\n", "1 8,000 11.63 11.66 78,300\n", "2 72,300 11.62 11.67 29,500\n", "3 79,300 11.61 11.68 38,700\n", "4 90,600 11.60 11.69 94,100\n", "\n", "Environment.step(): Market closed at 16:30:00! Trial aborted.\n", "Simulator.run(): Trial 4\n", "Environment.reset(): Trial set up to use 20160728.csv file\n", "Environment.step(): Market closed at 16:30:00! Trial aborted.\n", "Simulator.run(): Trial 5\n", "Environment.reset(): Trial set up to use 20160729.csv file\n", "id: 108555, date: 2016-07-29 14:58:07\n", " qBid Bid Ask qAsk\n", "0 200 11.92 11.92 22,500\n", "1 11,700 11.91 11.93 107,900\n", "2 83,000 11.90 11.94 103,600\n", "3 51,200 11.89 11.95 100,700\n", "4 81,100 11.88 NaN NaN\n", "\n", "corrected\n", " qBid Bid Ask qAsk\n", "0 11,700 11.91 11.92 22,300\n", "1 83,000 11.90 11.93 107,900\n", "2 51,200 11.89 11.94 103,600\n", "3 81,100 11.88 11.95 100,700\n", "4 54,100 11.87 NaN NaN\n", "\n", "Environment.step(): Market closed at 16:30:00! Trial aborted.\n", "Simulator.run(): Trial 6\n", "Environment.reset(): Trial set up to use 20160801.csv file\n", "Environment.step(): Market closed at 16:30:00! Trial aborted.\n", "Simulator.run(): Trial 7\n", "Environment.reset(): Trial set up to use 20160802.csv file\n", "id: 112762, date: 2016-08-02 16:34:54\n", " qBid Bid Ask qAsk\n", "0 6,600 11.33 11.33 2,600\n", "1 18,700 11.32 11.34 27,900\n", "2 13,700 11.31 11.35 45,600\n", "3 100 11.30 11.36 61,800\n", "4 53,900 11.29 11.37 59,800\n", "\n", "corrected\n", " qBid Bid Ask qAsk\n", "0 4,000 11.33 11.34 27,900\n", "1 18,700 11.32 11.35 45,600\n", "2 13,700 11.31 11.36 61,800\n", "3 100 11.30 11.37 59,800\n", "4 53,900 11.29 11.38 20,000\n", "\n", "id: 112763, date: 2016-08-02 16:35:02\n", " qBid Bid Ask qAsk\n", "0 4,000 11.33 11.33 2,700\n", "1 18,700 11.32 11.34 27,900\n", "2 13,700 11.31 11.35 45,600\n", "3 100 11.30 11.36 61,800\n", "4 53,900 11.29 11.37 59,800\n", "\n", "corrected\n", " qBid Bid Ask qAsk\n", "0 1,300 11.33 11.34 27,900\n", "1 18,700 11.32 11.35 45,600\n", "2 13,700 11.31 11.36 61,800\n", "3 100 11.30 11.37 59,800\n", "4 53,900 11.29 11.38 20,000\n", "\n", "id: 112764, date: 2016-08-02 16:35:04\n", " qBid Bid Ask qAsk\n", "0 1,300 11.33 11.33 4,700\n", "1 18,700 11.32 11.34 27,900\n", "2 13,700 11.31 11.35 45,600\n", "3 100 11.30 11.36 61,800\n", "4 53,900 11.29 11.37 59,800\n", "\n", "corrected\n", " qBid Bid Ask qAsk\n", "0 18,700 11.32 11.33 3,400\n", "1 13,700 11.31 11.34 27,900\n", "2 100 11.30 11.35 45,600\n", "3 53,900 11.29 11.36 61,800\n", "4 7,100 11.28 11.37 59,800\n", "\n", "id: 112765, date: 2016-08-02 16:35:08\n", " qBid Bid Ask qAsk\n", "0 8,600 11.33 11.33 3,400\n", "1 18,700 11.32 11.34 27,900\n", "2 13,700 11.31 11.35 45,600\n", "3 100 11.30 11.36 61,800\n", "4 53,900 11.29 11.37 59,800\n", "\n", "corrected\n", " qBid Bid Ask qAsk\n", "0 5,200 11.33 11.34 27,900\n", "1 18,700 11.32 11.35 45,600\n", "2 13,700 11.31 11.36 61,800\n", "3 100 11.30 11.37 59,800\n", "4 53,900 11.29 11.38 20,000\n", "\n", "id: 112781, date: 2016-08-02 16:35:44\n", " qBid Bid Ask qAsk\n", "0 13,400 11.33 11.33 5,900\n", "1 18,700 11.32 11.34 27,900\n", "2 13,700 11.31 11.35 45,600\n", "3 100 11.30 11.36 61,800\n", "4 53,900 11.29 11.37 59,800\n", "\n", "corrected\n", " qBid Bid Ask qAsk\n", "0 7,500 11.33 11.34 27,900\n", "1 18,700 11.32 11.35 45,600\n", "2 13,700 11.31 11.36 61,800\n", "3 100 11.30 11.37 59,800\n", "4 53,900 11.29 11.38 20,000\n", "\n", "id: 112803, date: 2016-08-02 16:36:09\n", " qBid Bid Ask qAsk\n", "0 7,500 11.33 11.33 7,100\n", "1 18,700 11.32 11.34 27,900\n", "2 13,700 11.31 11.35 45,600\n", "3 100 11.30 11.36 61,800\n", "4 53,900 11.29 11.37 59,800\n", "\n", "corrected\n", " qBid Bid Ask qAsk\n", "0 400 11.33 11.34 27,900\n", "1 18,700 11.32 11.35 45,600\n", "2 13,700 11.31 11.36 61,800\n", "3 100 11.30 11.37 59,800\n", "4 53,900 11.29 11.38 20,000\n", "\n", "id: 112805, date: 2016-08-02 16:36:13\n", " qBid Bid Ask qAsk\n", "0 19,900 11.33 11.33 8,100\n", "1 18,700 11.32 11.34 27,900\n", "2 13,700 11.31 11.35 45,600\n", "3 100 11.30 11.36 61,800\n", "4 53,900 11.29 11.37 59,800\n", "\n", "corrected\n", " qBid Bid Ask qAsk\n", "0 11,800 11.33 11.34 27,900\n", "1 18,700 11.32 11.35 45,600\n", "2 13,700 11.31 11.36 61,800\n", "3 100 11.30 11.37 59,800\n", "4 53,900 11.29 11.38 20,000\n", "\n", "id: 112806, date: 2016-08-02 16:36:14\n", " qBid Bid Ask qAsk\n", "0 11,800 11.33 11.33 8,300\n", "1 18,700 11.32 11.34 27,900\n", "2 13,700 11.31 11.35 45,600\n", "3 100 11.30 11.36 61,800\n", "4 53,900 11.29 11.37 59,800\n", "\n", "corrected\n", " qBid Bid Ask qAsk\n", "0 3,500 11.33 11.34 27,900\n", "1 18,700 11.32 11.35 45,600\n", "2 13,700 11.31 11.36 61,800\n", "3 100 11.30 11.37 59,800\n", "4 53,900 11.29 11.38 20,000\n", "\n", "id: 112807, date: 2016-08-02 16:36:15\n", " qBid Bid Ask qAsk\n", "0 3,500 11.33 11.32 600\n", "1 18,700 11.32 11.34 27,900\n", "2 13,700 11.31 11.35 45,600\n", "3 100 11.30 11.36 61,800\n", "4 53,900 11.29 11.37 59,800\n", "\n", "corrected\n", " qBid Bid Ask qAsk\n", "0 2,900 11.33 11.34 27,900\n", "1 18,700 11.32 11.35 45,600\n", "2 13,700 11.31 11.36 61,800\n", "3 100 11.30 11.37 59,800\n", "4 53,900 11.29 11.38 20,000\n", "\n", "id: 112808, date: 2016-08-02 16:36:25\n", " qBid Bid Ask qAsk\n", "0 300 11.40 11.34 27,900\n", "1 2,900 11.33 11.35 45,600\n", "2 18,700 11.32 11.36 61,800\n", "3 13,700 11.31 11.37 59,800\n", "4 100 11.30 11.38 20,000\n", "\n", "corrected\n", " qBid Bid Ask qAsk\n", "0 2,900 11.33 11.34 27,600\n", "1 18,700 11.32 11.35 45,600\n", "2 13,700 11.31 11.36 61,800\n", "3 100 11.30 11.37 59,800\n", "4 53,900 11.29 11.38 20,000\n", "\n", "id: 112811, date: 2016-08-02 16:37:18\n", " qBid Bid Ask qAsk\n", "0 2,900 11.33 11.30 1,700\n", "1 18,700 11.32 11.34 27,600\n", "2 13,700 11.31 11.35 45,600\n", "3 100 11.30 11.36 61,800\n", "4 53,900 11.29 11.37 59,800\n", "\n", "corrected\n", " qBid Bid Ask qAsk\n", "0 1,200 11.33 11.34 27,600\n", "1 18,700 11.32 11.35 45,600\n", "2 13,700 11.31 11.36 61,800\n", "3 100 11.30 11.37 59,800\n", "4 53,900 11.29 11.38 20,000\n", "\n", "id: 112813, date: 2016-08-02 16:37:56\n", " qBid Bid Ask qAsk\n", "0 1,200 11.33 11.30 2,000\n", "1 18,700 11.32 11.34 27,600\n", "2 13,700 11.31 11.35 45,600\n", "3 100 11.30 11.36 61,800\n", "4 53,900 11.29 11.37 59,800\n", "\n", "corrected\n", " qBid Bid Ask qAsk\n", "0 18,700 11.32 11.30 800\n", "1 13,700 11.31 11.34 27,600\n", "2 100 11.30 11.35 45,600\n", "3 53,900 11.29 11.36 61,800\n", "4 7,100 11.28 11.37 59,800\n", "\n", "id: 112813, date: 2016-08-02 16:37:56\n", " qBid Bid Ask qAsk\n", "0 18,700 11.32 11.30 800\n", "1 13,700 11.31 11.34 27,600\n", "2 100 11.30 11.35 45,600\n", "3 53,900 11.29 11.36 61,800\n", "4 7,100 11.28 11.37 59,800\n", "\n", "corrected\n", " qBid Bid Ask qAsk\n", "0 17,900 11.32 11.34 27,600\n", "1 13,700 11.31 11.35 45,600\n", "2 100 11.30 11.36 61,800\n", "3 53,900 11.29 11.37 59,800\n", "4 7,100 11.28 11.38 20,000\n", "\n", "id: 112930, date: 2016-08-02 17:10:08\n", " qBid Bid Ask qAsk\n", "0 17,900 11.32 11.00 200\n", "1 13,700 11.31 11.34 27,600\n", "2 100 11.30 11.35 45,600\n", "3 53,900 11.29 11.36 61,800\n", "4 7,100 11.28 11.37 59,800\n", "\n", "Environment.step(): Market closed at 16:30:00! Trial aborted.\n", "Simulator.run(): Trial 8\n", "Environment.reset(): Trial set up to use 20160803.csv file\n", "corrected\n", "Empty DataFrame\n", "Columns: [qBid, Bid, Ask, qAsk]\n", "Index: []\n", "\n", "Environment.step(): Market closed at 16:30:00! Trial aborted.\n", "Simulator.run(): Trial 9\n", "Environment.reset(): Trial set up to use 20160804.csv file\n", "id: 107887, date: 2016-08-04 15:08:10\n", " qBid Bid Ask qAsk\n", "0 49,600 12.09 12.09 100\n", "1 100 12.08 12.10 311,700\n", "2 42,800 12.07 12.11 99,700\n", "3 100 12.06 12.12 279,000\n", "4 24,900 12.05 NaN NaN\n", "\n", "corrected\n", " qBid Bid Ask qAsk\n", "0 49,500 12.09 12.10 311,700\n", "1 100 12.08 12.11 99,700\n", "2 42,800 12.07 12.12 279,000\n", "3 100 12.06 NaN NaN\n", "4 24,900 12.05 NaN NaN\n", "\n", "id: 114962, date: 2016-08-04 15:28:04\n", " qBid Bid Ask qAsk\n", "0 100 12.05 12.05 5,400\n", "1 139,900 12.04 12.06 15,400\n", "2 47,600 12.03 12.07 57,900\n", "3 16,500 12.02 12.08 24,500\n", "4 100 12.01 12.09 38,000\n", "\n", "corrected\n", " qBid Bid Ask qAsk\n", "0 139,900 12.04 12.05 5,300\n", "1 47,600 12.03 12.06 15,400\n", "2 16,500 12.02 12.07 57,900\n", "3 100 12.01 12.08 24,500\n", "4 20,900 12.00 12.09 38,000\n", "\n", "Environment.step(): Market closed at 16:30:00! Trial aborted.\n", "Simulator.run(): Trial 10\n", "Environment.reset(): Trial set up to use 20160805.csv file\n", "id: 61813, date: 2016-08-05 13:37:24\n", " qBid Bid Ask qAsk\n", "0 100 11.80 11.79 8,100\n", "1 12,400 11.78 11.80 25,900\n", "\n", "corrected\n", " qBid Bid Ask qAsk\n", "0 12,400 11.78 11.79 8,000\n", "\n", "Environment.step(): Market closed at 16:30:00! Trial aborted.\n", "Simulator.run(): Trial 11\n", "Environment.reset(): Trial set up to use 20160808.csv file\n", "id: 57769, date: 2016-08-08 13:24:23\n", " qBid Bid Ask qAsk\n", "0 800 11.91 11.91 100\n", "1 63,300 11.90 11.92 24,600\n", "2 23,000 11.89 11.93 12,700\n", "3 79,900 11.88 11.94 67,000\n", "4 11,600 11.87 11.95 13,900\n", "\n", "corrected\n", " qBid Bid Ask qAsk\n", "0 700 11.91 11.92 24,600\n", "1 63,300 11.90 11.93 12,700\n", "2 23,000 11.89 11.94 67,000\n", "3 79,900 11.88 11.95 13,900\n", "4 11,600 11.87 11.96 64,800\n", "\n", "Environment.step(): Market closed at 16:30:00! Trial aborted.\n", "Simulator.run(): Trial 12\n", "Environment.reset(): Trial set up to use 20160809.csv file\n", "Environment.step(): Market closed at 16:30:00! Trial aborted.\n", "Simulator.run(): Trial 13\n", "Environment.reset(): Trial set up to use 20160810.csv file\n", "Environment.step(): Market closed at 16:30:00! Trial aborted.\n", "Simulator.run(): Trial 14\n", "Environment.reset(): Trial set up to use 20160811.csv file\n", "Environment.step(): Market closed at 16:30:00! Trial aborted.\n", "Simulator.run(): Trial 15\n", "Environment.reset(): Trial set up to use 20160812.csv file\n", "id: 1244, date: 2016-08-12 10:07:42\n", " qBid Bid Ask qAsk\n", "0 3,700 12.20 12.20 100\n", "1 20,800 12.19 12.21 13,800\n", "2 25,200 12.18 NaN NaN\n", "3 17,000 12.17 NaN NaN\n", "4 21,400 12.16 NaN NaN\n", "\n", "corrected\n", " qBid Bid Ask qAsk\n", "0 3,600 12.20 12.21 13,800\n", "1 20,800 12.19 NaN NaN\n", "2 25,200 12.18 NaN NaN\n", "3 17,000 12.17 NaN NaN\n", "4 21,400 12.16 NaN NaN\n", "\n", "id: 20005, date: 2016-08-12 10:32:36\n", " qBid Bid Ask qAsk\n", "0 6,700 12.31 12.30 200\n", "1 89,100 12.30 12.32 45,900\n", "2 6,700 12.29 NaN NaN\n", "3 14,700 12.28 NaN NaN\n", "4 75,300 12.27 NaN NaN\n", "\n", "corrected\n", " qBid Bid Ask qAsk\n", "0 6,500 12.31 12.32 45,900\n", "1 89,100 12.30 NaN NaN\n", "2 6,700 12.29 NaN NaN\n", "3 14,700 12.28 NaN NaN\n", "4 75,300 12.27 NaN NaN\n", "\n", "id: 111297, date: 2016-08-12 14:46:20\n", " qBid Bid Ask qAsk\n", "0 100 12.15 12.15 20,000\n", "1 55,300 12.13 12.16 69,600\n", "2 23,200 12.12 12.17 60,800\n", "3 8,000 12.11 12.18 30,300\n", "4 10,100 12.10 12.19 128,600\n", "\n", "corrected\n", " qBid Bid Ask qAsk\n", "0 55,300 12.13 12.15 19,900\n", "1 23,200 12.12 12.16 69,600\n", "2 8,000 12.11 12.17 60,800\n", "3 10,100 12.10 12.18 30,300\n", "4 34,000 12.09 12.19 128,600\n", "\n", "Environment.step(): Market closed at 16:30:00! Trial aborted.\n", "Simulator.run(): Trial 16\n", "Environment.reset(): Trial set up to use 20160815.csv file\n", "Environment.step(): Market closed at 16:30:00! Trial aborted.\n", "Simulator.run(): Trial 17\n", "Environment.reset(): Trial set up to use 20160816.csv file\n", "Environment.step(): Market closed at 16:30:00! Trial aborted.\n", "Simulator.run(): Trial 18\n", "Environment.reset(): Trial set up to use 20160817.csv file\n", "Environment.step(): Market closed at 16:30:00! Trial aborted.\n", "Simulator.run(): Trial 19\n", "Environment.reset(): Trial set up to use 20160818.csv file\n", "id: 86051, date: 2016-08-18 16:21:40\n", " qBid Bid Ask qAsk\n", "0 100 13.02 13.02 43,700\n", "1 63,000 13.01 13.03 151,900\n", "2 8,400 13.00 NaN NaN\n", "3 118,800 12.99 NaN NaN\n", "4 58,100 12.98 NaN NaN\n", "\n", "corrected\n", " qBid Bid Ask qAsk\n", "0 63,000 13.01 13.02 43,600\n", "1 8,400 13.00 13.03 151,900\n", "2 118,800 12.99 NaN NaN\n", "3 58,100 12.98 NaN NaN\n", "4 53,100 12.97 NaN NaN\n", "\n", "CPU times: user 4min 12s, sys: 1.28 s, total: 4min 13s\n", "Wall time: 4min 13s\n" ] } ], "source": [ "e = environment.Environment()\n", "a = e.create_agent(agent.BasicAgent)\n", "e.set_primary_agent(a)\n", "\n", "sim = simulator.Simulator(e)\n", "%time sim.run(n_trials=20)" ] }, { "cell_type": "markdown", "metadata": { "collapsed": true }, "source": [ "Ok, now, let's implement my basic agent that will take actions randomly. I will let it insert limit order with 10 cents of spread between the bid price the the agent order I alow it to update its state just once a hour." ] }, { "cell_type": "code", "execution_count": 64, "metadata": { "collapsed": false }, "outputs": [], "source": [ "import qtrader.book as book; reload(book);\n", "import qtrader.matching_engine as matching_engine; reload(matching_engine);\n", "import qtrader.environment as environment; reload(environment);\n", "import qtrader.agent as agent; reload(agent);\n", "import qtrader.simulator as simulator; reload(simulator);\n", "import qtrader.translators as translators; reload(translators);" ] }, { "cell_type": "code", "execution_count": 65, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Simulator.run(): Trial 1\n", "Environment.reset(): Trial set up to use 20160725.csv file\n", "BasicAgent.update(): position = 100.0, inputs = {'qAsk': 7000, 'spread': 1, 'qAggr': 0.0, 'qTraded': 0.0, 'midPrice': '12.14', 'deltaMid': '0.000', 'qOfi': 0.0, 'qBid': 30400}, action = TAKE, price_action = ['12.14'], reward = -0.42, time = 2016-07-25 10:10:00\n", "\n", "BasicAgent.update(): position = 200.0, inputs = {'qAsk': 12800, 'spread': 1, 'qAggr': 0.0, 'qTraded': 0.0, 'midPrice': '12.07', 'deltaMid': '0.000', 'qOfi': 0.0, 'qBid': 17600}, action = TAKE, price_action = ['12.07'], reward = -7.42, time = 2016-07-25 11:10:00\n", "\n", "BasicAgent.update(): position = 300.0, inputs = {'qAsk': 58900, 'spread': 1, 'qAggr': 0.0, 'qTraded': 0.0, 'midPrice': '12.00', 'deltaMid': '0.000', 'qOfi': 0.0, 'qBid': 26200}, action = TAKE, price_action = ['12.00'], reward = -14.42, time = 2016-07-25 12:10:00\n", "\n", "BasicAgent.update(): position = 300.0, inputs = {'qAsk': 104200, 'spread': 1, 'qAggr': 0.0, 'qTraded': 0.0, 'midPrice': '12.04', 'deltaMid': '0.000', 'qOfi': 0.0, 'qBid': 20600}, action = None, price_action = [], reward = 0, time = 2016-07-25 13:10:00\n", "\n", "BasicAgent.update(): position = 200.0, inputs = {'qAsk': 90900, 'spread': 1, 'qAggr': 0.0, 'qTraded': 0.0, 'midPrice': '12.02', 'deltaMid': '0.000', 'qOfi': 0.0, 'qBid': 5100}, action = HIT, price_action = ['12.02'], reward = 5.58, time = 2016-07-25 14:10:00\n", "\n", "BasicAgent.update(): position = 200.0, inputs = {'qAsk': 32100, 'spread': 1, 'qAggr': 0.0, 'qTraded': 0.0, 'midPrice': '12.10', 'deltaMid': '0.000', 'qOfi': 0.0, 'qBid': 44500}, action = None, price_action = [], reward = 0, time = 2016-07-25 15:10:00\n", "\n", "BasicAgent.update(): position = 200.0, inputs = {'qAsk': 13200, 'spread': 1, 'qAggr': 0.0, 'qTraded': 0.0, 'midPrice': '12.07', 'deltaMid': '0.000', 'qOfi': 0.0, 'qBid': 42400}, action = None, price_action = [], reward = 0, time = 2016-07-25 16:10:00\n", "\n", "Environment.step(): Market closed at 16:30:00! MidPrice = 12.03. Trial aborted.\n", "\n", "Simulator.run(): Trial 2\n", "Environment.reset(): Trial set up to use 20160726.csv file\n", "BasicAgent.update(): position = -100.0, inputs = {'qAsk': 600, 'spread': 1, 'qAggr': 25600.0, 'qTraded': 83800.0, 'midPrice': '11.92', 'deltaMid': '-0.010', 'qOfi': 121700.0, 'qBid': 95400}, action = HIT, price_action = ['11.92'], reward = -0.42, time = 2016-07-26 10:10:03\n", "\n", "BasicAgent.update(): position = 0.0, inputs = {'qAsk': 15800, 'spread': 1, 'qAggr': -6500.0, 'qTraded': 6500.0, 'midPrice': '11.98', 'deltaMid': '0.000', 'qOfi': 1900.0, 'qBid': 7100}, action = TAKE, price_action = ['11.98'], reward = -6.42, time = 2016-07-26 11:10:03\n", "\n", "BasicAgent.update(): position = 0.0, inputs = {'qAsk': 49200, 'spread': 2, 'qAggr': 0.0, 'qTraded': 0.0, 'midPrice': '11.94', 'deltaMid': '0.000', 'qOfi': 0.0, 'qBid': 23600}, action = BEST_BOTH, price_action = ['11.83', '12.05'], reward = 0.0, time = 2016-07-26 12:10:03\n", "\n", "BasicAgent.update(): position = -100.0, inputs = {'qAsk': 317500, 'spread': 2, 'qAggr': 17200.0, 'qTraded': 46200.0, 'midPrice': '12.04', 'deltaMid': '0.005', 'qOfi': 17500.0, 'qBid': 67800}, action = SELL, price_action = ['12.05'], reward = 0.58, time = 2016-07-26 12:41:26\n", "\n", "BasicAgent.update(): position = -200.0, inputs = {'qAsk': 19000, 'spread': 1, 'qAggr': 10800.0, 'qTraded': 10800.0, 'midPrice': '12.06', 'deltaMid': '0.000', 'qOfi': -9400.0, 'qBid': 10000}, action = HIT, price_action = ['12.05'], reward = -3.42, time = 2016-07-26 13:41:27\n", "\n", "BasicAgent.update(): position = -300.0, inputs = {'qAsk': 12100, 'spread': 1, 'qAggr': 1100.0, 'qTraded': 1100.0, 'midPrice': '11.98', 'deltaMid': '0.000', 'qOfi': 12200.0, 'qBid': 133300}, action = HIT, price_action = ['11.98'], reward = 15.58, time = 2016-07-26 14:41:29\n", "\n", "BasicAgent.update(): position = -300.0, inputs = {'qAsk': 30300, 'spread': 1, 'qAggr': -500.0, 'qTraded': 900.0, 'midPrice': '11.96', 'deltaMid': '0.000', 'qOfi': -6600.0, 'qBid': 111300}, action = BEST_BOTH, price_action = ['11.83', '11.85', '12.06'], reward = 6.0, time = 2016-07-26 15:41:29\n", "\n", "BasicAgent.update(): position = -300.0, inputs = {'qAsk': 158200, 'spread': 1, 'qAggr': -2100.0, 'qTraded': 2900.0, 'midPrice': '11.93', 'deltaMid': '0.000', 'qOfi': -3100.0, 'qBid': 15400}, action = BEST_BID, price_action = ['12.06', '11.85', '11.83'], reward = 9.0, time = 2016-07-26 16:41:29\n", "\n", "Environment.step(): Market closed at 16:30:00! MidPrice = 11.94. Trial aborted.\n", "\n", "Simulator.run(): Trial 3\n", "Environment.reset(): Trial set up to use 20160727.csv file\n", "BasicAgent.update(): position = 0, inputs = {'qAsk': 5500, 'spread': 1, 'qAggr': 0, 'qTraded': 0, 'midPrice': '11.98', 'deltaMid': '0.000', 'qOfi': 0.0, 'qBid': 11700}, action = BEST_BID, price_action = ['11.88'], reward = 0.0, time = 2016-07-27 10:10:20\n", "\n", "BasicAgent.update(): position = 100.0, inputs = {'qAsk': 25000, 'spread': 1, 'qAggr': -100.0, 'qTraded': 100.0, 'midPrice': '11.93', 'deltaMid': '0.000', 'qOfi': 1200.0, 'qBid': 13700}, action = TAKE, price_action = ['11.94'], reward = -1.42, time = 2016-07-27 11:10:22\n", "\n", "BasicAgent.update(): position = 200.0, inputs = {'qAsk': 21200, 'spread': 2, 'qAggr': -230800.0, 'qTraded': 230800.0, 'midPrice': '11.89', 'deltaMid': '-0.015', 'qOfi': -40400.0, 'qBid': 93900}, action = BUY, price_action = ['11.88'], reward = -3.42, time = 2016-07-27 11:20:26\n", "\n", "BasicAgent.update(): position = 200.0, inputs = {'qAsk': 27700, 'spread': 1, 'qAggr': 9400.0, 'qTraded': 10600.0, 'midPrice': '11.70', 'deltaMid': '0.000', 'qOfi': 10600.0, 'qBid': 53900}, action = BEST_BID, price_action = ['11.59'], reward = -38.0, time = 2016-07-27 12:20:27\n", "\n", "BasicAgent.update(): position = 200.0, inputs = {'qAsk': 22600, 'spread': 1, 'qAggr': -1200.0, 'qTraded': 1400.0, 'midPrice': '11.68', 'deltaMid': '0.000', 'qOfi': 4000.0, 'qBid': 54900}, action = None, price_action = ['11.59'], reward = -4.0, time = 2016-07-27 13:20:27\n", "\n", "BasicAgent.update(): position = 300.0, inputs = {'qAsk': 30500, 'spread': 1, 'qAggr': 600.0, 'qTraded': 1800.0, 'midPrice': '11.58', 'deltaMid': '0.000', 'qOfi': 2500.0, 'qBid': 95200}, action = TAKE, price_action = ['11.59'], reward = -21.41, time = 2016-07-27 14:20:27\n", "\n", "BasicAgent.update(): position = 400.0, inputs = {'qAsk': 73300, 'spread': 1, 'qAggr': 2500.0, 'qTraded': 2700.0, 'midPrice': '11.62', 'deltaMid': '0.000', 'qOfi': -4800.0, 'qBid': 8300}, action = TAKE, price_action = ['11.63'], reward = 10.59, time = 2016-07-27 15:20:27\n", "\n", "id: 118756, date: 2016-07-27 16:18:07\n", " qBid Bid Ask qAsk\n", "0 100 11.65 11.65 9,000\n", "1 77,200 11.64 11.66 78,300\n", "2 8,000 11.63 11.67 29,500\n", "3 72,300 11.62 11.68 38,700\n", "4 79,300 11.61 11.69 94,100\n", "\n", "corrected\n", " qBid Bid Ask qAsk\n", "0 77,200 11.64 11.65 8,900\n", "1 8,000 11.63 11.66 78,300\n", "2 72,300 11.62 11.67 29,500\n", "3 79,300 11.61 11.68 38,700\n", "4 90,600 11.60 11.69 94,100\n", "\n", "BasicAgent.update(): position = 400.0, inputs = {'qAsk': 112800, 'spread': 1, 'qAggr': 8700.0, 'qTraded': 12100.0, 'midPrice': '11.64', 'deltaMid': '0.000', 'qOfi': -125400.0, 'qBid': 83200}, action = None, price_action = [], reward = 0, time = 2016-07-27 16:20:27\n", "\n", "Environment.step(): Market closed at 16:30:00! MidPrice = 11.53. Trial aborted.\n", "\n", "Simulator.run(): Trial 4\n", "Environment.reset(): Trial set up to use 20160728.csv file\n", "BasicAgent.update(): position = 100.0, inputs = {'qAsk': 1600, 'spread': 1, 'qAggr': 0.0, 'qTraded': 0.0, 'midPrice': '11.34', 'deltaMid': '0.000', 'qOfi': 0.0, 'qBid': 72800}, action = TAKE, price_action = ['11.35'], reward = -1.4, time = 2016-07-28 10:10:00\n", "\n", "BasicAgent.update(): position = 0.0, inputs = {'qAsk': 4100, 'spread': 1, 'qAggr': 3700.0, 'qTraded': 5900.0, 'midPrice': '11.26', 'deltaMid': '0.010', 'qOfi': 42400.0, 'qBid': 17900}, action = HIT, price_action = ['11.26'], reward = -8.39, time = 2016-07-28 11:10:01\n", "\n", "BasicAgent.update(): position = 100.0, inputs = {'qAsk': 6700, 'spread': 1, 'qAggr': -100.0, 'qTraded': 1300.0, 'midPrice': '11.26', 'deltaMid': '0.000', 'qOfi': 1900.0, 'qBid': 21300}, action = TAKE, price_action = ['11.27'], reward = -1.39, time = 2016-07-28 12:10:05\n", "\n", "BasicAgent.update(): position = 100.0, inputs = {'qAsk': 5400, 'spread': 1, 'qAggr': 3200.0, 'qTraded': 5000.0, 'midPrice': '11.26', 'deltaMid': '0.000', 'qOfi': -400.0, 'qBid': 35500}, action = None, price_action = [], reward = 0, time = 2016-07-28 13:10:06\n", "\n", "BasicAgent.update(): position = 0.0, inputs = {'qAsk': 78200, 'spread': 1, 'qAggr': 4400.0, 'qTraded': 5400.0, 'midPrice': '11.39', 'deltaMid': '0.000', 'qOfi': -700.0, 'qBid': 60300}, action = HIT, price_action = ['11.38'], reward = 11.6, time = 2016-07-28 14:10:06\n", "\n", "BasicAgent.update(): position = 0.0, inputs = {'qAsk': 5000, 'spread': 1, 'qAggr': 46000.0, 'qTraded': 75600.0, 'midPrice': '11.52', 'deltaMid': '0.020', 'qOfi': 121400.0, 'qBid': 19900}, action = BEST_BID, price_action = ['11.42'], reward = 0.0, time = 2016-07-28 15:10:06\n", "\n", "BasicAgent.update(): position = 100.0, inputs = {'qAsk': 6900, 'spread': 2, 'qAggr': -3900.0, 'qTraded': 3900.0, 'midPrice': '11.43', 'deltaMid': '-0.005', 'qOfi': -10400.0, 'qBid': 58300}, action = BUY, price_action = ['11.42'], reward = 0.6, time = 2016-07-28 15:31:02\n", "\n", "BasicAgent.update(): position = 100.0, inputs = {'qAsk': 29500, 'spread': 1, 'qAggr': 0.0, 'qTraded': 0.0, 'midPrice': '11.40', 'deltaMid': '0.000', 'qOfi': 3300.0, 'qBid': 15500}, action = BEST_BID, price_action = ['11.30'], reward = -3.0, time = 2016-07-28 16:31:04\n", "\n", "Environment.step(): Market closed at 16:30:00! MidPrice = 11.43. Trial aborted.\n", "\n", "Simulator.run(): Trial 5\n", "Environment.reset(): Trial set up to use 20160729.csv file\n", "BasicAgent.update(): position = -100.0, inputs = {'qAsk': 28000, 'spread': 1, 'qAggr': -300.0, 'qTraded': 300.0, 'midPrice': '11.76', 'deltaMid': '11.765', 'qOfi': 130100.0, 'qBid': 135100}, action = HIT, price_action = ['11.76'], reward = -0.41, time = 2016-07-29 10:10:11\n", "\n", "BasicAgent.update(): position = -100.0, inputs = {'qAsk': 23500, 'spread': 1, 'qAggr': 0.0, 'qTraded': 0.0, 'midPrice': '11.70', 'deltaMid': '0.000', 'qOfi': -400.0, 'qBid': 7400}, action = None, price_action = [], reward = 0, time = 2016-07-29 11:10:11\n", "\n", "BasicAgent.update(): position = 0.0, inputs = {'qAsk': 7000, 'spread': 1, 'qAggr': 600.0, 'qTraded': 600.0, 'midPrice': '11.76', 'deltaMid': '0.000', 'qOfi': 11000.0, 'qBid': 18300}, action = TAKE, price_action = ['11.76'], reward = -0.41, time = 2016-07-29 12:10:11\n", "\n", "BasicAgent.update(): position = 0.0, inputs = {'qAsk': 136800, 'spread': 2, 'qAggr': 0.0, 'qTraded': 0.0, 'midPrice': '11.81', 'deltaMid': '0.000', 'qOfi': 26100.0, 'qBid': 50400}, action = BEST_BID, price_action = ['11.70'], reward = 0.0, time = 2016-07-29 13:10:12\n", "\n", "BasicAgent.update(): position = -100.0, inputs = {'qAsk': 93200, 'spread': 1, 'qAggr': 2000.0, 'qTraded': 2400.0, 'midPrice': '11.80', 'deltaMid': '0.000', 'qOfi': 1200.0, 'qBid': 49800}, action = HIT, price_action = ['11.79'], reward = -1.41, time = 2016-07-29 14:10:12\n", "\n", "id: 108555, date: 2016-07-29 14:58:07\n", " qBid Bid Ask qAsk\n", "0 200 11.92 11.92 22,500\n", "1 11,700 11.91 11.93 107,900\n", "2 83,000 11.90 11.94 103,600\n", "3 51,200 11.89 11.95 100,700\n", "4 81,100 11.88 NaN NaN\n", "\n", "corrected\n", " qBid Bid Ask qAsk\n", "0 11,700 11.91 11.92 22,300\n", "1 83,000 11.90 11.93 107,900\n", "2 51,200 11.89 11.94 103,600\n", "3 81,100 11.88 11.95 100,700\n", "4 54,100 11.87 NaN NaN\n", "\n", "BasicAgent.update(): position = 0.0, inputs = {'qAsk': 11200, 'spread': 1, 'qAggr': 800.0, 'qTraded': 6200.0, 'midPrice': '11.96', 'deltaMid': '0.000', 'qOfi': -2700.0, 'qBid': 8600}, action = TAKE, price_action = ['11.96'], reward = -16.42, time = 2016-07-29 15:10:12\n", "\n", "BasicAgent.update(): position = 0.0, inputs = {'qAsk': 6600, 'spread': 1, 'qAggr': 0.0, 'qTraded': 0.0, 'midPrice': '11.92', 'deltaMid': '0.000', 'qOfi': 400.0, 'qBid': 14100}, action = BEST_BOTH, price_action = ['11.70', '11.81', '12.02'], reward = 0.0, time = 2016-07-29 16:10:12\n", "\n", "Environment.step(): Market closed at 16:30:00! MidPrice = 11.92. Trial aborted.\n", "\n", "Simulator.run(): Trial 6\n", "Environment.reset(): Trial set up to use 20160801.csv file\n", "BasicAgent.update(): position = 0, inputs = {'qAsk': 4300, 'spread': 1, 'qAggr': 0.0, 'qTraded': 0.0, 'midPrice': '11.90', 'deltaMid': '0.000', 'qOfi': 0.0, 'qBid': 52400}, action = BEST_BOTH, price_action = ['11.79', '12.00'], reward = 0.0, time = 2016-08-01 10:10:00\n", "\n", "BasicAgent.update(): position = 100.0, inputs = {'qAsk': 7400, 'spread': 1, 'qAggr': -89600.0, 'qTraded': 89600.0, 'midPrice': '11.80', 'deltaMid': '-0.010', 'qOfi': -131700.0, 'qBid': 17000}, action = BUY, price_action = ['11.79'], reward = 0.59, time = 2016-08-01 10:31:15\n", "\n", "BasicAgent.update(): position = 0.0, inputs = {'qAsk': 23900, 'spread': 1, 'qAggr': -46900.0, 'qTraded': 51700.0, 'midPrice': '11.64', 'deltaMid': '-0.010', 'qOfi': -73500.0, 'qBid': 31800}, action = HIT, price_action = ['11.63'], reward = -17.41, time = 2016-08-01 11:31:15\n", "\n", "BasicAgent.update(): position = 0.0, inputs = {'qAsk': 16400, 'spread': 1, 'qAggr': -100.0, 'qTraded': 100.0, 'midPrice': '11.57', 'deltaMid': '0.000', 'qOfi': -15400.0, 'qBid': 5000}, action = None, price_action = ['12.00'], reward = 0.0, time = 2016-08-01 12:31:16\n", "\n", "BasicAgent.update(): position = 0.0, inputs = {'qAsk': 16400, 'spread': 1, 'qAggr': 0.0, 'qTraded': 0.0, 'midPrice': '11.50', 'deltaMid': '0.000', 'qOfi': -7000.0, 'qBid': 105400}, action = BEST_BID, price_action = ['11.39'], reward = 0.0, time = 2016-08-01 13:31:16\n", "\n", "BasicAgent.update(): position = 0.0, inputs = {'qAsk': 11600, 'spread': 1, 'qAggr': -4900.0, 'qTraded': 4900.0, 'midPrice': '11.52', 'deltaMid': '0.000', 'qOfi': -2400.0, 'qBid': 17600}, action = BEST_BOTH, price_action = ['11.39', '11.41', '11.62'], reward = 0.0, time = 2016-08-01 14:31:17\n", "\n", "BasicAgent.update(): position = -100.0, inputs = {'qAsk': 14400, 'spread': 1, 'qAggr': -700.0, 'qTraded': 700.0, 'midPrice': '11.48', 'deltaMid': '0.000', 'qOfi': 5700.0, 'qBid': 129300}, action = HIT, price_action = ['11.47'], reward = -1.4, time = 2016-08-01 15:31:17\n", "\n", "BasicAgent.update(): position = 0.0, inputs = {'qAsk': 23500, 'spread': 1, 'qAggr': -23900.0, 'qTraded': 26100.0, 'midPrice': '11.42', 'deltaMid': '-0.010', 'qOfi': 25200.0, 'qBid': 74600}, action = BUY, price_action = ['11.41'], reward = 6.6, time = 2016-08-01 15:52:58\n", "\n", "Environment.step(): Market closed at 16:30:00! MidPrice = 11.24. Trial aborted.\n", "\n", "Simulator.run(): Trial 7\n", "Environment.reset(): Trial set up to use 20160802.csv file\n", "BasicAgent.update(): position = 0, inputs = {'qAsk': 16100, 'spread': 2, 'qAggr': 0.0, 'qTraded': 0.0, 'midPrice': '11.34', 'deltaMid': '0.000', 'qOfi': 0.0, 'qBid': 12900}, action = BEST_BID, price_action = ['11.23'], reward = 0.0, time = 2016-08-02 10:10:00\n", "\n", "BasicAgent.update(): position = 0, inputs = {'qAsk': 7600, 'spread': 1, 'qAggr': -6400.0, 'qTraded': 8800.0, 'midPrice': '11.36', 'deltaMid': '0.000', 'qOfi': 48600.0, 'qBid': 11100}, action = None, price_action = [], reward = 0, time = 2016-08-02 11:10:01\n", "\n", "BasicAgent.update(): position = 100.0, inputs = {'qAsk': 10900, 'spread': 1, 'qAggr': -800.0, 'qTraded': 33000.0, 'midPrice': '11.24', 'deltaMid': '-0.010', 'qOfi': 10400.0, 'qBid': 27700}, action = BUY, price_action = ['11.23'], reward = 0.61, time = 2016-08-02 11:52:08\n", "\n", "BasicAgent.update(): position = 100.0, inputs = {'qAsk': 21500, 'spread': 2, 'qAggr': -80600.0, 'qTraded': 80600.0, 'midPrice': '11.24', 'deltaMid': '-0.015', 'qOfi': -84400.0, 'qBid': 55800}, action = BEST_BID, price_action = ['11.13'], reward = 0.0, time = 2016-08-02 12:52:08\n", "\n", "BasicAgent.update(): position = 100.0, inputs = {'qAsk': 7400, 'spread': 1, 'qAggr': -3500.0, 'qTraded': 6500.0, 'midPrice': '11.24', 'deltaMid': '0.000', 'qOfi': -30800.0, 'qBid': 6800}, action = BEST_BID, price_action = ['11.13', '11.13'], reward = 0.0, time = 2016-08-02 13:52:11\n", "\n", "BasicAgent.update(): position = 200.0, inputs = {'qAsk': 14500, 'spread': 2, 'qAggr': -24400.0, 'qTraded': 29800.0, 'midPrice': '11.14', 'deltaMid': '-0.005', 'qOfi': -72700.0, 'qBid': 14100}, action = BUY, price_action = ['11.13'], reward = -9.39, time = 2016-08-02 14:10:38\n", "\n", "BasicAgent.update(): position = 200.0, inputs = {'qAsk': 6600, 'spread': 1, 'qAggr': 1400.0, 'qTraded': 10200.0, 'midPrice': '11.23', 'deltaMid': '0.000', 'qOfi': -10300.0, 'qBid': 53100}, action = None, price_action = [], reward = 0, time = 2016-08-02 15:10:38\n", "\n", "BasicAgent.update(): position = 200.0, inputs = {'qAsk': 7700, 'spread': 1, 'qAggr': -15000.0, 'qTraded': 16600.0, 'midPrice': '11.36', 'deltaMid': '-0.010', 'qOfi': -36700.0, 'qBid': 13700}, action = None, price_action = [], reward = 0, time = 2016-08-02 16:10:39\n", "\n", "id: 112762, date: 2016-08-02 16:34:54\n", " qBid Bid Ask qAsk\n", "0 6,600 11.33 11.33 2,600\n", "1 18,700 11.32 11.34 27,900\n", "2 13,700 11.31 11.35 45,600\n", "3 100 11.30 11.36 61,800\n", "4 53,900 11.29 11.37 59,800\n", "\n", "corrected\n", " qBid Bid Ask qAsk\n", "0 4,000 11.33 11.34 27,900\n", "1 18,700 11.32 11.35 45,600\n", "2 13,700 11.31 11.36 61,800\n", "3 100 11.30 11.37 59,800\n", "4 53,900 11.29 11.38 20,000\n", "\n", "id: 112763, date: 2016-08-02 16:35:02\n", " qBid Bid Ask qAsk\n", "0 4,000 11.33 11.33 2,700\n", "1 18,700 11.32 11.34 27,900\n", "2 13,700 11.31 11.35 45,600\n", "3 100 11.30 11.36 61,800\n", "4 53,900 11.29 11.37 59,800\n", "\n", "corrected\n", " qBid Bid Ask qAsk\n", "0 1,300 11.33 11.34 27,900\n", "1 18,700 11.32 11.35 45,600\n", "2 13,700 11.31 11.36 61,800\n", "3 100 11.30 11.37 59,800\n", "4 53,900 11.29 11.38 20,000\n", "\n", "id: 112764, date: 2016-08-02 16:35:04\n", " qBid Bid Ask qAsk\n", "0 1,300 11.33 11.33 4,700\n", "1 18,700 11.32 11.34 27,900\n", "2 13,700 11.31 11.35 45,600\n", "3 100 11.30 11.36 61,800\n", "4 53,900 11.29 11.37 59,800\n", "\n", "corrected\n", " qBid Bid Ask qAsk\n", "0 18,700 11.32 11.33 3,400\n", "1 13,700 11.31 11.34 27,900\n", "2 100 11.30 11.35 45,600\n", "3 53,900 11.29 11.36 61,800\n", "4 7,100 11.28 11.37 59,800\n", "\n", "id: 112765, date: 2016-08-02 16:35:08\n", " qBid Bid Ask qAsk\n", "0 8,600 11.33 11.33 3,400\n", "1 18,700 11.32 11.34 27,900\n", "2 13,700 11.31 11.35 45,600\n", "3 100 11.30 11.36 61,800\n", "4 53,900 11.29 11.37 59,800\n", "\n", "corrected\n", " qBid Bid Ask qAsk\n", "0 5,200 11.33 11.34 27,900\n", "1 18,700 11.32 11.35 45,600\n", "2 13,700 11.31 11.36 61,800\n", "3 100 11.30 11.37 59,800\n", "4 53,900 11.29 11.38 20,000\n", "\n", "id: 112781, date: 2016-08-02 16:35:44\n", " qBid Bid Ask qAsk\n", "0 13,400 11.33 11.33 5,900\n", "1 18,700 11.32 11.34 27,900\n", "2 13,700 11.31 11.35 45,600\n", "3 100 11.30 11.36 61,800\n", "4 53,900 11.29 11.37 59,800\n", "\n", "corrected\n", " qBid Bid Ask qAsk\n", "0 7,500 11.33 11.34 27,900\n", "1 18,700 11.32 11.35 45,600\n", "2 13,700 11.31 11.36 61,800\n", "3 100 11.30 11.37 59,800\n", "4 53,900 11.29 11.38 20,000\n", "\n", "id: 112803, date: 2016-08-02 16:36:09\n", " qBid Bid Ask qAsk\n", "0 7,500 11.33 11.33 7,100\n", "1 18,700 11.32 11.34 27,900\n", "2 13,700 11.31 11.35 45,600\n", "3 100 11.30 11.36 61,800\n", "4 53,900 11.29 11.37 59,800\n", "\n", "corrected\n", " qBid Bid Ask qAsk\n", "0 400 11.33 11.34 27,900\n", "1 18,700 11.32 11.35 45,600\n", "2 13,700 11.31 11.36 61,800\n", "3 100 11.30 11.37 59,800\n", "4 53,900 11.29 11.38 20,000\n", "\n", "id: 112805, date: 2016-08-02 16:36:13\n", " qBid Bid Ask qAsk\n", "0 19,900 11.33 11.33 8,100\n", "1 18,700 11.32 11.34 27,900\n", "2 13,700 11.31 11.35 45,600\n", "3 100 11.30 11.36 61,800\n", "4 53,900 11.29 11.37 59,800\n", "\n", "corrected\n", " qBid Bid Ask qAsk\n", "0 11,800 11.33 11.34 27,900\n", "1 18,700 11.32 11.35 45,600\n", "2 13,700 11.31 11.36 61,800\n", "3 100 11.30 11.37 59,800\n", "4 53,900 11.29 11.38 20,000\n", "\n", "id: 112806, date: 2016-08-02 16:36:14\n", " qBid Bid Ask qAsk\n", "0 11,800 11.33 11.33 8,300\n", "1 18,700 11.32 11.34 27,900\n", "2 13,700 11.31 11.35 45,600\n", "3 100 11.30 11.36 61,800\n", "4 53,900 11.29 11.37 59,800\n", "\n", "corrected\n", " qBid Bid Ask qAsk\n", "0 3,500 11.33 11.34 27,900\n", "1 18,700 11.32 11.35 45,600\n", "2 13,700 11.31 11.36 61,800\n", "3 100 11.30 11.37 59,800\n", "4 53,900 11.29 11.38 20,000\n", "\n", "id: 112807, date: 2016-08-02 16:36:15\n", " qBid Bid Ask qAsk\n", "0 3,500 11.33 11.32 600\n", "1 18,700 11.32 11.34 27,900\n", "2 13,700 11.31 11.35 45,600\n", "3 100 11.30 11.36 61,800\n", "4 53,900 11.29 11.37 59,800\n", "\n", "corrected\n", " qBid Bid Ask qAsk\n", "0 2,900 11.33 11.34 27,900\n", "1 18,700 11.32 11.35 45,600\n", "2 13,700 11.31 11.36 61,800\n", "3 100 11.30 11.37 59,800\n", "4 53,900 11.29 11.38 20,000\n", "\n", "id: 112808, date: 2016-08-02 16:36:25\n", " qBid Bid Ask qAsk\n", "0 300 11.40 11.34 27,900\n", "1 2,900 11.33 11.35 45,600\n", "2 18,700 11.32 11.36 61,800\n", "3 13,700 11.31 11.37 59,800\n", "4 100 11.30 11.38 20,000\n", "\n", "corrected\n", " qBid Bid Ask qAsk\n", "0 2,900 11.33 11.34 27,600\n", "1 18,700 11.32 11.35 45,600\n", "2 13,700 11.31 11.36 61,800\n", "3 100 11.30 11.37 59,800\n", "4 53,900 11.29 11.38 20,000\n", "\n", "id: 112811, date: 2016-08-02 16:37:18\n", " qBid Bid Ask qAsk\n", "0 2,900 11.33 11.30 1,700\n", "1 18,700 11.32 11.34 27,600\n", "2 13,700 11.31 11.35 45,600\n", "3 100 11.30 11.36 61,800\n", "4 53,900 11.29 11.37 59,800\n", "\n", "corrected\n", " qBid Bid Ask qAsk\n", "0 1,200 11.33 11.34 27,600\n", "1 18,700 11.32 11.35 45,600\n", "2 13,700 11.31 11.36 61,800\n", "3 100 11.30 11.37 59,800\n", "4 53,900 11.29 11.38 20,000\n", "\n", "id: 112813, date: 2016-08-02 16:37:56\n", " qBid Bid Ask qAsk\n", "0 1,200 11.33 11.30 2,000\n", "1 18,700 11.32 11.34 27,600\n", "2 13,700 11.31 11.35 45,600\n", "3 100 11.30 11.36 61,800\n", "4 53,900 11.29 11.37 59,800\n", "\n", "corrected\n", " qBid Bid Ask qAsk\n", "0 18,700 11.32 11.30 800\n", "1 13,700 11.31 11.34 27,600\n", "2 100 11.30 11.35 45,600\n", "3 53,900 11.29 11.36 61,800\n", "4 7,100 11.28 11.37 59,800\n", "\n", "id: 112813, date: 2016-08-02 16:37:56\n", " qBid Bid Ask qAsk\n", "0 18,700 11.32 11.30 800\n", "1 13,700 11.31 11.34 27,600\n", "2 100 11.30 11.35 45,600\n", "3 53,900 11.29 11.36 61,800\n", "4 7,100 11.28 11.37 59,800\n", "\n", "corrected\n", " qBid Bid Ask qAsk\n", "0 17,900 11.32 11.34 27,600\n", "1 13,700 11.31 11.35 45,600\n", "2 100 11.30 11.36 61,800\n", "3 53,900 11.29 11.37 59,800\n", "4 7,100 11.28 11.38 20,000\n", "\n", "id: 112930, date: 2016-08-02 17:10:08\n", " qBid Bid Ask qAsk\n", "0 17,900 11.32 11.00 200\n", "1 13,700 11.31 11.34 27,600\n", "2 100 11.30 11.35 45,600\n", "3 53,900 11.29 11.36 61,800\n", "4 7,100 11.28 11.37 59,800\n", "\n", "Environment.step(): Market closed at 16:30:00! MidPrice = 11.34. Trial aborted.\n", "\n", "Simulator.run(): Trial 8\n", "Environment.reset(): Trial set up to use 20160803.csv file\n", "corrected\n", "Empty DataFrame\n", "Columns: [qBid, Bid, Ask, qAsk]\n", "Index: []\n", "\n", "Environment.step(): Market closed at 16:30:00! MidPrice = 0.00. Trial aborted.\n", "\n", "Simulator.run(): Trial 9\n", "Environment.reset(): Trial set up to use 20160804.csv file\n", "BasicAgent.update(): position = 0, inputs = {'qAsk': 9400, 'spread': 1, 'qAggr': 0.0, 'qTraded': 0.0, 'midPrice': '11.96', 'deltaMid': '0.000', 'qOfi': 0.0, 'qBid': 13500}, action = BEST_BOTH, price_action = ['11.85', '12.06'], reward = 0.0, time = 2016-08-04 10:10:00\n", "\n", "BasicAgent.update(): position = -100, inputs = {'qAsk': 11300, 'spread': 1, 'qAggr': 173800.0, 'qTraded': 189600.0, 'midPrice': '12.06', 'deltaMid': '0.010', 'qOfi': 206000.0, 'qBid': 27400}, action = SELL, price_action = ['12.06'], reward = -0.42, time = 2016-08-04 10:15:06\n", "\n", "id: 3169, date: 2016-08-04 10:15:06\n", " qBid Bid Ask qAsk\n", "0 23,700 12.06 12.06 100\n", "1 27,400 12.05 NaN NaN\n", "2 11,700 12.04 NaN NaN\n", "3 146,600 12.03 NaN NaN\n", "4 26,700 12.02 NaN NaN\n", "\n", "corrected\n", " qBid Bid Ask qAsk\n", "0 23,600 12.06 NaN NaN\n", "1 27,400 12.05 NaN NaN\n", "2 11,700 12.04 NaN NaN\n", "3 146,600 12.03 NaN NaN\n", "4 26,700 12.02 NaN NaN\n", "\n", "BasicAgent.update(): position = -100, inputs = {'qAsk': 40600, 'spread': 1, 'qAggr': 300.0, 'qTraded': 300.0, 'midPrice': '11.90', 'deltaMid': '0.000', 'qOfi': 300.0, 'qBid': 46400}, action = BEST_BID, price_action = ['11.85', '11.80'], reward = 16.0, time = 2016-08-04 11:15:06\n", "\n", "BasicAgent.update(): position = -100, inputs = {'qAsk': 46800, 'spread': 1, 'qAggr': 0.0, 'qTraded': 0.0, 'midPrice': '11.98', 'deltaMid': '0.000', 'qOfi': -7200.0, 'qBid': 8300}, action = BEST_BID, price_action = ['11.80', '11.87'], reward = -8.0, time = 2016-08-04 12:15:06\n", "\n", "BasicAgent.update(): position = -100, inputs = {'qAsk': 13000, 'spread': 1, 'qAggr': 2200.0, 'qTraded': 2200.0, 'midPrice': '12.07', 'deltaMid': '0.000', 'qOfi': 5300.0, 'qBid': 12100}, action = BEST_BOTH, price_action = ['11.87', '11.96', '12.17'], reward = -9.0, time = 2016-08-04 13:15:06\n", "\n", "BasicAgent.update(): position = -200.0, inputs = {'qAsk': 9800, 'spread': 1, 'qAggr': -16500.0, 'qTraded': 30300.0, 'midPrice': '12.04', 'deltaMid': '0.000', 'qOfi': -61600.0, 'qBid': 18200}, action = HIT, price_action = ['12.03'], reward = 1.58, time = 2016-08-04 14:15:06\n", "\n", "id: 107887, date: 2016-08-04 15:08:10\n", " qBid Bid Ask qAsk\n", "0 49,600 12.09 12.09 100\n", "1 100 12.08 12.10 311,700\n", "2 42,800 12.07 12.11 99,700\n", "3 100 12.06 12.12 279,000\n", "4 24,900 12.05 12.17 100\n", "\n", "corrected\n", " qBid Bid Ask qAsk\n", "0 49,500 12.09 12.10 311,700\n", "1 100 12.08 12.11 99,700\n", "2 42,800 12.07 12.12 279,000\n", "3 100 12.06 12.17 100\n", "4 24,900 12.05 NaN NaN\n", "\n", "BasicAgent.update(): position = -200.0, inputs = {'qAsk': 25000, 'spread': 1, 'qAggr': 100.0, 'qTraded': 100.0, 'midPrice': '12.08', 'deltaMid': '0.000', 'qOfi': -1600.0, 'qBid': 15900}, action = None, price_action = [], reward = 0, time = 2016-08-04 15:15:07\n", "\n", "id: 114962, date: 2016-08-04 15:28:04\n", " qBid Bid Ask qAsk\n", "0 100 12.05 12.05 5,400\n", "1 139,900 12.04 12.06 15,400\n", "2 47,600 12.03 12.07 57,900\n", "3 16,500 12.02 12.08 24,500\n", "4 100 12.01 12.09 38,000\n", "\n", "corrected\n", " qBid Bid Ask qAsk\n", "0 139,900 12.04 12.05 5,300\n", "1 47,600 12.03 12.06 15,400\n", "2 16,500 12.02 12.07 57,900\n", "3 100 12.01 12.08 24,500\n", "4 20,900 12.00 12.09 38,000\n", "\n", "BasicAgent.update(): position = -100.0, inputs = {'qAsk': 5200, 'spread': 1, 'qAggr': -159200.0, 'qTraded': 181400.0, 'midPrice': '11.96', 'deltaMid': '-0.050', 'qOfi': -114400.0, 'qBid': 95000}, action = BUY, price_action = ['11.96'], reward = 15.58, time = 2016-08-04 15:32:58\n", "\n", "BasicAgent.update(): position = -100.0, inputs = {'qAsk': 9100, 'spread': 1, 'qAggr': 0.0, 'qTraded': 0.0, 'midPrice': '12.00', 'deltaMid': '0.000', 'qOfi': 0.0, 'qBid': 33500}, action = None, price_action = ['12.17'], reward = -4.0, time = 2016-08-04 16:33:00\n", "\n", "Environment.step(): Market closed at 16:30:00! MidPrice = 11.98. Trial aborted.\n", "\n", "Simulator.run(): Trial 10\n", "Environment.reset(): Trial set up to use 20160805.csv file\n", "BasicAgent.update(): position = 0, inputs = {'qAsk': 67900, 'spread': 1, 'qAggr': -300.0, 'qTraded': 300.0, 'midPrice': '12.11', 'deltaMid': '12.115', 'qOfi': 100.0, 'qBid': 100}, action = None, price_action = [], reward = 0, time = 2016-08-05 10:10:22\n", "\n", "BasicAgent.update(): position = 0, inputs = {'qAsk': 89700, 'spread': 1, 'qAggr': 1200.0, 'qTraded': 1200.0, 'midPrice': '11.86', 'deltaMid': '0.000', 'qOfi': 1100.0, 'qBid': 15000}, action = None, price_action = [], reward = 0, time = 2016-08-05 11:10:22\n", "\n", "BasicAgent.update(): position = 0, inputs = {'qAsk': 10100, 'spread': 1, 'qAggr': 1000.0, 'qTraded': 1000.0, 'midPrice': '11.84', 'deltaMid': '0.000', 'qOfi': 4300.0, 'qBid': 36200}, action = None, price_action = [], reward = 0, time = 2016-08-05 12:10:22\n", "\n", "BasicAgent.update(): position = 0, inputs = {'qAsk': 5900, 'spread': 1, 'qAggr': -1800.0, 'qTraded': 1800.0, 'midPrice': '11.84', 'deltaMid': '-0.010', 'qOfi': -23500.0, 'qBid': 46700}, action = BEST_BOTH, price_action = ['11.73', '11.94'], reward = 0.0, time = 2016-08-05 13:10:22\n", "\n", "id: 61813, date: 2016-08-05 13:37:24\n", " qBid Bid Ask qAsk\n", "0 100 11.80 11.79 8,100\n", "1 12,400 11.78 11.80 25,900\n", "2 100 11.73 11.81 12,900\n", "\n", "corrected\n", " qBid Bid Ask qAsk\n", "0 12,400 11.78 11.79 8,000\n", "1 100 11.73 11.80 25,900\n", "\n", "BasicAgent.update(): position = 0, inputs = {'qAsk': 12100, 'spread': 1, 'qAggr': 0.0, 'qTraded': 0.0, 'midPrice': '11.78', 'deltaMid': '0.000', 'qOfi': 100.0, 'qBid': 60000}, action = None, price_action = ['11.73', '11.94'], reward = 0.0, time = 2016-08-05 14:10:24\n", "\n", "BasicAgent.update(): position = 0, inputs = {'qAsk': 17100, 'spread': 1, 'qAggr': 1200.0, 'qTraded': 1200.0, 'midPrice': '11.80', 'deltaMid': '0.000', 'qOfi': 5700.0, 'qBid': 28800}, action = BEST_BID, price_action = ['11.69'], reward = 0.0, time = 2016-08-05 15:10:24\n", "\n", "BasicAgent.update(): position = -100.0, inputs = {'qAsk': 39300, 'spread': 1, 'qAggr': -900.0, 'qTraded': 3900.0, 'midPrice': '11.73', 'deltaMid': '0.000', 'qOfi': -1000.0, 'qBid': 48900}, action = HIT, price_action = ['11.72'], reward = -1.41, time = 2016-08-05 16:10:24\n", "\n", "BasicAgent.update(): position = 0.0, inputs = {'qAsk': 27000, 'spread': 1, 'qAggr': 12200.0, 'qTraded': 67400.0, 'midPrice': '11.70', 'deltaMid': '0.000', 'qOfi': 13700.0, 'qBid': 77900}, action = BUY, price_action = ['11.69'], reward = 3.59, time = 2016-08-05 16:49:09\n", "\n", "Environment.step(): Market closed at 16:30:00! MidPrice = 11.69. Trial aborted.\n", "\n", "Simulator.run(): Trial 11\n", "Environment.reset(): Trial set up to use 20160808.csv file\n", "BasicAgent.update(): position = -100.0, inputs = {'qAsk': 16600, 'spread': 1, 'qAggr': 0.0, 'qTraded': 0.0, 'midPrice': '11.76', 'deltaMid': '0.000', 'qOfi': 0.0, 'qBid': 22100}, action = HIT, price_action = ['11.75'], reward = -1.41, time = 2016-08-08 10:10:00\n", "\n", "BasicAgent.update(): position = -100.0, inputs = {'qAsk': 102400, 'spread': 1, 'qAggr': 0.0, 'qTraded': 0.0, 'midPrice': '11.94', 'deltaMid': '0.000', 'qOfi': 0.0, 'qBid': 36300}, action = None, price_action = [], reward = 0, time = 2016-08-08 11:10:00\n", "\n", "BasicAgent.update(): position = -100.0, inputs = {'qAsk': 30000, 'spread': 1, 'qAggr': 1100.0, 'qTraded': 1100.0, 'midPrice': '11.92', 'deltaMid': '0.000', 'qOfi': 500.0, 'qBid': 9500}, action = BEST_BOTH, price_action = ['11.82', '12.03'], reward = -16.0, time = 2016-08-08 12:10:04\n", "\n", "BasicAgent.update(): position = -100.0, inputs = {'qAsk': 16300, 'spread': 1, 'qAggr': 0.0, 'qTraded': 0.0, 'midPrice': '11.92', 'deltaMid': '0.000', 'qOfi': 100.0, 'qBid': 3400}, action = BEST_BID, price_action = ['12.03', '11.82', '11.81'], reward = 0.0, time = 2016-08-08 13:10:05\n", "\n", "id: 57769, date: 2016-08-08 13:24:23\n", " qBid Bid Ask qAsk\n", "0 800 11.91 11.91 100\n", "1 63,300 11.90 11.92 24,600\n", "2 23,000 11.89 11.93 12,700\n", "3 79,900 11.88 11.94 67,000\n", "4 11,600 11.87 11.95 13,900\n", "\n", "corrected\n", " qBid Bid Ask qAsk\n", "0 700 11.91 11.92 24,600\n", "1 63,300 11.90 11.93 12,700\n", "2 23,000 11.89 11.94 67,000\n", "3 79,900 11.88 11.95 13,900\n", "4 11,600 11.87 11.96 64,800\n", "\n", "BasicAgent.update(): position = -100.0, inputs = {'qAsk': 39100, 'spread': 1, 'qAggr': -3600.0, 'qTraded': 3600.0, 'midPrice': '11.90', 'deltaMid': '0.000', 'qOfi': -35700.0, 'qBid': 36000}, action = None, price_action = ['11.81'], reward = 2.0, time = 2016-08-08 14:10:05\n", "\n", "BasicAgent.update(): position = -100.0, inputs = {'qAsk': 5300, 'spread': 1, 'qAggr': 8500.0, 'qTraded': 8500.0, 'midPrice': '11.94', 'deltaMid': '0.000', 'qOfi': 12100.0, 'qBid': 53700}, action = BEST_BOTH, price_action = ['11.84', '12.05'], reward = -4.0, time = 2016-08-08 15:10:05\n", "\n", "BasicAgent.update(): position = -200.0, inputs = {'qAsk': 244800, 'spread': 1, 'qAggr': 12900.0, 'qTraded': 12900.0, 'midPrice': '11.94', 'deltaMid': '0.005', 'qOfi': 21500.0, 'qBid': 28100}, action = HIT, price_action = ['11.94'], reward = -0.42, time = 2016-08-08 16:10:07\n", "\n", "Environment.step(): Market closed at 16:30:00! MidPrice = 11.89. Trial aborted.\n", "\n", "Simulator.run(): Trial 12\n", "Environment.reset(): Trial set up to use 20160809.csv file\n", "BasicAgent.update(): position = 0, inputs = {'qAsk': 13200, 'spread': 1, 'qAggr': 0.0, 'qTraded': 0.0, 'midPrice': '11.93', 'deltaMid': '0.000', 'qOfi': 0.0, 'qBid': 20300}, action = BEST_BOTH, price_action = ['11.83', '12.04'], reward = 0.0, time = 2016-08-09 10:10:00\n", "\n", "BasicAgent.update(): position = -100, inputs = {'qAsk': 79900, 'spread': 3, 'qAggr': 0.0, 'qTraded': 0.0, 'midPrice': '12.02', 'deltaMid': '0.000', 'qOfi': 0.0, 'qBid': 15000}, action = SELL, price_action = ['12.04'], reward = 1.58, time = 2016-08-09 10:21:20\n", "\n", "BasicAgent.update(): position = -100, inputs = {'qAsk': 6500, 'spread': 1, 'qAggr': 0.0, 'qTraded': 0.0, 'midPrice': '12.00', 'deltaMid': '0.000', 'qOfi': 0.0, 'qBid': 24300}, action = None, price_action = [], reward = 0, time = 2016-08-09 11:21:20\n", "\n", "BasicAgent.update(): position = -100, inputs = {'qAsk': 30600, 'spread': 1, 'qAggr': 0.0, 'qTraded': 0.0, 'midPrice': '11.96', 'deltaMid': '0.000', 'qOfi': 0.0, 'qBid': 49000}, action = None, price_action = [], reward = 0, time = 2016-08-09 12:21:20\n", "\n", "BasicAgent.update(): position = 0, inputs = {'qAsk': 14800, 'spread': 2, 'qAggr': 0.0, 'qTraded': 0.0, 'midPrice': '11.84', 'deltaMid': '0.000', 'qOfi': 0.0, 'qBid': 77400}, action = BUY, price_action = ['11.83'], reward = 18.59, time = 2016-08-09 12:47:50\n", "\n", "BasicAgent.update(): position = 0, inputs = {'qAsk': 60000, 'spread': 1, 'qAggr': 0.0, 'qTraded': 0.0, 'midPrice': '11.77', 'deltaMid': '0.000', 'qOfi': 0.0, 'qBid': 62400}, action = None, price_action = [], reward = 0, time = 2016-08-09 13:47:50\n", "\n", "BasicAgent.update(): position = -100.0, inputs = {'qAsk': 48900, 'spread': 1, 'qAggr': 900.0, 'qTraded': 900.0, 'midPrice': '11.82', 'deltaMid': '0.000', 'qOfi': 1400.0, 'qBid': 43000}, action = HIT, price_action = ['11.82'], reward = -0.41, time = 2016-08-09 14:47:52\n", "\n", "BasicAgent.update(): position = 0.0, inputs = {'qAsk': 25000, 'spread': 1, 'qAggr': 100.0, 'qTraded': 100.0, 'midPrice': '11.82', 'deltaMid': '0.000', 'qOfi': 0.0, 'qBid': 48500}, action = TAKE, price_action = ['11.83'], reward = -1.41, time = 2016-08-09 15:47:52\n", "\n", "BasicAgent.update(): position = 100.0, inputs = {'qAsk': 78300, 'spread': 1, 'qAggr': 600.0, 'qTraded': 600.0, 'midPrice': '11.86', 'deltaMid': '0.000', 'qOfi': 400.0, 'qBid': 12700}, action = TAKE, price_action = ['11.87'], reward = -1.42, time = 2016-08-09 16:47:52\n", "\n", "Environment.step(): Market closed at 16:30:00! MidPrice = 11.87. Trial aborted.\n", "\n", "Simulator.run(): Trial 13\n", "Environment.reset(): Trial set up to use 20160810.csv file\n", "BasicAgent.update(): position = 0, inputs = {'qAsk': 7800, 'spread': 1, 'qAggr': -2000.0, 'qTraded': 2000.0, 'midPrice': '11.94', 'deltaMid': '11.945', 'qOfi': -2000.0, 'qBid': 3000}, action = BEST_BID, price_action = ['11.84'], reward = 0.0, time = 2016-08-10 10:10:11\n", "\n", "BasicAgent.update(): position = 100, inputs = {'qAsk': 28000, 'spread': 1, 'qAggr': -5600.0, 'qTraded': 7800.0, 'midPrice': '11.84', 'deltaMid': '-0.010', 'qOfi': -76300.0, 'qBid': 20100}, action = BUY, price_action = ['11.84'], reward = -0.41, time = 2016-08-10 10:41:43\n", "\n", "BasicAgent.update(): position = 100, inputs = {'qAsk': 8500, 'spread': 1, 'qAggr': -4000.0, 'qTraded': 4000.0, 'midPrice': '11.74', 'deltaMid': '0.000', 'qOfi': -10700.0, 'qBid': 33300}, action = BEST_BOTH, price_action = ['11.63', '11.84'], reward = -10.0, time = 2016-08-10 11:41:46\n", "\n", "BasicAgent.update(): position = 200.0, inputs = {'qAsk': 300, 'spread': 1, 'qAggr': -99000.0, 'qTraded': 104200.0, 'midPrice': '11.64', 'deltaMid': '-0.020', 'qOfi': -75400.0, 'qBid': 58700}, action = BUY, price_action = ['11.63'], reward = -9.41, time = 2016-08-10 12:11:55\n", "\n", "BasicAgent.update(): position = 200.0, inputs = {'qAsk': 23200, 'spread': 1, 'qAggr': 100.0, 'qTraded': 100.0, 'midPrice': '11.68', 'deltaMid': '0.000', 'qOfi': 2200.0, 'qBid': 56500}, action = BEST_BOTH, price_action = ['11.58', '11.84', '11.79'], reward = 8.0, time = 2016-08-10 13:11:55\n", "\n", "BasicAgent.update(): position = 200.0, inputs = {'qAsk': 9300, 'spread': 1, 'qAggr': 100.0, 'qTraded': 100.0, 'midPrice': '11.66', 'deltaMid': '0.000', 'qOfi': 36900.0, 'qBid': 52600}, action = BEST_BID, price_action = ['11.79', '11.58', '11.56'], reward = -4.0, time = 2016-08-10 14:11:56\n", "\n", "BasicAgent.update(): position = 200.0, inputs = {'qAsk': 68100, 'spread': 1, 'qAggr': -500.0, 'qTraded': 2700.0, 'midPrice': '11.77', 'deltaMid': '0.000', 'qOfi': 4000.0, 'qBid': 23600}, action = None, price_action = ['11.56'], reward = 22.0, time = 2016-08-10 15:11:57\n", "\n", "BasicAgent.update(): position = 300.0, inputs = {'qAsk': 26100, 'spread': 1, 'qAggr': -6900.0, 'qTraded': 7300.0, 'midPrice': '11.73', 'deltaMid': '0.000', 'qOfi': -21400.0, 'qBid': 43800}, action = TAKE, price_action = ['11.73'], reward = -8.41, time = 2016-08-10 16:11:57\n", "\n", "Environment.step(): Market closed at 16:30:00! MidPrice = 11.68. Trial aborted.\n", "\n", "Simulator.run(): Trial 14\n", "Environment.reset(): Trial set up to use 20160811.csv file\n", "BasicAgent.update(): position = 0, inputs = {'qAsk': 59300, 'spread': 1, 'qAggr': 0.0, 'qTraded': 0.0, 'midPrice': '11.66', 'deltaMid': '0.000', 'qOfi': 0.0, 'qBid': 10500}, action = None, price_action = [], reward = 0, time = 2016-08-11 10:10:00\n", "\n", "BasicAgent.update(): position = 0, inputs = {'qAsk': 17100, 'spread': 1, 'qAggr': 0.0, 'qTraded': 0.0, 'midPrice': '11.68', 'deltaMid': '0.000', 'qOfi': 0.0, 'qBid': 93900}, action = None, price_action = [], reward = 0, time = 2016-08-11 11:10:00\n", "\n", "BasicAgent.update(): position = -100.0, inputs = {'qAsk': 20500, 'spread': 1, 'qAggr': 300.0, 'qTraded': 300.0, 'midPrice': '11.78', 'deltaMid': '0.000', 'qOfi': 300.0, 'qBid': 7200}, action = HIT, price_action = ['11.78'], reward = -0.41, time = 2016-08-11 12:10:01\n", "\n", "BasicAgent.update(): position = -100.0, inputs = {'qAsk': 42200, 'spread': 1, 'qAggr': 0.0, 'qTraded': 0.0, 'midPrice': '11.84', 'deltaMid': '0.000', 'qOfi': 100.0, 'qBid': 1600}, action = None, price_action = [], reward = 0, time = 2016-08-11 13:10:01\n", "\n", "BasicAgent.update(): position = -100.0, inputs = {'qAsk': 14700, 'spread': 1, 'qAggr': 100.0, 'qTraded': 100.0, 'midPrice': '11.96', 'deltaMid': '0.000', 'qOfi': 100.0, 'qBid': 22300}, action = BEST_BOTH, price_action = ['11.85', '12.06'], reward = -18.0, time = 2016-08-11 14:10:01\n", "\n", "BasicAgent.update(): position = -200.0, inputs = {'qAsk': 9600, 'spread': 1, 'qAggr': 100.0, 'qTraded': 100.0, 'midPrice': '11.96', 'deltaMid': '0.000', 'qOfi': 100.0, 'qBid': 84400}, action = HIT, price_action = ['11.96'], reward = -0.42, time = 2016-08-11 15:10:01\n", "\n", "BasicAgent.update(): position = -300.0, inputs = {'qAsk': 62500, 'spread': 2, 'qAggr': 31300.0, 'qTraded': 31500.0, 'midPrice': '12.05', 'deltaMid': '0.005', 'qOfi': 12100.0, 'qBid': 40700}, action = SELL, price_action = ['12.06'], reward = -17.42, time = 2016-08-11 15:52:09\n", "\n", "Environment.step(): Market closed at 16:30:00! MidPrice = 12.07. Trial aborted.\n", "\n", "Simulator.run(): Trial 15\n", "Environment.reset(): Trial set up to use 20160812.csv file\n", "id: 1244, date: 2016-08-12 10:07:42\n", " qBid Bid Ask qAsk\n", "0 3,700 12.20 12.20 100\n", "1 20,800 12.19 12.21 13,800\n", "2 25,200 12.18 NaN NaN\n", "3 17,000 12.17 NaN NaN\n", "4 21,400 12.16 NaN NaN\n", "\n", "corrected\n", " qBid Bid Ask qAsk\n", "0 3,600 12.20 12.21 13,800\n", "1 20,800 12.19 NaN NaN\n", "2 25,200 12.18 NaN NaN\n", "3 17,000 12.17 NaN NaN\n", "4 21,400 12.16 NaN NaN\n", "\n", "BasicAgent.update(): position = -100.0, inputs = {'qAsk': 5500, 'spread': 1, 'qAggr': 0.0, 'qTraded': 0.0, 'midPrice': '12.12', 'deltaMid': '0.000', 'qOfi': 0.0, 'qBid': 13400}, action = HIT, price_action = ['12.12'], reward = -0.42, time = 2016-08-12 10:10:00\n", "\n", "id: 20005, date: 2016-08-12 10:32:36\n", " qBid Bid Ask qAsk\n", "0 6,700 12.31 12.30 200\n", "1 89,100 12.30 12.32 45,900\n", "2 6,700 12.29 NaN NaN\n", "3 14,700 12.28 NaN NaN\n", "4 75,300 12.27 NaN NaN\n", "\n", "corrected\n", " qBid Bid Ask qAsk\n", "0 6,500 12.31 12.32 45,900\n", "1 89,100 12.30 NaN NaN\n", "2 6,700 12.29 NaN NaN\n", "3 14,700 12.28 NaN NaN\n", "4 75,300 12.27 NaN NaN\n", "\n", "BasicAgent.update(): position = -100.0, inputs = {'qAsk': 100, 'spread': 1, 'qAggr': 0.0, 'qTraded': 0.0, 'midPrice': '12.32', 'deltaMid': '0.000', 'qOfi': 0.0, 'qBid': 61900}, action = None, price_action = [], reward = 0, time = 2016-08-12 11:10:00\n", "\n", "BasicAgent.update(): position = -100.0, inputs = {'qAsk': 55900, 'spread': 1, 'qAggr': 7600.0, 'qTraded': 9600.0, 'midPrice': '12.26', 'deltaMid': '0.010', 'qOfi': 81900.0, 'qBid': 8400}, action = BEST_BOTH, price_action = ['12.15', '12.36'], reward = -14.0, time = 2016-08-12 12:10:01\n", "\n", "BasicAgent.update(): position = -200.0, inputs = {'qAsk': 15800, 'spread': 1, 'qAggr': -18000.0, 'qTraded': 30200.0, 'midPrice': '12.22', 'deltaMid': '0.000', 'qOfi': 25700.0, 'qBid': 29700}, action = HIT, price_action = ['12.21'], reward = 2.57, time = 2016-08-12 13:10:01\n", "\n", "BasicAgent.update(): position = -100.0, inputs = {'qAsk': 13200, 'spread': 1, 'qAggr': -32400.0, 'qTraded': 38200.0, 'midPrice': '12.16', 'deltaMid': '-0.010', 'qOfi': -92500.0, 'qBid': 140700}, action = BUY, price_action = ['12.15'], reward = 12.57, time = 2016-08-12 13:46:58\n", "\n", "id: 111297, date: 2016-08-12 14:46:20\n", " qBid Bid Ask qAsk\n", "0 100 12.15 12.15 20,000\n", "1 55,300 12.13 12.16 69,600\n", "2 23,200 12.12 12.17 60,800\n", "3 8,000 12.11 12.18 30,300\n", "4 10,100 12.10 12.19 128,600\n", "\n", "corrected\n", " qBid Bid Ask qAsk\n", "0 55,300 12.13 12.15 19,900\n", "1 23,200 12.12 12.16 69,600\n", "2 8,000 12.11 12.17 60,800\n", "3 10,100 12.10 12.18 30,300\n", "4 34,000 12.09 12.19 128,600\n", "\n", "BasicAgent.update(): position = -100.0, inputs = {'qAsk': 46200, 'spread': 1, 'qAggr': -400.0, 'qTraded': 400.0, 'midPrice': '12.12', 'deltaMid': '0.000', 'qOfi': -12100.0, 'qBid': 20500}, action = BEST_BOTH, price_action = ['12.02', '12.36', '12.23'], reward = 4.0, time = 2016-08-12 14:46:58\n", "\n", "BasicAgent.update(): position = 0.0, inputs = {'qAsk': 76200, 'spread': 2, 'qAggr': 51900.0, 'qTraded': 53900.0, 'midPrice': '12.17', 'deltaMid': '0.005', 'qOfi': 6800.0, 'qBid': 10800}, action = TAKE, price_action = ['12.18'], reward = -6.43, time = 2016-08-12 15:46:58\n", "\n", "BasicAgent.update(): position = 100.0, inputs = {'qAsk': 18200, 'spread': 2, 'qAggr': -158400.0, 'qTraded': 165400.0, 'midPrice': '12.03', 'deltaMid': '-0.025', 'qOfi': -20700.0, 'qBid': 117000}, action = BUY, price_action = ['12.02'], reward = 0.58, time = 2016-08-12 16:31:32\n", "\n", "Environment.step(): Market closed at 16:30:00! MidPrice = 12.01. Trial aborted.\n", "\n", "Simulator.run(): Trial 16\n", "Environment.reset(): Trial set up to use 20160815.csv file\n", "BasicAgent.update(): position = 0, inputs = {'qAsk': 3100, 'spread': 1, 'qAggr': 0.0, 'qTraded': 0.0, 'midPrice': '12.16', 'deltaMid': '0.000', 'qOfi': 0.0, 'qBid': 26500}, action = None, price_action = [], reward = 0, time = 2016-08-15 10:10:00\n", "\n", "BasicAgent.update(): position = 0, inputs = {'qAsk': 99800, 'spread': 1, 'qAggr': 0.0, 'qTraded': 0.0, 'midPrice': '12.24', 'deltaMid': '0.000', 'qOfi': 0.0, 'qBid': 17100}, action = BEST_BOTH, price_action = ['12.13', '12.34'], reward = 0.0, time = 2016-08-15 11:10:00\n", "\n", "BasicAgent.update(): position = 0, inputs = {'qAsk': 24600, 'spread': 1, 'qAggr': 0.0, 'qTraded': 0.0, 'midPrice': '12.24', 'deltaMid': '0.000', 'qOfi': 0.0, 'qBid': 110500}, action = BEST_BOTH, price_action = ['12.13', '12.14', '12.34', '12.35'], reward = 0.0, time = 2016-08-15 12:10:00\n", "\n", "BasicAgent.update(): position = 0, inputs = {'qAsk': 48500, 'spread': 1, 'qAggr': 0.0, 'qTraded': 0.0, 'midPrice': '12.32', 'deltaMid': '0.000', 'qOfi': 0.0, 'qBid': 24300}, action = BEST_BID, price_action = ['12.35', '12.14', '12.22'], reward = 0.0, time = 2016-08-15 13:10:00\n", "\n", "BasicAgent.update(): position = 100.0, inputs = {'qAsk': 21100, 'spread': 1, 'qAggr': 0.0, 'qTraded': 0.0, 'midPrice': '12.30', 'deltaMid': '0.000', 'qOfi': 0.0, 'qBid': 96000}, action = TAKE, price_action = ['12.31'], reward = -1.43, time = 2016-08-15 14:10:00\n", "\n", "BasicAgent.update(): position = 0.0, inputs = {'qAsk': 16100, 'spread': 1, 'qAggr': 0.0, 'qTraded': 0.0, 'midPrice': '12.27', 'deltaMid': '0.000', 'qOfi': 0.0, 'qBid': 7000}, action = HIT, price_action = ['12.27'], reward = -3.43, time = 2016-08-15 15:10:00\n", "\n", "BasicAgent.update(): position = 0.0, inputs = {'qAsk': 60100, 'spread': 1, 'qAggr': 0.0, 'qTraded': 0.0, 'midPrice': '12.30', 'deltaMid': '0.000', 'qOfi': 0.0, 'qBid': 9600}, action = BEST_BID, price_action = ['12.22', '12.20'], reward = 0.0, time = 2016-08-15 16:10:00\n", "\n", "Environment.step(): Market closed at 16:30:00! MidPrice = 12.29. Trial aborted.\n", "\n", "Simulator.run(): Trial 17\n", "Environment.reset(): Trial set up to use 20160816.csv file\n", "BasicAgent.update(): position = -100.0, inputs = {'qAsk': 11500, 'spread': 1, 'qAggr': 0.0, 'qTraded': 0.0, 'midPrice': '12.30', 'deltaMid': '0.000', 'qOfi': 0.0, 'qBid': 19600}, action = HIT, price_action = ['12.29'], reward = -1.43, time = 2016-08-16 10:10:00\n", "\n", "BasicAgent.update(): position = -100.0, inputs = {'qAsk': 13100, 'spread': 1, 'qAggr': 0.0, 'qTraded': 0.0, 'midPrice': '12.36', 'deltaMid': '0.000', 'qOfi': 0.0, 'qBid': 6500}, action = None, price_action = [], reward = 0, time = 2016-08-16 11:10:00\n", "\n", "BasicAgent.update(): position = -100.0, inputs = {'qAsk': 27400, 'spread': 1, 'qAggr': -3600.0, 'qTraded': 3600.0, 'midPrice': '12.32', 'deltaMid': '0.000', 'qOfi': -900.0, 'qBid': 6400}, action = None, price_action = [], reward = 0, time = 2016-08-16 12:10:01\n", "\n", "BasicAgent.update(): position = -100.0, inputs = {'qAsk': 139500, 'spread': 1, 'qAggr': -3300.0, 'qTraded': 3300.0, 'midPrice': '12.44', 'deltaMid': '0.000', 'qOfi': 100.0, 'qBid': 7300}, action = None, price_action = [], reward = 0, time = 2016-08-16 13:10:01\n", "\n", "BasicAgent.update(): position = -100.0, inputs = {'qAsk': 96200, 'spread': 1, 'qAggr': 0.0, 'qTraded': 0.0, 'midPrice': '12.48', 'deltaMid': '0.000', 'qOfi': 5000.0, 'qBid': 40600}, action = None, price_action = [], reward = 0, time = 2016-08-16 14:10:01\n", "\n", "BasicAgent.update(): position = -200.0, inputs = {'qAsk': 61700, 'spread': 1, 'qAggr': -100.0, 'qTraded': 100.0, 'midPrice': '12.52', 'deltaMid': '0.000', 'qOfi': -100.0, 'qBid': 40000}, action = HIT, price_action = ['12.52'], reward = -22.44, time = 2016-08-16 15:10:01\n", "\n", "BasicAgent.update(): position = -200.0, inputs = {'qAsk': 66500, 'spread': 1, 'qAggr': -100.0, 'qTraded': 100.0, 'midPrice': '12.50', 'deltaMid': '0.000', 'qOfi': -100.0, 'qBid': 79100}, action = BEST_BID, price_action = ['12.39'], reward = 4.0, time = 2016-08-16 16:10:01\n", "\n", "Environment.step(): Market closed at 16:30:00! MidPrice = 12.51. Trial aborted.\n", "\n", "Simulator.run(): Trial 18\n", "Environment.reset(): Trial set up to use 20160817.csv file\n", "BasicAgent.update(): position = 0, inputs = {'qAsk': 100, 'spread': 1, 'qAggr': 0.0, 'qTraded': 0.0, 'midPrice': '12.42', 'deltaMid': '0.000', 'qOfi': 0.0, 'qBid': 43700}, action = BEST_BOTH, price_action = ['12.32', '12.53'], reward = 0.0, time = 2016-08-17 10:10:00\n", "\n", "BasicAgent.update(): position = 100, inputs = {'qAsk': 7400, 'spread': 1, 'qAggr': -78700.0, 'qTraded': 80500.0, 'midPrice': '12.32', 'deltaMid': '-0.015', 'qOfi': -44400.0, 'qBid': 67200}, action = BUY, price_action = ['12.32'], reward = -0.43, time = 2016-08-17 10:59:04\n", "\n", "BasicAgent.update(): position = 0, inputs = {'qAsk': 93400, 'spread': 1, 'qAggr': 169800.0, 'qTraded': 191600.0, 'midPrice': '12.52', 'deltaMid': '0.030', 'qOfi': 216700.0, 'qBid': 300}, action = SELL, price_action = ['12.53'], reward = 20.56, time = 2016-08-17 11:36:12\n", "\n", "BasicAgent.update(): position = 0, inputs = {'qAsk': 6800, 'spread': 1, 'qAggr': 8300.0, 'qTraded': 8300.0, 'midPrice': '12.48', 'deltaMid': '0.000', 'qOfi': 7400.0, 'qBid': 25700}, action = BEST_BOTH, price_action = ['12.37', '12.58'], reward = 0.0, time = 2016-08-17 12:36:12\n", "\n", "BasicAgent.update(): position = 100.0, inputs = {'qAsk': 19900, 'spread': 1, 'qAggr': 100.0, 'qTraded': 100.0, 'midPrice': '12.52', 'deltaMid': '0.000', 'qOfi': -2600.0, 'qBid': 21800}, action = TAKE, price_action = ['12.52'], reward = -0.44, time = 2016-08-17 13:36:12\n", "\n", "BasicAgent.update(): position = 0.0, inputs = {'qAsk': 73300, 'spread': 1, 'qAggr': -200.0, 'qTraded': 200.0, 'midPrice': '12.58', 'deltaMid': '0.000', 'qOfi': 11200.0, 'qBid': 16300}, action = SELL, price_action = ['12.58'], reward = 5.56, time = 2016-08-17 14:16:24\n", "\n", "BasicAgent.update(): position = 0.0, inputs = {'qAsk': 7400, 'spread': 1, 'qAggr': -5200.0, 'qTraded': 5200.0, 'midPrice': '12.60', 'deltaMid': '-0.010', 'qOfi': -24200.0, 'qBid': 34700}, action = None, price_action = [], reward = 0, time = 2016-08-17 15:16:24\n", "\n", "BasicAgent.update(): position = 100.0, inputs = {'qAsk': 4700, 'spread': 1, 'qAggr': -25400.0, 'qTraded': 46000.0, 'midPrice': '12.72', 'deltaMid': '-0.010', 'qOfi': -61600.0, 'qBid': 18000}, action = TAKE, price_action = ['12.72'], reward = -0.45, time = 2016-08-17 16:16:24\n", "\n", "Environment.step(): Market closed at 16:30:00! MidPrice = 12.74. Trial aborted.\n", "\n", "Simulator.run(): Trial 19\n", "Environment.reset(): Trial set up to use 20160818.csv file\n", "BasicAgent.update(): position = 100.0, inputs = {'qAsk': 20600, 'spread': 1, 'qAggr': 0.0, 'qTraded': 0.0, 'midPrice': '12.82', 'deltaMid': '0.000', 'qOfi': 0.0, 'qBid': 19800}, action = TAKE, price_action = ['12.83'], reward = -1.45, time = 2016-08-18 10:10:00\n", "\n", "BasicAgent.update(): position = 200.0, inputs = {'qAsk': 53600, 'spread': 1, 'qAggr': 0.0, 'qTraded': 0.0, 'midPrice': '12.93', 'deltaMid': '0.000', 'qOfi': 0.0, 'qBid': 30400}, action = TAKE, price_action = ['12.94'], reward = 9.55, time = 2016-08-18 11:10:00\n", "\n", "BasicAgent.update(): position = 200.0, inputs = {'qAsk': 14800, 'spread': 1, 'qAggr': 100.0, 'qTraded': 100.0, 'midPrice': '12.88', 'deltaMid': '0.000', 'qOfi': -6100.0, 'qBid': 41700}, action = BEST_BID, price_action = ['12.77'], reward = -10.0, time = 2016-08-18 12:10:03\n", "\n", "BasicAgent.update(): position = 200.0, inputs = {'qAsk': 32700, 'spread': 1, 'qAggr': -1100.0, 'qTraded': 3100.0, 'midPrice': '12.93', 'deltaMid': '0.005', 'qOfi': 11000.0, 'qBid': 10000}, action = BEST_BOTH, price_action = ['12.77', '12.83', '13.04'], reward = 10.0, time = 2016-08-18 13:10:05\n", "\n", "BasicAgent.update(): position = 200.0, inputs = {'qAsk': 133100, 'spread': 1, 'qAggr': 0.0, 'qTraded': 0.0, 'midPrice': '12.94', 'deltaMid': '0.000', 'qOfi': 0.0, 'qBid': 48000}, action = BEST_BID, price_action = ['13.04', '12.83', '12.84'], reward = 2.0, time = 2016-08-18 14:10:10\n", "\n", "BasicAgent.update(): position = 200.0, inputs = {'qAsk': 2000, 'spread': 1, 'qAggr': 5400.0, 'qTraded': 10200.0, 'midPrice': '12.92', 'deltaMid': '0.000', 'qOfi': -10600.0, 'qBid': 18300}, action = BEST_BID, price_action = ['12.84', '12.82'], reward = -4.0, time = 2016-08-18 15:10:13\n", "\n", "BasicAgent.update(): position = 200.0, inputs = {'qAsk': 297000, 'spread': 1, 'qAggr': 19200.0, 'qTraded': 24600.0, 'midPrice': '12.98', 'deltaMid': '0.000', 'qOfi': -6600.0, 'qBid': 25100}, action = None, price_action = [], reward = 0, time = 2016-08-18 16:10:13\n", "\n", "id: 86051, date: 2016-08-18 16:21:40\n", " qBid Bid Ask qAsk\n", "0 100 13.02 13.02 43,700\n", "1 63,000 13.01 13.03 151,900\n", "2 8,400 13.00 NaN NaN\n", "3 118,800 12.99 NaN NaN\n", "4 58,100 12.98 NaN NaN\n", "\n", "corrected\n", " qBid Bid Ask qAsk\n", "0 63,000 13.01 13.02 43,600\n", "1 8,400 13.00 13.03 151,900\n", "2 118,800 12.99 NaN NaN\n", "3 58,100 12.98 NaN NaN\n", "4 53,100 12.97 NaN NaN\n", "\n", "CPU times: user 4min 33s, sys: 3.4 s, total: 4min 36s\n", "Wall time: 4min 35s\n" ] } ], "source": [ "e = environment.Environment()\n", "a = e.create_agent(agent.BasicAgent, f_min_time=3600.)\n", "e.set_primary_agent(a)\n", "\n", "sim = simulator.Simulator(e)\n", "%time sim.run(n_trials=30)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "WOOOOWWWWWWWWWWW ... it worked. Now.... after almost a month doing that (today is 16th september), I can finally ...... start the Udacity projet =/" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "*Style notebook and change matplotlib defaults*" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "<style>\n", " @font-face {\n", " font-family: \"Computer Modern\";\n", " src: url('http://9dbb143991406a7c655e-aa5fcb0a5a4ec34cff238a2d56ca4144.r56.cf5.rackcdn.com/cmunss.otf');\n", " }\n", " @font-face {\n", " font-family: \"Computer Modern\";\n", " font-weight: bold;\n", " src: url('http://9dbb143991406a7c655e-aa5fcb0a5a4ec34cff238a2d56ca4144.r56.cf5.rackcdn.com/cmunsx.otf');\n", " }\n", " @font-face {\n", " font-family: \"Computer Modern\";\n", " font-style: oblique;\n", " src: url('http://9dbb143991406a7c655e-aa5fcb0a5a4ec34cff238a2d56ca4144.r56.cf5.rackcdn.com/cmunsi.otf');\n", " }\n", " @font-face {\n", " font-family: \"Computer Modern\";\n", " font-weight: bold;\n", " font-style: oblique;\n", " src: url('http://9dbb143991406a7c655e-aa5fcb0a5a4ec34cff238a2d56ca4144.r56.cf5.rackcdn.com/cmunso.otf');\n", " }\n", " div.cell{\n", " width:800px;\n", " margin-left:16% !important;\n", " margin-right:auto;\n", " }\n", " h1 {\n", " font-family: Helvetica, serif;\n", " }\n", " h4{\n", " margin-top:12px;\n", " margin-bottom: 3px;\n", " }\n", " div.text_cell_render{\n", " font-family: Computer Modern, \"Helvetica Neue\", Arial, Helvetica, Geneva, sans-serif;\n", " line-height: 145%;\n", " font-size: 130%;\n", " width:800px;\n", " margin-left:auto;\n", " margin-right:auto;\n", " }\n", " .CodeMirror{\n", " font-family: \"Source Code Pro\", source-code-pro,Consolas, monospace;\n", " }\n", " .prompt{\n", " display: None;\n", " }\n", " .text_cell_render h5 {\n", " font-weight: 300;\n", " font-size: 22pt;\n", " color: #4057A1;\n", " font-style: italic;\n", " margin-bottom: .5em;\n", " margin-top: 0.5em;\n", " display: block;\n", " }\n", "\n", " .warning{\n", " color: rgb( 240, 20, 20 )\n", " }\n", "</style>\n", "\n", "\n", "\n", "<style>\n", " table {\n", " overflow:hidden;\n", " font-family: Computer Modern, \"Helvetica Neue\", Arial, Helvetica, Geneva, sans-serif;\n", " font-size: 12px;\n", " margin: 10px;\n", " width: 480px;\n", " text-align: left;\n", " border-collapse: collapse;\n", " border: 1px solid #d3d3d3;\n", " -moz-border-radius:5px; FF1+;\n", " -webkit-border-radius:5px; Saf3-4;\n", " border-radius:5px;\n", " -moz-box-shadow: 0 0 4px rgba(0, 0, 0, 0.01);\n", " }\n", " th\n", " {\n", " padding: 12px 17px 12px 17px;\n", " font-weight: normal;\n", " font-size: 14px;\n", " border-bottom: 1px dashed #69c;\n", " }\n", "\n", " td\n", " {\n", " padding: 7px 17px 7px 17px;\n", "\n", " }\n", "\n", " tbody tr:hover th\n", " {\n", "\n", " background: #E9E9E9;\n", " }\n", "\n", " tbody tr:hover td\n", " {\n", "\n", " background: #E9E9E9;\n", " }\n", "\n", "</style>\n", "\n", "<script>\n", " MathJax.Hub.Config({\n", " TeX: {\n", " extensions: [\"AMSmath.js\"]\n", " },\n", " tex2jax: {\n", " inlineMath: [ ['$','$'], [\"\\\\(\",\"\\\\)\"] ],\n", " displayMath: [ ['$$','$$'], [\"\\\\[\",\"\\\\]\"] ]\n", " },\n", " displayAlign: 'center', // Change this to 'center' to center equations.\n", " \"HTML-CSS\": {\n", " styles: {'.MathJax_Display': {\"margin\": 4}}\n", " }\n", " });\n", "</script>\n" ], "text/plain": [ "<IPython.core.display.HTML object>" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "#loading style sheet\n", "from IPython.core.display import HTML\n", "HTML( open('ipython_style.css').read())" ] }, { "cell_type": "code", "execution_count": 67, "metadata": { "collapsed": true }, "outputs": [], "source": [ "#changing matplotlib defaults\n", "%matplotlib inline\n", "import seaborn as sns\n", "sns.set_palette(\"deep\", desat=.6)\n", "sns.set_context(rc={\"figure.figsize\": (8, 4)})\n", "sns.set_style(\"whitegrid\")\n", "sns.set_palette(sns.color_palette(\"Set2\", 10))" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [] } ], "metadata": { "anaconda-cloud": {}, "kernelspec": { "display_name": "Python [Root]", "language": "python", "name": "Python [Root]" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 2 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython2", "version": "2.7.12" } }, "nbformat": 4, "nbformat_minor": 0 }