用中泰证券的XTP接口编写L2行情接收c++代码

以下是针对 存储10档买卖盘行情数据 的完整实现方案,包含 SQLite内存数据库表结构设计回调函数数据处理 和 高性能存储优化


一、SQLite表结构设计(存储10档数据)

// 创建包含10档买卖盘的表结构
const char* create_table_sql = 
    "CREATE TABLE IF NOT EXISTS market_data ("
    "timestamp  INTEGER, "          // 时间戳
    "ticker     TEXT, "              // 股票代码
    "last_price REAL, "              // 最新价
    // 买盘10档
    "bid_price1 REAL, bid_qty1 INTEGER, "
    "bid_price2 REAL, bid_qty2 INTEGER, "
    "bid_price3 REAL, bid_qty3 INTEGER, "
    "bid_price4 REAL, bid_qty4 INTEGER, "
    "bid_price5 REAL, bid_qty5 INTEGER, "
    "bid_price6 REAL, bid_qty6 INTEGER, "
    "bid_price7 REAL, bid_qty7 INTEGER, "
    "bid_price8 REAL, bid_qty8 INTEGER, "
    "bid_price9 REAL, bid_qty9 INTEGER, "
    "bid_price10 REAL, bid_qty10 INTEGER, "
    // 卖盘10档
    "ask_price1 REAL, ask_qty1 INTEGER, "
    "ask_price2 REAL, ask_qty2 INTEGER, "
    "ask_price3 REAL, ask_qty3 INTEGER, "
    "ask_price4 REAL, ask_qty4 INTEGER, "
    "ask_price5 REAL, ask_qty5 INTEGER, "
    "ask_price6 REAL, ask_qty6 INTEGER, "
    "ask_price7 REAL, ask_qty7 INTEGER, "
    "ask_price8 REAL, ask_qty8 INTEGER, "
    "ask_price9 REAL, ask_qty9 INTEGER, "
    "ask_price10 REAL, ask_qty10 INTEGER"
    ");";

二、回调函数处理10档数据

1. 修改后的回调函数实现

void OnDepthMarketData(
    XTPMD *market_data,
    int64_t bid1_qty[],      // 参数根据实际情况调整(若需要)
    int32_t bid1_count,
    int32_t max_bid1_count,
    int64_t ask1_qty[],
    int32_t ask1_count,
    int32_t max_ask1_count
) override {
    // 生成SQL插入语句(包含10档买卖盘字段)
    const char* insert_sql = 
        "INSERT INTO market_data VALUES ("
        "?, ?, ?, "   // timestamp, ticker, last_price
        "?,?, ?,?, ?,?, ?,?, ?,?, ?,?, "  // bid_price1~10 + bid_qty1~10
        "?,?, ?,?, ?,?, ?,?, ?,?, ?,?"    // ask_price1~10 + ask_qty1~10
        ");";

    sqlite3_stmt* stmt;
    if (sqlite3_prepare_v2(db, insert_sql, -1, &stmt, 0) != SQLITE_OK) {
        std::cerr << "SQL编译错误: " << sqlite3_errmsg(db) << std::endl;
        return;
    }

    // 绑定基础字段
    sqlite3_bind_int64(stmt, 1, market_data->data_time);
    sqlite3_bind_text(stmt, 2, market_data->ticker, -1, SQLITE_STATIC);
    sqlite3_bind_double(stmt, 3, market_data->last_price);

    // 绑定买盘10档数据
    for (int i = 0; i < 10; ++i) {
        sqlite3_bind_double(stmt, 4 + 2*i,   market_data->bid[i].price);  // bid_price1~10
        sqlite3_bind_int64(stmt,  5 + 2*i,   market_data->bid[i].qty);    // bid_qty1~10
    }

    // 绑定卖盘10档数据
    for (int i = 0; i < 10; ++i) {
        sqlite3_bind_double(stmt, 24 + 2*i,  market_data->ask[i].price);  // ask_price1~10
        sqlite3_bind_int64(stmt,  25 + 2*i,  market_data->ask[i].qty);    // ask_qty1~10
    }

    // 执行插入
    if (sqlite3_step(stmt) != SQLITE_DONE) {
        std::cerr << "插入失败: " << sqlite3_errmsg(db) << std::endl;
    }
    sqlite3_finalize(stmt);
}

三、性能优化策略

1. 批量事务提交
// 在开始接收数据前开启事务
sqlite3_exec(db, "BEGIN TRANSACTION;", 0, 0, 0);

// 在数据接收完成后提交事务
sqlite3_exec(db, "COMMIT;", 0, 0, 0);
 
2. SQLite配置优化
// 禁用磁盘同步(内存数据库无需持久化)
sqlite3_exec(db, "PRAGMA synchronous = OFF;", 0, 0, 0);
// 启用内存映射
sqlite3_exec(db, "PRAGMA mmap_size = 268435456;", 0, 0, 0);
3. 数据压缩存储(可选)

若磁盘空间有限,可将数据序列化为二进制格式:

// 使用Protocol Buffers定义数据结构
message MarketData {
  int64 timestamp = 1;
  string ticker = 2;
  double last_price = 3;
  repeated double bid_prices = 4;  // 10 elements
  repeated int64 bid_qtys = 5;     // 10 elements
  repeated double ask_prices = 6;  // 10 elements
  repeated int64 ask_qtys = 7;     // 10 elements
}

// 存储为BLOB字段
sqlite3_bind_blob(stmt, 1, serialized_data.data(), serialized_data.size(), SQLITE_STATIC);
 

四、数据查询示例

1. 查询买五档数据

const char* query_sql = 
    "SELECT timestamp, ticker, bid_price5, bid_qty5 "
    "FROM market_data "
    "WHERE ticker = '600519.SH';";

sqlite3_stmt* stmt;
sqlite3_prepare_v2(db, query_sql, -1, &stmt, 0);

while (sqlite3_step(stmt) == SQLITE_ROW) {
    int64_t timestamp = sqlite3_column_int64(stmt, 0);
    const char* ticker = (const char*)sqlite3_column_text(stmt, 1);
    double bid_price5 = sqlite3_column_double(stmt, 2);
    int64_t bid_qty5 = sqlite3_column_int64(stmt, 3);
    
    std::cout << "时间: " << timestamp 
              << " 代码: " << ticker 
              << " 买五价: " << bid_price5 
              << " 买五量: " << bid_qty5 << std::endl;
}
2. 统计卖一档总量
const char* agg_sql = 
    "SELECT SUM(ask_qty1) FROM market_data "
    "WHERE timestamp BETWEEN 1620000000 AND 1620086400;";
// 执行并获取结果...

五、注意事项

  1. 数据结构验证
    确保 XTPMD 结构体中 bid 和 ask 数组长度至少为10:

    static_assert(sizeof(market_data->bid) >= 10 * sizeof(XTPOB), "bid数组长度不足10档");

  2. 空值处理
    若某档无数据,存储为 NULL 更规范:

    if (market_data->bid[i].price <= 0) {
        sqlite3_bind_null(stmt, 4 + 2*i);
    } else {
        sqlite3_bind_double(stmt, 4 + 2*i, market_data->bid[i].price);
    }

  3. 高频场景优化

    • 使用 连接池 管理多个数据库连接

    • 采用 环形缓冲区 分离数据接收与存储线程


六、完整代码整合

// 1. 初始化数据库
sqlite3* db;
sqlite3_open(":memory:", &db);
sqlite3_exec(db, create_table_sql, 0, 0, 0);
sqlite3_exec(db, "PRAGMA synchronous=OFF;", 0, 0, 0);

// 2. 初始化XTP API
XTP::API::QuoteAPI* api = XTP::API::QuoteAPI::CreateQuoteApi("client_id", "./log");
MyQuoteSpi spi;
api->RegisterSpi(&spi);
api->Login("127.0.0.1", 6001, "user", "pass", XTP_PROTOCOL_TCP);

// 3. 订阅全市场数据
api->SubscribeAllMarketData(XTP_EXCHANGE_SH);

// 4. 主循环(示例)
std::thread storage_thread([](){
    while (running) {
        std::this_thread::sleep_for(std::chrono::seconds(1));
        sqlite3_exec(db, "BEGIN; COMMIT;", 0, 0, 0); // 定时提交事务
    }
});

// 5. 退出时持久化数据
sqlite3* disk_db;
sqlite3_open("historical_data.db", &disk_db);
sqlite3_backup* backup = sqlite3_backup_init(disk_db, "main", db, "main");
sqlite3_backup_step(backup, -1);
sqlite3_backup_finish(backup);
sqlite3_close(disk_db);

                
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值