Browse Source

Implement order_history and command old_orders

Eren Yilmaz 6 years ago
parent
commit
fd7a9b4470
7 changed files with 120 additions and 6 deletions
  1. 26 0
      client_controller.py
  2. 32 0
      db_setup.py
  3. 47 4
      model.py
  4. 1 0
      run_client.py
  5. 1 0
      run_server.py
  6. 12 1
      server_controller.py
  7. 1 1
      trading_bot.py

+ 26 - 0
client_controller.py

@@ -423,6 +423,32 @@ def trades(limit=10):
             print('Trades access failed.')
 
 
+def old_orders(include_canceled=None, include_executed=None, limit=10):
+    limit = float(limit)
+    if include_canceled is None:
+        include_canceled = yn_dialog('Include canceled/expired orders?')
+    if include_executed is None:
+        include_executed = yn_dialog('Include fully executed orders?')
+    if not include_canceled and not include_executed:
+        data = []
+    else:
+        fake_loading_bar('Loading Data', duration=2.7)
+        response = client_request('old_orders', {"session_id": connection.session_id,
+                                                 "include_canceled": include_canceled,
+                                                 "include_executed": include_executed,
+                                                 "limit": limit})
+        success = 'data' in response
+        if success:
+            print(my_tabulate(response['data'],
+                              headers=['Buy?', 'Name', 'Size', 'Limit', 'Expiry', 'No.', 'Status'],
+                              tablefmt="pipe"))
+        else:
+            if 'error_message' in response:
+                print('Order access failed with message:', response['error_message'])
+            else:
+                print('Order access failed.')
+
+
 # noinspection PyShadowingBuiltins
 def exit():
     global exiting

+ 32 - 0
db_setup.py

@@ -291,6 +291,11 @@ def create_triggers(cursor):
                 WHEN NEW.seller_id IS NULL
                 BEGIN SELECT RAISE(ROLLBACK, 'seller_id must not be null for new transactions.'); END
                 ''')
+    cursor.execute('''
+                CREATE TRIGGER IF NOT EXISTS order_history_no_update
+                INSTEAD OF UPDATE ON order_history
+                BEGIN SELECT RAISE(ROLLBACK, 'Can not change order history.'); END
+                ''')
 
 
 def create_indices(cursor):
@@ -347,6 +352,18 @@ def create_indices(cursor):
                 CREATE INDEX IF NOT EXISTS transactions_buyer
                 ON transactions (buyer_id)
                 ''')
+    cursor.execute('''
+                CREATE INDEX IF NOT EXISTS order_history_id
+                ON order_history (order_id)
+                ''')
+    cursor.execute('''
+                CREATE INDEX IF NOT EXISTS order_canceled
+                ON order_history (archived_dt)
+                ''')
+    cursor.execute('''
+                CREATE INDEX IF NOT EXISTS order_history_ownership
+                ON order_history (ownership_id)
+                ''')
 
 
 def tables(cursor):
@@ -389,6 +406,21 @@ def tables(cursor):
                     FOREIGN KEY (ownership_id) REFERENCES ownership(rowid)
                 )
                 ''')
+    cursor.execute('''
+                CREATE TABLE IF NOT EXISTS order_history(
+                    ownership_id INTEGER NOT NULL,
+                    buy BOOLEAN NOT NULL,
+                    "limit" CURRENCY,
+                    ordered_amount CURRENCY NOT NULL,
+                    executed_amount CURRENCY NOT NULL,
+                    expiry_dt DATETIME NOT NULL,
+                    status VARCHAR(20) NOT NULL,
+                    order_id = INTEGER NOT NULL,
+                    archived_dt DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
+                    FOREIGN KEY (ownership_id) REFERENCES ownership(rowid)
+                    -- order_id is not a FOREIGN KEY since orders are deleted from order table afterwards
+                )
+                ''')
     cursor.execute('''
                 CREATE TABLE IF NOT EXISTS transactions(
                     dt DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,

+ 47 - 4
model.py

@@ -551,9 +551,25 @@ def user_money(user_id):
     return cursor.fetchone()[0]
 
 
-def delete_order(order_id):
+def delete_order(order_id, new_order_status):
     connect()
 
+    cursor.execute('''
+        INSERT INTO order_history
+        (ownership_id, buy, "limit", ordered_amount, executed_amount, expiry_dt, status, order_id)
+        SELECT 
+            ownership_id, 
+            buy, 
+            "limit", 
+            ordered_amount, 
+            executed_amount, 
+            expiry_dt, 
+            ?, 
+            rowid
+        FROM order
+        WHERE rowid = ?
+        ''', (order_id, new_order_status))
+
     cursor.execute('''
         DELETE FROM orders
         WHERE rowid = ?
@@ -692,7 +708,7 @@ def execute_orders(ownable_id):
                      _my_division(buyer_money, price))
 
         if amount == 0:  # probable because buyer has not enough money
-            delete_order(buy_order_id)
+            delete_order(buy_order_id, 'Unable to pay')
             continue
 
         buy_order_finished = (buy_order_amount - buy_executed_amount - amount <= 0) or (
@@ -715,9 +731,9 @@ def execute_orders(ownable_id):
             ''', (amount, buy_order_id, sell_order_id))
 
         if buy_order_finished:
-            delete_order(buy_order_id)
+            delete_order(buy_order_id, 'Executed')
         if sell_order_finished:
-            delete_order(sell_order_id)
+            delete_order(sell_order_id, 'Executed')
 
         if seller_id != buyer_id:  # prevent showing self-transactions
             cursor.execute('''
@@ -1126,3 +1142,30 @@ def ownable_ids():
         ''')
 
     return [ownable_id[0] for ownable_id in cursor.fetchall()]
+
+
+def get_old_orders(user_id, include_executed, include_canceled, limit):
+    connect()  # TODO testen
+    # TODO indices prüfen
+    cursor.execute('''
+        SELECT 
+            (CASE WHEN order_history.buy THEN 'Buy' ELSE 'Sell' END),
+            ownable.name,
+            order_history.amount,
+            order_history.limit,
+            order_history.expiry_dt,
+            order_history.order_id,
+            order_history.status
+        FROM order_history, ownership, ownable
+        WHERE ownership.user_id = ?
+        AND ownership.rowid = order_history.ownership_id
+        AND ownable.rowid = ownership.ownable_id
+        AND (
+             (order_history.status = 'Executed' AND ?)
+             OR 
+             ((order_history.status = 'Expired' OR order_history.status = 'Canceled') AND ?)
+            )
+        LIMIT ?
+        ''', (user_id, include_executed, include_canceled, limit))
+
+    return cursor.fetchall()

+ 1 - 0
run_client.py

@@ -61,6 +61,7 @@ allowed_commands = ['help',
                     'depot',
                     'orders',
                     'orders_on',
+                    'old_orders',
                     'trades',
                     'trades_on',
                     'buy',

+ 1 - 0
run_server.py

@@ -22,6 +22,7 @@ if __name__ == '__main__':
                     'trades',
                     'trades_on',
                     'orders_on',
+                    'old_orders',
                     'cancel_order',
                     'leaderboard',
                     'tradables',

+ 12 - 1
server_controller.py

@@ -189,13 +189,24 @@ def orders_on():
     return {'data': data}
 
 
+def old_orders():
+    missing = missing_attributes(['session_id', 'include_canceled', 'include_executed', 'limit'])
+    if missing:
+        return bad_request(missing)
+    include_executed = request.json['include_executed']
+    include_canceled = request.json['include_canceled']
+    user_id = model.get_user_id_by_session_id(request.json['session_id'])
+    data = model.get_old_orders(user_id, include_executed, include_canceled)
+    return {'data': data}
+
+
 def cancel_order():
     missing = missing_attributes(['session_id', 'order_id'])
     if missing:
         return bad_request(missing)
     if not model.user_has_order_with_id(request.json['session_id'], request.json['order_id']):
         return bad_request('You do not have an order with that number.')
-    model.delete_order(request.json['order_id'])
+    model.delete_order(request.json['order_id'], 'Canceled')
     return {'message': "Successfully deleted order"}
 
 

+ 1 - 1
trading_bot.py

@@ -115,7 +115,7 @@ def notify_order_traded(ownable_id):
     ''', (last_amount, ownable_id, dt_order_placed))
 
     if model.cursor.fechtone()[0]:
-        model.delete_order(last_order_id)
+        model.delete_order(last_order_id, 'Canceled')
         return place_order(ownable_id)
 
     return False