예제 #1
0
class PriceDiffUtil(object):
    def __init__(self, db_uri, exchangerate_db, source_db, target_db, coin,
                 first, second, date):

        super(PriceDiffUtil, self).__init__()
        self.exchangerate_db = exchangerate_db
        self.source_db = source_db
        self.target_db = target_db
        self.db_mgr = MysqlDatabaseManager(db_uri, exchangerate_db, source_db,
                                           target_db)

        self.coin = coin
        self.first_instmt = first.lower()
        self.second_instmt = second.lower()
        self.date = date

        self.exchange_rate = self.get_exchange_rate_of_day()
        self.price_diff_table = None

        self.create_price_diff_table()

    def get_exchange_rate_of_day(self):

        exchange_rate_table = 'exchange_rate'

        if not self.db_mgr.is_table_existed(self.exchangerate_db,
                                            exchange_rate_table):
            raise ValueError('No exchange rate table found')

        stmt = '''select * from {}.{} where date_time = '{}';
        '''.format(self.exchangerate_db.alias, exchange_rate_table, self.date)

        res = self.db_mgr.session.execute(stmt)
        rates = [rate for rate in res]
        if not rates:
            raise ValueError('No record exchange rate for day {}'.format(
                self.date))
        exchange_rate = ExchangeRate()
        exchange_rate.cny = rates[0][1]
        exchange_rate.jpy = rates[0][2]
        exchange_rate.eur = rates[0][3]
        exchange_rate.krw = rates[0][4]

        return exchange_rate

    def create_price_diff_table(self):
        self.price_diff_table = 'exch_{}_{}_{}_pricediff_{}'.format(
            self.coin.lower(), self.first_instmt.lower(),
            self.second_instmt.lower(), self.date)

        stmt = '''create table if not exists {}.{}
        (timestamp varchar(25) primary key, price_diff decimal(20, 8), price_diff_percent decimal(20, 8));'''
        if not self.db_mgr.is_table_existed(self.target_db,
                                            self.price_diff_table):
            self.db_mgr.session.execute(
                stmt.format(self.target_db.alias, self.price_diff_table))

    def get_price_by_tick(self, instmt, coin, date, start_time, tick):
        table_name = None
        tb_names = self.db_mgr.get_table_names_from_db(self.source_db)

        for tb in tb_names:
            m = re.search(r'exch_(.*)_(.*)_snapshot_(\d+)', tb)
            if m and instmt == m.group(1) \
               and coin in m.group(2) and m.group(3) == date:
                table_name = tb
                break
        else:
            raise ValueError('No instmt and coin pair table found')

        s_time = start_time.strftime('%Y%m%d %H:%M:%S.%f')
        d_time = (start_time +
                  timedelta(0, tick)).strftime('%Y%m%d %H:%M:%S.%f')
        stmt = '''select trade_px from {} where trades_date_time >= '{}'
        and trades_date_time < '{}' and update_type=2
        '''.format(table_name, s_time, d_time)

        res = self.db_mgr.session.execute(stmt)

        prices = [px for px in res]

        if prices:
            return float(prices[-1][0])
        else:
            return 0

    def consistent_currency_by_usd(self, instmt, coin, price, exchange_rate):
        er = exchange_rate
        base_currency = instmt.get_base_currency()
        coin_currency = re.split('_|-', coin)
        if len(coin_currency) > 1:
            nation = coin_currency[1]
            return price / float(getattr(er, nation.lower()))
        else:
            for item in er.supported_currency:
                if item.lower() in coin_currency:
                    return price / float(getattr(exchange_rate, item.lower()))
            else:
                return price / float(getattr(er, base_currency))

    def get_exact_coin_name(self, instmt, coin, date):

        tb_names = self.db_mgr.get_table_names_from_db(self.source_db)

        for tb in tb_names:
            m = re.search(r'exch_(.*)_(.*)_snapshot_(\d+)', tb)
            if m and instmt == m.group(1) \
               and coin in m.group(2) and m.group(3) == date:
                return m.group(2)
        else:
            raise ValueError('No instmt and coin pair table found')

    def generate_price_diff(self):
        exact_date = datetime.strptime(self.date, '%Y%m%d').date()
        begin_time = datetime.strptime(self.date, '%Y%m%d')

        exch_factory = ExchangeFactory()
        exch1 = exch_factory.get_exchange(exchange=self.first_instmt)
        exch2 = exch_factory.get_exchange(exchange=self.second_instmt)

        while True:
            if begin_time.date() > exact_date:
                break
            end_time = begin_time + timedelta(0, 60)

            coin1 = self.get_exact_coin_name(self.first_instmt, self.coin,
                                             self.date)
            coin2 = self.get_exact_coin_name(self.second_instmt, self.coin,
                                             self.date)

            price1 = self.get_price_by_tick(self.first_instmt, self.coin,
                                            self.date, begin_time, 60)
            price2 = self.get_price_by_tick(self.second_instmt, self.coin,
                                            self.date, begin_time, 60)

            if price1 == 0 or price2 == 0:
                begin_time = end_time
                continue

            consistent_currency1 = self.consistent_currency_by_usd(
                exch1, coin1, price1, self.exchange_rate)
            consistent_currency2 = self.consistent_currency_by_usd(
                exch2, coin2, price2, self.exchange_rate)

            price_diff = consistent_currency1 - consistent_currency2
            price_diff_percent = price_diff / min(consistent_currency1,
                                                  consistent_currency2) * 100.0

            stmt = '''replace into {}.{} (timestamp, price_diff, price_diff_percent) values('{}',{},{})
            '''.format(self.target_db.alias, self.price_diff_table,
                       begin_time.strftime('%Y%m%d %H:%M:%S.%f'), price_diff,
                       price_diff_percent)

            try:
                print(stmt)
                self.db_mgr.session.execute(stmt)
                self.db_mgr.session.commit()
            except Exception as e:
                print(e)
                self.db_mgr.session.rollback()

            begin_time = end_time
예제 #2
0
class MonitorConfig(with_metaclass(FlyweightMeta)):
    def __init__(self):

        super(MonitorConfig, self).__init__()
        self.config_file = None
        self.mysql_uri = None
        self.mysql_db = None
        self.rules = None
        self.mail_config = None
        self.rule_table_name = 'exchange_data_monitor_rules'
        self.lock = threading.Lock()

    def load_config(self, mysql_uri, mysql_db, config_file):
        self.mysql_uri = mysql_uri
        self.config_file = config_file
        with open(self.config_file, 'r') as f:
            content = json.loads(f.read())
            self.mail_config = content['mail']

        self.mysql_db = MysqlDB(mysql_db, mysql_db)

        self.db_mgr = MysqlDatabaseManager(self.mysql_uri, self.mysql_db)

        stmt = '''
        CREATE TABLE IF NOT EXISTS  {}.{}
        ( id int not null AUTO_INCREMENT, exch1 varchar(25), exch2 varchar(25),
        currency varchar(25), price_diff_threshold decimal(20, 8), direction varchar(25),
        succeeded_rule_id varchar(128),
        status varchar(16),
        primary key (id)
        );
        '''.format(self.mysql_db.alias, self.rule_table_name)
        if not self.db_mgr.is_table_existed(self.mysql_db,
                                            self.rule_table_name):
            try:
                self.db_mgr.session.execute(stmt)
                self.db_mgr.session.commit()
            except Exception as e:
                print(e)
                self.db_mgr.session.rollback()

        self.fetch_rules()

    def fetch_rules(self):

        stmt = '''
        select id, exch1, exch2, currency, price_diff_threshold, direction
        from {}.{} where status = 'active';
        '''.format(self.mysql_db.alias, self.rule_table_name)

        try:
            self.lock.acquire()
            print('Fetching Rules')
            self.db_mgr.session.execute('flush table {}.{}'.format(
                self.mysql_db.alias, self.rule_table_name))
            self.db_mgr.session.commit()
            res = self.db_mgr.session.execute(stmt)
            if self.rules:
                del self.rules

            self.rules = {}
            for item in res:
                self.rules[item[0]] = list(item[1:])
            print(self.rules)
        except Exception as e:
            print(e)
            self.db_mgr.session.rollback()
        finally:
            self.lock.release()

    def deactive_rule(self, id):

        stmt = '''
        update {}.{} set status = 'deactive' where id = {};
        '''.format(self.mysql_db.alias, self.rule_table_name, id)

        try:
            self.lock.acquire()
            self.db_mgr.session.execute(stmt)
            self.db_mgr.session.commit()
        except Exception as e:
            print(e)
        finally:
            self.lock.release()

    def active_rule(self, id):
        stmt = '''
        update {}.{} set status = 'active' where id = {};
        '''.format(self.mysql_db.alias, self.rule_table_name, id)

        try:
            self.lock.acquire()
            self.db_mgr.session.execute(stmt)
            self.db_mgr.session.commit()
        except Exception as e:
            print(e)
        finally:
            self.lock.release()

    def get_succeeded_rule_ids(self, key):
        stmt = '''
        select succeeded_rule_id from {}.{} where id = {};
        '''.format(self.mysql_db.alias, self.rule_table_name, key)

        try:
            self.lock.acquire()
            res = self.db_mgr.session.execute(stmt).fetchone()
            if res[0]:
                ids = list(
                    map(lambda x: int(x.strip()), re.split(',|\ |;', res[0])))
                return ids
            else:
                return None
        except Exception as e:
            print(e)
        finally:
            self.lock.release()

    def safe_exchage_rate(self, dbalias, tablename, cny, jpy, eur, krw):
        date = datetime.utcnow().date().strftime("%Y%m%d")
        stmt = '''replace into {}.{} (date_time, cny, jpy, eur, krw)
        values ('{}', {}, {}, {}, {});
        '''.format(dbalias, tablename, date, cny, jpy, eur, krw)

        try:
            self.lock.acquire()
            self.db_mgr.session.execute(stmt)
            self.db_mgr.session.commit()
        except Exception as e:
            print(e)
        finally:
            self.lock.release()
예제 #3
0
class KBarGenerator(object):

    def __init__(self, mysql_uri, source_db, target_db, since_date):

        self.db_mgr = MysqlDatabaseManager(mysql_uri, source_db, target_db)
        self.source_db = source_db
        self.target_db = target_db
        if not since_date:
            self.since_date = (datetime.utcnow().date() - timedelta(2)).strftime('%Y%m%d')
        else:
            self.since_date = since_date

    def create_kbar_data_table_if_not_exists(self, db, instmt, coin, durance, timestamp=None):

        kb_durance = KBarDurance(durance)
        if kb_durance.is_need_create_new_table:
            table_name = '{}.exch_{}_{}_{}_kbar_{}'.format(
                db.alias, instmt, coin, durance, timestamp)
        else:
            table_name = '{}.exch_{}_{}_{}_kbar'.format(
                db.alias, instmt, coin, durance)

        stmt = '''CREATE TABLE IF NOT EXISTS  {}
        (time_start varchar(25),
        time_end varchar(25),
        exchange varchar(25),
        market varchar(25),
        open decimal(20, 8),
        high decimal(20, 8),
        low decimal(20, 8),
        close decimal(20, 8),
        volume decimal(20, 8),
        primary key (time_start , time_end)
        );
        '''

        try:
            if not self.db_mgr.is_table_existed(db, table_name.split('.')[1]):
                print('Creating {} {} KBar with durance {}.'.format(instmt, coin, durance))
                self.db_mgr.session.execute(stmt.format(table_name))
                self.db_mgr.session.commit()
                return table_name
        except Exception as e:
            print(e)
            self.db_mgr.session.rollback()


    def create_last_kbar_data_table_if_not_exists(self, db):

        table_name = '{}.last_updated_kbar'.format(db.alias)

        stmt = '''CREATE TABLE IF NOT EXISTS  {}
        (
        exchange varchar(25),
        market varchar(25),
        durance varchar(25),
        open decimal(20, 8),
        high decimal(20, 8),
        low decimal(20, 8),
        close decimal(20, 8),
        volume decimal(20, 8),
        primary key (exchange , market, durance)
        );
        '''

        if not self.db_mgr.is_table_existed(db, 'last_updated_kbar'):
            print('Creating Last Updated KBar Table')
            self.db_mgr.session.execute(stmt.format(table_name))
            self.db_mgr.session.commit()

    def get_last_kbar_item(self, db, instmt, coin, durance):

        table_name = '{}.last_updated_kbar'.format(db.alias)

        stmt = '''select * from {} where exchange='{}'
        and market='{}' and durance='{}';
        '''

        res = self.db_mgr.session.execute(stmt.format(table_name, instmt,
                                                      coin, durance))
        if res:
            kbar = res.fetchone()
            return kbar
        else:
            return None

    def update_last_kbar_item(self, db, instmt, coin, durance,
                              open, high , low , close, volume):

        table_name = '{}.last_updated_kbar'.format(db.alias)

        stmt = '''replace into {} (exchange , market, durance , open, high , low , close, volume)
        values ('{}', '{}', '{}', {}, {}, {}, {}, {})
        '''.format(table_name, instmt, coin, durance, open, high, low, close, volume )

        try:
            self.db_mgr.session.execute(stmt)
            self.db_mgr.session.commit()
        except Exception as e:
            self.db_mgr.session.fallback()

    def kbar_generate_worker(self, instmt, coin, durance, timestamp):

        kbar_durance = KBarDurance(durance)

        data_table = '{}.{}_{}_order_{}'.format(self.source_db.alias, instmt, coin, timestamp)

        if kbar_durance.is_need_create_new_table:
            kbar_table = '{}.exch_{}_{}_{}_kbar_{}'.format(self.target_db.alias, instmt, coin, durance, timestamp)
        else:
            kbar_table = '{}.exch_{}_{}_{}_kbar'.format(self.target_db.alias, instmt, coin, durance)

        current_date = datetime.strptime(timestamp, '%Y_%m_%d').date()
        begin_time = datetime.strptime(timestamp, '%Y_%m_%d')

        last_kbar_item = self.get_last_kbar_item(self.target_db, instmt, coin, durance)

        last_trade = Trade(instmt, coin, last_kbar_item[3], last_kbar_item[4],
                           last_kbar_item[5], last_kbar_item[6],
                           last_kbar_item[7]) if last_kbar_item else Trade(instmt, coin)

        while True:
            if begin_time.date() > current_date:
                self.update_last_kbar_item(self.target_db, instmt, coin, durance,
                                           last_trade.open, last_trade.high,
                                           last_trade.low, last_trade.close,
                                           last_trade.volume)
                break

            end_time = begin_time + kbar_durance.interval

            stmt = '''
            select t, tq, date_time from {}
            where update_type=2 and date_time >= '{}' and date_time < '{}'
            order by date_time;
            '''.format(data_table, begin_time.strftime('%Y%m%d %H:%M:%S.%f'),
                       end_time.strftime('%Y%m%d %H:%M:%S.%f'))

            res = self.db_mgr.session.execute(stmt)
            items = [trade for trade in res]
            stmt = '''
            replace into {} (time_start, time_end, exchange, market, open, high , low, close, volume)
            values('{}', '{}', '{}', '{}', {}, {}, {}, {}, {})
            '''

            try:
                if not items:

                    self.db_mgr.session.execute(stmt.format(kbar_table,
                                                            begin_time.strftime('%Y%m%d %H:%M:%S.%f'),
                                                            end_time.strftime('%Y%m%d %H:%M:%S.%f'),
                                                            instmt, coin,
                                                            last_trade.open, last_trade.high, last_trade.low,
                                                            last_trade.close, last_trade.volume
                                                            ))
                    self.db_mgr.session.commit()
                else:
                    open = items[0][0]
                    high = reduce(lambda x,y:  x if x> y else y , [ item[0] for item in items])
                    low = reduce(lambda x,y:  x if x < y else y , [ item[0] for item in items])
                    close = items[-1][0]
                    volume = sum([item[1] for item in items])
                    #self.update_last_kbar_item(db, instmt, coin, durance, open, high, low, close, volume)
                    last_trade = Trade(instmt, coin, open, high, low, close, volume)
                    self.db_mgr.session.execute(stmt.format(kbar_table,
                                                            begin_time.strftime('%Y%m%d %H:%M:%S.%f'),
                                                            end_time.strftime('%Y%m%d %H:%M:%S.%f'),
                                                            instmt, coin,
                                                            open, high, low, close, volume))

                    self.db_mgr.session.commit()
            except Exception as e:
                print(e)
                self.db_mgr.session.rollback()

            begin_time = end_time

    def kbar_generate(self):
        tb_names = self.db_mgr.get_all_table_names()
        instmt_coin_table = {}
        self.create_last_kbar_data_table_if_not_exists(self.target_db)
        for tn in tb_names:
            r = re.search(r'bcex.(\w+)_(\w+)_order_(\d{4}_\d{2}_\d{2})', tn)
            if r:
                if r.group(1) not in instmt_coin_table:
                    instmt_coin_table[r.group(1)] = {r.group(2): [r.group(3)]}
                else:
                    if r.group(2) not in instmt_coin_table[r.group(1)]:
                        instmt_coin_table[r.group(1)][r.group(2)] = [r.group(3)]
                    else:
                        instmt_coin_table[r.group(1)][r.group(2)].append(r.group(3))

        import json
        print(json.dumps(instmt_coin_table))

        for instmt in instmt_coin_table:
            for coin in instmt_coin_table[instmt]:
                for timestamp in instmt_coin_table[instmt][coin]:
                    if timestamp >= self.since_date:
                        for durance in KBarDurance.kbar_durance_map.keys():
                            print('Generate KBar data for {} with {} by {} on {}'.format(instmt, coin, durance, timestamp))
                            self.create_kbar_data_table_if_not_exists(self.target_db, instmt, coin, durance, timestamp)
                            self.kbar_generate_worker(instmt, coin, durance, timestamp)
예제 #4
0
class MysqlMergeUtil(MergeUtil):
    def __init__(self,
                 db_uri,
                 from_db,
                 to_db,
                 zone_info,
                 since_date=None,
                 end_date=None):
        super(MysqlMergeUtil, self).__init__(db_uri, from_db, to_db, zone_info,
                                             since_date, end_date)
        self.db_mgr = MysqlDatabaseManager(db_uri, from_db, to_db)

    def is_table_need_merge(self, instmt, coin, timestamp):

        tb_name_post_fix = 'exch_{}_{}_snapshot_{}'.format(
            instmt, coin, timestamp)

        origin_table_name = '{}.{}'.format(self.origin_db.alias,
                                           tb_name_post_fix)
        target_table_name = '{}.{}'.format(self.target_db.alias,
                                           tb_name_post_fix)

        stmt = '''select count(trades_date_time) from {}
        where {}.trades_date_time != '20000101 00:00:00.000000'
        and {}.order_date_time != '20000101 00:00:00.000000'
        and {}.trades_date_time not in
        (select trades_date_time from {});
        '''.format(origin_table_name, origin_table_name, origin_table_name,
                   origin_table_name, target_table_name)

        res = self.db_mgr.session.execute(stmt)
        count = res.fetchone()[0]
        return count > 0

    def merge_unconfident_table(self, instmt, coin, timestamp):

        tb_name_post_fix = 'exch_{}_{}_snapshot_{}'.format(
            instmt, coin, timestamp)

        origin_table_name = '{}.{}'.format(self.origin_db.alias,
                                           tb_name_post_fix)
        target_table_name = '{}.{}'.format(self.target_db.alias,
                                           tb_name_post_fix)

        stmt = '''replace into {} (id, trade_px, trade_volume,
                                  b1, b2, b3, b4, b5, a1, a2, a3, a4, a5,
                                  bq1, bq2, bq3, bq4, bq5, aq1, aq2, aq3, aq4,
                                  aq5, order_date_time, trades_date_time, update_type)
        select distinct * from {}
        where {}.trades_date_time != '20000101 00:00:00.000000'
        and {}.order_date_time != '20000101 00:00:00.000000'
        and {}.trades_date_time not in
        (select distinct trades_date_time from {});
        '''.format(target_table_name, origin_table_name, origin_table_name,
                   origin_table_name, origin_table_name, target_table_name)
        try:
            res = self.db_mgr.session.execute(stmt)
            self.db_mgr.session.commit()
        except Exception as e:
            print(e)
            self.db_mgr.session.rollback()

    def merge_confident_table(self, instmt, coin, timestamp):

        tb_name_post_fix = 'exch_{}_{}_snapshot_{}'.format(
            instmt, coin, timestamp)

        origin_table_name = '{}.{}'.format(self.origin_db.alias,
                                           tb_name_post_fix)
        target_table_name = '{}.{}'.format(self.target_db.alias,
                                           tb_name_post_fix)

        stmt = '''replace into {} (id, trade_px, trade_volume,
                                  b1,b2,b3,b4,b5,a1,a2,a3,a4,a5,
                                  bq1,bq2,bq3,bq4,bq5,aq1,aq2,aq3,aq4,
                                  aq5,order_date_time,trades_date_time,update_type)
        select distinct * from {}
        where {}.trades_date_time != '20000101 00:00:00.000000'
        and {}.order_date_time != '20000101 00:00:00.000000';
        '''.format(target_table_name, origin_table_name, origin_table_name,
                   origin_table_name)

        try:
            res = self.db_mgr.session.execute(stmt)
            self.db_mgr.session.commit()
        except Exception as e:
            print(e)
            self.db_mgr.session.rollback()

    def merge(self):

        origin_tb_names = self.db_mgr.get_table_names_from_db(self.origin_db)
        instmt_coin_table = {}
        for tn in origin_tb_names:
            r = re.search(r'.*.exch_([a-z]+)_(.*)_snapshot_(\d+)', tn)
            if r:
                if r.group(1) not in instmt_coin_table:
                    instmt_coin_table[r.group(1)] = {r.group(2): [r.group(3)]}
                else:
                    if r.group(2) not in instmt_coin_table[r.group(1)]:
                        instmt_coin_table[r.group(1)][r.group(2)] = [
                            r.group(3)
                        ]
                    else:
                        instmt_coin_table[r.group(1)][r.group(2)].append(
                            r.group(3))

        import json
        print(json.dumps(instmt_coin_table))

        for instmt in instmt_coin_table:
            for coin in instmt_coin_table[instmt]:
                for timestamp in instmt_coin_table[instmt][coin]:
                    if timestamp >= self.since_date and timestamp <= self.end_date:
                        print('Merging data table: exch_{}_{}_{}'.format(
                            instmt, coin, timestamp))
                        if not self.db_mgr.is_table_existed(
                                self.target_db, 'exch_{}_{}_{}'.format(
                                    instmt, coin, timestamp)):
                            self.create_market_data_table(
                                self.target_db, instmt, coin, timestamp)
                        if self.zone_info.is_confident(self.origin_db.zone,
                                                       instmt):
                            self.merge_confident_table(instmt, coin, timestamp)
                        else:
                            self.merge_unconfident_table(
                                instmt, coin, timestamp)