Browse Source

Implement remaining features of trading bot

Eren Yilmaz 6 năm trước cách đây
mục cha
commit
4ebee70a0f
4 tập tin đã thay đổi với 86 bổ sung34 xóa
  1. 20 31
      model.py
  2. 3 1
      run_server.py
  3. 4 1
      server_controller.py
  4. 59 1
      trading_bot.py

+ 20 - 31
model.py

@@ -8,6 +8,7 @@ from math import floor
 from passlib.handlers.sha2_crypt import sha256_crypt
 
 import db_setup
+import trading_bot
 from debug import debug
 from game import CURRENCY_NAME
 from util import random_chars, salt
@@ -302,7 +303,7 @@ def activate_key(key, user_id):
                 AND key = ?
                 ''', (user_id, key,))
 
-    send_ownable(bank_id(), user_id, CURRENCY_NAME, 1000)
+    send_ownable(bank_id(), user_id, currency_id(), 1000)
 
 
 def bank_id():
@@ -653,11 +654,16 @@ def execute_orders(ownable_id):
         #               user_id,user_id,rowid,rowid)
 
         if not matching_orders:
-            break
+            # check if the trading bot has any new offers to make
+            new_order_was_placed = trading_bot.notify_order_traded(ownable_id)
+            if new_order_was_placed:
+                continue
+            else:
+                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:
@@ -697,32 +703,8 @@ def execute_orders(ownable_id):
             return AssertionError()
 
         # actually execute the order, but the bank does not send or receive anything
-        if buyer_id != bank_id():  # buyer pays
-            cursor.execute('''
-                UPDATE ownership 
-                SET amount = amount - ?
-                WHERE user_id = ?
-                AND ownable_id = ?
-                ''', (price * amount, buyer_id, currency_id()))
-        if seller_id != bank_id():  # seller pays
-            cursor.execute('''
-                UPDATE ownership 
-                SET amount = amount - ?
-                WHERE rowid = ?
-                ''', (amount, sell_ownership_id))
-        if buyer_id != bank_id():  # buyer receives
-            cursor.execute('''
-                UPDATE ownership 
-                SET amount = amount + ?
-                WHERE rowid = ?
-                ''', (amount, buy_ownership_id))
-        if seller_id != bank_id():  # seller receives
-            cursor.execute('''
-                UPDATE ownership 
-                SET amount = amount + ?
-                WHERE user_id = ?
-                AND ownable_id = ?
-                ''', (price * amount, seller_id, currency_id()))
+        send_ownable(buyer_id, seller_id, ownable_id, price * amount)
+        send_ownable(seller_id, buyer_id, ownable_id, amount)
 
         # update order execution state
         cursor.execute('''
@@ -850,12 +832,19 @@ def trades(user_id, limit):
 def drop_expired_orders():
     connect()
 
+    cursor.execute('''
+        SELECT rowid, * FROM orders 
+        WHERE expiry_dt < DATETIME('now')
+        ''')
+
+    data = cursor.fetchall()
+
     cursor.execute('''
         DELETE FROM orders 
         WHERE expiry_dt < DATETIME('now')
         ''')
 
-    return cursor.fetchall()
+    return data
 
 
 def generate_keys(count=1):

+ 3 - 1
run_server.py

@@ -6,6 +6,7 @@ from bottle import run, response, route, redirect
 import connection
 import model
 import server_controller
+import trading_bot
 from debug import debug
 from server_controller import not_found
 
@@ -38,7 +39,8 @@ if __name__ == '__main__':
         response.content_type = 'application/json'
         method_to_call = getattr(server_controller, path)
         try:
-            model.drop_expired_orders()
+            expired_orders = model.drop_expired_orders()
+            trading_bot.notify_expired_orders(expired_orders)
             resp = method_to_call()
             if response.status_code == 200:
                 model.connection.commit()

+ 4 - 1
server_controller.py

@@ -161,7 +161,10 @@ def gift():
     if not model.user_owns_at_least(amount, sender_id, ownable_id):
         amount = model.available_amount(sender_id, ownable_id)
 
-    model.send_ownable(sender_id, recipient_id, request.json['object_name'], amount)
+    model.send_ownable(sender_id,
+                       recipient_id,
+                       ownable_id,
+                       amount)
 
     return {'message': "Gift sent."}
 

+ 59 - 1
trading_bot.py

@@ -4,6 +4,8 @@ from math import log2, ceil
 
 import model
 
+order_expiry = 43200
+
 
 def place_order(ownable_id):
     cheapest_buy_order, best_sell_order = model.abs_spread(ownable_id)
@@ -16,7 +18,7 @@ def place_order(ownable_id):
     amounts = [order[3] for order in orders]
     amount = sum(amounts) / len(amounts)
 
-    expiry = datetime.strptime(model.current_db_time(), '%Y-%m-%d %H:%M:%S') + timedelta(minutes=43200)
+    expiry = datetime.strptime(model.current_db_time(), '%Y-%m-%d %H:%M:%S') + timedelta(minutes=order_expiry)
 
     model.place_order(buy=bool(random.getrandbits(1)),
                       ownership_id=model.get_ownership_id(ownable_id, investors_id),
@@ -41,3 +43,59 @@ def main():  # TODO testen
 
 if __name__ == '__main__':
     main()
+
+
+def notify_expired_orders(orders):
+    for order in orders:
+        # order_id = order[0]
+        ownership_id = order[1]
+
+        # check if that was one of the bots orders
+        bank_ownership_id = model.get_ownership_id(ownership_id, model.bank_id())
+        if ownership_id != bank_ownership_id:
+            continue
+
+        # create a new order
+        ownable_id = model.ownable_id_by_ownership_id(ownership_id)
+        place_order(ownable_id)
+
+
+def notify_order_traded(ownable_id):
+    """
+    Called after a trade has been done and now the auctions are finished.
+    :param ownable_id: the ownable that was traded
+    :return: True iff a new order was placed
+    """
+    model.connect()
+    if ownable_id == model.currency_id():
+        return False
+    ownership_id = model.get_ownership_id(ownable_id, model.bank_id())
+
+    model.cursor.execute('''
+        SELECT rowid, amount, expiry
+        FROM orders 
+        WHERE ownership_id = ? 
+         -- no need for ORDER since the bot should have only one order
+         -- ORDER BY rowid DESC -- equivalent to ordering by time created
+        LIMIT 1
+    ''', (ownership_id,))
+
+    my_last_order = model.cursor.fechtone()
+    last_order_id = my_last_order[0]
+    last_amount = my_last_order[1]
+    expiry = my_last_order[2]
+    dt_order_placed = datetime.strptime(expiry, '%Y-%m-%d %H:%M:%S') - timedelta(minutes=order_expiry)
+
+    model.cursor.execute('''
+        SELECT 2 * SUM(amount) >= ?
+        FROM transactions
+        WHERE ownable_id = ? 
+          AND dt >= ?
+    ''', (last_amount, ownable_id, dt_order_placed))
+
+    if model.cursor.fechtone()[0]:
+        model.delete_order(last_order_id)
+        place_order(ownable_id)
+        return True
+
+    return False