Update 更新文档
This commit is contained in:
227
TradingCore/data_processing/OrderBookParser.h
Normal file
227
TradingCore/data_processing/OrderBookParser.h
Normal file
@@ -0,0 +1,227 @@
|
||||
#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);
|
||||
}
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user