Qt券商接口封装深度解析:统一API设计与多源适配

不同券商接口千差万别?深入Qt交易系统的接口抽象层,构建可扩展的券商适配架构

一、券商接口概述

国内券商接口种类繁多,各有特点:

接口类型 代表厂商 特点 适用场景
CTP 上期技术 期货标准接口 期货交易
XTP 中泰证券 高性能股票接口 股票交易
KGS 国金证券 快速行情 高频交易
LTS 华鑫证券 嵌入式接口 私募产品
FIX 国际标准 通用协议 海外市场

1.1 接口抽象目标

  • 统一API:屏蔽不同券商的接口差异
  • 可扩展:支持快速接入新券商
  • 可测试:提供Mock实现便于测试
  • 高性能:减少抽象层开销

二、接口抽象设计

2.1 核心接口定义

cpp 复制代码
// ITradeApi.h - 交易接口基类
class ITradeApi : public QObject
{
    Q_OBJECT

public:
    virtual ~ITradeApi() = default;
    
    // 连接管理
    virtual bool connect(const QString &address, int port) = 0;
    virtual void disconnect() = 0;
    virtual bool isConnected() const = 0;
    
    // 登录认证
    virtual bool login(const QString &username, const QString &password) = 0;
    virtual void logout() = 0;
    
    // 账户查询
    virtual QFuture<AccountInfo> queryAccount() = 0;
    virtual QFuture<QList<Position>> queryPositions() = 0;
    virtual QFuture<QList<Order>> queryOrders() = 0;
    virtual QFuture<QList<Trade>> queryTrades() = 0;
    
    // 交易操作
    virtual QString insertOrder(const OrderRequest &request) = 0;
    virtual bool cancelOrder(const QString &orderId) = 0;
    
    // 行情订阅
    virtual bool subscribeMarketData(const QStringList &symbols) = 0;
    virtual bool unsubscribeMarketData(const QStringList &symbols) = 0;

signals:
    void connected();
    void disconnected();
    void loginResult(bool success, const QString &message);
    
    void orderUpdated(const Order &order);
    void tradeReceived(const Trade &trade);
    void positionUpdated(const Position &position);
    
    void marketDataReceived(const MarketData &data);
    void errorOccurred(int errorCode, const QString &errorMessage);
};

2.2 数据结构定义

cpp 复制代码
// TradeTypes.h
struct AccountInfo
{
    QString accountId;          // 账户ID
    double totalAssets;         // 总资产
    double availableCash;       // 可用资金
    double marketValue;         // 持仓市值
    double frozenCash;          // 冻结资金
    double margin;              // 保证金
};

struct Position
{
    QString symbol;             // 证券代码
    QString exchange;           // 交易所
    int64_t totalQty;           // 总持仓
    int64_t availableQty;       // 可用持仓
    double avgPrice;            // 成本价
    double marketPrice;         // 市价
    double profitLoss;          // 浮动盈亏
};

struct Order
{
    QString orderId;            // 订单ID
    QString symbol;             // 证券代码
    QString exchange;           // 交易所
    QString direction;          // 买卖方向 Buy/Sell
    QString offset;             // 开平 Open/Close
    double price;               // 委托价格
    int64_t quantity;           // 委托数量
    int64_t filledQty;          // 成交数量
    QString status;             // 订单状态
    QDateTime createTime;       // 创建时间
    QDateTime updateTime;       // 更新时间
};

struct Trade
{
    QString tradeId;            // 成交ID
    QString orderId;            // 订单ID
    QString symbol;             // 证券代码
    QString exchange;           // 交易所
    QString direction;          // 买卖方向
    double price;               // 成交价格
    int64_t quantity;           // 成交数量
    QDateTime tradeTime;        // 成交时间
};

struct MarketData
{
    QString symbol;             // 证券代码
    QString exchange;           // 交易所
    double lastPrice;           // 最新价
    double openPrice;           // 开盘价
    double highPrice;           // 最高价
    double lowPrice;            // 最低价
    int64_t volume;             // 成交量
    double turnover;            // 成交额
    
    double bidPrice[5];         // 买价
    int64_t bidVolume[5];       // 买量
    double askPrice[5];         // 卖价
    int64_t askVolume[5];       // 卖量
};

struct OrderRequest
{
    QString symbol;             // 证券代码
    QString exchange;           // 交易所
    QString direction;          // 买卖方向
    QString offset;             // 开平
    double price;               // 委托价格
    int64_t quantity;           // 委托数量
    QString orderType;          // 订单类型 Limit/Market
};

三、CTP接口适配实现

3.1 CTP适配器类

cpp 复制代码
// CtpTradeApi.h
class CtpTradeApi : public ITradeApi
{
    Q_OBJECT

public:
    explicit CtpTradeApi(QObject *parent = nullptr);
    ~CtpTradeApi() override;
    
    // ITradeApi接口实现
    bool connect(const QString &address, int port) override;
    void disconnect() override;
    bool isConnected() const override;
    
    bool login(const QString &username, const QString &password) override;
    void logout() override;
    
    QString insertOrder(const OrderRequest &request) override;
    bool cancelOrder(const QString &orderId) override;
    
    QFuture<AccountInfo> queryAccount() override;
    QFuture<QList<Position>> queryPositions() override;
    
    bool subscribeMarketData(const QStringList &symbols) override;

private slots:
    void onFrontConnected();
    void onFrontDisconnected(int reason);
    void onRspUserLogin(int errorId, const QString &errorMsg);
    void onRspOrderInsert(const QString &orderId, int errorId, const QString &errorMsg);
    void onRtnOrder(const CThostFtdcOrderField *pOrder);
    void onRtnTrade(const CThostFtdcTradeField *pTrade);
    void onRtnDepthMarketData(const CThostFtdcDepthMarketDataField *pData);

private:
    Order convertFromCtp(const CThostFtdcOrderField *pOrder);
    Trade convertFromCtp(const CThostFtdcTradeField *pTrade);
    MarketData convertFromCtp(const CThostFtdcDepthMarketDataField *pData);
    
    CThostFtdcMdApi *m_mdApi = nullptr;      // 行情API
    CThostFtdcTraderApi *m_tradeApi = nullptr; // 交易API
    QString m_brokerId;
    QString m_investorId;
    int m_requestId = 0;
    
    QPromise<AccountInfo> *m_accountPromise = nullptr;
    QPromise<QList<Position>> *m_positionPromise = nullptr;
};

3.2 CTP回调处理

cpp 复制代码
// CtpTradeApi.cpp
void CtpTradeApi::onRtnOrder(const CThostFtdcOrderField *pOrder)
{
    if (!pOrder) return;
    
    Order order = convertFromCtp(pOrder);
    emit orderUpdated(order);
}

void CtpTradeApi::onRtnTrade(const CThostFtdcTradeField *pTrade)
{
    if (!pTrade) return;
    
    Trade trade = convertFromCtp(pTrade);
    emit tradeReceived(trade);
}

Order CtpTradeApi::convertFromCtp(const CThostFtdcOrderField *pOrder)
{
    Order order;
    order.orderId = pOrder->OrderRef;
    order.symbol = pOrder->InstrumentID;
    order.exchange = pOrder->ExchangeID;
    order.direction = (pOrder->Direction == THOST_FTDC_D_Buy) ? "Buy" : "Sell";
    order.offset = (pOrder->CombOffsetFlag[0] == THOST_FTDC_OF_Open) ? "Open" : "Close";
    order.price = pOrder->LimitPrice;
    order.quantity = pOrder->VolumeTotalOriginal;
    order.filledQty = pOrder->VolumeTraded;
    
    // 状态转换
    switch (pOrder->OrderStatus) {
    case THOST_FTDC_OST_AllTraded:
        order.status = "Filled"; break;
    case THOST_FTDC_OST_PartTradedQueueing:
        order.status = "Partial"; break;
    case THOST_FTDC_OST_NoTradeQueueing:
        order.status = "Pending"; break;
    case THOST_FTDC_OST_Canceled:
        order.status = "Canceled"; break;
    default:
        order.status = "Unknown";
    }
    
    order.createTime = QDateTime::fromString(pOrder->InsertDate, "yyyyMMdd");
    
    return order;
}

四、接口工厂模式

4.1 工厂类设计

cpp 复制代码
// TradeApiFactory.h
class TradeApiFactory
{
public:
    enum ApiType {
        CTP,        // 期货CTP
        XTP,        // 中泰XTP
        KGS,        // 国金KGS
        Mock        // 测试用Mock
    };
    
    static ITradeApi* create(ApiType type, QObject *parent = nullptr)
    {
        switch (type) {
        case CTP:
            return new CtpTradeApi(parent);
        case XTP:
            return new XtpTradeApi(parent);
        case KGS:
            return new KgsTradeApi(parent);
        case Mock:
            return new MockTradeApi(parent);
        default:
            return nullptr;
        }
    }
    
    static QStringList supportedApis()
    {
        return {"CTP", "XTP", "KGS", "Mock"};
    }
};

4.2 配置化创建

cpp 复制代码
// 从配置文件读取券商类型
ITradeApi* createTradeApiFromConfig()
{
    QSettings settings("config.ini", QSettings::IniFormat);
    QString apiType = settings.value("Trade/ApiType").toString();
    
    ITradeApi *api = nullptr;
    
    if (apiType == "CTP") {
        api = TradeApiFactory::create(TradeApiFactory::CTP);
        api->connect(settings.value("CTP/TradeFront").toString(), 
                     settings.value("CTP/TradePort").toInt());
    } else if (apiType == "XTP") {
        api = TradeApiFactory::create(TradeApiFactory::XTP);
        // XTP初始化...
    }
    
    return api;
}

五、Mock实现

5.1 测试用Mock类

cpp 复制代码
// MockTradeApi.h
class MockTradeApi : public ITradeApi
{
    Q_OBJECT

public:
    explicit MockTradeApi(QObject *parent = nullptr);
    
    bool connect(const QString &address, int port) override;
    bool login(const QString &username, const QString &password) override;
    
    QString insertOrder(const OrderRequest &request) override;
    bool cancelOrder(const QString &orderId) override;
    
    QFuture<AccountInfo> queryAccount() override;
    QFuture<QList<Position>> queryPositions() override;
    
    // Mock特有方法
    void simulateOrderFill(const QString &orderId, double price, int64_t qty);
    void simulateMarketData(const QString &symbol, double price);

private:
    bool m_connected = false;
    bool m_loggedIn = false;
    QMap<QString, Order> m_orders;
    QMap<QString, Position> m_positions;
    AccountInfo m_account;
};

// 实现
QString MockTradeApi::insertOrder(const OrderRequest &request)
{
    QString orderId = QUuid::createUuid().toString(QUuid::WithoutBraces);
    
    Order order;
    order.orderId = orderId;
    order.symbol = request.symbol;
    order.exchange = request.exchange;
    order.direction = request.direction;
    order.offset = request.offset;
    order.price = request.price;
    order.quantity = request.quantity;
    order.filledQty = 0;
    order.status = "Pending";
    order.createTime = QDateTime::currentDateTime();
    
    m_orders[orderId] = order;
    
    // 模拟订单更新
    QTimer::singleShot(100, [this, orderId]() {
        Order &ord = m_orders[orderId];
        ord.status = "Partial";
        ord.filledQty = ord.quantity / 2;
        emit orderUpdated(ord);
    });
    
    return orderId;
}

六、统一管理类

6.1 TradeManager封装

cpp 复制代码
// TradeManager.h
class TradeManager : public QObject
{
    Q_OBJECT

public:
    static TradeManager* instance();
    
    void init(ITradeApi *api);
    void cleanup();
    
    // 便捷接口
    QString buy(const QString &symbol, double price, int64_t qty);
    QString sell(const QString &symbol, double price, int64_t qty);
    bool cancelOrder(const QString &orderId);
    
    void queryAll();
    void subscribe(const QStringList &symbols);

signals:
    void accountUpdated(const AccountInfo &account);
    void positionUpdated(const Position &position);
    void orderUpdated(const Order &order);
    void tradeReceived(const Trade &trade);
    void marketDataReceived(const MarketData &data);

private:
    TradeManager();
    
    ITradeApi *m_api = nullptr;
    AccountInfo m_account;
    QMap<QString, Position> m_positions;
    QMap<QString, Order> m_orders;
};

QString TradeManager::buy(const QString &symbol, double price, int64_t qty)
{
    OrderRequest request;
    request.symbol = symbol;
    request.direction = "Buy";
    request.offset = "Open";
    request.price = price;
    request.quantity = qty;
    request.orderType = "Limit";
    
    return m_api->insertOrder(request);
}

七、总结

券商接口封装核心要点:

  1. 抽象接口:ITradeApi定义统一操作
  2. 数据结构:标准化Account/Position/Order/Trade
  3. 适配器模式:CTP/XTP/KGS各自实现适配
  4. 工厂模式:配置化创建具体实现
  5. Mock测试:提供模拟环境便于开发测试

《注:若有发现问题欢迎大家提出来纠正》

以上仅为技术分享参考,不构成投资建议

相关推荐
wearegogog1231 小时前
基于Q-learning的栅格地图路径规划MATLAB仿真程序
开发语言·算法·matlab
T0uken1 小时前
基于 vcpkg 与 LLVM-MinGW 的 Qt6 静态链接开发方案
c++·windows·qt
csbysj20201 小时前
Java 条件语句
开发语言
Ulyanov2 小时前
《现代 Python 桌面应用架构实战:PySide6 + QML 从入门到工程化》 开发环境搭建与工具链极简主义 —— 拒绝臃肿,构建工业级基座
开发语言·python·qt·ui·架构·系统仿真
逻辑驱动的ken2 小时前
Java高频面试场景题19
java·开发语言·面试·职场和发展·求职招聘
初心未改HD2 小时前
Go语言net/http与Web开发:构建高性能HTTP服务
开发语言·golang
叼烟扛炮3 小时前
C++第一讲:C++ 入门基础
开发语言·c++·函数重载·引用·内联函数·nullptr
Ulyanov3 小时前
《现代 Python 桌面应用架构实战:PySide6 + QML 从入门到工程化》:QML 声明式语法与霓虹按钮 —— 当 Python 遇见现代美学
开发语言·python·ui·qml·系统仿真·雷达电子对抗仿真
弹不出的5h3ll3 小时前
Ghost Bits:高位截断如何让 Java WAF 形同虚设
java·开发语言