前言(废话)
byd,CSDN上消失了一个月,现在终于回归了
中间跑去做大作业了(虽然中间水了两周),还有一堆破事,转专业,竞赛啥的
嘛,这是最后的成果:
外排序部分很快就写完了,后面的画图和gui设计搞了我好久(毕竟第一次接触)
大作业的要求:
1.对股票数据进行排序 (必须使用外排序,用于排序的内存大小限制为32MB,此限制的检查,需要通过资源管理器展现。)
嘛,简单,我是参考了这篇文章:
【外排序】外排序算法(磁盘排序、磁带排序) 外存设备结构分析 败者树多路归并 最佳归并树白话讲解-CSDN博客
在知道是归并排序之后就开干了,其中对文件进行归并的时候用上了STL的priority_queue,后面老师又介绍了最小堆,这两个都可以,先不论效率咋样,直接使用现成的priority_queue是更加方便的
2.创建索引,加快数据访问
索引的创建直接使用文件输入输出把索引放在一个文件里面就行了,这个可以在外排序的过程中进行。
为了加快索引的访问,我是创建了一个索引类来读取文件里面的索引来将索引放在内存的
可以看看我的索引类的声明:
struct index{
char code[codeL];
int YM;
index(){}
index(char * tmp, int YM):YM(YM){memcpy(code, tmp, codeL);}
bool operator<(const index tmp)const;
bool operator!=(const index tmp)const;
bool operator==(const index tmp)const;
};//为索引类使用的结构
class Index{
private:
bool is_build;
std::map<index, long> m;
public:
Index(){is_build = false;}
void build(void);
long get_index(const index &tmp){return m[tmp];}
long get_next_index(const index &tmp);
bool is_index_existed(const index &tmp);
QStringList get_all_code(void);//给出所有的股票代码
QStringList get_all_code(const int YM);//根据年月给出对应的股票代码
QStringList get_all_month(void);//给出所有的年月
QStringList get_all_month(const char str[codeL]);//根据股票代码给出对应的年月
};//索引类
其中map是STL的map,即映射
3.对股票价格进行可视化
来了,最难的部分
为什么我说最难?因为这玩意我根本不了解,byd,老师不教你,网络上的描述不清不楚,我当时还以为是要扔到主函数来使用。还有那个qcustomplot,byd对qt版本还有要求(刚开始没看到),给qt换版本都遇到一堆问题,nnd qtcreator6.0以上的版本用using namespace std;还会出bug,看着那一个又一个的error,感觉都要寄了
不过最后是成功克服
先说说qcustomplot的部署吧:
Qt Plotting Widget QCustomPlot - Setting Up
这是官网,最新版本的qcustomplot要求qt版本不高于6.4(现在最新的基本都是6.7,6.8),里面也有教程,简单说就是把qcustomplot.cpp和.h下下来,扔到工程文件夹,让.pro添加这两个现有文件就行了,其中qt6.0以上的还要改.pro文件里面的一行,以及提升widget类(具体看里面教程)
(qcustomplot是用来画图的)
然后是qt版本的改变:
希望被虐的可以网络上找镜像下载5.15以下的离线安装包,然后用qt手动添加(太痛苦了)
当然这边有比较简单的办法:
先Win+R,然后输入cmd后回车
定位到你放qt的文件夹(这是我的文件夹,其中框出来的文件是要改qt版本的文件):
方法:Windows下cmd快速到达指定文件位置(三种方法总结)_cmd怎么转到指定文件夹-CSDN博客
(注意不是用资源管理器打开,要不然下载很慢)
然后输入:
.\MaintenanceTool.exe --mirror https://mirrors.ustc.edu.cn/qtproject
就可以镜像下载,速度更快
接下来
第二张图点完archive之后记得点筛选
第三张图选自己想要的版本就行了,相应版本的不要都选了,只要如图所示的MinGW就行了(我大作业只要这个就是了)
接下来就可以在qtcreator的构建界面添加构建的qt版本了(可以在新建工程的时候选)
接下来是qt的ui设计的使用
先构建带有ui的项目
构建的时候选自己想要的qt版本就行了
双击该文件就可以进行ui编辑
写组件的槽函数
(以上图片来自助教的ppt)
想要使用qt的ui设计,就需要了解一下信号和槽:
【Qt 学习笔记】详解Qt中的信号和槽_从信号与槽开始学qt-CSDN博客
简单来说就是信号触发的时候,执行槽函数
还需要了解一下qt ui设计的控件,就是ui设计左边那一栏:
【Qt教程】2.1 - Qt5 UI设计器、常用控件_打开qt5 设计器-CSDN博客
提前说一下,主函数main是不需要改的,qt已经给你弄好了,主要改变的是mainwindow(或者你把mainwindow改成的其他名称,以下我都称为mainwindow)
这一次的大作业我只用到了widget,lineedit,pushbutton这几个控件,相应的操作可以上网找,其中给用户输入候选项可以了解一下qt的completer,获取文件路径可以了解一下qt的getfilename函数
想要用哪个控件,就把它拖到中间,然后为它调整大小,位置,设计槽函数
比如我给一个pushbutton控件命名为“选择文件”,然后我向上图所示的一样,转到槽函数,然后选择clicked()信号,qt就会自动转到mainwindow.cpp,给你写好槽函数的框架,你填充函数内容就行了
对于一些控件的使用,比如lineedit,我想获取用户输入的内容,但是信号是在pushbutton的clicked()那里,我们可以通过在函数中用ui->lineedit(或者你给他取的名字)来使用这个控件,获取输入的内容就是:
QString str = ui->lineedit->text();
说实话,我觉得这是比较坑的一部分,因为对ui的定义文件并没有显示在工程中,当时我都不知道该怎么用(或者说我太菜了)
关于绘制k线图
助教已经给出示例代码了:
ui->custom_plot->clearItems();
ui->custom_plot->clearGraphs();
ui->custom_plot->clearPlottables();
ui->custom_plot->plotLayout()->clear();
ui->custom_plot->replot();
QCPAxisRect *cs_axis_rect = new QCPAxisRect(ui->custom_plot), *vol_axis_rect = new QCPAxisRect(ui->custom_plot);
ui->custom_plot->plotLayout()->addElement(0, 0, cs_axis_rect);
ui->custom_plot->plotLayout()->addElement(1, 0, vol_axis_rect);
vol_axis_rect->setMaximumSize(QSize(QWIDGETSIZE_MAX, 100));
for(QCPAxis *axis : cs_axis_rect->axes()) {
axis->setLayer("axes");
axis->grid()->setLayer("grid");
}
for(QCPAxis *axis : vol_axis_rect->axes()) {
axis->setLayer("axes");
axis->grid()->setLayer("grid");
}
QCPFinancial *candle_stick = new QCPFinancial(cs_axis_rect->axis(QCPAxis::atBottom), cs_axis_rect->axis(QCPAxis::atLeft));
QCPBars *volume_pos = new QCPBars(vol_axis_rect->axis(QCPAxis::atBottom), vol_axis_rect->axis(QCPAxis::atLeft));
QCPBars *volume_neg = new QCPBars(vol_axis_rect->axis(QCPAxis::atBottom), vol_axis_rect->axis(QCPAxis::atLeft));
QCPDataContainer<QCPFinancialData> QCP_financial_data;
QSharedPointer<QCPAxisTickerText> text_ticker(new QCPAxisTickerText);
// 替换为你读取到的数据
QDateTime currentDateTime = QDateTime::currentDateTime();
qint64 seed = currentDateTime.toMSecsSinceEpoch();
QRandomGenerator generator(seed);
for (int i=1; i<=31; i++) {
QCPFinancialData data;
data.key = i;
data.open = generator.generateDouble()*10;
data.close = generator.generateDouble()*10;
data.high = std::max(data.open, data.close) + generator.generateDouble();
data.low = std::min(data.open, data.close) - generator.generateDouble();
qDebug() << data.open << data.close << data.high << data.low;
QCP_financial_data.add(data);
(i % 2 ? volume_neg : volume_pos)->addData(data.key, generator.generateDouble()*10);
text_ticker->addTick(data.key, QString::fromStdString(std::to_string(i)));
}
candle_stick->setName("日K");
candle_stick->setChartStyle(QCPFinancial::csCandlestick);
candle_stick->setBrushPositive(QColor("#EC0000"));
candle_stick->setBrushNegative(QColor("#00DA3C"));
candle_stick->setPenPositive(QColor("#8A0000"));
candle_stick->setPenNegative(QColor("#008F28"));
candle_stick->data()->set(QCP_financial_data);
volume_pos->setPen(Qt::NoPen);
volume_pos->setBrush(QColor("#EC0000"));
volume_neg->setPen(Qt::NoPen);
volume_neg->setBrush(QColor("#00DA3C"));
connect(cs_axis_rect->axis(QCPAxis::atBottom), SIGNAL(rangeChanged(QCPRange)), vol_axis_rect->axis(QCPAxis::atBottom), SLOT(setRange(QCPRange)));
connect(vol_axis_rect->axis(QCPAxis::atBottom), SIGNAL(rangeChanged(QCPRange)), cs_axis_rect->axis(QCPAxis::atBottom), SLOT(setRange(QCPRange)));
vol_axis_rect->axis(QCPAxis::atBottom)->setTicker(text_ticker);
vol_axis_rect->axis(QCPAxis::atBottom)->setTickLabelRotation(15);
cs_axis_rect->axis(QCPAxis::atBottom)->setBasePen(Qt::NoPen);
cs_axis_rect->axis(QCPAxis::atBottom)->setTickLabels(false);
cs_axis_rect->axis(QCPAxis::atBottom)->setTicks(false);
ui->custom_plot->rescaleAxes();
cs_axis_rect->axis(QCPAxis::atBottom)->setRange(0, 32);
QCPMarginGroup *group = new QCPMarginGroup(ui->custom_plot);
ui->custom_plot->axisRect()->setMarginGroup(QCP::msLeft|QCP::msRight, group);
cs_axis_rect->setMarginGroup(QCP::msLeft|QCP::msRight, group);
vol_axis_rect->setMarginGroup(QCP::msLeft|QCP::msRight, group);
ui->custom_plot->replot();
(这玩意是放在槽函数里面的,别搞错了,需要改数据的地方也已经标示出来了)
其中ui->custom_plot中的custom_plot是被提升的widget类(你部署qcustomplot的时候搞的)的名字,可以自己改掉
4.相关系数计算与热力图展示
助教的示例代码:
ui->custom_plot->clearItems();
ui->custom_plot->clearGraphs();
ui->custom_plot->clearPlottables();
ui->custom_plot->plotLayout()->clear();
ui->custom_plot->replot();
QCPAxisRect *axis_rect = new QCPAxisRect(ui->custom_plot);
ui->custom_plot->plotLayout()->addElement(0, 0, axis_rect);
QCPColorMap *color_map = new QCPColorMap(axis_rect->axis(QCPAxis::atBottom), axis_rect->axis(QCPAxis::atLeft));
QSharedPointer<QCPAxisTickerText> text_ticker(new QCPAxisTickerText);
int k = 10;
color_map->data()->setSize(k, k);
color_map->data()->setRange(QCPRange(0, k-1), QCPRange(0, k-1));
QDateTime currentDateTime = QDateTime::currentDateTime();
qint64 seed = currentDateTime.toMSecsSinceEpoch();
QRandomGenerator generator(seed);
for (int i=0; i<k; i++) {
for (int j=0; j<k; j++) {
double correlation = generator.generateDouble() * 2 - 1;
color_map->data()->setCell(i, j, correlation);
QCPItemText *textLabel = new QCPItemText(ui->custom_plot);
if (correlation > 0) textLabel->setColor(Qt::white);
else textLabel->setColor(Qt::black);
textLabel->setPositionAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
textLabel->position->setAxes(axis_rect->axis(QCPAxis::atBottom), axis_rect->axis(QCPAxis::atLeft));
textLabel->position->setAxisRect(axis_rect);
textLabel->setClipToAxisRect(true);
textLabel->position->setCoords(i, j); // 设置位置
textLabel->setText(QString::number(correlation)); // 显示数值
}
text_ticker->addTick(i, QString::fromStdString(std::to_string(i)));
}
axis_rect->axis(QCPAxis::atLeft)->setTicker(text_ticker);
axis_rect->axis(QCPAxis::atBottom)->setTicker(text_ticker);
axis_rect->axis(QCPAxis::atBottom)->setTickLabelRotation(15);
axis_rect->axis(QCPAxis::atLeft)->setTickLength(0);
axis_rect->axis(QCPAxis::atBottom)->setTickLength(0);
axis_rect->axis(QCPAxis::atLeft)->grid()->setPen(Qt::NoPen);
axis_rect->axis(QCPAxis::atBottom)->grid()->setPen(Qt::NoPen);
axis_rect->axis(QCPAxis::atLeft)->grid()->setZeroLinePen(Qt::NoPen);
axis_rect->axis(QCPAxis::atBottom)->grid()->setZeroLinePen(Qt::NoPen);
axis_rect->axis(QCPAxis::atLeft)->setRange(-0.5, k-0.5);
axis_rect->axis(QCPAxis::atBottom)->setRange(-0.5, k-0.5);
QCPColorScale *color_scale = new QCPColorScale(ui->custom_plot);
ui->custom_plot->plotLayout()->addElement(0, 1, color_scale);
color_scale->setType(QCPAxis::atRight);
color_scale->setDataRange(QCPRange(-1.0, 1.0));
color_map->setColorScale(color_scale);
QCPColorGradient gradient;
gradient.setColorStopAt(0.0, QColor("#ffffd0"));
gradient.setColorStopAt(0.5, QColor("#3eb6c5"));
gradient.setColorStopAt(1.0, QColor("#042060"));
color_map->setGradient(gradient);
color_map->setInterpolate(false);
ui->custom_plot->replot();
(实际上助教有对数值设置的有改进,在微信群里)
补充(2024/6/3):
助教改进的代码:
double correlation = code1.second.calc_correlation(code2.second);
if (!std::isnan(correlation)) {
color_map->data()->setCell(i, j, correlation);
QCPItemText *textLabel = new QCPItemText(ui->custom_plot);
if (correlation > 0) textLabel->setColor(Qt::white);
else textLabel->setColor(Qt::black);
textLabel->setPositionAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
textLabel->position->setAxes(axis_rect->axis(QCPAxis::atBottom), axis_rect->axis(QCPAxis::atLeft));
textLabel->position->setAxisRect(axis_rect);
textLabel->setClipToAxisRect(true);
textLabel->position->setCoords(i, j); // 设置位置
textLabel->setText(QString::number(correlation)); // 显示数值
}
else color_map->data()->setAlpha(i, j, 0);
(把第二个for循环的内容换成这个)
5.预测价格变动并展示
助教的示例代码:
ui->custom_plot->clearItems();
ui->custom_plot->clearGraphs();
ui->custom_plot->clearPlottables();
ui->custom_plot->plotLayout()->clear();
ui->custom_plot->replot();
QCPAxisRect *last_axis_rect = new QCPAxisRect(ui->custom_plot), *next_axis_rect = new QCPAxisRect(ui->custom_plot);
ui->custom_plot->plotLayout()->addElement(0, 0, last_axis_rect);
ui->custom_plot->plotLayout()->addElement(0, 1, next_axis_rect);
QCPGraph *last_line_plot = new QCPGraph(last_axis_rect->axis(QCPAxis::atBottom), last_axis_rect->axis(QCPAxis::atLeft));
QCPGraph *next_target_line_plot = new QCPGraph(next_axis_rect->axis(QCPAxis::atBottom), next_axis_rect->axis(QCPAxis::atLeft));
QCPGraph *next_predict_line_plot = new QCPGraph(next_axis_rect->axis(QCPAxis::atBottom), next_axis_rect->axis(QCPAxis::atLeft));
last_line_plot->setPen(QPen(Qt::red));
next_target_line_plot->setPen(QPen(Qt::red));
next_predict_line_plot->setPen(QPen(Qt::green));
QDateTime currentDateTime = QDateTime::currentDateTime();
qint64 seed = currentDateTime.toMSecsSinceEpoch();
QRandomGenerator generator(seed);
for (int i=1; i<=31; i++) {
last_line_plot->addData(i, generator.generateDouble()*10);
next_target_line_plot->addData(i, generator.generateDouble()*10);
next_predict_line_plot->addData(i, generator.generateDouble()*10);
}
for(QCPAxis *axis : last_axis_rect->axes()) {
axis->setLayer("axes");
axis->grid()->setLayer("grid");
}
for(QCPAxis *axis : next_axis_rect->axes()) {
axis->setLayer("axes");
axis->grid()->setLayer("grid");
}
ui->custom_plot->rescaleAxes();
last_axis_rect->axis(QCPAxis::atBottom)->setRange(0, 32);
next_axis_rect->axis(QCPAxis::atBottom)->setRange(0, 32);
ui->custom_plot->replot();
其中,last_line_plot是当月实际,next_target_line_plot是下月实际,next_predict_line_plot是下月预测
一些牢骚(废话)
因为我不发朋友圈也不发QQ动态,有什么事我就顺便扔CSDN上,发发牢骚
害,转到信息学院被拒绝了,byd,没想到我拿出三个竞赛奖项也不能打动他们的心,虽然说蓝桥杯A组省三是很菜的啦,但是CSP认证370分可以排到全国前10%哦,可恶啊,校内举办的那什么微观博易杯我也是以第三名拿下了二等奖(可恶为什么一等奖不是三个人,悲),虽然说不能吊打信院的所有学生吧,至少能吊打大多数吧。可恶啊。到时候高瓴人工智能院也拒绝我,我可是要到处乱说“贵校的理科不仅不行,看人也不是很准”这种话的
不过转专业都失败了我还是要自学计算机就是了,计算机本来就是靠自学的,主要是我不想学任何文科相关的专业啦
转专业失败了就是农发的狗了,到时候到处乱蹭课
乐