def trade_apis():
    account = client_config.account
    openapi_client = TradeClient(client_config, logger=logger)

    # stock
    contract = openapi_client.get_contracts('AAPL')[0]
    # 或者本地构造合约对象
    # contract = stock_contract(symbol='AAPL', currency='USD')

    # option
    # contract = option_contract(identifier='AAPL  190118P00160000')
    # future
    # contract = future_contract('CHF', 'USD', '20190617', multiplier=125000, exchange='GLOBEX')

    order = openapi_client.create_order(account,
                                        contract,
                                        'BUY',
                                        'LMT',
                                        100,
                                        limit_price=5.0)
    # 或者本地构造订单对象
    # order = limit_order(account=account, contract=contract, action='BUY', quantity=100, limit_price=5.0)
    openapi_client.place_order(order)
    order_id = order.order_id  # you can operate order via id too

    new_order = openapi_client.get_order(order_id=order.order_id)
    assert order.order_id == new_order.order_id
    openapi_client.modify_order(new_order, quantity=150)
    new_order = openapi_client.get_order(order_id=order_id)
    assert new_order.quantity == 150
    openapi_client.cancel_order(order_id=order_id)
    new_order = openapi_client.get_order(order_id=order_id)
    assert new_order.status == OrderStatus.CANCELLED or new_order.status == OrderStatus.PENDING_CANCEL
def trade_apis():
    account = client_config.account
    openapi_client = TradeClient(client_config, logger=logger)
    # stock
    contract = openapi_client.get_contracts('AAPL')[0]
    # option
    # contract = option_contract(identifier='AAPL  190118P00160000')
    # future
    # contract = future_contract('CHF', 'USD', '20190617', multiplier=125000)
    # contract.exchange = 'GLOBEX'
    order = openapi_client.create_order(account,
                                        contract,
                                        'BUY',
                                        'LMT',
                                        100,
                                        limit_price=0.1)
    order_id = order.order_id  # you can operate order via id too
    openapi_client.place_order(order)
    new_order = openapi_client.get_order(order_id=order.order_id)
    assert order.order_id == new_order.order_id
    openapi_client.modify_order(new_order, quantity=150)
    new_order = openapi_client.get_order(order_id=order_id)
    assert new_order.quantity == 150
    openapi_client.cancel_order(order_id=order_id)
    new_order = openapi_client.get_order(order_id=order_id)
    assert new_order.status == ORDER_STATUS.CANCELLED or new_order.status == ORDER_STATUS.PENDING_CANCEL
def trade_apis():
    account = client_config.account
    openapi_client = TradeClient(client_config, logger=logger)

    # 通过请求获取合约
    contract = openapi_client.get_contracts('AAPL')[0]
    # contract = openapi_client.get_contract('AAPL', SecurityType.STK, currency=Currency.USD)

    # 本地构造合约
    # stock 股票
    # contract = stock_contract(symbol='AAPL', currency='USD')
    # option 期权
    # contract = option_contract(identifier='AAPL  190118P00160000')
    # contract = option_contract_by_symbol('AAPL', '20200110', strike=280.0, put_call='PUT', currency='USD')
    # future 期货
    # contract = future_contract('CHF', 'USD', '20190617', multiplier=125000, exchange='GLOBEX')
    # war 港股窝轮
    # contract = war_contract_by_symbol('02318', '20200326', 107.08, 'CALL', local_symbol='12616', currency='HKD')
    # iopt 港股牛熊证
    # contract = iopt_contract_by_symbol('02318', '20200420', 87.4, 'CALL', local_symbol='63379', currency='HKD')

    order = openapi_client.create_order(account, contract, 'BUY', 'LMT', 100, limit_price=5.0)
    # 或者本地构造订单对象
    # order = limit_order(account=account, contract=contract, action='BUY', quantity=100, limit_price=5.0)
    openapi_client.place_order(order)

    new_order = openapi_client.get_order(id=order.id)
    assert order.order_id == new_order.order_id
    openapi_client.modify_order(new_order, quantity=150)
    new_order = openapi_client.get_order(id=order.id)
    assert new_order.quantity == 150
    openapi_client.cancel_order(id=order.id)
    new_order = openapi_client.get_order(id=order.id)
    assert new_order.status == OrderStatus.CANCELLED or new_order.status == OrderStatus.PENDING_CANCEL

    # 预览订单 (下单前后保证金要求, 佣金等预览)
    result = openapi_client.preview_order(order)
    print(result)

    # 限价单 + 附加订单 (仅主订单为限价单时支持附加订单)
    stop_loss_order_leg = order_leg('LOSS', 8.0, time_in_force='GTC')  # 附加止损
    profit_taker_order_leg = order_leg('PROFIT', 12.0, time_in_force='GTC')  # 附加止盈

    main_order = openapi_client.create_order(account, contract, 'BUY', 'LMT', quantity=100, limit_price=10.0,
                                             order_legs=[stop_loss_order_leg, profit_taker_order_leg])
    # 本地构造限价单 + 附加订单
    # main_order = limit_order_with_legs(account, contract, 'BUY', 100, limit_price=10.0,
    # order_legs=[stop_loss_order_leg])

    openapi_client.place_order(main_order)
    print(main_order)
    # 查询主订单所关联的附加订单
    order_legs = openapi_client.get_open_orders(account, parent_id=main_order.order_id)
    print(order_legs)
def trade_apis():
    account = client_config.account
    openapi_client = TradeClient(client_config, logger=logger)
    contract = openapi_client.get_contracts('AAPL')[0]
    order = openapi_client.create_order(account, contract, 'BUY', 'LMT', 100, limit_price=5.0)
    order_id = order.order_id  # you can operate order via id too
    openapi_client.place_order(order)
    new_order = openapi_client.get_order(order_id=order.order_id)
    assert order.order_id == new_order.order_id
    openapi_client.modify_order(new_order, quantity=150)
    new_order = openapi_client.get_order(order_id=order_id)
    assert new_order.quantity == 150
    openapi_client.cancel_order(order_id=order_id)
    new_order = openapi_client.get_order(order_id=order_id)
    assert new_order.status == ORDER_STATUS.CANCELLED or new_order.status == ORDER_STATUS.PENDING_CANCEL
Esempio n. 5
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)
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)
Esempio n. 7
0
def trade_apis():
    account = client_config.account
    openapi_client = TradeClient(client_config, logger=logger)

    # stock
    contract = openapi_client.get_contracts('AAPL')[0]
    # 或者本地构造合约对象
    # contract = stock_contract(symbol='AAPL', currency='USD')

    # option
    # contract = option_contract(identifier='AAPL  190118P00160000')
    # future
    # contract = future_contract('CHF', 'USD', '20190617', multiplier=125000, exchange='GLOBEX')

    order = openapi_client.create_order(account,
                                        contract,
                                        'BUY',
                                        'LMT',
                                        100,
                                        limit_price=5.0)
    # 或者本地构造订单对象
    # order = limit_order(account=account, contract=contract, action='BUY', quantity=100, limit_price=5.0)
    openapi_client.place_order(order)
    order_id = order.order_id  # you can operate order via id too

    new_order = openapi_client.get_order(order_id=order.order_id)
    assert order.order_id == new_order.order_id
    openapi_client.modify_order(new_order, quantity=150)
    new_order = openapi_client.get_order(order_id=order_id)
    assert new_order.quantity == 150
    openapi_client.cancel_order(order_id=order_id)
    new_order = openapi_client.get_order(order_id=order_id)
    assert new_order.status == OrderStatus.CANCELLED or new_order.status == OrderStatus.PENDING_CANCEL

    # 预览订单 (下单前后保证金要求, 佣金等预览)
    result = openapi_client.preview_order(order)
    print(result)

    # 限价单 + 附加订单 (仅主订单为限价单时支持附加订单)
    stop_loss_order_leg = order_leg('LOSS', 8.0, time_in_force='GTC')  # 附加止损
    profit_taker_order_leg = order_leg('PROFIT', 12.0,
                                       time_in_force='GTC')  # 附加止盈

    main_order = openapi_client.create_order(
        account,
        contract,
        'BUY',
        'LMT',
        quantity=100,
        limit_price=10.0,
        order_legs=[stop_loss_order_leg, profit_taker_order_leg])
    # 本地构造限价单 + 附加订单
    # main_order = limit_order_with_legs(account, contract, 'BUY', 100, limit_price=10.0,
    # order_legs=[stop_loss_order_leg])

    openapi_client.place_order(main_order)
    print(main_order)
    # 查询主订单所关联的附加订单
    order_legs = openapi_client.get_open_orders(account,
                                                parent_id=main_order.order_id)
    print(order_legs)