Ejemplo n.º 1
0
def run(coin_pair, depth=10):
    """
    A single connection to stream.binance.com is only valid for 24 hours; expect to be disconnected at the 24 hour mark
    :param coin_pair: coin1:coin2|coin1:coin2 小币在前,大币在后
    :param depth: 5 / 10 / 20
    :return:
    """
    os.environ['WEBSOCKET_CLIENT_CA_BUNDLE'] = certifi.where()
    rds = Redis(host='localhost', port=6379, db=0)
    pair_part = coin_pair.split('|')
    coin_pair_list = [item.split(':') for item in pair_part]
    ws = start_websocket(coin_pair_list, depth)
    start_run = time.time()
    while 1:
        try:
            res = json.loads(ws.recv())
            print("{}|Received|{}".format(
                datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%S.%f'), res))
            if 'stream' in res:
                coin_info = res['stream'].split('@')[0]
                if coin_info[-3:] in bigcoin_set:
                    coin1 = coin_info[-3:]
                    coin2 = coin_info[:-3]
                else:
                    raise Exception(
                        'UnExcepted Coin Info {}'.format(coin_info))
                start = time.time()
                redis_key = get_redis_key(market=Market.BINANCE,
                                          coin1=coin1,
                                          coin2=coin2)
                price_data = res['data']
                # 序列化复杂数据
                price_data['ts'] = int(time.time() * 1000)
                # 保持字符串,不要随便转换为float损失精度
                price_data['bids'] = json.dumps([[item[0], item[1]]
                                                 for item in price_data['bids']
                                                 ])
                price_data['asks'] = json.dumps([[item[0], item[1]]
                                                 for item in price_data['asks']
                                                 ])
                rds.hmset(redis_key, price_data)
                end = time.time()
                print("{}|SetRedis|{}|{}".format(
                    datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%S.%f'),
                    redis_key, end - start))
            else:
                print("{}|UnExceptedMessage|{}".format(
                    datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%S.%f'), res))
            run_time = time.time() - start_run
            if run_time > RECONNECT_TIME:  # 不超过24小时,保险点,设置为10小时 10*60*60=36000
                print("{}|ReConnect".format(
                    datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%S.%f')))
                ws.close()
                ws = start_websocket(coin_pair_list, depth)
                start_run = time.time()
        except Exception as e:
            print("{}|Exception|{}".format(
                datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%S.%f'), e.message))
            print("Traceback|{}".format(traceback.format_exc()))
            try:
                ws.close()
            except:
                pass
            try:
                ExceptionInfoModel(host=ip,
                                   source='FETCH_BINANCE_DEPTH',
                                   message=e.message,
                                   log_time=datetime.utcnow()).add()
                clear_dbsession()
            except:
                pass
            for fail_count in xrange(5):
                # 休息10s
                time.sleep(10)
                try:
                    ws = start_websocket(coin_pair_list, depth)
                    start_run = time.time()
                except:
                    print("{}|Exception|{}".format(
                        datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%S.%f'),
                        e.message))
                    print("Traceback|{}".format(traceback.format_exc()))
                    # 第五次还不行
                    if fail_count >= 4:
                        raise
                else:
                    break
Ejemplo n.º 2
0
def run(coin_pair):
    """

    :param coin_pair: coin_pair: coin1:coin2|coin1:coin2 小币在前,大币在后
    :return:
    """
    rds = Redis(host='localhost', port=6379, db=0)
    pair_part = coin_pair.split('|')
    coin_pair_list = [item.split(':') for item in pair_part]
    ws = start_websocket(coin_pair_list)
    start_run = time.time()
    while 1:
        try:
            message = json.loads(ws.recv())
            if 'dataType' in message and message['dataType'] == 'depth':
                coin_info = message['channel'].split('_')[0]
                if coin_info[-3:] in bigcoin_set:
                    coin1 = coin_info[-3:]
                    coin2 = coin_info[:-3]
                else:
                    raise Exception(
                        'UnExcepted Coin Info {}'.format(coin_info))
                redis_key = get_redis_key(market=Market.ZB,
                                          coin1=coin1,
                                          coin2=coin2)
                price_data = dict()
                # 序列化复杂数据
                # 返回的时间戳为秒级别,不可用
                price_data['ts'] = int(time.time() * 1000)
                price_data['version'] = price_data['ts']
                # 保持字符串,不要随便转换为float损失精度
                price_data['bids'] = json.dumps([[str(item[0]),
                                                  str(item[1])]
                                                 for item in message['bids']])
                price_data['asks'] = json.dumps([[str(item[0]),
                                                  str(item[1])]
                                                 for item in message['asks']])
                start = time.time()
                rds.hmset(redis_key, price_data)
                end = time.time()
                print("{}|SetRedis|{}|{}".format(
                    datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%S.%f'),
                    redis_key, end - start))
            # 建立连接一段时间之后准备重建连接
            current_time = time.time()
            if current_time - start_run > RECONNECT_TIME:  # 设置为10小时 10*60*60=36000
                print("{}|ReConnect".format(
                    datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%S.%f')))
                ws.close()
                ws = start_websocket(coin_pair_list)
                start_run = current_time
            # elif current_time - ping_time > 10:  # 每10秒ping一次
            #     ws.send(json.dumps({'event': 'ping'}))
            #     ping_time = current_time
        except Exception as e:
            print("{}|Exception|{}".format(
                datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%S.%f'), e.message))
            print("Traceback|{}".format(traceback.format_exc()))
            try:  # 出现异常之后重新建立连接
                ws.close()
            except:
                pass
            try:
                ExceptionInfoModel(host=ip,
                                   source='FETCH_ZB_DEPTH',
                                   message=e.message,
                                   log_time=datetime.utcnow()).add()
                clear_dbsession()
            except:
                pass
            for fail_count in xrange(5):
                # 休息10s
                time.sleep(10)
                try:
                    ws = start_websocket(coin_pair_list)
                    start_run = time.time()
                except:
                    print("{}|Exception|{}".format(
                        datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%S.%f'),
                        e.message))
                    print("Traceback|{}".format(traceback.format_exc()))
                    # 第五次还不行
                    if fail_count >= 4:
                        raise
                else:
                    break
Ejemplo n.º 3
0
 def run(self):
     """
     运行
     :return:
     """
     if_trade, if_rebalance = self.frozen_check()
     if if_trade is False:
         print("{}|FrozenOverFLow|{}|{}|{}|{}".format(
             datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%S.%f'),
             self.first_market, self.first_market_account,
             self.second_market, self.second_market_account))
         # 被冻结太多了,休息会
         time.sleep(10)
         self.get_account()
         return
     pipe = self.rds.pipeline(transaction=False)
     redis_key1 = get_redis_key(market=self.first_market,
                                coin1=self.combination.small_coin,
                                coin2=self.combination.big_coin)
     pipe.hgetall(redis_key1)
     redis_key2 = get_redis_key(market=self.second_market,
                                coin1=self.combination.small_coin,
                                coin2=self.combination.big_coin)
     pipe.hgetall(redis_key2)
     res = pipe.execute()
     # 数据可能不存在
     if not res[0]:
         print("{}|BookNotExist|{}|{}|{}".format(
             datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%S.%f'),
             self.first_market, self.combination.small_coin,
             self.combination.big_coin))
         return
     if not res[1]:
         print("{}|BookNotExist|{}|{}|{}".format(
             datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%S.%f'),
             self.second_market, self.combination.small_coin,
             self.combination.big_coin))
         return
     # 先把bids和asks数据从字符串转换回去
     # 版本统一用version指代
     # 时间戳统一用ts
     for item in res:
         item['ts'] = int(item['ts'])
         if 'lastUpdateId' in item:
             item['version'] = int(item['lastUpdateId'])
         if 'version' in item:
             item['version'] = int(item['version'])
         item['bids'] = json.loads(item['bids'])
         item['asks'] = json.loads(item['asks'])
     # 数据可能已经处理过了,还没有更新
     # 这种情况很多,就不用打日志了
     if redis_key1 in self.current_data_version and redis_key2 in self.current_data_version \
             and (self.current_data_version[redis_key1] >= res[0]['version']
                  and self.current_data_version[redis_key2] >= res[1]['version']):
         # print("{}|DataNotUpdate|{}|{}".format(datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%S.%f'),
         #                                       coin1, coin2))
         return
     else:  # 缓存数据
         self.current_data_version[redis_key1] = res[0]['version']
         self.current_data_version[redis_key2] = \
             res[1]['lastUpdateId'] if 'lastUpdateId' in res[1] else res[1]['version']
     # 数据可能超时,注意,存储的数据是毫秒级的
     current = int(time.time() * 1000)
     if current - res[0]['ts'] > BOOK_TIMEOUT * 1000:
         print("{}|BookTimeOut|{}|{}|{}|{}|{}".format(
             datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%S.%f'),
             self.first_market, self.combination.small_coin,
             self.combination.big_coin, current, res[0]['ts']))
         return
     if current - res[1]['ts'] > BOOK_TIMEOUT * 1000:
         print("{}|BookTimeOut|{}|{}|{}|{}|{}".format(
             datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%S.%f'),
             self.second_market, self.combination.small_coin,
             self.combination.big_coin, current, res[1]['ts']))
         return
     # 比较差价
     # 先转换为Decimal
     for res_index in xrange(2):
         for type_index in ['bids', 'asks']:
             res[res_index][type_index] = [[
                 Decimal(str(item[0])),
                 Decimal(str(item[1]))
             ] for item in res[res_index][type_index]]
     first_market_depth_time = res[0]['ts']
     second_market_depth_time = res[1]['ts']
     # bids买,第一位为买小币的最高价;asks卖,第一位为卖小币的最低价
     bid_price, ask_price, amount = self.find_profit(
         res[0]['bids'], res[1]['asks'])
     if amount > 0:  # 有机会了
         self.trader.first_market_sell_second_market_market_buy(
             first_market_account=self.first_market_account,
             second_market_account=self.second_market_account,
             bid_price=bid_price,
             ask_price=ask_price,
             amount=amount,
             first_market_bids_depth=res[0]['bids'],
             second_market_asks_depth=res[1]['asks'],
             first_market_depth_time=first_market_depth_time,
             second_market_depth_time=second_market_depth_time)
     # 不可能出现一边买大于另一边卖,同时一边的卖低于另一边的买
     bid_price, ask_price, amount = self.find_profit(
         res[1]['bids'], res[0]['asks'])
     if amount > 0:
         self.trader.first_market_buy_second_market_market_sell(
             first_market_account=self.first_market_account,
             second_market_account=self.second_market_account,
             bid_price=bid_price,
             ask_price=ask_price,
             amount=amount,
             first_market_asks_depth=res[0]['asks'],
             second_market_bids_depth=res[1]['bids'],
             first_market_depth_time=first_market_depth_time,
             second_market_depth_time=second_market_depth_time)
     if if_rebalance is True:
         if self.first_market_account[self.combination.small_coin] \
                 < self.combination.small_coin_amount * REBALANCE_THRESHOLD:
             self.trader.first_market_small_coin_rebalance(
                 first_market_account=self.first_market_account,
                 second_market_account=self.second_market_account,
                 second_market_bid_info=res[1]['bids'],
                 first_market_ask_info=res[0]['asks'],
                 small_point_amount=self.combination.small_coin_amount,
                 first_market_depth_time=first_market_depth_time,
                 second_market_depth_time=second_market_depth_time)
         elif self.second_market_account[self.combination.small_coin] < \
                 self.combination.small_coin_amount * REBALANCE_THRESHOLD:
             self.trader.second_market_small_coin_rebalance(
                 first_market_account=self.first_market_account,
                 second_market_account=self.second_market_account,
                 first_market_bid_info=res[0]['bids'],
                 second_market_ask_info=res[1]['asks'],
                 small_point_amount=self.combination.small_coin_amount,
                 first_market_depth_time=first_market_depth_time,
                 second_market_depth_time=second_market_depth_time)
         # 小币调整应该是罕见的才对,先不限制只有没交易才小币调整
         self.trader.small_coin_adjust(
             first_market_account=self.first_market_account,
             second_market_account=self.second_market_account,
             small_coin_amount=self.combination.small_coin_amount,
             first_market_depth_info=res[0],
             second_market_depth_info=res[1],
             first_market_depth_time=first_market_depth_time,
             second_market_depth_time=second_market_depth_time)
     if time.time() - self.account_fetch_time > 600:  # 每10分钟获取account
         self.get_account()
         # 如果有需要补充货币,没10分钟处理一次
         self.coin_supplement()
Ejemplo n.º 4
0
def run(coin_pair, depth=10):
    """

    :param coin_pair: coin_pair: coin1:coin2|coin1:coin2 小币在前,大币在后
    :param depth: step0 - step5
    :return:
    """
    rds = Redis(host='localhost', port=6379, db=0)
    pair_part = coin_pair.split('|')
    coin_pair_list = [item.split(':') for item in pair_part]
    ws = start_websocket(coin_pair_list, depth)
    start_run = ping_time = time.time()
    while 1:
        try:
            message = json.loads(ws.recv())
            if isinstance(message, list):  # 订阅成功信息或者深度信息
                for item in message:
                    if item['channel'] == 'addChannel':
                        if item['data']['result'] is True:
                            print("{}|SubChannel|{}".format(datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%S.%f'),
                                                            item['data']['channel']))
                        else:
                            raise SubChannelError("{}|SubChannelFail|{}".format(
                                datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%S.%f'), item['data']['channel']))
                    else:  # 数据
                        channel = item['channel']
                        channel_parts = channel.split('_')
                        coin1 = channel_parts[-4]
                        coin2 = channel_parts[-3]
                        redis_key = get_redis_key(market=Market.OKEX, coin1=coin1, coin2=coin2)
                        price_data = item['data']
                        price_data['ts'] = price_data['timestamp']
                        price_data['version'] = price_data['timestamp']
                        price_data.pop('timestamp')
                        price_data['bids'] = json.dumps(price_data['bids'])
                        price_data['asks'] = json.dumps(price_data['asks'])
                        start = time.time()
                        rds.hmset(redis_key, price_data)
                        end = time.time()
                        print("{}|Received|{}".format(datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%S.%f'), price_data))
                        print("{}|SetRedis|{}|{}".format(datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%S.%f'),
                                                         redis_key, end-start))
            else:
                if 'event' in message and message['event'] == 'pong':
                    print("{}|ReceivedPong|{}".format(datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%S.%f'),
                                                      message))
            # if 'ping' in unziped_message:
            #     print("{}|PING|{}".format(datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%S.%f'),
            #                               unziped_message))
            #     ws.send(json.dumps({'pong': unziped_message['ping']}))
            # elif 'subbed' in unziped_message:
            #     print("{}|Sub|{}".format(datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%S.%f'),
            #                              unziped_message['subbed']))
            # else:  # 收到的是数据
            #     if 'ch' in unziped_message:
            #         coin_symbol = unziped_message['ch'].split('.')[1]
            #         if coin_symbol[-3:] in bigcoin_set:
            #             coin1 = coin_symbol[-3:]
            #             coin2 = coin_symbol[:-3]
            #         else:
            #             raise Exception('UnExcepted Coin Info {}'.format(coin_symbol))
            #         start = time.time()
            #         redis_key = get_redis_key(market=Market.HUOBI, coin1=coin1, coin2=coin2)
            #         price_data = unziped_message['tick']
            #         # 序列化复杂数据
            #         price_data['ts'] = unziped_message['ts']
            #         price_data['bids'] = json.dumps(price_data['bids'][:10])
            #         price_data['asks'] = json.dumps(price_data['asks'][:10])
            #         rds.hmset(redis_key, price_data)
            #         end = time.time()
            #         print("{}|Received|{}".format(datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%S.%f'), price_data))
            #         print("{}|SetRedis|{}|{}".format(datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%S.%f'),
            #                                          redis_key, end-start))
            #     else:
            #         print("{}|UnExceptedMessage|{}".format(datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%S.%f'),
            #                                                unziped_message))
            # 建立连接一段时间之后准备重建连接
            current_time = time.time()
            if current_time - start_run > RECONNECT_TIME:  # 设置为10小时 10*60*60=36000
                print("{}|ReConnect".format(datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%S.%f')))
                ws.close()
                ws = start_websocket(coin_pair_list, depth)
                start_run = current_time
            elif current_time - ping_time > 10:  # 每10秒ping一次
                ws.send(json.dumps({'event': 'ping'}))
                ping_time = current_time
        except Exception as e:
            print("{}|Exception|{}".format(datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%S.%f'),
                                           e.message))
            print("Traceback|{}".format(traceback.format_exc()))
            try:  # 出现异常之后重新建立连接
                ws.close()
            except:
                pass
            try:
                ExceptionInfoModel(host=ip, source='FETCH_OKEX_DEPTH', message=e.message,
                                   log_time=datetime.utcnow()).add()
                clear_dbsession()
            except:
                pass
            for fail_count in xrange(5):
                # 休息10s
                time.sleep(10)
                try:
                    ws = start_websocket(coin_pair_list, depth)
                    start_run = time.time()
                except:
                    print("{}|Exception|{}".format(datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%S.%f'),
                                                   e.message))
                    print("Traceback|{}".format(traceback.format_exc()))
                    # 第五次还不行
                    if fail_count >= 4:
                        raise
                else:
                    break
Ejemplo n.º 5
0
def run(coin_pair, depth='step0'):
    """

    :param coin_pair: string coin1:coin2|coin1:coin2
    :param depth: step0 - step5
    :return:
    """
    rds = Redis(host='localhost', port=6379, db=0)
    pair_part = coin_pair.split('|')
    coin_pair_list = [item.split(':') for item in pair_part]
    ws = start_websocket(coin_pair_list, depth)
    start_run = time.time()
    while 1:
        try:
            unziped_message = json.loads(
                zlib.decompress(ws.recv(), 16 + zlib.MAX_WBITS))
            if 'ping' in unziped_message:
                print("{}|PING|{}".format(
                    datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%S.%f'),
                    unziped_message))
                ws.send(json.dumps({'pong': unziped_message['ping']}))
            elif 'subbed' in unziped_message:
                print("{}|Sub|{}".format(
                    datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%S.%f'),
                    unziped_message['subbed']))
            else:  # 收到的是数据
                if 'ch' in unziped_message:
                    coin_symbol = unziped_message['ch'].split('.')[1]
                    if coin_symbol[-3:] in bigcoin_set:
                        coin1 = coin_symbol[-3:]
                        coin2 = coin_symbol[:-3]
                    else:
                        raise Exception(
                            'UnExcepted Coin Info {}'.format(coin_symbol))
                    start = time.time()
                    redis_key = get_redis_key(market=Market.HUOBI,
                                              coin1=coin1,
                                              coin2=coin2)
                    price_data = unziped_message['tick']
                    # 序列化复杂数据
                    price_data['ts'] = unziped_message['ts']
                    price_data['bids'] = json.dumps(price_data['bids'][:10])
                    price_data['asks'] = json.dumps(price_data['asks'][:10])
                    rds.hmset(redis_key, price_data)
                    end = time.time()
                    print("{}|Received|{}".format(
                        datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%S.%f'),
                        price_data))
                    print("{}|SetRedis|{}|{}".format(
                        datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%S.%f'),
                        redis_key, end - start))
                else:
                    print("{}|UnExceptedMessage|{}".format(
                        datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%S.%f'),
                        unziped_message))
            # 建立连接一段时间之后准备重建连接
            current_time = time.time()
            if current_time - start_run > RECONNECT_TIME:  # 设置为10小时 10*60*60=36000
                print("{}|ReConnect".format(
                    datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%S.%f')))
                ws.close()
                ws = start_websocket(coin_pair_list, depth)
                start_run = current_time

        except Exception as e:
            print("{}|Exception|{}".format(
                datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%S.%f'), e.message))
            print("Traceback|{}".format(traceback.format_exc()))
            try:  # 出现异常之后重新建立连接
                ws.close()
            except:
                pass
            try:
                ExceptionInfoModel(host=ip,
                                   source='FETCH_HUOBI_DEPTH',
                                   message=e.message,
                                   log_time=datetime.utcnow()).add()
                clear_dbsession()
            except:
                pass
            for fail_count in xrange(5):
                # 休息10s
                time.sleep(10)
                try:
                    ws = start_websocket(coin_pair_list, depth)
                    start_run = time.time()
                except:
                    print("{}|Exception|{}".format(
                        datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%S.%f'),
                        e.message))
                    print("Traceback|{}".format(traceback.format_exc()))
                    # 第五次还不行
                    if fail_count >= 4:
                        raise
                else:
                    break