<NME> sgit_gateway.py
<BEF> ADDFILE
<MSG> Merge pull request #2335 from 1122455801/SgitGateway00

[Mod] add vnpy.api.sgit
<DFF> @@ -0,0 +1,859 @@
+"""
+"""
+
+import sys
+from datetime import datetime
+from typing import Dict, List
+
+from vnpy.api.sgit import (
+    MdApi,
+    TdApi,
+    THOST_FTDC_OAS_Submitted,
+    THOST_FTDC_OAS_Accepted,
+    THOST_FTDC_OAS_Rejected,
+    THOST_FTDC_OST_NoTradeQueueing,
+    THOST_FTDC_OST_PartTradedQueueing,
+    THOST_FTDC_OST_AllTraded,
+    THOST_FTDC_OST_Canceled,
+    THOST_FTDC_D_Buy,
+    THOST_FTDC_D_Sell,
+    THOST_FTDC_PD_Long,
+    THOST_FTDC_PD_Short,
+    THOST_FTDC_OPT_LimitPrice,
+    THOST_FTDC_OPT_AnyPrice,
+    THOST_FTDC_OF_Open,
+    THOST_FTDC_OFEN_Close,
+    THOST_FTDC_OFEN_CloseYesterday,
+    THOST_FTDC_OFEN_CloseToday,
+    THOST_FTDC_PC_Futures,
+    THOST_FTDC_PC_Options,
+    THOST_FTDC_PC_SpotOption,
+    THOST_FTDC_PC_Combination,
+    THOST_FTDC_CP_CallOptions,
+    THOST_FTDC_CP_PutOptions,
+    THOST_FTDC_HF_Speculation,
+    THOST_FTDC_CC_Immediately,
+    THOST_FTDC_FCC_NotForceClose,
+    THOST_FTDC_TC_GFD,
+    THOST_FTDC_VC_AV,
+    THOST_FTDC_TC_IOC,
+    THOST_FTDC_VC_CV,
+    THOST_FTDC_AF_Delete
+)
+from vnpy.trader.constant import (
+    Direction,
+    Offset,
+    Exchange,
+    OrderType,
+    Product,
+    Status,
+    OptionType
+)
+from vnpy.trader.gateway import BaseGateway
+from vnpy.trader.object import (
+    TickData,
+    OrderData,
+    TradeData,
+    PositionData,
+    AccountData,
+    ContractData,
+    OrderRequest,
+    CancelRequest,
+    SubscribeRequest,
+)
+from vnpy.trader.utility import get_folder_path
+from vnpy.trader.event import EVENT_TIMER
+
+
+STATUS_SGIT2VT: Dict[str, Status] = {
+    THOST_FTDC_OAS_Submitted: Status.SUBMITTING,
+    THOST_FTDC_OAS_Accepted: Status.SUBMITTING,
+    THOST_FTDC_OAS_Rejected: Status.REJECTED,
+    THOST_FTDC_OST_NoTradeQueueing: Status.NOTTRADED,
+    THOST_FTDC_OST_PartTradedQueueing: Status.PARTTRADED,
+    THOST_FTDC_OST_AllTraded: Status.ALLTRADED,
+    THOST_FTDC_OST_Canceled: Status.CANCELLED
+}
+
+DIRECTION_VT2SGIT: Dict[Direction, str] = {
+    Direction.LONG: THOST_FTDC_D_Buy,
+    Direction.SHORT: THOST_FTDC_D_Sell
+}
+DIRECTION_SGIT2VT: Dict[str, Direction] = {v: k for k, v in DIRECTION_VT2SGIT.items()}
+DIRECTION_SGIT2VT[THOST_FTDC_PD_Long] = Direction.LONG
+DIRECTION_SGIT2VT[THOST_FTDC_PD_Short] = Direction.SHORT
+
+ORDERTYPE_VT2SGIT: Dict[OrderType, str] = {
+    OrderType.LIMIT: THOST_FTDC_OPT_LimitPrice,
+    OrderType.MARKET: THOST_FTDC_OPT_AnyPrice
+}
+ORDERTYPE_SGIT2VT: Dict[str, OrderType] = {v: k for k, v in ORDERTYPE_VT2SGIT.items()}
+
+OFFSET_VT2SGIT: Dict[Offset, str] = {
+    Offset.OPEN: THOST_FTDC_OF_Open,
+    Offset.CLOSE: THOST_FTDC_OFEN_Close,
+    Offset.CLOSETODAY: THOST_FTDC_OFEN_CloseToday,
+    Offset.CLOSEYESTERDAY: THOST_FTDC_OFEN_CloseYesterday,
+}
+OFFSET_SGIT2VT: Dict[str, Offset] = {v: k for k, v in OFFSET_VT2SGIT.items()}
+
+EXCHANGE_SGIT2VT: Dict[str, Exchange] = {
+    "CFFEX": Exchange.CFFEX,
+    "SHFE": Exchange.SHFE,
+    "CZCE": Exchange.CZCE,
+    "DCE": Exchange.DCE,
+    "INE": Exchange.INE
+}
+
+PRODUCT_SGIT2VT: Dict[str, Product] = {
+    THOST_FTDC_PC_Futures: Product.FUTURES,
+    THOST_FTDC_PC_Options: Product.OPTION,
+    THOST_FTDC_PC_SpotOption: Product.OPTION,
+    THOST_FTDC_PC_Combination: Product.SPREAD
+}
+
+OPTIONTYPE_SGIT2VT: Dict[str, OptionType] = {
+    THOST_FTDC_CP_CallOptions: OptionType.CALL,
+    THOST_FTDC_CP_PutOptions: OptionType.PUT
+}
+
+MAX_FLOAT: float = sys.float_info.max
+
+
+symbol_exchange_map: Dict = {}
+symbol_name_map: Dict = {}
+symbol_size_map: Dict = {}
+
+
+class SgitGateway(BaseGateway):
+    """
+    VN Trader Gateway for CTP .
+    """
+
+    default_setting: Dict[str, str] = {
+        "用户名": "",
+        "密码": "",
+        "经纪商代码": "",
+        "交易服务器": "",
+        "行情服务器": "",
+        "产品名称": "",
+        "授权编码": "",
+        "产品信息": ""
+    }
+
+    exchanges: List[Exchange] = list(EXCHANGE_SGIT2VT.values())
+
+    def __init__(self, event_engine):
+        """Constructor"""
+        super().__init__(event_engine, "CTP")
+
+        self.td_api = SgitTsdApi(self)
+        self.md_api = SgitMdApi(self)
+
+    def connect(self, setting: dict) -> None:
+        """"""
+        userid = setting["用户名"]
+        password = setting["密码"]
+        brokerid = setting["经纪商代码"]
+        td_address = setting["交易服务器"]
+        md_address = setting["行情服务器"]
+        appid = setting["产品名称"]
+        auth_code = setting["授权编码"]
+        product_info = setting["产品信息"]
+
+        if (
+            (not td_address.startswith("tcp://"))
+            and (not td_address.startswith("ssl://"))
+        ):
+            td_address = "tcp://" + td_address
+
+        if (
+            (not md_address.startswith("tcp://"))
+            and (not md_address.startswith("ssl://"))
+        ):
+            md_address = "tcp://" + md_address
+
+        self.td_api.connect(td_address, userid, password, brokerid, auth_code, appid, product_info)
+        self.md_api.connect(md_address, userid, password, brokerid)
+
+        self.init_query()
+
+    def subscribe(self, req: SubscribeRequest) -> None:
+        """"""
+        self.md_api.subscribe(req)
+
+    def send_order(self, req: OrderRequest) -> str:
+        """"""
+        return self.td_api.send_order(req)
+
+    def cancel_order(self, req: CancelRequest) -> None:
+        """"""
+        self.td_api.cancel_order(req)
+
+    def query_account(self) -> None:
+        """"""
+        self.td_api.query_account()
+
+    def query_position(self) -> None:
+        """"""
+        self.td_api.query_position()
+
+    def close(self) -> None:
+        """"""
+        self.td_api.close()
+        self.md_api.close()
+
+    def write_error(self, msg: str, error: dict) -> None:
+        """"""
+        error_id = error["ErrorID"]
+        error_msg = error["ErrorMsg"]
+        msg = f"{msg}，代码：{error_id}，信息：{error_msg}"
+        self.write_log(msg)
+
+    def process_timer_event(self, event) -> None:
+        """"""
+        self.count += 1
+        if self.count < 2:
+            return
+        self.count = 0
+
+        func = self.query_functions.pop(0)
+        func()
+        self.query_functions.append(func)
+
+    def init_query(self) -> None:
+        """"""
+        self.count = 0
+        self.query_functions = [self.query_account, self.query_position]
+        self.event_engine.register(EVENT_TIMER, self.process_timer_event)
+
+
+class SgitMdApi(MdApi):
+    """"""
+
+    def __init__(self, gateway):
+        """Constructor"""
+        super(SgitMdApi, self).__init__()
+
+        self.gateway = gateway
+        self.gateway_name = gateway.gateway_name
+
+        self.reqid = 0
+
+        self.connect_status = False
+        self.login_status = False
+        self.subscribed = set()
+
+        self.userid = ""
+        self.password = ""
+        self.brokerid = ""
+
+    def onFrontConnected(self):
+        """
+        Callback when front server is connected.
+        """
+        self.gateway.write_log("行情服务器连接成功")
+        self.login()
+
+    def onFrontDisconnected(self, reason: int):
+        """
+        Callback when front server is disconnected.
+        """
+        self.login_status = False
+        self.gateway.write_log(f"行情服务器连接断开，原因{reason}")
+
+    def onRspUserLogin(self, data: dict, error: dict, reqid: int, last: bool):
+        """
+        Callback when user is logged in.
+        """
+        if not error["ErrorID"]:
+            self.login_status = True
+            self.gateway.write_log("行情服务器登录成功")
+
+            for symbol in self.subscribed:
+                self.subscribeMarketData(symbol)
+        else:
+            self.gateway.write_error("行情服务器登录失败", error)
+
+    def onRspError(self, error: dict, reqid: int, last: bool):
+        """
+        Callback when error occured.
+        """
+        self.gateway.write_error("行情接口报错", error)
+
+    def onRspSubMarketData(self, data: dict, error: dict, reqid: int, last: bool):
+        """"""
+        if not error or not error["ErrorID"]:
+            return
+
+        self.gateway.write_error("行情订阅失败", error)
+
+    def onRtnDepthMarketData(self, data: dict):
+        """
+        Callback of tick data update.
+        """
+        symbol = data["InstrumentID"]
+        exchange = symbol_exchange_map.get(symbol, "")
+        if not exchange:
+            return
+
+        timestamp = f"{data['ActionDay']} {data['UpdateTime']}.{int(data['UpdateMillisec']/100)}"
+
+        tick = TickData(
+            symbol=symbol,
+            exchange=exchange,
+            datetime=datetime.strptime(timestamp, "%Y%m%d %H:%M:%S.%f"),
+            name=symbol_name_map[symbol],
+            volume=data["Volume"],
+            open_interest=data["OpenInterest"],
+            last_price=data["LastPrice"],
+            limit_up=data["UpperLimitPrice"],
+            limit_down=data["LowerLimitPrice"],
+            open_price=adjust_price(data["OpenPrice"]),
+            high_price=adjust_price(data["HighestPrice"]),
+            low_price=adjust_price(data["LowestPrice"]),
+            pre_close=adjust_price(data["PreClosePrice"]),
+            bid_price_1=adjust_price(data["BidPrice1"]),
+            ask_price_1=adjust_price(data["AskPrice1"]),
+            bid_volume_1=data["BidVolume1"],
+            ask_volume_1=data["AskVolume1"],
+            gateway_name=self.gateway_name
+        )
+
+        if data["BidVolume2"] or data["AskVolume2"]:
+            tick.bid_price_2 = adjust_price(data["BidPrice2"])
+            tick.bid_price_3 = adjust_price(data["BidPrice3"])
+            tick.bid_price_4 = adjust_price(data["BidPrice4"])
+            tick.bid_price_5 = adjust_price(data["BidPrice5"])
+
+            tick.ask_price_2 = adjust_price(data["AskPrice2"])
+            tick.ask_price_3 = adjust_price(data["AskPrice3"])
+            tick.ask_price_4 = adjust_price(data["AskPrice4"])
+            tick.ask_price_5 = adjust_price(data["AskPrice5"])
+
+            tick.bid_volume_2 = adjust_price(data["BidVolume2"])
+            tick.bid_volume_3 = adjust_price(data["BidVolume3"])
+            tick.bid_volume_4 = adjust_price(data["BidVolume4"])
+            tick.bid_volume_5 = adjust_price(data["BidVolume5"])
+
+            tick.ask_volume_2 = adjust_price(data["AskVolume2"])
+            tick.ask_volume_3 = adjust_price(data["AskVolume3"])
+            tick.ask_volume_4 = adjust_price(data["AskVolume4"])
+            tick.ask_volume_5 = adjust_price(data["AskVolume5"])
+
+        self.gateway.on_tick(tick)
+
+    def connect(self, address: str, userid: str, password: str, brokerid: int):
+        """
+        Start connection to server.
+        """
+        self.userid = userid
+        self.password = password
+        self.brokerid = brokerid
+
+        # If not connected, then start connection first.
+        if not self.connect_status:
+            path = get_folder_path(self.gateway_name.lower())
+            self.createFtdcMdApi(str(path) + "\\Md")
+
+            self.registerFront(address)
+            self.init()
+
+            self.connect_status = True
+        # If already connected, then login immediately.
+        elif not self.login_status:
+            self.login()
+
+    def login(self):
+        """
+        Login onto server.
+        """
+        req = {
+            "UserID": self.userid,
+            "Password": self.password,
+            "BrokerID": self.brokerid
+        }
+
+        self.reqid += 1
+        self.reqUserLogin(req, self.reqid)
+
+    def subscribe(self, req: SubscribeRequest):
+        """
+        Subscribe to tick data update.
+        """
+        if self.login_status:
+            self.subscribeMarketData(req.symbol)
+        self.subscribed.add(req.symbol)
+
+    def close(self):
+        """
+        Close the connection.
+        """
+        if self.connect_status:
+            self.exit()
+
+
+class SgitTsdApi(TdApi):
+    """"""
+
+    def __init__(self, gateway):
+        """Constructor"""
+        super(SgitTsdApi, self).__init__()
+
+        self.gateway = gateway
+        self.gateway_name = gateway.gateway_name
+
+        self.reqid = 0
+        self.order_ref = 0
+
+        self.connect_status = False
+        self.login_status = False
+        self.auth_staus = False
+        self.login_failed = False
+
+        self.userid = ""
+        self.password = ""
+        self.brokerid = ""
+        self.auth_code = ""
+        self.appid = ""
+        self.product_info = ""
+
+        self.frontid = 0
+        self.sessionid = 0
+
+        self.order_data = []
+        self.trade_data = []
+        self.positions = {}
+        self.sysid_orderid_map = {}
+
+    def onFrontConnected(self):
+        """"""
+        self.gateway.write_log("交易服务器连接成功")
+
+        if self.auth_code:
+            self.authenticate()
+        else:
+            self.login()
+
+    def onFrontDisconnected(self, reason: int):
+        """"""
+        self.login_status = False
+        self.gateway.write_log(f"交易服务器连接断开，原因{reason}")
+
+    def onRspAuthenticate(self, data: dict, error: dict, reqid: int, last: bool):
+        """"""
+        if not error['ErrorID']:
+            self.auth_staus = True
+            self.gateway.write_log("交易服务器授权验证成功")
+            self.login()
+        else:
+            self.gateway.write_error("交易服务器授权验证失败", error)
+
+    def onRspUserLogin(self, data: dict, error: dict, reqid: int, last: bool):
+        """"""
+        if not error["ErrorID"]:
+            self.frontid = data["FrontID"]
+            self.sessionid = data["SessionID"]
+            self.login_status = True
+            self.gateway.write_log("交易服务器登录成功")
+
+            # Confirm settlement
+            req = {
+                "BrokerID": self.brokerid,
+                "InvestorID": self.userid
+            }
+            self.reqid += 1
+            self.reqSettlementInfoConfirm(req, self.reqid)
+        else:
+            self.login_failed = True
+
+            self.gateway.write_error("交易服务器登录失败", error)
+
+    def onRspOrderInsert(self, data: dict, error: dict, reqid: int, last: bool):
+        """"""
+        order_ref = data["OrderRef"]
+        orderid = f"{self.frontid}_{self.sessionid}_{order_ref}"
+
+        symbol = data["InstrumentID"]
+        exchange = symbol_exchange_map[symbol]
+
+        order = OrderData(
+            symbol=symbol,
+            exchange=exchange,
+            orderid=orderid,
+            direction=DIRECTION_SGIT2VT[data["Direction"]],
+            offset=OFFSET_SGIT2VT.get(data["CombOffsetFlag"], Offset.NONE),
+            price=data["LimitPrice"],
+            volume=data["VolumeTotalOriginal"],
+            status=Status.REJECTED,
+            gateway_name=self.gateway_name
+        )
+        self.gateway.on_order(order)
+
+        self.gateway.write_error("交易委托失败", error)
+
+    def onRspOrderAction(self, data: dict, error: dict, reqid: int, last: bool):
+        """"""
+        self.gateway.write_error("交易撤单失败", error)
+
+    def onRspQueryMaxOrderVolume(self, data: dict, error: dict, reqid: int, last: bool):
+        """"""
+        pass
+
+    def onRspSettlementInfoConfirm(self, data: dict, error: dict, reqid: int, last: bool):
+        """
+        Callback of settlment info confimation.
+        """
+        self.gateway.write_log("结算信息确认成功")
+
+        self.reqid += 1
+        self.reqQryInstrument({}, self.reqid)
+
+    def onRspQryInvestorPosition(self, data: dict, error: dict, reqid: int, last: bool):
+        """"""
+        if not data:
+            return
+
+        # Check if contract data received
+        if data["InstrumentID"] in symbol_exchange_map:
+            # Get buffered position object
+            key = f"{data['InstrumentID'], data['PosiDirection']}"
+            position = self.positions.get(key, None)
+            if not position:
+                position = PositionData(
+                    symbol=data["InstrumentID"],
+                    exchange=symbol_exchange_map[data["InstrumentID"]],
+                    direction=DIRECTION_SGIT2VT[data["PosiDirection"]],
+                    gateway_name=self.gateway_name
+                )
+                self.positions[key] = position
+
+            # For SHFE and INE position data update
+            if position.exchange in [Exchange.SHFE, Exchange.INE]:
+                if data["YdPosition"] and not data["TodayPosition"]:
+                    position.yd_volume = data["Position"]
+            # For other exchange position data update
+            else:
+                position.yd_volume = data["Position"] - data["TodayPosition"]
+
+            # Get contract size (spread contract has no size value)
+            size = symbol_size_map.get(position.symbol, 0)
+
+            # Calculate previous position cost
+            cost = position.price * position.volume * size
+
+            # Update new position volume
+            position.volume += data["Position"]
+            position.pnl += data["PositionProfit"]
+
+            # Calculate average position price
+            if position.volume and size:
+                cost += data["PositionCost"]
+                position.price = cost / (position.volume * size)
+
+            # Get frozen volume
+            if position.direction == Direction.LONG:
+                position.frozen += data["ShortFrozen"]
+            else:
+                position.frozen += data["LongFrozen"]
+
+        if last:
+            for position in self.positions.values():
+                self.gateway.on_position(position)
+
+            self.positions.clear()
+
+    def onRspQryTradingAccount(self, data: dict, error: dict, reqid: int, last: bool):
+        """"""
+        if "AccountID" not in data:
+            return
+
+        account = AccountData(
+            accountid=data["AccountID"],
+            balance=data["Balance"],
+            frozen=data["FrozenMargin"] + data["FrozenCash"] + data["FrozenCommission"],
+            gateway_name=self.gateway_name
+        )
+        account.available = data["Available"]
+
+        self.gateway.on_account(account)
+
+    def onRspQryInstrument(self, data: dict, error: dict, reqid: int, last: bool):
+        """
+        Callback of instrument query.
+        """
+        product = PRODUCT_SGIT2VT.get(data["ProductClass"], None)
+        if product:
+            contract = ContractData(
+                symbol=data["InstrumentID"],
+                exchange=EXCHANGE_SGIT2VT[data["ExchangeID"]],
+                name=data["InstrumentName"],
+                product=product,
+                size=data["VolumeMultiple"],
+                pricetick=data["PriceTick"],
+                gateway_name=self.gateway_name
+            )
+
+            # For option only
+            if contract.product == Product.OPTION:
+                # Remove C/P suffix of CZCE option product name
+                if contract.exchange == Exchange.CZCE:
+                    contract.option_portfolio = data["ProductID"][:-1]
+                else:
+                    contract.option_portfolio = data["ProductID"]
+
+                contract.option_underlying = data["UnderlyingInstrID"]
+                contract.option_type = OPTIONTYPE_SGIT2VT.get(data["OptionsType"], None)
+                contract.option_strike = data["StrikePrice"]
+                contract.option_index = str(data["StrikePrice"])
+                contract.option_expiry = datetime.strptime(data["ExpireDate"], "%Y%m%d")
+
+            self.gateway.on_contract(contract)
+
+            symbol_exchange_map[contract.symbol] = contract.exchange
+            symbol_name_map[contract.symbol] = contract.name
+            symbol_size_map[contract.symbol] = contract.size
+
+        if last:
+            self.gateway.write_log("合约信息查询成功")
+
+            for data in self.order_data:
+                self.onRtnOrder(data)
+            self.order_data.clear()
+
+            for data in self.trade_data:
+                self.onRtnTrade(data)
+            self.trade_data.clear()
+
+    def onRtnOrder(self, data: dict):
+        """
+        Callback of order status update.
+        """
+        symbol = data["InstrumentID"]
+        exchange = symbol_exchange_map.get(symbol, "")
+        if not exchange:
+            self.order_data.append(data)
+            return
+
+        frontid = data["FrontID"]
+        sessionid = data["SessionID"]
+        order_ref = data["OrderRef"]
+        orderid = f"{frontid}_{sessionid}_{order_ref}"
+
+        order = OrderData(
+            symbol=symbol,
+            exchange=exchange,
+            orderid=orderid,
+            type=ORDERTYPE_SGIT2VT[data["OrderPriceType"]],
+            direction=DIRECTION_SGIT2VT[data["Direction"]],
+            offset=OFFSET_SGIT2VT[data["CombOffsetFlag"]],
+            price=data["LimitPrice"],
+            volume=data["VolumeTotalOriginal"],
+            traded=data["VolumeTraded"],
+            status=STATUS_SGIT2VT[data["OrderStatus"]],
+            time=data["InsertTime"],
+            gateway_name=self.gateway_name
+        )
+        self.gateway.on_order(order)
+
+        self.sysid_orderid_map[data["OrderSysID"]] = orderid
+
+    def onRtnTrade(self, data: dict):
+        """
+        Callback of trade status update.
+        """
+        symbol = data["InstrumentID"]
+        exchange = symbol_exchange_map.get(symbol, "")
+        if not exchange:
+            self.trade_data.append(data)
+            return
+
+        orderid = self.sysid_orderid_map[data["OrderSysID"]]
+
+        trade = TradeData(
+            symbol=symbol,
+            exchange=exchange,
+            orderid=orderid,
+            tradeid=data["TradeID"],
+            direction=DIRECTION_SGIT2VT[data["Direction"]],
+            offset=OFFSET_SGIT2VT[data["OffsetFlag"]],
+            price=data["Price"],
+            volume=data["Volume"],
+            time=data["TradeTime"],
+            gateway_name=self.gateway_name
+        )
+        self.gateway.on_trade(trade)
+
+    def connect(
+        self,
+        address: str,
+        userid: str,
+        password: str,
+        brokerid: int,
+        auth_code: str,
+        appid: str,
+        product_info
+    ):
+        """
+        Start connection to server.
+        """
+        self.userid = userid
+        self.password = password
+        self.brokerid = brokerid
+        self.auth_code = auth_code
+        self.appid = appid
+        self.product_info = product_info
+
+        if not self.connect_status:
+            path = get_folder_path(self.gateway_name.lower())
+            self.createFtdcTraderApi(str(path) + "\\Td")
+
+            self.subscribePrivateTopic(0)
+            self.subscribePublicTopic(0)
+
+            self.registerFront(address)
+            self.init()
+
+            self.connect_status = True
+        else:
+            self.authenticate()
+
+    def authenticate(self):
+        """
+        Authenticate with auth_code and appid.
+        """
+        req = {
+            "UserID": self.userid,
+            "BrokerID": self.brokerid,
+            "AuthCode": self.auth_code,
+            "AppID": self.appid
+        }
+
+        if self.product_info:
+            req["UserProductInfo"] = self.product_info
+
+        self.reqid += 1
+        self.reqAuthenticate(req, self.reqid)
+
+    def login(self):
+        """
+        Login onto server.
+        """
+        if self.login_failed:
+            return
+
+        req = {
+            "UserID": self.userid,
+            "Password": self.password,
+            "BrokerID": self.brokerid,
+            "AppID": self.appid
+        }
+
+        if self.product_info:
+            req["UserProductInfo"] = self.product_info
+
+        self.reqid += 1
+        self.reqUserLogin(req, self.reqid)
+
+    def send_order(self, req: OrderRequest) -> str:
+        """
+        Send new order.
+        """
+        if req.offset not in OFFSET_VT2SGIT:
+            self.gateway.write_log("请选择开平方向")
+            return ""
+
+        self.order_ref += 1
+
+        ctp_req = {
+            "InstrumentID": req.symbol,
+            "ExchangeID": req.exchange.value,
+            "LimitPrice": req.price,
+            "VolumeTotalOriginal": int(req.volume),
+            "OrderPriceType": ORDERTYPE_VT2SGIT.get(req.type, ""),
+            "Direction": DIRECTION_VT2SGIT.get(req.direction, ""),
+            "CombOffsetFlag": OFFSET_VT2SGIT.get(req.offset, ""),
+            "OrderRef": str(self.order_ref),
+            "InvestorID": self.userid,
+            "UserID": self.userid,
+            "BrokerID": self.brokerid,
+            "CombHedgeFlag": THOST_FTDC_HF_Speculation,
+            "ContingentCondition": THOST_FTDC_CC_Immediately,
+            "ForceCloseReason": THOST_FTDC_FCC_NotForceClose,
+            "IsAutoSuspend": 0,
+            "TimeCondition": THOST_FTDC_TC_GFD,
+            "VolumeCondition": THOST_FTDC_VC_AV,
+            "MinVolume": 1
+        }
+
+        if req.type == OrderType.FAK:
+            ctp_req["OrderPriceType"] = THOST_FTDC_OPT_LimitPrice
+            ctp_req["TimeCondition"] = THOST_FTDC_TC_IOC
+            ctp_req["VolumeCondition"] = THOST_FTDC_VC_AV
+        elif req.type == OrderType.FOK:
+            ctp_req["OrderPriceType"] = THOST_FTDC_OPT_LimitPrice
+            ctp_req["TimeCondition"] = THOST_FTDC_TC_IOC
+            ctp_req["VolumeCondition"] = THOST_FTDC_VC_CV
+
+        self.reqid += 1
+        self.reqOrderInsert(ctp_req, self.reqid)
+
+        orderid = f"{self.frontid}_{self.sessionid}_{self.order_ref}"
+        order = req.create_order_data(orderid, self.gateway_name)
+        self.gateway.on_order(order)
+
+        return order.vt_orderid
+
+    def cancel_order(self, req: CancelRequest):
+        """
+        Cancel existing order.
+        """
+        frontid, sessionid, order_ref = req.orderid.split("_")
+
+        ctp_req = {
+            "InstrumentID": req.symbol,
+            "ExchangeID": req.exchange.value,
+            "OrderRef": order_ref,
+            "FrontID": int(frontid),
+            "SessionID": int(sessionid),
+            "ActionFlag": THOST_FTDC_AF_Delete,
+            "BrokerID": self.brokerid,
+            "InvestorID": self.userid
+        }
+
+        self.reqid += 1
+        self.reqOrderAction(ctp_req, self.reqid)
+
+    def query_account(self):
+        """
+        Query account balance data.
+        """
+        self.reqid += 1
+        self.reqQryTradingAccount({}, self.reqid)
+
+    def query_position(self):
+        """
+        Query position holding data.
+        """
+        if not symbol_exchange_map:
+            return
+
+        req = {
+            "BrokerID": self.brokerid,
+            "InvestorID": self.userid
+        }
+
+        self.reqid += 1
+        self.reqQryInvestorPosition(req, self.reqid)
+
+    def close(self):
+        """"""
+        if self.connect_status:
+            self.exit()
+
+
+def adjust_price(price: float) -> float:
+    """"""
+    if price == MAX_FLOAT:
+        price = 0
+    return price

{'commit': 'diff --git a/vnpy/api/sgit/libcrypto.so b/vnpy/api/sgit/libcrypto.so\nnew file mode 100644\nindex 00000000..7c8790a2\nBinary files /dev/null and b/vnpy/api/sgit/libcrypto.so differ\ndiff --git a/vnpy/api/sgit/libsgitquotapi.so b/vnpy/api/sgit/libsgitquotapi.so\nnew file mode 100644\nindex 00000000..4d2e5457\nBinary files /dev/null and b/vnpy/api/sgit/libsgitquotapi.so differ\ndiff --git a/vnpy/api/sgit/libsgittradeapi.so b/vnpy/api/sgit/libsgittradeapi.so\nnew file mode 100644\nindex 00000000..35bddf68\nBinary files /dev/null and b/vnpy/api/sgit/libsgittradeapi.so differ\ndiff --git a/vnpy/api/sgit/libssl.so b/vnpy/api/sgit/libssl.so\nnew file mode 100644\nindex 00000000..a2357b2d\nBinary files /dev/null and b/vnpy/api/sgit/libssl.so differ\ndiff --git a/vnpy/api/sgit/sgit_constant.py b/vnpy/api/sgit/sgit_constant.py\nnew file mode 100644\nindex 00000000..38239c50\n--- /dev/null\n+++ b/vnpy/api/sgit/sgit_constant.py\n@@ -0,0 +1,1182 @@\n+NULL = 0\n+TRUE = 1\n+FALSE = 0\n+THOST_FTDC_ET_SHFE = "SHFE"\n+THOST_FTDC_ET_CZCE = "CZCE"\n+THOST_FTDC_ET_DCE = "DCE"\n+THOST_FTDC_ET_CFFEX = "CFFEX"\n+THOST_FTDC_ET_INE = "INE"\n+THOST_FTDC_ET_GOLD = "GOLD"\n+THOST_FTDC_ET_PAT = "PAT"\n+THOST_FTDC_ET_LTS = "LTS"\n+THOST_FTDC_ET_CME = "CME"\n+THOST_FTDC_ET_LME = "LME"\n+THOST_FTDC_ET_SGX = "SGX"\n+THOST_FTDC_ET_HKEX = "HKEX"\n+THOST_FTDC_EXP_Normal = \'0\'\n+THOST_FTDC_EXP_GenOrderByTrade = \'1\'\n+THOST_FTDC_ICT_EID = \'0\'\n+THOST_FTDC_ICT_IDCard = \'1\'\n+THOST_FTDC_ICT_OfficerIDCard = \'2\'\n+THOST_FTDC_ICT_PoliceIDCard = \'3\'\n+THOST_FTDC_ICT_SoldierIDCard = \'4\'\n+THOST_FTDC_ICT_HouseholdRegister = \'5\'\n+THOST_FTDC_ICT_Passport = \'6\'\n+THOST_FTDC_ICT_TaiwanCompatriotIDCard = \'7\'\n+THOST_FTDC_ICT_HomeComingCard = \'8\'\n+THOST_FTDC_ICT_LicenseNo = \'9\'\n+THOST_FTDC_ICT_TaxNo = \'A\'\n+THOST_FTDC_ICT_HMMainlandTravelPermit = \'B\'\n+THOST_FTDC_ICT_TwMainlandTravelPermit = \'C\'\n+THOST_FTDC_ICT_DrivingLicense = \'D\'\n+THOST_FTDC_ICT_SocialID = \'F\'\n+THOST_FTDC_ICT_LocalID = \'G\'\n+THOST_FTDC_ICT_BusinessRegistration = \'H\'\n+THOST_FTDC_ICT_HKMCIDCard = \'I\'\n+THOST_FTDC_ICT_AccountsPermits = \'J\'\n+THOST_FTDC_ICT_OtherCard = \'x\'\n+THOST_FTDC_IR_All = \'1\'\n+THOST_FTDC_IR_Group = \'2\'\n+THOST_FTDC_IR_Single = \'3\'\n+THOST_FTDC_DR_All = \'1\'\n+THOST_FTDC_DR_Group = \'2\'\n+THOST_FTDC_DR_Single = \'3\'\n+THOST_FTDC_DS_Asynchronous = \'1\'\n+THOST_FTDC_DS_Synchronizing = \'2\'\n+THOST_FTDC_DS_Synchronized = \'3\'\n+THOST_FTDC_BDS_Synchronized = \'1\'\n+THOST_FTDC_BDS_Synchronizing = \'2\'\n+THOST_FTDC_ECS_NoConnection = \'1\'\n+THOST_FTDC_ECS_QryInstrumentSent = \'2\'\n+THOST_FTDC_ECS_GotInformation = \'9\'\n+THOST_FTDC_TCS_NotConnected = \'1\'\n+THOST_FTDC_TCS_Connected = \'2\'\n+THOST_FTDC_TCS_QryInstrumentSent = \'3\'\n+THOST_FTDC_TCS_SubPrivateFlow = \'4\'\n+THOST_FTDC_FC_DataAsync = \'1\'\n+THOST_FTDC_FC_ForceUserLogout = \'2\'\n+THOST_FTDC_FC_UserPasswordUpdate = \'3\'\n+THOST_FTDC_FC_BrokerPasswordUpdate = \'4\'\n+THOST_FTDC_FC_InvestorPasswordUpdate = \'5\'\n+THOST_FTDC_FC_OrderInsert = \'6\'\n+THOST_FTDC_FC_OrderAction = \'7\'\n+THOST_FTDC_FC_SyncSystemData = \'8\'\n+THOST_FTDC_FC_SyncBrokerData = \'9\'\n+THOST_FTDC_FC_BachSyncBrokerData = \'A\'\n+THOST_FTDC_FC_SuperQuery = \'B\'\n+THOST_FTDC_FC_ParkedOrderInsert = \'C\'\n+THOST_FTDC_FC_ParkedOrderAction = \'D\'\n+THOST_FTDC_FC_SyncOTP = \'E\'\n+THOST_FTDC_FC_DeleteOrder = \'F\'\n+THOST_FTDC_BFC_ForceUserLogout = \'1\'\n+THOST_FTDC_BFC_UserPasswordUpdate = \'2\'\n+THOST_FTDC_BFC_SyncBrokerData = \'3\'\n+THOST_FTDC_BFC_BachSyncBrokerData = \'4\'\n+THOST_FTDC_BFC_OrderInsert = \'5\'\n+THOST_FTDC_BFC_OrderAction = \'6\'\n+THOST_FTDC_BFC_AllQuery = \'7\'\n+THOST_FTDC_BFC_log = \'a\'\n+THOST_FTDC_BFC_BaseQry = \'b\'\n+THOST_FTDC_BFC_TradeQry = \'c\'\n+THOST_FTDC_BFC_Trade = \'d\'\n+THOST_FTDC_BFC_Virement = \'e\'\n+THOST_FTDC_BFC_Risk = \'f\'\n+THOST_FTDC_BFC_Session = \'g\'\n+THOST_FTDC_BFC_RiskNoticeCtl = \'h\'\n+THOST_FTDC_BFC_RiskNotice = \'i\'\n+THOST_FTDC_BFC_BrokerDeposit = \'j\'\n+THOST_FTDC_BFC_QueryFund = \'k\'\n+THOST_FTDC_BFC_QueryOrder = \'l\'\n+THOST_FTDC_BFC_QueryTrade = \'m\'\n+THOST_FTDC_BFC_QueryPosition = \'n\'\n+THOST_FTDC_BFC_QueryMarketData = \'o\'\n+THOST_FTDC_BFC_QueryUserEvent = \'p\'\n+THOST_FTDC_BFC_QueryRiskNotify = \'q\'\n+THOST_FTDC_BFC_QueryFundChange = \'r\'\n+THOST_FTDC_BFC_QueryInvestor = \'s\'\n+THOST_FTDC_BFC_QueryTradingCode = \'t\'\n+THOST_FTDC_BFC_ForceClose = \'u\'\n+THOST_FTDC_BFC_PressTest = \'v\'\n+THOST_FTDC_BFC_RemainCalc = \'w\'\n+THOST_FTDC_BFC_NetPositionInd = \'x\'\n+THOST_FTDC_BFC_RiskPredict = \'y\'\n+THOST_FTDC_BFC_DataExport = \'z\'\n+THOST_FTDC_BFC_RiskTargetSetup = \'A\'\n+THOST_FTDC_BFC_MarketDataWarn = \'B\'\n+THOST_FTDC_BFC_QryBizNotice = \'C\'\n+THOST_FTDC_BFC_CfgBizNotice = \'D\'\n+THOST_FTDC_BFC_SyncOTP = \'E\'\n+THOST_FTDC_BFC_SendBizNotice = \'F\'\n+THOST_FTDC_BFC_CfgRiskLevelStd = \'G\'\n+THOST_FTDC_BFC_TbCommand = \'H\'\n+THOST_FTDC_BFC_DeleteOrder = \'J\'\n+THOST_FTDC_BFC_ParkedOrderInsert = \'K\'\n+THOST_FTDC_BFC_ParkedOrderAction = \'L\'\n+THOST_FTDC_OAS_Submitted = \'a\'\n+THOST_FTDC_OAS_Accepted = \'b\'\n+THOST_FTDC_OAS_Rejected = \'c\'\n+THOST_FTDC_OST_AllTraded = \'0\'\n+THOST_FTDC_OST_PartTradedQueueing = \'1\'\n+THOST_FTDC_OST_PartTradedNotQueueing = \'2\'\n+THOST_FTDC_OST_NoTradeQueueing = \'3\'\n+THOST_FTDC_OST_NoTradeNotQueueing = \'4\'\n+THOST_FTDC_OST_Canceled = \'5\'\n+THOST_FTDC_OST_Unknown = \'a\'\n+THOST_FTDC_OST_NotTouched = \'b\'\n+THOST_FTDC_OST_Touched = \'c\'\n+THOST_FTDC_OSS_InsertSubmitted = \'0\'\n+THOST_FTDC_OSS_CancelSubmitted = \'1\'\n+THOST_FTDC_OSS_ModifySubmitted = \'2\'\n+THOST_FTDC_OSS_Accepted = \'3\'\n+THOST_FTDC_OSS_InsertRejected = \'4\'\n+THOST_FTDC_OSS_CancelRejected = \'5\'\n+THOST_FTDC_OSS_ModifyRejected = \'6\'\n+THOST_FTDC_PSD_Today = \'1\'\n+THOST_FTDC_PSD_History = \'2\'\n+THOST_FTDC_PDT_UseHistory = \'1\'\n+THOST_FTDC_PDT_NoUseHistory = \'2\'\n+THOST_FTDC_ER_Broker = \'1\'\n+THOST_FTDC_ER_Host = \'2\'\n+THOST_FTDC_ER_Maker = \'3\'\n+THOST_FTDC_PC_Futures = \'1\'\n+THOST_FTDC_PC_Options = \'2\'\n+THOST_FTDC_PC_Combination = \'3\'\n+THOST_FTDC_PC_Spot = \'4\'\n+THOST_FTDC_PC_EFP = \'5\'\n+THOST_FTDC_PC_SpotOption = \'6\'\n+THOST_FTDC_PC_Defer = \'7\'\n+THOST_FTDC_IP_NotStart = \'0\'\n+THOST_FTDC_IP_Started = \'1\'\n+THOST_FTDC_IP_Pause = \'2\'\n+THOST_FTDC_IP_Expired = \'3\'\n+THOST_FTDC_D_Buy = \'0\'\n+THOST_FTDC_D_Sell = \'1\'\n+THOST_FTDC_PT_Net = \'1\'\n+THOST_FTDC_PT_Gross = \'2\'\n+THOST_FTDC_PD_Net = \'1\'\n+THOST_FTDC_PD_Long = \'2\'\n+THOST_FTDC_PD_Short = \'3\'\n+THOST_FTDC_SS_NonActive = \'1\'\n+THOST_FTDC_SS_Startup = \'2\'\n+THOST_FTDC_SS_Operating = \'3\'\n+THOST_FTDC_SS_Settlement = \'4\'\n+THOST_FTDC_SS_SettlementFinished = \'5\'\n+THOST_FTDC_RA_Trade = \'0\'\n+THOST_FTDC_RA_Settlement = \'1\'\n+THOST_FTDC_HF_Speculation = \'1\'\n+THOST_FTDC_HF_Arbitrage = \'2\'\n+THOST_FTDC_HF_Hedge = \'3\'\n+THOST_FTDC_HF_DEFER = \'4\'\n+THOST_FTDC_HF_MID = \'5\'\n+THOST_FTDC_BHF_Speculation = \'1\'\n+THOST_FTDC_BHF_Arbitrage = \'2\'\n+THOST_FTDC_BHF_Hedge = \'3\'\n+THOST_FTDC_CIDT_Speculation = \'1\'\n+THOST_FTDC_CIDT_Arbitrage = \'2\'\n+THOST_FTDC_CIDT_Hedge = \'3\'\n+THOST_FTDC_OPT_AnyPrice = \'1\'\n+THOST_FTDC_OPT_LimitPrice = \'2\'\n+THOST_FTDC_OPT_BestPrice = \'3\'\n+THOST_FTDC_OPT_LastPrice = \'4\'\n+THOST_FTDC_OPT_LastPricePlusOneTicks = \'5\'\n+THOST_FTDC_OPT_LastPricePlusTwoTicks = \'6\'\n+THOST_FTDC_OPT_LastPricePlusThreeTicks = \'7\'\n+THOST_FTDC_OPT_AskPrice1 = \'8\'\n+THOST_FTDC_OPT_AskPrice1PlusOneTicks = \'9\'\n+THOST_FTDC_OPT_AskPrice1PlusTwoTicks = \'A\'\n+THOST_FTDC_OPT_AskPrice1PlusThreeTicks = \'B\'\n+THOST_FTDC_OPT_BidPrice1 = \'C\'\n+THOST_FTDC_OPT_BidPrice1PlusOneTicks = \'D\'\n+THOST_FTDC_OPT_BidPrice1PlusTwoTicks = \'E\'\n+THOST_FTDC_OPT_BidPrice1PlusThreeTicks = \'F\'\n+THOST_FTDC_OPT_FiveLevelPrice = \'G\'\n+THOST_FTDC_OF_Open = \'0\'\n+THOST_FTDC_OF_Close = \'1\'\n+THOST_FTDC_OF_ForceClose = \'2\'\n+THOST_FTDC_OF_CloseToday = \'3\'\n+THOST_FTDC_OF_CloseYesterday = \'4\'\n+THOST_FTDC_OF_ForceOff = \'5\'\n+THOST_FTDC_OF_LocalForceClose = \'6\'\n+THOST_FTDC_FCC_NotForceClose = \'0\'\n+THOST_FTDC_FCC_LackDeposit = \'1\'\n+THOST_FTDC_FCC_ClientOverPositionLimit = \'2\'\n+THOST_FTDC_FCC_MemberOverPositionLimit = \'3\'\n+THOST_FTDC_FCC_NotMultiple = \'4\'\n+THOST_FTDC_FCC_Violation = \'5\'\n+THOST_FTDC_FCC_Other = \'6\'\n+THOST_FTDC_FCC_PersonDeliv = \'7\'\n+THOST_FTDC_ORDT_Normal = \'0\'\n+THOST_FTDC_ORDT_DeriveFromQuote = \'1\'\n+THOST_FTDC_ORDT_DeriveFromCombination = \'2\'\n+THOST_FTDC_ORDT_Combination = \'3\'\n+THOST_FTDC_ORDT_ConditionalOrder = \'4\'\n+THOST_FTDC_ORDT_Swap = \'5\'\n+THOST_FTDC_TC_IOC = \'1\'\n+THOST_FTDC_TC_GFS = \'2\'\n+THOST_FTDC_TC_GFD = \'3\'\n+THOST_FTDC_TC_GTD = \'4\'\n+THOST_FTDC_TC_GTC = \'5\'\n+THOST_FTDC_TC_GFA = \'6\'\n+THOST_FTDC_VC_AV = \'1\'\n+THOST_FTDC_VC_MV = \'2\'\n+THOST_FTDC_VC_CV = \'3\'\n+THOST_FTDC_CC_Immediately = \'1\'\n+THOST_FTDC_CC_Touch = \'2\'\n+THOST_FTDC_CC_TouchProfit = \'3\'\n+THOST_FTDC_CC_ParkedOrder = \'4\'\n+THOST_FTDC_CC_LastPriceGreaterThanStopPrice = \'5\'\n+THOST_FTDC_CC_LastPriceGreaterEqualStopPrice = \'6\'\n+THOST_FTDC_CC_LastPriceLesserThanStopPrice = \'7\'\n+THOST_FTDC_CC_LastPriceLesserEqualStopPrice = \'8\'\n+THOST_FTDC_CC_AskPriceGreaterThanStopPrice = \'9\'\n+THOST_FTDC_CC_AskPriceGreaterEqualStopPrice = \'A\'\n+THOST_FTDC_CC_AskPriceLesserThanStopPrice = \'B\'\n+THOST_FTDC_CC_AskPriceLesserEqualStopPrice = \'C\'\n+THOST_FTDC_CC_BidPriceGreaterThanStopPrice = \'D\'\n+THOST_FTDC_CC_BidPriceGreaterEqualStopPrice = \'E\'\n+THOST_FTDC_CC_BidPriceLesserThanStopPrice = \'F\'\n+THOST_FTDC_CC_BidPriceLesserEqualStopPrice = \'H\'\n+THOST_FTDC_AF_Delete = \'0\'\n+THOST_FTDC_AF_Modify = \'3\'\n+THOST_FTDC_TR_Allow = \'0\'\n+THOST_FTDC_TR_CloseOnly = \'1\'\n+THOST_FTDC_TR_Forbidden = \'2\'\n+THOST_FTDC_OSRC_Participant = \'0\'\n+THOST_FTDC_OSRC_Administrator = \'1\'\n+THOST_FTDC_TRDT_SplitCombination = \'#\'\n+THOST_FTDC_TRDT_Common = \'0\'\n+THOST_FTDC_TRDT_OptionsExecution = \'1\'\n+THOST_FTDC_TRDT_OTC = \'2\'\n+THOST_FTDC_TRDT_EFPDerived = \'3\'\n+THOST_FTDC_TRDT_CombinationDerived = \'4\'\n+THOST_FTDC_PSRC_LastPrice = \'0\'\n+THOST_FTDC_PSRC_Buy = \'1\'\n+THOST_FTDC_PSRC_Sell = \'2\'\n+THOST_FTDC_IS_BeforeTrading = \'0\'\n+THOST_FTDC_IS_NoTrading = \'1\'\n+THOST_FTDC_IS_Continous = \'2\'\n+THOST_FTDC_IS_AuctionOrdering = \'3\'\n+THOST_FTDC_IS_AuctionBalance = \'4\'\n+THOST_FTDC_IS_AuctionMatch = \'5\'\n+THOST_FTDC_IS_Closed = \'6\'\n+THOST_FTDC_IER_Automatic = \'1\'\n+THOST_FTDC_IER_Manual = \'2\'\n+THOST_FTDC_IER_Fuse = \'3\'\n+THOST_FTDC_BS_NoUpload = \'1\'\n+THOST_FTDC_BS_Uploaded = \'2\'\n+THOST_FTDC_BS_Failed = \'3\'\n+THOST_FTDC_RS_All = \'1\'\n+THOST_FTDC_RS_ByProduct = \'2\'\n+THOST_FTDC_RP_ByVolume = \'1\'\n+THOST_FTDC_RP_ByFeeOnHand = \'2\'\n+THOST_FTDC_RL_Level1 = \'1\'\n+THOST_FTDC_RL_Level2 = \'2\'\n+THOST_FTDC_RL_Level3 = \'3\'\n+THOST_FTDC_RL_Level4 = \'4\'\n+THOST_FTDC_RL_Level5 = \'5\'\n+THOST_FTDC_RL_Level6 = \'6\'\n+THOST_FTDC_RL_Level7 = \'7\'\n+THOST_FTDC_RL_Level8 = \'8\'\n+THOST_FTDC_RL_Level9 = \'9\'\n+THOST_FTDC_RSD_ByPeriod = \'1\'\n+THOST_FTDC_RSD_ByStandard = \'2\'\n+THOST_FTDC_MT_Out = \'0\'\n+THOST_FTDC_MT_In = \'1\'\n+THOST_FTDC_ISPI_BaseMargin = \'1\'\n+THOST_FTDC_ISPI_LowestInterest = \'2\'\n+THOST_FTDC_ISPI_MortgageRatio = \'4\'\n+THOST_FTDC_ISPI_MarginWay = \'5\'\n+THOST_FTDC_ISPI_BillDeposit = \'9\'\n+THOST_FTDC_ESPI_MortgageRatio = \'1\'\n+THOST_FTDC_ESPI_OtherFundItem = \'2\'\n+THOST_FTDC_ESPI_OtherFundImport = \'3\'\n+THOST_FTDC_ESPI_SHFEDelivFee = \'4\'\n+THOST_FTDC_ESPI_DCEDelivFee = \'5\'\n+THOST_FTDC_ESPI_CFFEXMinPrepa = \'6\'\n+THOST_FTDC_ESPI_CZCESettlementType = \'7\'\n+THOST_FTDC_ESPI_ExchDelivFeeMode = \'9\'\n+THOST_FTDC_ESPI_DelivFeeMode = \'0\'\n+THOST_FTDC_ESPI_CZCEComMarginType = \'A\'\n+THOST_FTDC_ESPI_DceComMarginType = \'B\'\n+THOST_FTDC_ESPI_OptOutDisCountRate = \'a\'\n+THOST_FTDC_ESPI_OptMiniGuarantee = \'b\'\n+THOST_FTDC_SPI_InvestorIDMinLength = \'1\'\n+THOST_FTDC_SPI_AccountIDMinLength = \'2\'\n+THOST_FTDC_SPI_UserRightLogon = \'3\'\n+THOST_FTDC_SPI_SettlementBillTrade = \'4\'\n+THOST_FTDC_SPI_TradingCode = \'5\'\n+THOST_FTDC_SPI_CheckFund = \'6\'\n+THOST_FTDC_SPI_CommModelRight = \'7\'\n+THOST_FTDC_SPI_MarginModelRight = \'9\'\n+THOST_FTDC_SPI_IsStandardActive = \'8\'\n+THOST_FTDC_SPI_UploadSettlementFile = \'U\'\n+THOST_FTDC_SPI_DownloadCSRCFile = \'D\'\n+THOST_FTDC_SPI_SettlementBillFile = \'S\'\n+THOST_FTDC_SPI_CSRCOthersFile = \'C\'\n+THOST_FTDC_SPI_InvestorPhoto = \'P\'\n+THOST_FTDC_SPI_CSRCData = \'R\'\n+THOST_FTDC_SPI_InvestorPwdModel = \'I\'\n+THOST_FTDC_SPI_CFFEXInvestorSettleFile = \'F\'\n+THOST_FTDC_SPI_InvestorIDType = \'a\'\n+THOST_FTDC_SPI_FreezeMaxReMain = \'r\'\n+THOST_FTDC_SPI_IsSync = \'A\'\n+THOST_FTDC_SPI_RelieveOpenLimit = \'O\'\n+THOST_FTDC_SPI_IsStandardFreeze = \'X\'\n+THOST_FTDC_SPI_CZCENormalProductHedge = \'B\'\n+THOST_FTDC_TPID_EncryptionStandard = \'E\'\n+THOST_FTDC_TPID_RiskMode = \'R\'\n+THOST_FTDC_TPID_RiskModeGlobal = \'G\'\n+THOST_FTDC_TPID_modeEncode = \'P\'\n+THOST_FTDC_TPID_tickMode = \'T\'\n+THOST_FTDC_TPID_SingleUserSessionMaxNum = \'S\'\n+THOST_FTDC_TPID_LoginFailMaxNum = \'L\'\n+THOST_FTDC_TPID_IsAuthForce = \'A\'\n+THOST_FTDC_TPID_IsPosiFreeze = \'F\'\n+THOST_FTDC_TPID_IsPosiLimit = \'M\'\n+THOST_FTDC_TPID_ForQuoteTimeInterval = \'Q\'\n+THOST_FTDC_FI_SettlementFund = \'F\'\n+THOST_FTDC_FI_Trade = \'T\'\n+THOST_FTDC_FI_InvestorPosition = \'P\'\n+THOST_FTDC_FI_SubEntryFund = \'O\'\n+THOST_FTDC_FI_CZCECombinationPos = \'C\'\n+THOST_FTDC_FI_CSRCData = \'R\'\n+THOST_FTDC_FI_CZCEClose = \'L\'\n+THOST_FTDC_FI_CZCENoClose = \'N\'\n+THOST_FTDC_FI_PositionDtl = \'D\'\n+THOST_FTDC_FI_OptionStrike = \'S\'\n+THOST_FTDC_FI_SettlementPriceComparison = \'M\'\n+THOST_FTDC_FI_NonTradePosChange = \'B\'\n+THOST_FTDC_FUT_Settlement = \'0\'\n+THOST_FTDC_FUT_Check = \'1\'\n+THOST_FTDC_FFT_Txt = \'0\'\n+THOST_FTDC_FFT_Zip = \'1\'\n+THOST_FTDC_FFT_DBF = \'2\'\n+THOST_FTDC_FUS_SucceedUpload = \'1\'\n+THOST_FTDC_FUS_FailedUpload = \'2\'\n+THOST_FTDC_FUS_SucceedLoad = \'3\'\n+THOST_FTDC_FUS_PartSucceedLoad = \'4\'\n+THOST_FTDC_FUS_FailedLoad = \'5\'\n+THOST_FTDC_TD_Out = \'0\'\n+THOST_FTDC_TD_In = \'1\'\n+THOST_FTDC_SC_NoSpecialRule = \'0\'\n+THOST_FTDC_SC_NoSpringFestival = \'1\'\n+THOST_FTDC_IPT_LastSettlement = \'1\'\n+THOST_FTDC_IPT_LaseClose = \'2\'\n+THOST_FTDC_PLP_Active = \'1\'\n+THOST_FTDC_PLP_NonActive = \'2\'\n+THOST_FTDC_PLP_Canceled = \'3\'\n+THOST_FTDC_DM_CashDeliv = \'1\'\n+THOST_FTDC_DM_CommodityDeliv = \'2\'\n+THOST_FTDC_FIOT_FundIO = \'1\'\n+THOST_FTDC_FIOT_Transfer = \'2\'\n+THOST_FTDC_FIOT_SwapCurrency = \'3\'\n+THOST_FTDC_FT_Deposite = \'1\'\n+THOST_FTDC_FT_ItemFund = \'2\'\n+THOST_FTDC_FT_Company = \'3\'\n+THOST_FTDC_FT_InnerTransfer = \'4\'\n+THOST_FTDC_FD_In = \'1\'\n+THOST_FTDC_FD_Out = \'2\'\n+THOST_FTDC_FS_Record = \'1\'\n+THOST_FTDC_FS_Check = \'2\'\n+THOST_FTDC_FS_Charge = \'3\'\n+THOST_FTDC_PS_None = \'1\'\n+THOST_FTDC_PS_Publishing = \'2\'\n+THOST_FTDC_PS_Published = \'3\'\n+THOST_FTDC_ES_NonActive = \'1\'\n+THOST_FTDC_ES_Startup = \'2\'\n+THOST_FTDC_ES_Initialize = \'3\'\n+THOST_FTDC_ES_Initialized = \'4\'\n+THOST_FTDC_ES_Close = \'5\'\n+THOST_FTDC_ES_Closed = \'6\'\n+THOST_FTDC_ES_Settlement = \'7\'\n+THOST_FTDC_STS_Initialize = \'0\'\n+THOST_FTDC_STS_Settlementing = \'1\'\n+THOST_FTDC_STS_Settlemented = \'2\'\n+THOST_FTDC_STS_Finished = \'3\'\n+THOST_FTDC_CT_Person = \'0\'\n+THOST_FTDC_CT_Company = \'1\'\n+THOST_FTDC_CT_Fund = \'2\'\n+THOST_FTDC_CT_SpecialOrgan = \'3\'\n+THOST_FTDC_CT_Asset = \'4\'\n+THOST_FTDC_BT_Trade = \'0\'\n+THOST_FTDC_BT_TradeSettle = \'1\'\n+THOST_FTDC_FAS_Low = \'1\'\n+THOST_FTDC_FAS_Normal = \'2\'\n+THOST_FTDC_FAS_Focus = \'3\'\n+THOST_FTDC_FAS_Risk = \'4\'\n+THOST_FTDC_FAS_ByTrade = \'1\'\n+THOST_FTDC_FAS_ByDeliv = \'2\'\n+THOST_FTDC_FAS_None = \'3\'\n+THOST_FTDC_FAS_FixFee = \'4\'\n+THOST_FTDC_PWDT_Trade = \'1\'\n+THOST_FTDC_PWDT_Account = \'2\'\n+THOST_FTDC_AG_All = \'1\'\n+THOST_FTDC_AG_OnlyLost = \'2\'\n+THOST_FTDC_AG_OnlyGain = \'3\'\n+THOST_FTDC_AG_None = \'4\'\n+THOST_FTDC_ICP_Include = \'0\'\n+THOST_FTDC_ICP_NotInclude = \'2\'\n+THOST_FTDC_AWT_Enable = \'0\'\n+THOST_FTDC_AWT_Disable = \'2\'\n+THOST_FTDC_AWT_NoHoldEnable = \'3\'\n+THOST_FTDC_FPWD_UnCheck = \'0\'\n+THOST_FTDC_FPWD_Check = \'1\'\n+THOST_FTDC_TT_BankToFuture = \'0\'\n+THOST_FTDC_TT_FutureToBank = \'1\'\n+THOST_FTDC_TVF_Invalid = \'0\'\n+THOST_FTDC_TVF_Valid = \'1\'\n+THOST_FTDC_TVF_Reverse = \'2\'\n+THOST_FTDC_RN_CD = \'0\'\n+THOST_FTDC_RN_ZT = \'1\'\n+THOST_FTDC_RN_QT = \'2\'\n+THOST_FTDC_SEX_None = \'0\'\n+THOST_FTDC_SEX_Man = \'1\'\n+THOST_FTDC_SEX_Woman = \'2\'\n+THOST_FTDC_UT_Investor = \'0\'\n+THOST_FTDC_UT_Operator = \'1\'\n+THOST_FTDC_UT_SuperUser = \'2\'\n+THOST_FTDC_RATETYPE_MarginRate = \'2\'\n+THOST_FTDC_NOTETYPE_TradeSettleBill = \'1\'\n+THOST_FTDC_NOTETYPE_TradeSettleMonth = \'2\'\n+THOST_FTDC_NOTETYPE_CallMarginNotes = \'3\'\n+THOST_FTDC_NOTETYPE_ForceCloseNotes = \'4\'\n+THOST_FTDC_NOTETYPE_TradeNotes = \'5\'\n+THOST_FTDC_NOTETYPE_DelivNotes = \'6\'\n+THOST_FTDC_SBS_Day = \'1\'\n+THOST_FTDC_SBS_Volume = \'2\'\n+THOST_FTDC_ST_Day = \'0\'\n+THOST_FTDC_ST_Month = \'1\'\n+THOST_FTDC_URT_Logon = \'1\'\n+THOST_FTDC_URT_Transfer = \'2\'\n+THOST_FTDC_URT_EMail = \'3\'\n+THOST_FTDC_URT_Fax = \'4\'\n+THOST_FTDC_URT_ConditionOrder = \'5\'\n+THOST_FTDC_MPT_PreSettlementPrice = \'1\'\n+THOST_FTDC_MPT_SettlementPrice = \'2\'\n+THOST_FTDC_MPT_AveragePrice = \'3\'\n+THOST_FTDC_MPT_OpenPrice = \'4\'\n+THOST_FTDC_BGS_None = \'0\'\n+THOST_FTDC_BGS_NoGenerated = \'1\'\n+THOST_FTDC_BGS_Generated = \'2\'\n+THOST_FTDC_AT_HandlePositionAlgo = \'1\'\n+THOST_FTDC_AT_FindMarginRateAlgo = \'2\'\n+THOST_FTDC_HPA_Base = \'1\'\n+THOST_FTDC_HPA_DCE = \'2\'\n+THOST_FTDC_HPA_CZCE = \'3\'\n+THOST_FTDC_FMRA_Base = \'1\'\n+THOST_FTDC_FMRA_DCE = \'2\'\n+THOST_FTDC_FMRA_CZCE = \'3\'\n+THOST_FTDC_HTAA_Base = \'1\'\n+THOST_FTDC_HTAA_DCE = \'2\'\n+THOST_FTDC_HTAA_CZCE = \'3\'\n+THOST_FTDC_PST_Order = \'1\'\n+THOST_FTDC_PST_Open = \'2\'\n+THOST_FTDC_PST_Fund = \'3\'\n+THOST_FTDC_PST_Settlement = \'4\'\n+THOST_FTDC_PST_Company = \'5\'\n+THOST_FTDC_PST_Corporation = \'6\'\n+THOST_FTDC_PST_LinkMan = \'7\'\n+THOST_FTDC_PST_Ledger = \'8\'\n+THOST_FTDC_PST_Trustee = \'9\'\n+THOST_FTDC_PST_TrusteeCorporation = \'A\'\n+THOST_FTDC_PST_TrusteeOpen = \'B\'\n+THOST_FTDC_PST_TrusteeContact = \'C\'\n+THOST_FTDC_PST_ForeignerRefer = \'D\'\n+THOST_FTDC_PST_CorporationRefer = \'E\'\n+THOST_FTDC_QIR_All = \'1\'\n+THOST_FTDC_QIR_Group = \'2\'\n+THOST_FTDC_QIR_Single = \'3\'\n+THOST_FTDC_IRS_Normal = \'1\'\n+THOST_FTDC_IRS_Warn = \'2\'\n+THOST_FTDC_IRS_Call = \'3\'\n+THOST_FTDC_IRS_Force = \'4\'\n+THOST_FTDC_IRS_Exception = \'5\'\n+THOST_FTDC_UET_Login = \'1\'\n+THOST_FTDC_UET_Logout = \'2\'\n+THOST_FTDC_UET_Trading = \'3\'\n+THOST_FTDC_UET_TradingError = \'4\'\n+THOST_FTDC_UET_UpdatePassword = \'5\'\n+THOST_FTDC_UET_Authenticate = \'6\'\n+THOST_FTDC_UET_Other = \'9\'\n+THOST_FTDC_ICS_Close = \'0\'\n+THOST_FTDC_ICS_CloseToday = \'1\'\n+THOST_FTDC_SM_Non = \'0\'\n+THOST_FTDC_SM_Instrument = \'1\'\n+THOST_FTDC_SM_Product = \'2\'\n+THOST_FTDC_SM_Investor = \'3\'\n+THOST_FTDC_PAOS_NotSend = \'1\'\n+THOST_FTDC_PAOS_Send = \'2\'\n+THOST_FTDC_PAOS_Deleted = \'3\'\n+THOST_FTDC_VDS_Dealing = \'1\'\n+THOST_FTDC_VDS_DeaclSucceed = \'2\'\n+THOST_FTDC_ORGS_Standard = \'0\'\n+THOST_FTDC_ORGS_ESunny = \'1\'\n+THOST_FTDC_ORGS_KingStarV6 = \'2\'\n+THOST_FTDC_VTS_NaturalDeal = \'0\'\n+THOST_FTDC_VTS_SucceedEnd = \'1\'\n+THOST_FTDC_VTS_FailedEND = \'2\'\n+THOST_FTDC_VTS_Exception = \'3\'\n+THOST_FTDC_VTS_ManualDeal = \'4\'\n+THOST_FTDC_VTS_MesException = \'5\'\n+THOST_FTDC_VTS_SysException = \'6\'\n+THOST_FTDC_VBAT_BankBook = \'1\'\n+THOST_FTDC_VBAT_BankCard = \'2\'\n+THOST_FTDC_VBAT_CreditCard = \'3\'\n+THOST_FTDC_VMS_Natural = \'0\'\n+THOST_FTDC_VMS_Canceled = \'9\'\n+THOST_FTDC_VAA_NoAvailAbility = \'0\'\n+THOST_FTDC_VAA_AvailAbility = \'1\'\n+THOST_FTDC_VAA_Repeal = \'2\'\n+THOST_FTDC_VTC_BankBankToFuture = \'102001\'\n+THOST_FTDC_VTC_BankFutureToBank = \'102002\'\n+THOST_FTDC_VTC_FutureBankToFuture = \'202001\'\n+THOST_FTDC_VTC_FutureFutureToBank = \'202002\'\n+THOST_FTDC_GEN_Program = \'0\'\n+THOST_FTDC_GEN_HandWork = \'1\'\n+THOST_FTDC_CFMMCKK_REQUEST = \'R\'\n+THOST_FTDC_CFMMCKK_AUTO = \'A\'\n+THOST_FTDC_CFMMCKK_MANUAL = \'M\'\n+THOST_FTDC_CFT_IDCard = \'0\'\n+THOST_FTDC_CFT_Passport = \'1\'\n+THOST_FTDC_CFT_OfficerIDCard = \'2\'\n+THOST_FTDC_CFT_SoldierIDCard = \'3\'\n+THOST_FTDC_CFT_HomeComingCard = \'4\'\n+THOST_FTDC_CFT_HouseholdRegister = \'5\'\n+THOST_FTDC_CFT_LicenseNo = \'6\'\n+THOST_FTDC_CFT_InstitutionCodeCard = \'7\'\n+THOST_FTDC_CFT_TempLicenseNo = \'8\'\n+THOST_FTDC_CFT_NoEnterpriseLicenseNo = \'9\'\n+THOST_FTDC_CFT_OtherCard = \'x\'\n+THOST_FTDC_CFT_SuperDepAgree = \'a\'\n+THOST_FTDC_FBC_Others = \'0\'\n+THOST_FTDC_FBC_TransferDetails = \'1\'\n+THOST_FTDC_FBC_CustAccStatus = \'2\'\n+THOST_FTDC_FBC_AccountTradeDetails = \'3\'\n+THOST_FTDC_FBC_FutureAccountChangeInfoDetails = \'4\'\n+THOST_FTDC_FBC_CustMoneyDetail = \'5\'\n+THOST_FTDC_FBC_CustCancelAccountInfo = \'6\'\n+THOST_FTDC_FBC_CustMoneyResult = \'7\'\n+THOST_FTDC_FBC_OthersExceptionResult = \'8\'\n+THOST_FTDC_FBC_CustInterestNetMoneyDetails = \'9\'\n+THOST_FTDC_FBC_CustMoneySendAndReceiveDetails = \'a\'\n+THOST_FTDC_FBC_CorporationMoneyTotal = \'b\'\n+THOST_FTDC_FBC_MainbodyMoneyTotal = \'c\'\n+THOST_FTDC_FBC_MainPartMonitorData = \'d\'\n+THOST_FTDC_FBC_PreparationMoney = \'e\'\n+THOST_FTDC_FBC_BankMoneyMonitorData = \'f\'\n+THOST_FTDC_CEC_Exchange = \'1\'\n+THOST_FTDC_CEC_Cash = \'2\'\n+THOST_FTDC_YNI_Yes = \'0\'\n+THOST_FTDC_YNI_No = \'1\'\n+THOST_FTDC_BLT_CurrentMoney = \'0\'\n+THOST_FTDC_BLT_UsableMoney = \'1\'\n+THOST_FTDC_BLT_FetchableMoney = \'2\'\n+THOST_FTDC_BLT_FreezeMoney = \'3\'\n+THOST_FTDC_GD_Unknown = \'0\'\n+THOST_FTDC_GD_Male = \'1\'\n+THOST_FTDC_GD_Female = \'2\'\n+THOST_FTDC_FPF_BEN = \'0\'\n+THOST_FTDC_FPF_OUR = \'1\'\n+THOST_FTDC_FPF_SHA = \'2\'\n+THOST_FTDC_PWKT_ExchangeKey = \'0\'\n+THOST_FTDC_PWKT_PassWordKey = \'1\'\n+THOST_FTDC_PWKT_MACKey = \'2\'\n+THOST_FTDC_PWKT_MessageKey = \'3\'\n+THOST_FTDC_PWT_Query = \'0\'\n+THOST_FTDC_PWT_Fetch = \'1\'\n+THOST_FTDC_PWT_Transfer = \'2\'\n+THOST_FTDC_PWT_Trade = \'3\'\n+THOST_FTDC_EM_NoEncry = \'0\'\n+THOST_FTDC_EM_DES = \'1\'\n+THOST_FTDC_EM_3DES = \'2\'\n+THOST_FTDC_BRF_BankNotNeedRepeal = \'0\'\n+THOST_FTDC_BRF_BankWaitingRepeal = \'1\'\n+THOST_FTDC_BRF_BankBeenRepealed = \'2\'\n+THOST_FTDC_BRORF_BrokerNotNeedRepeal = \'0\'\n+THOST_FTDC_BRORF_BrokerWaitingRepeal = \'1\'\n+THOST_FTDC_BRORF_BrokerBeenRepealed = \'2\'\n+THOST_FTDC_TS_Bank = \'0\'\n+THOST_FTDC_TS_Future = \'1\'\n+THOST_FTDC_TS_Store = \'2\'\n+THOST_FTDC_LF_Yes = \'0\'\n+THOST_FTDC_LF_No = \'1\'\n+THOST_FTDC_BAS_Normal = \'0\'\n+THOST_FTDC_BAS_Freeze = \'1\'\n+THOST_FTDC_BAS_ReportLoss = \'2\'\n+THOST_FTDC_MAS_Normal = \'0\'\n+THOST_FTDC_MAS_Cancel = \'1\'\n+THOST_FTDC_MSS_Point = \'0\'\n+THOST_FTDC_MSS_PrePoint = \'1\'\n+THOST_FTDC_MSS_CancelPoint = \'2\'\n+THOST_FTDC_SYT_FutureBankTransfer = \'0\'\n+THOST_FTDC_SYT_StockBankTransfer = \'1\'\n+THOST_FTDC_SYT_TheThirdPartStore = \'2\'\n+THOST_FTDC_TEF_NormalProcessing = \'0\'\n+THOST_FTDC_TEF_Success = \'1\'\n+THOST_FTDC_TEF_Failed = \'2\'\n+THOST_FTDC_TEF_Abnormal = \'3\'\n+THOST_FTDC_TEF_ManualProcessedForException = \'4\'\n+THOST_FTDC_TEF_CommuFailedNeedManualProcess = \'5\'\n+THOST_FTDC_TEF_SysErrorNeedManualProcess = \'6\'\n+THOST_FTDC_PSS_NotProcess = \'0\'\n+THOST_FTDC_PSS_StartProcess = \'1\'\n+THOST_FTDC_PSS_Finished = \'2\'\n+THOST_FTDC_CUSTT_Person = \'0\'\n+THOST_FTDC_CUSTT_Institution = \'1\'\n+THOST_FTDC_FBTTD_FromBankToFuture = \'1\'\n+THOST_FTDC_FBTTD_FromFutureToBank = \'2\'\n+THOST_FTDC_OOD_Open = \'1\'\n+THOST_FTDC_OOD_Destroy = \'0\'\n+THOST_FTDC_AVAF_Invalid = \'0\'\n+THOST_FTDC_AVAF_Valid = \'1\'\n+THOST_FTDC_AVAF_Repeal = \'2\'\n+THOST_FTDC_OT_Bank = \'1\'\n+THOST_FTDC_OT_Future = \'2\'\n+THOST_FTDC_OT_PlateForm = \'9\'\n+THOST_FTDC_OL_HeadQuarters = \'1\'\n+THOST_FTDC_OL_Branch = \'2\'\n+THOST_FTDC_PID_FutureProtocal = \'0\'\n+THOST_FTDC_PID_ICBCProtocal = \'1\'\n+THOST_FTDC_PID_ABCProtocal = \'2\'\n+THOST_FTDC_PID_CBCProtocal = \'3\'\n+THOST_FTDC_PID_CCBProtocal = \'4\'\n+THOST_FTDC_PID_BOCOMProtocal = \'5\'\n+THOST_FTDC_PID_FBTPlateFormProtocal = \'X\'\n+THOST_FTDC_CM_ShortConnect = \'0\'\n+THOST_FTDC_CM_LongConnect = \'1\'\n+THOST_FTDC_SRM_ASync = \'0\'\n+THOST_FTDC_SRM_Sync = \'1\'\n+THOST_FTDC_BAT_BankBook = \'1\'\n+THOST_FTDC_BAT_SavingCard = \'2\'\n+THOST_FTDC_BAT_CreditCard = \'3\'\n+THOST_FTDC_FAT_BankBook = \'1\'\n+THOST_FTDC_FAT_SavingCard = \'2\'\n+THOST_FTDC_FAT_CreditCard = \'3\'\n+THOST_FTDC_OS_Ready = \'0\'\n+THOST_FTDC_OS_CheckIn = \'1\'\n+THOST_FTDC_OS_CheckOut = \'2\'\n+THOST_FTDC_OS_CheckFileArrived = \'3\'\n+THOST_FTDC_OS_CheckDetail = \'4\'\n+THOST_FTDC_OS_DayEndClean = \'5\'\n+THOST_FTDC_OS_Invalid = \'9\'\n+THOST_FTDC_CCBFM_ByAmount = \'1\'\n+THOST_FTDC_CCBFM_ByMonth = \'2\'\n+THOST_FTDC_CAPIT_Client = \'1\'\n+THOST_FTDC_CAPIT_Server = \'2\'\n+THOST_FTDC_CAPIT_UserApi = \'3\'\n+THOST_FTDC_LS_Connected = \'1\'\n+THOST_FTDC_LS_Disconnected = \'2\'\n+THOST_FTDC_BPWDF_NoCheck = \'0\'\n+THOST_FTDC_BPWDF_BlankCheck = \'1\'\n+THOST_FTDC_BPWDF_EncryptCheck = \'2\'\n+THOST_FTDC_SAT_AccountID = \'1\'\n+THOST_FTDC_SAT_CardID = \'2\'\n+THOST_FTDC_SAT_SHStockholderID = \'3\'\n+THOST_FTDC_SAT_SZStockholderID = \'4\'\n+THOST_FTDC_TRFS_Normal = \'0\'\n+THOST_FTDC_TRFS_Repealed = \'1\'\n+THOST_FTDC_SPTYPE_Broker = \'0\'\n+THOST_FTDC_SPTYPE_Bank = \'1\'\n+THOST_FTDC_REQRSP_Request = \'0\'\n+THOST_FTDC_REQRSP_Response = \'1\'\n+THOST_FTDC_FBTUET_SignIn = \'0\'\n+THOST_FTDC_FBTUET_FromBankToFuture = \'1\'\n+THOST_FTDC_FBTUET_FromFutureToBank = \'2\'\n+THOST_FTDC_FBTUET_OpenAccount = \'3\'\n+THOST_FTDC_FBTUET_CancelAccount = \'4\'\n+THOST_FTDC_FBTUET_ChangeAccount = \'5\'\n+THOST_FTDC_FBTUET_RepealFromBankToFuture = \'6\'\n+THOST_FTDC_FBTUET_RepealFromFutureToBank = \'7\'\n+THOST_FTDC_FBTUET_QueryBankAccount = \'8\'\n+THOST_FTDC_FBTUET_QueryFutureAccount = \'9\'\n+THOST_FTDC_FBTUET_SignOut = \'A\'\n+THOST_FTDC_FBTUET_SyncKey = \'B\'\n+THOST_FTDC_FBTUET_Other = \'Z\'\n+THOST_FTDC_DBOP_Insert = \'0\'\n+THOST_FTDC_DBOP_Update = \'1\'\n+THOST_FTDC_DBOP_Delete = \'2\'\n+THOST_FTDC_SYNF_Yes = \'0\'\n+THOST_FTDC_SYNF_No = \'1\'\n+THOST_FTDC_SYNT_OneOffSync = \'0\'\n+THOST_FTDC_SYNT_TimerSync = \'1\'\n+THOST_FTDC_SYNT_TimerFullSync = \'2\'\n+THOST_FTDC_FBEDIR_Settlement = \'0\'\n+THOST_FTDC_FBEDIR_Sale = \'1\'\n+THOST_FTDC_FBERES_Success = \'0\'\n+THOST_FTDC_FBERES_InsufficientBalance = \'1\'\n+THOST_FTDC_FBERES_UnknownTrading = \'8\'\n+THOST_FTDC_FBERES_Fail = \'x\'\n+THOST_FTDC_FBEES_Normal = \'0\'\n+THOST_FTDC_FBEES_ReExchange = \'1\'\n+THOST_FTDC_FBEFG_DataPackage = \'0\'\n+THOST_FTDC_FBEFG_File = \'1\'\n+THOST_FTDC_FBEAT_NotTrade = \'0\'\n+THOST_FTDC_FBEAT_Trade = \'1\'\n+THOST_FTDC_FBEUET_SignIn = \'0\'\n+THOST_FTDC_FBEUET_Exchange = \'1\'\n+THOST_FTDC_FBEUET_ReExchange = \'2\'\n+THOST_FTDC_FBEUET_QueryBankAccount = \'3\'\n+THOST_FTDC_FBEUET_QueryExchDetial = \'4\'\n+THOST_FTDC_FBEUET_QueryExchSummary = \'5\'\n+THOST_FTDC_FBEUET_QueryExchRate = \'6\'\n+THOST_FTDC_FBEUET_CheckBankAccount = \'7\'\n+THOST_FTDC_FBEUET_SignOut = \'8\'\n+THOST_FTDC_FBEUET_Other = \'Z\'\n+THOST_FTDC_FBERF_UnProcessed = \'0\'\n+THOST_FTDC_FBERF_WaitSend = \'1\'\n+THOST_FTDC_FBERF_SendSuccess = \'2\'\n+THOST_FTDC_FBERF_SendFailed = \'3\'\n+THOST_FTDC_FBERF_WaitReSend = \'4\'\n+THOST_FTDC_NC_NOERROR = \'0\'\n+THOST_FTDC_NC_Warn = \'1\'\n+THOST_FTDC_NC_Call = \'2\'\n+THOST_FTDC_NC_Force = \'3\'\n+THOST_FTDC_NC_CHUANCANG = \'4\'\n+THOST_FTDC_NC_Exception = \'5\'\n+THOST_FTDC_FCT_Manual = \'0\'\n+THOST_FTDC_FCT_Single = \'1\'\n+THOST_FTDC_FCT_Group = \'2\'\n+THOST_FTDC_RNM_System = \'0\'\n+THOST_FTDC_RNM_SMS = \'1\'\n+THOST_FTDC_RNM_EMail = \'2\'\n+THOST_FTDC_RNM_Manual = \'3\'\n+THOST_FTDC_RNS_NotGen = \'0\'\n+THOST_FTDC_RNS_Generated = \'1\'\n+THOST_FTDC_RNS_SendError = \'2\'\n+THOST_FTDC_RNS_SendOk = \'3\'\n+THOST_FTDC_RNS_Received = \'4\'\n+THOST_FTDC_RNS_Confirmed = \'5\'\n+THOST_FTDC_RUE_ExportData = \'0\'\n+THOST_FTDC_COST_LastPriceAsc = \'0\'\n+THOST_FTDC_COST_LastPriceDesc = \'1\'\n+THOST_FTDC_COST_AskPriceAsc = \'2\'\n+THOST_FTDC_COST_AskPriceDesc = \'3\'\n+THOST_FTDC_COST_BidPriceAsc = \'4\'\n+THOST_FTDC_COST_BidPriceDesc = \'5\'\n+THOST_FTDC_UOAST_NoSend = \'0\'\n+THOST_FTDC_UOAST_Sended = \'1\'\n+THOST_FTDC_UOAST_Generated = \'2\'\n+THOST_FTDC_UOAST_SendFail = \'3\'\n+THOST_FTDC_UOAST_Success = \'4\'\n+THOST_FTDC_UOAST_Fail = \'5\'\n+THOST_FTDC_UOAST_Cancel = \'6\'\n+THOST_FTDC_UOACS_NoApply = \'1\'\n+THOST_FTDC_UOACS_Submited = \'2\'\n+THOST_FTDC_UOACS_Sended = \'3\'\n+THOST_FTDC_UOACS_Success = \'4\'\n+THOST_FTDC_UOACS_Refuse = \'5\'\n+THOST_FTDC_UOACS_Cancel = \'6\'\n+THOST_FTDC_QT_Radio = \'1\'\n+THOST_FTDC_QT_Option = \'2\'\n+THOST_FTDC_QT_Blank = \'3\'\n+THOST_FTDC_BT_Request = \'1\'\n+THOST_FTDC_BT_Response = \'2\'\n+THOST_FTDC_BT_Notice = \'3\'\n+THOST_FTDC_CRC_Success = \'0\'\n+THOST_FTDC_CRC_Working = \'1\'\n+THOST_FTDC_CRC_InfoFail = \'2\'\n+THOST_FTDC_CRC_IDCardFail = \'3\'\n+THOST_FTDC_CRC_OtherFail = \'4\'\n+THOST_FTDC_CfMMCCT_All = \'0\'\n+THOST_FTDC_CfMMCCT_Person = \'1\'\n+THOST_FTDC_CfMMCCT_Company = \'2\'\n+THOST_FTDC_CfMMCCT_Other = \'3\'\n+THOST_FTDC_CfMMCCT_SpecialOrgan = \'4\'\n+THOST_FTDC_CfMMCCT_Asset = \'5\'\n+THOST_FTDC_EIDT_SHFE = \'S\'\n+THOST_FTDC_EIDT_CZCE = \'Z\'\n+THOST_FTDC_EIDT_DCE = \'D\'\n+THOST_FTDC_EIDT_CFFEX = \'J\'\n+THOST_FTDC_EIDT_INE = \'N\'\n+THOST_FTDC_EIDT_GOLD = \'G\'\n+THOST_FTDC_EIDT_PAT = \'P\'\n+THOST_FTDC_EIDT_LTS = \'L\'\n+THOST_FTDC_EIDT_CME = \'A\'\n+THOST_FTDC_EIDT_LME = \'B\'\n+THOST_FTDC_EIDT_SGX = \'E\'\n+THOST_FTDC_EIDT_HKEX = \'F\'\n+THOST_FTDC_ECIDT_Hedge = \'1\'\n+THOST_FTDC_ECIDT_Arbitrage = \'2\'\n+THOST_FTDC_ECIDT_Speculation = \'3\'\n+THOST_FTDC_UF_NoUpdate = \'0\'\n+THOST_FTDC_UF_Success = \'1\'\n+THOST_FTDC_UF_Fail = \'2\'\n+THOST_FTDC_UF_TCSuccess = \'3\'\n+THOST_FTDC_UF_TCFail = \'4\'\n+THOST_FTDC_UF_Cancel = \'5\'\n+THOST_FTDC_AOID_OpenInvestor = \'1\'\n+THOST_FTDC_AOID_ModifyIDCard = \'2\'\n+THOST_FTDC_AOID_ModifyNoIDCard = \'3\'\n+THOST_FTDC_AOID_ApplyTradingCode = \'4\'\n+THOST_FTDC_AOID_CancelTradingCode = \'5\'\n+THOST_FTDC_AOID_CancelInvestor = \'6\'\n+THOST_FTDC_AOID_FreezeAccount = \'8\'\n+THOST_FTDC_AOID_ActiveFreezeAccount = \'9\'\n+THOST_FTDC_ASID_NoComplete = \'1\'\n+THOST_FTDC_ASID_Submited = \'2\'\n+THOST_FTDC_ASID_Checked = \'3\'\n+THOST_FTDC_ASID_Refused = \'4\'\n+THOST_FTDC_ASID_Deleted = \'5\'\n+THOST_FTDC_UOASM_ByAPI = \'1\'\n+THOST_FTDC_UOASM_ByFile = \'2\'\n+THOST_FTDC_EvM_ADD = \'1\'\n+THOST_FTDC_EvM_UPDATE = \'2\'\n+THOST_FTDC_EvM_DELETE = \'3\'\n+THOST_FTDC_EvM_CHECK = \'4\'\n+THOST_FTDC_EvM_COPY = \'5\'\n+THOST_FTDC_EvM_CANCEL = \'6\'\n+THOST_FTDC_EvM_Reverse = \'7\'\n+THOST_FTDC_UOAA_ASR = \'1\'\n+THOST_FTDC_UOAA_ASNR = \'2\'\n+THOST_FTDC_UOAA_NSAR = \'3\'\n+THOST_FTDC_UOAA_NSR = \'4\'\n+THOST_FTDC_EvM_InvestorGroupFlow = \'1\'\n+THOST_FTDC_EvM_InvestorRate = \'2\'\n+THOST_FTDC_EvM_InvestorCommRateModel = \'3\'\n+THOST_FTDC_CL_Zero = \'0\'\n+THOST_FTDC_CL_One = \'1\'\n+THOST_FTDC_CL_Two = \'2\'\n+THOST_FTDC_CHS_Init = \'0\'\n+THOST_FTDC_CHS_Checking = \'1\'\n+THOST_FTDC_CHS_Checked = \'2\'\n+THOST_FTDC_CHS_Refuse = \'3\'\n+THOST_FTDC_CHS_Cancel = \'4\'\n+THOST_FTDC_CHU_Unused = \'0\'\n+THOST_FTDC_CHU_Used = \'1\'\n+THOST_FTDC_CHU_Fail = \'2\'\n+THOST_FTDC_BAO_ByAccProperty = \'0\'\n+THOST_FTDC_BAO_ByFBTransfer = \'1\'\n+THOST_FTDC_MBTS_ByInstrument = \'0\'\n+THOST_FTDC_MBTS_ByDayInsPrc = \'1\'\n+THOST_FTDC_MBTS_ByDayIns = \'2\'\n+THOST_FTDC_FTC_BankLaunchBankToBroker = \'102001\'\n+THOST_FTDC_FTC_BrokerLaunchBankToBroker = \'202001\'\n+THOST_FTDC_FTC_BankLaunchBrokerToBank = \'102002\'\n+THOST_FTDC_FTC_BrokerLaunchBrokerToBank = \'202002\'\n+THOST_FTDC_OTP_NONE = \'0\'\n+THOST_FTDC_OTP_TOTP = \'1\'\n+THOST_FTDC_OTPS_Unused = \'0\'\n+THOST_FTDC_OTPS_Used = \'1\'\n+THOST_FTDC_OTPS_Disuse = \'2\'\n+THOST_FTDC_BUT_Investor = \'1\'\n+THOST_FTDC_BUT_BrokerUser = \'2\'\n+THOST_FTDC_FUTT_Commodity = \'1\'\n+THOST_FTDC_FUTT_Financial = \'2\'\n+THOST_FTDC_FET_Restriction = \'0\'\n+THOST_FTDC_FET_TodayRestriction = \'1\'\n+THOST_FTDC_FET_Transfer = \'2\'\n+THOST_FTDC_FET_Credit = \'3\'\n+THOST_FTDC_FET_InvestorWithdrawAlm = \'4\'\n+THOST_FTDC_FET_BankRestriction = \'5\'\n+THOST_FTDC_FET_Accountregister = \'6\'\n+THOST_FTDC_FET_ExchangeFundIO = \'7\'\n+THOST_FTDC_FET_InvestorFundIO = \'8\'\n+THOST_FTDC_AST_FBTransfer = \'0\'\n+THOST_FTDC_AST_ManualEntry = \'1\'\n+THOST_FTDC_CST_UnifyAccount = \'0\'\n+THOST_FTDC_CST_ManualEntry = \'1\'\n+THOST_FTDC_UR_All = \'0\'\n+THOST_FTDC_UR_Single = \'1\'\n+THOST_FTDC_BG_Investor = \'2\'\n+THOST_FTDC_BG_Group = \'1\'\n+THOST_FTDC_TSSM_Instrument = \'1\'\n+THOST_FTDC_TSSM_Product = \'2\'\n+THOST_FTDC_TSSM_Exchange = \'3\'\n+THOST_FTDC_ESM_Relative = \'1\'\n+THOST_FTDC_ESM_Typical = \'2\'\n+THOST_FTDC_RIR_All = \'1\'\n+THOST_FTDC_RIR_Model = \'2\'\n+THOST_FTDC_RIR_Single = \'3\'\n+THOST_FTDC_SDS_Initialize = \'0\'\n+THOST_FTDC_SDS_Settlementing = \'1\'\n+THOST_FTDC_SDS_Settlemented = \'2\'\n+THOST_FTDC_TSRC_NORMAL = \'0\'\n+THOST_FTDC_TSRC_QUERY = \'1\'\n+THOST_FTDC_FSM_Product = \'1\'\n+THOST_FTDC_FSM_Exchange = \'2\'\n+THOST_FTDC_FSM_All = \'3\'\n+THOST_FTDC_BIR_Property = \'1\'\n+THOST_FTDC_BIR_All = \'2\'\n+THOST_FTDC_PIR_All = \'1\'\n+THOST_FTDC_PIR_Property = \'2\'\n+THOST_FTDC_PIR_Single = \'3\'\n+THOST_FTDC_FIS_NoCreate = \'0\'\n+THOST_FTDC_FIS_Created = \'1\'\n+THOST_FTDC_FIS_Failed = \'2\'\n+THOST_FTDC_FGS_FileTransmit = \'0\'\n+THOST_FTDC_FGS_FileGen = \'1\'\n+THOST_FTDC_SoM_Add = \'1\'\n+THOST_FTDC_SoM_Update = \'2\'\n+THOST_FTDC_SoM_Delete = \'3\'\n+THOST_FTDC_SoM_Copy = \'4\'\n+THOST_FTDC_SoM_AcTive = \'5\'\n+THOST_FTDC_SoM_CanCel = \'6\'\n+THOST_FTDC_SoM_ReSet = \'7\'\n+THOST_FTDC_SoT_UpdatePassword = \'0\'\n+THOST_FTDC_SoT_UserDepartment = \'1\'\n+THOST_FTDC_SoT_RoleManager = \'2\'\n+THOST_FTDC_SoT_RoleFunction = \'3\'\n+THOST_FTDC_SoT_BaseParam = \'4\'\n+THOST_FTDC_SoT_SetUserID = \'5\'\n+THOST_FTDC_SoT_SetUserRole = \'6\'\n+THOST_FTDC_SoT_UserIpRestriction = \'7\'\n+THOST_FTDC_SoT_DepartmentManager = \'8\'\n+THOST_FTDC_SoT_DepartmentCopy = \'9\'\n+THOST_FTDC_SoT_Tradingcode = \'A\'\n+THOST_FTDC_SoT_InvestorStatus = \'B\'\n+THOST_FTDC_SoT_InvestorAuthority = \'C\'\n+THOST_FTDC_SoT_PropertySet = \'D\'\n+THOST_FTDC_SoT_ReSetInvestorPasswd = \'E\'\n+THOST_FTDC_SoT_InvestorPersonalityInfo = \'F\'\n+THOST_FTDC_CSRCQ_Current = \'0\'\n+THOST_FTDC_CSRCQ_History = \'1\'\n+THOST_FTDC_FRS_Normal = \'1\'\n+THOST_FTDC_FRS_Freeze = \'0\'\n+THOST_FTDC_STST_Standard = \'0\'\n+THOST_FTDC_STST_NonStandard = \'1\'\n+THOST_FTDC_RPT_Freeze = \'1\'\n+THOST_FTDC_RPT_FreezeActive = \'2\'\n+THOST_FTDC_RPT_OpenLimit = \'3\'\n+THOST_FTDC_RPT_RelieveOpenLimit = \'4\'\n+THOST_FTDC_AMLDS_Normal = \'0\'\n+THOST_FTDC_AMLDS_Deleted = \'1\'\n+THOST_FTDC_AMLCHS_Init = \'0\'\n+THOST_FTDC_AMLCHS_Checking = \'1\'\n+THOST_FTDC_AMLCHS_Checked = \'2\'\n+THOST_FTDC_AMLCHS_RefuseReport = \'3\'\n+THOST_FTDC_AMLDT_DrawDay = \'0\'\n+THOST_FTDC_AMLDT_TouchDay = \'1\'\n+THOST_FTDC_AMLCL_CheckLevel0 = \'0\'\n+THOST_FTDC_AMLCL_CheckLevel1 = \'1\'\n+THOST_FTDC_AMLCL_CheckLevel2 = \'2\'\n+THOST_FTDC_AMLCL_CheckLevel3 = \'3\'\n+THOST_FTDC_EFT_CSV = \'0\'\n+THOST_FTDC_EFT_EXCEL = \'1\'\n+THOST_FTDC_EFT_DBF = \'2\'\n+THOST_FTDC_SMT_Before = \'1\'\n+THOST_FTDC_SMT_Settlement = \'2\'\n+THOST_FTDC_SMT_After = \'3\'\n+THOST_FTDC_SMT_Settlemented = \'4\'\n+THOST_FTDC_SML_Must = \'1\'\n+THOST_FTDC_SML_Alarm = \'2\'\n+THOST_FTDC_SML_Prompt = \'3\'\n+THOST_FTDC_SML_Ignore = \'4\'\n+THOST_FTDC_SMG_Exhcange = \'1\'\n+THOST_FTDC_SMG_ASP = \'2\'\n+THOST_FTDC_SMG_CSRC = \'3\'\n+THOST_FTDC_LUT_Repeatable = \'1\'\n+THOST_FTDC_LUT_Unrepeatable = \'2\'\n+THOST_FTDC_DAR_Settle = \'1\'\n+THOST_FTDC_DAR_Exchange = \'2\'\n+THOST_FTDC_DAR_CSRC = \'3\'\n+THOST_FTDC_MGT_ExchMarginRate = \'0\'\n+THOST_FTDC_MGT_InstrMarginRate = \'1\'\n+THOST_FTDC_MGT_InstrMarginRateTrade = \'2\'\n+THOST_FTDC_ACT_Intraday = \'1\'\n+THOST_FTDC_ACT_Long = \'2\'\n+THOST_FTDC_MRT_Exchange = \'1\'\n+THOST_FTDC_MRT_Investor = \'2\'\n+THOST_FTDC_MRT_InvestorTrade = \'3\'\n+THOST_FTDC_BUS_UnBak = \'0\'\n+THOST_FTDC_BUS_BakUp = \'1\'\n+THOST_FTDC_BUS_BakUped = \'2\'\n+THOST_FTDC_BUS_BakFail = \'3\'\n+THOST_FTDC_SIS_UnInitialize = \'0\'\n+THOST_FTDC_SIS_Initialize = \'1\'\n+THOST_FTDC_SIS_Initialized = \'2\'\n+THOST_FTDC_SRS_NoCreate = \'0\'\n+THOST_FTDC_SRS_Create = \'1\'\n+THOST_FTDC_SRS_Created = \'2\'\n+THOST_FTDC_SRS_CreateFail = \'3\'\n+THOST_FTDC_SSS_UnSaveData = \'0\'\n+THOST_FTDC_SSS_SaveDatad = \'1\'\n+THOST_FTDC_SAS_UnArchived = \'0\'\n+THOST_FTDC_SAS_Archiving = \'1\'\n+THOST_FTDC_SAS_Archived = \'2\'\n+THOST_FTDC_SAS_ArchiveFail = \'3\'\n+THOST_FTDC_CTPT_Unkown = \'0\'\n+THOST_FTDC_CTPT_MainCenter = \'1\'\n+THOST_FTDC_CTPT_BackUp = \'2\'\n+THOST_FTDC_CDT_Normal = \'0\'\n+THOST_FTDC_CDT_SpecFirst = \'1\'\n+THOST_FTDC_MFUR_None = \'0\'\n+THOST_FTDC_MFUR_Margin = \'1\'\n+THOST_FTDC_MFUR_All = \'2\'\n+THOST_FTDC_SPT_CzceHedge = \'1\'\n+THOST_FTDC_SPT_IneForeignCurrency = \'2\'\n+THOST_FTDC_SPT_DceOpenClose = \'3\'\n+THOST_FTDC_FMT_Mortgage = \'1\'\n+THOST_FTDC_FMT_Redemption = \'2\'\n+THOST_FTDC_ASPI_BaseMargin = \'1\'\n+THOST_FTDC_ASPI_LowestInterest = \'2\'\n+THOST_FTDC_FMD_In = \'1\'\n+THOST_FTDC_FMD_Out = \'2\'\n+THOST_FTDC_BT_Profit = \'0\'\n+THOST_FTDC_BT_Loss = \'1\'\n+THOST_FTDC_BT_Other = \'Z\'\n+THOST_FTDC_SST_Manual = \'0\'\n+THOST_FTDC_SST_Automatic = \'1\'\n+THOST_FTDC_CED_Settlement = \'0\'\n+THOST_FTDC_CED_Sale = \'1\'\n+THOST_FTDC_CSS_Entry = \'1\'\n+THOST_FTDC_CSS_Approve = \'2\'\n+THOST_FTDC_CSS_Refuse = \'3\'\n+THOST_FTDC_CSS_Revoke = \'4\'\n+THOST_FTDC_CSS_Send = \'5\'\n+THOST_FTDC_CSS_Success = \'6\'\n+THOST_FTDC_CSS_Failure = \'7\'\n+THOST_FTDC_REQF_NoSend = \'0\'\n+THOST_FTDC_REQF_SendSuccess = \'1\'\n+THOST_FTDC_REQF_SendFailed = \'2\'\n+THOST_FTDC_REQF_WaitReSend = \'3\'\n+THOST_FTDC_RESF_Success = \'0\'\n+THOST_FTDC_RESF_InsuffiCient = \'1\'\n+THOST_FTDC_RESF_UnKnown = \'8\'\n+THOST_FTDC_EXS_Before = \'0\'\n+THOST_FTDC_EXS_After = \'1\'\n+THOST_FTDC_CR_Domestic = \'1\'\n+THOST_FTDC_CR_GMT = \'2\'\n+THOST_FTDC_CR_Foreign = \'3\'\n+THOST_FTDC_HB_No = \'0\'\n+THOST_FTDC_HB_Yes = \'1\'\n+THOST_FTDC_SM_Normal = \'1\'\n+THOST_FTDC_SM_Emerge = \'2\'\n+THOST_FTDC_SM_Restore = \'3\'\n+THOST_FTDC_TPT_Full = \'1\'\n+THOST_FTDC_TPT_Increment = \'2\'\n+THOST_FTDC_TPT_BackUp = \'3\'\n+THOST_FTDC_LM_Trade = \'0\'\n+THOST_FTDC_LM_Transfer = \'1\'\n+THOST_FTDC_CPT_Instrument = \'1\'\n+THOST_FTDC_CPT_Margin = \'2\'\n+THOST_FTDC_HT_Yes = \'1\'\n+THOST_FTDC_HT_No = \'0\'\n+THOST_FTDC_AMT_Bank = \'1\'\n+THOST_FTDC_AMT_Securities = \'2\'\n+THOST_FTDC_AMT_Fund = \'3\'\n+THOST_FTDC_AMT_Insurance = \'4\'\n+THOST_FTDC_AMT_Trust = \'5\'\n+THOST_FTDC_AMT_Other = \'9\'\n+THOST_FTDC_CFIOT_FundIO = \'0\'\n+THOST_FTDC_CFIOT_SwapCurrency = \'1\'\n+THOST_FTDC_CAT_Futures = \'1\'\n+THOST_FTDC_CAT_AssetmgrFuture = \'2\'\n+THOST_FTDC_CAT_AssetmgrTrustee = \'3\'\n+THOST_FTDC_CAT_AssetmgrTransfer = \'4\'\n+THOST_FTDC_LT_Chinese = \'1\'\n+THOST_FTDC_LT_English = \'2\'\n+THOST_FTDC_AMCT_Person = \'1\'\n+THOST_FTDC_AMCT_Organ = \'2\'\n+THOST_FTDC_AMCT_SpecialOrgan = \'4\'\n+THOST_FTDC_ASST_Futures = \'3\'\n+THOST_FTDC_ASST_SpecialOrgan = \'4\'\n+THOST_FTDC_CIT_HasExch = \'0\'\n+THOST_FTDC_CIT_HasATP = \'1\'\n+THOST_FTDC_CIT_HasDiff = \'2\'\n+THOST_FTDC_DT_HandDeliv = \'1\'\n+THOST_FTDC_DT_PersonDeliv = \'2\'\n+THOST_FTDC_MMSA_NO = \'0\'\n+THOST_FTDC_MMSA_YES = \'1\'\n+THOST_FTDC_CACT_Person = \'0\'\n+THOST_FTDC_CACT_Company = \'1\'\n+THOST_FTDC_CACT_Other = \'2\'\n+THOST_FTDC_UOAAT_Futures = \'1\'\n+THOST_FTDC_UOAAT_SpecialOrgan = \'2\'\n+THOST_FTDC_DEN_Buy = \'0\'\n+THOST_FTDC_DEN_Sell = \'1\'\n+THOST_FTDC_OFEN_Open = \'0\'\n+THOST_FTDC_OFEN_Close = \'1\'\n+THOST_FTDC_OFEN_ForceClose = \'2\'\n+THOST_FTDC_OFEN_CloseToday = \'3\'\n+THOST_FTDC_OFEN_CloseYesterday = \'4\'\n+THOST_FTDC_OFEN_ForceOff = \'5\'\n+THOST_FTDC_OFEN_LocalForceClose = \'6\'\n+THOST_FTDC_HFEN_Speculation = \'1\'\n+THOST_FTDC_HFEN_Arbitrage = \'2\'\n+THOST_FTDC_HFEN_Hedge = \'3\'\n+THOST_FTDC_FIOTEN_FundIO = \'1\'\n+THOST_FTDC_FIOTEN_Transfer = \'2\'\n+THOST_FTDC_FIOTEN_SwapCurrency = \'3\'\n+THOST_FTDC_FTEN_Deposite = \'1\'\n+THOST_FTDC_FTEN_ItemFund = \'2\'\n+THOST_FTDC_FTEN_Company = \'3\'\n+THOST_FTDC_FTEN_InnerTransfer = \'4\'\n+THOST_FTDC_FDEN_In = \'1\'\n+THOST_FTDC_FDEN_Out = \'2\'\n+THOST_FTDC_FMDEN_In = \'1\'\n+THOST_FTDC_FMDEN_Out = \'2\'\n+THOST_FTDC_CP_CallOptions = \'1\'\n+THOST_FTDC_CP_PutOptions = \'2\'\n+THOST_FTDC_STM_Continental = \'0\'\n+THOST_FTDC_STM_American = \'1\'\n+THOST_FTDC_STM_Bermuda = \'2\'\n+THOST_FTDC_STT_Hedge = \'0\'\n+THOST_FTDC_STT_Match = \'1\'\n+THOST_FTDC_APPT_NotStrikeNum = \'4\'\n+THOST_FTDC_GUDS_Gen = \'0\'\n+THOST_FTDC_GUDS_Hand = \'1\'\n+THOST_FTDC_OER_NoExec = \'n\'\n+THOST_FTDC_OER_Canceled = \'c\'\n+THOST_FTDC_OER_OK = \'0\'\n+THOST_FTDC_OER_NoPosition = \'1\'\n+THOST_FTDC_OER_NoDeposit = \'2\'\n+THOST_FTDC_OER_NoParticipant = \'3\'\n+THOST_FTDC_OER_NoClient = \'4\'\n+THOST_FTDC_OER_NoInstrument = \'6\'\n+THOST_FTDC_OER_NoRight = \'7\'\n+THOST_FTDC_OER_InvalidVolume = \'8\'\n+THOST_FTDC_OER_NoEnoughHistoryTrade = \'9\'\n+THOST_FTDC_OER_Unknown = \'a\'\n+THOST_FTDC_COMBT_Future = \'0\'\n+THOST_FTDC_COMBT_BUL = \'1\'\n+THOST_FTDC_COMBT_BER = \'2\'\n+THOST_FTDC_COMBT_STD = \'3\'\n+THOST_FTDC_COMBT_STG = \'4\'\n+THOST_FTDC_COMBT_PRT = \'5\'\n+THOST_FTDC_COMBT_CLD = \'6\'\n+THOST_FTDC_ORPT_PreSettlementPrice = \'1\'\n+THOST_FTDC_ORPT_OpenPrice = \'4\'\n+THOST_FTDC_BLAG_Default = \'1\'\n+THOST_FTDC_BLAG_IncludeOptValLost = \'2\'\n+THOST_FTDC_ACTP_Exec = \'1\'\n+THOST_FTDC_ACTP_Abandon = \'2\'\n+THOST_FTDC_FQST_Submitted = \'a\'\n+THOST_FTDC_FQST_Accepted = \'b\'\n+THOST_FTDC_FQST_Rejected = \'c\'\n+THOST_FTDC_VM_Absolute = \'0\'\n+THOST_FTDC_VM_Ratio = \'1\'\n+THOST_FTDC_EOPF_Reserve = \'0\'\n+THOST_FTDC_EOPF_UnReserve = \'1\'\n+THOST_FTDC_EOCF_AutoClose = \'0\'\n+THOST_FTDC_EOCF_NotToClose = \'1\'\n+THOST_FTDC_PTE_Futures = \'1\'\n+THOST_FTDC_PTE_Options = \'2\'\n+THOST_FTDC_CUFN_CUFN_O = \'O\'\n+THOST_FTDC_CUFN_CUFN_T = \'T\'\n+THOST_FTDC_CUFN_CUFN_P = \'P\'\n+THOST_FTDC_CUFN_CUFN_N = \'N\'\n+THOST_FTDC_CUFN_CUFN_L = \'L\'\n+THOST_FTDC_CUFN_CUFN_F = \'F\'\n+THOST_FTDC_CUFN_CUFN_C = \'C\'\n+THOST_FTDC_CUFN_CUFN_M = \'M\'\n+THOST_FTDC_DUFN_DUFN_O = \'O\'\n+THOST_FTDC_DUFN_DUFN_T = \'T\'\n+THOST_FTDC_DUFN_DUFN_P = \'P\'\n+THOST_FTDC_DUFN_DUFN_F = \'F\'\n+THOST_FTDC_DUFN_DUFN_C = \'C\'\n+THOST_FTDC_DUFN_DUFN_D = \'D\'\n+THOST_FTDC_DUFN_DUFN_M = \'M\'\n+THOST_FTDC_DUFN_DUFN_S = \'S\'\n+THOST_FTDC_SUFN_SUFN_O = \'O\'\n+THOST_FTDC_SUFN_SUFN_T = \'T\'\n+THOST_FTDC_SUFN_SUFN_P = \'P\'\n+THOST_FTDC_SUFN_SUFN_F = \'F\'\n+THOST_FTDC_CFUFN_SUFN_T = \'T\'\n+THOST_FTDC_CFUFN_SUFN_P = \'P\'\n+THOST_FTDC_CFUFN_SUFN_F = \'F\'\n+THOST_FTDC_CFUFN_SUFN_S = \'S\'\n+THOST_FTDC_CMDR_Comb = \'0\'\n+THOST_FTDC_CMDR_UnComb = \'1\'\n+THOST_FTDC_PDT_LTS = \'1\'\n+THOST_FTDC_PDT_STL = \'2\'\n+THOST_FTDC_PDT_NONE = \'3\'\ndiff --git a/vnpy/gateway/sgit/__init__.py b/vnpy/gateway/sgit/__init__.py\nnew file mode 100644\nindex 00000000..928a00b7\n--- /dev/null\n+++ b/vnpy/gateway/sgit/__init__.py\n@@ -0,0 +1 @@\n+from .sgit_gateway import SgitGateway\n\\ No newline at end of file\ndiff --git a/vnpy/gateway/sgit/sgit_gateway.py b/vnpy/gateway/sgit/sgit_gateway.py\nnew file mode 100644\nindex 00000000..d16dec96\n--- /dev/null\n+++ b/vnpy/gateway/sgit/sgit_gateway.py\n@@ -0,0 +1,859 @@\n+"""\n+"""\n+\n+import sys\n+from datetime import datetime\n+from typing import Dict, List\n+\n+from vnpy.api.sgit import (\n+    MdApi,\n+    TdApi,\n+    THOST_FTDC_OAS_Submitted,\n+    THOST_FTDC_OAS_Accepted,\n+    THOST_FTDC_OAS_Rejected,\n+    THOST_FTDC_OST_NoTradeQueueing,\n+    THOST_FTDC_OST_PartTradedQueueing,\n+    THOST_FTDC_OST_AllTraded,\n+    THOST_FTDC_OST_Canceled,\n+    THOST_FTDC_D_Buy,\n+    THOST_FTDC_D_Sell,\n+    THOST_FTDC_PD_Long,\n+    THOST_FTDC_PD_Short,\n+    THOST_FTDC_OPT_LimitPrice,\n+    THOST_FTDC_OPT_AnyPrice,\n+    THOST_FTDC_OF_Open,\n+    THOST_FTDC_OFEN_Close,\n+    THOST_FTDC_OFEN_CloseYesterday,\n+    THOST_FTDC_OFEN_CloseToday,\n+    THOST_FTDC_PC_Futures,\n+    THOST_FTDC_PC_Options,\n+    THOST_FTDC_PC_SpotOption,\n+    THOST_FTDC_PC_Combination,\n+    THOST_FTDC_CP_CallOptions,\n+    THOST_FTDC_CP_PutOptions,\n+    THOST_FTDC_HF_Speculation,\n+    THOST_FTDC_CC_Immediately,\n+    THOST_FTDC_FCC_NotForceClose,\n+    THOST_FTDC_TC_GFD,\n+    THOST_FTDC_VC_AV,\n+    THOST_FTDC_TC_IOC,\n+    THOST_FTDC_VC_CV,\n+    THOST_FTDC_AF_Delete\n+)\n+from vnpy.trader.constant import (\n+    Direction,\n+    Offset,\n+    Exchange,\n+    OrderType,\n+    Product,\n+    Status,\n+    OptionType\n+)\n+from vnpy.trader.gateway import BaseGateway\n+from vnpy.trader.object import (\n+    TickData,\n+    OrderData,\n+    TradeData,\n+    PositionData,\n+    AccountData,\n+    ContractData,\n+    OrderRequest,\n+    CancelRequest,\n+    SubscribeRequest,\n+)\n+from vnpy.trader.utility import get_folder_path\n+from vnpy.trader.event import EVENT_TIMER\n+\n+\n+STATUS_SGIT2VT: Dict[str, Status] = {\n+    THOST_FTDC_OAS_Submitted: Status.SUBMITTING,\n+    THOST_FTDC_OAS_Accepted: Status.SUBMITTING,\n+    THOST_FTDC_OAS_Rejected: Status.REJECTED,\n+    THOST_FTDC_OST_NoTradeQueueing: Status.NOTTRADED,\n+    THOST_FTDC_OST_PartTradedQueueing: Status.PARTTRADED,\n+    THOST_FTDC_OST_AllTraded: Status.ALLTRADED,\n+    THOST_FTDC_OST_Canceled: Status.CANCELLED\n+}\n+\n+DIRECTION_VT2SGIT: Dict[Direction, str] = {\n+    Direction.LONG: THOST_FTDC_D_Buy,\n+    Direction.SHORT: THOST_FTDC_D_Sell\n+}\n+DIRECTION_SGIT2VT: Dict[str, Direction] = {v: k for k, v in DIRECTION_VT2SGIT.items()}\n+DIRECTION_SGIT2VT[THOST_FTDC_PD_Long] = Direction.LONG\n+DIRECTION_SGIT2VT[THOST_FTDC_PD_Short] = Direction.SHORT\n+\n+ORDERTYPE_VT2SGIT: Dict[OrderType, str] = {\n+    OrderType.LIMIT: THOST_FTDC_OPT_LimitPrice,\n+    OrderType.MARKET: THOST_FTDC_OPT_AnyPrice\n+}\n+ORDERTYPE_SGIT2VT: Dict[str, OrderType] = {v: k for k, v in ORDERTYPE_VT2SGIT.items()}\n+\n+OFFSET_VT2SGIT: Dict[Offset, str] = {\n+    Offset.OPEN: THOST_FTDC_OF_Open,\n+    Offset.CLOSE: THOST_FTDC_OFEN_Close,\n+    Offset.CLOSETODAY: THOST_FTDC_OFEN_CloseToday,\n+    Offset.CLOSEYESTERDAY: THOST_FTDC_OFEN_CloseYesterday,\n+}\n+OFFSET_SGIT2VT: Dict[str, Offset] = {v: k for k, v in OFFSET_VT2SGIT.items()}\n+\n+EXCHANGE_SGIT2VT: Dict[str, Exchange] = {\n+    "CFFEX": Exchange.CFFEX,\n+    "SHFE": Exchange.SHFE,\n+    "CZCE": Exchange.CZCE,\n+    "DCE": Exchange.DCE,\n+    "INE": Exchange.INE\n+}\n+\n+PRODUCT_SGIT2VT: Dict[str, Product] = {\n+    THOST_FTDC_PC_Futures: Product.FUTURES,\n+    THOST_FTDC_PC_Options: Product.OPTION,\n+    THOST_FTDC_PC_SpotOption: Product.OPTION,\n+    THOST_FTDC_PC_Combination: Product.SPREAD\n+}\n+\n+OPTIONTYPE_SGIT2VT: Dict[str, OptionType] = {\n+    THOST_FTDC_CP_CallOptions: OptionType.CALL,\n+    THOST_FTDC_CP_PutOptions: OptionType.PUT\n+}\n+\n+MAX_FLOAT: float = sys.float_info.max\n+\n+\n+symbol_exchange_map: Dict = {}\n+symbol_name_map: Dict = {}\n+symbol_size_map: Dict = {}\n+\n+\n+class SgitGateway(BaseGateway):\n+    """\n+    VN Trader Gateway for CTP .\n+    """\n+\n+    default_setting: Dict[str, str] = {\n+        "用户名": "",\n+        "密码": "",\n+        "经纪商代码": "",\n+        "交易服务器": "",\n+        "行情服务器": "",\n+        "产品名称": "",\n+        "授权编码": "",\n+        "产品信息": ""\n+    }\n+\n+    exchanges: List[Exchange] = list(EXCHANGE_SGIT2VT.values())\n+\n+    def __init__(self, event_engine):\n+        """Constructor"""\n+        super().__init__(event_engine, "CTP")\n+\n+        self.td_api = SgitTsdApi(self)\n+        self.md_api = SgitMdApi(self)\n+\n+    def connect(self, setting: dict) -> None:\n+        """"""\n+        userid = setting["用户名"]\n+        password = setting["密码"]\n+        brokerid = setting["经纪商代码"]\n+        td_address = setting["交易服务器"]\n+        md_address = setting["行情服务器"]\n+        appid = setting["产品名称"]\n+        auth_code = setting["授权编码"]\n+        product_info = setting["产品信息"]\n+\n+        if (\n+            (not td_address.startswith("tcp://"))\n+            and (not td_address.startswith("ssl://"))\n+        ):\n+            td_address = "tcp://" + td_address\n+\n+        if (\n+            (not md_address.startswith("tcp://"))\n+            and (not md_address.startswith("ssl://"))\n+        ):\n+            md_address = "tcp://" + md_address\n+\n+        self.td_api.connect(td_address, userid, password, brokerid, auth_code, appid, product_info)\n+        self.md_api.connect(md_address, userid, password, brokerid)\n+\n+        self.init_query()\n+\n+    def subscribe(self, req: SubscribeRequest) -> None:\n+        """"""\n+        self.md_api.subscribe(req)\n+\n+    def send_order(self, req: OrderRequest) -> str:\n+        """"""\n+        return self.td_api.send_order(req)\n+\n+    def cancel_order(self, req: CancelRequest) -> None:\n+        """"""\n+        self.td_api.cancel_order(req)\n+\n+    def query_account(self) -> None:\n+        """"""\n+        self.td_api.query_account()\n+\n+    def query_position(self) -> None:\n+        """"""\n+        self.td_api.query_position()\n+\n+    def close(self) -> None:\n+        """"""\n+        self.td_api.close()\n+        self.md_api.close()\n+\n+    def write_error(self, msg: str, error: dict) -> None:\n+        """"""\n+        error_id = error["ErrorID"]\n+        error_msg = error["ErrorMsg"]\n+        msg = f"{msg}，代码：{error_id}，信息：{error_msg}"\n+        self.write_log(msg)\n+\n+    def process_timer_event(self, event) -> None:\n+        """"""\n+        self.count += 1\n+        if self.count < 2:\n+            return\n+        self.count = 0\n+\n+        func = self.query_functions.pop(0)\n+        func()\n+        self.query_functions.append(func)\n+\n+    def init_query(self) -> None:\n+        """"""\n+        self.count = 0\n+        self.query_functions = [self.query_account, self.query_position]\n+        self.event_engine.register(EVENT_TIMER, self.process_timer_event)\n+\n+\n+class SgitMdApi(MdApi):\n+    """"""\n+\n+    def __init__(self, gateway):\n+        """Constructor"""\n+        super(SgitMdApi, self).__init__()\n+\n+        self.gateway = gateway\n+        self.gateway_name = gateway.gateway_name\n+\n+        self.reqid = 0\n+\n+        self.connect_status = False\n+        self.login_status = False\n+        self.subscribed = set()\n+\n+        self.userid = ""\n+        self.password = ""\n+        self.brokerid = ""\n+\n+    def onFrontConnected(self):\n+        """\n+        Callback when front server is connected.\n+        """\n+        self.gateway.write_log("行情服务器连接成功")\n+        self.login()\n+\n+    def onFrontDisconnected(self, reason: int):\n+        """\n+        Callback when front server is disconnected.\n+        """\n+        self.login_status = False\n+        self.gateway.write_log(f"行情服务器连接断开，原因{reason}")\n+\n+    def onRspUserLogin(self, data: dict, error: dict, reqid: int, last: bool):\n+        """\n+        Callback when user is logged in.\n+        """\n+        if not error["ErrorID"]:\n+            self.login_status = True\n+            self.gateway.write_log("行情服务器登录成功")\n+\n+            for symbol in self.subscribed:\n+                self.subscribeMarketData(symbol)\n+        else:\n+            self.gateway.write_error("行情服务器登录失败", error)\n+\n+    def onRspError(self, error: dict, reqid: int, last: bool):\n+        """\n+        Callback when error occured.\n+        """\n+        self.gateway.write_error("行情接口报错", error)\n+\n+    def onRspSubMarketData(self, data: dict, error: dict, reqid: int, last: bool):\n+        """"""\n+        if not error or not error["ErrorID"]:\n+            return\n+\n+        self.gateway.write_error("行情订阅失败", error)\n+\n+    def onRtnDepthMarketData(self, data: dict):\n+        """\n+        Callback of tick data update.\n+        """\n+        symbol = data["InstrumentID"]\n+        exchange = symbol_exchange_map.get(symbol, "")\n+        if not exchange:\n+            return\n+\n+        timestamp = f"{data[\'ActionDay\']} {data[\'UpdateTime\']}.{int(data[\'UpdateMillisec\']/100)}"\n+\n+        tick = TickData(\n+            symbol=symbol,\n+            exchange=exchange,\n+            datetime=datetime.strptime(timestamp, "%Y%m%d %H:%M:%S.%f"),\n+            name=symbol_name_map[symbol],\n+            volume=data["Volume"],\n+            open_interest=data["OpenInterest"],\n+            last_price=data["LastPrice"],\n+            limit_up=data["UpperLimitPrice"],\n+            limit_down=data["LowerLimitPrice"],\n+            open_price=adjust_price(data["OpenPrice"]),\n+            high_price=adjust_price(data["HighestPrice"]),\n+            low_price=adjust_price(data["LowestPrice"]),\n+            pre_close=adjust_price(data["PreClosePrice"]),\n+            bid_price_1=adjust_price(data["BidPrice1"]),\n+            ask_price_1=adjust_price(data["AskPrice1"]),\n+            bid_volume_1=data["BidVolume1"],\n+            ask_volume_1=data["AskVolume1"],\n+            gateway_name=self.gateway_name\n+        )\n+\n+        if data["BidVolume2"] or data["AskVolume2"]:\n+            tick.bid_price_2 = adjust_price(data["BidPrice2"])\n+            tick.bid_price_3 = adjust_price(data["BidPrice3"])\n+            tick.bid_price_4 = adjust_price(data["BidPrice4"])\n+            tick.bid_price_5 = adjust_price(data["BidPrice5"])\n+\n+            tick.ask_price_2 = adjust_price(data["AskPrice2"])\n+            tick.ask_price_3 = adjust_price(data["AskPrice3"])\n+            tick.ask_price_4 = adjust_price(data["AskPrice4"])\n+            tick.ask_price_5 = adjust_price(data["AskPrice5"])\n+\n+            tick.bid_volume_2 = adjust_price(data["BidVolume2"])\n+            tick.bid_volume_3 = adjust_price(data["BidVolume3"])\n+            tick.bid_volume_4 = adjust_price(data["BidVolume4"])\n+            tick.bid_volume_5 = adjust_price(data["BidVolume5"])\n+\n+            tick.ask_volume_2 = adjust_price(data["AskVolume2"])\n+            tick.ask_volume_3 = adjust_price(data["AskVolume3"])\n+            tick.ask_volume_4 = adjust_price(data["AskVolume4"])\n+            tick.ask_volume_5 = adjust_price(data["AskVolume5"])\n+\n+        self.gateway.on_tick(tick)\n+\n+    def connect(self, address: str, userid: str, password: str, brokerid: int):\n+        """\n+        Start connection to server.\n+        """\n+        self.userid = userid\n+        self.password = password\n+        self.brokerid = brokerid\n+\n+        # If not connected, then start connection first.\n+        if not self.connect_status:\n+            path = get_folder_path(self.gateway_name.lower())\n+            self.createFtdcMdApi(str(path) + "\\\\Md")\n+\n+            self.registerFront(address)\n+            self.init()\n+\n+            self.connect_status = True\n+        # If already connected, then login immediately.\n+        elif not self.login_status:\n+            self.login()\n+\n+    def login(self):\n+        """\n+        Login onto server.\n+        """\n+        req = {\n+            "UserID": self.userid,\n+            "Password": self.password,\n+            "BrokerID": self.brokerid\n+        }\n+\n+        self.reqid += 1\n+        self.reqUserLogin(req, self.reqid)\n+\n+    def subscribe(self, req: SubscribeRequest):\n+        """\n+        Subscribe to tick data update.\n+        """\n+        if self.login_status:\n+            self.subscribeMarketData(req.symbol)\n+        self.subscribed.add(req.symbol)\n+\n+    def close(self):\n+        """\n+        Close the connection.\n+        """\n+        if self.connect_status:\n+            self.exit()\n+\n+\n+class SgitTsdApi(TdApi):\n+    """"""\n+\n+    def __init__(self, gateway):\n+        """Constructor"""\n+        super(SgitTsdApi, self).__init__()\n+\n+        self.gateway = gateway\n+        self.gateway_name = gateway.gateway_name\n+\n+        self.reqid = 0\n+        self.order_ref = 0\n+\n+        self.connect_status = False\n+        self.login_status = False\n+        self.auth_staus = False\n+        self.login_failed = False\n+\n+        self.userid = ""\n+        self.password = ""\n+        self.brokerid = ""\n+        self.auth_code = ""\n+        self.appid = ""\n+        self.product_info = ""\n+\n+        self.frontid = 0\n+        self.sessionid = 0\n+\n+        self.order_data = []\n+        self.trade_data = []\n+        self.positions = {}\n+        self.sysid_orderid_map = {}\n+\n+    def onFrontConnected(self):\n+        """"""\n+        self.gateway.write_log("交易服务器连接成功")\n+\n+        if self.auth_code:\n+            self.authenticate()\n+        else:\n+            self.login()\n+\n+    def onFrontDisconnected(self, reason: int):\n+        """"""\n+        self.login_status = False\n+        self.gateway.write_log(f"交易服务器连接断开，原因{reason}")\n+\n+    def onRspAuthenticate(self, data: dict, error: dict, reqid: int, last: bool):\n+        """"""\n+        if not error[\'ErrorID\']:\n+            self.auth_staus = True\n+            self.gateway.write_log("交易服务器授权验证成功")\n+            self.login()\n+        else:\n+            self.gateway.write_error("交易服务器授权验证失败", error)\n+\n+    def onRspUserLogin(self, data: dict, error: dict, reqid: int, last: bool):\n+        """"""\n+        if not error["ErrorID"]:\n+            self.frontid = data["FrontID"]\n+            self.sessionid = data["SessionID"]\n+            self.login_status = True\n+            self.gateway.write_log("交易服务器登录成功")\n+\n+            # Confirm settlement\n+            req = {\n+                "BrokerID": self.brokerid,\n+                "InvestorID": self.userid\n+            }\n+            self.reqid += 1\n+            self.reqSettlementInfoConfirm(req, self.reqid)\n+        else:\n+            self.login_failed = True\n+\n+            self.gateway.write_error("交易服务器登录失败", error)\n+\n+    def onRspOrderInsert(self, data: dict, error: dict, reqid: int, last: bool):\n+        """"""\n+        order_ref = data["OrderRef"]\n+        orderid = f"{self.frontid}_{self.sessionid}_{order_ref}"\n+\n+        symbol = data["InstrumentID"]\n+        exchange = symbol_exchange_map[symbol]\n+\n+        order = OrderData(\n+            symbol=symbol,\n+            exchange=exchange,\n+            orderid=orderid,\n+            direction=DIRECTION_SGIT2VT[data["Direction"]],\n+            offset=OFFSET_SGIT2VT.get(data["CombOffsetFlag"], Offset.NONE),\n+            price=data["LimitPrice"],\n+            volume=data["VolumeTotalOriginal"],\n+            status=Status.REJECTED,\n+            gateway_name=self.gateway_name\n+        )\n+        self.gateway.on_order(order)\n+\n+        self.gateway.write_error("交易委托失败", error)\n+\n+    def onRspOrderAction(self, data: dict, error: dict, reqid: int, last: bool):\n+        """"""\n+        self.gateway.write_error("交易撤单失败", error)\n+\n+    def onRspQueryMaxOrderVolume(self, data: dict, error: dict, reqid: int, last: bool):\n+        """"""\n+        pass\n+\n+    def onRspSettlementInfoConfirm(self, data: dict, error: dict, reqid: int, last: bool):\n+        """\n+        Callback of settlment info confimation.\n+        """\n+        self.gateway.write_log("结算信息确认成功")\n+\n+        self.reqid += 1\n+        self.reqQryInstrument({}, self.reqid)\n+\n+    def onRspQryInvestorPosition(self, data: dict, error: dict, reqid: int, last: bool):\n+        """"""\n+        if not data:\n+            return\n+\n+        # Check if contract data received\n+        if data["InstrumentID"] in symbol_exchange_map:\n+            # Get buffered position object\n+            key = f"{data[\'InstrumentID\'], data[\'PosiDirection\']}"\n+            position = self.positions.get(key, None)\n+            if not position:\n+                position = PositionData(\n+                    symbol=data["InstrumentID"],\n+                    exchange=symbol_exchange_map[data["InstrumentID"]],\n+                    direction=DIRECTION_SGIT2VT[data["PosiDirection"]],\n+                    gateway_name=self.gateway_name\n+                )\n+                self.positions[key] = position\n+\n+            # For SHFE and INE position data update\n+            if position.exchange in [Exchange.SHFE, Exchange.INE]:\n+                if data["YdPosition"] and not data["TodayPosition"]:\n+                    position.yd_volume = data["Position"]\n+            # For other exchange position data update\n+            else:\n+                position.yd_volume = data["Position"] - data["TodayPosition"]\n+\n+            # Get contract size (spread contract has no size value)\n+            size = symbol_size_map.get(position.symbol, 0)\n+\n+            # Calculate previous position cost\n+            cost = position.price * position.volume * size\n+\n+            # Update new position volume\n+            position.volume += data["Position"]\n+            position.pnl += data["PositionProfit"]\n+\n+            # Calculate average position price\n+            if position.volume and size:\n+                cost += data["PositionCost"]\n+                position.price = cost / (position.volume * size)\n+\n+            # Get frozen volume\n+            if position.direction == Direction.LONG:\n+                position.frozen += data["ShortFrozen"]\n+            else:\n+                position.frozen += data["LongFrozen"]\n+\n+        if last:\n+            for position in self.positions.values():\n+                self.gateway.on_position(position)\n+\n+            self.positions.clear()\n+\n+    def onRspQryTradingAccount(self, data: dict, error: dict, reqid: int, last: bool):\n+        """"""\n+        if "AccountID" not in data:\n+            return\n+\n+        account = AccountData(\n+            accountid=data["AccountID"],\n+            balance=data["Balance"],\n+            frozen=data["FrozenMargin"] + data["FrozenCash"] + data["FrozenCommission"],\n+            gateway_name=self.gateway_name\n+        )\n+        account.available = data["Available"]\n+\n+        self.gateway.on_account(account)\n+\n+    def onRspQryInstrument(self, data: dict, error: dict, reqid: int, last: bool):\n+        """\n+        Callback of instrument query.\n+        """\n+        product = PRODUCT_SGIT2VT.get(data["ProductClass"], None)\n+        if product:\n+            contract = ContractData(\n+                symbol=data["InstrumentID"],\n+                exchange=EXCHANGE_SGIT2VT[data["ExchangeID"]],\n+                name=data["InstrumentName"],\n+                product=product,\n+                size=data["VolumeMultiple"],\n+                pricetick=data["PriceTick"],\n+                gateway_name=self.gateway_name\n+            )\n+\n+            # For option only\n+            if contract.product == Product.OPTION:\n+                # Remove C/P suffix of CZCE option product name\n+                if contract.exchange == Exchange.CZCE:\n+                    contract.option_portfolio = data["ProductID"][:-1]\n+                else:\n+                    contract.option_portfolio = data["ProductID"]\n+\n+                contract.option_underlying = data["UnderlyingInstrID"]\n+                contract.option_type = OPTIONTYPE_SGIT2VT.get(data["OptionsType"], None)\n+                contract.option_strike = data["StrikePrice"]\n+                contract.option_index = str(data["StrikePrice"])\n+                contract.option_expiry = datetime.strptime(data["ExpireDate"], "%Y%m%d")\n+\n+            self.gateway.on_contract(contract)\n+\n+            symbol_exchange_map[contract.symbol] = contract.exchange\n+            symbol_name_map[contract.symbol] = contract.name\n+            symbol_size_map[contract.symbol] = contract.size\n+\n+        if last:\n+            self.gateway.write_log("合约信息查询成功")\n+\n+            for data in self.order_data:\n+                self.onRtnOrder(data)\n+            self.order_data.clear()\n+\n+            for data in self.trade_data:\n+                self.onRtnTrade(data)\n+            self.trade_data.clear()\n+\n+    def onRtnOrder(self, data: dict):\n+        """\n+        Callback of order status update.\n+        """\n+        symbol = data["InstrumentID"]\n+        exchange = symbol_exchange_map.get(symbol, "")\n+        if not exchange:\n+            self.order_data.append(data)\n+            return\n+\n+        frontid = data["FrontID"]\n+        sessionid = data["SessionID"]\n+        order_ref = data["OrderRef"]\n+        orderid = f"{frontid}_{sessionid}_{order_ref}"\n+\n+        order = OrderData(\n+            symbol=symbol,\n+            exchange=exchange,\n+            orderid=orderid,\n+            type=ORDERTYPE_SGIT2VT[data["OrderPriceType"]],\n+            direction=DIRECTION_SGIT2VT[data["Direction"]],\n+            offset=OFFSET_SGIT2VT[data["CombOffsetFlag"]],\n+            price=data["LimitPrice"],\n+            volume=data["VolumeTotalOriginal"],\n+            traded=data["VolumeTraded"],\n+            status=STATUS_SGIT2VT[data["OrderStatus"]],\n+            time=data["InsertTime"],\n+            gateway_name=self.gateway_name\n+        )\n+        self.gateway.on_order(order)\n+\n+        self.sysid_orderid_map[data["OrderSysID"]] = orderid\n+\n+    def onRtnTrade(self, data: dict):\n+        """\n+        Callback of trade status update.\n+        """\n+        symbol = data["InstrumentID"]\n+        exchange = symbol_exchange_map.get(symbol, "")\n+        if not exchange:\n+            self.trade_data.append(data)\n+            return\n+\n+        orderid = self.sysid_orderid_map[data["OrderSysID"]]\n+\n+        trade = TradeData(\n+            symbol=symbol,\n+            exchange=exchange,\n+            orderid=orderid,\n+            tradeid=data["TradeID"],\n+            direction=DIRECTION_SGIT2VT[data["Direction"]],\n+            offset=OFFSET_SGIT2VT[data["OffsetFlag"]],\n+            price=data["Price"],\n+            volume=data["Volume"],\n+            time=data["TradeTime"],\n+            gateway_name=self.gateway_name\n+        )\n+        self.gateway.on_trade(trade)\n+\n+    def connect(\n+        self,\n+        address: str,\n+        userid: str,\n+        password: str,\n+        brokerid: int,\n+        auth_code: str,\n+        appid: str,\n+        product_info\n+    ):\n+        """\n+        Start connection to server.\n+        """\n+        self.userid = userid\n+        self.password = password\n+        self.brokerid = brokerid\n+        self.auth_code = auth_code\n+        self.appid = appid\n+        self.product_info = product_info\n+\n+        if not self.connect_status:\n+            path = get_folder_path(self.gateway_name.lower())\n+            self.createFtdcTraderApi(str(path) + "\\\\Td")\n+\n+            self.subscribePrivateTopic(0)\n+            self.subscribePublicTopic(0)\n+\n+            self.registerFront(address)\n+            self.init()\n+\n+            self.connect_status = True\n+        else:\n+            self.authenticate()\n+\n+    def authenticate(self):\n+        """\n+        Authenticate with auth_code and appid.\n+        """\n+        req = {\n+            "UserID": self.userid,\n+            "BrokerID": self.brokerid,\n+            "AuthCode": self.auth_code,\n+            "AppID": self.appid\n+        }\n+\n+        if self.product_info:\n+            req["UserProductInfo"] = self.product_info\n+\n+        self.reqid += 1\n+        self.reqAuthenticate(req, self.reqid)\n+\n+    def login(self):\n+        """\n+        Login onto server.\n+        """\n+        if self.login_failed:\n+            return\n+\n+        req = {\n+            "UserID": self.userid,\n+            "Password": self.password,\n+            "BrokerID": self.brokerid,\n+            "AppID": self.appid\n+        }\n+\n+        if self.product_info:\n+            req["UserProductInfo"] = self.product_info\n+\n+        self.reqid += 1\n+        self.reqUserLogin(req, self.reqid)\n+\n+    def send_order(self, req: OrderRequest) -> str:\n+        """\n+        Send new order.\n+        """\n+        if req.offset not in OFFSET_VT2SGIT:\n+            self.gateway.write_log("请选择开平方向")\n+            return ""\n+\n+        self.order_ref += 1\n+\n+        ctp_req = {\n+            "InstrumentID": req.symbol,\n+            "ExchangeID": req.exchange.value,\n+            "LimitPrice": req.price,\n+            "VolumeTotalOriginal": int(req.volume),\n+            "OrderPriceType": ORDERTYPE_VT2SGIT.get(req.type, ""),\n+            "Direction": DIRECTION_VT2SGIT.get(req.direction, ""),\n+            "CombOffsetFlag": OFFSET_VT2SGIT.get(req.offset, ""),\n+            "OrderRef": str(self.order_ref),\n+            "InvestorID": self.userid,\n+            "UserID": self.userid,\n+            "BrokerID": self.brokerid,\n+            "CombHedgeFlag": THOST_FTDC_HF_Speculation,\n+            "ContingentCondition": THOST_FTDC_CC_Immediately,\n+            "ForceCloseReason": THOST_FTDC_FCC_NotForceClose,\n+            "IsAutoSuspend": 0,\n+            "TimeCondition": THOST_FTDC_TC_GFD,\n+            "VolumeCondition": THOST_FTDC_VC_AV,\n+            "MinVolume": 1\n+        }\n+\n+        if req.type == OrderType.FAK:\n+            ctp_req["OrderPriceType"] = THOST_FTDC_OPT_LimitPrice\n+            ctp_req["TimeCondition"] = THOST_FTDC_TC_IOC\n+            ctp_req["VolumeCondition"] = THOST_FTDC_VC_AV\n+        elif req.type == OrderType.FOK:\n+            ctp_req["OrderPriceType"] = THOST_FTDC_OPT_LimitPrice\n+            ctp_req["TimeCondition"] = THOST_FTDC_TC_IOC\n+            ctp_req["VolumeCondition"] = THOST_FTDC_VC_CV\n+\n+        self.reqid += 1\n+        self.reqOrderInsert(ctp_req, self.reqid)\n+\n+        orderid = f"{self.frontid}_{self.sessionid}_{self.order_ref}"\n+        order = req.create_order_data(orderid, self.gateway_name)\n+        self.gateway.on_order(order)\n+\n+        return order.vt_orderid\n+\n+    def cancel_order(self, req: CancelRequest):\n+        """\n+        Cancel existing order.\n+        """\n+        frontid, sessionid, order_ref = req.orderid.split("_")\n+\n+        ctp_req = {\n+            "InstrumentID": req.symbol,\n+            "ExchangeID": req.exchange.value,\n+            "OrderRef": order_ref,\n+            "FrontID": int(frontid),\n+            "SessionID": int(sessionid),\n+            "ActionFlag": THOST_FTDC_AF_Delete,\n+            "BrokerID": self.brokerid,\n+            "InvestorID": self.userid\n+        }\n+\n+        self.reqid += 1\n+        self.reqOrderAction(ctp_req, self.reqid)\n+\n+    def query_account(self):\n+        """\n+        Query account balance data.\n+        """\n+        self.reqid += 1\n+        self.reqQryTradingAccount({}, self.reqid)\n+\n+    def query_position(self):\n+        """\n+        Query position holding data.\n+        """\n+        if not symbol_exchange_map:\n+            return\n+\n+        req = {\n+            "BrokerID": self.brokerid,\n+            "InvestorID": self.userid\n+        }\n+\n+        self.reqid += 1\n+        self.reqQryInvestorPosition(req, self.reqid)\n+\n+    def close(self):\n+        """"""\n+        if self.connect_status:\n+            self.exit()\n+\n+\n+def adjust_price(price: float) -> float:\n+    """"""\n+    if price == MAX_FLOAT:\n+        price = 0\n+    return price\n', 'commit_subject': 'Merge pull request #2335 from 1122455801/SgitGateway00', 'repo_name': 'vnpy/vnpy', 'committer': {'name': 'GitHub', 'email': '1505422b2465e9a84f6fdfaa161078890c593f06@github.com', 'time_sec': '1581252330', 'tz_offset': '480', 'date': {'seconds': '1581252330'}}, 'commit_tree': '99808f0113c12aae8e329f103921aeb8a01d93df', 'commit_message': 'Merge pull request #2335 from 1122455801/SgitGateway00\n\n[Mod] add vnpy.api.sgit', 'language_name': 'Python', 'license': 'mit', 'hunks': '@@ -0,0 +1,859 @@\n+"""\n+"""\n+\n+import sys\n+from datetime import datetime\n+from typing import Dict, List\n+\n+from vnpy.api.sgit import (\n+    MdApi,\n+    TdApi,\n+    THOST_FTDC_OAS_Submitted,\n+    THOST_FTDC_OAS_Accepted,\n+    THOST_FTDC_OAS_Rejected,\n+    THOST_FTDC_OST_NoTradeQueueing,\n+    THOST_FTDC_OST_PartTradedQueueing,\n+    THOST_FTDC_OST_AllTraded,\n+    THOST_FTDC_OST_Canceled,\n+    THOST_FTDC_D_Buy,\n+    THOST_FTDC_D_Sell,\n+    THOST_FTDC_PD_Long,\n+    THOST_FTDC_PD_Short,\n+    THOST_FTDC_OPT_LimitPrice,\n+    THOST_FTDC_OPT_AnyPrice,\n+    THOST_FTDC_OF_Open,\n+    THOST_FTDC_OFEN_Close,\n+    THOST_FTDC_OFEN_CloseYesterday,\n+    THOST_FTDC_OFEN_CloseToday,\n+    THOST_FTDC_PC_Futures,\n+    THOST_FTDC_PC_Options,\n+    THOST_FTDC_PC_SpotOption,\n+    THOST_FTDC_PC_Combination,\n+    THOST_FTDC_CP_CallOptions,\n+    THOST_FTDC_CP_PutOptions,\n+    THOST_FTDC_HF_Speculation,\n+    THOST_FTDC_CC_Immediately,\n+    THOST_FTDC_FCC_NotForceClose,\n+    THOST_FTDC_TC_GFD,\n+    THOST_FTDC_VC_AV,\n+    THOST_FTDC_TC_IOC,\n+    THOST_FTDC_VC_CV,\n+    THOST_FTDC_AF_Delete\n+)\n+from vnpy.trader.constant import (\n+    Direction,\n+    Offset,\n+    Exchange,\n+    OrderType,\n+    Product,\n+    Status,\n+    OptionType\n+)\n+from vnpy.trader.gateway import BaseGateway\n+from vnpy.trader.object import (\n+    TickData,\n+    OrderData,\n+    TradeData,\n+    PositionData,\n+    AccountData,\n+    ContractData,\n+    OrderRequest,\n+    CancelRequest,\n+    SubscribeRequest,\n+)\n+from vnpy.trader.utility import get_folder_path\n+from vnpy.trader.event import EVENT_TIMER\n+\n+\n+STATUS_SGIT2VT: Dict[str, Status] = {\n+    THOST_FTDC_OAS_Submitted: Status.SUBMITTING,\n+    THOST_FTDC_OAS_Accepted: Status.SUBMITTING,\n+    THOST_FTDC_OAS_Rejected: Status.REJECTED,\n+    THOST_FTDC_OST_NoTradeQueueing: Status.NOTTRADED,\n+    THOST_FTDC_OST_PartTradedQueueing: Status.PARTTRADED,\n+    THOST_FTDC_OST_AllTraded: Status.ALLTRADED,\n+    THOST_FTDC_OST_Canceled: Status.CANCELLED\n+}\n+\n+DIRECTION_VT2SGIT: Dict[Direction, str] = {\n+    Direction.LONG: THOST_FTDC_D_Buy,\n+    Direction.SHORT: THOST_FTDC_D_Sell\n+}\n+DIRECTION_SGIT2VT: Dict[str, Direction] = {v: k for k, v in DIRECTION_VT2SGIT.items()}\n+DIRECTION_SGIT2VT[THOST_FTDC_PD_Long] = Direction.LONG\n+DIRECTION_SGIT2VT[THOST_FTDC_PD_Short] = Direction.SHORT\n+\n+ORDERTYPE_VT2SGIT: Dict[OrderType, str] = {\n+    OrderType.LIMIT: THOST_FTDC_OPT_LimitPrice,\n+    OrderType.MARKET: THOST_FTDC_OPT_AnyPrice\n+}\n+ORDERTYPE_SGIT2VT: Dict[str, OrderType] = {v: k for k, v in ORDERTYPE_VT2SGIT.items()}\n+\n+OFFSET_VT2SGIT: Dict[Offset, str] = {\n+    Offset.OPEN: THOST_FTDC_OF_Open,\n+    Offset.CLOSE: THOST_FTDC_OFEN_Close,\n+    Offset.CLOSETODAY: THOST_FTDC_OFEN_CloseToday,\n+    Offset.CLOSEYESTERDAY: THOST_FTDC_OFEN_CloseYesterday,\n+}\n+OFFSET_SGIT2VT: Dict[str, Offset] = {v: k for k, v in OFFSET_VT2SGIT.items()}\n+\n+EXCHANGE_SGIT2VT: Dict[str, Exchange] = {\n+    "CFFEX": Exchange.CFFEX,\n+    "SHFE": Exchange.SHFE,\n+    "CZCE": Exchange.CZCE,\n+    "DCE": Exchange.DCE,\n+    "INE": Exchange.INE\n+}\n+\n+PRODUCT_SGIT2VT: Dict[str, Product] = {\n+    THOST_FTDC_PC_Futures: Product.FUTURES,\n+    THOST_FTDC_PC_Options: Product.OPTION,\n+    THOST_FTDC_PC_SpotOption: Product.OPTION,\n+    THOST_FTDC_PC_Combination: Product.SPREAD\n+}\n+\n+OPTIONTYPE_SGIT2VT: Dict[str, OptionType] = {\n+    THOST_FTDC_CP_CallOptions: OptionType.CALL,\n+    THOST_FTDC_CP_PutOptions: OptionType.PUT\n+}\n+\n+MAX_FLOAT: float = sys.float_info.max\n+\n+\n+symbol_exchange_map: Dict = {}\n+symbol_name_map: Dict = {}\n+symbol_size_map: Dict = {}\n+\n+\n+class SgitGateway(BaseGateway):\n+    """\n+    VN Trader Gateway for CTP .\n+    """\n+\n+    default_setting: Dict[str, str] = {\n+        "用户名": "",\n+        "密码": "",\n+        "经纪商代码": "",\n+        "交易服务器": "",\n+        "行情服务器": "",\n+        "产品名称": "",\n+        "授权编码": "",\n+        "产品信息": ""\n+    }\n+\n+    exchanges: List[Exchange] = list(EXCHANGE_SGIT2VT.values())\n+\n+    def __init__(self, event_engine):\n+        """Constructor"""\n+        super().__init__(event_engine, "CTP")\n+\n+        self.td_api = SgitTsdApi(self)\n+        self.md_api = SgitMdApi(self)\n+\n+    def connect(self, setting: dict) -> None:\n+        """"""\n+        userid = setting["用户名"]\n+        password = setting["密码"]\n+        brokerid = setting["经纪商代码"]\n+        td_address = setting["交易服务器"]\n+        md_address = setting["行情服务器"]\n+        appid = setting["产品名称"]\n+        auth_code = setting["授权编码"]\n+        product_info = setting["产品信息"]\n+\n+        if (\n+            (not td_address.startswith("tcp://"))\n+            and (not td_address.startswith("ssl://"))\n+        ):\n+            td_address = "tcp://" + td_address\n+\n+        if (\n+            (not md_address.startswith("tcp://"))\n+            and (not md_address.startswith("ssl://"))\n+        ):\n+            md_address = "tcp://" + md_address\n+\n+        self.td_api.connect(td_address, userid, password, brokerid, auth_code, appid, product_info)\n+        self.md_api.connect(md_address, userid, password, brokerid)\n+\n+        self.init_query()\n+\n+    def subscribe(self, req: SubscribeRequest) -> None:\n+        """"""\n+        self.md_api.subscribe(req)\n+\n+    def send_order(self, req: OrderRequest) -> str:\n+        """"""\n+        return self.td_api.send_order(req)\n+\n+    def cancel_order(self, req: CancelRequest) -> None:\n+        """"""\n+        self.td_api.cancel_order(req)\n+\n+    def query_account(self) -> None:\n+        """"""\n+        self.td_api.query_account()\n+\n+    def query_position(self) -> None:\n+        """"""\n+        self.td_api.query_position()\n+\n+    def close(self) -> None:\n+        """"""\n+        self.td_api.close()\n+        self.md_api.close()\n+\n+    def write_error(self, msg: str, error: dict) -> None:\n+        """"""\n+        error_id = error["ErrorID"]\n+        error_msg = error["ErrorMsg"]\n+        msg = f"{msg}，代码：{error_id}，信息：{error_msg}"\n+        self.write_log(msg)\n+\n+    def process_timer_event(self, event) -> None:\n+        """"""\n+        self.count += 1\n+        if self.count < 2:\n+            return\n+        self.count = 0\n+\n+        func = self.query_functions.pop(0)\n+        func()\n+        self.query_functions.append(func)\n+\n+    def init_query(self) -> None:\n+        """"""\n+        self.count = 0\n+        self.query_functions = [self.query_account, self.query_position]\n+        self.event_engine.register(EVENT_TIMER, self.process_timer_event)\n+\n+\n+class SgitMdApi(MdApi):\n+    """"""\n+\n+    def __init__(self, gateway):\n+        """Constructor"""\n+        super(SgitMdApi, self).__init__()\n+\n+        self.gateway = gateway\n+        self.gateway_name = gateway.gateway_name\n+\n+        self.reqid = 0\n+\n+        self.connect_status = False\n+        self.login_status = False\n+        self.subscribed = set()\n+\n+        self.userid = ""\n+        self.password = ""\n+        self.brokerid = ""\n+\n+    def onFrontConnected(self):\n+        """\n+        Callback when front server is connected.\n+        """\n+        self.gateway.write_log("行情服务器连接成功")\n+        self.login()\n+\n+    def onFrontDisconnected(self, reason: int):\n+        """\n+        Callback when front server is disconnected.\n+        """\n+        self.login_status = False\n+        self.gateway.write_log(f"行情服务器连接断开，原因{reason}")\n+\n+    def onRspUserLogin(self, data: dict, error: dict, reqid: int, last: bool):\n+        """\n+        Callback when user is logged in.\n+        """\n+        if not error["ErrorID"]:\n+            self.login_status = True\n+            self.gateway.write_log("行情服务器登录成功")\n+\n+            for symbol in self.subscribed:\n+                self.subscribeMarketData(symbol)\n+        else:\n+            self.gateway.write_error("行情服务器登录失败", error)\n+\n+    def onRspError(self, error: dict, reqid: int, last: bool):\n+        """\n+        Callback when error occured.\n+        """\n+        self.gateway.write_error("行情接口报错", error)\n+\n+    def onRspSubMarketData(self, data: dict, error: dict, reqid: int, last: bool):\n+        """"""\n+        if not error or not error["ErrorID"]:\n+            return\n+\n+        self.gateway.write_error("行情订阅失败", error)\n+\n+    def onRtnDepthMarketData(self, data: dict):\n+        """\n+        Callback of tick data update.\n+        """\n+        symbol = data["InstrumentID"]\n+        exchange = symbol_exchange_map.get(symbol, "")\n+        if not exchange:\n+            return\n+\n+        timestamp = f"{data[\'ActionDay\']} {data[\'UpdateTime\']}.{int(data[\'UpdateMillisec\']/100)}"\n+\n+        tick = TickData(\n+            symbol=symbol,\n+            exchange=exchange,\n+            datetime=datetime.strptime(timestamp, "%Y%m%d %H:%M:%S.%f"),\n+            name=symbol_name_map[symbol],\n+            volume=data["Volume"],\n+            open_interest=data["OpenInterest"],\n+            last_price=data["LastPrice"],\n+            limit_up=data["UpperLimitPrice"],\n+            limit_down=data["LowerLimitPrice"],\n+            open_price=adjust_price(data["OpenPrice"]),\n+            high_price=adjust_price(data["HighestPrice"]),\n+            low_price=adjust_price(data["LowestPrice"]),\n+            pre_close=adjust_price(data["PreClosePrice"]),\n+            bid_price_1=adjust_price(data["BidPrice1"]),\n+            ask_price_1=adjust_price(data["AskPrice1"]),\n+            bid_volume_1=data["BidVolume1"],\n+            ask_volume_1=data["AskVolume1"],\n+            gateway_name=self.gateway_name\n+        )\n+\n+        if data["BidVolume2"] or data["AskVolume2"]:\n+            tick.bid_price_2 = adjust_price(data["BidPrice2"])\n+            tick.bid_price_3 = adjust_price(data["BidPrice3"])\n+            tick.bid_price_4 = adjust_price(data["BidPrice4"])\n+            tick.bid_price_5 = adjust_price(data["BidPrice5"])\n+\n+            tick.ask_price_2 = adjust_price(data["AskPrice2"])\n+            tick.ask_price_3 = adjust_price(data["AskPrice3"])\n+            tick.ask_price_4 = adjust_price(data["AskPrice4"])\n+            tick.ask_price_5 = adjust_price(data["AskPrice5"])\n+\n+            tick.bid_volume_2 = adjust_price(data["BidVolume2"])\n+            tick.bid_volume_3 = adjust_price(data["BidVolume3"])\n+            tick.bid_volume_4 = adjust_price(data["BidVolume4"])\n+            tick.bid_volume_5 = adjust_price(data["BidVolume5"])\n+\n+            tick.ask_volume_2 = adjust_price(data["AskVolume2"])\n+            tick.ask_volume_3 = adjust_price(data["AskVolume3"])\n+            tick.ask_volume_4 = adjust_price(data["AskVolume4"])\n+            tick.ask_volume_5 = adjust_price(data["AskVolume5"])\n+\n+        self.gateway.on_tick(tick)\n+\n+    def connect(self, address: str, userid: str, password: str, brokerid: int):\n+        """\n+        Start connection to server.\n+        """\n+        self.userid = userid\n+        self.password = password\n+        self.brokerid = brokerid\n+\n+        # If not connected, then start connection first.\n+        if not self.connect_status:\n+            path = get_folder_path(self.gateway_name.lower())\n+            self.createFtdcMdApi(str(path) + "\\\\Md")\n+\n+            self.registerFront(address)\n+            self.init()\n+\n+            self.connect_status = True\n+        # If already connected, then login immediately.\n+        elif not self.login_status:\n+            self.login()\n+\n+    def login(self):\n+        """\n+        Login onto server.\n+        """\n+        req = {\n+            "UserID": self.userid,\n+            "Password": self.password,\n+            "BrokerID": self.brokerid\n+        }\n+\n+        self.reqid += 1\n+        self.reqUserLogin(req, self.reqid)\n+\n+    def subscribe(self, req: SubscribeRequest):\n+        """\n+        Subscribe to tick data update.\n+        """\n+        if self.login_status:\n+            self.subscribeMarketData(req.symbol)\n+        self.subscribed.add(req.symbol)\n+\n+    def close(self):\n+        """\n+        Close the connection.\n+        """\n+        if self.connect_status:\n+            self.exit()\n+\n+\n+class SgitTsdApi(TdApi):\n+    """"""\n+\n+    def __init__(self, gateway):\n+        """Constructor"""\n+        super(SgitTsdApi, self).__init__()\n+\n+        self.gateway = gateway\n+        self.gateway_name = gateway.gateway_name\n+\n+        self.reqid = 0\n+        self.order_ref = 0\n+\n+        self.connect_status = False\n+        self.login_status = False\n+        self.auth_staus = False\n+        self.login_failed = False\n+\n+        self.userid = ""\n+        self.password = ""\n+        self.brokerid = ""\n+        self.auth_code = ""\n+        self.appid = ""\n+        self.product_info = ""\n+\n+        self.frontid = 0\n+        self.sessionid = 0\n+\n+        self.order_data = []\n+        self.trade_data = []\n+        self.positions = {}\n+        self.sysid_orderid_map = {}\n+\n+    def onFrontConnected(self):\n+        """"""\n+        self.gateway.write_log("交易服务器连接成功")\n+\n+        if self.auth_code:\n+            self.authenticate()\n+        else:\n+            self.login()\n+\n+    def onFrontDisconnected(self, reason: int):\n+        """"""\n+        self.login_status = False\n+        self.gateway.write_log(f"交易服务器连接断开，原因{reason}")\n+\n+    def onRspAuthenticate(self, data: dict, error: dict, reqid: int, last: bool):\n+        """"""\n+        if not error[\'ErrorID\']:\n+            self.auth_staus = True\n+            self.gateway.write_log("交易服务器授权验证成功")\n+            self.login()\n+        else:\n+            self.gateway.write_error("交易服务器授权验证失败", error)\n+\n+    def onRspUserLogin(self, data: dict, error: dict, reqid: int, last: bool):\n+        """"""\n+        if not error["ErrorID"]:\n+            self.frontid = data["FrontID"]\n+            self.sessionid = data["SessionID"]\n+            self.login_status = True\n+            self.gateway.write_log("交易服务器登录成功")\n+\n+            # Confirm settlement\n+            req = {\n+                "BrokerID": self.brokerid,\n+                "InvestorID": self.userid\n+            }\n+            self.reqid += 1\n+            self.reqSettlementInfoConfirm(req, self.reqid)\n+        else:\n+            self.login_failed = True\n+\n+            self.gateway.write_error("交易服务器登录失败", error)\n+\n+    def onRspOrderInsert(self, data: dict, error: dict, reqid: int, last: bool):\n+        """"""\n+        order_ref = data["OrderRef"]\n+        orderid = f"{self.frontid}_{self.sessionid}_{order_ref}"\n+\n+        symbol = data["InstrumentID"]\n+        exchange = symbol_exchange_map[symbol]\n+\n+        order = OrderData(\n+            symbol=symbol,\n+            exchange=exchange,\n+            orderid=orderid,\n+            direction=DIRECTION_SGIT2VT[data["Direction"]],\n+            offset=OFFSET_SGIT2VT.get(data["CombOffsetFlag"], Offset.NONE),\n+            price=data["LimitPrice"],\n+            volume=data["VolumeTotalOriginal"],\n+            status=Status.REJECTED,\n+            gateway_name=self.gateway_name\n+        )\n+        self.gateway.on_order(order)\n+\n+        self.gateway.write_error("交易委托失败", error)\n+\n+    def onRspOrderAction(self, data: dict, error: dict, reqid: int, last: bool):\n+        """"""\n+        self.gateway.write_error("交易撤单失败", error)\n+\n+    def onRspQueryMaxOrderVolume(self, data: dict, error: dict, reqid: int, last: bool):\n+        """"""\n+        pass\n+\n+    def onRspSettlementInfoConfirm(self, data: dict, error: dict, reqid: int, last: bool):\n+        """\n+        Callback of settlment info confimation.\n+        """\n+        self.gateway.write_log("结算信息确认成功")\n+\n+        self.reqid += 1\n+        self.reqQryInstrument({}, self.reqid)\n+\n+    def onRspQryInvestorPosition(self, data: dict, error: dict, reqid: int, last: bool):\n+        """"""\n+        if not data:\n+            return\n+\n+        # Check if contract data received\n+        if data["InstrumentID"] in symbol_exchange_map:\n+            # Get buffered position object\n+            key = f"{data[\'InstrumentID\'], data[\'PosiDirection\']}"\n+            position = self.positions.get(key, None)\n+            if not position:\n+                position = PositionData(\n+                    symbol=data["InstrumentID"],\n+                    exchange=symbol_exchange_map[data["InstrumentID"]],\n+                    direction=DIRECTION_SGIT2VT[data["PosiDirection"]],\n+                    gateway_name=self.gateway_name\n+                )\n+                self.positions[key] = position\n+\n+            # For SHFE and INE position data update\n+            if position.exchange in [Exchange.SHFE, Exchange.INE]:\n+                if data["YdPosition"] and not data["TodayPosition"]:\n+                    position.yd_volume = data["Position"]\n+            # For other exchange position data update\n+            else:\n+                position.yd_volume = data["Position"] - data["TodayPosition"]\n+\n+            # Get contract size (spread contract has no size value)\n+            size = symbol_size_map.get(position.symbol, 0)\n+\n+            # Calculate previous position cost\n+            cost = position.price * position.volume * size\n+\n+            # Update new position volume\n+            position.volume += data["Position"]\n+            position.pnl += data["PositionProfit"]\n+\n+            # Calculate average position price\n+            if position.volume and size:\n+                cost += data["PositionCost"]\n+                position.price = cost / (position.volume * size)\n+\n+            # Get frozen volume\n+            if position.direction == Direction.LONG:\n+                position.frozen += data["ShortFrozen"]\n+            else:\n+                position.frozen += data["LongFrozen"]\n+\n+        if last:\n+            for position in self.positions.values():\n+                self.gateway.on_position(position)\n+\n+            self.positions.clear()\n+\n+    def onRspQryTradingAccount(self, data: dict, error: dict, reqid: int, last: bool):\n+        """"""\n+        if "AccountID" not in data:\n+            return\n+\n+        account = AccountData(\n+            accountid=data["AccountID"],\n+            balance=data["Balance"],\n+            frozen=data["FrozenMargin"] + data["FrozenCash"] + data["FrozenCommission"],\n+            gateway_name=self.gateway_name\n+        )\n+        account.available = data["Available"]\n+\n+        self.gateway.on_account(account)\n+\n+    def onRspQryInstrument(self, data: dict, error: dict, reqid: int, last: bool):\n+        """\n+        Callback of instrument query.\n+        """\n+        product = PRODUCT_SGIT2VT.get(data["ProductClass"], None)\n+        if product:\n+            contract = ContractData(\n+                symbol=data["InstrumentID"],\n+                exchange=EXCHANGE_SGIT2VT[data["ExchangeID"]],\n+                name=data["InstrumentName"],\n+                product=product,\n+                size=data["VolumeMultiple"],\n+                pricetick=data["PriceTick"],\n+                gateway_name=self.gateway_name\n+            )\n+\n+            # For option only\n+            if contract.product == Product.OPTION:\n+                # Remove C/P suffix of CZCE option product name\n+                if contract.exchange == Exchange.CZCE:\n+                    contract.option_portfolio = data["ProductID"][:-1]\n+                else:\n+                    contract.option_portfolio = data["ProductID"]\n+\n+                contract.option_underlying = data["UnderlyingInstrID"]\n+                contract.option_type = OPTIONTYPE_SGIT2VT.get(data["OptionsType"], None)\n+                contract.option_strike = data["StrikePrice"]\n+                contract.option_index = str(data["StrikePrice"])\n+                contract.option_expiry = datetime.strptime(data["ExpireDate"], "%Y%m%d")\n+\n+            self.gateway.on_contract(contract)\n+\n+            symbol_exchange_map[contract.symbol] = contract.exchange\n+            symbol_name_map[contract.symbol] = contract.name\n+            symbol_size_map[contract.symbol] = contract.size\n+\n+        if last:\n+            self.gateway.write_log("合约信息查询成功")\n+\n+            for data in self.order_data:\n+                self.onRtnOrder(data)\n+            self.order_data.clear()\n+\n+            for data in self.trade_data:\n+                self.onRtnTrade(data)\n+            self.trade_data.clear()\n+\n+    def onRtnOrder(self, data: dict):\n+        """\n+        Callback of order status update.\n+        """\n+        symbol = data["InstrumentID"]\n+        exchange = symbol_exchange_map.get(symbol, "")\n+        if not exchange:\n+            self.order_data.append(data)\n+            return\n+\n+        frontid = data["FrontID"]\n+        sessionid = data["SessionID"]\n+        order_ref = data["OrderRef"]\n+        orderid = f"{frontid}_{sessionid}_{order_ref}"\n+\n+        order = OrderData(\n+            symbol=symbol,\n+            exchange=exchange,\n+            orderid=orderid,\n+            type=ORDERTYPE_SGIT2VT[data["OrderPriceType"]],\n+            direction=DIRECTION_SGIT2VT[data["Direction"]],\n+            offset=OFFSET_SGIT2VT[data["CombOffsetFlag"]],\n+            price=data["LimitPrice"],\n+            volume=data["VolumeTotalOriginal"],\n+            traded=data["VolumeTraded"],\n+            status=STATUS_SGIT2VT[data["OrderStatus"]],\n+            time=data["InsertTime"],\n+            gateway_name=self.gateway_name\n+        )\n+        self.gateway.on_order(order)\n+\n+        self.sysid_orderid_map[data["OrderSysID"]] = orderid\n+\n+    def onRtnTrade(self, data: dict):\n+        """\n+        Callback of trade status update.\n+        """\n+        symbol = data["InstrumentID"]\n+        exchange = symbol_exchange_map.get(symbol, "")\n+        if not exchange:\n+            self.trade_data.append(data)\n+            return\n+\n+        orderid = self.sysid_orderid_map[data["OrderSysID"]]\n+\n+        trade = TradeData(\n+            symbol=symbol,\n+            exchange=exchange,\n+            orderid=orderid,\n+            tradeid=data["TradeID"],\n+            direction=DIRECTION_SGIT2VT[data["Direction"]],\n+            offset=OFFSET_SGIT2VT[data["OffsetFlag"]],\n+            price=data["Price"],\n+            volume=data["Volume"],\n+            time=data["TradeTime"],\n+            gateway_name=self.gateway_name\n+        )\n+        self.gateway.on_trade(trade)\n+\n+    def connect(\n+        self,\n+        address: str,\n+        userid: str,\n+        password: str,\n+        brokerid: int,\n+        auth_code: str,\n+        appid: str,\n+        product_info\n+    ):\n+        """\n+        Start connection to server.\n+        """\n+        self.userid = userid\n+        self.password = password\n+        self.brokerid = brokerid\n+        self.auth_code = auth_code\n+        self.appid = appid\n+        self.product_info = product_info\n+\n+        if not self.connect_status:\n+            path = get_folder_path(self.gateway_name.lower())\n+            self.createFtdcTraderApi(str(path) + "\\\\Td")\n+\n+            self.subscribePrivateTopic(0)\n+            self.subscribePublicTopic(0)\n+\n+            self.registerFront(address)\n+            self.init()\n+\n+            self.connect_status = True\n+        else:\n+            self.authenticate()\n+\n+    def authenticate(self):\n+        """\n+        Authenticate with auth_code and appid.\n+        """\n+        req = {\n+            "UserID": self.userid,\n+            "BrokerID": self.brokerid,\n+            "AuthCode": self.auth_code,\n+            "AppID": self.appid\n+        }\n+\n+        if self.product_info:\n+            req["UserProductInfo"] = self.product_info\n+\n+        self.reqid += 1\n+        self.reqAuthenticate(req, self.reqid)\n+\n+    def login(self):\n+        """\n+        Login onto server.\n+        """\n+        if self.login_failed:\n+            return\n+\n+        req = {\n+            "UserID": self.userid,\n+            "Password": self.password,\n+            "BrokerID": self.brokerid,\n+            "AppID": self.appid\n+        }\n+\n+        if self.product_info:\n+            req["UserProductInfo"] = self.product_info\n+\n+        self.reqid += 1\n+        self.reqUserLogin(req, self.reqid)\n+\n+    def send_order(self, req: OrderRequest) -> str:\n+        """\n+        Send new order.\n+        """\n+        if req.offset not in OFFSET_VT2SGIT:\n+            self.gateway.write_log("请选择开平方向")\n+            return ""\n+\n+        self.order_ref += 1\n+\n+        ctp_req = {\n+            "InstrumentID": req.symbol,\n+            "ExchangeID": req.exchange.value,\n+            "LimitPrice": req.price,\n+            "VolumeTotalOriginal": int(req.volume),\n+            "OrderPriceType": ORDERTYPE_VT2SGIT.get(req.type, ""),\n+            "Direction": DIRECTION_VT2SGIT.get(req.direction, ""),\n+            "CombOffsetFlag": OFFSET_VT2SGIT.get(req.offset, ""),\n+            "OrderRef": str(self.order_ref),\n+            "InvestorID": self.userid,\n+            "UserID": self.userid,\n+            "BrokerID": self.brokerid,\n+            "CombHedgeFlag": THOST_FTDC_HF_Speculation,\n+            "ContingentCondition": THOST_FTDC_CC_Immediately,\n+            "ForceCloseReason": THOST_FTDC_FCC_NotForceClose,\n+            "IsAutoSuspend": 0,\n+            "TimeCondition": THOST_FTDC_TC_GFD,\n+            "VolumeCondition": THOST_FTDC_VC_AV,\n+            "MinVolume": 1\n+        }\n+\n+        if req.type == OrderType.FAK:\n+            ctp_req["OrderPriceType"] = THOST_FTDC_OPT_LimitPrice\n+            ctp_req["TimeCondition"] = THOST_FTDC_TC_IOC\n+            ctp_req["VolumeCondition"] = THOST_FTDC_VC_AV\n+        elif req.type == OrderType.FOK:\n+            ctp_req["OrderPriceType"] = THOST_FTDC_OPT_LimitPrice\n+            ctp_req["TimeCondition"] = THOST_FTDC_TC_IOC\n+            ctp_req["VolumeCondition"] = THOST_FTDC_VC_CV\n+\n+        self.reqid += 1\n+        self.reqOrderInsert(ctp_req, self.reqid)\n+\n+        orderid = f"{self.frontid}_{self.sessionid}_{self.order_ref}"\n+        order = req.create_order_data(orderid, self.gateway_name)\n+        self.gateway.on_order(order)\n+\n+        return order.vt_orderid\n+\n+    def cancel_order(self, req: CancelRequest):\n+        """\n+        Cancel existing order.\n+        """\n+        frontid, sessionid, order_ref = req.orderid.split("_")\n+\n+        ctp_req = {\n+            "InstrumentID": req.symbol,\n+            "ExchangeID": req.exchange.value,\n+            "OrderRef": order_ref,\n+            "FrontID": int(frontid),\n+            "SessionID": int(sessionid),\n+            "ActionFlag": THOST_FTDC_AF_Delete,\n+            "BrokerID": self.brokerid,\n+            "InvestorID": self.userid\n+        }\n+\n+        self.reqid += 1\n+        self.reqOrderAction(ctp_req, self.reqid)\n+\n+    def query_account(self):\n+        """\n+        Query account balance data.\n+        """\n+        self.reqid += 1\n+        self.reqQryTradingAccount({}, self.reqid)\n+\n+    def query_position(self):\n+        """\n+        Query position holding data.\n+        """\n+        if not symbol_exchange_map:\n+            return\n+\n+        req = {\n+            "BrokerID": self.brokerid,\n+            "InvestorID": self.userid\n+        }\n+\n+        self.reqid += 1\n+        self.reqQryInvestorPosition(req, self.reqid)\n+\n+    def close(self):\n+        """"""\n+        if self.connect_status:\n+            self.exit()\n+\n+\n+def adjust_price(price: float) -> float:\n+    """"""\n+    if price == MAX_FLOAT:\n+        price = 0\n+    return price\n', 'addition_count': 859, 'deletion_count': 0, 'src_file': '/dev/null', 'tgt_file': 'b/vnpy/gateway/sgit/sgit_gateway.py', 'file_extension': '.py', 'before_file': 'ADDFILE', 'message': 'Merge pull request #2335 from 1122455801/SgitGateway00\n\n[Mod] add vnpy.api.sgit', 'author_name': 'GitHub', 'lang': 'py'}