Ver Fonte

improve a lot of stuff and also an important fix regarding stop loss

Eren Yilmaz há 6 anos atrás
pai
commit
4936de5460
4 ficheiros alterados com 163 adições e 52 exclusões
  1. 3 1
      client_controller.py
  2. 75 27
      cool_query.py
  3. 4 0
      db_setup.py
  4. 81 24
      model.py

+ 3 - 1
client_controller.py

@@ -227,7 +227,9 @@ 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(
+    if limit is not None and \
+            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

+ 75 - 27
cool_query.py

@@ -2,34 +2,82 @@ 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('''
-            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
+        EXPLAIN QUERY PLAN
+            SELECT * FROM (
+                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
+                AND sell_order."limit" IS NULL
+                ORDER BY buy_order.rowid ASC,
+                         sell_order.rowid ASC
+                LIMIT 1)
+            UNION ALL -- best buy orders
+            SELECT * FROM (
+                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
+                AND sell_order."limit" IS NOT NULL
+                AND NOT sell_order.stop_loss
+                ORDER BY sell_order."limit" ASC,
+                         buy_order.rowid ASC,
+                         sell_order.rowid ASC
+                LIMIT 1)
+            UNION ALL -- best sell orders
+            SELECT * FROM (
+                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 NOT NULL
+                AND NOT buy_order.stop_loss
+                AND sell_order."limit" IS NULL
+                ORDER BY buy_order."limit" DESC,
+                         buy_order.rowid ASC,
+                         sell_order.rowid ASC
+                LIMIT 1)
+            UNION ALL -- both limit orders
+            SELECT * FROM (
+                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 NOT NULL
+                AND sell_order."limit" IS NOT NULL
+                AND sell_order."limit" <= buy_order."limit"
+                AND NOT sell_order.stop_loss
+                AND NOT buy_order.stop_loss
+                ORDER BY buy_order."limit" DESC,
+                         sell_order."limit" ASC,
+                         buy_order.rowid ASC,
+                         sell_order.rowid ASC
+                LIMIT 1)
             LIMIT 1
-            ''', (4, 4,))
+        '''.replace('?','1'))
+
+# model.cursor.execute('''
+#             SELECT 2
+#             UNION ALL
+#             SELECT * FROM (
+#                 WITH RECURSIVE ones(x) AS (VALUES(1) UNION ALL SELECT * FROM ones)
+#                 SELECT x FROM ones)
+#             LIMIT 1
+#          '''.replace('?','1'))
 
 print(_my_tabulate(model.cursor.fetchall(),tablefmt='pipe'))

+ 4 - 0
db_setup.py

@@ -240,6 +240,10 @@ def create_indices(cursor):
                 CREATE INDEX IF NOT EXISTS orders_ownership
                 ON orders (ownership_id)
                 ''')
+    cursor.execute('''
+                CREATE INDEX IF NOT EXISTS orders_limit
+                ON orders (limit)
+                ''')
     cursor.execute('''
                 CREATE INDEX IF NOT EXISTS transactions_dt
                 ON transactions (dt)

+ 81 - 24
model.py

@@ -298,6 +298,7 @@ def get_user_ownership(user_id):
         WHERE user_id = ?
         AND (ownership.amount > 0 OR ownership.ownable_id = ?)
         AND ownership.ownable_id = ownables.rowid
+        ORDER BY ownables.rowid ASC
         ''', (currency_id(), user_id, currency_id(),))
 
     return cursor.fetchall()
@@ -589,26 +590,73 @@ def execute_orders(ownable_id):
     while True:
         # find order to execute
         cursor.execute('''
-            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
+            -- two best orders
+            SELECT * FROM (
+                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
+                AND sell_order."limit" IS NULL
+                ORDER BY buy_order.rowid ASC,
+                         sell_order.rowid ASC
+                LIMIT 1)
+            UNION ALL -- best buy orders
+            SELECT * FROM (
+                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
+                AND sell_order."limit" IS NOT NULL
+                AND NOT sell_order.stop_loss
+                ORDER BY sell_order."limit" ASC,
+                         buy_order.rowid ASC,
+                         sell_order.rowid ASC
+                LIMIT 1)
+            UNION ALL -- best sell orders
+            SELECT * FROM (
+                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 NOT NULL
+                AND NOT buy_order.stop_loss
+                AND sell_order."limit" IS NULL
+                ORDER BY buy_order."limit" DESC,
+                         buy_order.rowid ASC,
+                         sell_order.rowid ASC
+                LIMIT 1)
+            UNION ALL -- both limit orders
+            SELECT * FROM (
+                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 NOT NULL
+                AND sell_order."limit" IS NOT NULL
+                AND sell_order."limit" <= buy_order."limit"
+                AND NOT sell_order.stop_loss
+                AND NOT buy_order.stop_loss
+                ORDER BY buy_order."limit" DESC,
+                         sell_order."limit" ASC,
+                         buy_order.rowid ASC,
+                         sell_order.rowid ASC
+                LIMIT 1)
             LIMIT 1
-            ''', (ownable_id, ownable_id,))
+            ''', tuple(ownable_id for _ in range(8)))
 
         matching_orders = cursor.fetchone()
         # return type: (ownership_id,buy,limit,stop_loss,ordered_amount,executed_amount,expiry_dt,
@@ -619,8 +667,8 @@ def execute_orders(ownable_id):
             break
 
         buy_ownership_id, _, buy_limit, _, buy_order_amount, buy_executed_amount, buy_expiry_dt, \
-        sell_ownership_id, _, sell_limit, _, sell_order_amount, sell_executed_amount, sell_expiry_dt, \
-        buyer_id, seller_id, buy_order_id, sell_order_id \
+            sell_ownership_id, _, sell_limit, _, sell_order_amount, sell_executed_amount, sell_expiry_dt, \
+            buyer_id, seller_id, buy_order_id, sell_order_id \
             = matching_orders
 
         if buy_limit is None and sell_limit is None:
@@ -630,14 +678,23 @@ 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
+            # the price of the older order is used, just like in the real exchange
+            if buy_order_id < sell_order_id:
+                price = buy_limit
+            else:
+                price = sell_limit
 
         buyer_money = user_money(buyer_id)
 
+        def _my_division(x,y):
+            try:
+                return floor(x/y)
+            except ZeroDivisionError:
+                return float('Inf')
+
         amount = min(buy_order_amount - buy_executed_amount,
                      sell_order_amount - sell_executed_amount,
-                     floor(buyer_money / price))
+                     _my_division(buyer_money,price))
 
         if amount == 0:  # probable because buyer has not enough money
             delete_order(buy_order_id)