|
5 | 5 | from six.moves import cStringIO
|
6 | 6 | from builtins import input
|
7 | 7 | from decimal import Decimal
|
| 8 | +from six.moves import cStringIO as StringIO |
| 9 | +from six.moves import zip_longest |
8 | 10 | import importlib
|
| 11 | +import json |
| 12 | +import copy |
| 13 | +import difflib |
| 14 | + |
| 15 | +d = difflib.Differ() |
| 16 | +format='html' |
9 | 17 |
|
10 | 18 | if __name__ == '__main__':
|
11 |
| - def process_line(order_book, line): |
| 19 | + def printme(*args): |
| 20 | + if format == 'html': |
| 21 | + print(*args) |
| 22 | + print('<br>') |
| 23 | + else: |
| 24 | + print(*args) |
| 25 | + |
| 26 | + def print_orderbook(newbook, oldbook): |
| 27 | + if format == 'html': |
| 28 | + tempfile = StringIO() |
| 29 | + tempfile.write('<table>') |
| 30 | + tempfile.write('<tr>') |
| 31 | + tempfile.write("<td><b>Bids</b></td>") |
| 32 | + tempfile.write("<td><b>Asks</b></td>") |
| 33 | + tempfile.write("</tr>") |
| 34 | + bids_new = [] |
| 35 | + asks_new = [] |
| 36 | + |
| 37 | + bids_old = [] |
| 38 | + asks_old = [] |
| 39 | + if newbook.bids != None and len(newbook.bids) > 0: |
| 40 | + for key, value in newbook.bids.price_tree.items(reverse=True): |
| 41 | + for order in value: |
| 42 | + bids_new += [str(order)] |
| 43 | + if newbook.asks != None and len(newbook.asks) > 0: |
| 44 | + for key, value in list(newbook.asks.price_tree.items()): |
| 45 | + for order in value: |
| 46 | + asks_new += [str(order)] |
| 47 | + if oldbook.bids != None and len(oldbook.bids) > 0: |
| 48 | + for key, value in oldbook.bids.price_tree.items(reverse=True): |
| 49 | + for order in value: |
| 50 | + bids_old += [str(order)] |
| 51 | + if oldbook.asks != None and len(oldbook.asks) > 0: |
| 52 | + for key, value in list(oldbook.asks.price_tree.items()): |
| 53 | + for order in value: |
| 54 | + asks_old += [str(order)] |
| 55 | + |
| 56 | + bids_diff = list(d.compare(bids_old, bids_new)) |
| 57 | + asks_diff = list(d.compare(asks_old, asks_new)) |
| 58 | + bids = [] |
| 59 | + for i in bids_diff: |
| 60 | + if i[0:2] == '? ': |
| 61 | + continue |
| 62 | + elif i[0:2] == '+ ': |
| 63 | + bids += ["<b>" + i[2:] + "</b>"] |
| 64 | + elif i[0:2] == '- ': |
| 65 | + bids += ["<strike>" + i[2:] + "</strike>"] |
| 66 | + else: |
| 67 | + bids += [i] |
| 68 | + |
| 69 | + asks = [] |
| 70 | + for i in asks_diff: |
| 71 | + if i[0:2] == '? ': |
| 72 | + continue |
| 73 | + elif i[0:2] == '+ ': |
| 74 | + asks += ["<b>" + i[2:] + "</b>"] |
| 75 | + elif i[0:2] == '- ': |
| 76 | + asks += ["<strike>" + i[2:] + "</strike>"] |
| 77 | + else: |
| 78 | + asks += [i] |
| 79 | + |
| 80 | + for i in zip_longest(bids, asks): |
| 81 | + tempfile.write('<tr><td>' + \ |
| 82 | + (i[0] if i[0] is not None else '') + \ |
| 83 | + '</td><td>' + \ |
| 84 | + (i[1] if i[1] is not None else '') + \ |
| 85 | + '</td></tr>\n') |
| 86 | + tempfile.write('</table><p>') |
| 87 | + tempfile.write("\n<b>Trades</b><br>\n") |
| 88 | + if newbook.tape != None and len(newbook.tape) > 0: |
| 89 | + num = 0 |
| 90 | + for entry in newbook.tape: |
| 91 | + if num < 10: # get last 5 entries |
| 92 | + tempfile.write(str(entry['quantity']) + " @ " + str(entry['price']) + " (" + str(entry['timestamp']) + ") " + str(entry['party1'][0]) + "/" + str(entry['party2'][0]) + "<br>\n") |
| 93 | + num += 1 |
| 94 | + else: |
| 95 | + break |
| 96 | + tempfile.write("\n") |
| 97 | + print(tempfile.getvalue()) |
| 98 | + else: |
| 99 | + print(newbook) |
| 100 | + |
| 101 | + def process_line(order_book, line, output=True): |
12 | 102 | tokens = line.strip().split(",")
|
13 | 103 | d = {"type" : "limit",
|
14 | 104 | "side" : "bid" if tokens[0] == 'B' else 'ask',
|
15 | 105 | "quantity": int(tokens[1]),
|
16 | 106 | "price" : Decimal(tokens[2]),
|
17 | 107 | "trade_id" : tokens[3]}
|
| 108 | + if output: |
| 109 | + printme('external order=', d) |
18 | 110 | return order_book.process_order(d, False, False)
|
19 | 111 |
|
20 | 112 |
|
21 | 113 | order_book = OrderBook()
|
22 |
| - if len(sys.argv) != 2 and len(sys.argv) != 3: |
23 |
| - print("usage: %s input.csv [algo]" % sys.argv[0]) |
| 114 | + if len(sys.argv) != 2 and len(sys.argv) != 3 and len(sys.argv) != 4: |
| 115 | + printme("usage: %s input.csv [algo]" % sys.argv[0]) |
24 | 116 | sys.exit(0)
|
25 | 117 | if len(sys.argv) == 3:
|
26 | 118 | myalgomodule = importlib.import_module(sys.argv[2])
|
27 | 119 | myalgo = myalgomodule.Algorithm(order_book)
|
| 120 | + elif len(sys.argv) == 4: |
| 121 | + myalgomodule = importlib.import_module(sys.argv[2]) |
| 122 | + json_data=open(sys.argv[3]).read() |
| 123 | + data = json.loads(json_data) |
| 124 | + myalgo = myalgomodule.Algorithm(order_book, **data) |
28 | 125 | else:
|
29 | 126 | myalgo = None
|
30 | 127 | try:
|
31 | 128 | reader = open(sys.argv[1], 'r')
|
| 129 | + start_algo = False |
32 | 130 | for line in reader:
|
33 | 131 | trades = None
|
34 | 132 | order = None
|
| 133 | + if start_algo: |
| 134 | + printme("--------- START -------") |
| 135 | + old_orderbook = copy.deepcopy(order_book) |
35 | 136 | if line[0] == '#':
|
36 | 137 | next
|
37 | 138 | elif line[0] == 'B' or line[0] == 'A':
|
38 |
| - (trade, order) = process_line(order_book, line) |
| 139 | + (trade, order) = process_line(order_book, line, start_algo) |
39 | 140 | myalgo.trade_stats(trade, 'trade')
|
| 141 | + elif line[0:12] == 'C,start-algo': |
| 142 | + start_algo = True |
| 143 | + printme("--------- START -------") |
| 144 | + |
| 145 | + if not start_algo: |
| 146 | + continue |
40 | 147 | # Manual Debugging
|
41 |
| - print ("\n") |
42 |
| - print ("Input: " + line) |
43 |
| - print (order_book) |
44 |
| - print (myalgo.stats()) |
45 |
| - # input("Press enter to continue.") |
| 148 | + printme ("\n") |
| 149 | + print_orderbook(order_book, old_orderbook) |
| 150 | + stats=myalgo.stats() |
| 151 | + printme ("total volume=", stats[0]) |
| 152 | + printme ("my volume=", stats[1]) |
| 153 | + printme ("participation=", stats[3]) |
46 | 154 |
|
47 | 155 | if myalgo != None:
|
48 | 156 | (algo_orders, mode) = myalgo.process_order(line,
|
49 | 157 | trade, order)
|
| 158 | + printme('') |
| 159 | + printme("RUNNING ALGO WITH MODE=", mode) |
| 160 | + old_orderbook = copy.deepcopy(order_book) |
50 | 161 | for line in algo_orders:
|
| 162 | + printme(line) |
51 | 163 | if line['type'] == 'cancel':
|
52 | 164 | order_book.cancel_order(line['side'],
|
53 | 165 | line['order_id'])
|
| 166 | + elif line['type'] == 'modify': |
| 167 | + order_book.modify_order(line['order_id'], { |
| 168 | + 'side': line['side'], |
| 169 | + 'price': line['price'], |
| 170 | + 'quantity': line['quantity']}) |
54 | 171 | else:
|
55 | 172 | (trade, order) = order_book.process_order(line,
|
56 | 173 | False,
|
57 | 174 | False)
|
58 | 175 | myalgo.trade_stats(trade, mode)
|
59 | 176 | if len(algo_orders) > 0:
|
60 |
| - print("\n") |
61 |
| - print("After algo") |
62 |
| - print(order_book) |
63 |
| - print (myalgo.stats()) |
64 |
| -# input("Press enter to continue.") |
| 177 | + printme("\n") |
| 178 | + printme("After algo") |
| 179 | + print_orderbook(order_book, old_orderbook) |
| 180 | + stats=myalgo.stats() |
| 181 | + printme ("total volume=", stats[0]) |
| 182 | + printme ("my volume=", stats[1]) |
| 183 | + printme ("participation=", stats[3]) |
| 184 | + else: |
| 185 | + printme("No action by algo") |
| 186 | + printme("--------- END -------") |
65 | 187 | reader.close()
|
66 | 188 | except IOError:
|
67 |
| - print ('Cannot open input file "%s"' % sys.argv[1]) |
| 189 | + printme ('Cannot open input file "%s"' % sys.argv[1]) |
68 | 190 | sys.exit(1)
|
0 commit comments