model.py 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. import psycopg2.extras
  2. def get_timestamp_previous(this_db):
  3. """
  4. Retrieve second to last timestamp from the stocks database
  5. :param this_db:
  6. :return timestamp:
  7. """
  8. cursor = this_db.cursor(cursor_factory=psycopg2.extras.NamedTupleCursor)
  9. query = """SELECT DISTINCT timestamp FROM stocks ORDER BY stocks.timestamp DESC LIMIT 1 OFFSET 1;"""
  10. cursor.execute(query)
  11. res = cursor.fetchone()
  12. this_timestamp_previous = res.timestamp
  13. cursor.close()
  14. return this_timestamp_previous
  15. def get_timestamp_latest(this_db):
  16. """
  17. Retrieve latest timestamp from the stocks database
  18. :param this_db:
  19. :return timestamp:
  20. """
  21. cursor = this_db.cursor(cursor_factory=psycopg2.extras.NamedTupleCursor)
  22. query = """SELECT DISTINCT timestamp FROM stocks ORDER BY stocks.timestamp DESC LIMIT 1;"""
  23. cursor.execute(query)
  24. res = cursor.fetchone()
  25. this_timestamp_latest = res.timestamp
  26. cursor.close()
  27. return this_timestamp_latest
  28. def get_timestamp_stored():
  29. """
  30. Retrieve the timestamp when the program checked the database
  31. :return timestamp:
  32. """
  33. with open('timestamp.txt', 'r') as f:
  34. this_timestamp_stored_string = f.read()
  35. if this_timestamp_stored_string.replace('.', '', 1).isdigit():
  36. this_timestamp_stored = int(this_timestamp_stored_string)
  37. else:
  38. this_timestamp_stored = 0
  39. return this_timestamp_stored
  40. def put_timestamp_stored(this_timestamp):
  41. """
  42. Update timestamp when the program checked the database
  43. :param this_timestamp:
  44. :return:
  45. """
  46. with open('timestamp.txt', 'w') as f:
  47. f.write("{}".format(this_timestamp))
  48. def get_data(stock_id, this_timestamp, this_db):
  49. """
  50. Retrieves detailed data from the existing stocks database
  51. :param stock_id:
  52. :param this_timestamp:
  53. :param this_db:
  54. :return:
  55. """
  56. cursor = this_db.cursor(cursor_factory=psycopg2.extras.NamedTupleCursor)
  57. query = """SELECT current_price, available_shares, forecast, total_shares
  58. FROM stocks
  59. WHERE stock_id = %s AND timestamp = %s"""
  60. cursor.execute(query, (stock_id, this_timestamp))
  61. this_data = cursor.fetchone()
  62. cursor.close()
  63. return this_data
  64. def process_data(data_previous, data_latest, price, threshold):
  65. """
  66. Calculate if there is enough change to call it a drop
  67. :param data_previous:
  68. :param data_latest:
  69. :param price:
  70. :param threshold:
  71. :return boolean:
  72. """
  73. this_drop = False
  74. quantity_previous = data_previous.available_shares * float(data_latest.current_price)
  75. quantity_latest = data_latest.available_shares * float(data_latest.current_price)
  76. if data_latest.current_price < price and quantity_latest - quantity_previous > threshold * 1e9:
  77. this_drop = True
  78. # New: don't report when there are a lot of stocks outstanding
  79. if data_previous.available_shares > data_previous.total_shares / 20:
  80. this_drop = False
  81. return this_drop
  82. def is_npc_drop(data_previous, data_latest):
  83. """
  84. A NPC drop is characterized by a spike in available shares
  85. :param data_previous:
  86. :param data_latest:
  87. :return:
  88. """
  89. npc_drop = False
  90. if data_latest.total_shares - data_previous.total_shares > 0:
  91. print('data_latest.total_shares {}'.format(data_latest.total_shares))
  92. print('data_previous.total_shares {}'.format(data_previous.total_shares))
  93. npc_drop = True
  94. return npc_drop
  95. def process_forecast(data_previous, data_latest, max_price, available):
  96. forecast_changed = False
  97. if data_previous.forecast in ("Very poor", "Poor", "Average"):
  98. if data_latest.forecast in ("Good", "Very good"):
  99. forecast_changed = True
  100. if data_latest.current_price > max_price:
  101. forecast_changed = False
  102. if data_latest.available_shares <= available:
  103. forecast_changed = False
  104. return forecast_changed