clientmainwindow.cpp | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
clientmainwindow.h | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
getstocklist.cpp | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
getstocklist.h | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
regularinvestment.cpp | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
regularinvestment.h | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
regularinvestment.ui | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
stock_plan.pro | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 |
clientmainwindow.cpp
@@ -35,10 +35,17 @@ m_showInfoMess = new ShowInfoMessage(this); ui->tabWidget->addTab(m_showInfoMess,"信息提示"); m_regular = new RegularInvestment(this); ui->tabWidget->addTab(m_regular,"定投设置"); // 关联一下2个界面的信号和槽,用来传递图表所需的数据及展示 connect(m_getStockList,SIGNAL(sendChartData(QLineSeries*)),m_stockPolicy,SLOT(showNewStockData(QLineSeries*))); connect(m_getStockList,SIGNAL(sendChartData(QSplineSeries*)),m_stockPolicy,SLOT(showNewStockData(QSplineSeries*))); connect(m_getStockList,SIGNAL(sendInfoMess(QString)),m_showInfoMess,SLOT(showInfo(QString))); connect(m_regular,SIGNAL(getClosePriceSignal(QString)),m_getStockList,SLOT(getLastClosePrice(QString))); connect(m_getStockList,SIGNAL(sendClosePrice(QString,QString)),m_regular,SLOT(showClosePrice(QString,QString))); } clientmainwindow.h
@@ -6,6 +6,8 @@ #include "stockpolicy.h" #include "leadingcompany.h" #include "showinfomessage.h" #include "regularinvestment.h" namespace Ui { class ClientMainWindow; @@ -27,6 +29,7 @@ StockPolicy *m_stockPolicy; LeadingCompany *m_leadingCom; // 龙头公司 ShowInfoMessage *m_showInfoMess; // 显示信息提示 RegularInvestment *m_regular; // 定投设置 }; getstocklist.cpp
@@ -915,3 +915,13 @@ m_manager.get(m_request); } void GetStockList::getLastClosePrice(QString name) { for(int i=0;i<m_model->rowCount();++i){ if(m_model->item(i,0)->text() == name){ QString closePrice = m_model->item(i,5)->text(); emit sendClosePrice(name,closePrice); } } } getstocklist.h
@@ -43,6 +43,7 @@ void sendChartData(QLineSeries*); // 折线 void sendChartData(QSplineSeries*); // 曲线 void sendInfoMess(QString); // 发送消息提示 void sendClosePrice(QString,QString); // 发送最新的价格:名字、价格 private slots: void on_pushButton_get_clicked(); @@ -66,6 +67,8 @@ void on_pushButton_industry_clicked(); void getLastClosePrice(QString name); // 通过名字获取股票价格槽 private: Ui::GetStockList *ui; // 这2个用于爬取数据的 regularinvestment.cpp
New file @@ -0,0 +1,205 @@ #include "regularinvestment.h" #include "ui_regularinvestment.h" #include <QDebug> #include <QJsonArray> #include <QJsonDocument> #include <QJsonObject> #include <qfile.h> #include <qnetworkcookie.h> #include <qnetworkreply.h> #include <QDebug> RegularInvestment::RegularInvestment(QWidget *parent) : QMainWindow(parent), ui(new Ui::RegularInvestment) { ui->setupUi(this); ui->statusbar->hide(); ui->dateTimeEdit->setDateTime(QDateTime::currentDateTime()); m_nameCodes["长江电力"]= "SH600900"; m_nameCodes["中国神华"]= "SH601088"; m_nameCodes["中国电信"]= "SH601728"; m_nameCodes["中国移动"]= "SH600941"; // 处理数据爬取的操作 // 模拟浏览器的参数 QString userAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36"; m_cookie = "__utma=1.731742638.1647403301.1699341909.1700229030.32; device_id=196eef62baf016c7d95a22752d9bdbab; smidV2=20240414233939e95389ecf7ecd2f4d08524ce770aacd500753aa68e9640320; s=c611de27gr; cookiesu=651726298794778; xq_a_token=220b0abef0fac476d076c9f7a3938b7edac35f48; xqat=220b0abef0fac476d076c9f7a3938b7edac35f48; xq_r_token=1d46f0ed628506486164e5055a4993f9b54b2f4c; xq_id_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJ1aWQiOi0xLCJpc3MiOiJ1YyIsImV4cCI6MTcyOTIxMjc4NCwiY3RtIjoxNzI3NDkwOTU3MjA0LCJjaWQiOiJkOWQwbjRBWnVwIn0.C_GmKEhTaaioDMLWkgZyMXDl4duYEVmsdJHsTi7gbcNz0Tohc-uxHsaw0yBT5k-qmbrJ_RaLMCSxy06v14-R3dwL-MsiKRHxHa5qvQZN4BjEgvPRkqqvPgE_fkPLte8qQOEgd5iVkhr-4mjip0-9WCeXYiH7DygxFOBXGlgoPtpPzAtOTm5TWJmXh0ipDsIZxfNOl8jipXYaIdkv_kqLul5gqiBi5qqnwONDa24Zx-Kvpm8ySWiPFBLzZBqTuRBs4oKAMpSdOiYGLVL7dcSDDZyWqAexmrN4f19hkmd6gBHL4dCczRMDGYc1e98sQtlbZ5lgeEuuM24jjcuwCxsxXQ; u=651726298794778; Hm_lvt_1db88642e346389874251b5a1eded6e3=1727099939,1727251802,1727488707,1727491020; HMACCOUNT=1628106D67895387; acw_tc=2760828017275244258732552e9880f861be6db0c40facbdd5f223490decc2; acw_sc__v2=66f7ee8290dc3f63112948801ef331b8c97ccb35; Hm_lpvt_1db88642e346389874251b5a1eded6e3=1727524485; .thumbcache_f24b8bbe5a5934237bbc0eda20c1b6e7=t00N841S/BEpxTGOoJrbm0blWik12om0ew/whcq/V2DNtyEA8um7J+yzeGOli+6iP/TrvrH0YKH2kHlsmDb5EQ%3D%3D; ssxmod_itna=YqAOBKYve+x0ODfxBcDB4DKM7RtAA4454DkDIEC+GAqGNK3DZDiqAPGhDC8RzeL4Ko7+e2aeQvSeopd5pYDk0Ge5TB0PIjaIDB3DEx06TCCQxiiSDCeDIDWeDiDG4Gm4qGtDpxG=DjDytZ9TtDm4GWGqDmDGYBWqDgDYQDGwIXD7QDIqtW07tQDDNQKpAKDiYeHlL5uMRMtOrK7DtDjdTD/3+kZCbCcPwVFeFO=nPcDB6wxBjZRq00Un+g4mNqLYf4IDAxQuYKtgheYYoAfDhTKhhLSGx4tGY4+GDKSiMS2DDAIvdKeD; ssxmod_itna2=YqAOBKYve+x0ODfxBcDB4DKM7RtAA4454DkDIEC+GDA69mqD/YttDFhxMltFKApT7bCMH+bytp7GQQyCbBWukeAF3+jxeN2wLjbQAFcdwbeNeoohjQ4qtEnLg4TKyX2LqVL=CGaV=GqZZqbDby8DFnFbgWiZEH8zoBzBCbzqWeqwoPq7/TpL=gIRY8sVhEpnWWHQU8sz+S8=+8oRerHq0wtQnSzyQDK7Dmvr3a+VY7fezRmxKF=bDeqexYUbuuzw2eR3In9evW6tzHbQY6vp=AIOUc9l6vc0vOl9plD6D07zGGQ41uxpii2Y5s7KvYQDWGYExD7=DYKKeD=="; QByteArray cookieByte = m_cookie.toUtf8(); QList<QNetworkCookie> list; list.push_back(QNetworkCookie(cookieByte)); QVariant var; var.setValue(list); // 设置要访问的网址 m_request.setUrl(QUrl("https://xueqiu.com/?md5__1038=QqGxcDnDyiitnD05o4%2Br%3Di%3De0KDtYqCDRWOoD")); // 设置请求头,用户代理,用来模拟浏览器 m_request.setHeader(QNetworkRequest::UserAgentHeader,userAgent); // 设置cookie //m_request.setHeader(QNetworkRequest::CookieHeader, var); // 查看manager都支持哪些协议 qDebug()<<"定投管理--支持的协议:"<<m_manager.supportedSchemes(); // 关联信号槽,当请求管理对象完全打开网页之后,会将数据给槽函数处理 connect(&m_manager,SIGNAL(finished(QNetworkReply*)),this,SLOT(showAplyData(QNetworkReply*))); // 去请求首页 m_manager.get(m_request); // 处理模型 m_model = new QStandardItemModel(0,7,this); ui->tableView->setModel(m_model); QStringList labels; labels<<"时间"<<"买入价格"<<"数量(手)"<<"所需金额(元)"<<"最新价格"<<"盈亏比"<<"盈亏金额"; m_model->setHorizontalHeaderLabels(labels); } RegularInvestment::~RegularInvestment() { delete ui; } void RegularInvestment::showClosePrice(QString name, QString closePrice) { qDebug()<<name<<closePrice; ui->label_closePrice->setText(closePrice); on_lineEdit_2_returnPressed(); // 刷新总价 } void RegularInvestment::on_comboBox_currentIndexChanged(const QString &arg1) { qDebug()<<"当前股票为:"<<arg1; emit getClosePriceSignal(arg1); } void RegularInvestment::on_lineEdit_2_returnPressed() { qDebug()<<ui->lineEdit_2->text(); double price = ui->lineEdit_2->text().toInt()* 100 * ui->label_closePrice->text().toDouble(); ui->lineEdit->setText(QString::number(price)); } void RegularInvestment::on_pushButton_clicked() { m_model->setRowCount(0); // 按指定时间开始,往后递增月来投入,进行统计 qDebug()<<"执行定投回测"; // emit sendInfoMess("<font size=12 color=pink>执行MACD策略 </font>"); // int curRow = ui->tableView->currentIndex().row(); // QString symbol = m_model->item(curRow,1)->text(); QString name = ui->comboBox->currentText(); QString symbol = m_nameCodes[name]; qint64 begin = QDateTime::currentMSecsSinceEpoch(); // 取当前时间戳 int numsCnt = 1; QString period = ui->comboBox_2->currentText(); QString type = period == "月" ? "month" : "year" ; QDateTime beginDate = ui->dateTimeEdit->dateTime(); // 可以按月增加来求价格,然后和最新的价格比较看收益情况 while (beginDate.toMSecsSinceEpoch() <= begin) { qint64 start = beginDate.toMSecsSinceEpoch(); QString urlStr = QString("https://stock.xueqiu.com/v5/stock/chart/kline.json?symbol=%1&begin=%2&period=%3&type=before&count=-%4&indicator=kline,macd").arg(symbol).arg(start).arg(type).arg(numsCnt); qDebug()<<urlStr; qDebug()<<"当前股票:"<<symbol<<name; // 下一步就是根据url请求到的数据,进行分析 //m_menuIndex = 3; // 第四个菜单项 m_request.setUrl(QUrl(urlStr)); m_manager.get(m_request); beginDate = beginDate.addMonths(1); // 增加一个月 } } void RegularInvestment::showAplyData(QNetworkReply *reply) { qDebug()<<"收到响应"; // 将响应的数据,一把读取完,放到字节数组里面来处理 QByteArray buffer = reply->readAll(); // 将数据写到文件中,方便观察数据内容 QFile file("data_dingtou.txt"); file.open(QIODevice::ReadWrite | QIODevice::Text); QTextStream out(&file); out << buffer << endl; file.close(); // 下面使用JSON进行数据处理 if(reply->url().toString().indexOf("https://xueqiu.com/") != -1){ qDebug()<<"发现首页url"; qDebug()<<buffer; }else if(reply->url().toString().indexOf("https://stock.xueqiu.com/v5/stock/chart/kline.json") != -1){ qDebug()<<"查看个股情况:"; getOneStock(buffer); } } /* 要处理的单个股票的格式如下 {"data":{" ":"SH601127","column":["timestamp","volume","open","high","low","close","chg","percent","turnoverrate","amount","volume_post","amount_post"], "item":[[1680192000000,592214010,37.57,41.56,35.63,37.85,0.2,0.53,50.63,2.3075281252E10,0,0.0], [1682611200000,355174985,36.6,36.6,28.61,29.52,-8.33,-22.01,27.0,1.1568002446E10,0,0.0], [1685462400000,345031667,29.51,30.1,25.27,25.78,-3.74,-12.67,23.04,9.442101926E9,0,0.0], [1688054400000,1217980960,25.6,42.19,24.75,36.77,10.99,42.63,81.24,4.2515733378E10,0,0.0], [1688572800000,427585117,37.5,47.3,37.06,46.62,9.85,26.79,28.37,1.8368604411E10,0,0.0]]},"error_code":0,"error_description":""} */ // 单个股票的 JSON格式处理 void RegularInvestment::getOneStock(QByteArray &buffer) { QJsonDocument jd = QJsonDocument::fromJson(buffer); if(jd.isObject()){ QJsonObject jObject = jd.object(); QJsonArray jArr = jObject.value("data").toObject().value("item").toArray(); // 通过键值对取值 int cnt = jArr.count(); qDebug()<<"数组size:"<<cnt; QString symbol = jObject.value("data").toObject().value("symbol").toString(); QString code = symbol; // 股票代号 qDebug()<<"定投:"<<code<<symbol; for(int i=0;i<cnt;++i){ qint64 timestamp = jArr.at(i).toArray().at(0).toVariant().toLongLong(); double close = jArr.at(i).toArray().at(5).toVariant().toDouble(); long long volume = jArr.at(i).toArray().at(1).toVariant().toLongLong()/100; long long amount = jArr.at(i).toArray().at(9).toVariant().toLongLong()/100000000; QString curDateTime = QDateTime::fromMSecsSinceEpoch(timestamp).toString("yyyy-MM-dd"); qDebug()<<curDateTime<<close<<volume<<amount; // 处理数据保存到模型中 // labels<<"时间"<<"买入价格"<<"数量(手)"<<"所需金额(元)"<<"最新价格"<<"盈亏比"<<"盈亏金额"; double lastClose = ui->label_closePrice->text().toDouble(); int row = m_model->rowCount(); m_model->setRowCount(row+1); m_model->setItem(row,0,new QStandardItem(curDateTime)); m_model->setItem(row,1,new QStandardItem(QString::number(close))); m_model->setItem(row,2,new QStandardItem(ui->lineEdit_2->text())); m_model->setItem(row,3,new QStandardItem(QString::number(close * ui->lineEdit_2->text().toInt()*100))); m_model->setItem(row,4,new QStandardItem(ui->label_closePrice->text())); m_model->setItem(row,5,new QStandardItem(QString::number((lastClose-close)/close))); m_model->setItem(row,6,new QStandardItem(QString::number(close * ui->lineEdit_2->text().toInt()*100 *(lastClose-close)/close))); } } } void RegularInvestment::on_pushButton_sum_clicked() { double allBuy = 0; double allWin = 0; for(int i=0;i<m_model->rowCount();++i){ allBuy += m_model->item(i,3)->text().toDouble(); allWin += m_model->item(i,6)->text().toDouble(); } ui->label_buyAll->setText(QString::number(allBuy)); ui->label_winAll->setText(QString::number(allWin)); ui->label_allRate->setText(QString::number((allWin/allBuy)*100)); } regularinvestment.h
New file @@ -0,0 +1,51 @@ #ifndef REGULARINVESTMENT_H #define REGULARINVESTMENT_H #include <QMainWindow> #include <QMap> #include <qnetworkaccessmanager.h> #include <qnetworkrequest.h> #include <QStandardItemModel> namespace Ui { class RegularInvestment; } class RegularInvestment : public QMainWindow { Q_OBJECT public: explicit RegularInvestment(QWidget *parent = 0); ~RegularInvestment(); signals: void getClosePriceSignal(QString); // 发名字拿价格 public slots: void showClosePrice(QString name,QString closePrice); private slots: void on_comboBox_currentIndexChanged(const QString &arg1); void on_lineEdit_2_returnPressed(); void on_pushButton_clicked(); void showAplyData(QNetworkReply* reply); void getOneStock(QByteArray &buffer); void on_pushButton_sum_clicked(); private: Ui::RegularInvestment *ui; QStandardItemModel *m_model; QMap<QString,QString> m_nameCodes; // 股票名字及代号 QNetworkRequest m_request; // 用于管理请求头的 QString m_cookie; // 缓存 QNetworkAccessManager m_manager; // 用于管理http请求及响应的 }; #endif // REGULARINVESTMENT_H regularinvestment.ui
New file @@ -0,0 +1,276 @@ <?xml version="1.0" encoding="UTF-8"?> <ui version="4.0"> <class>RegularInvestment</class> <widget class="QMainWindow" name="RegularInvestment"> <property name="geometry"> <rect> <x>0</x> <y>0</y> <width>856</width> <height>627</height> </rect> </property> <property name="windowTitle"> <string>MainWindow</string> </property> <widget class="QWidget" name="centralwidget"> <layout class="QGridLayout" name="gridLayout"> <item row="0" column="0"> <widget class="QTabWidget" name="tabWidget"> <property name="currentIndex"> <number>0</number> </property> <widget class="QWidget" name="tab"> <attribute name="title"> <string>定投测试</string> </attribute> <layout class="QGridLayout" name="gridLayout_3"> <item row="0" column="0"> <widget class="QGroupBox" name="groupBox"> <property name="title"> <string>定投设置</string> </property> <layout class="QGridLayout" name="gridLayout_2"> <item row="0" column="0"> <layout class="QHBoxLayout" name="horizontalLayout"> <item> <widget class="QLabel" name="label"> <property name="text"> <string>个股</string> </property> </widget> </item> <item> <widget class="QComboBox" name="comboBox"> <property name="editable"> <bool>true</bool> </property> <item> <property name="text"> <string>长江电力</string> </property> </item> <item> <property name="text"> <string>中国神华</string> </property> </item> <item> <property name="text"> <string>中国电信</string> </property> </item> <item> <property name="text"> <string>中国移动</string> </property> </item> </widget> </item> <item> <spacer name="horizontalSpacer"> <property name="orientation"> <enum>Qt::Horizontal</enum> </property> <property name="sizeHint" stdset="0"> <size> <width>40</width> <height>20</height> </size> </property> </spacer> </item> <item> <widget class="QLabel" name="label_7"> <property name="text"> <string>周期:</string> </property> </widget> </item> <item> <widget class="QComboBox" name="comboBox_2"> <item> <property name="text"> <string>月</string> </property> </item> <item> <property name="text"> <string>年</string> </property> </item> </widget> </item> <item> <widget class="QLabel" name="label_6"> <property name="text"> <string>开始时间:</string> </property> </widget> </item> <item> <widget class="QDateTimeEdit" name="dateTimeEdit"> <property name="calendarPopup"> <bool>true</bool> </property> </widget> </item> <item> <widget class="QLabel" name="label_2"> <property name="text"> <string>最新价</string> </property> </widget> </item> <item> <widget class="QLabel" name="label_closePrice"> <property name="text"> <string>0</string> </property> </widget> </item> </layout> </item> <item row="0" column="1" rowspan="2"> <widget class="QPushButton" name="pushButton"> <property name="text"> <string>开始测试</string> </property> </widget> </item> <item row="1" column="0"> <layout class="QHBoxLayout" name="horizontalLayout_2"> <item> <widget class="QLabel" name="label_4"> <property name="text"> <string>定投金额[元]</string> </property> </widget> </item> <item> <widget class="QLineEdit" name="lineEdit"/> </item> </layout> </item> <item row="2" column="0"> <layout class="QHBoxLayout" name="horizontalLayout_3"> <item> <widget class="QLabel" name="label_5"> <property name="text"> <string>定投份数[手]</string> </property> </widget> </item> <item> <widget class="QLineEdit" name="lineEdit_2"> <property name="text"> <string>1</string> </property> </widget> </item> <item> <widget class="QLabel" name="label_10"> <property name="text"> <string>累计投入(元):</string> </property> </widget> </item> <item> <widget class="QLabel" name="label_buyAll"> <property name="text"> <string>0</string> </property> </widget> </item> <item> <widget class="QLabel" name="label_9"> <property name="text"> <string>累计收益(元):</string> </property> </widget> </item> <item> <widget class="QLabel" name="label_winAll"> <property name="text"> <string>0</string> </property> </widget> </item> <item> <widget class="QLabel" name="label_3"> <property name="text"> <string>收益比(%):</string> </property> </widget> </item> <item> <widget class="QLabel" name="label_allRate"> <property name="text"> <string>0</string> </property> </widget> </item> </layout> </item> <item row="2" column="1"> <widget class="QPushButton" name="pushButton_sum"> <property name="text"> <string>统计</string> </property> </widget> </item> </layout> </widget> </item> <item row="1" column="0"> <widget class="QTableView" name="tableView"/> </item> </layout> </widget> <widget class="QWidget" name="tab_2"> <attribute name="title"> <string>开始定投</string> </attribute> <widget class="QGroupBox" name="groupBox_2"> <property name="geometry"> <rect> <x>20</x> <y>30</y> <width>801</width> <height>111</height> </rect> </property> <property name="title"> <string>定投买入</string> </property> </widget> <widget class="QTableView" name="tableView_2"> <property name="geometry"> <rect> <x>20</x> <y>160</y> <width>801</width> <height>391</height> </rect> </property> </widget> </widget> </widget> </item> </layout> </widget> <widget class="QMenuBar" name="menubar"> <property name="geometry"> <rect> <x>0</x> <y>0</y> <width>856</width> <height>26</height> </rect> </property> </widget> <widget class="QStatusBar" name="statusbar"/> </widget> <resources/> <connections/> </ui> stock_plan.pro
@@ -31,7 +31,8 @@ leadingcompany.cpp \ showinfomessage.cpp \ customitem.cpp \ customsortproxymodel.cpp customsortproxymodel.cpp \ regularinvestment.cpp HEADERS += \ clientmainwindow.h \ @@ -40,11 +41,13 @@ leadingcompany.h \ showinfomessage.h \ customitem.h \ customsortproxymodel.h customsortproxymodel.h \ regularinvestment.h FORMS += \ clientmainwindow.ui \ getstocklist.ui \ stockpolicy.ui \ leadingcompany.ui \ showinfomessage.ui showinfomessage.ui \ regularinvestment.ui