Przeglądaj źródła

implement expiry

Eren Yilmaz 6 lat temu
rodzic
commit
3ce611acaa
4 zmienionych plików z 57 dodań i 14 usunięć
  1. 15 5
      client_controller.py
  2. 19 0
      db_setup.py
  3. 18 7
      model.py
  4. 5 2
      server_controller.py

+ 15 - 5
client_controller.py

@@ -113,7 +113,7 @@ def yn_dialog(msg):
             return False
 
 
-def buy(amount=None, object_name=None, limit='', stop_loss=''):
+def buy(amount=None, object_name=None, limit='', stop_loss='', time_until_expiration=None):
     if object_name is None:  # TODO list some available objects
         object_name = input('Name of object to buy: ')
     if amount is None:
@@ -123,12 +123,17 @@ def buy(amount=None, object_name=None, limit='', stop_loss=''):
         if set_limit:
             limit = input('Limit: ')
             stop_loss = yn_dialog('Is this a stop-loss limit?')
+    if time_until_expiration is None:
+        time_until_expiration = input('Time until order expires (minutes, default 60):')
+        if time_until_expiration == '':
+            time_until_expiration = 60
     response = client_request('order', {"buy": True,
                                         "session_id": connection.session_id,
                                         "amount": amount,
                                         "ownable": object_name,
                                         "limit": limit,
-                                        "stop_loss": stop_loss})
+                                        "stop_loss": stop_loss,
+                                        "time_until_expiration": time_until_expiration})
     if 'error_message' in response:
         print('Order placement failed with message:', response['error_message'])
     else:
@@ -136,7 +141,7 @@ def buy(amount=None, object_name=None, limit='', stop_loss=''):
               'to see if the order has been executed already.')
 
 
-def sell(amount=None, object_name=None, limit='', stop_loss=''):
+def sell(amount=None, object_name=None, limit='', stop_loss='', time_until_expiration=None):
     if object_name is None:  # TODO list some available objects
         object_name = input('Name of object to sell: ')
     if amount is None:
@@ -146,12 +151,17 @@ def sell(amount=None, object_name=None, limit='', stop_loss=''):
         if set_limit:
             limit = input('Limit: ')
             stop_loss = yn_dialog('Is this a stop-loss limit?')
+    if time_until_expiration is None:
+        time_until_expiration = input('Time until order expires (minutes, default 60):')
+        if time_until_expiration == '':
+            time_until_expiration = 60
     response = client_request('order', {"buy": False,
                                         "session_id": connection.session_id,
                                         "amount": amount,
                                         "ownable": object_name,
                                         "limit": limit,
-                                        "stop_loss": stop_loss})
+                                        "stop_loss": stop_loss,
+                                        "time_until_expiration": time_until_expiration})
     if 'error_message' in response:
         print('Order placement failed with message:', response['error_message'])
     else:
@@ -164,7 +174,7 @@ def orders():
     success = 'data' in response
     if success:
         print(tabulate(response['data'],
-                       headers=['Buy?', 'Name', 'Amount', 'Limit', 'Stop Loss?', 'Orig. Order Size'],
+                       headers=['Buy?', 'Name', 'Amount', 'Limit', 'Stop Loss?', 'Orig. Order Size', 'Expires'],
                        tablefmt="pipe"))
     else:
         if 'error_message' in response:

+ 19 - 0
db_setup.py

@@ -148,6 +148,24 @@ def integrity_checks(cursor):
                     SELECT RAISE(ROLLBACK, 'Can not execute more than ordered.');
                 END
                 ''')
+    cursor.execute('''
+                CREATE TRIGGER IF NOT EXISTS expiry_dt_in_future_after_insert
+                AFTER INSERT
+                ON orders
+                WHEN NEW.expiry_dt < NEW.dt
+                BEGIN
+                    SELECT RAISE(ROLLBACK, 'Order is already expired.');
+                END
+                ''')
+    cursor.execute('''
+                CREATE TRIGGER IF NOT EXISTS expiry_dt_in_future_after_update
+                AFTER UPDATE
+                ON orders
+                WHEN NEW.expiry_dt < NEW.dt
+                BEGIN
+                    SELECT RAISE(ROLLBACK, 'Order is already expired.');
+                END
+                ''')
 
 
 def tables(cursor):
@@ -195,6 +213,7 @@ def tables(cursor):
                     price CURRENCY NOT NULL,
                     ownable_id INTEGER NOT NULL,
                     amount CURRENCY NOT NULL,
+                    expiry_dt DATETIME NOT NULL,
                     FOREIGN KEY (ownable_id) REFERENCES ownable(rowid)
                 )
                 ''')

+ 18 - 7
model.py

@@ -1,3 +1,4 @@
+import datetime
 import random
 import re
 import sqlite3 as db
@@ -323,6 +324,7 @@ def get_user_orders(user_id):
                 ELSE 'No'
             END, 
             orders.ordered_amount
+            orders.expiry_dt
         FROM orders, ownables, ownership
         WHERE ownership.user_id = ?
         AND ownership.ownable_id = ownables.rowid
@@ -429,7 +431,8 @@ def new_stock(name=None):
     bank_order(True,
                ownable_id_by_name(name),
                price,
-               amount)
+               amount,
+               60)
     return name
 
 
@@ -583,24 +586,32 @@ def ownable_id_by_ownership_id(ownership_id):
     return cursor.fetchone()[0]
 
 
-def bank_order(buy, ownable_id, limit, amount):
+def bank_order(buy, ownable_id, limit, amount, time_until_expiration):
     if limit is None:
         raise AssertionError()
     place_order(buy,
                 get_ownership_id(ownable_id, bank_id()),
                 limit,
                 False,
-                amount)
+                amount,
+                time_until_expiration)
+    ownable_name = ownable_name_by_id(ownable_id)
+    cursor.execute('''
+        INSERT INTO news(title)
+        VALUES (?)
+        ''', ('External investors are selling ' + ownable_name))
 
 
-def place_order(buy, ownership_id, limit, stop_loss, amount):
+def place_order(buy, ownership_id, limit, stop_loss, amount, time_until_expiration):
     connect()
 
+    expiry = datetime.datetime.now() + datetime.timedelta(minutes=time_until_expiration)
+
     cursor.execute('''
                 INSERT INTO orders 
-                (buy, ownership_id, "limit", stop_loss, ordered_amount)
-                VALUES (?, ?, ?, ?, ?)
-                ''', (buy, ownership_id, limit, stop_loss, amount))
+                (buy, ownership_id, "limit", stop_loss, ordered_amount, expiry_dt)
+                VALUES (?, ?, ?, ?, ?, ?)
+                ''', (buy, ownership_id, limit, stop_loss, amount, expiry))
 
     execute_orders(ownable_id_by_ownership_id(ownership_id))
     return True

+ 5 - 2
server_controller.py

@@ -71,7 +71,7 @@ def activate_key():
 
 
 def order():
-    missing = missing_attributes(['buy', 'session_id', 'amount', 'ownable'])
+    missing = missing_attributes(['buy', 'session_id', 'amount', 'ownable', 'time_until_expiration'])
     if missing:
         return bad_request(missing)
     if not model.ownable_name_exists(request.json['ownable']):
@@ -81,6 +81,9 @@ def order():
     session_id = request.json['session_id']
     amount = request.json['amount']
     ownable_name = request.json['ownable']
+    time_until_expiration = float(request.json['time_until_expiration'])
+    if time_until_expiration < 0:
+        return bad_request('Invalid expiration time.')
     ownable_id = model.ownable_id_by_name(ownable_name)
     user_id = model.get_user_id_by_session_id(session_id)
     model.own(user_id, ownable_name)
@@ -96,7 +99,7 @@ def order():
         if not model.user_owns_at_least(user_id, amount, ownership_id):
             return bad_request('You can not sell more than you own.')
 
-    model.place_order(buy, ownership_id, limit, stop_loss, amount)
+    model.place_order(buy, ownership_id, limit, stop_loss, amount, time_until_expiration)
     return {'message': "Order placed."}