Jelajahi Sumber

fix limit == 0 cases (is possible now)

Eren Yilmaz 6 tahun lalu
induk
melakukan
c486d2cbd4
4 mengubah file dengan 57 tambahan dan 10 penghapusan
  1. 13 0
      client_controller.py
  2. 28 6
      cool_query.py
  3. 14 0
      db_setup.py
  4. 2 4
      model.py

+ 13 - 0
client_controller.py

@@ -145,6 +145,8 @@ def help():
     print('  All parameters for all commands are optional!')
     print('  Commands can be combined in one line with ; between them.')
     print('  Parameters are separated with any whitespace.')
+    print('  Use . as a decimal separator.')
+    print('  Use 0/1 for boolean parameters (other strings might work).')
 
 
 def _my_tabulate(data, **params):
@@ -207,6 +209,7 @@ def yn_dialog(msg):
             return True
         if result == 'n':
             return False
+        print('Type in \'y\' or \'n\'!')
 
 
 def buy(obj_name=None, amount=None, limit='', stop_loss='', expiry=None):
@@ -224,11 +227,21 @@ def buy(obj_name=None, amount=None, limit='', stop_loss='', expiry=None):
             stop_loss = None
     if limit is not None and stop_loss == '':
         stop_loss = yn_dialog('Is this a stop-loss limit?')
+    if float(limit) <= 0 and input(input('Are you sure you want to use such a low limit (limit=' + str(
+            limit) + '? (type in "yes" or something else):') != 'yes'):
+        print('Order was not placed.')
+        return
 
     if expiry is None:
         expiry = input('Time until order expires (minutes, default 43200):')
         if expiry == '':
             expiry = 43200
+    try:
+        float(expiry)
+    except ValueError:
+        print('Invalid expiration time.')
+        return
+
     fake_loading_bar('Loading Data', duration=1.3)
     response = client_request('order', {"buy": True,
                                         "session_id": connection.session_id,

+ 28 - 6
cool_query.py

@@ -2,12 +2,34 @@ import model
 from client_controller import _my_tabulate
 
 model.connect()
+# model.cursor.execute('''
+#         EXPLAIN QUERY PLAN
+#         SELECT users.rowid
+#         FROM sessions, users
+#         WHERE sessions.session_id = ?
+#         AND users.rowid = sessions.user_id
+#         '''.replace('?','1'))
+
 model.cursor.execute('''
-        EXPLAIN QUERY PLAN 
-        SELECT users.rowid
-        FROM sessions, users
-        WHERE sessions.session_id = ?
-        AND users.rowid = sessions.user_id
-        '''.replace('?','1'))
+            SELECT buy_order.*, sell_order.*, buyer.user_id, seller.user_id, buy_order.rowid, sell_order.rowid
+            FROM orders buy_order, orders sell_order, ownership buyer, ownership seller
+            WHERE buy_order.buy AND NOT sell_order.buy
+            AND buyer.rowid = buy_order.ownership_id
+            AND seller.rowid = sell_order.ownership_id
+            AND buyer.ownable_id = ?
+            AND seller.ownable_id = ?
+            AND (buy_order."limit" IS NULL
+                OR sell_order."limit" IS NULL
+                OR (sell_order."limit" <= buy_order."limit"
+                    AND NOT sell_order.stop_loss
+                    AND NOT buy_order.stop_loss))
+            ORDER BY CASE WHEN sell_order."limit" IS NULL THEN 0 ELSE 1 END ASC, 
+                     CASE WHEN buy_order."limit" IS NULL THEN 0 ELSE 1 END ASC, 
+                     buy_order."limit" DESC,
+                     sell_order."limit" ASC,
+                     buy_order.ordered_amount - buy_order.executed_amount DESC,
+                     sell_order.ordered_amount - sell_order.executed_amount DESC
+            LIMIT 1
+            ''', (4, 4,))
 
 print(_my_tabulate(model.cursor.fetchall(),tablefmt='pipe'))

+ 14 - 0
db_setup.py

@@ -38,6 +38,8 @@ def drop_triggers(cursor):
     cursor.execute("DROP TRIGGER IF EXISTS integer_amount_after_insert")
     cursor.execute("DROP TRIGGER IF EXISTS dt_monotonic_after_insert")
     cursor.execute("DROP TRIGGER IF EXISTS dt_monotonic_after_update")
+    cursor.execute("DROP TRIGGER IF EXISTS orders_rowid_sorted_by_creation_time_after_insert")
+    cursor.execute("DROP TRIGGER IF EXISTS news_dt_monotonic_after_update")
 
 
 # def drop_database(cursor):
@@ -206,6 +208,18 @@ def create_triggers(cursor):
                 WHEN NEW.dt < (SELECT MAX(dt) FROM news t2 WHERE t2.rowid < rowid)
                 BEGIN SELECT RAISE(ROLLBACK, 'Transaction rowid programming bug, not your fault.'); END
                 ''')
+    cursor.execute('''
+                CREATE TRIGGER IF NOT EXISTS orders_rowid_sorted_by_creation_time_after_insert
+                AFTER INSERT ON orders
+                WHEN NEW.rowid < (SELECT MAX(rowid) FROM orders o2)
+                BEGIN SELECT RAISE(ROLLBACK, 'Order-rowid programming bug (insert), not your fault.'); END
+                ''')
+    cursor.execute('''
+                CREATE TRIGGER IF NOT EXISTS news_dt_monotonic_after_update
+                AFTER UPDATE ON orders
+                WHEN NEW.rowid <> OLD.rowid
+                BEGIN SELECT RAISE(ROLLBACK, 'Cannot change number of existing order.'); END
+                ''')
 
 
 def create_indices(cursor):

+ 2 - 4
model.py

@@ -630,11 +630,9 @@ def execute_orders(ownable_id):
         elif sell_limit is None:
             price = buy_limit
         else:  # both not NULL
+            # that is not how it works at the real exchange, the price of the older order is used
             price = (float(sell_limit) + float(buy_limit)) / 2
 
-        if price == 0:
-            raise AssertionError()
-
         buyer_money = user_money(buyer_id)
 
         amount = min(buy_order_amount - buy_executed_amount,
@@ -649,7 +647,7 @@ def execute_orders(ownable_id):
                 buyer_money - amount * price < price)
         sell_order_finished = (sell_order_amount - sell_executed_amount - amount <= 0)
 
-        if price < 0 or amount <= 0:
+        if price < 0 or amount <= 0:  # price of 0 is possible though unlikely
             return AssertionError()
 
         # actually execute the order, but the bank does not send or receive anything