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)))
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')
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)
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"
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')
def on_error(ws, error): QA_util_log_expection(error)
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 )
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 []
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 []
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 []
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 []
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"