|
| 1 | +# coding=utf-8 |
| 2 | +from plugins.Plugin import Plugin |
| 3 | +import modules.Poloniex as Poloniex |
| 4 | +import sqlite3 |
| 5 | + |
| 6 | +BITCOIN_GENESIS_BLOCK_DATE = "2009-01-03 18:15:05" |
| 7 | +DAY_IN_SEC = 86400 |
| 8 | +DB_DROP = "DROP TABLE IF EXISTS history" |
| 9 | +DB_CREATE = "CREATE TABLE IF NOT EXISTS history(" \ |
| 10 | + "id INTEGER UNIQUE, open TIMESTAMP, close TIMESTAMP," \ |
| 11 | + " duration NUMBER, interest NUMBER, rate NUMBER," \ |
| 12 | + " currency TEXT, amount NUMBER, earned NUMBER, fee NUMBER )" |
| 13 | +DB_INSERT = "INSERT OR REPLACE INTO 'history'" \ |
| 14 | + "('id','open','close','duration','interest','rate','currency','amount','earned','fee')" \ |
| 15 | + " VALUES (?,?,?,?,?,?,?,?,?,?);" |
| 16 | +DB_GET_LAST_TIMESTAMP = "SELECT max(close) as last_timestamp FROM 'history'" |
| 17 | +DB_GET_FIRST_TIMESTAMP = "SELECT min(close) as first_timestamp FROM 'history'" |
| 18 | +DB_GET_TOTAL_EARNED = "SELECT sum(earned) as total_earned, currency FROM 'history' GROUP BY currency" |
| 19 | +DB_GET_24HR_EARNED = "SELECT sum(earned) as total_earned, currency FROM 'history' " \ |
| 20 | + "WHERE close BETWEEN datetime('now','-1 day') AND datetime('now') GROUP BY currency" |
| 21 | + |
| 22 | + |
| 23 | +class AccountStats(Plugin): |
| 24 | + last_notification = 0 |
| 25 | + |
| 26 | + def on_bot_init(self): |
| 27 | + super(AccountStats, self).on_bot_init() |
| 28 | + self.init_db() |
| 29 | + |
| 30 | + def after_lending(self): |
| 31 | + self.update_history() |
| 32 | + self.notify_daily() |
| 33 | + |
| 34 | + # noinspection PyAttributeOutsideInit |
| 35 | + def init_db(self): |
| 36 | + self.db = sqlite3.connect(r'market_data\loan_history.sqlite3') |
| 37 | + self.db.execute(DB_CREATE) |
| 38 | + self.db.commit() |
| 39 | + |
| 40 | + def update_history(self): |
| 41 | + # timestamps are in UTC |
| 42 | + last_time_stamp = self.get_last_timestamp() |
| 43 | + |
| 44 | + if last_time_stamp is None: |
| 45 | + # no entries means db is empty and needs initialization |
| 46 | + last_time_stamp = BITCOIN_GENESIS_BLOCK_DATE |
| 47 | + self.db.execute("PRAGMA user_version = 0") |
| 48 | + |
| 49 | + self.fetch_history(Poloniex.create_time_stamp(last_time_stamp), sqlite3.time.time()) |
| 50 | + |
| 51 | + # As Poloniex API return a unspecified number of recent loans, but not all so we need to loop back. |
| 52 | + if (self.get_db_version() == 0) and (self.get_first_timestamp() is not None): |
| 53 | + last_time_stamp = BITCOIN_GENESIS_BLOCK_DATE |
| 54 | + loop = True |
| 55 | + while loop: |
| 56 | + sqlite3.time.sleep(10) # delay a bit, try not to annoy poloniex |
| 57 | + first_time_stamp = self.get_first_timestamp() |
| 58 | + count = self.fetch_history(Poloniex.create_time_stamp(last_time_stamp, ) |
| 59 | + , Poloniex.create_time_stamp(first_time_stamp)) |
| 60 | + loop = count != 0 |
| 61 | + # if we reached here without errors means we managed to fetch all the history, db is ready. |
| 62 | + self.set_db_version(1) |
| 63 | + |
| 64 | + def set_db_version(self, version): |
| 65 | + self.db.execute("PRAGMA user_version = " + str(version)) |
| 66 | + |
| 67 | + def get_db_version(self): |
| 68 | + return self.db.execute("PRAGMA user_version").fetchone()[0] |
| 69 | + |
| 70 | + def fetch_history(self, first_time_stamp, last_time_stamp): |
| 71 | + history = self.api.return_lending_history(first_time_stamp, last_time_stamp - 1, 50000) |
| 72 | + loans = [] |
| 73 | + for loan in reversed(history): |
| 74 | + loans.append( |
| 75 | + [loan['id'], loan['open'], loan['close'], loan['duration'], loan['interest'], |
| 76 | + loan['rate'], loan['currency'], loan['amount'], loan['earned'], loan['fee']]) |
| 77 | + self.db.executemany(DB_INSERT, loans) |
| 78 | + self.db.commit() |
| 79 | + count = len(loans) |
| 80 | + self.log.log('Downloaded ' + str(count) + ' loans history ' |
| 81 | + + sqlite3.datetime.datetime.utcfromtimestamp(first_time_stamp).strftime('%Y-%m-%d %H:%M:%S') |
| 82 | + + ' to ' + sqlite3.datetime.datetime.utcfromtimestamp(last_time_stamp - 1).strftime( |
| 83 | + '%Y-%m-%d %H:%M:%S')) |
| 84 | + if count > 0: |
| 85 | + self.log.log('Last: ' + history[0]['close'] + ' First:' + history[count - 1]['close']) |
| 86 | + return count |
| 87 | + |
| 88 | + def get_last_timestamp(self): |
| 89 | + cursor = self.db.execute(DB_GET_LAST_TIMESTAMP) |
| 90 | + row = cursor.fetchone() |
| 91 | + cursor.close() |
| 92 | + return row[0] |
| 93 | + |
| 94 | + def get_first_timestamp(self): |
| 95 | + cursor = self.db.execute(DB_GET_FIRST_TIMESTAMP) |
| 96 | + row = cursor.fetchone() |
| 97 | + cursor.close() |
| 98 | + return row[0] |
| 99 | + |
| 100 | + def notify_daily(self): |
| 101 | + if self.get_db_version() == 0: |
| 102 | + self.log.log_error('AccountStats DB isn\'t ready.') |
| 103 | + return |
| 104 | + |
| 105 | + if self.last_notification != 0 and self.last_notification + DAY_IN_SEC > sqlite3.time.time(): |
| 106 | + return |
| 107 | + |
| 108 | + cursor = self.db.execute(DB_GET_24HR_EARNED) |
| 109 | + output = '' |
| 110 | + for row in cursor: |
| 111 | + output += str(row[0]) + ' ' + str(row[1]) + ' in last 24hrs\n' |
| 112 | + cursor.close() |
| 113 | + |
| 114 | + cursor = self.db.execute(DB_GET_TOTAL_EARNED) |
| 115 | + for row in cursor: |
| 116 | + output += str(row[0]) + ' ' + str(row[1]) + ' in total\n' |
| 117 | + cursor.close() |
| 118 | + if output != '': |
| 119 | + self.last_notification = sqlite3.time.time() |
| 120 | + output = 'Earnings:\n----------\n' + output |
| 121 | + self.log.notify(output, self.notify_config) |
| 122 | + self.log.log(output) |
0 commit comments