Beispiel #1
0
def QA_risk_account_freeCash_frozenAssest(freeCash,frozenAssest):
    try:
        result=float(freeCash)/float(frozenAssest)
        return result
    except:
        return 0
        QA_util_log_expection('error in QA_risk_account_freeCash_frozenAssest')
        QA_util_log_expection('freeCash: '+str(freeCash))
        QA_util_log_expection('currentAssest: '+str(frozenAssest))
        QA_util_log_expection('expected result: '+str(float(freeCash)/float(frozenAssest)))
Beispiel #2
0
def QA_risk_eva_account(client, message, days):
    cookie = message['header']['cookie']
    account = message['body']['account']
    # 绩效表现指标分析
    """ 
    message= {
            'annualized_returns':annualized_returns,
            'benchmark_annualized_returns':benchmark_annualized_returns,
            'benchmark_assest':benchmark_assest,
            'vol':volatility_year,
            'benchmark_vol':benchmark_volatility_year,
            'sharpe':sharpe,
            'alpha':alpha,
            'beta':beta,
            'max_drop':max_drop,
            'win_rate':win_rate}
    """
    try:
        # 1.可用资金占当前总资产比重
        risk_account_freeCash_currentAssest = QA_risk_account_freeCash_currentAssest(
            float(account['assest_free']), float(account['assest_now']))
        # 2.当前策略速动比率(流动资产/流动负债)
        risk_account_freeCash_initAssest = QA_risk_account_freeCash_initAssest(
            account['assest_free'], account['init_assest'])
        risk_account_freeCash_frozenAssest = QA_risk_account_freeCash_frozenAssest(
            float(account['assest_free']), float(account['assest_fix']))

        return {""}

    except:
        QA_util_log_expection('error in risk evaluation')
Beispiel #3
0
def QA_fetch_bitmex_kline(symbol="XBTUSD",
                          count=100,
                          startTime="",
                          endTime='',
                          binSize="1m",
                          partial='false',
                          reverse='false',
                          proxies=proxies):
    body = ''

    url = '%s/trade/bucketed?' \
          'binSize=%s&partial=%s&symbol=%s&count=%d&reverse=%s&startTime=%s&endTime=%s' \
          % (Bitmex_base_url, binSize, partial, symbol, count, reverse, startTime, endTime)
    try:
        req = requests.get(url, timeout=TIMEOUT, proxies=proxies)
        remaining = int(req.headers['x-ratelimit-remaining'])
        if remaining <20:
            time.sleep(5)
        elif remaining <10:
            time.sleep(10)
        elif remaining <3:
            time.sleep(30)
    except ConnectTimeout:
        raise ConnectTimeout('Bitmex connect timeout when getting kline.')
    except (ssl.SSLError, requests.exceptions.SSLError) as ex:
        QA_util_log_info(ex)
    except Exception as ex:
        QA_util_log_expection(ex)

    return json.loads(req.content)
Beispiel #4
0
    def __QA_backtest_send_bid(self, __bid):
        if __bid.towards == 1:
            # 扣费以下这个订单时的bar的open扣费

            if self.account.cash_available > (__bid.price * __bid.amount):
                # 这是买入的情况 买入的时候主要考虑的是能不能/有没有足够的钱来买入
                __message = self.market.receive_bid(__bid)
                self.account.cash_available -= (__bid.price * __bid.amount)
                # 先扔进去买入,再通过返回的值来判定是否成功
                if __message['header']['status'] == 200 and __message['body'][
                        'bid']['amount'] > 0:
                    # 这个判断是为了 如果买入资金不充足,所以买入报了一个0量单的情况
                    # 如果买入量>0, 才判断为成功交易

                    self.account.QA_account_receive_deal(__message)
                    return __message
                else:

                    # self.account.cash_available += (__bid.price * __bid.amount) #报单还挂着 不能恢复
                    self.account.order_queue.append(__bid)

        # 下面是卖出操作,这里在卖出前需要考虑一个是否有仓位的问题:
        # 因为在股票中是不允许卖空操作的,所以这里是股票的交易引擎和期货的交易引擎的不同所在

        elif __bid.towards == -1:
            # 如果是卖出操作 检查是否有持仓
            # 股票中不允许有卖空操作
            # 检查持仓面板
            __amount_hold = self.QA_backtest_hold_amount(self, __bid.code)

            if __amount_hold > 0:

                __bid.amount = __amount_hold if __amount_hold < __bid.amount else __bid.amount
                self.account.hold_available[__bid.code] -= __bid.amount
                __message = self.market.receive_bid(__bid)

                print(__message)
                if __message['header']['status'] == 200:
                    self.account.QA_account_receive_deal(__message)
                    return __message
                else:
                    self.account.order_queue.append(__bid)
                    return __message

            else:
                err_info = 'Error: Not Enough amount for code %s in hold list' % str(
                    __bid.code)
                QA_util_log_expection(err_info)
                return err_info

        else:
            return "Error: No buy/sell towards"
Beispiel #5
0
def QA_SU_save_account_message(message, client):
    coll = client.quantaxis.backtest_history
    try:
        coll.insert({
            'time_stamp': message['body']['date_stamp'],
            "cookie": message['header']['cookie'],
            'user': message['header']['session']['user'],
            'strategy': message['header']['session']['strategy'],
            'cash': message['body']['account']['cash'],
            'hold': message['body']['account']['hold'],
            'history': message['body']['account']['history'],
            'assets': message['body']['account']['assets'],
            'detail': message['body']['account']['detail']
        })
    except:
        QA_util_log_expection('💢 error in saving backtest account')
Beispiel #6
0
def on_error(ws, error):
    QA_util_log_expection(error)
Beispiel #7
0
def QA_SU_save_okex_day(frequency, ui_log=None, ui_progress=None):
    """
    Save OKEx day kline
    """
    print('Under construction... I will test and debug soon...')
    return False
    market = 'OKEx'
    symbol_list = QA_fetch_crypto_asset_list(market='OKEx')
    col = DATABASE.crypto_asset_day
    col.create_index(
        [
            ('market',
             pymongo.ASCENDING),
            ("symbol",
             pymongo.ASCENDING),
            ("date_stamp",
             pymongo.ASCENDING)
        ],
        unique=True
    )

    end = datetime.datetime.now(tzutc())

    QA_util_log_info(
        'Starting DOWNLOAD PROGRESS of day Klines from OKEx... ',
        ui_log=ui_log,
        ui_progress=ui_progress
    )
    for index in range(len(symbol_list)):
        symbol_info = symbol_list.iloc[index]
        # 上架仅处理交易对
        QA_util_log_info(
            'The "{}" #{} of total in {}'.format(
                symbol_info['symbol'],
                index,
                len(symbol_list)
            ),
            ui_log=ui_log,
            ui_progress=ui_progress
        )
        QA_util_log_info(
            'DOWNLOAD PROGRESS {} '
            .format(str(float(index / len(symbol_list) * 100))[0:4] + '%'),
            ui_log=ui_log,
            ui_progress=ui_progress
        )
        query_id = {"symbol": symbol_info['symbol'], 'market': market}
        ref = col.find(query_id).sort('time_stamp', -1)

        if (col.count_documents(query_id) > 0):
            start_stamp = ref.next()['date_stamp']
            start_time = datetime.datetime.fromtimestamp(start_stamp)
            QA_util_log_info(
                'UPDATE_SYMBOL "{}" Trying updating "{}" from {} to {}'.format(
                    symbol_info['symbol'],
                    OKEx2QA_FREQUENCY_DICT[frequency],
                    QA_util_timestamp_to_str(start_time),
                    QA_util_timestamp_to_str(end)
                ),
                ui_log=ui_log,
                ui_progress=ui_progress
            )
        else:
            start_time = OKEx_MIN_DATE
            QA_util_log_info(
                'NEW_SYMBOL "{}" Trying downloading "{}" from {} to {}'.format(
                    symbol_info['symbol'],
                    OKEx2QA_FREQUENCY_DICT[frequency],
                    QA_util_timestamp_to_str(start_time),
                    QA_util_timestamp_to_str(end)
                ),
                ui_log=ui_log,
                ui_progress=ui_progress
            )

        data = QA_fetch_OKEx_kline(
            symbol_info['symbol'],
            time.mktime(start_time.utctimetuple()),
            time.mktime(end.utctimetuple()),
            frequency
        )
        if data is None:
            QA_util_log_info(
                'SYMBOL "{}" from {} to {} has no data'.format(
                    symbol_info['symbol'],
                    QA_util_timestamp_to_str(start_time),
                    QA_util_timestamp_to_str(end)
                ),
                ui_log=ui_log,
                ui_progress=ui_progress
            )
            continue
        QA_util_log_info(
            'SYMBOL "{}" Recived "{}" from {} to {} in total {} klines'.format(
                symbol_info['symbol'],
                OKEx2QA_FREQUENCY_DICT[frequency],
                time.strftime(
                    '%Y-%m-%d %H:%M:%S',
                    time.localtime(data[0]['time_stamp'])
                ),
                time.strftime(
                    '%Y-%m-%d %H:%M:%S',
                    time.localtime(data[-1]['time_stamp'])
                ),
                len(data)
            )
        )
        query_id = {
            "symbol": symbol_info['symbol'],
            'market': market,
            'date_stamp': {
                '$in': list(map(lambda x: x['date_stamp'],
                                data))
            }
        }
        if (symbol_info['symbol'] == 'LRCETH'):
            #print(len(data)) # To do: 这个会抛出异常,有空再解决
            pass
        if (col.count_documents(query_id) > 0):
            # 删掉重复数据
            col.delete_many(query_id)
        try:
            col.insert_many(data)
        except:
            QA_util_log_expection(
                'QA_SU_save_OKEx_day():Insert_many(kline) to {} got Exception {}'
                .format(symbol_info['symbol'],
                        len(data))
            )
            pass
    QA_util_log_info(
        'DOWNLOAD PROGRESS of day Klines from OKEx accomplished.',
        ui_log=ui_log,
        ui_progress=ui_progress
    )
Beispiel #8
0
def QA_SU_save_okex_symbol(client=DATABASE, market="OKEx"):
    """
    保存OKEx交易对信息
    """
    print('Under construction... I will test and debug soon...')
    return False
    QA_util_log_info('Downloading {:s} symbol list...'.format(market))

    # 保存 OKEx API 原始 Symbol 数据备查阅,自动交易用得着
    raw_symbol_lists = QA_util_save_raw_symbols(
        QA_fetch_okex_symbols,
        market
    )
    if (len(raw_symbol_lists) > 0):
        # 保存到 QUANTAXIS.crypto_asset_list 数字资产列表,为了跨市场统一查询做数据汇总
        symbol_lists = pd.DataFrame(raw_symbol_lists)

        # market,symbol为 mongodb 索引字段,保存之前必须要检查存在
        symbol_lists['market'] = market
        symbol_lists['category'] = 1
        symbol_lists.rename(
            {
                'baseAssetPrecision': 'price_precision',
                'baseAsset': 'base_currency',
                'quoteAsset': 'quote_currency',
                'status': 'state',
            },
            axis=1,
            inplace=True
        )
        symbol_lists['name'] = symbol_lists.apply(
            lambda x: '{:s}/{:s}'.
            format(x['base_currency'].upper(),
                   x['quote_currency'].upper()),
            axis=1
        )
        symbol_lists['desc'] = symbol_lists['name']
        symbol_lists['created_at'] = int(
            time.mktime(datetime.datetime.now().utctimetuple())
        )
        symbol_lists['updated_at'] = int(
            time.mktime(datetime.datetime.now().utctimetuple())
        )

        # 移除非共性字段,这些字段只有 broker 才关心,做对应交易所 broker 接口的时候在交易所 raw_symbol_lists
        # 数据中读取。
        symbol_lists.drop(
            [
                '_id',
                'price_precision',
                'baseCommissionPrecision',
                'quotePrecision',
                'filters',
                'icebergAllowed',
                'isMarginTradingAllowed',
                'isSpotTradingAllowed',
                'ocoAllowed',
                'orderTypes',
                'quoteCommissionPrecision',
                'quoteOrderQtyMarketAllowed',
            ],
            axis=1,
            inplace=True
        )

        # 删除不交易的交易对
        symbol_lists = symbol_lists[symbol_lists['state'].isin(['TRADING'])]

        coll_crypto_asset_list = client.crypto_asset_list
        coll_crypto_asset_list.create_index(
            [('market',
              pymongo.ASCENDING),
             ('symbol',
              pymongo.ASCENDING)],
            unique=True
        )
        try:
            query_id = {'market': market}
            if (coll_crypto_asset_list.count_documents(query_id) > 0):
                # 删掉重复数据
                query_id = {
                    'market': market,
                    'symbol': {
                        '$in': symbol_lists['symbol'].tolist()
                    }
                }
                coll_crypto_asset_list.delete_many(query_id)
            coll_crypto_asset_list.insert_many(
                QA_util_to_json_from_pandas(symbol_lists)
            )
            return symbol_lists
        except:
            QA_util_log_expection(
                'QA_SU_save_OKEx_symbol: Insert_many(symbol) to "crypto_asset_list" got Exception {}'
                .format(len(data))
            )
            pass
        return []
Beispiel #9
0
def QA_SU_save_okex_symbol(
    market="okex",
    client=DATABASE,
):
    """
    保存OKEx交易对信息
    """
    QA_util_log_info('Downloading {:s} symbol list...'.format(market))

    # 保存 OKEx API 原始 Symbol 数据备查阅,自动交易用得着
    raw_symbol_lists = QA_util_save_raw_symbols(QA_fetch_okex_symbols, market)
    if (len(raw_symbol_lists) > 0):
        # 保存到 QUANTAXIS.crypto_asset_list 数字资产列表,为了跨市场统一查询做数据汇总
        symbol_lists = pd.DataFrame(raw_symbol_lists)

        # market,symbol为 mongodb 索引字段,保存之前必须要检查存在
        symbol_lists['market'] = market
        symbol_lists['category'] = 1
        symbol_lists.rename(
            {
                'instrument_id': 'symbol',
                'tick_size': 'price_precision',
            },
            axis=1,
            inplace=True)

        symbol_lists['state'] = 'online'
        symbol_lists['name'] = symbol_lists.apply(lambda x: '{:s}/{:s}'.format(
            x['base_currency'].upper(), x['quote_currency'].upper()),
                                                  axis=1)
        symbol_lists['desc'] = symbol_lists['name']

        # 移除非共性字段,这些字段只有 broker 才关心,做对应交易所 broker 接口的时候在交易所 raw_symbol_lists
        # 数据中读取。
        symbol_lists.drop([
            'min_size',
            'size_increment',
        ],
                          axis=1,
                          inplace=True)

        symbol_lists['created_at'] = int(
            time.mktime(datetime.datetime.now().utctimetuple()))
        symbol_lists['updated_at'] = int(
            time.mktime(datetime.datetime.now().utctimetuple()))

        coll_crypto_asset_list = client.crypto_asset_list
        coll_crypto_asset_list.create_index([('market', pymongo.ASCENDING),
                                             ('symbol', pymongo.ASCENDING)],
                                            unique=True)
        try:
            query_id = {'market': market}
            if (coll_crypto_asset_list.count_documents(query_id) > 0):
                # 删掉重复数据
                query_id = {
                    'market': market,
                    'symbol': {
                        '$in': symbol_lists['symbol'].tolist()
                    }
                }
                coll_crypto_asset_list.delete_many(query_id)
            coll_crypto_asset_list.insert_many(
                QA_util_to_json_from_pandas(symbol_lists))
            return symbol_lists
        except:
            QA_util_log_expection(
                'QA_SU_save_okex_symbol(): Insert_many(symbol) to "crypto_asset_list" got Exception with {} klines'
                .format(len(data)))
            pass
        return []
Beispiel #10
0
def QA_SU_save_huobi_symbol(client=DATABASE, market="huobi"):
    """
    保存火币交易对信息
    """
    QA_util_log_info('Downloading {:s} symbol list...'.format(market))

    # 保存Huobi API 原始 Symbol 数据备查阅,自动交易用得着
    raw_symbol_lists = QA_util_save_raw_symbols(QA_fetch_huobi_symbols, market)

    if (len(raw_symbol_lists) > 0):
        # 保存到 QUANTAXIS.crypto_asset_list 数字资产列表,为了跨市场统一查询做数据汇总
        symbol_lists = pd.DataFrame(raw_symbol_lists)

        # market,symbol为 mongodb 索引字段,保存之前必须要检查存在
        symbol_lists['market'] = market
        symbol_lists['category'] = 1
        symbol_lists['name'] = symbol_lists.apply(lambda x: '{:s}/{:s}'.format(
            x['base-currency'].upper(), x['base-currency'].upper()),
                                                  axis=1)
        symbol_lists['desc'] = symbol_lists.apply(
            lambda x: '现货: {:s} 兑换 {:s}'.format(x['base-currency'], x[
                'quote-currency']),
            axis=1)

        # 移除非共性字段,这些字段只有 broker 才关心,做对应交易所 broker 接口的时候在交易所 raw_symbol_lists
        # 数据中读取。火币网超有个性的,注意字段里面的减号,不是下划线!!!
        symbol_lists.drop([
            '_id', 'amount-precision', 'leverage-ratio', 'max-order-amt',
            'min-order-amt', 'min-order-value', 'symbol-partition',
            'value-precision'
        ],
                          axis=1,
                          inplace=True)

        symbol_lists['created_at'] = int(
            time.mktime(datetime.datetime.now().utctimetuple()))
        symbol_lists['updated_at'] = int(
            time.mktime(datetime.datetime.now().utctimetuple()))

        coll_crypto_asset_list = client.crypto_asset_list
        coll_crypto_asset_list.create_index([('market', pymongo.ASCENDING),
                                             ('symbol', pymongo.ASCENDING)],
                                            unique=True)
        try:
            query_id = {'market': market}
            if (coll_crypto_asset_list.count_documents(query_id) > 0):
                # 删掉重复数据
                query_id = {
                    'market': market,
                    'symbol': {
                        '$in': symbol_lists['symbol'].tolist()
                    }
                }
                coll_crypto_asset_list.delete_many(query_id)
            coll_crypto_asset_list.insert_many(
                QA_util_to_json_from_pandas(symbol_lists))
            return symbol_lists
        except:
            QA_util_log_expection(
                'QA_SU_save_huobi_symbol(): Insert_many(symbol) to "crypto_asset_list" got Exception with {} klines'
                .format(len(data)))
            pass
        return []
Beispiel #11
0
def QA_SU_save_bitmex_symbol(
    market=bitmex_EXCHANGE,
    client=DATABASE,
):
    """
    保存 bitmex 交易对信息
    """
    market = market.upper()
    QA_util_log_info('Downloading {:s} symbol list...'.format(market))

    # 保存 bitmex API 原始 Symbol 数据备查阅,自动交易用得着
    raw_symbol_lists = QA_util_save_raw_symbols(QA_fetch_bitmex_symbols,
                                                market)
    if (len(raw_symbol_lists) > 0):
        # 保存到 QUANTAXIS.crypto_asset_list 数字资产列表,为了跨市场统一查询做数据汇总
        symbol_lists = pd.DataFrame(raw_symbol_lists)

        # market,symbol为 mongodb 索引字段,保存之前必须要检查存在
        symbol_lists['market'] = market
        symbol_lists['category'] = symbol_lists['typ']
        symbol_lists.rename(
            {
                'rootSymbol': 'base_currency',
                'quoteCurrency': 'quote_currency',
            },
            axis=1,
            inplace=True)
        symbol_lists['price_precision'] = symbol_lists.apply(
            lambda x: 2 + -1 * int(math.log10(float(x.maintMargin))), axis=1)
        symbol_lists['name'] = symbol_lists['symbol']
        symbol_lists['desc'] = ''

        # 移除非共性字段,这些字段只有 broker 才关心,做对应交易所 broker 接口的时候在交易所 raw_symbol_lists
        # 数据中读取。
        symbol_lists = symbol_lists[[
            'symbol', 'name', 'market', 'state', 'category', 'base_currency',
            'quote_currency', 'price_precision', 'desc'
        ]]
        if ('_id' in symbol_lists.columns.values):
            # 有时有,必须单独删除
            symbol_lists.drop([
                '_id',
            ], axis=1, inplace=True)
        symbol_lists['created_at'] = int(
            time.mktime(datetime.datetime.now().utctimetuple()))
        symbol_lists['updated_at'] = int(
            time.mktime(datetime.datetime.now().utctimetuple()))

        coll_cryptocurrency_list = client.cryptocurrency_list
        coll_cryptocurrency_list.create_index([('market', pymongo.ASCENDING),
                                               ('symbol', pymongo.ASCENDING)],
                                              unique=True)
        try:
            query_id = {'market': market}
            if (coll_cryptocurrency_list.count_documents(query_id) > 0):
                # 删掉重复数据
                query_id = {
                    'market': market,
                    'symbol': {
                        '$in': symbol_lists['symbol'].tolist()
                    }
                }
                coll_cryptocurrency_list.delete_many(query_id)
            coll_cryptocurrency_list.insert_many(
                QA_util_to_json_from_pandas(symbol_lists))
            return symbol_lists
        except:
            QA_util_log_expection(
                'QA_SU_save_bitmex_symbol(): Insert_many(symbol) to "cryptocurrency_list" got Exception with {} klines'
                .format(len(symbol_lists)))
            pass
        return []
Beispiel #12
0
def QA_SU_save_binance_min(frequency, ui_log=None, ui_progress=None):
    """
    Save binance min kline
    """
    market = 'binance'
    symbol_list = QA_fetch_crypto_asset_list(market='binance')
    col = DATABASE.crypto_asset_min
    col.create_index([('market', pymongo.ASCENDING),
                      ("symbol", pymongo.ASCENDING),
                      ('time_stamp', pymongo.ASCENDING),
                      ('date_stamp', pymongo.ASCENDING)])
    col.create_index([('market', pymongo.ASCENDING),
                      ("symbol", pymongo.ASCENDING),
                      ("type", pymongo.ASCENDING),
                      ('time_stamp', pymongo.ASCENDING)],
                     unique=True)

    end = datetime.datetime.now(tzutc())

    QA_util_log_info(
        'Starting DOWNLOAD PROGRESS of min Klines from binance... ',
        ui_log=ui_log,
        ui_progress=ui_progress)
    for index in range(len(symbol_list)):
        symbol_info = symbol_list.iloc[index]
        # 上架仅处理交易对
        QA_util_log_info('The "{}" #{} of total in {}'.format(
            symbol_info['symbol'], index, len(symbol_list)),
                         ui_log=ui_log,
                         ui_progress=ui_progress)
        QA_util_log_info('DOWNLOAD PROGRESS {} '.format(
            str(float(index / len(symbol_list) * 100))[0:4] + '%'),
                         ui_log=ui_log,
                         ui_progress=ui_progress)
        query_id = {
            "symbol": symbol_info['symbol'],
            'market': market,
            'type': Binance2QA_FREQUENCY_DICT[frequency]
        }
        ref = col.find(query_id).sort('time_stamp', -1)

        if (col.count_documents(query_id) > 0):
            start_stamp = ref.next()['time_stamp']
            start_time = datetime.datetime.fromtimestamp(start_stamp)
            QA_util_log_info(
                'UPDATE_SYMBOL "{}" Trying updating "{}" from {} to {}'.format(
                    symbol_info['symbol'],
                    Binance2QA_FREQUENCY_DICT[frequency],
                    QA_util_timestamp_to_str(start_time),
                    QA_util_timestamp_to_str(end)),
                ui_log=ui_log,
                ui_progress=ui_progress)
        else:
            start_time = BINANCE_MIN_DATE
            QA_util_log_info(
                'NEW_SYMBOL "{}" Trying downloading "{}" from {} to {}'.format(
                    symbol_info['symbol'],
                    Binance2QA_FREQUENCY_DICT[frequency],
                    QA_util_timestamp_to_str(start_time),
                    QA_util_timestamp_to_str(end)),
                ui_log=ui_log,
                ui_progress=ui_progress)

        data = QA_fetch_binance_kline(symbol_info['symbol'],
                                      time.mktime(start_time.utctimetuple()),
                                      time.mktime(end.utctimetuple()),
                                      frequency)
        if data is None:
            QA_util_log_info('SYMBOL "{}" from {} to {} has no data'.format(
                symbol_info['symbol'], QA_util_timestamp_to_str(start_time),
                QA_util_timestamp_to_str(end)))
            continue
        QA_util_log_info(
            'SYMBOL "{}" Recived "{}" from {} to {} in total {} klines'.format(
                symbol_info['symbol'], Binance2QA_FREQUENCY_DICT[frequency],
                time.strftime('%Y-%m-%d %H:%M:%S',
                              time.localtime(data[0]['time_stamp'])),
                time.strftime('%Y-%m-%d %H:%M:%S',
                              time.localtime(data[-1]['time_stamp'])),
                len(data)),
            ui_log=ui_log,
            ui_progress=ui_progress)
        query_id = {
            "symbol": symbol_info['symbol'],
            'market': market,
            'type': Binance2QA_FREQUENCY_DICT[frequency],
            'time_stamp': {
                '$in': list(map(lambda x: x['time_stamp'], data))
            }
        }
        if (col.count_documents(query_id) > 0):
            # 删掉重复数据
            col.delete_many(query_id)
        try:
            col.insert_many(data)
        except:
            QA_util_log_expection(
                'QA_SU_save_binance_min():Insert_many(kline) to {} got Exception {}'
                .format(symbol_info['symbol'], len(data)))
            pass
    QA_util_log_info(
        'DOWNLOAD PROGRESS of min Klines from binance accomplished.',
        ui_log=ui_log,
        ui_progress=ui_progress)
    def QA_backtest_send_order(self, __code: str, __amount: int,
                               __towards: int, __order: dict):
        """
        2017/8/4
        委托函数
        在外部封装的一个报价接口,尽量满足和实盘一样的模式

        输入
        =============
        买入/卖出
        股票代码
        买入/卖出数量
        委托模式*
            0 限价委托 LIMIT ORDER
            1 市价委托 MARKET ORDER
            2 严格模式(买入按最高价 卖出按最低价) STRICT ORDER


        输出
        =============
        返回: 

        委托状态/委托id

        成交状态/成交id/成交量/成交价

        错误/错误id/

        return bid_status,trade_status,error
        """

        # 必须是100股的倍数
        __amount = int(__amount / 100) * 100

        # self.__QA_backtest_set_bid_model()
        if __order['bid_model'] in [
                'limit', 'Limit', 'Limited', 'limited', 'l', 'L', 0, '0'
        ]:
            # 限价委托模式
            __bid_price = __order['price']
        elif __order['bid_model'] in [
                'Market', 'market', 'MARKET', 'm', 'M', 1, '1'
        ]:
            __bid_price = 'market_price'
        elif __order['bid_model'] in ['strict', 'Strict', 's', 'S', '2', 2]:
            __bid_price = 'strict_price'
        elif __order['bid_model'] in [
                'close', 'close_price', 'c', 'C', '3', 3
        ]:
            __bid_price = 'close_price'
        __bid = self.bid.bid

        __bid['order_id'] = str(random.random())
        __bid['user'] = self.setting.QA_setting_user_name
        __bid['strategy'] = self.strategy_name
        __bid['code'] = __code
        __bid['date'] = self.running_date
        __bid['price'] = __bid_price
        __bid['amount'] = __amount

        if __towards == 1:
            # 这是买入的情况 买入的时候主要考虑的是能不能/有没有足够的钱来买入

            __bid['towards'] = 1
            __message = self.market.receive_bid(__bid, self.setting.client)

            # 先扔进去买入,再通过返回的值来判定是否成功

            if float(self.account.message['body']['account']['cash'][-1]) > \
                    float(__message['body']['bid']['price']) * \
                    float(__message['body']['bid']['amount']):
                # 这里是买入资金充足的情况
                # 不去考虑
                pass
            else:
                # 如果买入资金不充足,则按照可用资金去买入
                # 这里可以这样做的原因是在买入的时候 手续费为0
                __message['body']['bid']['amount'] = int(
                    float(self.account.message['body']['account']['cash'][-1])
                    / float(
                        float(str(__message['body']['bid']['price'])[0:5]) *
                        100)) * 100

            if __message['body']['bid']['amount'] > 0:
                # 这个判断是为了 如果买入资金不充足,所以买入报了一个0量单的情况
                #如果买入量>0, 才判断为成功交易
                self.account.QA_account_receive_deal(__message)
                return __message

        # 下面是卖出操作,这里在卖出前需要考虑一个是否有仓位的问题:
        # 因为在股票中是不允许卖空操作的,所以这里是股票的交易引擎和期货的交易引擎的不同所在

        elif __towards == -1:
            # 如果是卖出操作 检查是否有持仓
            # 股票中不允许有卖空操作
            # 检查持仓面板
            __amount_hold = self.QA_backtest_hold_amount(self, __code)
            if __amount_hold > 0:
                __bid['towards'] = -1
                if __amount_hold >= __amount:
                    pass
                else:
                    __bid['amount'] = __amount_hold
                __message = self.market.receive_bid(__bid, self.setting.client)
                if __message['header']['status'] == 200:
                    self.account.QA_account_receive_deal(__message)
                return __message
            else:
                err_info = 'Error: Not Enough amount for code %s in hold list' % str(
                    __code)
                QA_util_log_expection(err_info)
                return err_info

        else:
            return "Error: No buy/sell towards"