diff --git a/db.py b/db.py index d320a52..d5bda10 100644 --- a/db.py +++ b/db.py @@ -52,7 +52,7 @@ class Order(Model): buy = BooleanField() quantity = DoubleField() price = DoubleField() - uuid = CharField() + uuid = TextField() active = BooleanField(default=True) cancelled = BooleanField(default=False) date = DateTimeField(default=get_time) diff --git a/grafana/trading.json b/grafana/trading.json index 46a1e6e..38f64c3 100644 --- a/grafana/trading.json +++ b/grafana/trading.json @@ -16,7 +16,7 @@ "gnetId": null, "graphTooltip": 0, "id": 1, - "iteration": 1599453836661, + "iteration": 1599544047350, "links": [], "panels": [ { @@ -113,6 +113,11 @@ { "alias": "B Sell Orders", "color": "#E0B400" + }, + { + "alias": "C Fulfilled Orders", + "color": "rgb(0, 0, 0)", + "pointradius": 3 } ], "spaceLength": 10, @@ -242,6 +247,65 @@ "type": "expression" } ] + }, + { + "format": "table", + "group": [ + { + "params": [ + "$__interval", + "NULL" + ], + "type": "time" + } + ], + "hide": false, + "metricColumn": "uuid", + "rawQuery": false, + "rawSql": "SELECT\n $__timeGroupAlias(date,$__interval,NULL),\n uuid AS metric,\n avg(price) AS \"Fulfilled Orders\"\nFROM \"order\"\nWHERE\n $__timeFilter(date) AND\n active = 'false'\nGROUP BY 1,2\nORDER BY 1,2", + "refId": "C", + "select": [ + [ + { + "params": [ + "price" + ], + "type": "column" + }, + { + "params": [ + "avg" + ], + "type": "aggregate" + }, + { + "params": [ + "Fulfilled Orders" + ], + "type": "alias" + } + ] + ], + "table": "\"order\"", + "timeColumn": "date", + "timeColumnType": "timestamp", + "where": [ + { + "name": "$__timeFilter", + "params": [], + "type": "macro" + }, + { + "datatype": "bool", + "name": "", + "params": [ + "active", + "=", + "'false'" + ], + "type": "expression" + } + ] } ], "thresholds": [], @@ -366,13 +430,13 @@ ], "metricColumn": "none", "rawQuery": false, - "rawSql": "SELECT\n $__timeGroupAlias(date,$__interval),\n count(id) AS \"id\"\nFROM \"order\"\nWHERE\n $__timeFilter(date) AND\n active = 'false' AND\n cancelled = 'false'\nGROUP BY 1\nORDER BY 1", + "rawSql": "SELECT\n $__timeGroupAlias(date,$__interval),\n count(price) AS \"price\"\nFROM \"order\"\nWHERE\n active = 'false' AND\n cancelled = 'false'\nGROUP BY 1\nORDER BY 1", "refId": "A", "select": [ [ { "params": [ - "id" + "price" ], "type": "column" }, @@ -384,7 +448,7 @@ }, { "params": [ - "id" + "price" ], "type": "alias" } @@ -394,11 +458,6 @@ "timeColumn": "date", "timeColumnType": "timestamp", "where": [ - { - "name": "$__timeFilter", - "params": [], - "type": "macro" - }, { "datatype": "bool", "name": "", @@ -516,13 +575,13 @@ ], "metricColumn": "none", "rawQuery": false, - "rawSql": "SELECT\n $__timeGroupAlias(date,$__interval),\n count(id) AS \"id\"\nFROM \"order\"\nWHERE\n $__timeFilter(date) AND\n active = 'true' AND\n cancelled = 'false'\nGROUP BY 1\nORDER BY 1", + "rawSql": "SELECT\n $__timeGroupAlias(date,$__interval),\n count(price) AS \"price\"\nFROM \"order\"\nWHERE\n active = 'true' AND\n cancelled = 'false'\nGROUP BY 1\nORDER BY 1", "refId": "A", "select": [ [ { "params": [ - "id" + "price" ], "type": "column" }, @@ -534,7 +593,7 @@ }, { "params": [ - "id" + "price" ], "type": "alias" } @@ -544,11 +603,6 @@ "timeColumn": "date", "timeColumnType": "timestamp", "where": [ - { - "name": "$__timeFilter", - "params": [], - "type": "macro" - }, { "datatype": "bool", "name": "", @@ -841,7 +895,7 @@ "y": 14 }, "hiddenSeries": false, - "id": 18, + "id": 26, "legend": { "alignAsTable": true, "avg": true, @@ -866,7 +920,7 @@ "renderer": "flot", "repeat": null, "repeatDirection": "h", - "repeatIteration": 1599453836661, + "repeatIteration": 1599544047350, "repeatPanelId": 12, "scopedVars": { "currency": { @@ -1813,7 +1867,7 @@ ] }, "time": { - "from": "now-3h", + "from": "now-2d", "to": "now" }, "timepicker": { @@ -1833,5 +1887,5 @@ "timezone": "", "title": "Trading", "uid": "1KF3M1DGz", - "version": 20 + "version": 28 } diff --git a/requirements.txt b/requirements.txt index 701266f..dce0993 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,4 @@ requests peewee psycopg2-binary +python-dotenv diff --git a/trade.py b/trade.py index 259a780..fc8f905 100755 --- a/trade.py +++ b/trade.py @@ -3,6 +3,7 @@ import logging from os import getenv from argparse import ArgumentParser +from datetime import datetime from decimal import Decimal from random import uniform from time import sleep @@ -21,7 +22,7 @@ class Trader(TradeOgre): base_currency = 'BTC' trade_currency = 'WOW' trade_pair = f'{base_currency}-{trade_currency}' - trade_amount = 100 + trade_amount = 250 def get_market_data(self): logging.info(f'[MARKET] Getting market data for trade pair {self.trade_pair}') @@ -78,6 +79,23 @@ class Trader(TradeOgre): logging.debug(f'Found {len(orders)} in database') return orders + def reconcile_orders(self): + logging.info('[ORDERS] Reconciling orders on TradeOgre with local database') + to_orders = self.get_orders(self.trade_pair) + for order in to_orders: + if not Order.filter(Order.uuid==order['uuid']): + o = Order( + trade_pair=order['market'], + trade_type='manual', + buy=order['type'] == 'buy', + quantity=float(order['quantity']), + price=float(order['price']), + uuid=order['uuid'], + date=datetime.utcfromtimestamp(order['date']) + ) + o.save() + logging.info(f'[ORDERS] Saved order {order["uuid"]} to the database') + def update_orders(self): logging.info('[ORDERS] Updating orders in local database against TradeOgre') for order in self.get_active_orders(): @@ -155,6 +173,7 @@ if __name__ == '__main__': exit() if args.update_orders: + t.reconcile_orders() t.update_orders() exit() @@ -168,8 +187,8 @@ if __name__ == '__main__': except Exception as e: logging.info('[ERROR] Unable to store market data!', e) - # update orders every 3 minutes - if orders_counter == 3: + # update orders every 5 minutes + if orders_counter == 5: try: t.update_orders() logging.info('[ORDERS] Resetting orders counter') diff --git a/tradeogre.py b/tradeogre.py index 17639f2..df5c261 100644 --- a/tradeogre.py +++ b/tradeogre.py @@ -43,3 +43,8 @@ class TradeOgre(object): def get_order(self, uuid): route = f'/account/order/{uuid}' return self.req(route) + + def get_orders(self, pair): + route = f'/account/orders' + data = {'market': pair} + return self.req(route, 'post', data)