{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "## Building The Environment\n", "UirĂ¡ Caiado. Aug 19, 2016\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": [ "
\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
DateTypePriceSize
02016-08-18 10:09:09TRADE12.801000
12016-08-18 10:09:09BID12.8015900
22016-08-18 10:09:09ASK12.812900
32016-08-18 10:09:09ASK12.817900
42016-08-18 10:09:09BID12.8020900
\n", "
" ], "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": [ "" ] }, "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": [ "" ] }, "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": [ "
\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
qBidBidAskqAsk
020012.1112.12400
130012.10NaNNaN
\n", "
" ], "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": [ "
\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
qBidBidAskqAsk
020012.1112.12400
120012.10NaNNaN
\n", "
" ], "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": [ "
\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
qBidBidAskqAsk
010012.1112.12400
120012.10NaNNaN
\n", "
" ], "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": [ "
\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
DateTypePriceSize
02016-08-18 10:09:09TRADE12.801000
12016-08-18 10:09:09BID12.8015900
22016-08-18 10:09:09ASK12.812900
32016-08-18 10:09:09ASK12.817900
42016-08-18 10:09:09BID12.8020900
\n", "
" ], "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": [ "
\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
qBidBidAskqAsk
01,20012.8812.802,000
12,625,40012.8712.81144,800
21,712,60012.8612.82281,100
31,957,30012.8512.831,169,900
494,60012.8412.84396,200
\n", "
" ], "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": [ "
\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
qBidBidAskqAsk
050,60012.9512.96130,000
1159,20012.9412.9762,400
28,70012.9312.9834,600
374,00012.9212.9928,100
49,70012.9113.0065,900
513,90012.9013.0131,900
645,40012.8913.0210,300
769,90012.8813.03119,300
8123,00012.87NaNNaN
921,90012.86NaNNaN
1033,00012.85NaNNaN
11161,10012.84NaNNaN
1253,80012.83NaNNaN
1358,40012.82NaNNaN
1412,70012.81NaNNaN
1540,20012.80NaNNaN
1644,90012.79NaNNaN
1764,50012.78NaNNaN
\n", "
" ], "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": [ "
\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
DateTypePriceSize
02016-08-18 10:09:09TRADE12.801000
12016-08-18 10:09:09BID12.8015900
22016-08-18 10:09:09ASK12.812900
32016-08-18 10:09:09ASK12.817900
42016-08-18 10:09:09BID12.8020900
\n", "
" ], "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": [ "
\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
qBidBidAskqAsk
02,00012.0112.0336,000
180012.0012.0471,600
237,90011.9912.0520,400
397,00011.9812.0623,100
445,10011.9712.0727,900
\n", "
" ], "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": [ "\n", "\n", "\n", "\n", "\n", "\n", "\n" ], "text/plain": [ "" ] }, "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 }