wumu
2025-01-24 69fc6911e8c09e2a34640da642874eab0c8a2256
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
#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";
    m_nameCodes["工商银行"]= "SH601398";
 
 
    // 处理数据爬取的操作
    // 模拟浏览器的参数
    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);
 
    // 定投买入
    m_modelBuy = new QStandardItemModel(0,9,this);
    ui->tableView_buyRecord->setModel(m_modelBuy);
    QStringList buyLabels;
    buyLabels<<"申请时间"<<"申请价格(元)"<<"成交时间"<<"成交价格(元)"<<"购买数量(手)"<<"所需金额(元)"<<"最新价格(元)"<<"盈亏比"<<"盈亏金额(元)";
    m_modelBuy->setHorizontalHeaderLabels(buyLabels);
 
 
}
 
RegularInvestment::~RegularInvestment()
{
    delete ui;
}
 
void RegularInvestment::showClosePrice(QString name, QString closePrice)
{
    qDebug()<<name<<closePrice;
    if(ui->comboBox->currentText() == name){
        ui->label_closePrice->setText(closePrice);
        on_lineEdit_2_returnPressed(); // 刷新总价
    }else if(ui->comboBox_3->currentText() == name){
        ui->label_closePrice_2->setText(closePrice);
        on_lineEdit_buyNum_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));
}
 
void RegularInvestment::on_comboBox_3_currentIndexChanged(const QString &arg1)
{
    qDebug()<<"开始定投当前股票为:"<<arg1;
    emit getClosePriceSignal(arg1);
}
 
void RegularInvestment::on_lineEdit_buyNum_returnPressed()
{
    qDebug()<<ui->lineEdit_buyNum->text();
    double price = ui->lineEdit_buyNum->text().toInt()* 100 * ui->label_closePrice_2->text().toDouble();
    ui->lineEdit_money->setText(QString::number(price));
}
 
void RegularInvestment::on_pushButton_buy_clicked()
{
    QString applyTime = QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss");
    QString name = ui->comboBox_3->currentText();
    QString code = m_nameCodes[name];
    QString numStr = ui->lineEdit_buyNum->text();
    QString applyPrice = ui->label_closePrice_2->text();
    double needMoney = numStr.toInt() * applyPrice.toDouble()*100;
 
    int rowCnt = m_modelBuy->rowCount();
    m_modelBuy->setRowCount(rowCnt+1);
 
    m_modelBuy->setItem(rowCnt,0,new QStandardItem(applyTime));
    m_modelBuy->setItem(rowCnt,1,new QStandardItem(applyPrice));
    m_modelBuy->setItem(rowCnt,4,new QStandardItem(numStr));
    m_modelBuy->setItem(rowCnt,5,new QStandardItem(QString::number(needMoney)));
 
}