def __init__(self, account_type, config, sandbox_debug=False, logger_name=None, open_time_adj=0, close_time_adj=0): # get logger self.logger = Tiger.defualt_logger if ( logger_name is None) else logging.getLogger(logger_name) # read user info, position record from local files self.__user_info = io_util.read_config(file_path=config['tiger_path'], file_name='user_info.json') self.__position_record = io_util.read_config( file_path=config['config_path'], file_name='tiger_position_record.json') self.record = self.__position_record[account_type].copy() self.eod_api_key = config['api_key']['eod'] # set account, account type self.account = self.__user_info[account_type] self.account_type = account_type # initialize client_config self.client_config = TigerOpenClientConfig(sandbox_debug=sandbox_debug) self.client_config.private_key = read_private_key( config['tiger_path'] + self.__user_info['private_key_name']) self.client_config.tiger_id = str(self.__user_info['tiger_id']) self.client_config.language = Language.en_US self.client_config.account = self.account # get quote/trade clients, assets, positions self.quote_client = QuoteClient(self.client_config) self.trade_client = TradeClient(self.client_config) self.positions = self.trade_client.get_positions(account=self.account) self.assets = self.trade_client.get_assets(account=self.account) # get market status and trade time self.update_trade_time(open_time_adj=open_time_adj, close_time_adj=close_time_adj) # update position record self.synchronize_position_record(config=config) self.logger.info(f'[tiger]: Tiger instance created: {logger_name}')
def __init__(self, account_type, config, market='US', is_encrypt=False, logger_name=None): # get logger self.logger = Futu.defualt_logger if ( logger_name is None) else logging.getLogger(logger_name) # read user info, position record from local files self.__user_info = io_util.read_config(file_path=config['futu_path'], file_name='user_info.json') self.__position_record = io_util.read_config( file_path=config['config_path'], file_name='futu_position_record.json') self.record = self.__position_record[account_type].copy() self.eod_api_key = config['api_key']['eod'] # set account type self.account_type = account_type # get quote and trade context, assets, positions self.open_quote_context(host=self.__user_info['host'], port=self.__user_info['port'], is_encrypt=is_encrypt) self.open_trade_context(market=market, host=self.__user_info['host'], port=self.__user_info['port'], is_encrypt=is_encrypt) if self.trade_context is not None: self.trade_context.unlock_trade(self.__user_info['unlock_pwd']) ret_positions, self.positions = self.trade_context.position_list_query( trd_env=account_type) ret_assets, self.assets = self.trade_context.accinfo_query( trd_env=account_type) else: self.positions = None self.assets = None self.logger.error('trade_context not available') # update position record self.synchronize_position_record(config=config) self.logger.info(f'[futu]: Futu instance created: {logger_name}')
def update_portfolio_record(self, config, position_summary=None, is_print=True): # get position summary if position_summary is None: position_summary = self.get_position_summary(get_briefs=False) position_summary.set_index('symbol', inplace=True) position_summary = position_summary.round(2) # get assets summary net_value = 0 market_value = 0 cash = 0 asset_summary = self.get_asset_summary() if len(asset_summary) > 0: net_value = asset_summary.loc[0, 'total_assets'] market_value = asset_summary.loc[0, 'market_val'] cash = asset_summary.loc[0, 'cash'] # post process if market_value == float('inf'): market_value = position_summary['market_value'].sum().round(2) # load portfolio record portfolio_record = io_util.read_config(file_path=config['config_path'], file_name='portfolio.json') old_net_value = portfolio_record['futu'][self.account_type].get( 'net_value') support = portfolio_record['futu'][self.account_type].get( 'portfolio').get('support') resistant = portfolio_record['futu'][self.account_type].get( 'portfolio').get('resistant') # update portfolio record for current account portfolio_record['futu'][ self.account_type]['portfolio'] = position_summary.to_dict() portfolio_record['futu'][ self.account_type]['portfolio']['support'] = {} portfolio_record['futu'][ self.account_type]['portfolio']['resistant'] = {} quantity = portfolio_record['futu'][ self.account_type]['portfolio'].get('quantity') if quantity is not None: if support is not None: for symbol in quantity.keys(): portfolio_record['futu'][self.account_type]['portfolio'][ 'support'][symbol] = support.get(symbol) if resistant is not None: for symbol in quantity.keys(): portfolio_record['futu'][self.account_type]['portfolio'][ 'resistant'][symbol] = resistant.get(symbol) portfolio_record['futu'][ self.account_type]['market_value'] = market_value portfolio_record['futu'][self.account_type]['net_value'] = net_value portfolio_record['futu'][self.account_type]['cash'] = cash portfolio_record['futu'][self.account_type]['updated'] = datetime.now( ).strftime(format="%Y-%m-%d %H:%M:%S") io_util.create_config_file(config_dict=portfolio_record, file_path=config['config_path'], file_name='portfolio.json') # print change if is_print: self.logger.info( f'[{self.account_type[:4]}]: net value {old_net_value} --> {net_value}' )
def update_position_record(self, config, init_cash=None, init_position=None, start_time=None, end_time=None, is_print=True): # set default values init_cash = config['trade']['init_cash'][self.account_type] if ( init_cash is None) else init_cash init_position = 0 if (init_position is None) else init_position start_time = datetime.now().strftime( format="%Y-%m-%d") if (start_time is None) else start_time end_time = start_time if (end_time is None) else end_time try: # get today filled orders ret_orders, orders = self.trade_context.history_order_list_query( trd_env=self.account_type, status_filter_list=[ OrderStatus.FILLED_PART, OrderStatus.FILLED_ALL ], start=start_time, end=end_time) # update position records if ret_orders == 0: for index, row in orders.iterrows(): symbol = row['code'].split('.')[1] # order.contract.symbol action = row['trd_side'] # order.action quantity = row[ 'dealt_qty'] # order.quantity - order.remaining commission = 3 # order.commission avg_fill_price = row[ 'dealt_avg_price'] # order.avg_fill_price # init record if not exist if symbol not in self.record.keys(): self.record[symbol] = { 'cash': init_cash, 'position': init_position } record_cash = self.record[symbol]['cash'] record_position = self.record[symbol]['position'] # calculate new cash and position if action == 'BUY': cost = avg_fill_price * quantity + commission new_cash = record_cash - cost new_position = record_position + quantity elif action == 'SELL': acquire = avg_fill_price * quantity - commission new_cash = record_cash + acquire new_position = record_position - quantity else: new_cash = self.record[symbol]['cash'] new_position = self.record[symbol]['position'] # update record if new_cash >= 0 and new_position >= 0: self.record[symbol]['cash'] = new_cash self.record[symbol]['position'] = new_position if is_print: self.logger.info( f'[{self.account_type[:4]}]: updating position record for {symbol} {record_cash, record_position} -> {new_cash, new_position}' ) # update __position_record # self.record['updated'] = datetime.now().strftime(format="%Y-%m-%d %H:%M:%S") self.__position_record = io_util.read_config( file_path=config['config_path'], file_name='futu_position_record.json') self.__position_record[self.account_type] = self.record.copy() self.__position_record['updated'][ self.account_type] = datetime.now().strftime( format="%Y-%m-%d %H:%M:%S") io_util.create_config_file( config_dict=self.__position_record, file_path=config['config_path'], file_name='futu_position_record.json') elif ret_orders == -1: self.logger.error(f'[erro]: fail getting orders - {orders}') except Exception as e: self.logger.exception( f'[erro]: fail updating position records for {self.account_type}, {e}' )
def update_position_record(self, config, init_cash=None, init_position=None, start_time=None, end_time=None, is_print=True): # set default values init_cash = config['trade']['init_cash'][self.account_type] if ( init_cash is None) else init_cash init_position = 0 if (init_position is None) else init_position start_time = self.trade_time['pre_open_time'].strftime( format="%Y-%m-%d %H:%M:%S") if (start_time is None) else start_time end_time = self.trade_time['post_close_time'].strftime( format="%Y-%m-%d %H:%M:%S") if (end_time is None) else end_time try: # get today filled orders orders = self.trade_client.get_filled_orders(start_time=start_time, end_time=end_time) # update position records for order in orders: symbol = order.contract.symbol action = order.action quantity = order.quantity - order.remaining commission = order.commission avg_fill_price = order.avg_fill_price # init record if not exist if symbol not in self.record.keys(): self.record[symbol] = { 'cash': init_cash, 'position': init_position } record_cash = self.record[symbol]['cash'] record_position = self.record[symbol]['position'] # calculate new cash and position if action == 'BUY': cost = avg_fill_price * quantity + commission new_cash = record_cash - cost new_position = record_position + quantity elif action == 'SELL': acquire = avg_fill_price * quantity - commission new_cash = record_cash + acquire new_position = record_position - quantity else: new_cash = record_cash new_position = record_position # update record if new_cash >= 0 and new_position >= 0: self.record[symbol]['cash'] = new_cash self.record[symbol]['position'] = new_position if is_print: self.logger.info( f'[{self.account_type[:4]}]: updating position record for {symbol} {record_cash, record_position} -> {new_cash, new_position}' ) # update __position_record # self.record['updated'] = datetime.datetime.now().strftime(format="%Y-%m-%d %H:%M:%S") self.__position_record = io_util.read_config( file_path=config['config_path'], file_name='tiger_position_record.json') self.__position_record[self.account_type] = self.record.copy() self.__position_record['updated'][ self.account_type] = datetime.datetime.now().strftime( format="%Y-%m-%d %H:%M:%S") io_util.create_config_file(config_dict=self.__position_record, file_path=config['config_path'], file_name='tiger_position_record.json') except Exception as e: self.logger.exception( f'[erro]: fail updating position records for {self.account_type}, {e}' )