trading_bot.py 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. import random
  2. from datetime import timedelta, datetime
  3. from math import log2, ceil
  4. import model
  5. from debug import debug
  6. order_expiry = 43200
  7. def place_order(ownable_id):
  8. """
  9. places a new order according to the algorithm described in `assets/follower.py`
  10. :param ownable_id: on which ownable to place the order
  11. :return: True iff a new order was placed
  12. """
  13. cheapest_buy_order, best_sell_order = model.abs_spread(ownable_id)
  14. if cheapest_buy_order is None or best_sell_order is None:
  15. return False
  16. investors_id = model.bank_id()
  17. orders = model.get_ownable_orders(investors_id, ownable_id)
  18. orders = [random.choice(orders) for _ in range(int(ceil(log2(len(orders)))))]
  19. amounts = [order[3] for order in orders]
  20. amount = sum(amounts) / len(amounts)
  21. expiry = datetime.strptime(model.current_db_time(), '%Y-%m-%d %H:%M:%S') + timedelta(minutes=order_expiry)
  22. model.place_order(buy=bool(random.getrandbits(1)),
  23. ownership_id=model.get_ownership_id(ownable_id, investors_id),
  24. limit=random.uniform(cheapest_buy_order, best_sell_order),
  25. stop_loss=False,
  26. amount=amount,
  27. expiry=expiry)
  28. return True
  29. def main(): # TODO testen
  30. """the initial part of the trading bot algorithm"""
  31. if model.get_user_orders(model.bank_id()):
  32. raise AssertionError('The trading bot already has some orders.')
  33. if input('Are you sure you want to place the initial orders? (type in "yes" or something else):') == 'yes':
  34. for ownable_id in model.ownable_ids():
  35. if ownable_id != model.currency_id():
  36. place_order(ownable_id)
  37. else:
  38. print('Not placing orders.')
  39. model.cleanup()
  40. if __name__ == '__main__':
  41. main()
  42. def notify_expired_orders(orders):
  43. for order in orders:
  44. # order_id = order[0]
  45. ownership_id = order[1]
  46. # check if that was one of the bots orders
  47. bank_ownership_id = model.get_ownership_id(ownership_id, model.bank_id())
  48. if ownership_id != bank_ownership_id:
  49. continue
  50. # create a new order
  51. ownable_id = model.ownable_id_by_ownership_id(ownership_id)
  52. place_order(ownable_id)
  53. def notify_order_traded(ownable_id):
  54. """
  55. Called after a trade has been done and now the auctions are finished.
  56. :param ownable_id: the ownable that was traded
  57. :return: True iff a new order was placed
  58. """
  59. model.connect()
  60. if ownable_id == model.currency_id():
  61. return False
  62. ownership_id = model.get_ownership_id(ownable_id, model.bank_id())
  63. if debug: # the bot should only have one order
  64. model.cursor.execute('''
  65. SELECT COUNT(*) <= 1
  66. FROM orders
  67. WHERE ownership_id = ?
  68. ''', (ownership_id,))
  69. if not model.cursor.fetchone()[0]:
  70. raise AssertionError('The bot should have at most one order.')
  71. model.cursor.execute('''
  72. SELECT rowid, amount, expiry
  73. FROM orders
  74. WHERE ownership_id = ?
  75. -- no need for ORDER since the bot should have only one order
  76. -- ORDER BY rowid DESC -- equivalent to ordering by time created
  77. -- LIMIT might still improve performance
  78. LIMIT 1
  79. ''', (ownership_id,))
  80. data = model.cursor.fechtall()
  81. # TODO Neu überdenken, das geht so nicht, wenn die order schon ausgeführt ist, ist sie nicht mehr in der DB
  82. if not data:
  83. return place_order(ownable_id)
  84. my_last_order = model.cursor.fechtone()
  85. last_order_id = my_last_order[0]
  86. last_amount = my_last_order[1]
  87. expiry = my_last_order[2]
  88. dt_order_placed = datetime.strptime(expiry, '%Y-%m-%d %H:%M:%S') - timedelta(minutes=order_expiry)
  89. model.cursor.execute('''
  90. SELECT 2 * SUM(amount) >= ?
  91. FROM transactions
  92. WHERE ownable_id = ?
  93. AND dt >= ?
  94. ''', (last_amount, ownable_id, dt_order_placed))
  95. if model.cursor.fechtone()[0]:
  96. model.delete_order(last_order_id)
  97. return place_order(ownable_id)
  98. return False