def create_qapp(app_name: str = "Veighna Trader") -> QtWidgets.QApplication:
    def excepthook(exctype: type, value: Exception, tb: types.TracebackType) -> None:
    def __init__(self, parent: QtWidgets.QWidget = None):
    def init_ui(self) -> None:
    def show_exception(self, msg: str) -> None:
    def _copy_text(self) -> None:
    def _open_community(self) -> None:
class ExceptionWidget(QtWidgets.QWidget): class Direction(Enum):
    """
    Direction of order/trade/position.
    """
    LONG = "多"
    SHORT = "空"
    NET = "净" class Exchange(Enum):
    """
    Exchange.
    """
    # Chinese
    CFFEX = "CFFEX"         # China Financial Futures Exchange
    SHFE = "SHFE"           # Shanghai Futures Exchange
    CZCE = "CZCE"           # Zhengzhou Commodity Exchange
    DCE = "DCE"             # Dalian Commodity Exchange
    INE = "INE"             # Shanghai International Energy Exchange
    SSE = "SSE"             # Shanghai Stock Exchange
    SZSE = "SZSE"           # Shenzhen Stock Exchange
    BSE = "BSE"             # Beijing Stock Exchange
    SGE = "SGE"             # Shanghai Gold Exchange
    WXE = "WXE"             # Wuxi Steel Exchange
    CFETS = "CFETS"         # CFETS Bond Market Maker Trading System
    XBOND = "XBOND"         # CFETS X-Bond Anonymous Trading System

    # Global
    SMART = "SMART"         # Smart Router for US stocks
    NYSE = "NYSE"           # New York Stock Exchnage
    NASDAQ = "NASDAQ"       # Nasdaq Exchange
    ARCA = "ARCA"           # ARCA Exchange
    EDGEA = "EDGEA"         # Direct Edge Exchange
    ISLAND = "ISLAND"       # Nasdaq Island ECN
    BATS = "BATS"           # Bats Global Markets
    IEX = "IEX"             # The Investors Exchange
    NYMEX = "NYMEX"         # New York Mercantile Exchange
    COMEX = "COMEX"         # COMEX of CME
    GLOBEX = "GLOBEX"       # Globex of CME
    IDEALPRO = "IDEALPRO"   # Forex ECN of Interactive Brokers
    CME = "CME"             # Chicago Mercantile Exchange
    ICE = "ICE"             # Intercontinental Exchange
    SEHK = "SEHK"           # Stock Exchange of Hong Kong
    HKFE = "HKFE"           # Hong Kong Futures Exchange
    SGX = "SGX"             # Singapore Global Exchange
    CBOT = "CBT"            # Chicago Board of Trade
    CBOE = "CBOE"           # Chicago Board Options Exchange
    CFE = "CFE"             # CBOE Futures Exchange
    DME = "DME"             # Dubai Mercantile Exchange
    EUREX = "EUX"           # Eurex Exchange
    APEX = "APEX"           # Asia Pacific Exchange
    LME = "LME"             # London Metal Exchange
    BMD = "BMD"             # Bursa Malaysia Derivatives
    TOCOM = "TOCOM"         # Tokyo Commodity Exchange
    EUNX = "EUNX"           # Euronext Exchange
    KRX = "KRX"             # Korean Exchange
    OTC = "OTC"             # OTC Product (Forex/CFD/Pink Sheet Equity)
    IBKRATS = "IBKRATS"     # Paper Trading Exchange of IB

    # Special Function
    LOCAL = "LOCAL"         # For local generated data class Offset(Enum):
    """
    Offset of order/trade.
    """
    NONE = ""
    OPEN = "开"
    CLOSE = "平"
    CLOSETODAY = "平今"
    CLOSEYESTERDAY = "平昨" class OrderType(Enum):
    """
    Order type.
    """
    LIMIT = "限价"
    MARKET = "市价"
    STOP = "STOP"
    FAK = "FAK"
    FOK = "FOK"
    RFQ = "询价" class MainEngine:
class BaseEngine(ABC):
class LogEngine(BaseEngine):
class OmsEngine(BaseEngine):
class EmailEngine(BaseEngine):
    def __init__(self, event_engine: EventEngine = None):
    def add_engine(self, engine_class: Any) -> "BaseEngine":
    def add_gateway(self, gateway_class: Type[BaseGateway], gateway_name: str = "") -> BaseGateway:
    def add_app(self, app_class: Type[BaseApp]) -> "BaseEngine":
    def init_engines(self) -> None:
    def write_log(self, msg: str, source: str = "") -> None:
    def get_gateway(self, gateway_name: str) -> BaseGateway:
    def get_engine(self, engine_name: str) -> "BaseEngine":
    def get_default_setting(self, gateway_name: str) -> Optional[Dict[str, Any]]:
    def get_all_gateway_names(self) -> List[str]:
    def get_all_apps(self) -> List[BaseApp]:
    def get_all_exchanges(self) -> List[Exchange]:
    def connect(self, setting: dict, gateway_name: str) -> None:
    def subscribe(self, req: SubscribeRequest, gateway_name: str) -> None:
    def send_order(self, req: OrderRequest, gateway_name: str) -> str:
    def cancel_order(self, req: CancelRequest, gateway_name: str) -> None:
    def send_quote(self, req: QuoteRequest, gateway_name: str) -> str:
    def cancel_quote(self, req: CancelRequest, gateway_name: str) -> None:
    def query_history(self, req: HistoryRequest, gateway_name: str) -> Optional[List[BarData]]:
    def close(self) -> None:
    def __init__(
        self,
        main_engine: MainEngine,
        event_engine: EventEngine,
        engine_name: str,
    ):
    def close(self):
    def __init__(self, main_engine: MainEngine, event_engine: EventEngine):
    def add_null_handler(self) -> None:
    def add_console_handler(self) -> None:
    def add_file_handler(self) -> None:
    def register_event(self) -> None:
    def process_log_event(self, event: Event) -> None:
    def __init__(self, main_engine: MainEngine, event_engine: EventEngine):
    def add_function(self) -> None:
    def register_event(self) -> None:
    def process_tick_event(self, event: Event) -> None:
    def process_order_event(self, event: Event) -> None:
    def process_trade_event(self, event: Event) -> None:
    def process_position_event(self, event: Event) -> None:
    def process_account_event(self, event: Event) -> None:
    def process_contract_event(self, event: Event) -> None:
    def process_quote_event(self, event: Event) -> None:
    def get_tick(self, vt_symbol: str) -> Optional[TickData]:
    def get_order(self, vt_orderid: str) -> Optional[OrderData]:
    def get_trade(self, vt_tradeid: str) -> Optional[TradeData]:
    def get_position(self, vt_positionid: str) -> Optional[PositionData]:
    def get_account(self, vt_accountid: str) -> Optional[AccountData]:
    def get_contract(self, vt_symbol: str) -> Optional[ContractData]:
    def get_quote(self, vt_quoteid: str) -> Optional[QuoteData]:
    def get_all_ticks(self) -> List[TickData]:
    def get_all_orders(self) -> List[OrderData]:
    def get_all_trades(self) -> List[TradeData]:
    def get_all_positions(self) -> List[PositionData]:
    def get_all_accounts(self) -> List[AccountData]:
    def get_all_contracts(self) -> List[ContractData]:
    def get_all_quotes(self) -> List[QuoteData]:
    def get_all_active_orders(self, vt_symbol: str = "") -> List[OrderData]:
    def get_all_active_quotes(self, vt_symbol: str = "") -> List[QuoteData]:
    def __init__(self, main_engine: MainEngine, event_engine: EventEngine):
    def send_email(self, subject: str, content: str, receiver: str = "") -> None:
    def run(self) -> None:
    def start(self) -> None:
    def close(self) -> None: EVENT_QUOTE = "eQuote." EVENT_TICK = "eTick." EVENT_TRADE = "eTrade." EVENT_ORDER = "eOrder." EVENT_POSITION = "ePosition." EVENT_ACCOUNT = "eAccount." EVENT_LOG = "eLog" class OrderRequest:
    """
    Request sending to specific gateway for creating a new order.
    """

    symbol: str
    exchange: Exchange
    direction: Direction
    type: OrderType
    volume: float
    price: float = 0
    offset: Offset = Offset.NONE
    reference: str = ""

    def __post_init__(self):
        """"""
        self.vt_symbol = f"{self.symbol}.{self.exchange.value}"

    def create_order_data(self, orderid: str, gateway_name: str) -> OrderData:
        """
        Create order data from request.
        """
        order = OrderData(
            symbol=self.symbol,
            exchange=self.exchange,
            orderid=orderid,
            type=self.type,
            direction=self.direction,
            offset=self.offset,
            price=self.price,
            volume=self.volume,
            reference=self.reference,
            gateway_name=gateway_name,
        )
        return order class SubscribeRequest:
    """
    Request sending to specific gateway for subscribing tick data update.
    """

    symbol: str
    exchange: Exchange

    def __post_init__(self):
        """"""
        self.vt_symbol = f"{self.symbol}.{self.exchange.value}" class PositionData(BaseData):
    """
    Positon data is used for tracking each individual position holding.
    """

    symbol: str
    exchange: Exchange
    direction: Direction

    volume: float = 0
    frozen: float = 0
    price: float = 0
    pnl: float = 0
    yd_volume: float = 0

    def __post_init__(self):
        """"""
        self.vt_symbol = f"{self.symbol}.{self.exchange.value}"
        self.vt_positionid = f"{self.vt_symbol}.{self.direction.value}" def load_json(filename: str) -> dict:
    """
    Load data from json file in temp path.
    """
    filepath = get_file_path(filename)

    if filepath.exists():
        with open(filepath, mode="r", encoding="UTF-8") as f:
            data = json.load(f)
        return data
    else:
        save_json(filename, {})
        return {} def save_json(filename: str, data: dict) -> None:
    """
    Save data into json file in temp path.
    """
    filepath = get_file_path(filename)
    with open(filepath, mode="w+", encoding="UTF-8") as f:
        json.dump(
            data,
            f,
            indent=4,
            ensure_ascii=False
        ) def get_digits(value: float) -> int:
    """
    Get number of digits after decimal point.
    """
    value_str = str(value)

    if "e-" in value_str:
        _, buf = value_str.split("e-")
        return int(buf)
    elif "." in value_str:
        _, buf = value_str.split(".")
        return len(buf)
    else:
        return 0 SETTING_FILENAME: str = "vt_setting.json" SETTINGS: Dict[str, Any] = {
    "font.family": "微软雅黑",
    "font.size": 12,

    "log.active": True,
    "log.level": CRITICAL,
    "log.console": True,
    "log.file": True,

    "email.server": "smtp.qq.com",
    "email.port": 465,
    "email.username": "",
    "email.password": "",
    "email.sender": "",
    "email.receiver": "",

    "datafeed.name": "",
    "datafeed.username": "",
    "datafeed.password": "",

    "database.timezone": get_localzone().zone,
    "database.name": "sqlite",
    "database.database": "database.db",
    "database.host": "",
    "database.port": 0,
    "database.user": "",
    "database.password": ""
}
import csv
import platform
import importlib_metadata
from enum import Enum
from typing import Any, Dict
from copy import copy
from tzlocal import get_localzone
from .qt import QtCore, QtGui, QtWidgets
from ..constant import Direction, Exchange, Offset, OrderType
from ..engine import MainEngine, Event, EventEngine
from ..event import (
    EVENT_QUOTE,
    EVENT_TICK,
    EVENT_TRADE,
    EVENT_ORDER,
    EVENT_POSITION,
    EVENT_ACCOUNT,
    EVENT_LOG
)
from ..object import OrderRequest, SubscribeRequest, PositionData
from ..utility import load_json, save_json, get_digits
from ..setting import SETTING_FILENAME, SETTINGS
        from ... import __version__ as vnpy_version
        self.setSortingEnabled(self.sorting)

    def init_menu(self) -> None:
        """
        Create right click menu.
        """
        self.menu = QtWidgets.QMenu(self)

        resize_action = QtWidgets.QAction("调整列宽", self)
        resize_action.triggered.connect(self.resize_columns)
        self.menu.addAction(resize_action)

        save_action = QtWidgets.QAction("保存数据", self)
        save_action.triggered.connect(self.save_csv)
        self.menu.addAction(save_action)

    def register_event(self) -> None:
        """
        Register event handler into event engine.
        """
        if self.event_type:
            self.signal.connect(self.process_event)
            self.event_engine.register(self.event_type, self.signal.emit)

    def process_event(self, event: Event) -> None:
        """
        Process new data from event and update into table.
        """
        # Disable sorting to prevent unwanted error.
        if self.sorting:
            self.setSortingEnabled(False)

        # Update data into table.
        data = event.data

        if not self.data_key:
            self.insert_new_row(data)
        else:
            key = data.__getattribute__(self.data_key)

            if key in self.cells:
                self.update_old_row(data)
            else:
                self.insert_new_row(data)

        # Enable sorting
        if self.sorting:
            self.setSortingEnabled(True)

    def insert_new_row(self, data: Any):
        """
        Insert a new row at the top of table.
        """
        self.insertRow(0)

        row_cells = {}
        for column, header in enumerate(self.headers.keys()):
            setting = self.headers[header]

            content = data.__getattribute__(header)
            cell = setting["cell"](content, data)
            self.setItem(0, column, cell)

            if setting["update"]:
                row_cells[header] = cell

        if self.data_key:
            key = data.__getattribute__(self.data_key)
            self.cells[key] = row_cells

    def update_old_row(self, data: Any) -> None:
        """
        Update an old row in table.
        """
        key = data.__getattribute__(self.data_key)
        row_cells = self.cells[key]

        for header, cell in row_cells.items():
            content = data.__getattribute__(header)
            cell.set_content(content, data)

    def resize_columns(self) -> None:
        """
        Resize all columns according to contents.
        """
        self.horizontalHeader().resizeSections(QtWidgets.QHeaderView.ResizeToContents)

    def save_csv(self) -> None:
        """
        Save table data into a csv file
        """
        path, _ = QtWidgets.QFileDialog.getSaveFileName(
            self, "保存数据", "", "CSV(*.csv)")

        if not path:
            return

        with open(path, "w") as f:
            writer = csv.writer(f, lineterminator="\n")

            headers = [d["display"] for d in self.headers.values()]
            writer.writerow(headers)

            for row in range(self.rowCount()):
                if self.isRowHidden(row):
                    continue

                row_data = []
                for column in range(self.columnCount()):
                    item = self.item(row, column)
                    if item:
                        row_data.append(str(item.text()))
                    else:
                        row_data.append("")
                writer.writerow(row_data)

    def contextMenuEvent(self, event: QtGui.QContextMenuEvent) -> None:
        """
        Show menu with right click.
        """

        self.menu.popup(QtGui.QCursor.pos())