#include "getstocklist.h"
|
#include "ui_getstocklist.h"
|
#include <QDebug>
|
#include <QFile>
|
#include <QNetworkCookieJar>
|
#include <QJsonDocument>
|
#include <QJsonObject>
|
#include <QJsonArray>
|
#include <QLibrary> // 用于加载dll动态库的类
|
|
GetStockList::GetStockList(QWidget *parent) :
|
QMainWindow(parent),
|
ui(new Ui::GetStockList)
|
{
|
ui->setupUi(this);
|
ui->pushButton_get->hide();
|
ui->statusbar->hide();
|
|
// 方案2:
|
// 如果https 访问的时候,还是爬取失败,可以代码加载动态库来支持
|
// 前提条件是把2个dll动态库拷贝的生成目录中:libeay32.dll 和 ssleay32.dll
|
// 拷贝到生成目录,就可以直接加载
|
QLibrary lb("libeay32.dll");
|
if(lb.load()){
|
qDebug()<<"load libeay32.dll 成功";
|
}
|
|
QLibrary lb2("ssleay32.dll");
|
if(lb2.load()){
|
qDebug()<<"load ssleay32.dll 成功";
|
}
|
|
// 指定当前日期类型为 week
|
m_dateType = "week";
|
// 初始化回测数量为100
|
m_maTestNum = 100;
|
|
// 模型及表格视图
|
m_model = new QStandardItemModel(this);
|
m_model->setColumnCount(10); // 设置10列
|
QStringList labels;
|
labels<<"股票名字"<<"股票代号"<<"总市值(亿)"<<"流通市值(亿)"<<"涨跌幅(%)"<<"收盘价"<<"成交额(亿)"<<"成交量(手)"<<"换手率(%)"<<"市盈率";
|
m_model->setHorizontalHeaderLabels(labels); // 设置模型的列标签名
|
m_customModel = new CustomSortProxyModel;
|
m_customModel->setSourceModel(m_model); // 设置源模型
|
|
//ui->tableView->setModel(m_model); // 将模型和视图关联
|
ui->tableView->setModel(m_customModel); // 设置自定义排序的模型
|
ui->tableView->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch); // 设置内容自适应,拉伸
|
|
// 给表格视图添加右击自定义菜单
|
ui->tableView->setContextMenuPolicy(Qt::CustomContextMenu); // 设置上下文菜单策略为自定义菜单
|
connect(ui->tableView,SIGNAL(customContextMenuRequested(QPoint)),this,SLOT(showMenu()));
|
|
m_menu = new QMenu(this);
|
|
QMenu *dateMenu = new QMenu("设置周期");
|
QAction *m30Action = dateMenu->addAction("设置为30分");
|
QAction *m60Action = dateMenu->addAction("设置为60分");
|
QAction *m120Action = dateMenu->addAction("设置为120分");
|
QAction *dayAction = dateMenu->addAction("设置为日");
|
QAction *weekAction = dateMenu->addAction("设置为周");
|
QAction *monthAction = dateMenu->addAction("设置为月");
|
QAction *yearAction = dateMenu->addAction("设置为年");
|
m_menu->addMenu(dateMenu);
|
|
connect(m30Action,&QAction::triggered,this,[&]{ m_dateType = "30m";});
|
connect(m60Action,&QAction::triggered,this,[&]{ m_dateType = "60m";});
|
connect(m120Action,&QAction::triggered,this,[&]{ m_dateType = "120m";});
|
connect(dayAction,&QAction::triggered,this,[&]{ m_dateType = "day";});
|
connect(weekAction,&QAction::triggered,this,[&]{ m_dateType = "week";}); // 修改日期类型
|
connect(monthAction,&QAction::triggered,this,[&]{ m_dateType = "month";});
|
connect(yearAction,&QAction::triggered,this,[&]{ m_dateType = "year";});
|
|
|
QMenu *testMenu = new QMenu("设置回测股票数量");
|
QAction *pre100Action = testMenu->addAction("设置为前100");
|
QAction *pre300Action = testMenu->addAction("设置为前300");
|
QAction *pre500Action = testMenu->addAction("设置为前500");
|
QAction *pre1000Action = testMenu->addAction("设置为前1000");
|
QAction *pre5000Action = testMenu->addAction("设置为前5000");
|
|
m_menu->addMenu(testMenu);
|
|
connect(pre100Action,&QAction::triggered,this,[&]{ m_maTestNum = 100;}); // 修改回测数量类型
|
connect(pre300Action,&QAction::triggered,this,[&]{ m_maTestNum = 300;});
|
connect(pre500Action,&QAction::triggered,this,[&]{ m_maTestNum = 500;});
|
connect(pre1000Action,&QAction::triggered,this,[&]{ m_maTestNum = 1000;});
|
connect(pre5000Action,&QAction::triggered,this,[&]{ m_maTestNum = 5000;});
|
|
QMenu *timerMenu = new QMenu("设置轮询执行策略");
|
QAction *timerMultiResonateAction = timerMenu->addAction("轮询多策略共振");
|
|
m_menu->addMenu(timerMenu);
|
|
m_pollMultiTimer = new QTimer(this);
|
connect(m_pollMultiTimer,SIGNAL(timeout()),this,SLOT(pollMultiSlot()));
|
|
connect(timerMultiResonateAction,&QAction::triggered,this,[&] {
|
static int cnt=0;
|
if(cnt % 2 == 0){
|
m_pollMultiTimer->start(1000*60);
|
qDebug()<<"启动轮询多策略共振的定时器";
|
}else{
|
m_pollMultiTimer->stop();
|
qDebug()<<"停止轮询多策略共振策略";
|
}
|
}); // 轮询多策略共振
|
|
|
QAction *policy = m_menu->addAction("策略分析");
|
QAction *price = m_menu->addAction("最新价格");
|
QAction *maPolicy = m_menu->addAction("MA策略");
|
QAction *macdPolicy = m_menu->addAction("MACD策略");
|
QAction *maTest100 = m_menu->addAction("MA策略-回测");
|
QAction *buttomToUpPolicy = m_menu->addAction("底部反转策略");
|
QAction *multiResonatePolicy = m_menu->addAction("多策略共振");
|
QAction *multiResonateTest100 = m_menu->addAction("多策略共振-回测");
|
QAction *oneUpCrossFourPolicy = m_menu->addAction("一阳穿四线策略");
|
QAction *oneUpCrossFourTest100 = m_menu->addAction("一阳穿四线策略-回测");
|
|
|
|
connect(policy,SIGNAL(triggered(bool)),this,SLOT(policySlot())); // 当点击菜单策略分析之后,就会出发槽 policySlot 函数
|
connect(price,SIGNAL(triggered(bool)),this,SLOT(priceSlot()));
|
connect(maPolicy,SIGNAL(triggered(bool)),this,SLOT(maPolicySlot())); // MA均线策略
|
connect(macdPolicy,SIGNAL(triggered(bool)),this,SLOT(macdPolicySlot())); // MA均线策略
|
connect(maTest100,SIGNAL(triggered(bool)),this,SLOT(maTest100Slot())); // MA回测前100名
|
connect(buttomToUpPolicy,SIGNAL(triggered(bool)),this,SLOT(buttomToUpPolicySlot())); // 底部反转策略
|
connect(multiResonatePolicy,SIGNAL(triggered(bool)),this,SLOT(multiResonatePolicySlot())); // 多策略共振
|
connect(multiResonateTest100,SIGNAL(triggered(bool)),this,SLOT(multiResonateTest100Slot())); // 多策略共振回测
|
connect(oneUpCrossFourPolicy,SIGNAL(triggered(bool)),this,SLOT(oneUpCrossFourSlot())); // 一阳穿四线策略
|
connect(oneUpCrossFourTest100,SIGNAL(triggered(bool)),this,SLOT(oneUpCrossFourTest100Slot())); // 一阳穿四线回测
|
|
|
// 处理数据爬取的操作
|
// 模拟浏览器的参数
|
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*)));
|
on_pushButton_get_clicked();
|
|
// 表格列排序
|
ui->tableView->setSortingEnabled(true);
|
// ui->tableView->setSortingEnabled(false);
|
// ui->tableView->horizontalHeader()->setSortIndicatorShown(false);
|
// connect(ui->tableView->horizontalHeader(),&QHeaderView::sortIndicatorChanged,this,[=](int index,Qt::SortOrder order){
|
// qDebug()<<"sort:"<<index<<order;
|
// //m_model->sort(index,order);
|
// m_customModel->sort(index,order);
|
// ui->tableView->horizontalHeader()->setSortIndicatorShown(true);
|
|
// });
|
|
// 定时获取股票代号的定时器相关
|
m_getCodeTimer = new QTimer(this);
|
connect(m_getCodeTimer,SIGNAL(timeout()),this,SLOT(getCodeSlot()));
|
|
}
|
|
GetStockList::~GetStockList()
|
{
|
delete ui;
|
}
|
|
/*
|
* 要处理的大概格式如下
|
*
|
* {"data":{"count":5000,"list":[{"symbol":"SZ300817","net_profit_cagr":-17.50317062659299,"north_net_inflow":null,
|
* "ps":4.4809,"type":11,"percent":20.03,"has_follow":false,"tick_size":0.01,"pb_ttm":3.2607,"float_shares":99366912,
|
* "current":18.04,"amplitude":24.02,"pcf":21.3128,"current_year_percent":28.25,"float_market_capital":1.792579092E9,
|
* "north_net_inflow_time":null,"market_capital":3.1504802E9,"dividend_yield":1.153,"lot_size":100,"roe_ttm":5.6761589850147,
|
* "total_percent":78.15,"percent5m":0.0,"income_cagr":2.235799161377394,"amount":3.5973639118E8,"chg":3.01,
|
* "issue_date_ts":1581955200000,"eps":0.32,"main_net_inflows":6078207.0,"volume":21355714,"volume_ratio":4.35,"pb":3.143,
|
* "followers":6931,"turnover_rate":21.49,"first_percent":43.98,"name":"双飞股份","pe_ttm":56.123,"total_shares":174638592,
|
* "limitup_days":1}]}}
|
*/
|
|
// 获取所有沪深股票的信息
|
void GetStockList::getStockAllCode(QByteArray &buffer)
|
{
|
// 使用JSON进行数据处理
|
QJsonDocument jd = QJsonDocument::fromJson(buffer);
|
if(jd.isArray()){
|
qDebug()<<"js array";
|
|
}else if(jd.isObject()){
|
qDebug()<<"js object";
|
QJsonObject jobject = jd.object();
|
QStringList jlist = jobject.keys();
|
qDebug()<<"jlist:"<<jlist; // 输出一下一级键的情况
|
// 通过键值对的方式提取数据
|
int count = jobject["data"].toObject()["count"].toInt();
|
qDebug()<<"count:"<<count;
|
QJsonArray listData = jobject["data"].toObject()["list"].toArray();
|
count = listData.size(); // 适应新版的处理
|
for(int i=0;i<count;++i){
|
QString symbol = listData.at(i).toObject().value("symbol").toString(); // 股票代号
|
QString name = listData.at(i).toObject().value("name").toString(); // 股票名字
|
double market_capital = listData.at(i).toObject().value("market_capital").toDouble()/100000000; // 总市值 单位 亿
|
double float_market_capital = listData.at(i).toObject().value("float_market_capital").toDouble()/100000000; // 流通市值 单位 亿
|
double percent = listData.at(i).toObject().value("percent").toDouble(); // 涨跌幅 百分比,大于0上涨,小于0下跌
|
double current = listData.at(i).toObject().value("current").toDouble(); // 收盘价
|
double amount = listData.at(i).toObject().value("amount").toDouble()/100000000; // 成交额 单位 亿
|
double volume = listData.at(i).toObject().value("volume").toInt(); // 成交量 单位 手
|
double turnover_rate = listData.at(i).toObject().value("turnover_rate").toDouble(); // 换手率 百分比
|
double pe_ttm = listData.at(i).toObject().value("pe_ttm").toDouble(); // PE值 市盈率 百分比
|
//qDebug()<<name<<symbol<<market_capital;
|
|
m_codeNames[symbol] = name; // 添加或覆盖键值对,保存股票代号和股票名字到map中
|
|
// 添加模型行的数据:股票名字、股票代号 总市值 流通市值 涨跌幅 收盘价 成交额 成交量 换手率 市盈率
|
QList<QStandardItem*> rowItems;
|
rowItems.append(new QStandardItem(name));
|
rowItems.append(new QStandardItem(symbol));
|
rowItems.append(new QStandardItem(QString::number(market_capital,'f',2)));
|
rowItems.append(new QStandardItem(QString::number(float_market_capital)));
|
//rowItems.append(new CustomItem(QString::number(float_market_capital)));
|
QStandardItem *percentItem = new QStandardItem(QString::number(percent));
|
if(percent > 0){
|
percentItem->setData(QColor("red"),Qt::DecorationRole); // 添加一个装饰的颜色为红色
|
percentItem->setData(QColor("red"),Qt::TextColorRole); // 将字体颜色设置为红色
|
rowItems.at(0)->setData(QColor("red"),Qt::TextColorRole); // 将股票名字设置为红色
|
}
|
else if(percent < 0){
|
percentItem->setData(QColor("green"),Qt::BackgroundColorRole);
|
rowItems.at(0)->setData(QColor("green"),Qt::TextColorRole);
|
}
|
rowItems.append(percentItem);
|
rowItems.append(new QStandardItem(QString::number(current)));
|
rowItems.append(new QStandardItem(QString::number(amount)));
|
rowItems.append(new QStandardItem(QString::number(volume)));
|
rowItems.append(new QStandardItem(QString::number(turnover_rate)));
|
if(pe_ttm > 0){
|
rowItems.append(new QStandardItem(QString::number(pe_ttm)));
|
}
|
else{
|
rowItems.append(new QStandardItem("亏损"));
|
}
|
// 添加一行数据项到模型中
|
m_model->appendRow(rowItems);
|
}
|
}
|
}
|
|
|
/* 要处理的单个股票的格式如下
|
{"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 GetStockList::getStockOne(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; // 股票代号
|
QLineSeries *series = new QLineSeries; // QLineSeries 折线的类,QSplineSeries 为圆滑曲线类
|
series->setName(symbol); // 设置折线名字
|
//series->setColor(QColor(255,0,0)); // 设置颜色 r,g,b 红绿蓝三原色,随意组合
|
QSplineSeries *sp = new QSplineSeries;
|
sp->setName(symbol);
|
QSplineSeries *spVolume = new QSplineSeries;
|
spVolume->setName(symbol.append("--volume"));
|
QSplineSeries *spAmount = new QSplineSeries;
|
spVolume->setName(symbol.append("--amount"));
|
|
int ma10_20_flag = 0; // 标记MA金叉、死叉的情况 0:初始值,1:金叉,-1:死叉
|
long long oldVolume = 0; // MACD: 老的成交量
|
int macd_buy = 0; // 买入标志
|
double buy_price = 0; // 买入价格
|
double rate_all = 0; // 收益百分比
|
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;
|
series->append(timestamp,close); // 折线数据添加
|
sp->append(timestamp,close); // 曲线数据添加
|
spVolume->append(timestamp,volume);
|
spAmount->append(timestamp,amount);
|
if(m_menuIndex == 2){
|
// MA ma10交ma20 金叉,ma10交ma60 死叉
|
double ma5 = jArr.at(i).toArray().at(12).toVariant().toDouble();
|
double ma10 = jArr.at(i).toArray().at(13).toVariant().toDouble();
|
double ma20 = jArr.at(i).toArray().at(14).toVariant().toDouble();
|
double ma30 = jArr.at(i).toArray().at(15).toVariant().toDouble();
|
//qDebug()<<"MA5-10-20-30"<<ma5<<ma10<<ma20<<ma30;
|
if(i>0){
|
double ma5_old = jArr.at(i-1).toArray().at(12).toVariant().toDouble();
|
double ma10_old = jArr.at(i-1).toArray().at(13).toVariant().toDouble();
|
double ma20_old = jArr.at(i-1).toArray().at(14).toVariant().toDouble();
|
double ma30_old = jArr.at(i-1).toArray().at(15).toVariant().toDouble();
|
|
// if(ma5_old > ma20_old && ma5 <= ma20){
|
// // 死叉
|
// qDebug()<<"MA5-20死叉:"<<curDateTime<<" 价格:"<<close;
|
// }else if(ma5_old < ma20_old && ma5 >= ma20){
|
// // 金叉
|
// qDebug()<<"MA5-20金叉:"<<curDateTime<<" 价格:"<<close;
|
// }
|
|
if(ma10_old > ma20_old && ma10 <= ma20){
|
// 死叉
|
qDebug()<<"MA10-20死叉:"<<curDateTime<<" 价格:"<<close;
|
if(buy_price == 0) buy_price = close;
|
double tmp_rate = (close-buy_price)/buy_price;
|
rate_all += tmp_rate;
|
|
QString info = QString("<font size=8 color=green> %3 %6 MA10-20死叉:%1 价格:%2 盈利比:%4 总盈利:%5</font>").arg(curDateTime).arg(close).arg(code)
|
.arg(QString::number(tmp_rate*100)).arg(QString::number(rate_all*100)).arg(m_codeNames[code]);
|
emit sendInfoMess(info);
|
//buy_price = close; // 死叉买入的情况
|
}else if(ma10_old < ma20_old && ma10 >= ma20){
|
// 金叉
|
buy_price = close; // 金叉买入的情况
|
|
qDebug()<<"MA10-20金叉:"<<curDateTime<<" 价格:"<<close;
|
// if(buy_price == 0) buy_price = close;
|
// double tmp_rate = (close-buy_price)/buy_price;
|
// rate_all += tmp_rate;
|
QString info = QString("<font size=8 color=red> %3 %4 MA10-20金叉:%1 价格:%2 </font>").arg(curDateTime).arg(close).arg(code).arg(m_codeNames[code]);
|
//.arg(QString::number(tmp_rate*100)).arg(QString::number(rate_all*100));
|
emit sendInfoMess(info);
|
|
}
|
}
|
}else if(m_menuIndex == 3){
|
// MACD策略 结合成交量来判断会更好:买入点成交量继续放大则持有,缩小则离场
|
double dea = jArr.at(i).toArray().at(12).toVariant().toDouble();
|
double dif = jArr.at(i).toArray().at(13).toVariant().toDouble();
|
double macd = jArr.at(i).toArray().at(14).toVariant().toDouble();
|
|
if(macd_buy == 1 && oldVolume > volume){
|
QString info = QString("<font size=8 color=green> %4 MACD 成交量初次见顶 离场1:%1 价格:%2 MACD=%3 </font>").arg(curDateTime).arg(close).arg(macd).arg(code);
|
emit sendInfoMess(info);
|
macd_buy = 0;
|
oldVolume = 0;
|
|
}
|
if(i > 0){
|
double dea_old = jArr.at(i-1).toArray().at(12).toVariant().toDouble();
|
double dif_old = jArr.at(i-1).toArray().at(13).toVariant().toDouble();
|
double macd_old = jArr.at(i-1).toArray().at(14).toVariant().toDouble();
|
|
if(dif_old > dea_old && dif <= dea){
|
// 死叉
|
qDebug()<<"MACD死叉:"<<curDateTime<<" 价格:"<<close <<"MACD="<<macd ;
|
QString info=QString("<font size=8 color=green> %4 MACD死叉:%1 价格:%2 MACD=%3 </font>").arg(curDateTime).arg(close).arg(macd).arg(code);
|
emit sendInfoMess(info);
|
}else if(dif_old < dea_old && dif >= dea){
|
// 金叉
|
qDebug()<<"MACD金叉:"<<curDateTime<<" 价格:"<<close <<"MACD="<<macd <<"建议记录当前金叉MACD的值,若后面有低于此值,关注离场提示";
|
QString info=QString("<font size=9 color=red> %4 MACD金叉:%1 价格:%2 MACD=%3 建议记录当前金叉MACD的值,若后面有低于此值,关注离场提示 </font>").arg(curDateTime).arg(close).arg(macd).arg(code);
|
emit sendInfoMess(info);
|
|
macd_buy = 1;
|
oldVolume = volume;
|
}
|
}
|
}else if(m_menuIndex == 4){
|
// 底部反转策略,提前的感知的时间会更早,得到更好的预判趋势
|
// qDebug()<<"底部反转策略";
|
if(i > 0){
|
double volume_cur = jArr.at(i).toArray().at(1).toDouble();
|
double volume_old = jArr.at(i-1).toArray().at(1).toDouble();
|
double volume_rate = volume_cur / volume_old;
|
if(volume_rate > 2){
|
qDebug()<<"底部反转策略:量能比"<<volume_rate<<code <<curDateTime<<"价格:" <<close;
|
}
|
}
|
|
}else if(m_menuIndex == 5){
|
// 多策略共振:量能、MACD、MA、BOLL
|
|
int cnt = 0;
|
// 量能
|
if(i > 0){
|
double volume_cur = jArr.at(i).toArray().at(1).toDouble();
|
double volume_old = jArr.at(i-1).toArray().at(1).toDouble();
|
double volume_rate = volume_cur / volume_old;
|
if(volume_rate > 2){
|
cnt++;
|
qDebug()<<"多策略共振:量能比"<<volume_rate<<code <<curDateTime<<"价格:" <<close;
|
QString info = QString("<font size=8 color=red> %4 多策略共振:量能策略 时间:%1 价格:%2 量能比值=%3 共振值:%5</font>").arg(curDateTime).arg(close).arg(volume_rate).arg(code).arg(cnt);
|
emit sendInfoMess(info);
|
}
|
}
|
|
// MACD策略 结合成交量来判断会更好:买入点成交量继续放大则持有,缩小则离场
|
double dea = jArr.at(i).toArray().at(16).toVariant().toDouble();
|
double dif = jArr.at(i).toArray().at(17).toVariant().toDouble();
|
double macd = jArr.at(i).toArray().at(18).toVariant().toDouble();
|
|
if(macd_buy == 1 && oldVolume > volume){
|
QString info = QString("<font size=8 color=green> %4 MACD 成交量初次见顶 离场1:%1 价格:%2 MACD=%3 </font>").arg(curDateTime).arg(close).arg(macd).arg(code);
|
emit sendInfoMess(info);
|
macd_buy = 0;
|
oldVolume = 0;
|
|
}
|
if(i > 0){
|
double dea_old = jArr.at(i-1).toArray().at(16).toVariant().toDouble();
|
double dif_old = jArr.at(i-1).toArray().at(17).toVariant().toDouble();
|
double macd_old = jArr.at(i-1).toArray().at(18).toVariant().toDouble();
|
|
if(dif_old > dea_old && dif <= dea){
|
// 死叉
|
qDebug()<<"MACD死叉:"<<curDateTime<<" 价格:"<<close <<"MACD="<<macd ;
|
QString info=QString("<font size=8 color=green> %4 MACD死叉:%1 价格:%2 MACD=%3 </font>").arg(curDateTime).arg(close).arg(macd).arg(code);
|
emit sendInfoMess(info);
|
}else if(dif_old < dea_old && dif >= dea){
|
// 金叉
|
cnt++;
|
qDebug()<<"MACD金叉:"<<curDateTime<<" 价格:"<<close <<"MACD="<<macd <<"建议记录当前金叉MACD的值,若后面有低于此值,关注离场提示";
|
QString info=QString("<font size=9 color=red> %4 MACD金叉:%1 价格:%2 MACD=%3 共振值:%5 </font>").arg(curDateTime).arg(close).arg(macd).arg(code).arg(cnt);
|
emit sendInfoMess(info);
|
|
macd_buy = 1;
|
oldVolume = volume;
|
}
|
}
|
|
|
// MA ma10交ma20 金叉,ma10交ma60 死叉
|
double ma5 = jArr.at(i).toArray().at(12).toVariant().toDouble();
|
double ma10 = jArr.at(i).toArray().at(13).toVariant().toDouble();
|
double ma20 = jArr.at(i).toArray().at(14).toVariant().toDouble();
|
double ma30 = jArr.at(i).toArray().at(15).toVariant().toDouble();
|
//qDebug()<<"MA5-10-20-30"<<ma5<<ma10<<ma20<<ma30;
|
if(i>0){
|
double ma5_old = jArr.at(i-1).toArray().at(12).toVariant().toDouble();
|
double ma10_old = jArr.at(i-1).toArray().at(13).toVariant().toDouble();
|
double ma20_old = jArr.at(i-1).toArray().at(14).toVariant().toDouble();
|
double ma30_old = jArr.at(i-1).toArray().at(15).toVariant().toDouble();
|
|
// if(ma5_old > ma20_old && ma5 <= ma20){
|
// // 死叉
|
// qDebug()<<"MA5-20死叉:"<<curDateTime<<" 价格:"<<close;
|
// }else if(ma5_old < ma20_old && ma5 >= ma20){
|
// // 金叉
|
// qDebug()<<"MA5-20金叉:"<<curDateTime<<" 价格:"<<close;
|
// }
|
|
if(ma10_old > ma20_old && ma10 <= ma20){
|
// 死叉
|
qDebug()<<"MA10-20死叉:"<<curDateTime<<" 价格:"<<close;
|
if(buy_price == 0) buy_price = close;
|
double tmp_rate = (close-buy_price)/buy_price;
|
rate_all += tmp_rate;
|
|
QString info = QString("<font size=8 color=green> %3 %6 MA10-20死叉:%1 价格:%2 盈利比:%4 总盈利:%5</font>").arg(curDateTime).arg(close).arg(code)
|
.arg(QString::number(tmp_rate*100)).arg(QString::number(rate_all*100)).arg(m_codeNames[code]);
|
emit sendInfoMess(info);
|
//buy_price = close; // 死叉买入的情况
|
}else if(ma10_old < ma20_old && ma10 >= ma20){
|
// 金叉
|
cnt++;
|
buy_price = close; // 金叉买入的情况
|
|
qDebug()<<"MA10-20金叉:"<<curDateTime<<" 价格:"<<close;
|
QString info = QString("<font size=8 color=red> %3 %4 MA10-20金叉:%1 价格:%2 共振值:%5 </font>").arg(curDateTime).arg(close).arg(code).arg(m_codeNames[code]).arg(cnt);
|
//.arg(QString::number(tmp_rate*100)).arg(QString::number(rate_all*100));
|
emit sendInfoMess(info);
|
|
}
|
}
|
|
}else if(m_menuIndex == 6){
|
// 一阳穿四线
|
|
double ma5 = jArr.at(i).toArray().at(12).toVariant().toDouble();
|
double ma10 = jArr.at(i).toArray().at(13).toVariant().toDouble();
|
double ma20 = jArr.at(i).toArray().at(14).toVariant().toDouble();
|
double ma30 = jArr.at(i).toArray().at(15).toVariant().toDouble();
|
|
double open = jArr.at(i).toArray().at(2).toVariant().toDouble();
|
|
double volume_rate = 0;
|
if(i > 0){ // 计算量能比
|
double volume_cur = jArr.at(i).toArray().at(1).toDouble();
|
double volume_old = jArr.at(i-1).toArray().at(1).toDouble();
|
volume_rate = volume_cur / volume_old;
|
}
|
|
if(ma5 >= open && ma10 >= open && ma20 >= open && ma30 >= open
|
&& ma5 <= close && ma10 <= close && ma20 <= close && ma30 <= close){
|
qDebug()<<"一阳穿四线:"<< code <<curDateTime<<" 价格:"<<close << "量能比:"<<volume_rate;
|
QString info = QString("<font size=8 color=red> %3 %4 一阳穿四线:%1 价格:%2 量能比:%5 周期:%6 </font>").arg(curDateTime).arg(close).arg(code).arg(m_codeNames[code]).arg(volume_rate).arg(m_dateType);
|
emit sendInfoMess(info);
|
}
|
}
|
|
|
}
|
if(m_menuIndex == 0){
|
// 策略分析 只能选一种线形数据
|
//emit sendChartData(series); // 发送折线数据
|
emit sendChartData(sp); // 发送曲线数据 收盘价
|
emit sendChartData(spVolume); // 发送交易量曲线
|
emit sendChartData(spAmount); // 交易额曲线
|
}else if(m_menuIndex == 1){
|
// 最新价格
|
}else if(m_menuIndex == 2){
|
// MA策略
|
}else if(m_menuIndex == 3){
|
// MACD策略
|
}
|
}
|
}
|
|
|
/* 获取行业信息
|
*
|
* {"data":{"industries":[{"encode":"S1101","name":"种植业","pinyin":"zzy"},
|
* {"encode":"S1102","name":"渔业","pinyin":"yy"},{"encode":"S1103","name":"林业","pinyin":"ly"},
|
* {"encode":"S1104","name":"饲料","pinyin":"sl"},{"encode":"S1105","name":"农产品加工","pinyin":"ncpjg"},
|
* {"encode":"S1107","name":"养殖业","pinyin":"yzy"},{"encode":"S1108","name":"动物保健","pinyin":"dwbj"},
|
* {"encode":"S1109","name":"农业综合","pinyin":"nyzh"},{"encode":"S2202","name":"化学原料","pinyin":"hxyl"},
|
* {"encode":"S2203","name":"化学制品","pinyin":"hxzp"},{"encode":"S2204","name":"化学纤维","pinyin":"hxxw"
|
* */
|
|
void GetStockList::getIndustryInfo(QByteArray &buffer)
|
{
|
|
QJsonDocument jd = QJsonDocument::fromJson(buffer);
|
if(jd.isObject()){
|
QJsonObject jObject = jd.object();
|
QJsonArray jArr = jObject.value("data").toObject().value("industries").toArray(); // 通过键值对取值
|
int cnt = jArr.count();
|
for(int i=0;i<cnt;++i){
|
QJsonObject tmpObj = jArr[i].toObject();
|
QString encode = tmpObj.value("encode").toString();
|
QString name = tmpObj.value("name").toString();
|
qDebug()<<encode<<name;
|
m_industryInfo[encode] = name; // 添加到行业map里面去保存
|
|
// 接着遍历所有行业拥有的对应股票
|
m_curIndustry = encode; // 设置当前行业
|
QString url = QString("https://stock.xueqiu.com/v5/stock/screener/quote/list.json?page=1&size=100&order=desc&order_by=percent&market=CN&ind_code=%1").arg(encode);
|
m_request.setUrl(url);
|
m_manager.get(m_request);
|
}
|
|
}
|
}
|
|
|
/*
|
|
{"data":{"count":21,"list":[{"symbol":"SZ000995","net_profit_cagr":92.61556393554986,
|
"north_net_inflow":null,"ps":19.4318,"type":11,"percent":1.86,"has_follow":false,
|
"tick_size":0.01,"pb_ttm":20.688,"float_shares":177408000,"current":16.95,
|
"amplitude":8.65,"pcf":534.2042,"current_year_percent":2.73,"float_market_capital":3.0070656E9,
|
"north_net_inflow_time":null,"market_capital":3.0070656E9,"dividend_yield":null,"lot_size":100,
|
"roe_ttm":2.8913250918407045,"total_percent":90.46,"percent5m":0.53,"income_cagr":19.383233238212405,
|
"amount":5.4679898205E8,"chg":0.31,"issue_date_ts":965577600000,"eps":0.02,"main_net_inflows":-9917325.0,
|
"volume":32611719,"volume_ratio":1.31,"pb":20.688,"followers":46602,"turnover_rate":18.38,"mapping_quote_current":null,
|
"first_percent":99.74,"name":"皇台酒业","pe_ttm":731.576,"dual_counter_mapping_symbol":null,"total_shares":177408000,"limitup_days":0},
|
|
*/
|
void GetStockList::getStockByIndustry(QByteArray &buffer,QString industryCode)
|
{
|
// 通过行业获取股票信息
|
static int sAllCnt = 0;
|
QJsonDocument jd = QJsonDocument::fromJson(buffer);
|
if(jd.isObject()){
|
QJsonObject jObject = jd.object();
|
QJsonArray jArr = jObject.value("data").toObject().value("list").toArray(); // 通过键值对取值
|
int allCnt = jObject.value("data").toObject().value("count").toInt();
|
sAllCnt += allCnt;
|
int cnt = jArr.count();
|
qDebug()<<"行业:"<<industryCode<<m_industryInfo[industryCode]<<"allCnt:"<<allCnt<<"pageCnt:"<<cnt;
|
for(int i=0;i<cnt;++i){
|
QString symbol = jArr[i].toObject().value("symbol").toString();
|
QString name = jArr[i].toObject().value("name").toString();
|
m_codeAndIndustry[symbol].append(m_industryInfo[industryCode]); // 添加行业到对应map
|
qDebug()<<"股票:"<<symbol<<name<<industryCode;
|
}
|
}
|
qDebug()<<"行业统计到的股票sAllCnt"<<sAllCnt;
|
}
|
|
void GetStockList::on_pushButton_get_clicked()
|
{
|
qDebug()<<"开始请求";
|
m_manager.get(m_request);
|
qDebug()<<"请求中...";
|
}
|
|
void GetStockList::showAplyData(QNetworkReply *reply)
|
{
|
qDebug()<<"收到响应";
|
// 将响应的数据,一把读取完,放到字节数组里面来处理
|
QByteArray buffer = reply->readAll();
|
|
// 将数据写到文件中,方便观察数据内容
|
QFile file("data.txt");
|
file.open(QIODevice::ReadWrite | QIODevice::Text);
|
QTextStream out(&file);
|
out << buffer << endl;
|
file.close();
|
|
// 下面使用JSON进行数据处理
|
if(reply->url() == QUrl("https://xueqiu.com/")){
|
qDebug()<<"发现首页url";
|
qDebug()<<buffer;
|
|
}else if(reply->url().toString().indexOf("https://stock.xueqiu.com/v5/stock/chart/kline.json") != -1){
|
qDebug()<<"查看个股情况:";
|
getStockOne(buffer);
|
|
}else if(reply->url().toString().indexOf("https://stock.xueqiu.com/v5/stock/screener/quote/list.json?page=1&size=100&order=desc&order_by=percent&market=CN&ind_code") != -1){
|
qDebug()<<"根据行业获取股票信息"<<reply->url();
|
QString industryCode = reply->url().toString().split("=").back();
|
qDebug()<<"行业信息:"<<industryCode;
|
getStockByIndustry(buffer,industryCode);
|
|
}else if(reply->url().toString().indexOf("https://stock.xueqiu.com/v5/stock/screener/quote/list.json") != -1){
|
qDebug()<<"获取所有沪深股票 可以干活了";
|
getStockAllCode(buffer);
|
}else if(reply->url().toString().indexOf("https://stock.xueqiu.com/v5/stock/screener/industries.json") != -1){
|
qDebug()<<"获取行业信息";
|
getIndustryInfo(buffer);
|
}
|
|
reply->deleteLater();
|
}
|
|
void GetStockList::on_pushButton_get_2_clicked()
|
{
|
|
m_model->setRowCount(0); // 清除当前模型中的内容
|
|
// 最好输出一下所有股票及行业信息
|
qDebug()<<"一把能看到的股票数量"<<m_codeAndIndustry.size();
|
for(auto it = m_codeAndIndustry.begin();it != m_codeAndIndustry.end();++it){
|
qDebug()<<it.key()<<"所属行业数量:"<<it.value().size();
|
for(auto e:it.value()){
|
qDebug()<<e;
|
}
|
}
|
|
// // 设置要爬取的核心网址
|
// m_request.setUrl(QUrl("https://stock.xueqiu.com/v5/stock/screener/quote/list.json?page=1&size=5000&order=desc&orderby=amount&order_by=amount&market=CN&type=sh_sz"));
|
// // 执行get请求,去拿网址对应的数据
|
// m_manager.get(m_request);
|
// qDebug()<<"req ok";
|
|
// 2024-9-21 修改新版,官方做了数量限制,可以单页100条,但是不能一把取所有了
|
//m_request.setHeader(QNetworkRequest::CookieHeader,m_cookie);
|
//m_request.setHeader(QNetworkRequest::SetCookieHeader,m_cookie);
|
|
int allCnt = 6000;
|
int singlePageCnt = 90; // 单页股票的股票数量
|
int pages = allCnt/singlePageCnt;
|
|
qDebug()<<"请求股票代号:"<<QTime::currentTime();
|
for(int i=1;i<=pages;++i){
|
QString url = QString("https://stock.xueqiu.com/v5/stock/screener/quote/list.json?page=%1&size=%2&order=desc&orderby=amount&order_by=amount&market=CN&type=sh_sz").arg(i).arg(singlePageCnt);
|
m_request.setUrl(QUrl(url));
|
m_manager.get(m_request);
|
}
|
qDebug()<<"OK--完成请求股票代号:"<<QTime::currentTime();
|
|
// 使用定时器来定时获取
|
// m_getCodeTimer->start(10);
|
|
}
|
|
void GetStockList::showMenu()
|
{
|
qDebug()<<"右击菜单";
|
m_menu->popup(QCursor::pos()); // 在鼠标光标的位置弹出菜单
|
}
|
|
void GetStockList::policySlot()
|
{
|
qDebug()<<"策略查看";
|
if(m_model->rowCount() == 0)return; // 防止异常
|
|
int row = ui->tableView->currentIndex().row(); // 取出菜单所在的行号
|
// QString symbol = m_model->item(row,1)->text(); // 取当前行所在的股票代号
|
QString symbol = m_customModel->data(m_customModel->index(row,1)).toString();
|
qint64 begin = QDateTime::currentMSecsSinceEpoch(); // 取当前时间戳
|
m_numsCnt = 30; // 这里是设置获取单个股票的数据量
|
QString urlStr = QString("https://stock.xueqiu.com/v5/stock/chart/kline.json?symbol=%1&begin=%2&period=week&type=before&count=-%3&indicator=kline").arg(symbol).arg(begin).arg(m_numsCnt);
|
qDebug()<<urlStr;
|
// qDebug()<<"当前股票:"<<symbol<<m_model->item(row,0)->text();
|
qDebug()<<"当前股票:"<<symbol<<m_customModel->data(m_customModel->index(row,0)).toString();
|
// 下一步就是根据url请求到的数据,进行分析
|
m_menuIndex = 0; // 第一个菜单
|
m_request.setUrl(QUrl(urlStr)); // 设置新的网址
|
m_manager.get(m_request); // 打开网址,拿数据
|
}
|
|
void GetStockList::priceSlot()
|
{
|
qDebug()<<"最新价格";
|
if(m_model->rowCount() == 0)return;
|
int row = ui->tableView->currentIndex().row();
|
// QString symbol = m_model->item(row,1)->text(); // 取当前行所在的股票代号
|
QString symbol = m_customModel->data(m_customModel->index(row,1)).toString();
|
qint64 begin = QDateTime::currentMSecsSinceEpoch(); // 取当前时间戳
|
int numsCnt = 20;
|
QString urlStr = QString("https://stock.xueqiu.com/v5/stock/chart/kline.json?symbol=%1&begin=%2&period=day&type=before&count=-%3&indicator=kline").arg(symbol).arg(begin).arg(numsCnt);
|
qDebug()<<urlStr;
|
// 下一步就是根据url请求到的数据,进行分析
|
m_menuIndex = 1; // 第二个菜单项
|
m_request.setUrl(QUrl(urlStr));
|
m_manager.get(m_request);
|
|
}
|
|
void GetStockList::maPolicySlot()
|
{
|
qDebug()<<"执行MA策略";
|
emit sendInfoMess("<font size=12 color=pink>执行MA策略 </font>");
|
int curRow = ui->tableView->currentIndex().row();
|
// QString symbol = m_model->item(curRow,1)->text();
|
QString symbol = m_customModel->data(m_customModel->index(curRow,1)).toString();
|
qint64 begin = QDateTime::currentMSecsSinceEpoch(); // 取当前时间戳
|
int numsCnt = 300;
|
QString urlStr = QString("https://stock.xueqiu.com/v5/stock/chart/kline.json?symbol=%1&begin=%2&period=%4&type=before&count=-%3&indicator=kline,ma").arg(symbol).arg(begin).arg(numsCnt).arg(m_dateType);
|
qDebug()<<urlStr;
|
// qDebug()<<"当前股票:"<<symbol<<m_model->item(curRow,0)->text();
|
qDebug()<<"当前股票:"<<symbol<<m_customModel->data(m_customModel->index(curRow,0)).toString();
|
// 下一步就是根据url请求到的数据,进行分析
|
m_menuIndex = 2; // 第三个菜单项
|
m_request.setUrl(QUrl(urlStr));
|
m_manager.get(m_request);
|
|
}
|
|
void GetStockList::maTest100Slot()
|
{
|
// for(int i=0;i<m_model->rowCount() && i < m_maTestNum;++i){
|
// ui->tableView->setCurrentIndex(m_model->index(i,0)); // 设置当前表格索引,主要是为了设置行
|
// maPolicySlot(); // 调用MA策略去回测
|
// }
|
|
for(int i=0;i<m_customModel->rowCount() && i < m_maTestNum;++i){
|
ui->tableView->setCurrentIndex(m_customModel->index(i,0)); // 设置当前表格索引,主要是为了设置行
|
maPolicySlot(); // 调用MA策略去回测
|
}
|
}
|
|
void GetStockList::multiResonateTest100Slot()
|
{
|
for(int i=0;i<m_customModel->rowCount() && i < m_maTestNum;++i){
|
ui->tableView->setCurrentIndex(m_customModel->index(i,0)); // 设置当前表格索引,主要是为了设置行
|
multiResonatePolicySlot(); // 调用多策略共振策略去回测
|
}
|
}
|
|
void GetStockList::macdPolicySlot()
|
{
|
qDebug()<<"执行MACD策略";
|
emit sendInfoMess("<font size=12 color=pink>执行MACD策略 </font>");
|
int curRow = ui->tableView->currentIndex().row();
|
// QString symbol = m_model->item(curRow,1)->text();
|
|
QString symbol = m_customModel->data(m_customModel->index(curRow,1)).toString();
|
qint64 begin = QDateTime::currentMSecsSinceEpoch(); // 取当前时间戳
|
int numsCnt = 300;
|
QString urlStr = QString("https://stock.xueqiu.com/v5/stock/chart/kline.json?symbol=%1&begin=%2&period=week&type=before&count=-%3&indicator=kline,macd").arg(symbol).arg(begin).arg(numsCnt);
|
qDebug()<<urlStr;
|
qDebug()<<"当前股票:"<<symbol<<m_customModel->data(m_customModel->index(curRow,0)).toString();
|
// 下一步就是根据url请求到的数据,进行分析
|
m_menuIndex = 3; // 第四个菜单项
|
m_request.setUrl(QUrl(urlStr));
|
m_manager.get(m_request);
|
|
}
|
|
void GetStockList::buttomToUpPolicySlot()
|
{
|
/*
|
复盘之前的月线突破情况,放量上涨,5倍左右,并且在60日均线上冲高,不回落,大概率可以继续冲
|
关注好冲的形态,加上很好的换手率80%+,甚至100%+,说明充分换手了,突破会更好,有就会赚多倍
|
并且多日查看,比例值一直在放大,说明很靠谱,就是有一个数值比例的爬升过程,那就可以重仓买入等收益了,可以绘制一条曲线来观察情况
|
*/
|
|
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 symbol = m_customModel->data(m_customModel->index(curRow,1)).toString();
|
qint64 begin = QDateTime::currentMSecsSinceEpoch(); // 取当前时间戳
|
int numsCnt = 300;
|
QString urlStr = QString("https://stock.xueqiu.com/v5/stock/chart/kline.json?symbol=%1&begin=%2&period=%4&type=before&count=-%3&indicator=kline,macd").arg(symbol).arg(begin).arg(numsCnt).arg(m_dateType);
|
qDebug()<<urlStr;
|
qDebug()<<"当前股票:"<<symbol<<m_customModel->data(m_customModel->index(curRow,0)).toString();
|
// 下一步就是根据url请求到的数据,进行分析
|
m_menuIndex = 4; // 第五个菜单项
|
m_request.setUrl(QUrl(urlStr));
|
m_manager.get(m_request);
|
}
|
|
void GetStockList::multiResonatePolicySlot()
|
{
|
qDebug()<<"多策略共振:量能、MACD、MA、BOLL";
|
emit sendInfoMess("<font size=12 color=pink>执行多策略共振 </font>");
|
int curRow = ui->tableView->currentIndex().row();
|
// QString symbol = m_model->item(curRow,1)->text();
|
|
QString symbol = m_customModel->data(m_customModel->index(curRow,1)).toString();
|
qint64 begin = QDateTime::currentMSecsSinceEpoch(); // 取当前时间戳
|
int numsCnt = 200;
|
QString urlStr = QString("https://stock.xueqiu.com/v5/stock/chart/kline.json?symbol=%1&begin=%2&period=%4&type=before&count=-%3&indicator=kline,macd,ma,boll").arg(symbol).arg(begin).arg(numsCnt).arg(m_dateType);
|
qDebug()<<urlStr;
|
qDebug()<<"当前股票:"<<symbol<<m_customModel->data(m_customModel->index(curRow,0)).toString();
|
// 下一步就是根据url请求到的数据,进行分析
|
m_menuIndex = 5; // 第六个菜单项
|
m_request.setUrl(QUrl(urlStr));
|
m_manager.get(m_request);
|
}
|
|
void GetStockList::oneUpCrossFourSlot()
|
{
|
/* 一阳穿四线
|
K线出现了大阳线并且贯穿4条均线,说明在猛涨了,并且量能也跟上的话,就说明强劲
|
|
日K、周K、月K就很明显。
|
大趋势以周、月为主,适合中长线处理
|
---------------------------
|
也非常适合超短线的处理,30分、60分、120分的大穿阳线也很明显
|
---------------------------
|
就是开盘价和收盘价包含了一个区间,这个区间内都把Ma5 Ma10 Ma20 Ma30给包住了,说明触发了一阳穿四线
|
*/
|
qDebug()<<"一阳穿四线策略";
|
emit sendInfoMess("<font size=12 color=pink>执行一阳穿四线策略 </font>");
|
int curRow = ui->tableView->currentIndex().row();
|
// QString symbol = m_model->item(curRow,1)->text();
|
|
QString symbol = m_customModel->data(m_customModel->index(curRow,1)).toString();
|
qint64 begin = QDateTime::currentMSecsSinceEpoch(); // 取当前时间戳
|
int numsCnt = 200;
|
QString urlStr = QString("https://stock.xueqiu.com/v5/stock/chart/kline.json?symbol=%1&begin=%2&period=%4&type=before&count=-%3&indicator=kline,macd,ma,boll").arg(symbol).arg(begin).arg(numsCnt).arg(m_dateType);
|
qDebug()<<urlStr;
|
qDebug()<<"当前股票:"<<symbol<<m_customModel->data(m_customModel->index(curRow,0)).toString();
|
// 下一步就是根据url请求到的数据,进行分析
|
m_menuIndex = 6; // 第七个菜单项
|
m_request.setUrl(QUrl(urlStr));
|
m_manager.get(m_request);
|
|
}
|
|
void GetStockList::oneUpCrossFourTest100Slot()
|
{
|
for(int i=0;i<m_customModel->rowCount() && i < m_maTestNum;++i){
|
ui->tableView->setCurrentIndex(m_customModel->index(i,0)); // 设置当前表格索引,主要是为了设置行
|
oneUpCrossFourSlot(); // 调用一阳穿四线去回测
|
}
|
}
|
|
void GetStockList::getCodeSlot()
|
{
|
// 2024-9-21 修改新版,官方做了数量限制,可以单页100条,但是不能一把取所有了
|
static int allCnt = 6000;
|
static int pages = allCnt/100;
|
static int i=1;
|
|
QString url = QString("https://stock.xueqiu.com/v5/stock/screener/quote/list.json?page=%1&size=100&order=desc&orderby=amount&order_by=amount&market=CN&type=sh_sz").arg(i);
|
m_request.setUrl(QUrl(url));
|
m_manager.get(m_request);
|
|
++i;
|
if(i > pages){
|
i=1;
|
m_getCodeTimer->stop(); // 停掉定时器
|
}
|
|
}
|
|
void GetStockList::pollMultiSlot()
|
{
|
multiResonateTest100Slot(); // 多策略共振回测
|
}
|
|
void GetStockList::on_pushButton_industry_clicked()
|
{
|
// 获取行业信息,能拿到 行业代码和名字,简写等
|
QString url = "https://stock.xueqiu.com/v5/stock/screener/industries.json?category=cn";
|
m_request.setUrl(QUrl(url));
|
m_manager.get(m_request);
|
|
}
|