Files
QTradeProgram/Sqbase/qhistoryorderdialog.cpp
2025-08-31 23:07:06 +08:00

277 lines
7.6 KiB
C++

#pragma execution_character_set("utf-8")
#include "qhistoryorderdialog.h"
#include "qbigordermanager.h"
#include <QHeaderView>
#include <QFileDialog>
#include <QTextStream>
#include <QCoreApplication>
#include <QDateTime>
#include <QDebug>
QHistoryOrderDialog::QHistoryOrderDialog(QWidget *parent)
: QDialog(parent),
m_dateSelector(new QDateEdit(this)),
m_orderTypeFilter(new QComboBox(this)),
m_stockCodeFilter(new QLineEdit(this)),
m_tableView(new QTableView(this)),
m_exportButton(new QPushButton("导出数据", this)),
m_statsLabel(new QLabel(this)),
m_model(new QStandardItemModel(this)),
m_proxyModel(new QSortFilterProxyModel(this)),
m_typeDelegate(new OrderTypeDelegate(this)),
m_numberDelegate(new NumberFormatDelegate(this))
{
setWindowTitle("历史订单查询");
setMinimumSize(800, 600);
m_historyPath = QCoreApplication::applicationDirPath() + QString("/history");
initUI();
onDateChanged(QDate::currentDate());
}
void QHistoryOrderDialog::initUI()
{
QVBoxLayout *mainLayout = new QVBoxLayout(this);
// 顶部控制区域
QHBoxLayout *topLayout = new QHBoxLayout();
// 日期选择器
m_dateSelector->setDate(QDate::currentDate());
m_dateSelector->setCalendarPopup(true);
topLayout->addWidget(new QLabel("选择日期:"));
topLayout->addWidget(m_dateSelector);
// 股票代码过滤
m_stockCodeFilter->setPlaceholderText("股票代码过滤");
topLayout->addWidget(new QLabel("股票代码:"));
topLayout->addWidget(m_stockCodeFilter);
// 订单类型过滤
m_orderTypeFilter->addItem("全部", "");
m_orderTypeFilter->addItem("买入", "BID");
m_orderTypeFilter->addItem("卖出", "ASK");
topLayout->addWidget(new QLabel("订单类型:"));
topLayout->addWidget(m_orderTypeFilter);
// 导出按钮
topLayout->addStretch();
topLayout->addWidget(m_exportButton);
mainLayout->addLayout(topLayout);
// 统计信息
QHBoxLayout *statsLayout = new QHBoxLayout();
statsLayout->addWidget(m_statsLabel);
statsLayout->addStretch();
mainLayout->addLayout(statsLayout);
// 表格视图
m_proxyModel->setSourceModel(m_model);
m_tableView->setItemDelegateForColumn(2, m_typeDelegate);
m_tableView->setItemDelegateForColumn(3, m_numberDelegate);
m_tableView->setModel(m_proxyModel);
m_tableView->setSortingEnabled(true);
m_tableView->setEditTriggers(QAbstractItemView::NoEditTriggers);
m_tableView->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
m_tableView->setSelectionBehavior(QAbstractItemView::SelectRows);
// 设置表头
m_model->setHorizontalHeaderLabels(
QStringList()
<< "股票代码" << "股票名称" << "订单类型"
<< "股票数量" << "股票价格" << "订单档位" << "时间"
);
mainLayout->addWidget(m_tableView);
const int timeColumnIndex = 6;
m_proxyModel->sort(timeColumnIndex, Qt::AscendingOrder);
// 连接信号
connect(m_dateSelector, &QDateEdit::dateChanged,
this, &QHistoryOrderDialog::onDateChanged);
connect(m_stockCodeFilter, &QLineEdit::textChanged,
this, &QHistoryOrderDialog::onFilterChanged);
connect(m_orderTypeFilter, QOverload<int>::of(&QComboBox::currentIndexChanged),
this, &QHistoryOrderDialog::onFilterChanged);
connect(m_exportButton, &QPushButton::clicked,
this, &QHistoryOrderDialog::onExportClicked);
}
void QHistoryOrderDialog::onDateChanged(const QDate &date)
{
loadOrdersForDate(date);
}
void QHistoryOrderDialog::loadOrdersForDate(const QDate &date)
{
auto orders = getHistoryOrders(date);
m_model->removeRows(0, m_model->rowCount());
for (const auto& order : orders) {
QList<QStandardItem*> rowItems;
rowItems << new QStandardItem(order->code);
rowItems << new QStandardItem(order->name);
rowItems << new QStandardItem(order->nBigOrderType == 0 ? "卖出" : "买入");
rowItems << new QStandardItem(QString::number(std::fabs(order->volume / 1000)) + "K");
rowItems << new QStandardItem(QString::number(order->price, 'f', 2));
rowItems << new QStandardItem(QString::number(order->level));
QString str = order->svrRecvTime.mid(11);
if (str == nullptr)
{
QDateTime dateTime = QDateTime::currentDateTime();
str = dateTime.toString("hh:mm:ss");
}
rowItems << new QStandardItem(str);
m_model->appendRow(rowItems);
}
updateStatistics(orders);
}
void QHistoryOrderDialog::updateStatistics(const QList<QSharedPointer<class BigOrderInfo>>& orders)
{
int buyCount = 0, sellCount = 0;
double totalBuyAmount = 0, totalSellAmount = 0;
for (const auto& order : orders) {
double value = order->price * order->volume;
if (order->nBigOrderType) {
buyCount++;
totalBuyAmount += value;
}
else {
sellCount++;
totalSellAmount += value;
}
}
QString stats = QString("总订单: %1 笔 | 买入: %2 笔 (%3 万) | 卖出: %4 笔 (%5 万)")
.arg(orders.size())
.arg(buyCount)
.arg(totalBuyAmount / 10000, 0, 'f', 1)
.arg(sellCount)
.arg(totalSellAmount / 10000, 0, 'f', 1);
m_statsLabel->setText(stats);
}
void QHistoryOrderDialog::onFilterChanged()
{
QString stockCode = m_stockCodeFilter->text().trimmed();
QString orderType = m_orderTypeFilter->currentData().toString();
// 设置股票代码过滤
m_proxyModel->setFilterKeyColumn(0);
m_proxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive);
m_proxyModel->setFilterFixedString(stockCode);
// 设置订单类型过滤
if (!orderType.isEmpty()) {
m_proxyModel->setFilterKeyColumn(2);
m_proxyModel->setFilterFixedString(orderType == "ASK" ? "卖出" : "买入");
}
}
void QHistoryOrderDialog::onExportClicked()
{
QString fileName = QFileDialog::getSaveFileName(this, "导出历史数据", "", "CSV文件 (*.csv)");
if (fileName.isEmpty()) return;
QFile file(fileName);
if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) return;
QTextStream out(&file);
out.setCodec("GBK");
// 写入表头
for (int col = 0; col < m_model->columnCount(); ++col) {
out << m_model->headerData(col, Qt::Horizontal).toString();
if (col < m_model->columnCount() - 1) out << ",";
}
out << "\n";
// 写入数据
for (int row = 0; row < m_proxyModel->rowCount(); ++row) {
for (int col = 0; col < m_proxyModel->columnCount(); ++col) {
out << m_proxyModel->index(row, col).data().toString();
if (col < m_proxyModel->columnCount() - 1) out << ",";
}
out << "\n";
}
file.close();
m_statsLabel->setText(QString("数据已导出到: %1").arg(fileName));
}
QList<QSharedPointer<BigOrderInfo>> QHistoryOrderDialog::getHistoryOrders(const QDate& date) const
{
QMutexLocker locker(&m_cacheMutex);
// 检查缓存
if (m_historyCache.contains(date)) {
return m_historyCache[date];
}
QString filePath = QString("%1/bigorders_%2.json")
.arg(m_historyPath)
.arg(date.toString("yyyyMMdd"));
if (!QFile::exists(filePath)) {
return QList<QSharedPointer<BigOrderInfo>>();
}
QFile file(filePath);
if (!file.open(QIODevice::ReadOnly)) {
qWarning() << "Failed to open history file:" << filePath;
return QList<QSharedPointer<BigOrderInfo>>();
}
QList<QSharedPointer<BigOrderInfo>> orders;
QTextStream in(&file);
in.setCodec("UTF-8");
while (!in.atEnd()) {
QJsonParseError error;
QJsonDocument doc = QJsonDocument::fromJson(in.readLine().toUtf8(), &error);
if (error.error == QJsonParseError::NoError && doc.isObject()) {
BigOrderInfo order = BigOrderInfo::fromJson(doc.object());
orders.append(QSharedPointer<BigOrderInfo>::create(order));
//if (order.isValid()) {
//}
}
}
file.close();
// 缓存结果
m_historyCache.insert(date, orders);
return orders;
}
QList<QDate> QHistoryOrderDialog::getAvailableDates() const
{
QList<QDate> dates;
QDir historyDir(m_historyPath);
QStringList files = historyDir.entryList(QStringList() << "bigorders_*.json", QDir::Files);
for (const QString& file : files) {
QString dateStr = file.mid(10, 8); // bigorders_20230101.json
QDate date = QDate::fromString(dateStr, "yyyyMMdd");
if (date.isValid()) {
dates.append(date);
}
}
std::sort(dates.begin(), dates.end());
return dates;
}