Exemple #1
0
def get_quote(begin_time=None, Symbol=None):
    client_config = get_client_config()
    quote_client = QuoteClient(client_config)
    #timeArray = time.strptime("2000-01-01 00:00:00","%Y-%m-%d %H:%M:%S")
    #begin_time=int(time.mktime(timeArray))*10**3
    return quote_client.get_bars('600570',
                                 period=BarPeriod.ONE_MINUTE,
                                 begin_time=begintimestamp)
    def __init__(self):
        self.client_config = get_client_config()
        self.trade_client = TradeClient(self.client_config)
        self.openapi_client = QuoteClient(self.client_config, logger=logger)
        # 初始化 pushclient

        protocol, host, port = self.client_config.socket_host_port
        self.push_client = PushClient(host, port, use_ssl=(protocol == 'ssl'))
        self.push_client.connect(self.client_config.tiger_id, self.client_config.private_key)
Exemple #3
0
def get_symbol_names():
    """
    获取所有股票代码和名称
    :return: 代码与名称数组
    """
    config = get_client_config()
    quant_client = QuoteClient(config)
    symbols = quant_client.get_symbol_names(market=Market.ALL)

    return symbols
Exemple #4
0
def get_quote():
    client_config = get_client_config()
    quote_client = QuoteClient(client_config)
    #    return quote_client.get_market_status(Market.ALL) #股市开市情况
    return quote_client.get_briefs(symbols=['AAPL', '00700', '600519'],
                                   include_ask_bid=True,
                                   right=QuoteRight.BR)
    #return quote_client.get_briefs(symbols=['00700', '600519'], include_ask_bid=True, right=QuoteRight.BR)
    #    return quote_client.get_timeline('AAPL', period=TimelinePeriod.DAY, include_hour_trading=True)
    return quote_client.get_bars('600570')
Exemple #5
0
def get_quote_apis():
    client_config = get_client_config()
    quote_client = QuoteClient(client_config)
    quote_client.get_market_status(Market.US)
    quote_client.get_briefs(symbols=['AAPL', '00700', '600519'],
                            include_ask_bid=True,
                            right=QuoteRight.BR)
    quote_client.get_timeline(['AAPL'],
                              period=TimelinePeriod.DAY,
                              include_hour_trading=True)
    quote_client.get_bars(['AAPL'])
Exemple #6
0
    def __init__(self):
        """"""
        logging.basicConfig(level=logging.INFO,
                    format='%(asctime)s %(levelname)s %(message)s',
                    filemode='a', )
        logger = logging.getLogger('TigerOpenApi')
        client_config = get_client_config()
        self.openapi_client = QuoteClient(client_config, logger=logger)

        self.inited = False
        self.symbols = set()
Exemple #7
0
def get_quote():
    client_config = get_client_config()
    quote_client = QuoteClient(client_config)
    #quote_client.get_market_status(Market.ALL)
    #quote_client.get_briefs(symbols=['AAPL', '00700', '600519'], include_ask_bid=True, right=QuoteRight.BR)
    #quote_client.get_briefs(symbols=['00700', '600519'], include_ask_bid=True, right=QuoteRight.BR)
    #quote_client.get_timeline('AAPL', period=TimelinePeriod.5MIN, begin_time='20181213', include_hour_trading=True)
    #    today_time = time.strftime('%Y-%m-%d 00:00:00',time.localtime(time.time()))
    timeArray = time.strptime("2000-01-01 00:00:00", "%Y-%m-%d %H:%M:%S")
    begin_time = int(time.mktime(timeArray)) * 10**3
    return quote_client.get_bars('600570',
                                 period=BarPeriod.ONE_MINUTE,
                                 begin_time=begin_time)
Exemple #8
0
    def connect_quote(self):
        """
        Connect to market data server.
        """
        try:
            self.quote_client = QuoteClient(self.client_config)
            self.symbol_names = dict(
                self.quote_client.get_symbol_names(lang=Language.zh_CN))
            self.query_contract()
        except ApiException:
            self.write_log("查询合约失败")
            return

        self.write_log("行情接口连接成功")
    def connect_quote(self):
        """
        Connect to market data server.
        """
        try:
            self.quote_client = QuoteClient(self.client_config)
            self.symbol_names = dict(
                self.quote_client.get_symbol_names(lang=Language.zh_CN))
            self.query_contract()
        except ApiException:
            self.write_log(" queries contract failure ")
            return

        self.write_log(" quotes interfacing success ")
        self.write_log(" contract query succeeds ")
Exemple #10
0
    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}')
Exemple #11
0
def get_quote_client():
    """
    获取 QuoteClient
    :return: QuoteClient
    """
    config = get_client_config()
    quote_client = QuoteClient(config)

    return quote_client
Exemple #12
0
    def connect_quote(self):
        """
        Connect to market data server.
        """
        try:
            self.quote_client = QuoteClient(self.client_config)
            self.symbol_names = dict(
                self.quote_client.get_symbol_names(lang=Language.zh_CN))
            self.query_contract()
        except ApiException:
            self.write_log("查询合约失败")
            return

        self.write_log("行情接口连接成功")
        self.write_log("合约查询成功")
Exemple #13
0
def get_bars_from_cache(quote_client: QuoteClient,
                        symbols,
                        period=BarPeriod.DAY,
                        begin_time=-1,
                        end_time=-1,
                        right=QuoteRight.BR,
                        limit=10000,
                        lang=None):
    """
    走文件缓存,加快多次访问速度
    :param quote_client:
    :param symbols:
    :param period:
    :param begin_time:
    :param end_time:
    :param right:
    :param limit:
    :param lang:
    :return:
    """
    md5 = tuple_2_md5(
        [symbols, period, begin_time, end_time, right, limit, lang])

    # 从文件缓存获取数据
    data = read_pd_from_cache(md5)

    if data is not None:
        return data

    # 调用API获取
    if data is None:
        data = quote_client.get_bars(symbols=symbols,
                                     period=period,
                                     begin_time=begin_time,
                                     end_time=end_time,
                                     limit=limit)

        if not data.empty:
            write_pd_2_cache(data, md5)

    # data = offset_by_date(data)
    return data
Exemple #14
0
def get_quote_client(account='global_account'):
    client_config = get_client_config(account=account)
    quote_client = QuoteClient(client_config)

    return quote_client
Exemple #15
0
class TigerGateway(BaseGateway):
    """"""
    default_setting = {
        "tiger_id": "",
        "account": "",
        "服务器": ["标准", "环球", "仿真"],
        "private_key": "",
    }
    # 在 VNTRADER 中展示的交易所列表
    exchanges = [
        Exchange.SEHK, Exchange.SMART, Exchange.SSE, Exchange.SZSE,
        Exchange.CFE, Exchange.ECBOT, Exchange.CMECRYPTO, Exchange.CFE,
        Exchange.GLOBEX, Exchange.NYMEX, Exchange.SGX, Exchange.HKFE
    ]

    def __init__(self, event_engine):
        """Constructor"""
        super(TigerGateway, self).__init__(event_engine, "TIGER")

        self.tiger_id = ""
        self.account = ""
        self.server = ""
        self.language = ""

        self.client_config = None
        self.quote_client = None
        self.push_client = None

        self.local_id = 1000000
        self.tradeid = 0

        self.active = False
        self.queue = Queue()
        self.pool = None

        self.ID_TIGER2VT = {}
        self.ID_VT2TIGER = {}
        self.ticks = {}
        self.trades = set()
        self.contracts = {}
        self.symbol_names = {}

        # {symbol NQ1909: (exchange, trading_contract)}
        self.vt_tiger_symbol_map = {}

        self.push_connected = False
        self.subscribed_symbols = set()

    def run(self):
        """"""
        while self.active:
            try:
                func, args = self.queue.get(timeout=0.1)
                func(*args)
            except Empty:
                pass
            except Exception:
                self.write_log('方法%s调用失败,参数为%s' % (func.__name__, args))

    def add_task(self, func, *args):
        """"""
        self.queue.put((func, [*args]))

    def connect(self, setting: dict):
        """"""
        self.private_key = setting["private_key"]
        self.tiger_id = setting["tiger_id"]
        self.server = setting["服务器"]
        self.account = setting["account"]
        self.languege = Language.zh_CN

        # Start thread pool for REST call
        self.active = True
        self.pool = Pool(5)
        self.pool.apply_async(self.run)

        # Put connect task into quque.
        self.init_client_config()
        self.add_task(self.connect_quote)
        self.add_task(self.connect_trade)
        self.add_task(self.connect_push)

    def init_client_config(self, sandbox=SANDBOX):
        """"""
        self.client_config = TigerOpenClientConfig(sandbox_debug=sandbox)
        self.client_config.private_key = self.private_key
        self.client_config.tiger_id = self.tiger_id
        self.client_config.account = self.account
        self.client_config.language = self.language

    def connect_quote(self):
        """
        Connect to market data server.
        """
        try:
            self.quote_client = QuoteClient(self.client_config)
            self.symbol_names = dict(
                self.quote_client.get_symbol_names(lang=Language.zh_CN))
            self.query_contract()
        except ApiException:
            self.write_log("查询合约失败")
            return

        self.write_log("行情接口连接成功")

    def connect_trade(self):
        """
        Connect to trade server.
        """
        self.write_log('查询交易接口')
        self.trade_client = TradeClient(self.client_config)
        try:
            self.add_task(self.query_order)
            self.add_task(self.query_position)
            self.add_task(self.query_account)
        except ApiException:
            self.write_log("交易接口连接失败")
            return

        self.write_log("交易接口连接成功")

    def connect_push(self):
        """
        Connect to push server.
        """
        protocol, host, port = self.client_config.socket_host_port
        self.push_client = PushClient(host, port, (protocol == "ssl"))

        self.push_client.quote_changed = self.on_quote_change
        self.push_client.asset_changed = self.on_asset_change
        self.push_client.position_changed = self.on_position_change
        self.push_client.order_changed = self.on_order_change
        self.push_client.connect_callback = self.on_push_connected
        self.push_client.disconnect_callback = self.on_disconnected

        self.push_client.connect(self.client_config.tiger_id,
                                 self.client_config.private_key)

    def subscribe(self, req: SubscribeRequest):
        """"""
        self.subscribed_symbols.add(req.symbol)

        if self.push_connected:
            self.push_client.subscribe_quote(symbols=[req.symbol],
                                             quote_key_type=QuoteKeyType.ALL)

    def on_push_connected(self):
        """"""
        self.push_connected = True
        self.write_log("推送接口连接成功")

        self.push_client.subscribe_asset(account=self.account)
        self.push_client.subscribe_position(account=self.account)
        self.push_client.subscribe_order(account=self.account)

        self.push_client.subscribe_quote(list(self.subscribed_symbols))

    def on_disconnected(self):
        self.write_log('推送接口断开链接')
        self.push_connected = False

    def on_quote_change(self, tiger_symbol: str, data: list, trading: bool):
        """"""
        data = dict(data)
        symbol, exchange = self.get_vt_symbol_exchange(tiger_symbol)

        # 如果只推送了时间戳,或只推送了timeline,不向策略中推送新的tick事件
        if 'latest_price' not in data and 'bid_price' not in data:
            return

        tick = self.ticks.get(symbol, None)
        if not tick:
            tick = TickData(
                symbol=symbol,
                exchange=exchange,
                gateway_name=self.gateway_name,
                datetime=datetime.now(),
                name=symbol,
            )
            self.ticks[symbol] = tick
        # 本地止损单的设计依赖于limit up 与limit down(张跌停价格)。目前API中没有提供。
        # 所以这里用high low 来代替 limit up 与limit down
        tick.datetime = datetime.fromtimestamp(int(data["timestamp"]) / 1000)
        tick.volume = data.get("volume", tick.volume)
        tick.ask_volume_1 = data.get("ask_size", tick.ask_volume_1)
        tick.bid_volume_1 = data.get("bid_size", tick.bid_volume_1)
        tick.pre_close = data.get("prev_close", tick.pre_close)
        tick.last_price = data.get("latest_price", tick.last_price)
        tick.open_price = data.get("open", tick.open_price)
        tick.high_price = data.get("high", tick.high_price)
        tick.low_price = data.get("low", tick.low_price)
        tick.ask_price_1 = data.get("ask_price", tick.ask_price_1)
        tick.bid_price_1 = data.get("bid_price", tick.bid_price_1)
        tick.limit_down = tick.low_price
        tick.limit_up = tick.high_price

        self.on_tick(copy(tick))

    def on_asset_change(self, tiger_account: str, data: list):
        """"""
        data = dict(data)
        if "net_liquidation" not in data:
            return
        segment = data.get('segment')
        # 环球账户, 只推送summary的信息,含股票期货
        if segment == 'summary' or segment is None:
            account = tiger_account
        # 标准账户有『子账户』的概念, 分别推送股票与期货账户的信息
        elif segment == 'S':
            account = 'Security'
        elif segment == 'C':
            account = 'Commodity'

        account = AccountData(
            accountid=account,
            balance=round(data["net_liquidation"], 2),
            frozen=0.0,
            gateway_name=self.gateway_name,
        )
        self.on_account(account)

    def on_position_change(self, tiger_account: str, data: list):
        """"""
        if tiger_account != self.account:
            return
        data = dict(data)
        # 处理标准与环球账户的差异, 环球的账户的期货信息要从originsymbol中获取,标准的从symbol中获取
        origin_symbol = data.get("origin_symbol")
        if origin_symbol:
            symbol = origin_symbol2symbol(origin_symbol)
        else:
            symbol = data.get('symbol')
        symbol, exchange = self.get_vt_symbol_exchange(symbol)

        pos = PositionData(
            symbol=symbol,
            exchange=exchange,
            direction=Direction.NET,
            volume=int(data["quantity"]),
            frozen=0.0,
            price=round(data["average_cost"], 2),
            pnl=round(data["unrealized_pnl"], 2),
            gateway_name=self.gateway_name,
        )
        self.on_position(pos)

    def on_order_change(self, tiger_account: str, data: list):
        """"""
        # 处理订阅了多个账户的情况
        if tiger_account != self.account:
            return
        data = dict(data)
        origin_symbol = data.get("origin_symbol")
        if origin_symbol:
            symbol = origin_symbol2symbol(origin_symbol)
        else:
            symbol = data.get('symbol')
        symbol, exchange = self.get_vt_symbol_exchange(symbol)
        status = STATUS_TIGER2VT[data["status"]]
        order_time = data.get('order_time')
        order = OrderData(
            symbol=symbol,
            exchange=exchange,
            orderid=self.ID_TIGER2VT.get(str(data["id"]),
                                         self.get_new_local_id()),
            direction=DIRECTION_TIGER2VT[data.get('action')],
            price=data.get("limit_price", 0),
            volume=data["quantity"],
            traded=data["filled"],
            status=status,
            time=datetime.fromtimestamp(order_time / 1000).strftime("%H:%M:%S")
            if order_time else datetime.now().strftime("%H:%M:%S"),
            gateway_name=self.gateway_name,
        )
        self.ID_TIGER2VT[str(data["id"])] = order.orderid
        self.on_order(order)

        if status == Status.ALLTRADED:
            self.tradeid += 1

            trade = TradeData(
                symbol=symbol,
                exchange=exchange,
                direction=DIRECTION_TIGER2VT[data.get('action')],
                tradeid=self.tradeid,
                orderid=self.ID_TIGER2VT[str(data["id"])],
                price=data["avg_fill_price"],
                volume=data["filled"],
                time=datetime.fromtimestamp(order_time /
                                            1000).strftime("%H:%M:%S")
                if order_time else datetime.now().strftime("%H:%M:%S"),
                gateway_name=self.gateway_name,
            )
            self.on_trade(trade)

    def get_new_local_id(self):
        self.local_id += 1
        return self.local_id

    def send_order(self, req: OrderRequest):
        """"""
        local_id = self.get_new_local_id()
        order = req.create_order_data(local_id, self.gateway_name)

        self.on_order(order)
        self.add_task(self._send_order, req, local_id)
        return order.vt_orderid

    def _send_order(self, req: OrderRequest, local_id):
        """"""
        try:  # 主要处理一些API层面的校验带来的异常,如下单价格错误。
            contract = self.get_trading_contract(req.symbol)
            order = self.trade_client.create_order(
                account=self.account,
                contract=contract,
                action=DIRECTION_VT2TIGER[req.direction],
                order_type=ORDERTYPE_VT2TIGER[req.type],
                quantity=int(req.volume),
                limit_price=round(req.price, 2),
            )

            self.trade_client.place_order(order)
            self.ID_TIGER2VT[str(order.id)] = local_id
            self.ID_VT2TIGER[local_id] = str(order.id)
        except Exception:
            # 一些订单会在API层面被拒掉,不会推送订单的回报,这里模拟一个订单回报。
            # 目前gateway 只实现了mkt 和limit 两种类型的订单,使用其他类型的订单也会出现异常。
            # 这时本地的订单已经存在了, 所以返回一个状态为rejected的虚拟订单
            symbol = contract2symbol(order.contract)
            symbol, exchange = self.get_vt_symbol_exchange(symbol)

            mock_order = OrderData(
                symbol=symbol,
                exchange=exchange,
                orderid=local_id,
                direction=DIRECTION_TIGER2VT[order.action],
                price=order.limit_price,
                volume=order.quantity,
                traded=0,
                status=Status.REJECTED,
                time=datetime.now().strftime("%H:%M:%S"),
                gateway_name=self.gateway_name,
            )
            self.on_order(mock_order)
            self.write_log("发单失败")
            traceback.print_exc()

    def cancel_order(self, req: CancelRequest):
        """"""
        self.add_task(self._cancel_order, req)

    def _cancel_order(self, req: CancelRequest):
        """"""
        try:
            id = self.ID_VT2TIGER[req.orderid]
            data = self.trade_client.cancel_order(id=id)
            if not data:
                self.write_log("撤单成功")
        except ApiException:
            self.write_log(f"撤单请求提交失败:{req.orderid}")
            traceback.print_exc()
        except Exception:
            self.write_log('撤单失败,id:%s' % (req.orderid))

    def query_contract(self):
        """"""
        self.write_log('开始查询合约信息')
        # HK Stock
        # 查询的速度太慢了, 注释掉了
        try:
            symbols_names_HK = self.quote_client.get_symbol_names(
                lang=Language.zh_CN, market=Market.HK)
            contract_names_HK = DataFrame(symbols_names_HK,
                                          columns=["symbol", "name"])

            contractList = list(contract_names_HK["symbol"])
            i, n = 0, len(contractList)
            result = DataFrame()
            while i < n:
                i += 50
                c = contractList[i - 50:i]
                r = self.quote_client.get_trade_metas(c)
                result = result.append(r)
                sleep(0.1)
        except:
            self.write_log('查询港股合约失败')

        contract_detail_HK = result.sort_values(by="symbol", ascending=True)
        contract_HK = merge(contract_names_HK,
                            contract_detail_HK,
                            how="left",
                            on="symbol")

        for ix, row in contract_HK.iterrows():
            contract = ContractData(
                symbol=row["symbol"],
                exchange=Exchange.SEHK,
                name=row["name"],
                product=Product.EQUITY,
                size=1,
                min_volume=row["lot_size"],
                pricetick=row["min_tick"],
                net_position=True,
                gateway_name=self.gateway_name,
            )
            self.on_contract(contract)
            self.contracts[contract.vt_symbol] = contract
            self.vt_tiger_symbol_map.update({
                contract.symbol:
                (Exchange.SEHK, stock_contract(contract.symbol,
                                               currency='HKD'))
            })

        # US Stock
        symbols_names_US = self.quote_client.get_symbol_names(
            lang=Language.zh_CN, market=Market.US)
        contract_US = DataFrame(symbols_names_US, columns=["symbol", "name"])

        for ix, row in contract_US.iterrows():
            contract = ContractData(
                symbol=row["symbol"],
                exchange=Exchange.SMART,
                name=row["name"],
                product=Product.EQUITY,
                size=1,
                min_volume=1,
                pricetick=0.001,
                gateway_name=self.gateway_name,
            )
            self.on_contract(contract)
            self.vt_tiger_symbol_map.update({
                contract.symbol:
                (Exchange.SMART, stock_contract(contract.symbol,
                                                currency='USD'))
            })
            self.contracts[contract.vt_symbol] = contract
        self.write_log('初始化美股合约完成')

        # Future contracts
        exchanges = self.quote_client.get_future_exchanges(
            sec_type=SecurityType.FUT, lang=Language.zh_CN)
        exchanges_list = exchanges['code']
        contract_futures = DataFrame()
        for e in exchanges_list:
            exchange_contract = self.quote_client.get_future_contracts(
                e, lang=Language.zh_CN)
            if len(exchange_contract) != 0:
                contract_futures = contract_futures.append(exchange_contract)

        for ix, row in contract_futures.iterrows():
            contract = ContractData(
                # symbol 用于查询存储数据 NQ1909
                symbol=row.loc['contract_code'],
                exchange=config_future_exchange(row.loc['exchange']),
                name=row.loc['name'],
                product=Product.FUTURES,
                size=1,
                min_volume=1,
                pricetick=0.001,
                gateway_name=self.gateway_name)
            self.on_contract(contract)
            self.vt_tiger_symbol_map.update({
                contract.symbol: (contract.exchange,
                                  future_contract(
                                      symbol=row.type,
                                      currency=row.currency,
                                      expiry=row.last_trading_date,
                                      exchange=row.exchange,
                                      multiplier=row.multiplier,
                                  ))
            })
            self.contracts[contract.vt_symbol] = contract
        self.write_log('初始化期货合约完成')

    def query_account(self):
        self.write_log('开始查询账户信息')
        try:
            assets = self.trade_client.get_assets(segment=True)
        except ApiException:
            self.write_log("查询资金失败")
            return

        for i in assets:
            account = AccountData(
                accountid=self.account,
                balance=round(i.summary.net_liquidation, 2),
                frozen=0.0,
                gateway_name=self.gateway_name,
            )
            # 下面两个账户仅作vntrader 展示使用。
            # 环球账户的资产信息可以通过 summary 获取,标准账户需要区分股票和期货Segment, 且没有合并的summary信息。
            sec_account = AccountData(
                accountid='Security',
                balance=round(i.segments.get('S').net_liquidation, 2),
                frozen=0.0,
                gateway_name=self.gateway_name,
            )

            com_account = AccountData(
                accountid='Commodity',
                balance=round(i.segments.get('C').net_liquidation, 2),
                frozen=0.0,
                gateway_name=self.gateway_name,
            )

            self.on_account(account)
            self.on_account(sec_account)
            self.on_account(com_account)
        self.write_log('账户信息查询完成')

    def query_position(self):
        """"""
        self.write_log('开始查询持仓信息')
        try:
            # 分别查询股票和期货的持仓
            stock_position = self.trade_client.get_positions(
                sec_type=SecurityType.STK)
            future_position = self.trade_client.get_positions(
                sec_type=SecurityType.FUT)
            positions = stock_position + future_position

        except ApiException:
            self.write_log("查询持仓失败")
            return

        for i in positions:
            try:
                # 标准账户里面的symbol 是origin symbol
                symbol, exchange = self.get_vt_symbol_exchange(
                    contract2symbol(i.contract))

                pos = PositionData(
                    symbol=symbol,
                    exchange=exchange,
                    direction=Direction.NET,
                    volume=int(i.quantity),
                    frozen=0.0,
                    price=i.average_cost,
                    pnl=float(i.unrealized_pnl),
                    gateway_name=self.gateway_name,
                )

                self.on_position(pos)
            except:
                self.write_log('处理持仓失败,symbol: %s' % (i.contract.symbol))
        self.write_log('持仓信息查询完成')

    def query_order(self):
        self.write_log('开始查询历史订单信息')
        try:
            # 需要分别查询股票和期货的订单
            stock_data = self.trade_client.get_orders(
                account=self.account, sec_type=SecurityType.STK)
            future_data = self.trade_client.get_orders(
                account=self.account, sec_type=SecurityType.FUT)
            data = stock_data + future_data
            data = sorted(data, key=lambda x: x.order_time, reverse=False)
        except:
            traceback.print_exc()
            self.write_log("查询订单失败")
            return

        self.process_order(data)
        self.process_deal(data)
        self.write_log('历史订单处理完成')

    def close(self):
        """"""
        self.active = False

        if self.push_client:
            # 退出前先进行退订操作,避免下次打开时的订阅异常
            try:
                self.push_client.unsubscribe_asset()
                self.push_client.unsubscribe_position()
                self.push_client.unsubscribe_order()
                self.push_client.unsubscribe_quote(
                    symbols=self.subscribed_symbols)
                self.push_client.disconnect()
            except:
                pass

    def process_order(self, data):
        """"""
        for i in data:
            try:
                symbol = contract2symbol(i.contract)
                symbol, exchange = self.get_vt_symbol_exchange(symbol)
                local_id = self.get_new_local_id()

                order = OrderData(
                    symbol=symbol,
                    exchange=exchange,
                    orderid=local_id,
                    direction=DIRECTION_TIGER2VT[i.action],
                    price=i.limit_price if i.limit_price else 0.0,
                    volume=i.quantity,
                    traded=i.filled,
                    status=STATUS_TIGER2VT[i.status],
                    time=datetime.fromtimestamp(i.order_time /
                                                1000).strftime("%H:%M:%S"),
                    gateway_name=self.gateway_name,
                )
                self.ID_TIGER2VT[str(i.id)] = local_id
                self.on_order(order)
            except:
                pass

        self.ID_VT2TIGER = {v: k for k, v in self.ID_TIGER2VT.items()}

    def process_deal(self, data):
        """
        Process trade data for both query and update.
        """
        for i in data:
            if i.status == OrderStatus.PARTIALLY_FILLED or i.status == OrderStatus.FILLED:
                try:
                    symbol = contract2symbol(i.contract)
                    symbol, exchange = self.get_vt_symbol_exchange(symbol)
                    self.tradeid += 1

                    trade = TradeData(
                        symbol=symbol,
                        exchange=exchange,
                        direction=DIRECTION_TIGER2VT[i.action],
                        tradeid=self.tradeid,
                        orderid=self.ID_TIGER2VT[str(i.id)],
                        price=i.avg_fill_price,
                        volume=i.filled,
                        time=datetime.fromtimestamp(i.trade_time /
                                                    1000).strftime("%H:%M:%S"),
                        gateway_name=self.gateway_name,
                    )

                    self.on_trade(trade)
                except:
                    pass

    def get_vt_symbol_exchange(self, symbol):
        try:
            exchange = self.vt_tiger_symbol_map.get(symbol)[0]
        except:
            self.write_log('can not get symbol %s' % (symbol))

        return symbol, exchange

    def get_trading_contract(self, symbol):
        """用于下单时获取交易合约
        :param symbol:
        :return:
        """
        try:
            return self.vt_tiger_symbol_map.get(symbol)[1]
        except:
            self.write_log('cannot get traidng contract for symbol %s' %
                           (symbol))
Exemple #16
0
import pandas as pd
import os
from client_config import get_client_config
import talib
import struct
import logging

logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s %(levelname)s %(message)s',
    filemode='a',
)
logger = logging.getLogger('TigerOpenApi')

client_config = get_client_config()
openapi_client = QuoteClient(client_config, logger=logger)


def get_option_quote():
    symbol = 'AAPL'
    expirations = openapi_client.get_option_expirations(symbols=[symbol])
    if len(expirations) > 1:
        print(expirations)
        expiry = int(
            expirations[expirations['symbol'] == symbol].at[0, 'timestamp'])
        chains = openapi_client.get_option_chain(symbol, expiry)
        print(chains)
    for index, row in chains.iterrows():
        print(row["identifier"], row["strike"], row["put_call"])
    briefs = openapi_client.get_option_briefs(['AAPL  190906C00215000'])
    print(briefs)
Exemple #17
0
from tigeropen.common.consts import Market, QuoteRight, FinancialReportPeriodType, Valuation, \
    Income, Balance, CashFlow, BalanceSheetRatio, Growth, Leverage, Profitability

from tigeropen.quote.quote_client import QuoteClient

from tigeropen.examples.client_config import get_client_config

logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s %(levelname)s %(message)s',
    filemode='a',
)
logger = logging.getLogger('TigerOpenApi')

client_config = get_client_config()
openapi_client = QuoteClient(client_config, logger=logger)


def get_quote():
    market_status_list = openapi_client.get_market_status(Market.US)
    print(market_status_list)
    briefs = openapi_client.get_briefs(symbols=['AAPL', '00700', '600519'],
                                       include_ask_bid=True,
                                       right=QuoteRight.BR)
    print(briefs)
    briefs = openapi_client.get_stock_briefs(
        symbols=['AAPL', '00700', '600519'])
    print(briefs)
    metas = openapi_client.get_trade_metas(symbols=['00700'])
    print(metas)
    timelines = openapi_client.get_timeline(['AAPL'],
Exemple #18
0
class Tiger:

    # default logger
    defualt_logger = logging.getLogger('bc_tiger_logger')

    # init
    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}')

    # get user info
    def get_user_info(self):
        return self.__user_info

    # get position record
    def get_position_record(self):
        return self.__position_record

    # synchronize position record with real position status
    def synchronize_position_record(self, config):

        account_type = self.account_type

        # initialize position record for symbols that not in position record
        init_cash = config['trade']['init_cash'][account_type]
        pool = config['selected_sec_list'][config['trade']['pool']
                                           [account_type]]
        for symbol in pool:
            if symbol not in self.record.keys():
                self.record[symbol] = {'cash': init_cash, 'position': 0}

        # get real position (dict)
        position_dict = dict([(x.contract.symbol, x.quantity)
                              for x in self.positions])

        # compare position record with real position
        record_conflicted = False
        for symbol in self.record.keys():

            if symbol not in pool:
                continue

            # update position in record
            record_position = self.record[symbol]['position']
            current_position = 0 if (
                symbol not in position_dict.keys()) else position_dict[symbol]
            if current_position != record_position:
                record_conflicted = True
                if current_position > 0:
                    self.record[symbol] = {
                        'cash': 0,
                        'position': current_position
                    }
                else:
                    self.record[symbol] = {'cash': init_cash, 'position': 0}
                self.logger.error(
                    f'[{account_type[:4]}]: {symbol} position({current_position}) rather than ({record_position}), reset record'
                )

        # add record for position that not recorded
        for symbol in [
                x for x in position_dict.keys()
                if (x in pool and x not in self.record.keys())
        ]:
            record_conflicted = True
            self.record[symbol] = {
                'cash': 0,
                'position': position_dict[symbol]
            }
            self.logger.error(
                f'[{account_type[:4]}]: {symbol} position({position_dict[symbol]}) not in record, add record'
            )

        # update __position_record
        if record_conflicted:
            self.__position_record[self.account_type] = self.record.copy()
            io_util.create_config_file(config_dict=self.__position_record,
                                       file_path=config['config_path'],
                                       file_name='tiger_position_record.json')

    # update position for an account
    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}'
            )

    # update portfolio for an account
    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 asset 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, 'net_value']
            market_value = asset_summary.loc[0, 'holding_value']
            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['tiger'][self.account_type].get(
            'net_value')
        support = portfolio_record['tiger'][self.account_type].get(
            'portfolio').get('support')
        resistant = portfolio_record['tiger'][self.account_type].get(
            'portfolio').get('resistant')

        # update portfolio record for current account
        portfolio_record['tiger'][
            self.account_type]['portfolio'] = position_summary.to_dict()
        portfolio_record['tiger'][
            self.account_type]['portfolio']['support'] = {}
        portfolio_record['tiger'][
            self.account_type]['portfolio']['resistant'] = {}

        quantity = portfolio_record['tiger'][
            self.account_type]['portfolio'].get('quantity')
        if quantity is not None:
            if support is not None:
                for symbol in quantity.keys():
                    portfolio_record['tiger'][self.account_type]['portfolio'][
                        'support'][symbol] = support.get(symbol)

            if resistant is not None:
                for symbol in quantity.keys():
                    portfolio_record['tiger'][self.account_type]['portfolio'][
                        'resistant'][symbol] = resistant.get(symbol)

        portfolio_record['tiger'][
            self.account_type]['market_value'] = market_value
        portfolio_record['tiger'][self.account_type]['net_value'] = net_value
        portfolio_record['tiger'][self.account_type]['cash'] = cash
        portfolio_record['tiger'][
            self.account_type]['updated'] = datetime.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
        if is_print:
            self.logger.info(
                f'[{self.account_type[:4]}]: net value {old_net_value} --> {net_value}'
            )

    # get summary of positions
    def get_position_summary(self, get_briefs=False):

        try:
            # update positions
            self.positions = self.trade_client.get_positions(
                account=self.client_config.account)

            # convert positions(list) to dataframe
            if len(self.positions) > 0:
                result = {
                    'symbol': [],
                    'quantity': [],
                    'average_cost': [],
                    'market_price': []
                }
                for pos in self.positions:
                    result['symbol'].append(pos.contract.symbol)
                    result['quantity'].append(pos.quantity)
                    result['average_cost'].append(pos.average_cost)
                    result['market_price'].append(pos.market_price)
                result = pd.DataFrame(result)

                # get briefs for stocks in positions
                if get_briefs:
                    status = io_util.get_stock_briefs(
                        symbols=[x.contract.symbol for x in self.positions],
                        source='eod',
                        period='1d',
                        interval='1m',
                        api_key=self.eod_api_key)
                    result = pd.merge(result,
                                      status,
                                      how='left',
                                      left_on='symbol',
                                      right_on='symbol')
                    result['rate'] = round(
                        (result['latest_price'] - result['average_cost']) /
                        result['average_cost'], 2)
                    result = result[[
                        'symbol', 'quantity', 'average_cost', 'latest_price',
                        'rate', 'latest_time'
                    ]]
                else:
                    result.rename(columns={'market_price': 'latest_price'},
                                  inplace=True)
                    result['rate'] = round(
                        (result['latest_price'] - result['average_cost']) /
                        result['average_cost'], 2)
                    result['latest_time'] = None

                # calculate market value
                result['market_value'] = result['quantity'] * result[
                    'latest_price']

            else:
                result = pd.DataFrame({
                    'symbol': [],
                    'quantity': [],
                    'average_cost': [],
                    'latest_price': [],
                    'rate': [],
                    'market_value': [],
                    'latest_time': []
                })

        except Exception as e:
            result = pd.DataFrame({
                'symbol': [],
                'quantity': [],
                'average_cost': [],
                'latest_price': [],
                'rate': [],
                'market_value': [],
                'latest_time': []
            })
            self.logger.exception(f'[erro]: can not get position summary: {e}')

        return result

    # get summary of assets
    def get_asset_summary(self, print_summary=False):

        # update assets
        self.assets = self.trade_client.get_assets(
            account=self.client_config.account)
        asset = self.assets[0]
        result = {
            'account': [asset.account],
            'net_value': [asset.summary.net_liquidation],
            'holding_value': [asset.summary.gross_position_value],
            'cash': [asset.summary.cash],
            'available_casg': [asset.summary.available_funds],
            'pnl': [asset.summary.realized_pnl],
            'holding_pnl': [asset.summary.unrealized_pnl]
        }

        if print_summary:
            summary = f'''
      账户: {asset.account}({asset.summary.currency}):
      总资产: {asset.summary.net_liquidation}
      现金: {asset.summary.cash} (可用 {asset.summary.available_funds})
      持仓市值: {asset.summary.gross_position_value}
      日内交易次数: {asset.summary.day_trades_remaining}
      已实现盈亏: {asset.summary.realized_pnl}
      未实现盈亏: {asset.summary.unrealized_pnl}
      '''
            print(summary)

        return pd.DataFrame(result)

    # get available money
    def get_available_cash(self):

        # get available cash for real accounts
        self.assets = self.trade_client.get_assets(
            account=self.client_config.account)
        available_cash = self.assets[0].summary.cash

        return available_cash

    # get quantity of symbol currently in the position
    def get_in_position_quantity(self, symbol, get_briefs=False):

        # initialize affordable quantity
        quantity = 0

        # get position summary
        position = self.get_position_summary(get_briefs=get_briefs)
        if len(position) > 0:
            position = position.set_index('symbol')
            if symbol in position.index:
                quantity = position.loc[symbol, 'quantity']

        return quantity

    # check whether it is affordable to buy certain amount of a stock
    def get_affordable_quantity(self, symbol, cash=None, trading_fee=3):

        # initialize affordable quantity and available cash
        quantity = 0
        available_cash = self.get_available_cash() if (cash is None) else cash

        # get latest price of stock
        stock_brief = io_util.get_stock_briefs(
            symbols=[symbol],
            source='eod',
            period='1d',
            interval='1m',
            api_key=self.eod_api_key).set_index('symbol')
        latest_price = stock_brief.loc[symbol, 'latest_price']

        # check if it is affordable
        quantity = math.floor((available_cash - trading_fee) / latest_price)

        return quantity

    # idle for specified time and check position in certain frequency
    def idle(self, target_time, check_frequency=600):
        """
    Sleep with a fixed frequency, until the target time

    :param target_time: the target time in datetime.datetime format
    :param check_frequency: the fixed sleep_time 
    :returns: none
    :raises: none
    """
        # get current time
        now = datetime.datetime.now()
        while now < target_time:

            # # get position summary
            # pos = self.get_position_summary()
            # self.logger.info(f'[rate]:----------------------------------------------\n{pos}\n')

            # get current time, calculate difference between current time and target time
            diff_time = round((target_time - now).total_seconds())
            sleep_time = (diff_time + 1) if (
                diff_time <= check_frequency) else check_frequency

            # sleep
            self.logger.info(
                f'[idle]: {now.strftime(format="%Y-%m-%d %H:%M:%S")}: sleep for {sleep_time} seconds'
            )
            time.sleep(sleep_time)

            # update current time
            now = datetime.datetime.now()

        self.logger.info(
            f'[wake]: {now.strftime(format="%Y-%m-%d %H:%M:%S")}: exceed target time({target_time})'
        )

    # update trade time
    def update_trade_time(self,
                          market=Market.US,
                          tz='Asia/Shanghai',
                          open_time_adj=0,
                          close_time_adj=0):

        # get local timezone
        tz = pytz.timezone(tz)

        try:
            # get open_time
            status = self.quote_client.get_market_status(market=market)[0]
            current_status = status.status
            open_time = status.open_time.astimezone(tz).replace(tzinfo=None)
            open_time = open_time + datetime.timedelta(hours=open_time_adj)

            # if program runs after market open, api will return trade time for next trade day,
            # trade time for current trade day need to be calculated manually
            if status.status in ['Trading', 'Post-Market Trading']:
                if open_time.weekday() == 0:
                    open_time = open_time - datetime.timedelta(days=3)
                else:
                    open_time = open_time - datetime.timedelta(days=1)

            # calculate close time, pre_open_time, post_close_time
            close_time = open_time + datetime.timedelta(hours=6.5 +
                                                        close_time_adj)
            pre_open_time = open_time - datetime.timedelta(hours=5.5)
            post_close_time = close_time + datetime.timedelta(hours=4)

            # open and close time of chinese stock market
            a_open_time = pre_open_time + datetime.timedelta(
                hours=9.5 - pre_open_time.hour)
            a_close_time = pre_open_time + datetime.timedelta(
                hours=15 - pre_open_time.hour)

        except Exception as e:
            self.logger.error(e)
            current_status = None
            open_time = None
            close_time = None
            pre_open_time = None
            post_close_time = None

        self.trade_time = {
            'status': current_status,
            'tz': tz,
            'pre_open_time': pre_open_time,
            'open_time': open_time,
            'close_time': close_time,
            'post_close_time': post_close_time,
            'a_open_time': a_open_time,
            'a_close_time': a_close_time
        }

    # update market status
    def update_market_status(self, market=Market.US, return_str=False):

        try:
            # get market status
            status = self.quote_client.get_market_status(market=market)[0]
            self.trade_time['status'] = status.status

            if return_str:
                time_format = '%Y-%m-%d %H:%M'
                pre_open_time = self.trade_time['pre_open_time'].strftime(
                    time_format)
                post_close_time = self.trade_time['post_close_time'].strftime(
                    time_format)

                time_format = '%H:%M'
                open_time = self.trade_time['open_time'].strftime(time_format)
                close_time = self.trade_time['close_time'].strftime(
                    time_format)

                time_str = f'<({pre_open_time}){open_time} -- {close_time}({post_close_time})>'

                return time_str

        except Exception as e:
            self.logger.error(e)

    # buy or sell stocks
    def trade(self,
              symbol,
              action,
              quantity,
              price=None,
              stop_loss=None,
              stop_profit=None,
              print_summary=True):

        trade_summary = ''
        try:

            # construct contract
            contract = stock_contract(symbol=symbol, currency='USD')

            # construct order
            if price is None:
                order_price = 'market'
                order = market_order(account=self.client_config.account,
                                     contract=contract,
                                     action=action,
                                     quantity=quantity)
            else:
                order_price = float(f'{price}')
                order = limit_order(account=self.client_config.account,
                                    contract=contract,
                                    action=action,
                                    quantity=quantity,
                                    limit_price=price)

            # construct trade summary
            trade_summary += f'[{action}]: {symbol} X {quantity} ({order_price})\t'

            # attach order legs
            order_legs = []
            if stop_loss is not None:
                stop_loss_order_leg = order_leg('LOSS',
                                                stop_loss,
                                                time_in_force='GTC')  # 附加止损单
                order_legs.append(stop_loss_order_leg)
            if stop_profit is not None:
                stop_profit_order_leg = order_leg('PROFIT',
                                                  stop_profit,
                                                  time_in_force='GTC')  # 附加止盈单
                order_legs.append(stop_profit_order_leg)
            if len(order_legs) > 0:
                order.order_legs = order_legs

            # place buy order if affordable
            if action == 'BUY':
                affordable_quantity = self.get_affordable_quantity(
                    symbol=symbol)
                if quantity <= affordable_quantity:
                    self.trade_client.place_order(order)
                    trade_summary += f'SUCCEED: {order.id}'
                else:
                    trade_summary += f'FAILED: Not affordable({affordable_quantity}/{quantity})'

            # place sell order if holding enough stocks
            elif action == 'SELL':
                in_position_quantity = self.get_in_position_quantity(symbol)
                if in_position_quantity >= quantity:
                    self.trade_client.place_order(order)
                    trade_summary += f'SUCCEED: {order.id}'
                else:
                    trade_summary += f'FAILED: Not enough stock to sell({in_position_quantity}/{quantity})'

            # other actions
            else:
                trade_summary += f'FAILED: Unknown action({action})'

        except Exception as e:
            trade_summary += f'FAILED: {e}'

        # print trade summary
        if print_summary:
            self.logger.info(trade_summary)

        return trade_summary

    # auto trade according to signals
    def signal_trade(self,
                     signal,
                     money_per_sec,
                     order_type='market',
                     trading_fee=5,
                     pool=None,
                     according_to_record=True,
                     minimum_position=None):

        # set symbol to index
        if len(signal) > 0:
            # signal = signal.rename(columns={'代码':'symbol', '交易信号':'action'})
            # signal = signal.set_index('symbol')

            # filter sec with pool
            if pool is not None:
                filtered_list = [x for x in signal.index if x in pool]
                signal = signal.loc[filtered_list, signal.columns].copy()

        # if signal list is not empty
        if len(signal) > 0:
            # get latest price for signals

            # if order_type == 'market':
            # signal_brief = self.quote_client.get_stock_briefs(symbols=signal.index.tolist()).set_index('symbol')
            # signal_brief = io_util.get_stock_briefs(symbols=signal.index.tolist(), source='eod', period='1d', interval='1m', api_key=self.eod_api_key).set_index('symbol')
            # signal = pd.merge(signal, signal_brief[['latest_price']], how='left', left_index=True, right_index=True)

            # get in-position quantity and latest price for signals
            position = self.get_position_summary(get_briefs=False)
            if len(position) == 0:
                position = pd.DataFrame({'symbol': [], 'quantity': []})
            position = position.set_index('symbol')
            signal = pd.merge(signal,
                              position[['quantity']],
                              how='left',
                              left_index=True,
                              right_index=True).fillna(0)

            # sell
            # get sell signals
            sell_signal = signal.query('action == "s"')
            if len(sell_signal) > 0:
                # go through sell signals
                for symbol in sell_signal.index:
                    # check whether symbol is in positions
                    in_position_quantity = signal.loc[symbol, 'quantity']
                    if in_position_quantity > 0:
                        if order_type == 'limit':
                            price = signal.loc[symbol, 'latest_price']
                        else:
                            price = None
                        trade_summary = self.trade(
                            symbol=symbol,
                            action='SELL',
                            quantity=in_position_quantity,
                            price=price,
                            print_summary=False)
                        self.logger.info(trade_summary)
                    else:
                        self.logger.info(
                            f'[SELL]: {symbol} skipped (not in positions)')
            else:
                self.logger.info(f'[SELL]: no signal')

            # buy
            # get available cash, set minimum position
            available_cash = self.get_available_cash()
            if minimum_position is None:
                minimum_position = money_per_sec

            # get buy signals which not in posiitons yet
            default_money_per_sec = money_per_sec
            buy_signal = signal.query('action == "b"')
            if len(buy_signal) > 0:
                # go through buy signals
                for symbol in buy_signal.index:

                    # break when available cash is below 200
                    if available_cash <= minimum_position:
                        self.logger.info(
                            f'[BUY]: Available cash is too low({available_cash}/{minimum_position}), stop buying'
                        )
                        break

                    # check whether symbol is already in positions
                    in_position_quantity = signal.loc[symbol, 'quantity']
                    if in_position_quantity == 0:
                        # set money used to establish a new position
                        if according_to_record:
                            if (symbol in self.record.keys()) and (
                                    self.record[symbol]['position'] == 0):
                                money_per_sec = self.record[symbol]['cash']
                            else:
                                money_per_sec = default_money_per_sec

                        # check whether there is enough available money
                        money_per_sec = available_cash if (
                            money_per_sec > available_cash) else money_per_sec

                        # calculate quantity to buy
                        quantity = math.floor(
                            (money_per_sec - trading_fee) /
                            signal.loc[symbol, 'latest_price'])
                        if quantity > 0:
                            if order_type == 'limit':
                                price = signal.loc[symbol, 'latest_price']
                            else:
                                price = None
                            trade_summary = self.trade(symbol=symbol,
                                                       action='BUY',
                                                       quantity=quantity,
                                                       price=price,
                                                       print_summary=False)
                            self.logger.info(trade_summary)

                            # update available cash
                            available_cash -= quantity * signal.loc[
                                symbol, 'latest_price']
                        else:
                            self.logger.info(f'[BUY]: not enough money')
                            continue
                    else:
                        self.logger.info(
                            f'[BUY]: {symbol} skipped (already in positions:{in_position_quantity})'
                        )
                        continue
            else:
                self.logger.info(f'[BUY]: no signal')
        else:
            self.logger.info(f'[SKIP]: no signal')

    # stop loss or stop profit or clear all positions
    def cash_out(self,
                 stop_loss_rate=None,
                 stop_profit_rate=None,
                 clear_all=False,
                 print_summary=True):

        # get current position with summary
        position = self.get_position_summary(get_briefs=True)
        if len(position) > 0:

            # set symbol as index
            position = position.set_index('symbol')

            # if clear all positions
            if clear_all:
                cash_out_list = position.index.tolist()
            else:
                stop_loss_list = [] if stop_loss_rate is None else position.query(
                    f'rate < {stop_loss_rate}').index.tolist()
                stop_profit_list = [] if stop_profit_rate is None else position.query(
                    f'rate > {stop_profit_rate}').index.tolist()
                cash_out_list = list(set(stop_loss_list + stop_profit_list))

            # cash out
            if len(cash_out_list) > 0:
                cash_out_position = position.loc[cash_out_list, ].copy()
                self.logger.info(
                    f'[STOP]: LOSS: {stop_loss_list}, PROFIT: {stop_profit_list}'
                )

                for index, row in cash_out_position.iterrows():
                    self.trade(symbol=index,
                               action='SELL',
                               quantity=row['quantity'],
                               print_summary=print_summary)
Exemple #19
0
def get_future_quote():
    client_config = get_client_config()
    quote_client = QuoteClient(client_config)
    exchanges = quote_client.get_future_exchanges()
    print(exchanges)
    quote_client.get_future_bars(['CN1901'],
                                 begin_time=-1,
                                 end_time=1545105097358)
    quote_client.get_future_trade_ticks(['CN1901'])
    quote_client.get_future_contracts('CME')
    quote_client.get_future_trading_times('CN1901', trading_date=1545049282852)
    quote_client.get_future_brief(['ES1906', 'CN1901'])
Exemple #20
0
def get_option_quote():
    client_config = get_client_config()
    quote_client = QuoteClient(client_config)
    symbol = 'AAPL'
    expirations = quote_client.get_option_expirations(symbols=[symbol])
    if len(expirations) > 1:
        expiry = int(
            expirations[expirations['symbol'] == symbol].at[0, 'timestamp'])
        quote_client.get_option_chain(symbol, expiry)

    quote_client.get_option_briefs(['AAPL  190104C00121000'])
    quote_client.get_option_bars(['AAPL  190104P00134000'])
    quote_client.get_option_trade_ticks(['AAPL  190104P00134000'])
class Test:
    def __init__(self):
        self.client_config = get_client_config()
        self.trade_client = TradeClient(self.client_config)
        self.openapi_client = QuoteClient(self.client_config, logger=logger)
        # 初始化 pushclient

        protocol, host, port = self.client_config.socket_host_port
        self.push_client = PushClient(host, port, use_ssl=(protocol == 'ssl'))
        self.push_client.connect(self.client_config.tiger_id, self.client_config.private_key)



    def trade(self):
        stock = stock_contract(symbol='AAPL', currency='USD')
        option = option_contract(identifier='AAPL  190927P00200000')

        emu_account = []
        # stock_contract = trade_client.get_contracts(symbol='FB')[0]

        account = self.trade_client.get_managed_accounts()
        print(account)
        emu_account = account[1]
        account = self.client_config.paper_account
        assets = self.trade_client.get_assets(account=account)
        print(assets)
        posinfo = self.trade_client.get_positions(account=account)
        print(posinfo)
        stock_order = market_order(account=account,   # 下单账户,可以使用标准、环球、或模拟账户
                                  contract = option,       # 第1步中获取的合约对象
                                  action = 'BUY',
                                  quantity = 1)
        print(stock_order)
        self.trade_client.place_order(stock_order)
        print(stock_order)

# 直接本地构造contract对象。 期货 contract 的构造方法请参考后面的文档
    def get_option_quote(self):
        symbol = 'AAPL'
        expirations = self.openapi_client.get_option_expirations(symbols=[symbol])
        if len(expirations) > 1:
            print(expirations)
            expiry = int(expirations[expirations['symbol'] == symbol].at[0, 'timestamp'])
            chains = self.openapi_client.get_option_chain(symbol, expiry)
            print(chains)
        for index,row in chains.iterrows():
            print(row["identifier"], row["strike"], row["put_call"])
        briefs = self.openapi_client.get_option_briefs(['AAPL  190927P00200000'])
        print(briefs)
        bars = self.openapi_client.get_option_bars(['AAPL  190927P00200000'])
        print(bars)
        ticks = self.openapi_client.get_option_trade_ticks(['AAPL  190927P00200000'])
        print(ticks)
        for index,row in ticks.iterrows():
            print(row["identifier"], row["time"], row["price"])

    def on_quote_changed(self, symbol, items, hour_trading):
        print(symbol, items, hour_trading)


    def test1(self):
        info = app.openapi_client.get_briefs(symbols)
        print(info)

    def run(self):
        option_trade_ticks = self.openapi_client.get_option_trade_ticks(['AAPL  190927P00200000'])
        print(option_trade_ticks)

    def subscribe(self):
        # self.push_client.connect(self.client_config.tiger_id, self.client_config.private_key)
        self.push_client.quote_changed = self.on_quote_changed
        self.push_client.subscribe_quote(symbols=['AAPL  190927P00200000', 'GOOG', 'FB'], quote_key_type=QuoteKeyType.ALL)
        self.push_client.subscribe_asset()
        time.sleep(30)
        # self.push_client.unsubscribe_quote(['AAPL', 'GOOG'])

    def subscribe2(self):

        self.push_client.quote_changed = self.on_quote_changed
        self.push_client.subscribe_quote(symbols=['aapl'], quote_key_type=QuoteKeyType.ALL)
        self.push_client.subscribe_asset()

    def on_changed(self, symbol, items, hour_trading):
        print(symbol, items, hour_trading)
        data = dict(items)
        latest_price = data.get('latest_price')
        volume = data.get('volume')


    def query_subscribed(self):
        def on_subscribed_symbols(symbols, focus_keys, limit, used):
            print(symbols, focus_keys, limit, used)

        self.push_client.subscribed_symbols = on_subscribed_symbols
        self.push_client.query_subscribed_quote()
class TigerGateway(BaseGateway):
    """"""
    default_setting = {
        "tiger_id": "",
        "account": "",
        " server ": [" standard ", " global ", " simulation "],
        "private_key": "",
    }

    exchanges = [Exchange.SEHK, Exchange.SMART, Exchange.SSE, Exchange.SZSE]

    def __init__(self, event_engine):
        """Constructor"""
        super(TigerGateway, self).__init__(event_engine, "TIGER")

        self.tiger_id = ""
        self.account = ""
        self.server = ""
        self.language = ""

        self.client_config = None
        self.quote_client = None
        self.push_client = None

        self.local_id = 1000000
        self.tradeid = 0

        self.active = False
        self.queue = Queue()
        self.pool = None

        self.ID_TIGER2VT = {}
        self.ID_VT2TIGER = {}
        self.ticks = {}
        self.trades = set()
        self.contracts = {}
        self.symbol_names = {}

        self.push_connected = False
        self.subscribed_symbols = set()

    def run(self):
        """"""
        while self.active:
            try:
                func, args = self.queue.get(timeout=0.1)
                func(*args)
            except Empty:
                pass

    def add_task(self, func, *args):
        """"""
        self.queue.put((func, [*args]))

    def connect(self, setting: dict):
        """"""
        self.private_key = setting["private_key"]
        self.tiger_id = setting["tiger_id"]
        self.server = setting[" server "]
        self.account = setting["account"]
        self.languege = Language.zh_CN

        # Start thread pool for REST call
        self.active = True
        self.pool = Pool(5)
        self.pool.apply_async(self.run)

        # Put connect task into quque.
        self.init_client_config()
        self.add_task(self.connect_quote)
        self.add_task(self.connect_trade)
        self.add_task(self.connect_push)

    def init_client_config(self, sandbox=False):
        """"""
        self.client_config = TigerOpenClientConfig(sandbox_debug=sandbox)
        self.client_config.private_key = self.private_key
        self.client_config.tiger_id = self.tiger_id
        self.client_config.account = self.account
        self.client_config.language = self.language

    def connect_quote(self):
        """
        Connect to market data server.
        """
        try:
            self.quote_client = QuoteClient(self.client_config)
            self.symbol_names = dict(
                self.quote_client.get_symbol_names(lang=Language.zh_CN))
            self.query_contract()
        except ApiException:
            self.write_log(" queries contract failure ")
            return

        self.write_log(" quotes interfacing success ")
        self.write_log(" contract query succeeds ")

    def connect_trade(self):
        """
        Connect to trade server.
        """
        self.trade_client = TradeClient(self.client_config)
        try:
            self.add_task(self.query_order)
            self.add_task(self.query_position)
            self.add_task(self.query_account)
        except ApiException:
            self.write_log(" transaction interface connection failure ")
            return

        self.write_log(" successful transaction interface ")

    def connect_push(self):
        """
        Connect to push server.
        """
        protocol, host, port = self.client_config.socket_host_port
        self.push_client = PushClient(host, port, (protocol == "ssl"))

        self.push_client.quote_changed = self.on_quote_change
        self.push_client.asset_changed = self.on_asset_change
        self.push_client.position_changed = self.on_position_change
        self.push_client.order_changed = self.on_order_change
        self.push_client.connect_callback = self.on_push_connected

        self.push_client.connect(self.client_config.tiger_id,
                                 self.client_config.private_key)

    def subscribe(self, req: SubscribeRequest):
        """"""
        self.subscribed_symbols.add(req.symbol)

        if self.push_connected:
            self.push_client.subscribe_quote([req.symbol])

    def on_push_connected(self):
        """"""
        self.push_connected = True
        self.write_log(" push interfacing success ")

        self.push_client.subscribe_asset()
        self.push_client.subscribe_position()
        self.push_client.subscribe_order()

        self.push_client.subscribe_quote(list(self.subscribed_symbols))

    def on_quote_change(self, tiger_symbol: str, data: list, trading: bool):
        """"""
        data = dict(data)
        symbol, exchange = convert_symbol_tiger2vt(tiger_symbol)

        tick = self.ticks.get(symbol, None)
        if not tick:
            tick = TickData(
                symbol=symbol,
                exchange=exchange,
                gateway_name=self.gateway_name,
                datetime=datetime.now(),
                name=self.symbol_names[symbol],
            )
            self.ticks[symbol] = tick

        tick.datetime = datetime.fromtimestamp(int(data["timestamp"]) / 1000)
        tick.pre_close = data.get("prev_close", tick.pre_close)
        tick.last_price = data.get("latest_price", tick.last_price)
        tick.volume = data.get("volume", tick.volume)
        tick.open_price = data.get("open", tick.open_price)
        tick.high_price = data.get("high", tick.high_price)
        tick.low_price = data.get("low", tick.low_price)
        tick.ask_price_1 = data.get("ask_price", tick.ask_price_1)
        tick.bid_price_1 = data.get("bid_price", tick.bid_price_1)
        tick.ask_volume_1 = data.get("ask_size", tick.ask_volume_1)
        tick.bid_volume_1 = data.get("bid_size", tick.bid_volume_1)

        self.on_tick(copy(tick))

    def on_asset_change(self, tiger_account: str, data: list):
        """"""
        data = dict(data)
        if "net_liquidation" not in data:
            return

        account = AccountData(
            accountid=tiger_account,
            balance=data["net_liquidation"],
            frozen=0.0,
            gateway_name=self.gateway_name,
        )
        self.on_account(account)

    def on_position_change(self, tiger_account: str, data: list):
        """"""
        data = dict(data)
        symbol, exchange = convert_symbol_tiger2vt(data["origin_symbol"])

        pos = PositionData(
            symbol=symbol,
            exchange=exchange,
            direction=Direction.NET,
            volume=int(data["quantity"]),
            frozen=0.0,
            price=data["average_cost"],
            pnl=data["unrealized_pnl"],
            gateway_name=self.gateway_name,
        )
        self.on_position(pos)

    def on_order_change(self, tiger_account: str, data: list):
        """"""
        data = dict(data)
        symbol, exchange = convert_symbol_tiger2vt(data["origin_symbol"])
        status = STATUS_TIGER2VT[data["status"]]

        order = OrderData(
            symbol=symbol,
            exchange=exchange,
            orderid=self.ID_TIGER2VT.get(str(data["order_id"]),
                                         self.get_new_local_id()),
            direction=Direction.NET,
            price=data.get("limit_price", 0),
            volume=data["quantity"],
            traded=data["filled"],
            status=status,
            time=datetime.fromtimestamp(data["order_time"] /
                                        1000).strftime("%H:%M:%S"),
            gateway_name=self.gateway_name,
        )
        self.ID_TIGER2VT[str(data["order_id"])] = order.orderid
        self.on_order(order)

        if status == Status.ALLTRADED:
            self.tradeid += 1

            trade = TradeData(
                symbol=symbol,
                exchange=exchange,
                direction=Direction.NET,
                tradeid=self.tradeid,
                orderid=self.ID_TIGER2VT[str(data["order_id"])],
                price=data["avg_fill_price"],
                volume=data["filled"],
                time=datetime.fromtimestamp(data["trade_time"] /
                                            1000).strftime("%H:%M:%S"),
                gateway_name=self.gateway_name,
            )
            self.on_trade(trade)

    def get_new_local_id(self):
        self.local_id += 1
        return self.local_id

    def send_order(self, req: OrderRequest):
        """"""
        local_id = self.get_new_local_id()
        order = req.create_order_data(local_id, self.gateway_name)

        self.on_order(order)
        self.add_task(self._send_order, req, local_id)
        return order.vt_orderid

    def _send_order(self, req: OrderRequest, local_id):
        """"""
        currency = config_symbol_currency(req.symbol)
        try:
            contract = self.trade_client.get_contracts(symbol=req.symbol,
                                                       currency=currency)[0]
            order = self.trade_client.create_order(
                account=self.account,
                contract=contract,
                action=DIRECTION_VT2TIGER[req.direction],
                order_type=ORDERTYPE_VT2TIGER[req.type],
                quantity=int(req.volume),
                limit_price=req.price,
            )
            self.ID_TIGER2VT[str(order.order_id)] = local_id
            self.ID_VT2TIGER[local_id] = str(order.order_id)

            self.trade_client.place_order(order)

        except:  # noqa
            traceback.print_exc()
            self.write_log(" billed failure ")
            return

    def cancel_order(self, req: CancelRequest):
        """"""
        self.add_task(self._cancel_order, req)

    def _cancel_order(self, req: CancelRequest):
        """"""
        try:
            order_id = self.ID_VT2TIGER[req.orderid]
            data = self.trade_client.cancel_order(order_id=order_id)
        except ApiException:
            self.write_log(f" withdrawals failure :{req.orderid}")

        if not data:
            self.write_log(" withdrawals success ")

    def query_contract(self):
        """"""
        # HK Stock

        symbols_names_HK = self.quote_client.get_symbol_names(
            lang=Language.zh_CN, market=Market.HK)
        contract_names_HK = DataFrame(symbols_names_HK,
                                      columns=["symbol", "name"])

        contractList = list(contract_names_HK["symbol"])
        i, n = 0, len(contractList)
        result = pd.DataFrame()
        while i < n:
            i += 50
            c = contractList[i - 50:i]
            r = self.quote_client.get_trade_metas(c)
            result = result.append(r)

        contract_detail_HK = result.sort_values(by="symbol", ascending=True)
        contract_HK = pd.merge(contract_names_HK,
                               contract_detail_HK,
                               how="left",
                               on="symbol")

        for ix, row in contract_HK.iterrows():
            contract = ContractData(
                symbol=row["symbol"],
                exchange=Exchange.SEHK,
                name=row["name"],
                product=Product.EQUITY,
                size=1,
                min_volume=row["lot_size"],
                pricetick=row["min_tick"],
                net_position=True,
                gateway_name=self.gateway_name,
            )
            self.on_contract(contract)
            self.contracts[contract.vt_symbol] = contract

        # US Stock
        symbols_names_US = self.quote_client.get_symbol_names(
            lang=Language.zh_CN, market=Market.US)
        contract_US = DataFrame(symbols_names_US, columns=["symbol", "name"])

        for ix, row in contract_US.iterrows():
            contract = ContractData(
                symbol=row["symbol"],
                exchange=Exchange.SMART,
                name=row["name"],
                product=Product.EQUITY,
                size=1,
                min_volume=100,
                pricetick=0.001,
                gateway_name=self.gateway_name,
            )
            self.on_contract(contract)
            self.contracts[contract.vt_symbol] = contract

        # CN Stock
        symbols_names_CN = self.quote_client.get_symbol_names(
            lang=Language.zh_CN, market=Market.CN)
        contract_CN = DataFrame(symbols_names_CN, columns=["symbol", "name"])

        for ix, row in contract_CN.iterrows():
            symbol = row["symbol"]
            symbol, exchange = convert_symbol_tiger2vt(symbol)

            contract = ContractData(
                symbol=symbol,
                exchange=exchange,
                name=row["name"],
                product=Product.EQUITY,
                size=1,
                min_volume=100,
                pricetick=0.001,
                gateway_name=self.gateway_name,
            )
            self.on_contract(contract)
            self.contracts[contract.vt_symbol] = contract

    def query_account(self):
        """"""
        try:
            assets = self.trade_client.get_assets()
        except ApiException:
            self.write_log(" queries funds fail ")
            return

        for i in assets:
            account = AccountData(
                accountid=self.account,
                balance=i.summary.net_liquidation,
                frozen=0.0,
                gateway_name=self.gateway_name,
            )

            self.on_account(account)

    def query_position(self):
        """"""
        try:
            position = self.trade_client.get_positions()
        except ApiException:
            self.write_log(" queries positions fail ")
            return

        for i in position:
            symbol, exchange = convert_symbol_tiger2vt(i.contract.symbol)

            pos = PositionData(
                symbol=symbol,
                exchange=exchange,
                direction=Direction.NET,
                volume=int(i.quantity),
                frozen=0.0,
                price=i.average_cost,
                pnl=float(i.unrealized_pnl),
                gateway_name=self.gateway_name,
            )

            self.on_position(pos)

    def query_order(self):
        """"""
        try:
            data = self.trade_client.get_orders()
            data = sorted(data, key=lambda x: x.order_time, reverse=False)
        except:  # noqa
            traceback.print_exc()
            self.write_log(" inquiry commission failed ")
            return

        self.process_order(data)
        self.process_deal(data)

    def close(self):
        """"""
        self.active = False

        if self.push_client:
            self.push_client.disconnect()

    def process_order(self, data):
        """"""
        for i in data:
            symbol, exchange = convert_symbol_tiger2vt(str(i.contract))
            local_id = self.get_new_local_id()

            order = OrderData(
                symbol=symbol,
                exchange=exchange,
                orderid=local_id,
                direction=Direction.NET,
                price=i.limit_price if i.limit_price else 0.0,
                volume=i.quantity,
                traded=i.filled,
                status=STATUS_TIGER2VT[i.status],
                time=datetime.fromtimestamp(i.order_time /
                                            1000).strftime("%H:%M:%S"),
                gateway_name=self.gateway_name,
            )
            self.ID_TIGER2VT[str(i.order_id)] = local_id
            self.on_order(order)

        self.ID_VT2TIGER = {v: k for k, v in self.ID_TIGER2VT.items()}

    def process_deal(self, data):
        """
        Process trade data for both query and update.
        """
        for i in data:
            if i.status == OrderStatus.PARTIALLY_FILLED or i.status == OrderStatus.FILLED:
                symbol, exchange = convert_symbol_tiger2vt(str(i.contract))
                self.tradeid += 1

                trade = TradeData(
                    symbol=symbol,
                    exchange=exchange,
                    direction=Direction.NET,
                    tradeid=self.tradeid,
                    orderid=self.ID_TIGER2VT[str(i.order_id)],
                    price=i.avg_fill_price,
                    volume=i.filled,
                    time=datetime.fromtimestamp(i.trade_time /
                                                1000).strftime("%H:%M:%S"),
                    gateway_name=self.gateway_name,
                )

                self.on_trade(trade)
Exemple #23
0
def get_quote(symbol=None):
    client_config = get_client_config()
    quote_client = QuoteClient(client_config)
    return quote_client.get_hour_trading_timeline(symbol=symbol)
Exemple #24
0
class RqdataClient:
    """
    Client for querying history data from RQData.
    """

    def __init__(self):
        """"""
        logging.basicConfig(level=logging.INFO,
                    format='%(asctime)s %(levelname)s %(message)s',
                    filemode='a', )
        logger = logging.getLogger('TigerOpenApi')
        client_config = get_client_config()
        self.openapi_client = QuoteClient(client_config, logger=logger)

        self.inited = False
        self.symbols = set()

    def init(self, username="", password=""):
        """"""
        if self.inited:
            return True

        self.__init__()

        self.inited = True
        return True

    def to_rq_symbol(self, symbol: str, exchange: Exchange):
        
        return symbol
    
    def get_data(self, symbol, period=BarPeriod.ONE_MINUTE, limit=1300, begin=-1, end=-1):
        return self.openapi_client.get_bars(symbols=[symbol], period=period, limit=limit, begin_time=begin, end_time=end)

    def query_history(self, req: HistoryRequest):
        """
        Query history bar data from RQData.
        """
        symbol = req.symbol
        exchange = req.exchange
        interval = req.interval
        start = req.start
        end = req.end

        # rq_symbol = self.to_rq_symbol(symbol, exchange)
        # if rq_symbol not in self.symbols:
        #     return None

        rq_interval = INTERVAL_VT2RQ.get(interval)
        if not rq_interval:
            return None

        # For adjust timestamp from bar close point (RQData) to open point (VN Trader)
        adjustment = INTERVAL_ADJUSTMENT_MAP[interval]

        # For querying night trading period data

        end += adjustment
        final = end.timestamp()
        
        calendar_name = EXCHANGE_CALENDAR[exchange]
        calendar = get_calendar(calendar_name)
        schedule = calendar.schedule(start, end)

        df = None
        for _,s in schedule.iterrows():
            df_data = self.openapi_client.get_bars([symbol], 
                                    period=rq_interval, 
                                    limit=5000, 
                                    begin_time=s.market_open.to_pydatetime().timestamp() * 1000, 
                                    end_time=s.market_close.to_pydatetime().timestamp() * 1000)
            if df_data.__len__() > 0:
                print("query_history:symbol={0},从{1}到{2},一共获取到{3}条数据".format(
                    symbol,
                    datetime.fromtimestamp(df_data['time'].iloc[0]/1000),
                    datetime.fromtimestamp(df_data['time'].iloc[-1]/1000),
                    df_data.__len__()))
            if df is None:
                df = df_data
            else:
                df = pd.concat([df, df_data])

            if df is None:
                return []
            if df.__len__() > 0:
                print("query_history:symbol={0},从{1}到{2},一共获取到{3}条数据".format(
                    symbol,
                    datetime.fromtimestamp(df['time'].iloc[0]/1000),
                    datetime.fromtimestamp(df['time'].iloc[-1]/1000),
                    df.__len__()))


        # 获取总时间间隔
        # interval_total = end - start
        # unix_start = start.timestamp() * 1000
        # unix_end = end.timestamp() * 1000
        # bars_start = start.timestamp()
        # bars_end = bars_start + timedelta(3).total_seconds()
        # bars_end = bars_end if bars_end < final else final
        # df = None
        # while bars_start < final:
        #     df_data = self.openapi_client.get_bars([symbol], 
        #                                       period=rq_interval, 
        #                                       limit=5000, 
        #                                       begin_time=bars_start * 1000, 
        #                                       end_time=bars_end * 1000)
        #     if df_data.__len__() > 0:
        #         print("query_history:symbol={0},从{1}到{2},一共获取到{3}条数据".format(
        #             symbol,
        #             datetime.fromtimestamp(df_data['time'].iloc[0]/1000),
        #             datetime.fromtimestamp(df_data['time'].iloc[-1]/1000),
        #             df_data.__len__()))
        #     bars_start = bars_end
        #     bars_end = bars_end + timedelta(3).total_seconds()
        #     bars_end = bars_end if bars_end < final else final
        #     if df_data.empty:
        #         continue
    
        #     if df is None:
        #         df = df_data
        #     else:
        #         df = pd.concat([df, df_data])
        #     print(df)
        
        # if df is None:
        #     return []
        # if df.__len__() > 0:
        #     print("query_history:symbol={0},从{1}到{2},一共获取到{3}条数据".format(
        #         symbol,
        #         datetime.fromtimestamp(df['time'].iloc[0]/1000),
        #         datetime.fromtimestamp(df['time'].iloc[-1]/1000),
        #         df.__len__()))

        # df = rqdata_get_price(
        #     rq_symbol,
        #     frequency=rq_interval,
        #     fields=["open", "high", "low", "close", "volume"],
        #     start_date=start,
        #     end_date=end,
        #     adjust_type="none"
        # )

        data: List[BarData] = []

        if df is not None:
            for ix, row in df.iterrows():
                bar = BarData(
                    symbol=symbol,
                    exchange=exchange,
                    interval=interval,
                    datetime=datetime.fromtimestamp(row.time / 1000),
                    open_price=row["open"],
                    high_price=row["high"],
                    low_price=row["low"],
                    close_price=row["close"],
                    volume=row["volume"],
                    gateway_name="RQ"
                )
                data.append(bar)

        return data
    'SLG', 'SNA', 'SO', 'LUV', 'SPGI', 'SWK', 'SBUX', 'STT', 'SRCL', 'SYK',
    'STI', 'SIVB', 'SYMC', 'SYF', 'SNPS', 'SYY', 'TROW', 'TTWO', 'TPR', 'TGT',
    'TEL', 'FTI', 'TXN', 'TXT', 'TMO', 'TIF', 'TWX', 'TJX', 'TMK', 'TSS',
    'TSCO', 'TDG', 'TRV', 'TRIP', 'FOXA', 'FOX', 'TSN', 'UDR', 'ULTA', 'USB',
    'UAA', 'UA', 'UNP', 'UAL', 'UNH', 'UPS', 'URI', 'UTX', 'UHS', 'UNM', 'VFC',
    'VLO', 'VAR', 'VTR', 'VRSN', 'VRSK', 'VZ', 'VRTX', 'VIAB', 'V', 'VNO',
    'VMC', 'WMT', 'WBA', 'DIS', 'WM', 'WAT', 'WEC', 'WFC', 'WELL', 'WDC', 'WU',
    'WRK', 'WY', 'WHR', 'WMB', 'WLTW', 'WYN', 'WYNN', 'XEL', 'XRX', 'XLNX',
    'XL', 'XYL', 'YUM', 'ZBH', 'ZION', 'ZTS'
]

client_config = get_client_config(private_key_path=PRIVATE_KEY_PATH,
                                  tiger_id=TIGER_ID,
                                  account=ACCOUNT,
                                  sandbox_debug=True)
quote_client = QuoteClient(client_config)
trade_client = TradeClient(client_config)

# 初始化 log 模块
logging.basicConfig(
    format='%(asctime)s - %(module)s - %(levelname)s - %(message)s',
    filename=LOG_PATH,
    filemode='a')
log = logging.getLogger(__name__)
log.setLevel(logging.INFO)


def recorder(func):
    @wraps(func)
    def do_log(*args, **kwargs):
        try:
Exemple #26
0
def get_quote():
    client_config = get_client_config()
    quote_client = QuoteClient(client_config)
    return quote_client.get_bars('600570')
Exemple #27
0
class TigerGateway(BaseGateway):
    """"""
    default_setting = {
        "tiger_id": "",
        "account": "",
        "standard_account": "",
        "private_key": '',
    }

    def __init__(self, event_engine):
        """Constructor"""
        super(TigerGateway, self).__init__(event_engine, "TIGER")

        self.tiger_id = ""
        self.account = ""
        self.standard_account = ""
        self.paper_account = ""
        self.language = ""

        self.client_config = None
        self.quote_client = None
        self.push_client = None

        self.local_id = 1000000
        self.tradeid = 0

        self.active = False
        self.queue = Queue()
        self.pool = None

        self.ID_TIGER2VT = {}
        self.ID_VT2TIGER = {}
        self.ticks = {}
        self.trades = set()
        self.contracts = {}
        self.symbol_names = {}

    def run(self):
        """"""
        while self.active:
            try:
                func, args = self.queue.get(timeout=0.1)
                func(*args)
            except Empty:
                pass

    def add_task(self, func, *args):
        """"""
        self.queue.put((func, [*args]))

    def connect(self, setting: dict):
        """"""
        self.private_key = setting['private_key']
        self.tiger_id = setting["tiger_id"]
        self.account = setting["account"]
        self.standard_account = setting["standard_account"]
        self.paper_account = setting["account"]
        self.languege = Language.zh_CN

        # Start thread pool for REST call
        self.active = True
        self.pool = Pool(5)
        self.pool.apply_async(self.run)

        # Put connect task into quque.
        self.init_client_config()
        self.add_task(self.connect_quote)
        self.add_task(self.connect_trade)
        self.add_task(self.connect_push)

    def init_client_config(self, sandbox=True):
        """"""
        self.client_config = TigerOpenClientConfig(sandbox_debug=sandbox)
        self.client_config.private_key = self.private_key
        self.client_config.tiger_id = self.tiger_id
        self.client_config.account = self.account
        self.client_config.standard_account = self.standard_account
        self.client_config.paper_account = self.paper_account
        self.client_config.language = self.language

    def connect_quote(self):
        """
        Connect to market data server.
        """
        try:
            self.quote_client = QuoteClient(self.client_config)
            self.symbol_names = dict(
                self.quote_client.get_symbol_names(lang=Language.zh_CN))
            self.query_contract()
        except ApiException:
            self.write_log("查询合约失败")
            return

        self.write_log("行情接口连接成功")
        self.write_log("合约查询成功")

    def connect_trade(self):
        """
        Connect to trade server.
        """
        self.trade_client = TradeClient(self.client_config)
        try:
            self.add_task(self.query_order)
            self.add_task(self.query_position)
            self.add_task(self.query_account)
        except ApiException:
            self.write_log("交易接口连接失败")
            return

        self.write_log("交易接口连接成功")

    def connect_push(self):
        """
        Connect to push server.
        """
        protocol, host, port = self.client_config.socket_host_port
        self.push_client = PushClient(host, port, (protocol == 'ssl'))
        self.push_client.connect(
            self.client_config.tiger_id, self.client_config.private_key)

        self.push_client.quote_changed = self.on_quote_change
        self.push_client.asset_changed = self.on_asset_change
        self.push_client.position_changed = self.on_position_change
        self.push_client.order_changed = self.on_order_change

        self.write_log("推送接口连接成功")

    def subscribe(self, req: SubscribeRequest):
        """"""
        self.push_client.subscribe_quote([req.symbol])
        self.push_client.subscribe_asset()
        self.push_client.subscribe_position()
        self.push_client.subscribe_order()

    def on_quote_change(self, tiger_symbol: str, data: list, trading: bool):
        """"""
        data = dict(data)
        symbol, exchange = convert_symbol_tiger2vt(tiger_symbol)

        tick = self.ticks.get(symbol, None)
        if not tick:
            tick = TickData(
                symbol=symbol,
                exchange=exchange,
                gateway_name=self.gateway_name,
                datetime=datetime.now(),
                name=self.symbol_names[symbol],
            )
            self.ticks[symbol] = tick

        tick.datetime = datetime.fromtimestamp(data["latest_time"] / 1000)
        tick.pre_close = data.get("prev_close", 0)
        tick.last_price = data.get("latest_price", 0)
        tick.volume = data.get("volume", 0)
        tick.open_price = data.get("open", 0)
        tick.open_price = data.get("open", 0)
        tick.high_price = data.get("high", 0)
        tick.low_price = data.get("low", 0)
        tick.ask_price_1 = data.get("ask_price", 0)
        tick.bid_price_1 = data.get("bid_price", 0)
        tick.ask_volume_1 = data.get("ask_size", 0)
        tick.bid_volume_1 = data.get("bid_size", 0)

        self.on_tick(copy(tick))

    def on_asset_change(self, tiger_account: str, data: list):
        """"""
        data = dict(data)
        if "net_liquidation" not in data:
            return

        account = AccountData(
            accountid=tiger_account,
            balance=data["net_liquidation"],
            frozen=0.0,
            gateway_name=self.gateway_name,
        )
        self.on_account(account)

    def on_position_change(self, tiger_account: str, data: list):
        """"""
        data = dict(data)
        symbol, exchange = convert_symbol_tiger2vt(data["origin_symbol"])

        pos = PositionData(
            symbol=symbol,
            exchange=exchange,
            direction=Direction.NET,
            volume=int(data["quantity"]),
            frozen=0.0,
            price=data["average_cost"],
            pnl=data["unrealized_pnl"],
            gateway_name=self.gateway_name,
        )
        self.on_position(pos)

    def on_order_change(self, tiger_account: str, data: list):
        """"""
        data = dict(data)
        print("委托推送", data["origin_symbol"],
              data["order_id"], data["filled"], data["status"])
        symbol, exchange = convert_symbol_tiger2vt(data["origin_symbol"])
        status = PUSH_STATUS_TIGER2VT[data["status"]]

        order = OrderData(
            symbol=symbol,
            exchange=exchange,
            orderid=self.ID_TIGER2VT.get(
                str(data["order_id"]), self.get_new_local_id()),
            direction=Direction.NET,
            price=data.get("limit_price", 0),
            volume=data["quantity"],
            traded=data["filled"],
            status=status,
            time=datetime.fromtimestamp(
                data["order_time"] / 1000).strftime("%H:%M:%S"),
            gateway_name=self.gateway_name,
        )
        self.on_order(order)

        if status == Status.ALLTRADED:
            self.tradeid += 1

            trade = TradeData(
                symbol=symbol,
                exchange=exchange,
                direction=Direction.NET,
                tradeid=self.tradeid,
                orderid=self.ID_TIGER2VT[str(data["order_id"])],
                price=data["avg_fill_price"],
                volume=data["filled"],
                time=datetime.fromtimestamp(
                    data["trade_time"] / 1000).strftime("%H:%M:%S"),
                gateway_name=self.gateway_name,
            )
            self.on_trade(trade)

    def get_new_local_id(self):
        self.local_id += 1
        return self.local_id

    def send_order(self, req: OrderRequest):
        """"""
        local_id = self.get_new_local_id()
        order = req.create_order_data(local_id, self.gateway_name)

        self.on_order(order)
        self.add_task(self._send_order, req, local_id)
        return order.vt_orderid

    def _send_order(self, req: OrderRequest, local_id):
        """"""
        currency = config_symbol_currency(req.symbol)
        try:
            contract = self.trade_client.get_contracts(
                symbol=req.symbol, currency=currency)[0]
            order = self.trade_client.create_order(
                account=self.account,
                contract=contract,
                action=DIRECTION_VT2TIGER[req.direction],
                order_type=ORDERTYPE_VT2TIGER[req.type],
                quantity=int(req.volume),
                limit_price=req.price,
            )
            self.ID_TIGER2VT[str(order.order_id)] = local_id
            self.ID_VT2TIGER[local_id] = str(order.order_id)

            self.trade_client.place_order(order)
            print("发单:", order.contract.symbol,
                  order.order_id, order.quantity, order.status)

        except:  # noqa
            traceback.print_exc()
            self.write_log("发单失败")
            return

    def cancel_order(self, req: CancelRequest):
        """"""
        self.add_task(self._cancel_order, req)

    def _cancel_order(self, req: CancelRequest):
        """"""
        try:
            order_id = self.ID_VT2TIGER[req.orderid]
            data = self.trade_client.cancel_order(order_id=order_id)
        except ApiException:
            self.write_log(f"撤单失败:{req.orderid}")

        if not data:
            self.write_log('撤单成功')

    def query_contract(self):
        """"""
        # HK Stock

        symbols_names_HK = self.quote_client.get_symbol_names(
            lang=Language.zh_CN, market=Market.HK)
        contract_names_HK = DataFrame(
            symbols_names_HK, columns=['symbol', 'name'])

        contractList = list(contract_names_HK["symbol"])
        i, n = 0, len(contractList)
        result = pd.DataFrame()
        while i < n:
            i += 500
            c = contractList[i - 500:i]
            r = self.quote_client.get_trade_metas(c)
            result = result.append(r)

        contract_detail_HK = result.sort_values(by="symbol", ascending=True)
        contract_HK = pd.merge(
            contract_names_HK, contract_detail_HK, how='left', on='symbol')

        for ix, row in contract_HK.iterrows():
            contract = ContractData(
                symbol=row["symbol"],
                exchange=Exchange.SEHK,
                name=row["name"],
                product=Product.EQUITY,
                size=1,
                pricetick=row["min_tick"],
                net_position=True,
                gateway_name=self.gateway_name,
            )
            self.on_contract(contract)
            self.contracts[contract.vt_symbol] = contract

        # US Stock
        symbols_names_US = self.quote_client.get_symbol_names(
            lang=Language.zh_CN, market=Market.US)
        contract_US = DataFrame(symbols_names_US, columns=['symbol', 'name'])

        for ix, row in contract_US.iterrows():
            contract = ContractData(
                symbol=row["symbol"],
                exchange=Exchange.SMART,
                name=row["name"],
                product=Product.EQUITY,
                size=1,
                pricetick=0.001,
                gateway_name=self.gateway_name,
            )
            self.on_contract(contract)
            self.contracts[contract.vt_symbol] = contract

        # CN Stock
        symbols_names_CN = self.quote_client.get_symbol_names(
            lang=Language.zh_CN, market=Market.CN)
        contract_CN = DataFrame(symbols_names_CN, columns=['symbol', 'name'])

        for ix, row in contract_CN.iterrows():
            symbol = row["symbol"]
            symbol, exchange = convert_symbol_tiger2vt(symbol)

            contract = ContractData(
                symbol=symbol,
                exchange=exchange,
                name=row["name"],
                product=Product.EQUITY,
                size=1,
                pricetick=0.001,
                gateway_name=self.gateway_name,
            )
            self.on_contract(contract)
            self.contracts[contract.vt_symbol] = contract

    def query_account(self):
        """"""
        try:
            assets = self.trade_client.get_assets()
        except ApiException:
            self.write_log("查询资金失败")
            return

        for i in assets:
            account = AccountData(
                accountid=self.account,
                balance=i.summary.net_liquidation,
                frozen=0.0,
                gateway_name=self.gateway_name,
            )

            self.on_account(account)

    def query_position(self):
        """"""
        try:
            position = self.trade_client.get_positions()
        except ApiException:
            self.write_log("查询持仓失败")
            return

        for i in position:
            symbol, exchange = convert_symbol_tiger2vt(i.contract.symbol)

            pos = PositionData(
                symbol=symbol,
                exchange=exchange,
                direction=Direction.NET,
                volume=int(i.quantity),
                frozen=0.0,
                price=i.average_cost,
                pnl=float(i.unrealized_pnl),
                gateway_name=self.gateway_name,
            )

            self.on_position(pos)

    def query_order(self):
        """"""
        try:
            data = self.trade_client.get_orders()
            data = sorted(data, key=lambda x: x.order_time, reverse=False)
        except:  # noqa
            traceback.print_exc()
            self.write_log("查询委托失败")
            return

        self.process_order(data)
        self.process_deal(data)

    def close(self):
        """"""
        self.active = False

        if self.push_client:
            self.push_client.disconnect()

    def process_order(self, data):
        """"""
        for i in data:
            symbol, exchange = convert_symbol_tiger2vt(str(i.contract))
            local_id = self.get_new_local_id()

            order = OrderData(
                symbol=symbol,
                exchange=exchange,
                orderid=local_id,
                direction=Direction.NET,
                price=i.limit_price if i.limit_price else 0.0,
                volume=i.quantity,
                traded=i.filled,
                status=STATUS_TIGER2VT[i.status],
                time=datetime.fromtimestamp(
                    i.order_time / 1000).strftime("%H:%M:%S"),
                gateway_name=self.gateway_name,
            )
            self.ID_TIGER2VT[str(i.order_id)] = local_id
            self.on_order(order)

        self.ID_VT2TIGER = {v: k for k, v in self.ID_TIGER2VT.items()}
        print("原始委托字典", self.ID_TIGER2VT)
        print("原始反向字典", self.ID_VT2TIGER)

    def process_deal(self, data):
        """
        Process trade data for both query and update.
        """
        for i in data:
            if i.status == ORDER_STATUS.PARTIALLY_FILLED or i.status == ORDER_STATUS.FILLED:
                symbol, exchange = convert_symbol_tiger2vt(str(i.contract))
                self.tradeid += 1

                trade = TradeData(
                    symbol=symbol,
                    exchange=exchange,
                    direction=Direction.NET,
                    tradeid=self.tradeid,
                    orderid=self.ID_TIGER2VT[str(i.order_id)],
                    price=i.avg_fill_price,
                    volume=i.filled,
                    time=datetime.fromtimestamp(
                        i.trade_time / 1000).strftime("%H:%M:%S"),
                    gateway_name=self.gateway_name,
                )

                self.on_trade(trade)
Exemple #28
0

def random_color():
    color_arr = [
        '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E',
        'F'
    ]
    color = ""
    for i in range(6):
        color += color_arr[random.randint(0, 14)]
    return "#" + color


if __name__ == '__main__':
    config = get_client_config()
    quant_client = QuoteClient(config)

    stocks = ['QQQ', 'TLT']
    data = quant_client.get_bars(stocks)

    years = mdates.YearLocator()  # every year
    months = mdates.MonthLocator()  # every month
    yearsFmt = mdates.DateFormatter('%Y')

    # fig, ax = plt.subplots()
    fig = plt.figure()
    ax = fig.add_subplot(111)

    # ax1 = None
    # for index, stock in stocks:
    y1 = data.loc[(data["symbol"] == stocks[0])]