admin
2023-01-16 9190340264f947b7978072aad4b0d9660f9f891f
'交易策略优化'
16个文件已修改
414 ■■■■■ 已修改文件
ConsoleApplication/L2DataCapture.cpp 94 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ConsoleApplication/L2DataCapture.h 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ConsoleApplication/THSL2RepairTool.cpp 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ConsoleApplication/TradeListCapture.cpp 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ConsoleApplication/TradeListCapture.h 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ConsoleApplication/main.cpp 19 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/ExcelUtil.cpp 38 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/ExcelUtil.h 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/JsonUtil.h 41 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/app.aps 补丁 | 查看 | 原始文档 | blame | 历史
app/app.rc 补丁 | 查看 | 原始文档 | blame | 历史
app/app.vcxproj.user 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/appDlg.cpp 138 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/appDlg.h 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/level2DataDlg.cpp 30 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/level2DataDlg.h 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
ConsoleApplication/L2DataCapture.cpp
@@ -66,7 +66,7 @@
                    throw string("截图出错");
                }
                list<TradeData> resultList = captureLevel2TradeData(mat, index);
                list<TradeData*> resultList = captureLevel2TradeData(mat, index);
                long processTime = clock() - start;
                data_callback(index, code, start, processTime, resultList, context);
                cout << "时间消耗:" << processTime << endl;
@@ -131,7 +131,7 @@
            }
        }
        Sleep(2);
        Sleep(50);
    }
}
@@ -246,14 +246,14 @@
    return inited;
}
list<TradeData>  L2DataCapture::captureLevel2TradeData(cv::Mat& oimg, int identify) {
list<TradeData*>  L2DataCapture::captureLevel2TradeData(cv::Mat& oimg, int identify) {
    if (oimg.rows == 0 || oimg.cols == 0) {
        throw ERROR_CODE_CAPTURE_FAIL;
    }
    clock_t  starttime = clock();
    list<TradeData> resultList = captureLevel2TradeData(openCLExcuter[identify], oimg, identify);
    list<TradeData*> resultList = captureLevel2TradeData(openCLExcuter[identify], oimg, identify);
    std::cout << "-------L2行情识别结束任务: threadid-" << std::this_thread::get_id() << "  序号:" << identify << " CODE:" << gpCodes[identify] << " 耗时:" << clock() - starttime << "  数据量:" << resultList.size() << endl;
@@ -261,7 +261,7 @@
}
list<TradeData> L2DataCapture::captureLevel2TradeData(OpenCLExcuter* openCLExcuter, cv::Mat& oimg, int identify)
list<TradeData*> L2DataCapture::captureLevel2TradeData(OpenCLExcuter* openCLExcuter, cv::Mat& oimg, int identify)
{
    if (oimg.cols <= 0 || oimg.rows <= 0) {
@@ -393,9 +393,9 @@
        std::cout << "分隔完成: threadid-" << std::this_thread::get_id() << " 耗时:" << time_3 - time_2 << "总耗时:" << time_3 - time_1 << endl;
    //结果初始化
    list<TradeData> resultList;
    list<TradeData*> resultList;
    for (int i = 0; i < rowDataList.size(); i++) {
        TradeData td = TradeData();
        TradeData *td = new TradeData;
        resultList.push_back(td);
    }
@@ -407,15 +407,15 @@
    int i = 0;
    for (list<TradeData>::iterator ele = resultList.begin(); ele != resultList.end(); ++ele) {
    for (list<TradeData*>::iterator ele = resultList.begin(); ele != resultList.end(); ++ele) {
        switch (notNumberResult[i * 3])
        {
        case 0:
            (*ele).cancelTimeUnit = TIME_SECOND; break;
            (*ele)->cancelTimeUnit = TIME_SECOND; break;
        case 1:
            (*ele).cancelTimeUnit = TIME_MINITE; break;
            (*ele)->cancelTimeUnit = TIME_MINITE; break;
        case 2:
            (*ele).cancelTimeUnit = TIME_HOUR; break;
            (*ele)->cancelTimeUnit = TIME_HOUR; break;
        default:
            break;
@@ -424,11 +424,11 @@
        switch (notNumberResult[i * 3 + 1])
        {
        case 0:
            (*ele).limitPrice = LIMIT_PRICE_NORMAL; break;
            (*ele)->limitPrice = LIMIT_PRICE_NORMAL; break;
        case 1:
            (*ele).limitPrice = LIMIT_PRICE_UP; break;
            (*ele)->limitPrice = LIMIT_PRICE_UP; break;
        case 2:
            (*ele).limitPrice = LIMIT_PRICE_DOWN; break;
            (*ele)->limitPrice = LIMIT_PRICE_DOWN; break;
        default:
            break;
@@ -436,19 +436,19 @@
        switch (notNumberResult[i * 3 + 2])
        {
        case OPERATE_BUY:
            (*ele).operateType = OPERATE_BUY;
            (*ele)->operateType = OPERATE_BUY;
            break;
        case OPERATE_BUY_CANCEL:
            (*ele).operateType = OPERATE_BUY_CANCEL;
            (*ele)->operateType = OPERATE_BUY_CANCEL;
            break;
        case OPERATE_SELL:
            (*ele).operateType = OPERATE_SELL;
            (*ele)->operateType = OPERATE_SELL;
            break;
        case OPERATE_SELL_CANCEL:
            (*ele).operateType = OPERATE_SELL_CANCEL;
            (*ele)->operateType = OPERATE_SELL_CANCEL;
            break;
        case OPERATE_OPERATE_ERROR:
            (*ele).operateType = OPERATE_OPERATE_ERROR;
            (*ele)->operateType = OPERATE_OPERATE_ERROR;
            break;
        };
@@ -512,6 +512,8 @@
        index++;
    }
    free(rowSplitDataOneLevel);
    clock_t time_32 = clock();
@@ -605,7 +607,7 @@
    }
    //循环读取数字
    list<TradeData>::iterator tradeEle;
    list<TradeData*>::iterator tradeEle;
    index = 0;
    for (tradeEle = resultList.begin(); tradeEle != resultList.end(); tradeEle++) {
        uchar* lineData = numberResult[index];
@@ -629,11 +631,11 @@
        num.append(to_string(lineData[12 + 2])).append(to_string(lineData[13 + 2])).append(to_string(lineData[14 + 2])).append(to_string(lineData[15 + 2])).append(to_string(lineData[16 + 2]));
        (*tradeEle).time = time;
        (*tradeEle).num = stoi(num);
        (*tradeEle).price = price;
        (*tradeEle).index = index;
        (*tradeEle).cancelTime = stoi(cancelTime);
        (*tradeEle)->time = time;
        (*tradeEle)->num = stoi(num);
        (*tradeEle)->price = price;
        (*tradeEle)->index = index;
        (*tradeEle)->cancelTime = stoi(cancelTime);
        //释放内存
        free(lineData);
@@ -652,7 +654,7 @@
    img.release();
    rowDataList.clear();
    list<int*>().swap(rowDataList);
    free(rowSplitDataOneLevel);
    return resultList;
}
@@ -727,7 +729,7 @@
                zeroData[r * _NUMBER_GP_CODE_WIDTH + c] = ImgUtil::NUMS_GP_CODE[0].data.ptr<uchar>(r)[c];
            }
        }
        int num_length_per_ele = 6;
        int num_length_per_ele = 7;
        int ele_count_per_line = 6;
        int line_number_count = ele_count_per_line * num_length_per_ele;
        unsigned char* totalNumberData = (unsigned char*)malloc(sizeof(unsigned char) * (_NUMBER_GP_CODE_HEIGHT * 1) * _NUMBER_GP_CODE_WIDTH * 10 * line_number_count);
@@ -772,48 +774,48 @@
        //循环读取数字
        uchar* lineData = numberResult[0];
        string sellOneTime = "";
        sellOneTime.append(to_string(lineData[0])).append(to_string(lineData[1]));
        sellOneTime.append(to_string(lineData[1])).append(to_string(lineData[2]));
        sellOneTime.append(":");
        sellOneTime.append(to_string(lineData[2])).append(to_string(lineData[3]));
        sellOneTime.append(to_string(lineData[3])).append(to_string(lineData[4]));
        sellOneTime.append(":");
        sellOneTime.append(to_string(lineData[4])).append(to_string(lineData[5]));
        sellOneTime.append(to_string(lineData[5])).append(to_string(lineData[6]));
        string buyOneTime = "";
        buyOneTime.append(to_string(lineData[6])).append(to_string(lineData[7]));
        buyOneTime.append(to_string(lineData[num_length_per_ele*1+1])).append(to_string(lineData[num_length_per_ele * 1 + 2]));
        buyOneTime.append(":");
        buyOneTime.append(to_string(lineData[8])).append(to_string(lineData[9]));
        buyOneTime.append(to_string(lineData[num_length_per_ele * 1 + 3])).append(to_string(lineData[num_length_per_ele * 1 + 4]));
        buyOneTime.append(":");
        buyOneTime.append(to_string(lineData[10])).append(to_string(lineData[11]));
        buyOneTime.append(to_string(lineData[num_length_per_ele * 1 + 5])).append(to_string(lineData[num_length_per_ele * 1 + 6]));
        string sellOnePrice = "";
        for (int i = 0; i < 6; i++)
        for (int i = 0; i < num_length_per_ele; i++)
        {
            sellOnePrice.append(to_string(lineData[12 + i]));
            if (i == 3) {
            sellOnePrice.append(to_string(lineData[num_length_per_ele * 2 + i]));
            if (i == num_length_per_ele - 3) {
                sellOnePrice.append(".");
            }
        }
        string sellOneNum = "";
        for (int i = 0; i < 6; i++)
        for (int i = 0; i < num_length_per_ele; i++)
        {
            sellOneNum.append(to_string(lineData[18 + i]));
            sellOneNum.append(to_string(lineData[num_length_per_ele * 3 + i]));
        }
        string buyOnePrice = "";
        for (int i = 0; i < 6; i++)
        for (int i = 0; i < num_length_per_ele; i++)
        {
            buyOnePrice.append(to_string(lineData[24 + i]));
            if (i == 3) {
            buyOnePrice.append(to_string(lineData[num_length_per_ele * 4 + i]));
            if (i == num_length_per_ele - 3) {
                buyOnePrice.append(".");
            }
        }
        string buyOneNum = "";
        for (int i = 0; i < 6; i++)
        for (int i = 0; i < num_length_per_ele; i++)
        {
            buyOneNum.append(to_string(lineData[30 + i]));
            buyOneNum.append(to_string(lineData[num_length_per_ele * 5 + i]));
        }
        //释放内存
@@ -840,7 +842,7 @@
}
//捕获level2的盘口数据
list<TradeData> L2DataCapture::captureLevel2TradeData(HWND hwnd, int index) throw(int) {
list<TradeData*> L2DataCapture::captureLevel2TradeData(HWND hwnd, int index) throw(int) {
    clock_t  starttime = clock();
    cv::Mat img = CaptureUtil::capture(hwnd);
@@ -856,12 +858,12 @@
    std::map<string, TradeData> map;
    */
    try {
        list<TradeData> resultList = captureLevel2TradeData(img, index);
        list<TradeData*> resultList = captureLevel2TradeData(img, index);
        return resultList;
    }
    catch (int code) {
    }
    list<TradeData> tempList;
    list<TradeData*> tempList;
    return tempList;
}
ConsoleApplication/L2DataCapture.h
@@ -18,7 +18,7 @@
    string buyOneVolumn;
};
typedef void (*CallbackFun)(int index, string code,long captureTime,long processTime, list<TradeData> dataList, void* contex);
typedef void (*CallbackFun)(int index, string code,long captureTime,long processTime, list<TradeData*> dataList, void* contex);
typedef void (*CallbackFun_Trade_Queue)(int index, string code, L2TradeQueue info, void* contex);
@@ -86,9 +86,9 @@
    bool isInited();
    //捕获level2的盘口数据
    static list<TradeData>  captureLevel2TradeData(HWND hwnd,int index) throw(int);
    static list<TradeData>  captureLevel2TradeData(cv::Mat& oimg,int identify);
    static list<TradeData>  captureLevel2TradeData(OpenCLExcuter *openCLExcuter, cv::Mat& oimg, int identify);
    static list<TradeData*>  captureLevel2TradeData(HWND hwnd,int index) throw(int);
    static list<TradeData*>  captureLevel2TradeData(cv::Mat& oimg,int identify);
    static list<TradeData*>  captureLevel2TradeData(OpenCLExcuter *openCLExcuter, cv::Mat& oimg, int identify);
    static L2TradeQueue captureLevel2TradeQueueData(HWND hwnd, int index);
ConsoleApplication/THSL2RepairTool.cpp
@@ -11,7 +11,7 @@
void THSL2RepairTool::repairL2Data(RecognitionManager *recognitionManager, int index, string code, double min_price, double max_price)
{
    try {
        list<TradeData> dataList;
        list<TradeData*> dataList;
        try {
            cv::Mat mat = CaptureUtil::capture(index, CAPTURE_TYPE_L2);
            dataList = L2DataCapture::captureLevel2TradeData(openCLExcuter, mat, index);
@@ -57,8 +57,8 @@
            Sleep(1000);
            bool normal = true;
            for (list<TradeData>::iterator ele = dataList.begin();ele != dataList.end();++ele) {
                double price = stod((*ele).price);
            for (list<TradeData*>::iterator ele = dataList.begin();ele != dataList.end();++ele) {
                double price = stod((*ele)->price);
                if (price >= max_price + 0.0001) {
                    normal = false;
                    break;
ConsoleApplication/TradeListCapture.cpp
@@ -792,6 +792,20 @@
    return codes;
}
HWND TradeListCapture::getSimpleTradeLeftMenu(HWND tradeWin)
{
    HWND win = FindWindowEx(tradeWin, NULL, TEXT("AfxMDIFrame140s"), NULL);
    if (win <= 0) {
        throw string("未获取到菜单句柄");
    }
    win = FindWindowEx(win, NULL, TEXT("AfxWnd140s"), NULL);
    if (win <= 0) {
        throw string("未获取到菜单句柄");
    }
    win = FindWindowEx(win, NULL, NULL, TEXT("HexinScrollWnd"));
    return win;
}
list<TradeDelegateData> TradeListCapture::captureSimpleTradeDelegateInfo(cv::Mat img)
{
    cv::Mat grayImg = grayImgs(img, openCLExcuterDelegate);
@@ -863,10 +877,17 @@
        }
    }
    else {
        //如果最后一条数据与倒数第二条数据的
        std::advance(end, -1);
        int end_start = (*end)[0];
        std::advance(end, -1);
        if (end_start - (*end)[1]>15) {
            //删除最后1条数据
            std::advance(end, 1);
        free(*end);
        rowData.erase(end);
    }
    }
    int* rowIndex = (int*)malloc(sizeof(int) * rowData.size() * 4);
ConsoleApplication/TradeListCapture.h
@@ -112,6 +112,9 @@
    static list<TradeDelegateData> captureTradeDelegateInfo();
    // 获取交易页面的左侧菜单HWND
    static HWND getSimpleTradeLeftMenu(HWND tradeWin);
    //精简版交易委托
    static list<TradeDelegateData> captureSimpleTradeDelegateInfo(cv::Mat img);
ConsoleApplication/main.cpp
@@ -157,7 +157,7 @@
    ImgUtil::init();
    OpenCLExcuter* openCLExcuter = new OpenCLExcuter();
    openCLExcuter->init();
    cv::Mat img = cv::imread("C:\\Users\\Administrator\\Desktop\\ocr\\l2_trade_queue_2.png");
    cv::Mat img = cv::imread("C:\\Users\\Administrator\\Desktop\\ocr\\trade\\Snipaste_2023-01-13_18-23-34.png");
    uchar* datas = (uchar*)malloc(sizeof(uchar) * img.rows * img.cols);
    if (img.channels() == 4)
    {
@@ -172,7 +172,7 @@
    cv::Mat binary;
    threshold(img1, binary, 96, 255, cv::THRESH_BINARY);
    cv::imwrite("C:\\Users\\Administrator\\Desktop\\ocr\\l2_trade_queue_gray.png", img1);
    cv::imwrite("C:\\Users\\Administrator\\Desktop\\ocr\\trade\\Snipaste_2023-01-13_18-23-34_gray.png", img1);
}
@@ -187,17 +187,9 @@
    OpenCLExcuter* openCLExcuter = new OpenCLExcuter();
    openCLExcuter->init();
    L2DataCapture *capture = new L2DataCapture();
    HWND win = THSActionUtil::getL2Win();
    CaptureUtil::init(win);
    while (TRUE)
    {
        //cv::Mat img = cv::imread("C:\\Users\\Administrator\\Desktop\\ocr\\l2_trade_queue_2_2.png");
        cv::Mat img = CaptureUtil::capture(0, CAPTURE_TYPE_TRADE_QUEUE);
    cv::Mat img = cv::imread("C:\\Users\\Administrator\\Desktop\\ocr\\l2_trade_queue_3.png");
        L2TradeQueue tradeQueue = capture->captureLevel2TradeQueueData(openCLExcuter, img, 0);
        printf("\n");
        Sleep(10);
    }
}
void testCaptureL2TradeQueue() {
@@ -215,7 +207,7 @@
    ImgUtil::init();
    TradeListCapture* capture = new TradeListCapture();
    capture->init(NULL,NULL,NULL);
    cv::Mat oimg = cv::imread("C:\\Users\\Administrator\\Desktop\\ocr\\trade\\Snipaste_2022-12-23_09-42-19.png");
    cv::Mat oimg = cv::imread("C:\\Users\\Administrator\\Desktop\\ocr\\trade\\Snipaste_2023-01-03_09-33-57.png");
    capture->captureSimpleTradeDelegateInfo(oimg);
}
@@ -228,8 +220,7 @@
int main() {
    //grayImg();
    testTradeSuccess();
    grayImg();
    return 1;
    //testL2();
    //if (TRUE) {
app/ExcelUtil.cpp
@@ -6,15 +6,15 @@
using namespace xls;
using namespace xlslib_core;
void ExcelUtil::save(list<TradeData> data, string path) {
    list<TradeData>::iterator ele1= data.begin();
void ExcelUtil::save(list<TradeData*> data, string path) {
    list<TradeData*>::iterator ele1= data.begin();
    Json::Value root,item;
    Json::StreamWriterBuilder writerBuilder;
    //自动换行
    writerBuilder.settings_["indentation"] = "";
    item["time"] = (*ele1).time;
    item["price"] = (*ele1).price;
    item["num"] = (*ele1).num;
    item["time"] = (*ele1)->time;
    item["price"] = (*ele1)->price;
    item["num"] = (*ele1)->num;
    root[0] = item;
    std::ostringstream os;
    std::unique_ptr<Json::StreamWriter> jsonWriter(writerBuilder.newStreamWriter());
@@ -36,49 +36,49 @@
    int index = 0;
    list<TradeData>::iterator ele;
    list<TradeData*>::iterator ele;
    for (ele = data.begin();ele != data.end();ele++) {
        TradeData tradeData = *ele;
        TradeData *tradeData = *ele;
        index++;
        std::ostringstream out_str;
        out_str << setiosflags(ios::fixed) << std::setprecision(2) << stof(tradeData.price);
        out_str << setiosflags(ios::fixed) << std::setprecision(2) << stof(tradeData->price);
        string t = tradeData.time;
        if (tradeData.cancelTime > 0)
        string t = tradeData->time;
        if (tradeData->cancelTime > 0)
        {
            t.append(" ").append(to_string(tradeData.cancelTime));
            t.append(" ").append(to_string(tradeData->cancelTime));
            string cancelTimeUnit;
            if (tradeData.cancelTimeUnit == TIME_SECOND) {
            if (tradeData->cancelTimeUnit == TIME_SECOND) {
                cancelTimeUnit = "s";
            }
            else  if (tradeData.cancelTimeUnit == TIME_MINITE) {
            else  if (tradeData->cancelTimeUnit == TIME_MINITE) {
                cancelTimeUnit = "m";
            }
            else  if (tradeData.cancelTimeUnit == TIME_HOUR) {
            else  if (tradeData->cancelTimeUnit == TIME_HOUR) {
                cancelTimeUnit = "h";
            }
            t.append(cancelTimeUnit);
        }
        ws->label(index, 0,t, xf);
        ws->label(index, 1, out_str.str(), xf);
        if (tradeData.limitPrice == LIMIT_PRICE_NORMAL) {
        if (tradeData->limitPrice == LIMIT_PRICE_NORMAL) {
            ws->label(index, 2, L"正常价", xf);
        }
        else  if (tradeData.limitPrice == LIMIT_PRICE_UP) {
        else  if (tradeData->limitPrice == LIMIT_PRICE_UP) {
            ws->label(index, 2, L"涨停价", xf);
        }
        else  if (tradeData.limitPrice == LIMIT_PRICE_DOWN) {
        else  if (tradeData->limitPrice == LIMIT_PRICE_DOWN) {
            ws->label(index, 2, L"跌停价", xf);
        }
        ws->label(index, 3, to_string(tradeData.num), xf);
        ws->label(index, 3, to_string(tradeData->num), xf);
   
        wstring operate;
        switch (tradeData.operateType)
        switch (tradeData->operateType)
        {
        case OPERATE_BUY:
            operate = L"买";break;
app/ExcelUtil.h
@@ -13,7 +13,7 @@
class ExcelUtil
{
public:
    static void save(list<TradeData> data, string path);
    static void save(list<TradeData*> data, string path);
    static std::list<ExcelGPCodeInfo> readGPCodes(string path);
app/JsonUtil.h
@@ -13,20 +13,20 @@
public:
    static  Json::Value toJson(std::list<TradeData> dataList) {
    static  Json::Value toJson(std::list<TradeData*> dataList) {
        Json::Value root;
        std::list<TradeData>::iterator ele;
        std::list<TradeData*>::iterator ele;
        int index = 0;
        for (ele = dataList.begin();ele != dataList.end();ele++) {
            Json::Value  item;
            item["time"] = (*ele).time;
            item["price"] = (*ele).price;
            item["num"] = (*ele).num;
            item["limitPrice"] = (*ele).limitPrice;
            item["operateType"] = (*ele).operateType;
            item["cancelTime"] = (*ele).cancelTime;
            item["cancelTimeUnit"] = (*ele).cancelTimeUnit;
            item["time"] = (*ele)->time;
            item["price"] = (*ele)->price;
            item["num"] = (*ele)->num;
            item["limitPrice"] = (*ele)->limitPrice;
            item["operateType"] = (*ele)->operateType;
            item["cancelTime"] = (*ele)->cancelTime;
            item["cancelTimeUnit"] = (*ele)->cancelTimeUnit;
            root[index++] = item;
        }
        return root;
@@ -54,10 +54,12 @@
        std::unique_ptr<Json::StreamWriter> jsonWriter(writerBuilder.newStreamWriter());
        jsonWriter->write(json, &os);
        string jsonStr = os.str();
        //释放资源
        jsonWriter.reset();
        return jsonStr;
    }
    static  std::string loadL2Data(int clientID, int channel, string code, long captureTime, long processTime, std::list<TradeData> dataList) {
    static  std::string loadL2Data(int clientID, int channel, string code, long captureTime, long processTime, std::list<TradeData*> dataList) {
        Json::Value data;
        data["channel"] = channel;
        data["code"] = code;
@@ -305,6 +307,25 @@
        root["data"] = data;
        return toJsonStr(root);
    }
    // ocr识别
    static  std::string loadOcrData(int client,cv::Mat mat,string key) {
        Json::Value data;
        Json::Value array;
        int len = mat.rows * mat.cols;
        for (int i = 0; i < len; i++) {
            Json::Value d;
            d[0] = mat.data[i];
            array[i] = d;
        }
        data["data"] = array;
        data["width"] = mat.cols;
        data["height"] = mat.rows;
        data["key"] = key;
        Json::Value root;
        root["data"] = data;
        root["type"] = 100;
        return toJsonStr(root);
    }
    static std::string toJson(ClientEnvState state) {
        Json::Value root;
app/app.aps
Binary files differ
app/app.rc
Binary files differ
app/app.vcxproj.user
@@ -4,10 +4,10 @@
    <RESOURCE_FILE>app.rc</RESOURCE_FILE>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
    <DebuggerFlavor>WindowsRemoteDebugger</DebuggerFlavor>
    <RemoteDebuggerCommand>\\192.168.3.242\FXDMounter\Debug\DataCapture.exe</RemoteDebuggerCommand>
    <RemoteDebuggerWorkingDirectory>\\192.168.3.242\FXDMounter\</RemoteDebuggerWorkingDirectory>
    <RemoteDebuggerServerName>192.168.3.242</RemoteDebuggerServerName>
    <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
    <RemoteDebuggerCommand>\\192.168.3.241\FXDMounter\Debug\DataCapture.exe</RemoteDebuggerCommand>
    <RemoteDebuggerWorkingDirectory>\\192.168.3.241\FXDMounter\</RemoteDebuggerWorkingDirectory>
    <RemoteDebuggerServerName>192.168.3.241</RemoteDebuggerServerName>
    <RemoteDebuggerConnection>RemoteWithoutAuthentication</RemoteDebuggerConnection>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
app/appDlg.cpp
@@ -294,13 +294,29 @@
                }
            }
            autoMsgStatic.SetWindowTextW(_T("等待打开副屏1..."));
            for (int i = 0; i < 5; i++) {
                HWND second = THSActionUtil::getSecondWindow();
                if (second > 0) {
                    break;
                }
            THSActionUtil::openSecondScreen();
                Sleep(1000);
            }
            autoMsgStatic.SetWindowTextW(_T("副屏1已打开..."));
            Sleep(1000);
            // 开启 涨停识别
            autoMsgStatic.SetWindowTextW(_T("启动涨停识别中..."));
            CappDlg::OnBnClickedButton12();
            autoMsgStatic.SetWindowTextW(_T("启动涨停启动成功"));
           // 开启委托识别
           // 开启交易成功识别
        }
    }
    else {
@@ -464,7 +480,7 @@
}
void  CappDlg::OnL2DataCallback(int index, string code, long captureTime, long processTime, list<TradeData> dataList, void* context) {
void  CappDlg::OnL2DataCallback(int index, string code, long captureTime, long processTime, list<TradeData*> dataList, void* context) {
    //转为json
    CappDlg* app = (CappDlg*)context;
    //cout << "回调:" << std::this_thread::get_id() << ":" << index << endl;
@@ -472,6 +488,10 @@
    bool check = btn->GetCheck();
    if (check) {
        string data = JsonUtil::loadL2Data(app->clientNum, index, code, captureTime, processTime, dataList);
        for (list<TradeData*>::iterator el = dataList.begin(); el != dataList.end();++el) {
            delete (*el);
        }
        dataList.clear();
        clock_t time_start = clock();
        try {
            app->socketManager->sendMsg(index, data.c_str());
@@ -1385,7 +1405,7 @@
    if (p.length() <= 0) {
        return;
    }
    list<TradeData> result = capture->captureLevel2TradeData(cv::imread(p), 0);
    list<TradeData*> result = capture->captureLevel2TradeData(cv::imread(p), 0);
    time = clock() - time;
    Clevel2DataDlg::level2Data = { time, result };
@@ -1414,7 +1434,7 @@
    if (p.length() <= 0) {
        return;
    }
    list<TradeData> result = capture->captureLevel2TradeData(cv::imread(p), 0);
    list<TradeData*> result = capture->captureLevel2TradeData(cv::imread(p), 0);
    time = clock() - time;
    Clevel2DataDlg::level2Data = { time, result };
@@ -1756,6 +1776,67 @@
void CappDlg::OnBnClickedButtonTradeDelegate()
{
    //打开同花顺远航版的委托界面
    HWND win = 0;
   if (win <= 0) {
       //判断是否已经打开了同花顺远航版
       for (int i = 0; i < 10; i++)
       {
           win = THSActionUtil::getTradeSimpleDelegateWindow();
           if (win <= 0)
           {
               list<HWND> wlist = Win32Util::searchWindow("同花顺远航版");
               if (wlist.size() > 0) {
                   HWND mainWin = *(wlist.begin());
                   //按F12
                   Win32Util::sendMessage(mainWin, WM_KEYDOWN, VK_F12, 0);
                   Win32Util::sendMessage(mainWin, WM_KEYUP, VK_F12, 0);
                   //等待反应
                   Sleep(500);
               }
               else {
                   //等待远航版打开
                   Sleep(1000);
               }
           }
           else {
               break;
           }
       }
   }
   //如果已经打开了远航版的交易,就需要点击当日委托
   try {
      HWND menuWin = TradeListCapture::getSimpleTradeLeftMenu(win);
      if (menuWin > 0) {
        cv::Mat img =  CaptureUtil::capture(menuWin);
        string result = JsonUtil::loadOcrData(clientNum, img, "当日委托");
        result = socketManager->sendMsg(result.c_str());
        Json::Value root = JsonUtil::parseJson(result);
        if (root["code"] == 0) {
          //图像识别成功
            Json::Value datas = root["data"]["datas"];
            Json::Value ps = datas[0]["position"];
            //position格式:[[0,13],[12,13],[12,15],[0,15]]
            //获取中心点
            int x = (ps[0][0].asInt() + ps[1][0].asInt()) / 2;
            int y= (ps[0][1].asInt() + ps[2][1].asInt()) / 2;
            RECT rect;
            Win32Util::getWindowRect(menuWin,&rect);
            x = rect.left + x;
            y = rect.top + y;
            //点击
            Win32Util::click(x,y,10);
        }
      }
   }
   catch (...) {
   }
@@ -1787,7 +1868,6 @@
            AfxMessageBox(msg);
            return;
        }
        tradeListCapture->startTradeDelegate();
        delegateBtn.SetWindowTextW(_T("暂停委托识别任务"));
    }
@@ -1799,46 +1879,26 @@
//测试按钮
void CappDlg::OnBnClickedButtonTest()
{
    int index = 0;
    std::list<TradeData> dataList;
    for (int i = 0; i < 10; i++) {
        TradeData data = TradeData();
        //7.32
        data.time = "09:30:00";
        data.price = "26.84";
        data.operateType = OPERATE_BUY;
        data.limitPrice = LIMIT_PRICE_UP;
        data.num = 5000 + i;
        dataList.push_back(data);
    cv::Mat mat = cv::imread("C:\\Users\\Administrator\\Desktop\\ocr\\trade\\Snipaste_2023-01-13_18-23-34_gray.png", cv::IMREAD_GRAYSCALE);
    Json::Value array;
    int len = mat.rows * mat.cols;
    for (int i = 0; i < len; i++) {
        array[i] = mat.data[i];
    }
    for (int i = 10; i < 11; i++) {
        TradeData data = TradeData();
        //7.32
        data.time = "09:30:00";
        data.price = "26.84";
        data.operateType = OPERATE_BUY_CANCEL;
        data.limitPrice = LIMIT_PRICE_UP;
        data.num = 5000 + i;
        dataList.push_back(data);
    }
    string data = JsonUtil::loadL2Data(clientNum, 0, "002338", 0, 0, dataList);
    clock_t time_start = clock();
    Json::Value data;
    data["data"] = array;
    data["width"] = mat.cols;
    data["height"] = mat.rows;
    data["key"] = "当日委托" ;
    Json::Value root;
    root["data"] = data;
    root["type"] = 100;
    string result = JsonUtil::jsonValue2String(root);
    try {
        socketManager->sendMsg(index, data.c_str());
        socketManager->sendMsg(result.c_str());
    }
    catch (string st) {
        //重新连接服务器
        socketManager->resetClient(index);
        socketManager->Connect(index);
    }
}
void CappDlg::OnBnClickedCheck5()
app/appDlg.h
@@ -45,8 +45,8 @@
    THSL2RepairTool *thsL2RepairTool;
    TradeQueueCaptureManager *tradeQueueCaptureManager;
    void OnDataCallback(int index, list<TradeData> dataList);
    static void  OnL2DataCallback(int index,string code, long captureTime, long processTime, list<TradeData> dataList, void* context);
    void OnDataCallback(int index, list<TradeData*> dataList);
    static void  OnL2DataCallback(int index,string code, long captureTime, long processTime, list<TradeData*> dataList, void* context);
    static void  OnTradeQueueDataCallback(int index, string code, L2TradeQueue tradeQueue, void* context);
    static void  OnLimitUpDataCallback(list<LimitUpData> dataList, void* context);
    static void  OnTradeSuccessDataCallback(list<TradeSuccessData> dataList, void* context);
app/level2DataDlg.cpp
@@ -80,7 +80,7 @@
    st.Format(_T("总共%d条数据,耗时%d毫秒"), level2Data.dataList.size(), level2Data.time);
    GetDlgItem(IDC_STATIC)->SetWindowTextW(st);
    //设置list的数据
    list<TradeData>::iterator ele;
    list<TradeData*>::iterator ele;
    m_list.InsertColumn(0, _T("序号"), LVCFMT_CENTER, 40);
    m_list.InsertColumn(1, _T("时间"), LVCFMT_LEFT, 80);
    m_list.InsertColumn(2, _T("价格"), LVCFMT_CENTER, 80);
@@ -94,11 +94,11 @@
    int index = 0;
    for (ele = level2Data.dataList.begin();ele != level2Data.dataList.end();++ele) {
        index++;
        TradeData data = *ele;
        TradeData *data = *ele;
        CString time;
        time = data.time.c_str();
        time = data->time.c_str();
        CString operate;
        switch (data.operateType)
        switch (data->operateType)
        {
        case OPERATE_BUY:
            operate = _T("买");break;
@@ -113,31 +113,31 @@
        }
        char chCode[20];
        sprintf(chCode, "%.2lf", stod(data.price));
        sprintf(chCode, "%.2lf", stod(data->price));
        std::string price(chCode);
        if (data.limitPrice == LIMIT_PRICE_NORMAL) {
        if (data->limitPrice == LIMIT_PRICE_NORMAL) {
            price.append("(正常)");
        }
        else  if (data.limitPrice == LIMIT_PRICE_UP) {
        else  if (data->limitPrice == LIMIT_PRICE_UP) {
            price.append("(涨停)");
        }
        else  if (data.limitPrice == LIMIT_PRICE_DOWN) {
        else  if (data->limitPrice == LIMIT_PRICE_DOWN) {
            price.append("(跌停)");
        }
        string t=data.time;
        if (data.cancelTime > 0)
        string t=data->time;
        if (data->cancelTime > 0)
        {
            t.append(" ").append(to_string( data.cancelTime));
            t.append(" ").append(to_string( data->cancelTime));
            string cancelTimeUnit;
            if (data.cancelTimeUnit == TIME_SECOND) {
            if (data->cancelTimeUnit == TIME_SECOND) {
                cancelTimeUnit = "s";
            }
            else  if (data.cancelTimeUnit == TIME_MINITE) {
            else  if (data->cancelTimeUnit == TIME_MINITE) {
                cancelTimeUnit = "m";
            }
            else  if (data.cancelTimeUnit == TIME_HOUR) {
            else  if (data->cancelTimeUnit == TIME_HOUR) {
                cancelTimeUnit = "h";
            }
            t.append(cancelTimeUnit);
@@ -147,7 +147,7 @@
        m_list.SetItemText(index - 1, 0, CString(to_string( index).c_str()));
        m_list.SetItemText(index - 1, 1, CString(t.c_str()));
        m_list.SetItemText(index - 1, 2, CString(price.c_str()));
        m_list.SetItemText(index - 1, 3, CString(to_string(data.num).c_str()));
        m_list.SetItemText(index - 1, 3, CString(to_string(data->num).c_str()));
        m_list.SetItemText(index - 1, 4, operate);
    }
app/level2DataDlg.h
@@ -8,7 +8,7 @@
struct Level2CaptureInfo
{
    clock_t time;
    list<TradeData> dataList;
    list<TradeData*> dataList;
};
// CappDlg 对话框