Files
2026-02-25 23:01:42 +08:00

228 lines
5.8 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#pragma once
#include <google/protobuf/arena.h>
#include <QVector>
#include <QDebug>
#include <QSet>
#include <QCache>
#include <algorithm>
#include <functional>
#include "tool.h"
#include "BZStruct.h"
class OrderBookParser {
public:
OrderBookParser() {
// 初始化缓存最大缓存100个订单簿数据
m_orderCache.setMaxCost(100);
}
bool parse(const char* data, int size, OrderBookData& output) {
// 创建Response消息并解析
google::protobuf::Arena arena;
auto* response = new Qot_UpdateOrderBook::Response;
if (!response->ParseFromArray(data, size)) {
return false;
}
// 检查响应状态 (0表示成功)
if (response->rettype() != 0) {
arena.Reset();
return false;
}
// 检查是否存在有效数据
if (!response->has_s2c()) {
arena.Reset();
return true;
}
const auto& s2c = response->s2c();
output.clear();
output.name = QString(s2c.name().c_str());
output.code = QString(s2c.security().code().c_str());
output.askTime = QString(s2c.svrrecvtimeask().c_str());
output.bidTime = QString(s2c.svrrecvtimebid().c_str());
// 处理买盘订单簿 (bids)
if (s2c.orderbookbidlist_size() > 0) {
parseOrderBookList(s2c.orderbookbidlist(), output.bids);
}
// 处理卖盘订单簿 (asks)
if (s2c.orderbookasklist_size() > 0) {
parseOrderBookList(s2c.orderbookasklist(), output.asks);
}
// 数据预处理优化
if (!validateOrderData(*response)) {
arena.Reset();
return false;
}
// 压缩数据以减少内存占用
compressOrderData(output);
// 去重处理
removeDuplicateOrders(output);
arena.Reset(); // 重置内存池供下次使用
return true;
}
// 添加数据有效性检查
bool validateOrderData(const Qot_UpdateOrderBook::Response &stRsp) {
if (!stRsp.has_s2c()) {
return false;
}
const auto& s2c = stRsp.s2c();
// 检查基本字段
if (s2c.security().code().empty() || s2c.name().empty()) {
return false;
}
// 检查时间戳有效性
if (s2c.svrrecvtimeask().empty() && s2c.svrrecvtimebid().empty()) {
return false;
}
// 检查价格和数量合理性
auto validatePriceVolume = [](const google::protobuf::RepeatedPtrField<Qot_Common::OrderBook>& list) {
for (const auto& item : list) {
if (item.price() <= 0 || item.volume() < 0) {
return false;
}
for (const auto& detail : item.detaillist()) {
if (detail.orderid() < 0 || detail.volume() < 0) {
return false;
}
}
}
return true;
};
if (!validatePriceVolume(s2c.orderbookbidlist()) ||
!validatePriceVolume(s2c.orderbookasklist())) {
return false;
}
return true;
}
// 添加数据去重机制
void removeDuplicateOrders(OrderBookData& data) {
auto removeDuplicates = [](QVector<OrderBookEntry>& entries) {
QSet<QString> seenPrices;
QVector<OrderBookEntry> uniqueEntries;
uniqueEntries.reserve(entries.size());
for (const auto& entry : entries) {
QString priceKey = QString::number(entry.price, 'f', 4);
if (!seenPrices.contains(priceKey)) {
seenPrices.insert(priceKey);
uniqueEntries.append(entry);
}
}
entries = std::move(uniqueEntries);
};
removeDuplicates(data.bids);
removeDuplicates(data.asks);
}
// 添加数据压缩,减少内存占用
void compressOrderData(OrderBookData& data) {
// 压缩字符串数据
data.name = data.name.simplified();
data.code = data.code.simplified();
data.askTime = data.askTime.simplified();
data.bidTime = data.bidTime.simplified();
// 移除空明细的订单条目
auto compressEntries = [](QVector<OrderBookEntry>& entries) {
QVector<OrderBookEntry> compressed;
compressed.reserve(entries.size());
for (auto& entry : entries) {
if (entry.isValid() && !entry.details.isEmpty()) {
// 压缩明细数据 - 移除volume为0的明细
QVector<OrderDetail> validDetails;
validDetails.reserve(entry.details.size());
for (const auto& detail : entry.details) {
if (detail.volume > 0 && detail.orderId > 0) {
validDetails.append(detail);
}
}
if (!validDetails.isEmpty()) {
entry.details = std::move(validDetails);
compressed.append(entry);
}
}
}
entries = std::move(compressed);
};
compressEntries(data.bids);
compressEntries(data.asks);
}
private:
QCache<QString, OrderBookData> m_orderCache;
void parseOrderBookList(
const google::protobuf::RepeatedPtrField<Qot_Common::OrderBook>& pbList,
QVector<OrderBookEntry>& output)
{
output.clear();
const int itemCount = pbList.size();
if (itemCount == 0) return;
// 预分配输出内存
output.reserve(itemCount);
// 第一遍:计算最大明细数量
int maxDetails = 0;
for (int i = 0; i < itemCount; ++i) {
maxDetails = std::max(maxDetails, pbList.Get(i).detaillist_size());
}
// 第二遍:填充数据(使用局部缓冲区)
for (int i = 0; i < itemCount; ++i) {
const auto& pb_item = pbList.Get(i);
const int detailCount = pb_item.detaillist_size();
// 为当前条目创建独立的明细缓冲区
QVector<OrderDetail> detailsBuffer;
detailsBuffer.reserve(detailCount); // 按实际需求预分配
// 安全解析明细
try {
for (int j = 0; j < detailCount; ++j) {
const auto& pb_detail = pb_item.detaillist(j);
OrderDetail detail;
detail.orderId = pb_detail.orderid();
detail.volume = pb_detail.volume();
detailsBuffer.append(detail);
}
}
catch (const std::exception& e) {
detailsBuffer.clear(); // 清除非法数据
}
// 构造 OrderBookEntry直接移动缓冲区
OrderBookEntry item;
item.price = pb_item.price();
item.volume = pb_item.volume();
item.orderCount = pb_item.oredercount();
item.details = detailCount > 0 ? std::move(detailsBuffer) : QVector<OrderDetail>{};
output.append(item);
}
}
};