wumu
2025-09-11 abc5b592843b5482ddbeb576ee7fba46f2fc5e39
analysisbyrediscache.cpp
@@ -3,6 +3,11 @@
#include <QDateTime>
#include <QDebug>
#include <QElapsedTimer>
#include <QFile>
#include <QJsonArray>
#include <QJsonDocument>
#include <QJsonObject>
#include <QNetworkReply>
AnalysisByRedisCache::AnalysisByRedisCache(QWidget *parent) :
    QMainWindow(parent),
@@ -10,7 +15,8 @@
{
    ui->setupUi(this);
    ui->dateEdit->setDate(QDate::currentDate().addMonths(-1));
    ui->dateEdit->setDate(QDate::currentDate().addMonths(-1)); // 初始化开始查询时间
    ui->dateEdit_end->setDate(QDate::currentDate()); // 初始化结束时间
    if(m_dbCache.initMySQL("127.0.0.1",3306,"root","root","stock_plan")){
        qDebug()<<"mysql conn ok";
@@ -31,9 +37,16 @@
    ui->tableView_2->setModel(m_modelResult);
    QStringList labels;
    labels<<"股票名字"<<"市值"<<"收盘价"<<"涨跌幅"<<"排名"<<"交易时间"<<"排名变化"<<"底部反转时间"<<"一阳穿四线时间";
    labels<<"股票名字"<<"市值"<<"收盘价"<<"涨跌幅"<<"排  名"<<"交易时间"<<"排名变化"<<"交易额"<<"底部反转时间"<<"一阳穿四线时间";
    m_model->setHorizontalHeaderLabels(labels);
    m_modelResult->setHorizontalHeaderLabels(labels);
    //ui->tableView->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
    //ui->tableView->verticalHeader()->setSectionResizeMode(QHeaderView::Stretch);
    ui->tableView->resizeColumnToContents(0);
    ui->tableView->resizeColumnToContents(4);
    // 初始化爬虫相关的Http
    loadHttpInit(QUrl("https://xueqiu.com/S/SZ002466"));
}
AnalysisByRedisCache::~AnalysisByRedisCache()
@@ -45,8 +58,9 @@
{
    ui->label_load->setText("缓存加载中...");
    QString begin_date = ui->dateEdit->text();
    QString end_date = ui->dateEdit_end->text();
    QString limit_str = ui->comboBox->currentText();
    QString sql = QString("select * from stock_day_info where time_trade > '%1' limit %2;").arg(begin_date).arg(limit_str);
    QString sql = QString("select * from stock_day_info where time_trade > '%1' and time_trade <= '%3' limit %2;").arg(begin_date).arg(limit_str).arg(end_date);
    qDebug()<<"sql:"<<sql;
    QElapsedTimer timer;
    timer.start();
@@ -99,6 +113,469 @@
    }
}
void AnalysisByRedisCache::loadHttpInit(QUrl url)
{
    // 处理数据爬取的操作
    // 模拟浏览器的参数
    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/S/SZ002466"));
    m_request.setUrl(url);
    // 设置请求头,用户代理,用来模拟浏览器
    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*)));
}
void AnalysisByRedisCache::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 AnalysisByRedisCache::buttomToUpPolicySlot(QString symbol)
{
    /*
    复盘之前的月线突破情况,放量上涨,5倍左右,并且在60日均线上冲高,不回落,大概率可以继续冲
    关注好冲的形态,加上很好的换手率80%+,甚至100%+,说明充分换手了,突破会更好,有就会赚多倍
    并且多日查看,比例值一直在放大,说明很靠谱,就是有一个数值比例的爬升过程,那就可以重仓买入等收益了,可以绘制一条曲线来观察情况
    */
    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 = 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 AnalysisByRedisCache::oneUpCrossFourSlot(QString symbol)
{
    /*  一阳穿四线
    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,market_capital").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 AnalysisByRedisCache::updateAllFindTimeSlot()
{
    qDebug()<<"触发了更新策略时间操作";
    for(auto kv:m_codes.keys()){
        qDebug()<<"code:"<<kv<<m_codes[kv];
        //buttomToUpPolicySlot(kv);
        oneUpCrossFourSlot(kv);
    }
}
// 单个股票的 JSON格式处理
void AnalysisByRedisCache::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 || m_menuIndex == 6){
                // 底部反转策略,提前的感知的时间会更早,得到更好的预判趋势
               // 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;
                            QString info = QString("<font size=8 color=red> %4 底部反转策略:量能 时间:%1 价格:%2 量能比值=%3  </font>").arg(curDateTime).arg(close).arg(volume_rate).arg(code);
                            //emit sendInfoMess(info);
                            //修改发现的最新时间
                            updateFindTime(m_codes[code],curDateTime,7); // 下标为7
                        }
                    }
                    {
                        // 一阳穿四线
                        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();
                        long long market_cap = jArr.at(i).toArray().at(22).toVariant().toLongLong();
                        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;
                            if(volume_rate > 4){
        //                        QString info = QString("<font size=8 color=blue> %3 %4 一阳穿四线:%1 价格:%2 量能比:%5 周期:%6  市值:%7亿</font>").arg(curDateTime).arg(close).arg(code).arg(m_codeNames[code]).arg(volume_rate)
        //                                .arg(m_dateType).arg(market_cap/100000000.0);
                                //emit sendInfoMess(info);
                            }else{
        //                        QString info = QString("<font size=8 color=red> %3 %4 一阳穿四线:%1 价格:%2 量能比:%5 周期:%6  市值:%7亿</font>").arg(curDateTime).arg(close).arg(code).arg(m_codeNames[code]).arg(volume_rate)
        //                                .arg(m_dateType).arg(market_cap/100000000.0);
                                //emit sendInfoMess(info);
                            }
                            //修改发现的最新时间
                            updateFindTime(m_codes[code],curDateTime,8); // 下标为8
                        }
                    }
                }
            }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();
                long long market_cap = jArr.at(i).toArray().at(22).toVariant().toLongLong();
                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;
                    if(volume_rate > 4){
//                        QString info = QString("<font size=8 color=blue> %3 %4 一阳穿四线:%1 价格:%2 量能比:%5 周期:%6  市值:%7亿</font>").arg(curDateTime).arg(close).arg(code).arg(m_codeNames[code]).arg(volume_rate)
//                                .arg(m_dateType).arg(market_cap/100000000.0);
                        //emit sendInfoMess(info);
                    }else{
//                        QString info = QString("<font size=8 color=red> %3 %4 一阳穿四线:%1 价格:%2 量能比:%5 周期:%6  市值:%7亿</font>").arg(curDateTime).arg(close).arg(code).arg(m_codeNames[code]).arg(volume_rate)
//                                .arg(m_dateType).arg(market_cap/100000000.0);
                        //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策略
        }
    }
}
void AnalysisByRedisCache::updateFindTime(QString name, QString trade_time, int index)
{
    for(int i=0;i<m_modelResult->rowCount();++i){
        if(m_modelResult->item(i,0)->text() == name){ // 匹配到名字
            m_modelResult->setItem(i,index,new QStandardItem(trade_time)); // 更新时间
        }
    }
}
void AnalysisByRedisCache::searchAndAnalysisData(QString name)
{
    QElapsedTimer timer;
@@ -106,6 +583,7 @@
    qDebug()<<"m_result size:"<<m_result.size()<<name;
    int rank_val = 0;
    double amount_old = 0;
    int cnt = 0;
    int bigFlag = false;
    int bigRankUp = false; // 突然从很低的排名上升到大排名
@@ -180,6 +658,18 @@
                rank_val = amount_rank.toInt();
            }
            double amount = it["amount"].toDouble();
            QStandardItem *amountItem = new QStandardItem(QString::number(amount/100000000));
            if(amount_old > 0){
                if(amount / amount_old >= 3){
                    amountItem->setData(QColor("red"),Qt::BackgroundColorRole);
                    amountItem->setData(QString::number(amount / amount_old),Qt::ToolTipRole);
                }
            }
            items.append(amountItem);
            amount_old = amount;
            m_model->appendRow(items);
            if(bigFlag){
                QList<QStandardItem*> items_2;
@@ -201,6 +691,8 @@
                            items_2.back()->setData(QColor(85,255,255),Qt::BackgroundColorRole);
                        }
                    }else if(i==7){
                        // 看交易额变化
                    }
                }
                m_modelResult->appendRow(items_2);
@@ -208,6 +700,9 @@
                bigRankUp = false;
                big_3000 = false;
                big_2000 = false;
                // 保存名字信息:code-name
                m_codes.insert(it["code"].toString(),name);
            }
        }
@@ -216,6 +711,9 @@
    qDebug() << "Query executed in" << timer.elapsed() << "ms";
    qDebug()<<"滑动窗口排名-cnt:"<<m_model->rowCount()<<cnt<<"start:"<<m_model->rowCount() - cnt + 1;
    calcWindowRank(m_model->rowCount() - cnt + 1);
    // 更新时间
}
void AnalysisByRedisCache::on_pushButton_analysisByRedis_clicked()
{
@@ -236,5 +734,12 @@
    int batch_num = ui->comboBox_batchNum->currentText().toInt(); // 批量分析个股的数量
    // 拿出个股交易额排名的前N名,进行缓存分析
    emit getStockNamesSignal(batch_num);
    qDebug()<<"批量分析完成";
}
void AnalysisByRedisCache::on_pushButton_updateStrategyTime_clicked()
{
    // 更新策略的时间
    updateAllFindTimeSlot();
}