admin
2024-07-05 3ef188e6075649f4c72e3e7588d8966e1071f2ff
update .gitignore
4个文件已删除
43个文件已修改
28个文件已添加
8458 ■■■■■ 已修改文件
.gitignore 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
AndroidChannelPackage/AndroidChannelPackage.cpp 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
AndroidChannelPackage/workspace/cache/AndroidManifest-readable-out.xml 2138 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
AndroidChannelPackage/workspace/cache/AndroidManifest.xml 补丁 | 查看 | 原始文档 | blame | 历史
AndroidChannelPackage/workspace/cache/meizu/AndroidManifest-readable.xml 446 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
AndroidChannelPackage/workspace/cache/meizu/AndroidManifest.xml 补丁 | 查看 | 原始文档 | blame | 历史
AndroidChannelPackage/workspace/cache/meizu/影视大全布丸_3.10.25_release_64位_31025_jiagu.apk 补丁 | 查看 | 原始文档 | blame | 历史
CBTrade/BlinkingMessageDialog.cpp 55 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
CBTrade/BlinkingMessageDialog.h 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
CBTrade/CBTrade.vcxproj 28 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
CBTrade/CBTrade.vcxproj.filters 51 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
CBTrade/CBTrade.vcxproj.user 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
CBTrade/DataParseUtil.h 168 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
CBTrade/DataStruct.h 90 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
CBTrade/JueJInSettingFrame.cpp 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
CBTrade/JueJInSettingFrame.h 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
CBTrade/JueJinDataUtil.cpp 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
CBTrade/JueJinDataUtil.h 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
CBTrade/MainFrame.cpp 778 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
CBTrade/MainFrame.h 131 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
CBTrade/MyConfigUtil.cpp 157 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
CBTrade/MyConfigUtil.h 90 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
CBTrade/MyNetworkApi.cpp 74 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
CBTrade/MyNetworkApi.h 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
CBTrade/TickChart.cpp 909 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
CBTrade/TickChart.h 297 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
CBTrade/TickDataRequestStrategy.cpp 46 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
CBTrade/TickDataRequestStrategy.h 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
CBTrade/TickDataUtil.h 95 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
CBTrade/TickFrame.cpp 54 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
CBTrade/TickFrame.h 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
CBTrade/ViewManager.cpp 295 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
CBTrade/ViewManager.h 162 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
CBTrade/config.cfg 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
CBTrade/gmcache/cedb649398358db74e367c6655061303 补丁 | 查看 | 原始文档 | blame | 历史
CBTrade/gmcache/cedb649398358db74e367c6655061303.inf 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
CBTrade/logo.ico 补丁 | 查看 | 原始文档 | blame | 历史
CBTrade/main.cpp 34 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
DelegateQueue/DataStruct.h 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
DelegateQueue/MainFrame.cpp 260 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
DelegateQueue/MainFrame.h 9 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
DelegateQueue/MyNetworkApi.cpp 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
DelegateQueue/MyNetworkApi.h 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
DelegateQueue/TradeQueueFrame.cpp 110 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
DelegateQueue/TradeQueueFrame.h 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
DelegateQueue/TradeQueueListControl.cpp 50 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
DelegateQueue/TradeQueueListControl.h 9 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
DelegateQueue/config.cfg 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
FloatTrade/FloatTradeDlg.cpp 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
FloatTrade/config.cfg 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Monitor/Monitor.aps 补丁 | 查看 | 原始文档 | blame | 历史
Monitor/Monitor.rc 补丁 | 查看 | 原始文档 | blame | 历史
Monitor/MonitorDlg.cpp 89 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Monitor/MonitorDlg.h 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Monitor/resource.h 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
MonitorSetup/MonitorSetup.vdproj 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
SetupCBTrade/SetupCBTrade.vdproj 206 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SetupDelegateQueue/SetupDelegateQueue.vdproj 474 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
TradeDesk.sln 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
common/NetworkApi.cpp 73 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
common/NetworkApi.h 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
common/Win32Util.cpp 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
common/Win32Util.h 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
common_nopch/StringUtil.h 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
common_nopch/TimeUtil.h 22 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
common_nopch/WidgetsRenderUtil.cpp 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
common_nopch/WidgetsRenderUtil.h 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
common_nopch/Win32Util.cpp 7 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hqChart/dll/HQChart_Dll.dll 补丁 | 查看 | 原始文档 | blame | 历史
hqChart/dll/HQChart_Dll.lib 补丁 | 查看 | 原始文档 | blame | 历史
hqChart/dll/HQChart_Dll.pdb 补丁 | 查看 | 原始文档 | blame | 历史
hqChart/dll/libcrypto-1_1-x64.dll 补丁 | 查看 | 原始文档 | blame | 历史
hqChart/dll/libssl-1_1-x64.dll 补丁 | 查看 | 原始文档 | blame | 历史
hqChart/include/HQChart.Dll.h 109 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hqChart/include/HQChart.KLineData.h 549 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
.gitignore
@@ -2,3 +2,7 @@
Release/
.vs/
x64/
wxCharts/
wxWidgets-3.2.4/
gmsdk/
AndroidChannelPackage/AndroidChannelPackage.cpp
@@ -40,7 +40,7 @@
    XMLError eResult = xmlDoc.LoadFile(sourcePath.c_str());
    if (eResult != XML_SUCCESS)
    {
        cout << "打开源配置文件失败\n";
        cout << "打开源配置文件失败:" << sourcePath <<endl;
        return;
    }
    XMLElement* pRoot = xmlDoc.FirstChildElement();
@@ -173,7 +173,7 @@
    }
    else {
    //测试
        package("E:\\WXWork\\1688855861247320\\Cache\\File\\2023-11\\影视大全布丸_3.10.25_release_64位_31025_jiagu.apk", "meizu", "D:\\项目\\影音\\签名\\doudouvideo.jks", "weikou2015", "豆豆", "weikou2015");
        package("E:\\WXWork\\1688855861247320\\Cache\\File\\2024-06\\影视大全_3.10.27_release_64_32.apk", "qq,huawei", "D:\\项目\\影音\\签名\\doudouvideo.jks", "weikou2015", "豆豆", "weikou2015");
    }
}
AndroidChannelPackage/workspace/cache/AndroidManifest-readable-out.xml
File was deleted
AndroidChannelPackage/workspace/cache/AndroidManifest.xml
Binary files differ
AndroidChannelPackage/workspace/cache/meizu/AndroidManifest-readable.xml
File was deleted
AndroidChannelPackage/workspace/cache/meizu/AndroidManifest.xml
Binary files differ
AndroidChannelPackage/workspace/cache/meizu/Ó°ÊÓ´óÈ«²¼Íè_3.10.25_release_64λ_31025_jiagu.apk
Binary files differ
CBTrade/BlinkingMessageDialog.cpp
New file
@@ -0,0 +1,55 @@
#include "BlinkingMessageDialog.h"
#define MSG_WINDOW_SIZE wxSize(200,80)
BlinkingMessageDialog::BlinkingMessageDialog(wxWindow* parent, const wxString& message) : wxFrame(parent, wxID_ANY, "可转债提示", wxDefaultPosition, MSG_WINDOW_SIZE, wxDEFAULT_FRAME_STYLE & ~(wxMAXIMIZE_BOX | wxMINIMIZE_BOX))
{
    long style = GetWindowStyle();//& ~(wxCAPTION);
    style |= wxSTAY_ON_TOP;
    SetWindowStyle(style);
    SetBackgroundColour(*wxWHITE);
    m_shakeCount = 0;
    wxBoxSizer* sizer = new wxBoxSizer(wxVERTICAL);
    wxStaticText* text = new wxStaticText(this, wxID_ANY, message);
    text->SetForegroundColour(*wxRED);
    sizer->Add(text, 0, wxALL | wxALIGN_CENTER);
    SetSizer(sizer);
    // Start blinking
    m_timer = new wxTimer(this, wxID_ANY);
    Bind(wxEVT_TIMER, &BlinkingMessageDialog::OnTimer, this);
    m_timer->Start(100);
    //获取屏幕右下角
    int screenWidth = GetSystemMetrics(SM_CXSCREEN);
    int screenHeight = GetSystemMetrics(SM_CYSCREEN);
    // å³ä¸‹è§’位置
    wxPoint bottomRight(screenWidth - MSG_WINDOW_SIZE.GetWidth()-10, screenHeight - MSG_WINDOW_SIZE.GetHeight()-10);
    SetPosition(bottomRight);
}
void BlinkingMessageDialog::show()
{
    if (!IsShown()) {
        m_timer->Stop();
        m_shakeCount = 0;
        m_timer->Start(100);
        Show();
    }
}
void BlinkingMessageDialog::OnTimer(wxTimerEvent& event)
{
    if (m_shakeCount < 100) {  // Shake for 6 cycles
        int dx = (m_shakeCount % 2 == 0) ? 10 : -10;
        int dy = (m_shakeCount % 2 == 0) ? 10 : -10;
        Move(GetPosition() + wxPoint(dx, dy));
        m_shakeCount++;
    }
    else {
        m_timer->Stop();
        Close();
    }
}
CBTrade/BlinkingMessageDialog.h
New file
@@ -0,0 +1,14 @@
#pragma once
#include <wx/wx.h>
class BlinkingMessageDialog: public wxFrame
{
public:
        BlinkingMessageDialog(wxWindow* parent, const wxString& message);
        void show();
private:
    wxTimer* m_timer;
    int m_shakeCount;
    void OnTimer(wxTimerEvent& event);
};
CBTrade/CBTrade.vcxproj
@@ -24,6 +24,7 @@
    <ProjectGuid>{8bff1459-65b0-4a91-b278-d1ef8fa3e031}</ProjectGuid>
    <RootNamespace>CBTrade</RootNamespace>
    <WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
    <ProjectName>CBTrade</ProjectName>
  </PropertyGroup>
  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
@@ -139,16 +140,20 @@
      <SDLCheck>false</SDLCheck>
      <PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <ConformanceMode>true</ConformanceMode>
      <AdditionalIncludeDirectories>..\wxWidgets-3.2.4\include;..\wxWidgets-3.2.4\include\msvc;..\wxCharts\include;..\gmsdk\include;..\lib_config\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <AdditionalIncludeDirectories>..\wxWidgets-3.2.4\include;..\wxWidgets-3.2.4\include\msvc;..\wxCharts\include;..\gmsdk\include;..\lib_config\include;..\\hqChart\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
    </ClCompile>
    <Link>
      <SubSystem>Windows</SubSystem>
      <EnableCOMDATFolding>true</EnableCOMDATFolding>
      <OptimizeReferences>true</OptimizeReferences>
      <GenerateDebugInformation>true</GenerateDebugInformation>
      <AdditionalLibraryDirectories>..\wxWidgets-3.2.4\lib\vc_x64_lib;..\wxCharts\lib\vc_x64_lib;..\gmsdk\lib\win64;..\lib_config\x64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
      <AdditionalDependencies>wxcharts.lib;gmsdk.lib;libconfig++.lib;%(AdditionalDependencies)</AdditionalDependencies>
      <AdditionalLibraryDirectories>..\wxWidgets-3.2.4\lib\vc_x64_lib;..\wxCharts\lib\vc_x64_lib;..\gmsdk\lib\win64;..\lib_config\x64;..\hqChart\dll;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
      <AdditionalDependencies>wxcharts.lib;gmsdk.lib;libconfig++.lib;HQChart_Dll.lib;%(AdditionalDependencies)</AdditionalDependencies>
    </Link>
    <PostBuildEvent>
      <Command>
      </Command>
    </PostBuildEvent>
  </ItemDefinitionGroup>
  <ItemGroup>
    <ClCompile Include="..\common_nopch\ConfigUtil.cpp" />
@@ -157,9 +162,16 @@
    <ClCompile Include="..\common_nopch\SocketManager.cpp" />
    <ClCompile Include="..\common_nopch\WidgetsRenderUtil.cpp" />
    <ClCompile Include="..\common_nopch\Win32Util.cpp" />
    <ClCompile Include="BlinkingMessageDialog.cpp" />
    <ClCompile Include="JueJinDataUtil.cpp" />
    <ClCompile Include="JueJInSettingFrame.cpp" />
    <ClCompile Include="main.cpp" />
    <ClCompile Include="MainFrame.cpp" />
    <ClCompile Include="MyConfigUtil.cpp" />
    <ClCompile Include="MyNetworkApi.cpp" />
    <ClCompile Include="TickChart.cpp" />
    <ClCompile Include="TickDataRequestStrategy.cpp" />
    <ClCompile Include="TickFrame.cpp" />
    <ClCompile Include="ViewManager.cpp" />
  </ItemGroup>
  <ItemGroup>
@@ -172,8 +184,18 @@
    <ClInclude Include="..\common_nopch\TimeUtil.h" />
    <ClInclude Include="..\common_nopch\WidgetsRenderUtil.h" />
    <ClInclude Include="..\common_nopch\Win32Util.h" />
    <ClInclude Include="BlinkingMessageDialog.h" />
    <ClInclude Include="DataParseUtil.h" />
    <ClInclude Include="DataStruct.h" />
    <ClInclude Include="JueJinDataUtil.h" />
    <ClInclude Include="JueJInSettingFrame.h" />
    <ClInclude Include="MainFrame.h" />
    <ClInclude Include="MyConfigUtil.h" />
    <ClInclude Include="MyNetworkApi.h" />
    <ClInclude Include="TickChart.h" />
    <ClInclude Include="TickDataRequestStrategy.h" />
    <ClInclude Include="TickDataUtil.h" />
    <ClInclude Include="TickFrame.h" />
    <ClInclude Include="ViewManager.h" />
  </ItemGroup>
  <ItemGroup>
CBTrade/CBTrade.vcxproj.filters
@@ -51,6 +51,27 @@
    <ClCompile Include="MyNetworkApi.cpp">
      <Filter>源文件</Filter>
    </ClCompile>
    <ClCompile Include="TickChart.cpp">
      <Filter>源文件</Filter>
    </ClCompile>
    <ClCompile Include="TickDataRequestStrategy.cpp">
      <Filter>源文件</Filter>
    </ClCompile>
    <ClCompile Include="JueJinDataUtil.cpp">
      <Filter>源文件</Filter>
    </ClCompile>
    <ClCompile Include="MyConfigUtil.cpp">
      <Filter>源文件</Filter>
    </ClCompile>
    <ClCompile Include="JueJInSettingFrame.cpp">
      <Filter>源文件</Filter>
    </ClCompile>
    <ClCompile Include="TickFrame.cpp">
      <Filter>源文件</Filter>
    </ClCompile>
    <ClCompile Include="BlinkingMessageDialog.cpp">
      <Filter>源文件</Filter>
    </ClCompile>
  </ItemGroup>
  <ItemGroup>
    <ClInclude Include="MainFrame.h">
@@ -89,6 +110,36 @@
    <ClInclude Include="MyNetworkApi.h">
      <Filter>头文件</Filter>
    </ClInclude>
    <ClInclude Include="DataStruct.h">
      <Filter>头文件</Filter>
    </ClInclude>
    <ClInclude Include="DataParseUtil.h">
      <Filter>头文件</Filter>
    </ClInclude>
    <ClInclude Include="TickChart.h">
      <Filter>头文件</Filter>
    </ClInclude>
    <ClInclude Include="TickDataUtil.h">
      <Filter>头文件</Filter>
    </ClInclude>
    <ClInclude Include="JueJinDataUtil.h">
      <Filter>头文件</Filter>
    </ClInclude>
    <ClInclude Include="TickDataRequestStrategy.h">
      <Filter>头文件</Filter>
    </ClInclude>
    <ClInclude Include="MyConfigUtil.h">
      <Filter>头文件</Filter>
    </ClInclude>
    <ClInclude Include="JueJInSettingFrame.h">
      <Filter>头文件</Filter>
    </ClInclude>
    <ClInclude Include="TickFrame.h">
      <Filter>头文件</Filter>
    </ClInclude>
    <ClInclude Include="BlinkingMessageDialog.h">
      <Filter>头文件</Filter>
    </ClInclude>
  </ItemGroup>
  <ItemGroup>
    <None Include="packages.config" />
CBTrade/CBTrade.vcxproj.user
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
    <LocalDebuggerEnvironment>PATH=D:\workspace\GP\trade_desk_cplus\TradeDesk\gmsdk\lib\win64
    <LocalDebuggerEnvironment>PATH=D:\workspace\GP\trade_desk_cplus\TradeDesk\gmsdk\lib\win64;D:\workspace\GP\trade_desk_cplus\TradeDesk\lib_config\x64
$(LocalDebuggerEnvironment)</LocalDebuggerEnvironment>
    <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
  </PropertyGroup>
CBTrade/DataParseUtil.h
New file
@@ -0,0 +1,168 @@
#pragma once
#include "../common_nopch/JsonUtil.h"
#include "DataStruct.h"
#include <list>
// æ•°æ®è§£æžå¸®åŠ©ç±»
class DataParseUtil {
public:
    static std::list<PositionInfo> parsePositionList(string result) {
        std::list<PositionInfo> fresults;
        auto doc = JsonUtil::parseUTF16(result);
        if (doc.IsObject()) {
            if (doc[L"code"].GetInt() == 0) {
                auto array = doc[L"data"].GetArray();
                for (int i = 0; i < array.Size(); i++) {
                    auto item = array[i].GetObject();
                    PositionInfo position;
                    position.id = item[L"id"].GetString();
                    position.investorID = item[L"investorID"].GetString();
                    position.tradingDay = item[L"tradingDay"].GetString();
                    position.securityName = item[L"securityName"].GetString();
                    position.securityID = item[L"securityID"].GetString();
                    position.historyPos = item[L"historyPos"].GetInt();
                    position.historyPosFrozen = item[L"historyPosFrozen"].GetInt();
                    position.todayBSPos = item[L"todayBSPos"].GetInt();
                    position.todayBSPosFrozen = item[L"todayBSPosFrozen"].GetInt();
                    position.historyPosPrice = item[L"historyPosPrice"].GetString();
                    position.totalPosCost = item[L"totalPosCost"].GetString();
                    position.prePosition = item[L"prePosition"].GetInt();
                    position.availablePosition = item[L"availablePosition"].GetInt();
                    position.currentPosition = item[L"currentPosition"].GetInt();
                    position.openPosCost = item[L"openPosCost"].GetString();
                    position.todayCommission = item[L"todayCommission"].GetString();
                    position.todayTotalBuyAmount = item[L"todayTotalBuyAmount"].GetString();
                    position.todayTotalSellAmount = item[L"todayTotalSellAmount"].GetString();
                    position.updateTime = item[L"updateTime"].GetString();
                    MarketInfo market,underlyingMarket;
                    if (item.HasMember(L"marketInfo")) {
                        auto marketItem = item[L"marketInfo"].GetObject();
                        market.code = marketItem[L"code"].GetString();
                        market.name = marketItem[L"name"].GetString();
                        market.rate = marketItem[L"rate"].GetString();
                        market.price = StringUtil::to_string( marketItem[L"price"].GetDouble(),2);
                        market.lastVolume = to_string(marketItem[L"lastVolume"].GetInt());
                        market.buy1Money = marketItem[L"buy1Money"].GetString();
                        market.preClosePrice = marketItem[L"preClosePrice"].GetDouble();
                    }
                    if (item.HasMember(L"underlyingMarketInfo")) {
                        auto marketItem = item[L"underlyingMarketInfo"].GetObject();
                        underlyingMarket.code = marketItem[L"code"].GetString();
                        underlyingMarket.name = marketItem[L"name"].GetString();
                        underlyingMarket.rate = marketItem[L"rate"].GetString();
                        underlyingMarket.price = StringUtil::to_string(marketItem[L"price"].GetDouble(), 2);
                        underlyingMarket.lastVolume = to_string(marketItem[L"lastVolume"].GetInt());
                        underlyingMarket.buy1Money = marketItem[L"buy1Money"].GetString();
                        underlyingMarket.preClosePrice = marketItem[L"preClosePrice"].GetDouble();
                    }
                    if (item.HasMember(L"underlyingDetailInfo")) {
                        auto detailInfoObj = item[L"underlyingDetailInfo"].GetObject();
                        CodeDetailInfo detailInfo;
                        if (detailInfoObj.HasMember(L"limitUpReason")) {
                            detailInfo.limitUpReason = detailInfoObj[L"limitUpReason"].GetString();
                        }
                        else {
                            detailInfo.limitUpReason = "无";
                        }
                        detailInfo.bigOrderDealCount = detailInfoObj[L"bigOrderDealCount"].GetInt();
                        detailInfo.bigOrderDealMoney = detailInfoObj[L"bigOrderDealMoney"].GetString();
                        detailInfo.limit_up_time = detailInfoObj[L"limit_up_time"].GetString();
                        detailInfo.highDesc = detailInfoObj[L"highDesc"].GetString();
                        detailInfo.zyltgb = detailInfoObj[L"zyltgb"].GetString();
                        detailInfo.price = StringUtil::to_string( detailInfoObj[L"price"].GetDouble(),2);
                        if (detailInfoObj.HasMember(L"blocks")) {
                            detailInfo.blocks.clear();
                            auto array = detailInfoObj[L"blocks"].GetArray();
                            for (int i = 0; i < array.Size(); i++) {
                                detailInfo.blocks.push_back(array[i].GetString());
                            }
                        }
                        if (detailInfoObj.HasMember(L"blockInfos")) {
                            detailInfo.blockInfos.clear();
                            auto array = detailInfoObj[L"blockInfos"].GetArray();
                            for (int i = 0; i < array.Size(); i++) {
                                CodeBlockInfo blockInfo;
                                auto tempObj = array[i].GetObject();
                                blockInfo.name = tempObj[L"name"].GetString();
                                blockInfo.totalLimitUpCount = tempObj[L"totalLimitUpCount"].GetInt();
                                blockInfo.openLimitUpCount = tempObj[L"openLimitUpCount"].GetInt();
                                blockInfo.rank = tempObj[L"rank"].GetInt();
                                detailInfo.blockInfos.push_back(blockInfo);
                            }
                        }
                        position.underlyingDetailInfo = detailInfo;
                    }
                    if (item.HasMember(L"buy_list")) {
                        std::list<DealInfo> buyList;
                        auto array = item[L"buy_list"].GetArray();
                        for (int i = 0; i < array.Size(); i++) {
                            auto item = array[i].GetObject();
                            DealInfo dealInfo;
                            dealInfo.price = item[L"price"].GetString();
                            dealInfo.tradeTime = item[L"tradeTime"].GetString();
                            dealInfo.volume = item[L"volume"].GetInt();
                            buyList.push_back(dealInfo);
                        }
                        position.buyList = buyList;
                    }
                    if (item.HasMember(L"sell_list")) {
                        std::list<DealInfo> sellList;
                        auto array = item[L"sell_list"].GetArray();
                        for (int i = 0; i < array.Size(); i++) {
                            auto item = array[i].GetObject();
                            DealInfo dealInfo;
                            dealInfo.price = item[L"price"].GetString();
                            dealInfo.tradeTime = item[L"tradeTime"].GetString();
                            dealInfo.volume = item[L"volume"].GetInt();
                            sellList.push_back(dealInfo);
                        }
                        position.sellList = sellList;
                    }
                    if (item.HasMember(L"createTime")) {
                        position.createTime = item[L"createTime"].GetUint64();
                    }
                    position.marketInfo = market;
                    position.underlyingMarketInfo = underlyingMarket;
                    fresults.push_back(position);
                }
                return fresults;
            }
            else {
                wxString msg = doc[L"msg"].GetString();
                throw msg;
            }
        }
        else {
            throw wxString("网络请求错误");
        }
    }
    static float computeCostRate(PositionInfo p) {
        double totalPosCost = 0;
        int totalVolume = 0;
        for (std::list<DealInfo>::iterator e = p.buyList.begin(); e != p.buyList.end(); e++) {
            DealInfo info = *e;
            string price = info.price.ToStdString();
            totalPosCost += stod(price.c_str()) * info.volume;
            totalVolume += info.volume;
        }
        double todayCommission;
        p.todayCommission.ToDouble(&todayCommission);
        totalPosCost += todayCommission;
        double cost_price = totalPosCost / totalVolume;
        double preClosePrice= p.marketInfo.preClosePrice;
        return (cost_price - preClosePrice) * 100 / preClosePrice;
    }
};
CBTrade/DataStruct.h
New file
@@ -0,0 +1,90 @@
#pragma once
#include <wx\string.h>
#include <list>
enum MsgTypeEnum {
    MSG_TYPE_ERROR,
    MSG_TYPE_WARNING,
    MSG_TYPE_INFO
};
/// <summary>
/// æŒä»“信息
/// </summary>
struct MarketInfo {
    wxString code;
    wxString name;
    wxString rate;// æ¶¨å¹…
    wxString price;// çް价
    wxString lastVolume;// çŽ°æ‰‹/瞬时成交量
    wxString buy1Money;// ä¹°1金额
    double preClosePrice;
};
/// <summary>
/// æˆäº¤ä¿¡æ¯
/// </summary>
struct DealInfo {
    wxString tradeTime;// æˆäº¤æ—¶é—´
    wxString price;// æˆäº¤ä»·
    int volume;//成交量
};
// ä»£ç æ¿å—信息
struct CodeBlockInfo {
    wxString name;// åç§°
    int totalLimitUpCount;//总共涨停数量
    int openLimitUpCount;// ç‚¸æ¿æ•°é‡
    int rank;// æŽ’名
};
// ä»£ç è¯¦æƒ…信息
struct CodeDetailInfo {
    wxString limitUpReason; // æ¶¨åœåŽŸå› 
    std::list<wxString> blocks;//板块名称
    std::list<CodeBlockInfo> blockInfos;// æ¿å—详情
    wxString limit_up_time; //涨停时间
    wxString highDesc; //几板
    wxString zyltgb; //自由流通市值
    wxString price; //股价
    wxString bigOrderDealMoney; //大单成交金额与数量
    int bigOrderDealCount;// å¤§å•成交数量
};
struct PositionInfo
{
    wxString id;
    wxString  investorID;
    wxString tradingDay;
    wxString securityName;
    wxString securityID;
    int historyPos;
    int historyPosFrozen;
    int todayBSPos;
    int todayBSPosFrozen;
    wxString historyPosPrice;
    wxString totalPosCost;
    int prePosition;
    int availablePosition;
    int currentPosition;
    wxString openPosCost;
    wxString todayCommission;
    wxString todayTotalBuyAmount;
    wxString todayTotalSellAmount;
    wxString updateTime;
    MarketInfo marketInfo;// è¡Œæƒ…信息
    MarketInfo underlyingMarketInfo;//正股信息
    std::list<DealInfo> buyList;// ä¹°å…¥åˆ—表
    std::list<DealInfo> sellList;// å–出列表
    CodeDetailInfo underlyingDetailInfo;// æ­£è‚¡è¯¦æƒ…信息
    uint64_t createTime;
};
struct MoneyInfo
{
};
CBTrade/JueJInSettingFrame.cpp
New file
@@ -0,0 +1,39 @@
#include "JueJInSettingFrame.h"
#include "MyConfigUtil.h"
void JueJInSettingFrame::OnSureClick(wxCommandEvent& event)
{
  wxString token =    editToken->GetValue();
  wxString  strategyId = editStrategyId->GetValue();
  MyConfigUtil::setJueJinParams(JueJinParams({ token.ToStdString(), strategyId.ToStdString()}));
  // è®¾ç½®æŽ˜é‡‘的参数
  wxMessageBox("保存成功");
}
JueJInSettingFrame::JueJInSettingFrame(const wxString& title):wxDialog(NULL, wxID_ANY, title, wxDefaultPosition, wxSize(300, 160))
{
    editToken = new wxTextCtrl(this,wxID_ANY,"", wxDefaultPosition, wxSize(200,-1));
    editStrategyId = new wxTextCtrl(this, wxID_ANY,"", wxDefaultPosition, wxSize(200, -1));
    wxStaticText *label1 =new wxStaticText(this, wxID_ANY,"token");
    wxStaticText *label2 =new wxStaticText(this, wxID_ANY, "策略ID");
    wxFlexGridSizer *sizer =new wxFlexGridSizer(3,2,10,5);
    sizer->Add(label1, 0, wxALL, 5);
    sizer->Add(editToken, 0, wxEXPAND|wxLEFT, 1);
    sizer->Add(label2, 0, wxALL, 5);
    sizer->Add(editStrategyId, 1, wxEXPAND | wxLEFT, 1);
    wxBoxSizer* rootSizer = new wxBoxSizer(wxVERTICAL);
    rootSizer->Add(sizer,0,wxTOP,10);
    sureBtn = new wxButton(this, 10101, "确定");
    rootSizer->Add(sureBtn,0, wxALIGN_CENTER|wxTOP,10);
    SetSizer(rootSizer);
    sureBtn->Bind(wxEVT_BUTTON, &JueJInSettingFrame::OnSureClick, this);
    // åˆå§‹åŒ–参数
    JueJinParams params =    MyConfigUtil::getJueJinParams();
    editToken->SetValue(params.token);
    editStrategyId->SetValue(params.strategy_id);
}
CBTrade/JueJInSettingFrame.h
New file
@@ -0,0 +1,16 @@
#pragma once
#include <wx/wx.h>
class JueJInSettingFrame: public wxDialog
{
private:
    wxTextCtrl* editToken;
    wxTextCtrl* editStrategyId;
    wxButton* sureBtn;
    void OnSureClick(wxCommandEvent& event);
public:
    JueJInSettingFrame(const wxString& title);
};
CBTrade/JueJinDataUtil.cpp
New file
@@ -0,0 +1,31 @@
#include "JueJinDataUtil.h"
/// <summary>
    /// åˆå§‹åŒ–
    /// </summary>
    /// <param name="token"></param>
 void JueJinDataUtil::init(std::string token) {
    set_token(token.c_str());
}
 std::string JueJinDataUtil::getSymbol(std::string code) {
    if (code.find("11") == 0 || code.find("60") == 0 || code.find("68") == 0) {
        return std::string("SHSE.").append(code);
    }
    else if (code.find("00") == 0 || code.find("30") == 0 || code.find("12") == 0) {
        return std::string("SZSE.").append(code);
    }
}
DataArray<Tick>* JueJinDataUtil::getTickDatas(std::string symbol, std::string startTime, std::string endTime) {
    DataArray<Tick>* ticks = history_ticks(symbol.c_str(), startTime.c_str(), endTime.c_str(), 1);
    std::cout << "TICK数量:" << ticks->count() << std::endl;
    return ticks;
}
DataArray<Bar>* JueJinDataUtil::getBarDatas(std::string symbol, std::string startTime, std::string endTime, std::string frequency) {
    DataArray<Bar>* bars = history_bars(symbol.c_str(), frequency.c_str(), startTime.c_str(), endTime.c_str(), 1);
    return bars;
}
CBTrade/JueJinDataUtil.h
New file
@@ -0,0 +1,17 @@
#pragma once
#include <string>
#include <gmapi.h>
class JueJinDataUtil {
public:
    /// <summary>
    /// åˆå§‹åŒ–
    /// </summary>
    /// <param name="token"></param>
    static void init(std::string token);
    static std::string getSymbol(std::string code);
    static DataArray<Tick>* getTickDatas(std::string symbol, std::string startTime,std::string endTime);
    static DataArray<Bar>* getBarDatas(std::string symbol, std::string startTime, std::string endTime, std::string frequency="60s");
};
CBTrade/MainFrame.cpp
@@ -4,17 +4,48 @@
#include <wx/panel.h>
#include <wx/sizer.h>
#include <string.h>
#include "MyNetworkApi.h"
#include <thread>
#include "DataParseUtil.h"
#include "../common_nopch/StringUtil.h"
#include "../common_nopch/TimeUtil.h"
#include "MyConfigUtil.h"
#include "TickFrame.h"
#include <wx/app.h>
#include "../common_nopch/Win32Util.h"
#define MSG_SHOW_TIME 5 * 1000
#define COLOR_VALID wxColor(0,0,0)
#define COLOR_INVALID wxColor(164,164,164)
BEGIN_EVENT_TABLE(MainFrame, wxFrame)
EVT_MENU(wxID_ABOUT, MainFrame::OnAbout)
EVT_MENU(wxID_EXIT, MainFrame::OnQuit)
EVT_TEXT_ENTER(wxID_ANY, MainFrame::OnTextEnter)
END_EVENT_TABLE()
 MainFrame::MainFrame(const wxString& title):wxFrame(NULL, wxID_ANY, title, wxDefaultPosition, wxSize(MAIN_WINDOW_WIDTH, MAIN_WINDOW_HEIGHT)) {
MainFrame::MainFrame(const wxString& title, wxPoint position, wxSize size) :wxFrame(NULL, wxID_ANY, title, position, size) {
    wxIcon icon;
    icon.LoadFile("logo.ico", wxBITMAP_TYPE_ICO); // æ›¿æ¢ "app_icon.ico" ä¸ºä½ çš„应用程序图标文件路径
    SetIcon(icon);
    //SetTransparent(225);
    viewManager = new ViewManager();
    viewManager->initView(this);
    initData();
    bindEvent();
    initTask();
    Bind(wxEVT_SHOW, [this](wxShowEvent& event) {
        this->SetWindowStyleFlag(GetWindowStyleFlag() | wxSTAY_ON_TOP);
    });
    this->SetWindowStyleFlag(GetWindowStyleFlag() | wxSTAY_ON_TOP);
}
@@ -24,4 +55,747 @@
void MainFrame::OnAbout(wxCommandEvent& event) {
}
}
void MainFrame::OnTextEnter(wxCommandEvent& event)
{
    wxTextCtrl* textCtrl = dynamic_cast<wxTextCtrl*>(event.GetEventObject());
    string value = textCtrl->GetValue().ToStdString();
    if (textCtrl == viewManager->sellWidgets->buyMoney) {
        if (!viewManager->sellWidgets->buyLock->GetValue()) {
            return;
        }
        if (!StringUtil::isNumber(value)) {
            wxMessageBox("输入格式错误");
            return;
        }
        MyConfigUtil::setBuyMoney(stoi(value.c_str()));
        wxMessageBox("锁定买入金额成功");
    }
    else if (textCtrl == viewManager->sellWidgets->sellMoney) {
        if (!viewManager->sellWidgets->sellLock->GetValue()) {
            return;
        }
        if (!StringUtil::isNumber(value)) {
            wxMessageBox("输入格式错误");
            return;
        }
        MyConfigUtil::setSellMoney(stoi(value.c_str()));
        wxMessageBox("锁定卖出金额成功");
    }
}
void MainFrame::bindEvent()
{
    Bind(wxEVT_CLOSE_WINDOW, &MainFrame::OnClose, this);
    viewManager->topWidgets->refreshBtn->Bind(wxEVT_BUTTON, &MainFrame::OnBtnRefreshClick, this);
    viewManager->sellWidgets->buyBtn->Bind(wxEVT_BUTTON, &MainFrame::OnBtnBuyClick, this);
    viewManager->sellWidgets->sellBtn->Bind(wxEVT_BUTTON, &MainFrame::OnBtnSellClick, this);
    viewManager->positionWidgets->listCtrlReport->Bind(wxEVT_DATAVIEW_SELECTION_CHANGED, &MainFrame::OnPositionSelectionChanged, this);
    viewManager->topWidgets->btnBackTest->Bind(wxEVT_BUTTON, &MainFrame::OnBtnBackTest, this);
    for (std::list<wxButton*>::iterator e = viewManager->sellWidgets->sellNums.begin(); e != viewManager->sellWidgets->sellNums.end(); ++e) {
        wxButton* sellBtn = *e;
        //sellBtn->Bind(wxEVT_BUTTON, &MainFrame::OnBtnSellNum, this);
        sellBtn->Bind(wxEVT_BUTTON, [this](wxCommandEvent& event) {
            wxButton* btn = (wxButton*)event.GetEventObject();
            this->viewManager->sellWidgets->sellMoney->SetLabelText(btn->GetLabelText());
            });
    }
}
void MainFrame::initData()
{
    // -----------------------初始化掘金参数--------------------------
    JueJinParams jueJinParams = MyConfigUtil::getJueJinParams();
    tickDataRequestStrategy = new TickDataRequestStrategy(jueJinParams.token, jueJinParams.strategy_id, MODE_LIVE, this, &MainFrame::tickDataCallback);
    // è®¾ç½®å›žæµ‹å‚æ•°
    tickDataRequestStrategy->set_token(jueJinParams.token.c_str());
    tickDataRequestStrategy->set_strategy_id(jueJinParams.strategy_id.c_str());
    tickDataRequestStrategy->set_mode(MODE_LIVE);
    JueJinDataUtil::init(jueJinParams.token);
    MyNetworkApi::set_server_info("43.138.167.68", 13008, "43.138.167.68", 13008);
    // -----------------------初始化快捷键--------------------------
    wxAcceleratorEntry entries[2] = {
         wxAcceleratorEntry(wxACCEL_SHIFT, WXK_F10, 901),
         wxAcceleratorEntry(wxACCEL_CTRL, 'H', 902)
    };
    auto acceleratorTable = wxAcceleratorTable(2, entries);
    this->SetAcceleratorTable(acceleratorTable);
    this->Bind(wxEVT_MENU, [this](wxCommandEvent& event) {
        this->OnBtnSellClick(event);
    }, 901);
    this->Bind(wxEVT_MENU, [this](wxCommandEvent& event) {
        for (std::list<PositionInfo>::iterator e = this->positionList.begin(); e != this->positionList.end(); e++) {
        PositionInfo info = *e;
        if (this->selectPositionId == info.id) {
            try {
                Sleep(200);
                CallAfter([info]() {
                    thread t(Win32Util::addToTHS, info.underlyingMarketInfo.code.ToStdString());
                    t.detach();
                });
            }
            catch (...) {
            }
            break;
        }
    }
    }, 902);
    // -----------------------卖出参数初始化--------------------------
    int buyMoney = MyConfigUtil::getBuyMoney();
    int sellMoney = MyConfigUtil::getSellMoney();
    viewManager->sellWidgets->buyMoney->SetValue(to_string(buyMoney));
    viewManager->sellWidgets->sellMoney->SetValue(to_string(sellMoney));
    viewManager->sellWidgets->buyLock->SetValue(TRUE);
    viewManager->sellWidgets->sellLock->SetValue(TRUE);
    killed = FALSE;
    blinkingMessageDialog = nullptr;
}
void MainFrame::initTask()
{
    thread t(MainFrame::startRequestPositionsTask, this);
    t.detach();
    thread t2(MainFrame::startRequestMoneyTask, this);
    t2.detach();
    thread t1(MainFrame::runJueJinStrategy, this);
    t1.detach();
}
void MainFrame::requestPositions()
{
    cout << "###########请求持仓##########" << endl;
    string result = MyNetworkApi::get_all_positions();
    if (this == nullptr) {
        return;
    }
    requestCount += 1;
    std::list < PositionInfo> plist = DataParseUtil::parsePositionList(result);
    //根据持仓排序,
    plist.sort([](PositionInfo p1, PositionInfo p2) {
        return p1.availablePosition == p2.availablePosition? p1.createTime > p2.createTime:  p1.availablePosition > p2.availablePosition;
    });
    if (requestCount>1&&this->orginPositionList.size() != plist.size()) {
        CallAfter([this]() {
                this->blinkingMessageDialog = new BlinkingMessageDialog(this, "可转债有新下单");
                this->blinkingMessageDialog->show();
        });
    }
    this->orginPositionList = plist;
    viewManager->positionWidgets->listCtrlReport->DeleteAllItems();
    // æŒ‰æ¡ä»¶è¿‡æ»¤
    std::list < PositionInfo> temList;
    for (std::list<PositionInfo>::iterator e = plist.begin(); e != plist.end(); ++e) {
        PositionInfo p = *e;
        if (!viewManager->sellWidgets->showAllPosition->GetValue()) {
            if (p.availablePosition > 0) {
                temList.push_back(*e);
            }
        }
        else {
            temList.push_back(*e);
        }
    }
    this->positionList = temList;
    int index = 0;
    for (std::list<PositionInfo>::iterator e = positionList.begin(); e != positionList.end(); ++e) {
        PositionInfo p = *e;
        //{ "名称", "涨幅", "现价", "L1现手", "剩余持仓", "持仓金额", "盈亏", "盈亏比", "正股名称", "更多" };
        wxVector<wxVariant> data;
        bool hasPosition = p.availablePosition > 0;
        wxColor color = !hasPosition ? COLOR_INVALID: COLOR_VALID;
        data.push_back(wxVariant(MyColorText(p.securityName, color)));
        if (!hasPosition)
        {
            data.push_back(wxVariant(MyColorText(p.marketInfo.rate,color)));
        }
        else {
            wxString rateText = p.marketInfo.rate;
            rateText.Replace("%", "");
            double rate;
            rateText.ToCDouble(&rate);
            wxColor tempColor;
            if (rate > 0.0001) {
                tempColor = wxColor(255, 42, 7);
                if (rate > 8.9) {
                    tempColor = wxColor(243, 143, 250);
                }
            }
            else if (rate < 0.0001) {
                tempColor = wxColor(0, 230, 0);
            }
            else {
                tempColor = wxColor(64, 64, 64);
            }
            data.push_back(wxVariant(MyColorText(p.marketInfo.rate, tempColor)));
        }
        data.push_back(wxVariant(MyColorText(wxString(p.marketInfo.price),color)));
        data.push_back(wxVariant(MyColorText(p.marketInfo.lastVolume, color)));
        data.push_back(wxVariant(MyColorText(p.underlyingMarketInfo.rate, color)));
        if (!hasPosition)
        {
            data.push_back(wxVariant(MyColorText(p.underlyingMarketInfo.buy1Money, color)));
        }
        else {
            data.push_back(wxVariant(MyColorText(p.underlyingMarketInfo.buy1Money, wxColor(204, 78, 232))));
        }
        // è®¡ç®—持仓金额
        double positionMoney = 0.00;
        if (p.marketInfo.price.Length() > 0) {
            double price;
            p.marketInfo.price.ToCDouble(&price);
            positionMoney = price * p.currentPosition;
        }
        if (!hasPosition) {
            data.push_back(wxVariant(MyColorText(StringUtil::to_string(positionMoney, 2),color)));
        }
        else {
            data.push_back(wxVariant(MyColorText(StringUtil::to_string(positionMoney, 2), *wxRED)));
        }
        // æˆæœ¬ä»·è®¡ç®—: æ€»ä¹°å…¥é‡‘额 + æ‰‹ç»­è´¹
        double totalPosCost = 0;
        int totalVolume = 0;
        for (std::list<DealInfo>::iterator e = p.buyList.begin(); e != p.buyList.end(); e++) {
            DealInfo info = *e;
            string price = info.price.ToStdString();
            totalPosCost += stod(price.c_str()) * info.volume;
            totalVolume += info.volume;
        }
        double todayCommission;
        p.todayCommission.ToDouble(&todayCommission);
        totalPosCost += todayCommission;
        wxString cost_price = StringUtil::to_string(totalPosCost / totalVolume, 3);
        data.push_back(wxVariant(MyColorText(cost_price, color)));
        // ä»Šæ—¥ç›ˆäºè®¡ç®—: æ€»å–出金额 + æŒä»“*现价 -  ä¹°å…¥é‡‘额 - æ‰‹ç»­è´¹
        double totalSellMoney = 0;
        for (std::list<DealInfo>::iterator e = p.sellList.begin(); e != p.sellList.end(); e++) {
            double price;
            (*e).price.ToDouble(&price);
            totalSellMoney += price * (*e).volume;
        }
        double profit_money = totalSellMoney + positionMoney - totalPosCost;
        // è®¡ç®—今日盈亏比
        double profit_rate = profit_money / totalPosCost;
        wxString profit_rate_str = "";
        profit_rate_str.Append(StringUtil::to_string(profit_rate * 100)).Append("%");
        data.push_back(wxVariant(MyColorText(profit_rate_str, color)));
        // æ­£è‚¡æ•°æ®è®¾ç½®
        if (hasPosition) {
            data.push_back(wxVariant(MyButton( p.underlyingMarketInfo.code,"查看",wxColor(64,64,64), wxColor(225,225,225))));
        }
        else {
            data.push_back(wxVariant(MyButton(p.underlyingMarketInfo.code, "查看", color, wxColor(255,255,255))));
        }
        data.push_back(wxVariant(MyColorText(wxString(to_string(p.currentPosition).c_str()),color)));
        data.push_back(wxVariant(MyColorText(StringUtil::to_string(profit_money, 2), color)));
        data.push_back(wxVariant(MyColorText(p.underlyingMarketInfo.name, color)));
        viewManager->positionWidgets->listCtrlReport->AppendItem(data);
        if (selectPositionId == p.id) {
            viewManager->positionWidgets->listCtrlReport->Select(viewManager->positionWidgets->listCtrlReport->RowToItem(index));
            // è®¾ç½®tick的买点与卖点
            std::list<TickTradeData> tradePoints;
            for (std::list<DealInfo>::iterator e = p.buyList.begin(); e != p.buyList.end(); ++e) {
                DealInfo info = *e;
                double price = stod(info.price.ToStdString().c_str());
                double rate = (price - p.marketInfo.preClosePrice) * 100 / p.marketInfo.preClosePrice;
                tradePoints.push_back(TickTradeData({ info.tradeTime, (float)rate, info.price.ToStdString(), info.volume, StringUtil::to_string(info.volume * stod(info.price.ToStdString().c_str())) }));
            }
            viewManager->tickWidgets->tickChart->SetBuyPoint(tradePoints);
            tradePoints.clear();
            for (std::list<DealInfo>::iterator e = p.sellList.begin(); e != p.sellList.end(); ++e) {
                DealInfo info = *e;
                double price = stod(info.price.ToStdString().c_str());
                double rate = (price - p.marketInfo.preClosePrice) * 100 / p.marketInfo.preClosePrice;
                tradePoints.push_back(TickTradeData({ info.tradeTime,  (float)rate, info.price.ToStdString(), info.volume, StringUtil::to_string(info.volume * stod(info.price.ToStdString().c_str())) }));
            }
            viewManager->tickWidgets->tickChart->SetSellPoint(tradePoints);
        }
        index += 1;
    }
    viewManager->positionWidgets->listCtrlReport->Refresh();
}
void MainFrame::requestMoney()
{
    cout << "###########请求账户资金##########" << endl;
    string result = MyNetworkApi::get_money();
    if (this == nullptr) {
        return;
    }
    auto doc = JsonUtil::parseUTF16(result);
    try {
        if (doc.IsObject() && doc[L"code"].GetInt() == 0) {
            auto array = doc[L"data"].GetArray();
            if (array.Size() > 0)
            {
                auto data = array[0].GetObject();
                viewManager->moneyWidgets->availableLabel->SetLabelText(StringUtil::to_string(data[L"usefulMoney"].GetDouble(), 2));
                viewManager->moneyWidgets->frozenLabel->SetLabelText(StringUtil::to_string(data[L"frozenCash"].GetDouble(), 2));
            }
        }
    }
    catch (...) {
    }
}
void MainFrame::startRequestPositionsTask(MainFrame* context)
{
    while (TRUE) {
        try {
            context->requestPositions();
        }
        catch (...) {
        }
        Sleep(2000);
    }
}
void MainFrame::startRequestMoneyTask(MainFrame* context)
{
    while (TRUE) {
        try {
            context->requestMoney();
        }
        catch (...) {
        }
        Sleep(2000);
    }
}
void MainFrame::OnTickCallBack(CodeBasicInfo info, wxString xStartTime, wxString xEndTime, std::list<TickTradeData> buyPoints, std::list<TickTradeData> sellPoints, float costRate, void* context)
{
    MainFrame* mainFrame = (MainFrame*)context;
    wxSize size = mainFrame->GetSize();
    int width = size.GetWidth();
    width = width * 3 / 4;
    int height = width * 2 / 3;
    TickFrame* tickFrame = new TickFrame(mainFrame, info.codeName, info.code, info.codeName, info.preClosePrice, xStartTime, xEndTime, buyPoints, sellPoints, costRate, wxDefaultPosition, wxSize(width, height));
    tickFrame->Show();
}
LRESULT MainFrame::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam)
{
    cout <<"MSWWindowProc:"<< nMsg << endl;
    if (nMsg == WM_COPYDATA) {
        COPYDATASTRUCT* pcds = (COPYDATASTRUCT*)lParam;
        if (pcds != NULL) {
            int action_code =    pcds->dwData;
            if (action_code == 100) {
                // å–
                BYTE* pBuf = (BYTE*)(pcds->lpData);
                DWORD dwSize = (DWORD)(pcds->cbData);
                std::string str(reinterpret_cast<const char*>(pBuf), dwSize);
                // åœ¨è¿™é‡Œå¤„理接收到的字符串数据 receivedData
                cout << "内容:" << str << endl;
                wxCommandEvent event;
                this->OnBtnSellClick(event);
            }
        }
    }
    return wxFrame::MSWWindowProc(nMsg, wParam, lParam);
}
void MainFrame::OnClose(wxCloseEvent& event) {
    killed = true;
    MyConfigUtil::setMainWindowPos(GetPosition(), GetSize());
    // ä¿å­˜æŒä»“股列宽
    int columnCount = viewManager->positionWidgets->listCtrlReport->GetColumnCount();
    std::list<int> positionWidthList;
    for (int i = 0; i < columnCount; i++) {
        wxDataViewColumn* column = viewManager->positionWidgets->listCtrlReport->GetColumn(i);
        int columnWidth = column->GetWidth();
        positionWidthList.push_back(columnWidth);
    }
    MyConfigUtil::setPositionColumnWidth(positionWidthList);
    event.Skip();
    exit(0);
}
void MainFrame::OnBtnRefreshClick(wxCommandEvent& event)
{
    string result = MyNetworkApi::refresh_position();
    cout << "刷新持仓结果:" << result.c_str() << endl;
    result = MyNetworkApi::refresh_deal();
    cout << "刷新成交结果:" << result.c_str() << endl;
}
void MainFrame::OnBtnBuyClick(wxCommandEvent& event)
{
    if (!selectPositionId || selectPositionId.length() == 0) {
        showMsg("尚未选中持仓", MSG_TYPE_WARNING);
        return;
    }
    PositionInfo pos = getSeclectedPosition();
    wxString code = viewManager->topWidgets->codeEdit->GetValue();
    wxString buyMoney = viewManager->sellWidgets->buyMoney->GetValue();
    if (buyMoney.length() <= 0) {
        showMsg("请输入买入金额", MSG_TYPE_WARNING);
        return;
    }
    int priceType = viewManager->sellWidgets->buyPrice->GetSelection();
    // é€šè¿‡é‡‘额计算卖的量
    double volume = stoi(buyMoney.ToStdString().c_str()) / stod(pos.marketInfo.price.ToStdString().c_str());
    int volume_int = (int)volume;
    volume_int = volume_int / 10 * 10;
    if (volume_int <= 0) {
        showMsg("买入小于10股", MSG_TYPE_WARNING);
        return;
    }
    string result = MyNetworkApi::buy(code.ToStdString(), priceType, volume_int);
    auto doc = JsonUtil::parseUTF16(result);
    if (doc.IsObject()) {
        if (doc[L"code"].GetInt() == 0) {
            auto data = doc[L"data"].GetObject();
            if (data.HasMember(L"orderStatus") && data[L"orderStatus"].GetInt() == -1) {
                showMsg(data[L"orderStatusMsg"].GetString(), MSG_TYPE_ERROR);
            }
            else {
                showMsg("买入成功", MSG_TYPE_INFO);
                requestPositions();
            }
        }
        else {
            showMsg(doc[L"msg"].GetString(), MSG_TYPE_ERROR);
        }
    }
    else {
        showMsg("网络请求出错", MSG_TYPE_ERROR);
    }
}
void MainFrame::showMsg(wxString msg, MsgTypeEnum type)
{
    // æ˜¾ç¤º15s
    msgExpireTime = TimeUtil::getNowTimeStamp() + MSG_SHOW_TIME;
    switch (type)
    {
    case MSG_TYPE_ERROR:
        viewManager->topWidgets->msgLabel->SetForegroundColour(*wxGREEN);
        break;
    case MSG_TYPE_WARNING:
        viewManager->topWidgets->msgLabel->SetForegroundColour(*wxGREEN);
        break;
    case MSG_TYPE_INFO:
        viewManager->topWidgets->msgLabel->SetForegroundColour(*wxBLACK);
        break;
    default:
        break;
    }
    viewManager->topWidgets->msgLabel->SetLabelText(msg);
    // å¯åŠ¨çº¿ç¨‹ç»“æŸæ˜¾ç¤º
    thread t(clearMsg, this);
    t.detach();
}
void MainFrame::clearMsg(MainFrame* context)
{
    Sleep(MSG_SHOW_TIME);
    if (TimeUtil::getNowTimeStamp() > context->msgExpireTime) {
        context->viewManager->topWidgets->msgLabel->SetLabelText("");
    }
}
void MainFrame::runJueJinStrategy(MainFrame* context)
{
    context->tickDataRequestStrategy->run();
    while (TRUE) {
        Sleep(3000);
    }
}
void MainFrame::tickDataCallback(Tick* tick, void* context)
{
    string symbol = tick->symbol;
    symbol = symbol.substr(symbol.find(".") + 1, 6);
    cout << "回调:" << symbol << endl;
    MainFrame* that = (MainFrame*)context;
    for (std::list<PositionInfo>::iterator e = that->positionList.begin(); e != that->positionList.end(); e++) {
        PositionInfo info = *e;
        if (that->selectPositionId == info.id) {
            if (info.securityID == symbol)
            {
                that->viewManager->tickWidgets->tickChart->AddTickData(TimeUtil::format((long)tick->created_at, "%H:%M:%S"), 100 * (tick->price - info.marketInfo.preClosePrice) / info.marketInfo.preClosePrice, to_string(tick->price));
            }
            else if (info.underlyingMarketInfo.code == symbol) {
                that->viewManager->tickWidgets->tickChart->AddUnderlyingTickData(TimeUtil::format((long)tick->created_at, "%H:%M:%S"), 100 * (tick->price - info.underlyingMarketInfo.preClosePrice) / info.underlyingMarketInfo.preClosePrice);
            }
            break;
        }
    }
}
PositionInfo MainFrame::getSeclectedPosition()
{
    for (list<PositionInfo>::iterator e = positionList.begin(); e != positionList.end(); ++e) {
        PositionInfo info = *e;
        if (info.id == selectPositionId) {
            return info;
        }
    }
}
void MainFrame::OnBtnSellClick(wxCommandEvent& event)
{
    if (!selectPositionId || selectPositionId.length() == 0) {
        showMsg("尚未选中持仓", MSG_TYPE_WARNING);
        return;
    }
    PositionInfo pos = getSeclectedPosition();
    wxString code = viewManager->topWidgets->codeEdit->GetValue();
    wxString sellMoney = viewManager->sellWidgets->sellMoney->GetValue();
    if (sellMoney.length() <= 0) {
        showMsg("请输入卖金额", MSG_TYPE_WARNING);
        return;
    }
    int priceType = viewManager->sellWidgets->sellPrice->GetSelection();
    // é€šè¿‡é‡‘额计算卖的量
    double volume = stoi(sellMoney.ToStdString().c_str()) / stod(pos.marketInfo.price.ToStdString().c_str());
    int volume_int = (int)volume;
    volume_int = volume_int / 10 * 10;
    cout << "卖出的量:" << volume_int << endl;
    if (volume_int > pos.availablePosition) {
        volume_int = pos.availablePosition;
    }
    string result = MyNetworkApi::sell(code.ToStdString(), priceType, volume_int);
    auto doc = JsonUtil::parseUTF16(result);
    if (doc.IsObject()) {
        if (doc[L"code"].GetInt() == 0) {
            auto data = doc[L"data"].GetObject();
            if (data.HasMember(L"orderStatus") && data[L"orderStatus"].GetInt() == -1) {
                showMsg(data[L"orderStatusMsg"].GetString(), MSG_TYPE_ERROR);
            }
            else {
                showMsg("卖出成功", MSG_TYPE_INFO);
                requestPositions();
            }
        }
        else {
            showMsg(doc[L"msg"].GetString(), MSG_TYPE_ERROR);
        }
    }
    else {
        showMsg("网络请求出错", MSG_TYPE_ERROR);
    }
}
void MainFrame::OnPositionSelectionChanged(wxDataViewEvent& event)
{
    auto item = viewManager->positionWidgets->listCtrlReport->GetSelection();
    int rowIndex = viewManager->positionWidgets->listCtrlReport->ItemToRow(item);
    std::list<PositionInfo>::iterator e = positionList.begin();
    if (rowIndex > 0) {
        std::advance(e, rowIndex);
    }
    if (rowIndex >= 0)
    {
        PositionInfo p = *e;
        selectPositionId = p.id;
        // è®¾ç½®å†…容
        this->viewManager->topWidgets->codeEdit->SetValue(p.securityID);
        this->viewManager->tickWidgets->tickChart->Init(CodeBasicInfo({ p.securityID ,p.marketInfo.name,p.marketInfo.preClosePrice }), CodeBasicInfo({ p.underlyingMarketInfo.code ,p.underlyingMarketInfo.name,p.underlyingMarketInfo.preClosePrice }), this, MainFrame::OnTickCallBack);
        float costRate = DataParseUtil::computeCostRate(p);
        this->viewManager->tickWidgets->tickChart->SetCostRate(p.securityID, costRate, "");
        for (std::list<DealInfo>::iterator e = p.buyList.begin(); e != p.buyList.end(); ++e) {
            DealInfo info = *e;
            double price = stod(info.price.ToStdString().c_str());
            double rate = (price - p.marketInfo.preClosePrice) * 100 / p.marketInfo.preClosePrice;
            this->viewManager->tickWidgets->tickChart->AddBuyPoint(info.tradeTime, rate, info.price.ToStdString(), info.volume, StringUtil::to_string(info.volume * stod(info.price.ToStdString().c_str())));
        }
        for (std::list<DealInfo>::iterator e = p.sellList.begin(); e != p.sellList.end(); ++e) {
            DealInfo info = *e;
            double price = stod(info.price.ToStdString().c_str());
            double rate = (price - p.marketInfo.preClosePrice) * 100 / p.marketInfo.preClosePrice;
            this->viewManager->tickWidgets->tickChart->AddSellPoint(info.tradeTime, rate, info.price.ToStdString(), info.volume, StringUtil::to_string(info.volume * stod(info.price.ToStdString().c_str())));
        }
        wxRichTextAttr style;
        wxRichTextCtrl *richText =    this->viewManager->tickWidgets->codeInfoLabel;
        richText->GetBuffer().Clear();
        richText->Clear();
        //设置值
        wxString codeInfoStr = "";
        codeInfoStr.Append(p.underlyingMarketInfo.code).Append("(").Append(p.underlyingMarketInfo.name).Append("),");
        richText->WriteText(codeInfoStr);
        codeInfoStr = "";
        style.SetTextColour(*wxRED);
        richText->BeginStyle(style);
        richText->WriteText("【涨停原因:");
        richText->WriteText(p.underlyingDetailInfo.limitUpReason);
        codeInfoStr.Append("&板块身位:");
        int i = 0;
        for (std::list<CodeBlockInfo>::iterator e = p.underlyingDetailInfo.blockInfos.begin(); e != p.underlyingDetailInfo.blockInfos.end(); ++e) {
            CodeBlockInfo info = *e;
            codeInfoStr.Append(info.name).Append("-").Append(to_string(info.rank));
            i++;
            if (i != p.underlyingDetailInfo.blockInfos.size()) {
                codeInfoStr.Append("、");
            }
        }
        codeInfoStr.Append("】");
        richText->WriteText(codeInfoStr);
        richText->EndStyle();
        style.SetTextColour(*wxBLACK);
        codeInfoStr = "";
        codeInfoStr.Append(",板块:");
        auto blocks = p.underlyingDetailInfo.blocks;
        i = 0;
        for (std::list<wxString>::iterator e = blocks.begin(); e != blocks.end(); ++e) {
            codeInfoStr.Append(*e);
            i++;
            if (i != blocks.size()) {
                codeInfoStr.Append("/");
            }
        }
        codeInfoStr.Append(",");
        codeInfoStr.Append("时间:").Append(p.underlyingDetailInfo.limit_up_time).Append(",");
        codeInfoStr.Append("市场身位:").Append(p.underlyingDetailInfo.highDesc).Append(",");
        codeInfoStr.Append("板块数量:");
        i = 0;
        for (std::list<CodeBlockInfo>::iterator e = p.underlyingDetailInfo.blockInfos.begin(); e != p.underlyingDetailInfo.blockInfos.end(); ++e) {
            CodeBlockInfo info = *e;
            wxString s = "&";
            codeInfoStr.Append(info.name).Append(s).Append(to_string(info.totalLimitUpCount)).Append(s).Append(to_string(info.openLimitUpCount));
            i++;
            if (i != p.underlyingDetailInfo.blockInfos.size()) {
                codeInfoStr.Append("、");
            }
        }
        codeInfoStr.Append(",");
        codeInfoStr.Append("市值:").Append(p.underlyingDetailInfo.zyltgb).Append(",");
        codeInfoStr.Append("股价:").Append(p.underlyingDetailInfo.price).Append(",");
        codeInfoStr.Append("大单成交:").Append(p.underlyingDetailInfo.bigOrderDealMoney).Append("-").Append(to_string(p.underlyingDetailInfo.bigOrderDealCount)).Append("笔");
        richText->WriteText(codeInfoStr);
        tickDataRequestStrategy->subscribeSymbol(JueJinDataUtil::getSymbol(p.securityID.ToStdString()), JueJinDataUtil::getSymbol(p.underlyingMarketInfo.code.ToStdString()));
    }
    else {
        selectPositionId = "";
    }
    cout << "选中的行:" << rowIndex << endl;
    event.Skip();
    //event.Veto();
}
void MainFrame::OnBtnBackTest(wxCommandEvent& event)
{
    wxString date = viewManager->topWidgets->backTestDate->GetValue();
    wxString btnValue = viewManager->topWidgets->btnBackTest->GetLabelText();
    try {
        if (btnValue.StartsWith("开始")) {
            string result = MyNetworkApi::set_backtest_mode(date.ToStdString(), true);
            auto doc = JsonUtil::parseUTF16(result);
            if (!doc.IsObject()) {
                throw wxString("网络请求出错");
            }
            if (doc[L"code"].GetInt() != 0) {
                throw wxString(doc[L"msg"].GetString());
            }
            viewManager->topWidgets->btnBackTest->SetLabelText("结束回测");
        }
        else {
            string result = MyNetworkApi::set_backtest_mode(date.ToStdString(), false);
            auto doc = JsonUtil::parseUTF16(result);
            if (!doc.IsObject()) {
                throw wxString("网络请求出错");
            }
            if (doc[L"code"].GetInt() != 0) {
                throw wxString(doc[L"msg"].GetString());
            }
            viewManager->topWidgets->btnBackTest->SetLabelText("开始回测");
        }
    }
    catch (wxString st) {
        wxMessageBox(st);
    }
    catch (...) {
        wxMessageBox(L"网络请求出错");
    }
}
CBTrade/MainFrame.h
@@ -4,6 +4,10 @@
#include <wx/dataview.h>
#include <list>
#include "ViewManager.h"
#include "DataStruct.h"
#include "TickDataRequestStrategy.h"
#include "JueJinDataUtil.h"
#include "BlinkingMessageDialog.h"
@@ -11,17 +15,142 @@
{
private:
    ViewManager* viewManager;
    std::list<PositionInfo> orginPositionList;
    std::list<PositionInfo> positionList;
    wxString selectPositionId;// é€‰ä¸­çš„æŒä»“ID
    long msgExpireTime;
    TickDataRequestStrategy* tickDataRequestStrategy;
    bool killed;
    BlinkingMessageDialog* blinkingMessageDialog;
    int requestCount;
public:
    // Constructor
    MainFrame(const wxString& title);
    MainFrame(const wxString& title, wxPoint position=wxDefaultPosition, wxSize size= wxDefaultSize);
    // Event handlers
    void OnQuit(wxCommandEvent& event);
    void OnAbout(wxCommandEvent& event);
    void OnTextEnter(wxCommandEvent& event);
private:
    // This class handles events
    DECLARE_EVENT_TABLE()
    /// <summary>
    /// ç»‘定事件
    /// </summary>
    void bindEvent();
    /// <summary>
    /// åˆå§‹åŒ–数据
    /// </summary>
    void initData();
    /// <summary>
    /// åˆå§‹åŒ–任务
    /// </summary>
    void initTask();
    /// <summary>
    /// èŽ·å–æŒä»“
    /// </summary>
    void requestPositions();
    /// <summary>
    /// èŽ·å–èµ„é‡‘
    /// </summary>
    void requestMoney();
    /// <summary>
    /// å¼€å§‹æŒä»“任务
    /// </summary>
    /// <param name="context"></param>
    static void startRequestPositionsTask(MainFrame *context);
    /// <summary>
    /// èŽ·å–æŒä»“ä»»åŠ¡
    /// </summary>
    /// <param name="context"></param>
    static void startRequestMoneyTask(MainFrame* context);
    /// <summary>
    /// æ˜¾ç¤ºä¿¡æ¯
    /// </summary>
    /// <param name="msg"></param>
    /// <param name="type"></param>
    void showMsg(wxString msg, MsgTypeEnum type);
    /// <summary>
    /// æ¸…除信息
    /// </summary>
    /// <param name="context"></param>
    static void clearMsg(MainFrame* context);
    /// <summary>
    /// è¿è¡ŒæŽ˜é‡‘ç­–ç•¥
    /// </summary>
    /// <param name="context"></param>
    static void runJueJinStrategy(MainFrame* context);
    /// <summary>
    /// æŽ˜é‡‘行情数据回调
    /// </summary>
    /// <param name="tick"></param>
    /// <param name="context"></param>
    static void tickDataCallback(Tick *tick, void* context);
    /// <summary>
    /// èŽ·å–é€‰ä¸­çš„æŒä»“
    /// </summary>
    /// <returns></returns>
    PositionInfo getSeclectedPosition();
    /// <summary>
    /// Tick å›žè°ƒ
    /// </summary>
    /// <param name="info"></param>
    /// <param name="xStartTime"></param>
    /// <param name="xEndTime"></param>
    static void OnTickCallBack(CodeBasicInfo info, wxString xStartTime, wxString xEndTime, std::list<TickTradeData> buyPoints, std::list<TickTradeData> sellPoints, float costRate, void* context);
protected:
    LRESULT MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam);
private:
    /// <summary>
    /// åˆ·æ–°äº‹ä»¶
    /// </summary>
    /// <param name="event"></param>
    void OnBtnRefreshClick(wxCommandEvent& event);
    /// <summary>
    /// ä¹°å…¥ç‚¹å‡»äº‹ä»¶
    /// </summary>
    /// <param name="event"></param>
    void OnBtnBuyClick(wxCommandEvent& event);
    /// <summary>
    /// å–出
    /// </summary>
    /// <param name="event"></param>
    void OnBtnSellClick(wxCommandEvent& event);
    void OnPositionSelectionChanged(wxDataViewEvent& event);
    /// <summary>
    /// å›žæµ‹
    /// </summary>
    /// <param name="event"></param>
    void OnBtnBackTest(wxCommandEvent& event);
    /// <summary>
    /// çª—口关闭
    /// </summary>
    /// <param name="event"></param>
    void OnClose(wxCloseEvent& event);
};
CBTrade/MyConfigUtil.cpp
New file
@@ -0,0 +1,157 @@
#include "MyConfigUtil.h"
#include "../common_nopch/JsonUtil.h"
#include <wx/wx.h>
JueJinParams MyConfigUtil::getJueJinParams()
{
    try {
        string params = readStringConfig("juejin_params");
        auto doc = JsonUtil::parseUTF8(params);
        string token = doc[0].GetString();
        string strategyId = doc[1].GetString();
        JueJinParams param;
        param.token = token;
        param.strategy_id = strategyId;
        return param;
    }
    catch (...) {
        return JueJinParams({"",""});
    }
}
void MyConfigUtil::setJueJinParams(JueJinParams params)
{
    rapidjson::StringBuffer buf;
    rapidjson::PrettyWriter<rapidjson::StringBuffer> writer(buf);
    writer.StartArray();
    writer.String(params.token.c_str());
    writer.String(params.strategy_id.c_str());
    writer.EndArray();
    const char* json_content = buf.GetString();
    setStringConfig("juejin_params", json_content);
}
int MyConfigUtil::getBuyMoney()
{
    try {
        int params = readIntConfig("buy_money");
        return params;
    }
    catch (...) {
        // é»˜è®¤
        return 2000;
    }
}
void MyConfigUtil::setBuyMoney(int money)
{
    setIntConfig("buy_money", money);
}
int MyConfigUtil::getSellMoney()
{
    try {
        int params = readIntConfig("sell_money");
        return params;
    }
    catch (...) {
        // é»˜è®¤
        return 2000;
    }
}
void MyConfigUtil::setSellMoney(int money)
{
    setIntConfig("sell_money", money);
}
void MyConfigUtil::setMainWindowPos(wxPoint point, wxSize size)
{
    rapidjson::StringBuffer buf;
    rapidjson::PrettyWriter<rapidjson::StringBuffer> writer(buf);
    writer.StartArray();
    writer.Int(point.x);
    writer.Int(point.y);
    writer.Int(size.GetWidth());
    writer.Int(size.GetHeight());
    writer.EndArray();
    const char* json_content = buf.GetString();
    setStringConfig("main_window_info", json_content);
}
WindowPosSize MyConfigUtil::getMainWindowPos()
{
    try {
        string result = readStringConfig("main_window_info");
        auto doc = JsonUtil::parseUTF8(result);
        return  WindowPosSize({ doc[0].GetInt(), doc[1].GetInt(),doc[2].GetInt(), doc[3].GetInt() });
    }
    catch (...) {
    }
    return DEFAULT_WINOW_POS_AND_SIZE;
}
void MyConfigUtil::setTickWindowPos(wxPoint point, wxSize size)
{
    rapidjson::StringBuffer buf;
    rapidjson::PrettyWriter<rapidjson::StringBuffer> writer(buf);
    writer.StartArray();
    writer.Int(point.x);
    writer.Int(point.y);
    writer.Int(size.GetWidth());
    writer.Int(size.GetHeight());
    writer.EndArray();
    const char* json_content = buf.GetString();
    setStringConfig("tick_window_info", json_content);
}
WindowPosSize MyConfigUtil::getTickWindowPos()
{
    try {
        string result = readStringConfig("tick_window_info");
        auto doc = JsonUtil::parseUTF8(result);
        WindowPosSize info = { doc[0].GetInt(), doc[1].GetInt(),doc[2].GetInt(), doc[3].GetInt() };
        return info;
    }
    catch (...) {
    }
    return DEFAULT_WINOW_POS_AND_SIZE;
}
void MyConfigUtil::setPositionColumnWidth(std::list<int> widthList)
{
    string st;
    for (std::list<int>::iterator e = widthList.begin(); e != widthList.end(); ++e) {
        st.append(to_string(*e)).append(",");
    }
    st = st.substr(0, st.size() - 1);
    setStringConfig("position_view_column_width", st);
}
list<int> MyConfigUtil::getPositionColumnWidth()
{
    list<int> fwidths;
    try {
        string st = readStringConfig("position_view_column_width");
        if (st.size() > 0) {
            std::vector<std::string> widths = StringUtil::split(st, ",");
            for (std::vector<std::string>::iterator e = widths.begin(); e != widths.end(); ++e) {
                int width = stoi((*e).c_str());
                fwidths.push_back(width);
            }
        }
    }
    catch (...) {
    }
    return fwidths;
}
CBTrade/MyConfigUtil.h
New file
@@ -0,0 +1,90 @@
#pragma once
#include "../common_nopch/ConfigUtil.h"
#include <wx/wx.h>
#define DEFAULT_WINOW_POS_AND_SIZE WindowPosSize({-1, -1, -1, -1})
struct WindowPosSize {
    int x;
    int y;
    int width;
    int height;
};
struct JueJinParams
{
    string token;
    string strategy_id;
};
class MyConfigUtil:public ConfigUtil
{
public:
    /// <summary>
    /// èŽ·å–æŽ˜é‡‘å‚æ•°
    /// </summary>
    /// <returns></returns>
    static JueJinParams getJueJinParams();
    /// <summary>
    /// è®¾ç½®æŽ˜é‡‘参数
    /// </summary>
    /// <param name="params"></param>
    static void setJueJinParams(JueJinParams params);
    /// <summary>
    /// èŽ·å–ä¹°å…¥èµ„é‡‘
    /// </summary>
    /// <returns></returns>
    static int getBuyMoney();
    /// <summary>
    /// è®¾ç½®ä¹°å…¥èµ„金
    /// </summary>
    /// <param name="money"></param>
    static void setBuyMoney(int money);
    /// <summary>
    /// èŽ·å–å–å‡ºé‡‘é¢
    /// </summary>
    /// <returns></returns>
    static int getSellMoney();
    /// <summary>
    /// è®¾ç½®å–出金额
    /// </summary>
    static void setSellMoney(int money);
    // è®¾ç½®ä¸»çª—口的位置与大小
    static void setMainWindowPos(wxPoint point, wxSize size);
    // èŽ·å–ä¸»çª—å£ä½ç½®ä¸Žå¤§å°
    static WindowPosSize getMainWindowPos();
    /// <summary>
    /// è®¾ç½®Tick窗口位置
    /// </summary>
    /// <param name="point"></param>
    /// <param name="size"></param>
    static void setTickWindowPos(wxPoint point, wxSize size);
    /// <summary>
    /// èŽ·å–tick窗口位置
    /// </summary>
    /// <returns></returns>
    static WindowPosSize getTickWindowPos();
    /// <summary>
    /// è®¾ç½®æŒä»“的宽度
    /// </summary>
    /// <param name="widthList"></param>
    static void setPositionColumnWidth(std::list<int> widthList);
    /// <summary>
    /// èŽ·å–æŒä»“è§†å›¾åˆ—å®½
    /// </summary>
    /// <returns></returns>
    static list<int> getPositionColumnWidth();
};
CBTrade/MyNetworkApi.cpp
@@ -81,3 +81,77 @@
    string result = base_trade_request(std::string(json_content));
    return result;
}
string MyNetworkApi::refresh_trade_data(string type)
{
    rapidjson::StringBuffer buf;
    rapidjson::PrettyWriter<rapidjson::StringBuffer> writer(buf);
    writer.StartObject();
    writer.Key("type");
    writer.String("refresh_trade_data");
    writer.Key("data");
    writer.StartObject();
    writer.Key("ctype");
    writer.String(type.c_str());
    writer.EndObject();
    writer.EndObject();
    const char* json_content = buf.GetString();
    string result = base_trade_request(std::string(json_content));
    return result;
}
string MyNetworkApi::refresh_position()
{
    return refresh_trade_data("position_list");
}
string MyNetworkApi::refresh_money()
{
    return refresh_trade_data("money");
}
string MyNetworkApi::refresh_deal()
{
    return refresh_trade_data("deal_list");
}
string MyNetworkApi::set_backtest_mode(string date, bool is_back_test)
{
    rapidjson::StringBuffer buf;
    rapidjson::PrettyWriter<rapidjson::StringBuffer> writer(buf);
    writer.StartObject();
    writer.Key("type");
    writer.String("common");
    writer.Key("data");
    writer.StartObject();
    writer.Key("ctype");
    writer.String("set_backtest_mode");
    writer.Key("date");
    writer.String(date.c_str());
    writer.Key("mode");
    writer.Bool(is_back_test);
    writer.EndObject();
    writer.EndObject();
    const char* json_content = buf.GetString();
    string result = base_trade_request(std::string(json_content));
    return result; return string();
}
string MyNetworkApi::get_backtest_mode()
{
    rapidjson::StringBuffer buf;
    rapidjson::PrettyWriter<rapidjson::StringBuffer> writer(buf);
    writer.StartObject();
    writer.Key("type");
    writer.String("common");
    writer.Key("data");
    writer.StartObject();
    writer.Key("ctype");
    writer.String("get_backtest_mode");
    writer.EndObject();
    writer.EndObject();
    const char* json_content = buf.GetString();
    string result = base_trade_request(std::string(json_content));
    return result; return string();
}
CBTrade/MyNetworkApi.h
@@ -36,5 +36,46 @@
    /// <returns></returns>
    static string sell(string code, int price_type, int volume, string price="");
    /// <summary>
    /// åˆ·æ–°äº¤æ˜“数据
    /// </summary>
    /// <param name="type">money/position_list/deal_list/delegate_list</param>
    /// <returns></returns>
    static string refresh_trade_data(string type);
    /// <summary>
    /// åˆ·æ–°æŒä»“
    /// </summary>
    /// <returns></returns>
    static string refresh_position();
    /// <summary>
    /// åˆ·æ–°èµ„金
    /// </summary>
    /// <returns></returns>
    static string refresh_money();
    /// <summary>
    /// åˆ·æ–°æˆäº¤
    /// </summary>
    /// <returns></returns>
    static string refresh_deal();
    /// <summary>
    /// è®¾ç½®å›žæµ‹æ¨¡å¼
    /// </summary>
    /// <param name="date">日期</param>
    /// <param name="is_back_test">是否回车</param>
    /// <returns></returns>
    static string set_backtest_mode(string date,bool is_back_test);
    /// <summary>
    /// èŽ·å–å›žæµ‹æ¨¡å¼
    /// </summary>
    /// <returns></returns>
    static string get_backtest_mode();
};
CBTrade/TickChart.cpp
New file
@@ -0,0 +1,909 @@
#include "TickChart.h"
#include "../common_nopch/StringUtil.h"
#include "../common_nopch/TimeUtil.h"
#include "TickDataUtil.h"
#include "JueJinDataUtil.h"
#include <wx/dcbuffer.h>
using namespace std;
#define COLOR_RED wxColor(128,0,0)
#define COLOR_RED_TEXT wxColor(225,0,0)
#define COLOR_GREEN_TEXT wxColor(0,225,0)
#define COLOR_WHITE_TEXT wxColor(255,255,255)
#define COLOR_YELLOW wxColor(255,128,32)
#define COLOR_UNDERLYING_LINE wxColor(133,202,255)
// æ …格线数量
#define GRID_LINE_ROW_COUNT 15
#define GRID_LINE_COL_COUNT 9
#define GRID_MARGIN Padding({ 60,20,50,25})
#define MAX_RATE_FLOAT 0.7
#define POINT_REDIUS 2
wxPoint TickChart::convertTickDataToPoint(TickData tickData, wxRect area, float scale)
{
    int X_COUNT = this->xScopeSeconds / this->timeSpace;// 4小时5分钟囊括的所有点
    int width = (tickData.time / this->timeSpace) * (area.width - GRID_MARGIN.left - GRID_MARGIN.right) / X_COUNT;
    int x = area.x + GRID_MARGIN.left + width;
    int y = area.y + GRID_MARGIN.top + (area.height - GRID_MARGIN.top - GRID_MARGIN.bottom) * (maxYRate - tickData.rate * scale) / (maxYRate * 2);
    return wxPoint(x, y);
}
wxPoint TickChart::convertTickDataToPoint(TickTradeData tickData, wxRect area)
{
    int X_COUNT = this->xScopeSeconds / this->timeSpace;// æ•´ä¸ªX轴的所有点
    int width = (TickDataUtil::timeStrToSecondsAsAxisX(tickData.time, xStartTimeSeconds) / this->timeSpace) * (area.width - GRID_MARGIN.left - GRID_MARGIN.right) / X_COUNT;
    int x = area.x + GRID_MARGIN.left + width;
    int y = area.y + GRID_MARGIN.top + (area.height - GRID_MARGIN.top - GRID_MARGIN.bottom) * (maxYRate - tickData.rate) / (maxYRate * 2);
    return wxPoint(x, y);
}
TickData TickChart::pointToTick(wxPoint point, wxRect area)
{
    // è·ç¦»å·¦è¾¹ç¼˜è¾¹çš„距离
    int x = point.x - area.x - GRID_MARGIN.left;
    int y = point.y - area.y - GRID_MARGIN.top;
    int width = area.GetWidth() - GRID_MARGIN.left - GRID_MARGIN.right;
    int height = area.GetHeight() - GRID_MARGIN.top - GRID_MARGIN.bottom;
    int seconds = x * this->xScopeSeconds / width;
    seconds = seconds / this->timeSpace * this->timeSpace;
    // å°†æ—¶é—´s转为字符串
    float rate = maxYRate - y * maxYRate * 2 / height;
    TickData tickData;
    tickData.rate = rate;
    tickData.time = seconds;
    tickData.price = "";
    return tickData;
}
void TickChart::drawAxis(wxDC& dc, wxRect area)
{
    //WidgetsRenderUtil::drawText(dc, "测试123", wxPoint(area.x, area.y), 100,50);
    Padding padding = GRID_MARGIN;
    // ç»˜åˆ¶æ …æ ¼
    int row_line_count = GRID_LINE_ROW_COUNT;
    int column_line_count = GRID_LINE_COL_COUNT;
    list<LineInfo*> grides_rows;
    double rowSpace = (area.height - padding.top - padding.bottom) / ((row_line_count - 1) * 1.0f);
    for (int i = 0; i < row_line_count; i++) {
        // ç»˜åˆ¶æ¨ªå‘æ …æ ¼
        LineInfo* lineInfo = new LineInfo();
        lineInfo->lineWidth = 1;
        if (i == row_line_count / 2) {
            lineInfo->lineWidth = 3;
        }
        lineInfo->style = wxPENSTYLE_SOLID;
        lineInfo->start = wxPoint(area.x + padding.left, area.y + padding.top + (int)(rowSpace * (i)) - lineInfo->lineWidth / 2);
        lineInfo->end = wxPoint(area.x + area.width - padding.right, area.y + padding.top + (int)(rowSpace * (i)) - lineInfo->lineWidth / 2);
        grides_rows.push_back(lineInfo);
    }
    for (list<LineInfo*>::iterator e = grides_rows.begin(); e != grides_rows.end(); ++e) {
        try {
            LineInfo* lineInfo = *e;
            wxPen dashedPen(COLOR_RED, lineInfo->lineWidth, lineInfo->style);
            dc.SetPen(dashedPen);
            dc.DrawLine(lineInfo->start, lineInfo->end);
        }
        catch (...) {
        }
    }
    list<LineInfo*> grides_cols;
    double columnSpace = (area.width - padding.left - padding.right) / ((column_line_count - 1) * 1.0f);
    for (int i = 0; i < column_line_count; i++) {
        // ç»˜åˆ¶æ¨ªå‘æ …æ ¼
        LineInfo* lineInfo = new LineInfo();
        lineInfo->lineWidth = 1;
        lineInfo->start = wxPoint(area.x + padding.left + (int)(columnSpace * (i)), area.y + padding.top);
        lineInfo->end = wxPoint(area.x + padding.left + (int)(columnSpace * (i)), area.y + area.height - padding.bottom - 1);
        if (i % 2 == 1) {
            lineInfo->style = wxPENSTYLE_DOT;
        }
        else {
            lineInfo->style = wxPENSTYLE_SOLID;
        }
        if (i == column_line_count / 2) {
            lineInfo->lineWidth = 2;
        }
        grides_cols.push_back(lineInfo);
    }
    for (list<LineInfo*>::iterator e = grides_cols.begin(); e != grides_cols.end(); ++e) {
        try {
            LineInfo* lineInfo = *e;
            wxPen dashedPen(COLOR_RED, lineInfo->lineWidth, lineInfo->style);
            dc.SetPen(dashedPen);
            dc.DrawLine(lineInfo->start, lineInfo->end);
        }
        catch (...) {
        }
    }
    //---------------绘制Label-------------------
    AxisYLabel ylabels[GRID_LINE_ROW_COUNT];
    const int UP_COUNT = (GRID_LINE_ROW_COUNT - 1) / 2;
    for (int i = 0; i < GRID_LINE_ROW_COUNT; i++) {
        AxisYLabel label;
        float rate = (UP_COUNT - i) * maxYRate / UP_COUNT;
        label.rightLabel = StringUtil::toString(abs(rate), 2).append("%");
        label.leftLabel = StringUtil::toString((100 + rate) * preClosePrice / 100, 3);
        ylabels[i] = AxisYLabel(label);
    }
    dc.SetPen(COLOR_RED);
    dc.SetBrush(COLOR_RED);
    wxPen dashedPen(COLOR_RED, 1, wxPENSTYLE_SOLID);
    dc.SetPen(dashedPen);
    int index = 0;
    for (list<LineInfo*>::iterator e = grides_rows.begin(); e != grides_rows.end(); ++e) {
        if (index == 0) {
            dc.SetTextForeground(COLOR_RED_TEXT);
        }
        else if (index == grides_rows.size() / 2) {
            dc.SetTextForeground(COLOR_WHITE_TEXT);
        }
        else if (index == grides_rows.size() / 2 + 1) {
            dc.SetTextForeground(COLOR_GREEN_TEXT);
        }
        try {
            LineInfo* lineInfo = *e;
            // ç»˜åˆ¶Y轴左侧标签
            wxSize textSize = dc.GetTextExtent(ylabels[index].leftLabel);
            dc.DrawText(ylabels[index].leftLabel, wxPoint(lineInfo->start.x - textSize.GetWidth() - 2, lineInfo->start.y - textSize.GetHeight() / 2));
            // ç»˜åˆ¶Y轴右侧标签
            textSize = dc.GetTextExtent(ylabels[index].rightLabel);
            dc.DrawText(ylabels[index].rightLabel, wxPoint(lineInfo->end.x + 2, lineInfo->end.y - textSize.GetHeight() / 2));
        }
        catch (...) {
        }
        index++;
    }
    // ç»˜åˆ¶æ—¶é—´
    dc.SetTextForeground(COLOR_RED_TEXT);
    if (timeSpaceType == TIME_SPACE_BAR)
    {
        wxString times[5] = { "09:30:00","10:30:00","11:30:00","14:00:00","15:00:00" };
        for (int i = 0; i < 5; i++) {
            wxPoint p = convertTickDataToPoint(TickData({ TickDataUtil::timeStrToSecondsAsAxisX(times[i], xStartTimeSeconds) ,0,"" }), area);
            wxString text = times[i].substr(0, 5);
            wxSize size = dc.GetTextExtent(text);
            wxPoint point(p.x - size.GetWidth() / 2, area.y + area.height - GRID_MARGIN.bottom + 2);
            dc.DrawText(text, point);
        }
    }
    else if (timeSpaceType == TIME_SPACE_TICK) {
        int spaceSeconds = this->xScopeSeconds / 4;
        wxString times[5];
        times[0] = xStartTime;
        for (int i = 0; i < 5; i++) {
            times[i] = TickDataUtil::tradTimeAdd(xStartTime, this->xScopeSeconds * i / 4);
        }
        for (int i = 0; i < 5; i++) {
            wxPoint p = convertTickDataToPoint(TickData({ TickDataUtil::timeStrToSecondsAsAxisX(times[i], xStartTimeSeconds) ,0,"" }), area);
            wxString text = times[i];
            wxSize size = dc.GetTextExtent(text);
            wxPoint point(p.x - size.GetWidth() / 2, area.y + area.height - GRID_MARGIN.bottom + 2);
            dc.DrawText(text, point);
        }
    }
}
void TickChart::drawMouse(wxDC& dc, wxRect area, wxPoint point)
{
    int x = mousePos.x;
    int y = mousePos.y;
    if (x >= area.x + GRID_MARGIN.left && x <= area.x + area.width - GRID_MARGIN.right) {
        if (y >= area.y + GRID_MARGIN.top && y <= area.y + area.height - GRID_MARGIN.bottom) {
            if (point.x >= 0 && point.y >= 0) {
                TickData tickData = pointToTick(point, area);
                dc.SetPen(COLOR_WHITE_TEXT);
                // æ¨ªçº¿
                dc.DrawLine(wxPoint(area.x + GRID_MARGIN.left, area.y + point.y), wxPoint(area.x + area.width - GRID_MARGIN.right, area.y + point.y));
                // ç«–线
                dc.DrawLine(wxPoint(area.x + point.x, area.y + GRID_MARGIN.top), wxPoint(area.x + point.x, area.y + area.height - GRID_MARGIN.bottom));
                // ç»˜åˆ¶æ—¶é—´
                wxPoint timePoint = wxPoint(area.x + point.x, area.y + area.height - GRID_MARGIN.bottom);
                wxString timeText = TickDataUtil::axisXSecondsToTimeStr(tickData.time, xStartTimeSeconds, timeSpaceType == TIME_SPACE_TICK ? TRUE : FALSE);
                wxSize size = dc.GetTextExtent(timeText);
                timePoint.x -= size.GetWidth() / 2; timePoint.y += 1;
                dc.SetPen(wxColor(64, 0, 128));
                dc.SetBrush(wxColor(64, 0, 128));
                // æ˜¾ç¤ºæ—¶é—´
                dc.DrawRectangle(wxRect(timePoint, size));
                dc.SetTextForeground(COLOR_RED_TEXT);
                dc.DrawLabel(timeText, wxRect(timePoint, size), wxALIGN_CENTER);
                // æ˜¾ç¤ºæ¯”例
                float rate = tickData.rate;
                string rateText = StringUtil::to_string(tickData.rate, 2);
                rateText.append("%");
                size = dc.GetTextExtent(rateText);
                wxPoint ratePoint = wxPoint(area.x + area.width - GRID_MARGIN.right, area.y + point.y);
                ratePoint.y -= size.GetHeight() / 2;
                ratePoint.x += 1;
                dc.DrawRectangle(wxRect(ratePoint, size));
                int r = (int)round(rate * 10000) / 100;
                if (r == 0) {
                    dc.SetTextForeground(COLOR_WHITE_TEXT);
                }
                else if (r > 0) {
                    dc.SetTextForeground(COLOR_RED_TEXT);
                }
                else {
                    dc.SetTextForeground(COLOR_GREEN_TEXT);
                }
                dc.DrawLabel(rateText, wxRect(ratePoint, size), wxALIGN_CENTER);
            }
        }
    }
}
void TickChart::drawTickLine(wxDC& dc, wxRect area)
{
    // ---------------绘制K线----------------
    int index = 0;
    wxPointList pointList;
    dc.SetPen(COLOR_WHITE_TEXT);
    for (std::list<TickData>::iterator e = cbTickDatas.begin(); e != cbTickDatas.end(); e++) {
        //点定位坐标
        TickData tickData = *e;
        wxPoint point = convertTickDataToPoint(tickData, area);
        pointList.Append(new wxPoint(point.x, point.y));
        index++;
    }
    dc.DrawLines(&pointList);
    //释放点内存
    pointList.Clear();
}
void TickChart::drawUnderlyingTickLine(wxDC& dc, wxRect area)
{
    // ---------------绘制股票K线----------------
    int index = 0;
    wxPointList pointList;
    dc.SetPen(COLOR_UNDERLYING_LINE);
    for (std::list<TickData>::iterator e = underlyingTickDatas.begin(); e != underlyingTickDatas.end(); e++) {
        //点定位坐标
        TickData tickData = *e;
        wxPoint point = convertTickDataToPoint(tickData, area, underlyingScale);
        pointList.Append(new wxPoint(point.x, point.y));
        index++;
    }
    dc.DrawLines(&pointList);
    //释放点内存
    pointList.Clear();
}
void TickChart::drawBuyPoint(wxDC& dc, wxPoint point)
{
    dc.SetPen(wxColor(232, 62, 37));
    dc.SetBrush(wxColor(232, 62, 37));
    dc.DrawCircle(point, POINT_REDIUS);
}
void TickChart::drawSellPoint(wxDC& dc, wxPoint point)
{
    dc.SetPen(wxColor(59, 123, 191));
    dc.SetBrush(wxColor(59, 123, 191));
    dc.DrawCircle(point, POINT_REDIUS);
}
void TickChart::drawBuyAndSellPointInfo(wxDC& paint, wxRect area, wxPoint mousePoint)
{
    paint.SetPen(wxColour(255, 255, 255, 125));
    paint.SetBrush(wxColour(255, 255, 255, 125));
    // å¦‚果在买点周围4个像素
    // ç»˜åˆ¶ä¹°å–点
    for (std::list<TickTradeData>::iterator e = buyPoints.begin(); e != buyPoints.end(); e++) {
        TickTradeData tickData = *e;
        wxPoint point = convertTickDataToPoint(*e, area);
        if (abs(mousePoint.x - point.x) < POINT_REDIUS * 2 && abs(mousePoint.y - point.y) < POINT_REDIUS * 2) {
            // è®¡ç®—位置
            wxString text = wxString("成交时间:").Append(tickData.time).Append("\n");
            text.Append("涨幅:").Append(StringUtil::to_string(tickData.rate)).Append("%").Append("\n");
            text.Append("成交价:").Append(tickData.price).Append("元\n");
            text.Append("成交量:").Append(to_string(tickData.volume)).Append("\n");
            text.Append("成交额:").Append(tickData.money).Append("元");
            drawInfo(paint, wxPoint(point.x + POINT_REDIUS, point.y + POINT_REDIUS), text, {});
            break;
        }
    }
    for (std::list<TickTradeData>::iterator e = sellPoints.begin(); e != sellPoints.end(); e++) {
        TickTradeData tickData = *e;
        wxPoint point = convertTickDataToPoint(*e, area);
        if (abs(mousePoint.x - point.x) < POINT_REDIUS * 2 && abs(mousePoint.y - point.y) < POINT_REDIUS * 2) {
            wxString text = wxString("成交时间:").Append(tickData.time).Append("\n");
            text.Append("涨幅:").Append(StringUtil::to_string(tickData.rate)).Append("%").Append("\n");
            text.Append("成交价:").Append(tickData.price).Append("元\n");
            text.Append("成交量:").Append(to_string(tickData.volume)).Append("\n");
            text.Append("成交额:").Append(tickData.money).Append("元");
            drawInfo(paint, wxPoint(point.x + POINT_REDIUS, point.y + POINT_REDIUS), text, {});
            break;
        }
    }
}
void TickChart::drawInfo(wxDC& paint, wxPoint position, wxString content, std::list<ColorIndexInfo> colorIndexes)
{
    std::vector<wxString> substrings;
    size_t start = 0;
    size_t end = content.find("\n");
    while (end != std::string::npos) {
        substrings.push_back(content.substr(start, end - start));
        start = end + 1;
        end = content.find("\n", start);
    }
    substrings.push_back(content.substr(start, end));
    int maxWidth = 0;
    int lineHeight = 0;
    for (std::vector<wxString>::iterator e = substrings.begin(); e != substrings.end(); ++e) {
        wxString text = *e;
        wxSize size = paint.GetTextExtent(text);
        if (size.GetWidth() > maxWidth) {
            maxWidth = size.GetWidth();
        }
        if (size.GetHeight() > lineHeight) {
            lineHeight = size.GetHeight();
        }
    }
    int padding = 2;
    wxRect rect = wxRect(wxPoint(position.x, position.y), wxSize(maxWidth + padding * 2, lineHeight * substrings.size()));
    paint.DrawRoundedRectangle(rect, 2);
    std::list<ColorIndexInfo> colors;
    WidgetsRenderUtil::drawText(&paint, content, wxPoint(rect.GetPosition().x + padding, rect.GetPosition().y), rect.GetSize().GetWidth() - padding * 2, lineHeight, colorIndexes);
}
void TickChart::drawUnderlyingLatestRate(wxDC& paint, wxRect area)
{
    if (underlyingTickDatas.size() > 0) {
        // ç»˜åˆ¶Tick线最新的点
        TickData lastTickData = underlyingTickDatas.back();
        wxPoint point = convertTickDataToPoint(lastTickData, area, underlyingScale);
        // ç»˜åˆ¶æ–‡å­—
        wxString rateText = " æ­£è‚¡ï¼š";
        if (lastTickData.rate < 0) {
            paint.SetTextForeground(COLOR_GREEN_TEXT);
            rateText.Append(StringUtil::to_string(lastTickData.rate));
            rateText.Append("%");
        }
        else {
            paint.SetTextForeground(COLOR_RED_TEXT);
            rateText.Append(L"+");
            rateText.Append(StringUtil::to_string(lastTickData.rate));
            rateText.Append("%");
        }
        rateText.Append(" ");
        wxSize rateSize = paint.GetTextExtent(rateText);
        int x = area.x + area.GetWidth() - rateSize.GetWidth()- GRID_MARGIN.right;
        int y = area.y + area.GetHeight() - rateSize.GetHeight() - GRID_MARGIN.bottom;
        paint.DrawRoundedRectangle(wxPoint(x, y), rateSize, 0);
        paint.DrawText(rateText, wxPoint(x,y));
    }
}
TickChart::TickChart(wxWindow* parent, wxWindowID id, int timeSpace, TIME_SPACE_TYPE timeSpaceType, wxString xStartTime, wxString xEndTime, const wxPoint& pos, const wxSize& size) : wxControl(parent, id, pos, size, wxBORDER_NONE), timeSpace(timeSpace), timeSpaceType(timeSpaceType), xStartTime(xStartTime), xEndTime(xEndTime), maxYRate(20), limitUpRate(20), preClosePrice(10.00)
{
    SetBackgroundStyle(wxBG_STYLE_PAINT);
    mousePos = wxPoint(-1, -1);
    Bind(wxEVT_PAINT, &TickChart::OnPaint, this);
    Bind(wxEVT_MOTION, &TickChart::OnMouseMove, this);
    Bind(wxEVT_LEFT_DCLICK, &TickChart::OnDoubleClick, this);
    mouseDC = new wxClientDC(this);
    this->xStartTimeSeconds = TickDataUtil::timeStrToSeconds(xStartTime);
    this->xScopeSeconds = TickDataUtil::tradTimeSub(xEndTime, xStartTime);
    cout << xStartTime << "==>" << xEndTime << ":" << this->xScopeSeconds << endl;
    // åˆå§‹åŒ–数据
    cbCodeInfo = { "","",0 };
    underlyingCodeInfo = { "","",0 };
    underlyingScale = 1.0f;
}
void TickChart::OnPaint(wxPaintEvent& event)
{
    try {
        wxBufferedPaintDC  dc(this);
        PrepareDC(dc);
        /*wxMemoryDC dc;
        wxBitmap bitmap(GetSize());
        dc.SelectObject(bitmap);*/
        dc.SetBackground(wxBrush(*wxBLACK));
        // ç»˜åˆ¶èƒŒæ™¯
        dc.SetPen(*wxBLACK);
        dc.SetBrush(*wxBLACK);
        dc.DrawRectangle(GetClientRect());
        dc.SetTextForeground(*wxBLACK);
        // ç»˜åˆ¶åæ ‡è½´
        dc.SetPen(COLOR_RED);
        wxRect rect = GetClientRect();
        // ç»˜åˆ¶åæ ‡è½´
        drawAxis(dc, rect);
        // ç»˜åˆ¶åç§°
        if (cbCodeInfo.codeName.Length() > 0) {
            dc.SetTextForeground(COLOR_RED_TEXT);
            wxSize s = dc.GetTextExtent(cbCodeInfo.codeName);
            dc.DrawText(cbCodeInfo.codeName, wxPoint((rect.GetWidth() - s.GetWidth()) / 2, 0));
        }
        drawTickLine(dc, rect);
        drawUnderlyingTickLine(dc, rect);
        // ç»˜åˆ¶æˆæœ¬çº¿
        TickData costRateInfo;
        costRateInfo.rate = costRate;
        costRateInfo.time = 0;
        costRateInfo.price = "0.00";
        wxPoint startPoint = convertTickDataToPoint(costRateInfo, rect);
        costRateInfo.time = xScopeSeconds;
        wxPoint endPoint = convertTickDataToPoint(costRateInfo, rect);
        wxPen dashedPen(COLOR_YELLOW, 1, wxPENSTYLE_DOT);
        dc.SetPen(dashedPen);
        dc.DrawLine(startPoint, endPoint);
        // ç»˜åˆ¶ä¹°å–点
        for (std::list<TickTradeData>::iterator e = buyPoints.begin(); e != buyPoints.end(); e++) {
            if (TickDataUtil::tradTimeSub((*e).time, xStartTime) < 0) {
                continue;
            }
            if (TickDataUtil::tradTimeSub((*e).time, xEndTime) > 0) {
                continue;
            }
            wxPoint point = convertTickDataToPoint(*e, rect);
            drawBuyPoint(dc, point);
        }
        for (std::list<TickTradeData>::iterator e = sellPoints.begin(); e != sellPoints.end(); e++) {
            if (TickDataUtil::tradTimeSub((*e).time, xStartTime) < 0) {
                continue;
            }
            if (TickDataUtil::tradTimeSub((*e).time, xEndTime) > 0) {
                continue;
            }
            wxPoint point = convertTickDataToPoint(*e, rect);
            drawSellPoint(dc, point);
        }
        drawMouse(dc, rect, mousePos);
        drawBuyAndSellPointInfo(dc, rect, mousePos);
        drawUnderlyingLatestRate(dc, rect);
        //pdc.Clear();
        // é‡‡ç”¨åŒç¼“存绘制
        //pdc.Blit(0, 0, GetSize().GetWidth(), GetSize().GetHeight(), &dc, 0, 0);
        // æ›´æ–°ç•Œé¢
        Update();
    }
    catch (...) {
    }
}
void TickChart::OnMouseMove(wxMouseEvent& event)
{
    event.Skip();
    mousePos = event.GetPosition();
    Refresh();
}
void TickChart::OnDoubleClick(wxMouseEvent& event)
{
    event.Skip();
    wxPoint point = event.GetPosition();
    if (timeSpaceType != TIME_SPACE_BAR) {
        return;
    }
    int x_time = -1;
    int line_index = 0;// ç¬¬å‡ æ¡çº¿
    for (std::list<TickTradeData>::iterator e = buyPoints.begin(); e != buyPoints.end(); ++e) {
        TickTradeData tick = *e;
        wxPoint p = convertTickDataToPoint(tick, GetClientRect());
        if (abs(p.x - point.x) < POINT_REDIUS && abs(p.y - point.y) < POINT_REDIUS) {
            x_time = TickDataUtil::timeStrToSecondsAsAxisX(tick.time, xStartTimeSeconds);
            line_index = 0;
            break;
        }
    }
    if (x_time < 0) {
        for (std::list<TickTradeData>::iterator e = sellPoints.begin(); e != sellPoints.end(); ++e) {
            TickTradeData tick = *e;
            wxPoint p = convertTickDataToPoint(tick, GetClientRect());
            if (abs(p.x - point.x) < POINT_REDIUS && abs(p.y - point.y) < POINT_REDIUS) {
                x_time = TickDataUtil::timeStrToSecondsAsAxisX(tick.time, xStartTimeSeconds);
                line_index = 0;
                break;
            }
        }
    }
    if (x_time < 0) {
        // åˆ¤æ–­åŒå‡»æ˜¯ç‚¹å‡»åœ¨å“ªæ ¹çº¿ä¸Š
        for (std::list<TickData>::iterator e = underlyingTickDatas.begin(); e != underlyingTickDatas.end(); ++e) {
            TickData tick = *e;
            wxPoint p = convertTickDataToPoint(tick, GetClientRect());
            if (abs(p.x - point.x) < 4 && abs(p.y - point.y) < 4) {
                x_time = tick.time;
                line_index = 1;
                break;
            }
        }
    }
    if (x_time < 0) {
        // åˆ¤æ–­åŒå‡»æ˜¯ç‚¹å‡»åœ¨å“ªæ ¹çº¿ä¸Š
        for (std::list<TickData>::iterator e = cbTickDatas.begin(); e != cbTickDatas.end(); ++e) {
            TickData tick = *e;
            wxPoint p = convertTickDataToPoint(tick, GetClientRect());
            if (abs(p.x - point.x) < 4) {
                x_time = tick.time;
                line_index = 0;
                break;
            }
        }
    }
    if (x_time >= 0) {
        // èŽ·å–é™„è¿‘5分钟的tick信息
        int start_time = x_time - 300;
        int end_time = x_time + 300;
        wxString start_time_str = TickDataUtil::axisXSecondsToTimeStr(start_time, xStartTimeSeconds);
        cout << "tick详情:" << start_time_str << endl;
        if (TickDataUtil::tradTimeSub(start_time_str, "09:30:00") < 0) {
            start_time_str = "09:30:00";
        }
        wxString end_time_str = TickDataUtil::axisXSecondsToTimeStr(end_time, xStartTimeSeconds);
        cout << "tick详情:" << end_time_str << endl;
        if (TickDataUtil::tradTimeSub(end_time_str, "15:00:00") > 0) {
            end_time_str = "15:00:00";
        }
        if (this->tickDetailCallback) {
            if (line_index == 0) {
                this->tickDetailCallback(cbCodeInfo, start_time_str, end_time_str, buyPoints, sellPoints, costRate, parentContext);
            }
            else  if (line_index == 1) {
                this->tickDetailCallback(underlyingCodeInfo, start_time_str, end_time_str, buyPoints, sellPoints, costRate, parentContext);
            }
        }
    }
}
void TickChart::Init(CodeBasicInfo cb, CodeBasicInfo underlying, void* parentContext, std::function<void(CodeBasicInfo, wxString, wxString, std::list<TickTradeData>, std::list<TickTradeData>, float, void*)> tickCllback)
{
    this->parentContext = parentContext;
    this->tickDetailCallback = tickCllback;
    this->cbCodeInfo = cb;
    this->underlyingCodeInfo = underlying;
    if (this->cbCodeInfo.code.Length() > 0) {
        this->preClosePrice = cb.preClosePrice;
        double limitUpPrice = std::round((cb.preClosePrice * 1.2) * 1000) / 1000;
        double limitUpRate = std::round(((limitUpPrice - cb.preClosePrice) / cb.preClosePrice) * 10000) / 100;
        this->maxYRate = limitUpRate;
        this->maxYRateUnderlying = 0;
        this->limitUpRate = limitUpRate;
    }
    else if (this->underlyingCodeInfo.code.Length() > 0) {
        float rate = 1.2;
        if (underlyingCodeInfo.code.find("00") == 0 || underlyingCodeInfo.code.find("60") == 0) {
            rate = 1.1;
        }
        this->preClosePrice = underlyingCodeInfo.preClosePrice;
        double limitUpPrice = std::round((underlyingCodeInfo.preClosePrice * rate) * 1000) / 1000;
        double limitUpRate = std::round(((limitUpPrice - underlyingCodeInfo.preClosePrice) / underlyingCodeInfo.preClosePrice) * 10000) / 100;
        this->maxYRate = limitUpRate;
        this->maxYRateUnderlying = 0;
        this->limitUpRate = limitUpRate;
    }
    this->cbTickDatas.clear();
    this->underlyingTickDatas.clear();
    this->buyPoints.clear();
    this->sellPoints.clear();
    this->costRate = 0;
    //请求之前的数据
    long now = TimeUtil::getNowTimeStamp();
    string day = TimeUtil::format(now, "%Y-%m-%d");
    string time = TimeUtil::format(now, "%H:%M:%S");
    if (TickDataUtil::tradTimeSub(time, xStartTime) >= 0) {
        if (TickDataUtil::tradTimeSub(time, xEndTime) > 0) {
            time = xEndTime;
        }
        // 09:25之后开始拉数据
        string startTime = string("").append(day).append(" ").append(xStartTime);
        string endTime = string("").append(day).append(" ").append(time);
        if (TickDataUtil::tradTimeSub(startTime, endTime) < this->timeSpace) {
            if (timeSpaceType == TIME_SPACE_BAR)
            {
                if (underlyingCodeInfo.code.Length() > 0)
                {
                    // æ‹‰å–正股数据
                    DataArray<Bar>* tempUDatas = JueJinDataUtil::getBarDatas(JueJinDataUtil::getSymbol(underlyingCodeInfo.code.ToStdString()), startTime, endTime);
                    for (int i = 0; i < tempUDatas->count(); i++)
                    {
                        auto datas = tempUDatas->at(i);
                        if (datas.close < 0.0001) {
                            continue;
                        }
                        wxString time_str = TimeUtil::format((long)datas.bob, "%H:%M:%S");
                        float price = datas.open;
                        AddUnderlyingTickData(time_str, 100 * (price - underlyingCodeInfo.preClosePrice) / underlyingCodeInfo.preClosePrice, FALSE);
                        if (i == tempUDatas->count() - 1) {
                            // åŠ è½½Bar线无法覆盖的时间段数据
                            time_str = TimeUtil::format((long)datas.eob, "%H:%M:%S");
                            wxString tickStartTime = "";
                            tickStartTime.Append(day).Append(" ");
                            tickStartTime.Append(time_str);
                            DataArray<Tick>* tempTickDatas = JueJinDataUtil::getTickDatas(JueJinDataUtil::getSymbol(underlyingCodeInfo.code.ToStdString()), tickStartTime.ToStdString(), endTime);
                            for (int j = 0; j < tempTickDatas->count(); j++)
                            {
                                auto datas = tempTickDatas->at(j);
                                if (datas.price < 0.0001) {
                                    continue;
                                }
                                AddUnderlyingTickData(TimeUtil::format((long)datas.created_at, "%H:%M:%S"), 100 * (datas.price - underlyingCodeInfo.preClosePrice) / underlyingCodeInfo.preClosePrice, FALSE);
                            }
                        }
                    }
                }
                if (cbCodeInfo.code.Length() > 0) {
                    //需要大于timeSpace才能拉数据
                    DataArray<Bar>* tempDatas = JueJinDataUtil::getBarDatas(JueJinDataUtil::getSymbol(cbCodeInfo.code.ToStdString()), startTime, endTime);
                    for (int i = 0; i < tempDatas->count(); i++)
                    {
                        auto datas = tempDatas->at(i);
                        if (datas.close < 0.0001) {
                            continue;
                        }
                        string  time_str = TimeUtil::format((long)datas.bob, "%H:%M:%S");
                        float price = datas.open;
                        AddTickData(time_str, 100 * (price - preClosePrice) / preClosePrice, to_string(datas.close), FALSE);
                        if (i == tempDatas->count() - 1) {
                            // åŠ è½½Bar线无法覆盖的时间段数据
                            time_str = TimeUtil::format((long)datas.eob, "%H:%M:%S");
                            price = datas.close;
                            wxString tickStartTime = "";
                            tickStartTime.Append(day).Append(" ");
                            tickStartTime.Append(time_str);
                            DataArray<Tick>* tempTickDatas = JueJinDataUtil::getTickDatas(JueJinDataUtil::getSymbol(cbCodeInfo.code.ToStdString()), tickStartTime.ToStdString(), endTime);
                            for (int j = 0; j < tempTickDatas->count(); j++)
                            {
                                auto datas = tempTickDatas->at(j);
                                if (datas.price < 0.0001) {
                                    continue;
                                }
                                AddTickData(TimeUtil::format((long)datas.created_at, "%H:%M:%S"), 100 * (datas.price - preClosePrice) / preClosePrice, to_string(datas.price), FALSE);
                            }
                        }
                    }
                }
            }
            else if (timeSpaceType == TIME_SPACE_TICK) {
                if (cbCodeInfo.code.Length() > 0) {
                    //需要大于timeSpace才能拉数据
                    DataArray<Tick>* tempDatas = JueJinDataUtil::getTickDatas(JueJinDataUtil::getSymbol(cbCodeInfo.code.ToStdString()), startTime, endTime);
                    for (int i = 0; i < tempDatas->count(); i++)
                    {
                        auto datas = tempDatas->at(i);
                        if (datas.price < 0.0001) {
                            continue;
                        }
                        AddTickData(TimeUtil::format((long)datas.created_at, "%H:%M:%S"), 100 * (datas.price - preClosePrice) / preClosePrice, to_string(datas.price), FALSE);
                    }
                }
                if (underlyingCodeInfo.code.Length() > 0) {
                    // æ‹‰å–正股数据
                    DataArray<Tick>* tempUDatas = JueJinDataUtil::getTickDatas(JueJinDataUtil::getSymbol(underlyingCodeInfo.code.ToStdString()), startTime, endTime);
                    for (int i = 0; i < tempUDatas->count(); i++)
                    {
                        auto datas = tempUDatas->at(i);
                        if (datas.price < 0.0001) {
                            continue;
                        }
                        AddUnderlyingTickData(TimeUtil::format((long)datas.created_at, "%H:%M:%S"), 100 * (datas.price - underlyingCodeInfo.preClosePrice) / underlyingCodeInfo.preClosePrice, FALSE);
                    }
                }
            }
        }
    }
    Refresh();
}
void TickChart::AddTickData(wxString time, float rate, wxString price, bool refresh)
{
    if (TickDataUtil::tradTimeSub(time, xEndTime) > 0) {
        return;
    }
    int seconds = TickDataUtil::timeStrToSecondsAsAxisX(time, TickDataUtil::timeStrToSeconds(xStartTime));
    if (!cbTickDatas.empty())
    {
        TickData last = cbTickDatas.back();
        if (last.time > seconds) {
            return;
        }
        if (seconds / this->timeSpace != last.time / this->timeSpace) {
            cbTickDatas.push_back(TickData({ seconds , rate, price }));
        }
        else {
            cbTickDatas.back().price = price;
            cbTickDatas.back().time = seconds;
            cbTickDatas.back().rate = rate;
            cout << "最后一条数据:" << cbTickDatas.back().time << "-" << cbTickDatas.back().price << endl;
        }
        float newMaxYRate = abs(rate) + MAX_RATE_FLOAT;
        if (newMaxYRate > maxYRate) {
            maxYRate = min(newMaxYRate, limitUpRate);
            if (maxYRateUnderlying > 0) {
                underlyingScale = maxYRate / maxYRateUnderlying / 2;
            }
        }
    }
    else {
        cbTickDatas.push_back(TickData({ seconds , rate, price }));
        if (abs(rate) < limitUpRate - MAX_RATE_FLOAT) {
            maxYRate = abs(rate) + MAX_RATE_FLOAT;
            if (maxYRateUnderlying > 0) {
                underlyingScale = maxYRate / maxYRateUnderlying / 2;
            }
        }
    }
    if (refresh) {
        Refresh();
    }
}
void TickChart::AddUnderlyingTickData(wxString time, float rate, bool refresh)
{
    if (TickDataUtil::tradTimeSub(time, xEndTime) > 0) {
        return;
    }
    int seconds = TickDataUtil::timeStrToSecondsAsAxisX(time, xStartTimeSeconds);
    if (!underlyingTickDatas.empty())
    {
        TickData last = underlyingTickDatas.back();
        if (last.time > seconds) {
            return;
        }
        if (seconds / this->timeSpace != last.time / this->timeSpace) {
            underlyingTickDatas.push_back(TickData({ seconds , rate, "" }));
        }
        else {
            underlyingTickDatas.back().price = "";
            underlyingTickDatas.back().time = seconds;
            underlyingTickDatas.back().rate = rate;
            cout << "最后一条数据:" << underlyingTickDatas.back().time << "-" << underlyingTickDatas.back().price << endl;
        }
        float newMaxYRate = abs(rate) + MAX_RATE_FLOAT;
        if (newMaxYRate > maxYRateUnderlying) {
            maxYRateUnderlying = min(newMaxYRate, limitUpRate);
        }
    }
    else {
        underlyingTickDatas.push_back(TickData({ seconds , rate, "" }));
    }
    // æ­£è‚¡ä¸æµ®åЍ
    float newMaxYRate = abs(rate);
    if (newMaxYRate > maxYRateUnderlying) {
        maxYRateUnderlying = min(newMaxYRate, limitUpRate);
    }
    if (refresh) {
        Refresh();
    }
}
void TickChart::AddBuyPoint(wxString time, float rate, wxString price, int volume, wxString money)
{
    AddBuyPoint(TickTradeData({ time , rate, price,volume, money }));
}
void TickChart::AddBuyPoint(TickTradeData data)
{
    buyPoints.push_back(data);
    Refresh();
}
void TickChart::SetBuyPoint(std::list<TickTradeData> datas)
{
    buyPoints.clear();
    for (std::list<TickTradeData>::iterator e = datas.begin(); e != datas.end(); ++e) {
        buyPoints.push_back(*e);
    }
}
void TickChart::AddSellPoint(wxString time, float rate, wxString price, int volume, wxString money)
{
    AddSellPoint(TickTradeData({ time , rate, price ,volume, money }));
}
void TickChart::AddSellPoint(TickTradeData data)
{
    sellPoints.push_back(data);
    Refresh();
}
void TickChart::SetSellPoint(std::list<TickTradeData> datas)
{
    sellPoints.clear();
    for (std::list<TickTradeData>::iterator e = datas.begin(); e != datas.end(); ++e) {
        sellPoints.push_back(*e);
    }
}
void TickChart::SetCostRate(wxString code, float rate, wxString price)
{
    this->costRate = rate;
    if (this->costRate > limitUpRate) {
        this->costRate = limitUpRate;
    }
    Refresh();
}
CBTrade/TickChart.h
New file
@@ -0,0 +1,297 @@
#pragma once
/// <summary>
/// åˆ†æ—¶çº¿
/// </summary>
#include <wx/wx.h>
#include<list>
#include <map>
#include "../common_nopch/WidgetsRenderUtil.h"
struct  CodeBasicInfo
{
    wxString code;
    wxString codeName;
    double preClosePrice;
};
enum TIME_SPACE_TYPE {
    TIME_SPACE_TICK,
    TIME_SPACE_BAR
};
struct Padding {
    int left;
    int top;
    int right;
    int bottom;
};
struct LineInfo{
    wxPoint start;//q起点
    wxPoint end;//终点
    int lineWidth;//线宽
    wxPenStyle style;
};
/// <summary>
/// çºµåæ ‡çš„æ ‡ç­¾
/// </summary>
struct AxisYLabel {
    wxString leftLabel;
    wxString rightLabel;
};
/// <summary>
/// K线分时数据
/// </summary>
struct TickData {
    int time;// è·ç¦»9点25的s数
    float rate;//涨幅
    wxString price;// ä»·æ ¼
};
/// <summary>
/// tick交易信息
/// </summary>
struct TickTradeData {
    wxString time;// è·ç¦»å¼€å§‹æ—¶é—´çš„s数
    float rate;//涨幅
    wxString price;// ä»·æ ¼
    int volume;// æˆäº¤é‡
    wxString money;// æˆäº¤é‡‘额
};
class TickChart : public wxControl
{
private:
    void* parentContext;
    // æ­£è‚¡ç¼©æ”¾æ¯”例
    float underlyingScale;
    // æœ€å°åˆ»åº¦ç±»åž‹
    TIME_SPACE_TYPE timeSpaceType;
    // æœ€å°åˆ»åº¦æ—¶é—´
    int timeSpace;
    // X轴开始时间
    wxString xStartTime;
    int xStartTimeSeconds;
    // X轴结束时间
    wxString xEndTime;
    // æ•´ä¸ªX轴的时间囊括
    int xScopeSeconds;
    wxClientDC *mouseDC;
    // Tick数据
    std::list<TickData> cbTickDatas;
    std::list<TickData> underlyingTickDatas;
    std::list<TickTradeData> buyPoints;
    std::list<TickTradeData> sellPoints;
    // ä»£ç åç§°
    CodeBasicInfo cbCodeInfo;
    CodeBasicInfo underlyingCodeInfo;
    // æ¶¨åœæ¶¨å¹…
    float limitUpRate;
    // åšå¤§çš„Y轴值
    float maxYRate;
    // æ­£è‚¡æœ€å¤§Y轴的值
    float maxYRateUnderlying;
    // æ˜¨æ—¥æ”¶ç›˜ä»·
    float preClosePrice;
    // æˆæœ¬æ¯”例
    float costRate;
    // é¼ æ ‡ä½ç½®
    wxPoint mousePos;
private:
    /// <summary>
    /// è¡Œæƒ…详情回调,回调参数:(代码,名称,收盘价,X轴开始时间,X轴结束时间)
    /// </summary>
    std::function<void(CodeBasicInfo, wxString, wxString, std::list<TickTradeData> , std::list<TickTradeData> , float, void*)> tickDetailCallback;
private:
    /// <summary>
    /// å°†TickData转为坐标点
    /// </summary>
    /// <param name="tickData"></param>
    /// <returns></returns>
    wxPoint convertTickDataToPoint(TickData tickData, wxRect area, float scale = 1);
    /// <summary>
    /// å°†TickTradeData转为坐标点
    /// </summary>
    /// <param name="tickData"></param>
    /// <returns></returns>
    wxPoint convertTickDataToPoint(TickTradeData tickData, wxRect area);
    /// <summary>
    /// å°†ç‚¹è½¬ä¸ºtick数据
    /// </summary>
    /// <param name="tick"></param>
    /// <param name="area"></param>
    /// <returns></returns>
    TickData pointToTick(wxPoint tick, wxRect area);
    /// <summary>
    /// ç»˜åˆ¶åæ ‡ç³»
    /// </summary>
    /// <param name="dc"></param>
    /// <param name="area"></param>
    void drawAxis(wxDC& dc,wxRect area);
    /// <summary>
    /// ç»˜åˆ¶åˆ†æ—¶çº¿
    /// </summary>
    /// <param name="paint"></param>
    /// <param name="area"></param>
    void drawTickLine(wxDC& paint, wxRect area);
    /// <summary>
    /// ç»˜åˆ¶æ­£è‚¡åˆ†æ—¶çº¿
    /// </summary>
    /// <param name="paint"></param>
    /// <param name="area"></param>
    void drawUnderlyingTickLine(wxDC& paint, wxRect area);
    /// <summary>
    /// ç»˜åˆ¶ä¹°ç‚¹
    /// </summary>
    /// <param name="paint"></param>
    /// <param name="point"></param>
    void drawBuyPoint(wxDC& paint, wxPoint point);
    /// <summary>
    /// ç»˜åˆ¶å–点
    /// </summary>
    /// <param name="paint"></param>
    /// <param name="point"></param>
    void drawSellPoint(wxDC& paint, wxPoint point);
    /// <summary>
    /// ç»˜åˆ¶é¼ æ ‡åå­—星线
    /// </summary>
    /// <param name="paint"></param>
    /// <param name="area"></param>
    /// <param name="point"></param>
    void drawMouse(wxDC& paint, wxRect area, wxPoint point);
    /// <summary>
    /// ç»˜åˆ¶ä¹°ç‚¹æˆ–者卖点的信息
    /// </summary>
    /// <param name="paint"></param>
    /// <param name="area"></param>
    /// <param name="mousePoint"></param>
    void drawBuyAndSellPointInfo(wxDC& paint, wxRect area, wxPoint mousePoint);
    /// <summary>
    /// ç»˜åˆ¶ä¿¡æ¯æ¡†
    /// </summary>
    /// <param name="paint"></param>
    /// <param name="position"></param>
    /// <param name="content"></param>
    /// <param name="colorIndexes"></param>
    void drawInfo(wxDC& paint, wxPoint position, wxString content, std::list<ColorIndexInfo> colorIndexes );
    /// <summary>
    /// ç»˜åˆ¶æœ€æ–°çš„æ¶¨å¹…
    /// </summary>
    /// <param name="paint"></param>
    /// <param name="area"></param>
    void drawUnderlyingLatestRate(wxDC& paint, wxRect area);
public:
    TickChart(wxWindow* parent, wxWindowID id,int timeSpace, TIME_SPACE_TYPE timeSpaceType, wxString xStartTime,wxString xEndTime,
        const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize);
    void OnPaint(wxPaintEvent& event);
    void OnMouseMove(wxMouseEvent& event);
    void OnDoubleClick(wxMouseEvent& event);
    /// <summary>
    /// åˆå§‹åŒ–
    /// </summary>
    /// <param name="name">名称</param>
    /// <param name="maxRate">最大涨幅</param>
    void Init(CodeBasicInfo cb, CodeBasicInfo underlying,void* parentContext, std::function<void(CodeBasicInfo, wxString, wxString, std::list<TickTradeData>, std::list<TickTradeData>, float, void*)> tickCllback);
    /// <summary>
    ///  æ·»åŠ Tick数据
    /// </summary>
    /// <param name="time"></param>
    /// <param name="rate"></param>
    /// <param name="price"></param>
    void AddTickData(wxString time, float rate, wxString price, bool refresh=TRUE);
    /// <summary>
    /// æ·»åŠ æ­£è‚¡æ•°æ®
    /// </summary>
    /// <param name="time"></param>
    /// <param name="rate"></param>
    /// <param name="refresh"></param>
    void AddUnderlyingTickData(wxString time, float rate, bool refresh = TRUE);
    /// <summary>
    /// æ·»åŠ ä¹°ç‚¹
    /// </summary>
    /// <param name="time"></param>
    /// <param name="rate"></param>
    /// <param name="price"></param>
    void AddBuyPoint(wxString time, float rate, wxString price, int volume, wxString money);
    /// <summary>
    /// æ·»åŠ ä¹°ç‚¹
    /// </summary>
    /// <param name="data"></param>
    void AddBuyPoint(TickTradeData data);
    /// <summary>
    /// è®¾ç½®ä¹°ç‚¹
    /// </summary>
    /// <param name="datas"></param>
    void SetBuyPoint(std::list<TickTradeData> datas);
    /// <summary>
    /// æ·»åŠ å–ç‚¹
    /// </summary>
    /// <param name="time"></param>
    /// <param name="rate"></param>
    /// <param name="price"></param>
    void AddSellPoint(wxString time, float rate, wxString price, int volume, wxString money);
    /// <summary>
    /// æ·»åŠ å–ç‚¹
    /// </summary>
    /// <param name="data"></param>
    void AddSellPoint(TickTradeData data);
    /// <summary>
    /// è®¾ç½®å–点
    /// </summary>
    /// <param name="datas"></param>
    void SetSellPoint(std::list<TickTradeData> datas);
    /// <summary>
    /// è®¾ç½®æˆæœ¬æ¯”例
    /// </summary>
    /// <param name="code"></param>
    /// <param name="rate"></param>
    void SetCostRate(wxString code, float rate, wxString price);
};
CBTrade/TickDataRequestStrategy.cpp
New file
@@ -0,0 +1,46 @@
#include "TickDataRequestStrategy.h"
using namespace std;
TickDataRequestStrategy::TickDataRequestStrategy(std::string token, std::string strategy_id, int mode, void* context, std::function<void(Tick* tick, void* context)> callback):Strategy(token.c_str(), strategy_id.c_str(),mode),callback(callback), parentContext(context)
{
}
void TickDataRequestStrategy::subscribeSymbol(std::string symbol, std::string underlyingSymbol)
{
    int result = subscribe(symbol.c_str(), "tick", true);
    result = subscribe(underlyingSymbol.c_str(), "tick", false);
    if (result != 0) {
        throw std::string("订阅失败:").append(std::to_string(result));
    }
    cout << "订阅结果:"<< result << endl;
}
void TickDataRequestStrategy::on_init()
{
    cout<<"策略初始化" << endl;
}
void TickDataRequestStrategy::on_tick(Tick* tick)
{
    cout << "on_tick:"<< tick->price << endl;
    if (this->callback) {
        callback(tick, this->parentContext);
    }
}
void TickDataRequestStrategy::on_market_data_connected()
{
    cout << "on_market_data_connected" << endl;
}
void TickDataRequestStrategy::on_market_data_disconnected()
{
    cout << "on_market_data_disconnected" << endl;
}
//回测完成事件
void TickDataRequestStrategy::on_backtest_finished(Indicator* indicator)
{
    cout << "on_backtest_finished" << endl;
}
CBTrade/TickDataRequestStrategy.h
New file
@@ -0,0 +1,34 @@
#pragma once
#include <strategy.h>
#include "JueJinDataUtil.h"
#include <functional>
/// <summary>
/// åˆ†æ—¶æ•°æ®è¯·æ±‚ç­–ç•¥
/// </summary>
class TickDataRequestStrategy: public Strategy
{
private:
    std::function<void(Tick* tick, void* context)> callback;
    void* parentContext;
public:
    TickDataRequestStrategy(std::string token, std::string strategy_id, int mode, void* context, std::function<void(Tick* tick, void *context)> callback);
    void subscribeSymbol(std::string symbol, std::string underlyingSymbol);
    // åˆå§‹åŒ–函数
    virtual void on_init();
    //收到Tick行情
    virtual void on_tick(Tick* tick);
    virtual void on_market_data_connected();
    virtual void on_market_data_disconnected();
    virtual void on_backtest_finished(Indicator* indicator);
};
CBTrade/TickDataUtil.h
New file
@@ -0,0 +1,95 @@
#pragma once
#include <wx\string.h>
using namespace std;
/// <summary>
/// åˆ†æ—¶æ•°æ®å¸®åŠ©ç±»
/// </summary>
class TickDataUtil {
public :
    /// <summary>
    /// å°†æ—¶é—´è½¬ä¸ºS,作为x的横坐标
    /// </summary>
    /// <param name="time_str"></param>
    /// <param name="xStartTimeAsSeconds"></param>
    /// <returns></returns>
    static int timeStrToSecondsAsAxisX(wxString time_str,int xStartTimeAsSeconds) {
        int seconds = timeStrToSeconds(time_str);
        if (seconds > 41400&& xStartTimeAsSeconds<= 41400) { //大于11:30
            seconds -= 5400;
        }
        return seconds - xStartTimeAsSeconds;
    }
    /// <summary>
    /// timeStrToSecondsAsAxisX的逆变换
    /// </summary>
    /// <param name="x"></param>
    /// <param name="xStartTimeAsSeconds"></param>
    /// <returns></returns>
    static wxString axisXSecondsToTimeStr(int x, int xStartTimeAsSeconds,bool with_s = TRUE) {
        int seconds = x + xStartTimeAsSeconds;
        if (seconds > 41400&& xStartTimeAsSeconds <= 41400) {
            seconds += 5400;
        }
        return secondToTimeStr(seconds, with_s);
    }
    static int tradTimeSub(wxString time_str1, wxString time_str2) {
        return timeStrToSecondsAsAxisX(time_str1, 0) - timeStrToSecondsAsAxisX(time_str2, 0);
    }
    /// <summary>
    /// æˆäº¤æ—¶é—´åŠ ç§’
    /// </summary>
    /// <param name="time_str"></param>
    /// <param name="add_seconds"></param>
    /// <returns></returns>
    static wxString tradTimeAdd(wxString time_str, int add_seconds) {
        int seconds = timeStrToSeconds(time_str);
        if (seconds < 41400 && (seconds + add_seconds > 41400)) {
             seconds += add_seconds + 5400;
        }
        else {
            seconds += add_seconds;
        }
        return secondToTimeStr(seconds, true);
    }
    /// <summary>
    /// æ—¶é—´è½¬ä¸ºs
    /// </summary>
    /// <param name="time_str"></param>
    /// <returns></returns>
    static int timeStrToSeconds(wxString time_str) {
        std::string time_s = time_str.ToStdString();
        int h = stoi(time_s.substr(0, 2).c_str());
        int m = stoi(time_s.substr(3, 2));
        int s = stoi(time_s.substr(6, 2));
        int seconds = h * 3600 + m * 60 + s;
        return seconds;
    }
    static wxString secondToTimeStr(int seconds,bool with_s = FALSE) {
        int hour = seconds / 3600;
        int m = seconds % 3600 / 60;
        int s = seconds % 60;
        wxString timeStr = "";
        if (hour < 10)
            timeStr.Append("0");
        timeStr.Append(to_string(hour)).Append(":");
        if (m < 10)
            timeStr.Append("0");
        timeStr.Append(to_string(m));
        if (with_s) {
            timeStr.Append(":");
            if (s < 10)
                timeStr.Append("0");
            timeStr.Append(to_string(s));
        }
        return timeStr;
    }
};
CBTrade/TickFrame.cpp
New file
@@ -0,0 +1,54 @@
#include "TickFrame.h"
#include "MyConfigUtil.h"
TickFrame::TickFrame(wxWindow* parent,const wxString& title, wxString code, wxString codeName, float preClosePrice, wxString xStartTime, wxString xEndTime, std::list<TickTradeData> buyPoints, std::list<TickTradeData> sellPoints, float costRate, wxPoint position, wxSize size):wxFrame(parent,wxID_ANY,title,position,size) {
    wxIcon icon;
    icon.LoadFile("logo.ico", wxBITMAP_TYPE_ICO); // æ›¿æ¢ "app_icon.ico" ä¸ºä½ çš„应用程序图标文件路径
    SetIcon(icon);
    //SetTransparent(225);
    SetWindowStyleFlag(GetWindowStyleFlag() | wxSTAY_ON_TOP);
    WindowPosSize rect = MyConfigUtil::getTickWindowPos();
    if (rect.x == -1 && rect.y == -1) {
    }
    else {
        wxPoint    p = wxPoint(rect.x, rect.y);
        cout << "设置的坐标:" << p.x << "  " << p.y << endl;
        wxSize    s = wxSize(rect.width, rect.height);
        SetPosition(p);
        SetSize(s);
    }
    Bind(wxEVT_CLOSE_WINDOW, &TickFrame::OnClose, this);
    wxBoxSizer* sizer = new wxBoxSizer(wxHORIZONTAL);
    TickChart *tickChart=new TickChart(this, wxID_ANY, 3, TIME_SPACE_TICK , xStartTime, xEndTime);
    if (code.find("11") == 0 || code.find("12") == 0)
    {
        tickChart->Init(CodeBasicInfo({ code,codeName, preClosePrice }), CodeBasicInfo(), nullptr, NULL);
    }
    else {
        tickChart->Init(CodeBasicInfo(), CodeBasicInfo({ code,codeName, preClosePrice }), nullptr, NULL);
    }
    if (buyPoints.size() > 0) {
        for (std::list<TickTradeData>::iterator e = buyPoints.begin(); e != buyPoints.end(); e++) {
            tickChart->AddBuyPoint(*e);
        }
    }
    if (sellPoints.size() > 0) {
        for (std::list<TickTradeData>::iterator e = sellPoints.begin(); e != sellPoints.end(); e++) {
            tickChart->AddSellPoint(*e);
        }
    }
    sizer->Add(tickChart, 1, wxEXPAND);
    SetSizer(sizer);
}
void TickFrame::OnClose(wxCloseEvent& event) {
    MyConfigUtil::setTickWindowPos(GetPosition(), GetSize());
    event.Skip();
}
CBTrade/TickFrame.h
New file
@@ -0,0 +1,13 @@
#pragma once
#include "TickChart.h"
class TickFrame :public wxFrame
{
private:
    void OnClose(wxCloseEvent& event);
public:
    TickFrame(wxWindow* parent,const wxString& title, wxString code,wxString codeName, float preClosePrice, wxString xStartTime, wxString xEndTime, std::list<TickTradeData> buyPoints, std::list<TickTradeData> sellPoints, float costRate, wxPoint position = wxDefaultPosition, wxSize size=wxDefaultSize);
};
CBTrade/ViewManager.cpp
@@ -1,7 +1,14 @@
#include "ViewManager.h"
#include <wx/charts/wxcharts.h>
#include <gmapi.h>
#include <set>
#include "MyNetworkApi.h"
#include "JueJInSettingFrame.h"
#include "../common_nopch/Win32Util.h"
#include <thread>
#include "MyConfigUtil.h"
IMPLEMENT_VARIANT_OBJECT(MyColorText)
IMPLEMENT_VARIANT_OBJECT(MyButton)
ViewManager::ViewManager() {
    this->topWidgets = new TopWidgets();
@@ -9,7 +16,6 @@
    this->moneyWidgets = new MoneyWidgets();
    this->positionWidgets = new PositionWidgets();
    this->sellWidgets = new SellWidgets();
    set_token("123123");
}
wxPanel* ViewManager::createSplitLine(wxWindow* parent)
@@ -24,40 +30,72 @@
    window->SetBackgroundColour(wxColor(255, 255, 255));
    wxBoxSizer* sizer = new wxBoxSizer(wxVERTICAL);
    wxPanel* topPanel = new wxPanel(window, wxID_ANY, wxDefaultPosition, wxSize(MAIN_WINDOW_WIDTH, PANNEL_TOP_HEIGHT));
    wxSize size = window->GetSize();
    cout << "size:"<< size.GetWidth() << endl;
    wxPanel* tickPanel = new wxPanel(window, wxID_ANY, wxDefaultPosition, wxSize(MAIN_WINDOW_WIDTH, PANNEL_TICK_HEIGHT));
    wxPanel* topPanel = new wxPanel(window, wxID_ANY, wxDefaultPosition, wxSize(-1, PANNEL_TOP_HEIGHT));
    wxPanel* moneyPanel = new wxPanel(window, wxID_ANY, wxDefaultPosition, wxSize(MAIN_WINDOW_WIDTH, PANNEL_MONEY_HEIGHT));
    wxPanel* tickPanel = new wxPanel(window, wxID_ANY, wxDefaultPosition, wxSize(-1,size.GetWidth()<100? PANNEL_TICK_HEIGHT: size.GetWidth()*2/3));
    wxPanel* positionPanel = new wxPanel(window, wxID_ANY, wxDefaultPosition, wxSize(MAIN_WINDOW_WIDTH, PANNEL_POSITION_HEIGHT));
    wxPanel* moneyPanel = new wxPanel(window, wxID_ANY, wxDefaultPosition, wxSize(-1, PANNEL_MONEY_HEIGHT));
    wxPanel* sellPanel = new wxPanel(window, wxID_ANY, wxDefaultPosition, wxSize(MAIN_WINDOW_WIDTH, PANNEL_SELL_HEIGHT));
    wxPanel* positionPanel = new wxPanel(window, wxID_ANY, wxDefaultPosition, wxSize(-1, -1));
    sizer->Add(topPanel, 0, wxLEFT | wxRIGHT, 2);
    wxPanel* sellPanel = new wxPanel(window, wxID_ANY, wxDefaultPosition, wxSize(-1, PANNEL_SELL_HEIGHT));
    initMenu((wxFrame*)window);
    sizer->Add(topPanel, 0, wxEXPAND|wxLEFT | wxRIGHT, 2);
    sizer->Add(createSplitLine(window), 0, wxEXPAND);
    sizer->Add(tickPanel, 0, wxLEFT | wxRIGHT, 2);
    sizer->Add(tickPanel, 0, wxEXPAND|wxLEFT | wxRIGHT, 2);
    sizer->Add(createSplitLine(window), 0, wxEXPAND);
    sizer->Add(moneyPanel, 0, wxLEFT | wxRIGHT, 2);
    sizer->Add(moneyPanel, 0, wxEXPAND|wxLEFT | wxRIGHT, 2);
    sizer->Add(createSplitLine(window), 0, wxEXPAND);
    sizer->Add(positionPanel, 0, wxLEFT | wxRIGHT, 2);
    sizer->Add(positionPanel, 1, wxEXPAND |wxLEFT | wxRIGHT, 2);
    sizer->Add(createSplitLine(window), 0, wxEXPAND);
    sizer->Add(sellPanel, 0, wxLEFT | wxRIGHT, 2);
    sizer->Add(sellPanel, 0, wxEXPAND|wxLEFT | wxRIGHT, 2);
    sizer->Add(createSplitLine(window), 0, wxEXPAND);
    window->SetSizer(sizer);
    this->initTopView(topPanel);
    this->initTickView(tickPanel);
    this->initMoneyView(moneyPanel);
    this->initPositionView(positionPanel);
    this->initSellView(sellPanel);
}
void ViewManager::ShowJueJinSetting(wxCommandEvent& event)
{
    JueJInSettingFrame *jueJinFrame = new JueJInSettingFrame("掘金参数设置");
    jueJinFrame->ShowModal();
}
void ViewManager::initMenu(wxFrame* window)
{
    // åˆå§‹åŒ–菜单
    menuBar = new wxMenuBar();
    // åˆ›å»ºæ–‡ä»¶èœå•
    wxMenu* menuSetting = new wxMenu();
    menuSetting->Append(10012, "&掘金参数设置");
    menuSetting->AppendSeparator();
    // å°†æ–‡ä»¶èœå•添加到菜单栏
    menuBar->Append(menuSetting, "&设置");
    // å°†èœå•栏设置为窗口的菜单栏
    window->SetMenuBar(menuBar);
    window->Bind(wxEVT_MENU, &ViewManager::ShowJueJinSetting, this, 10012);
}
void ViewManager::initTopView(wxPanel* pancel)
{
@@ -65,10 +103,19 @@
    this->topWidgets->refreshBtn = new wxButton(pancel, wxID_ANY, "刷新", wxDefaultPosition, wxSize(50, -1));
    this->topWidgets->msgLabel = new wxStaticText(pancel, wxID_ANY, "提示语提示语", wxDefaultPosition);
    this->topWidgets->codeEdit = new wxTextCtrl(pancel, wxID_ANY, "000333", wxDefaultPosition, wxSize(60, 25));
    this->topWidgets->codeEdit = new wxTextCtrl(pancel, wxID_ANY, "", wxDefaultPosition, wxSize(-1, 25));
    this->topWidgets->backTestDate = new wxTextCtrl(pancel, wxID_ANY);
    this->topWidgets->btnBackTest = new wxButton(pancel, wxID_ANY, "开始回测");
    // ç»‘定事件
    this->topWidgets->refreshBtn->Bind(wxEVT_BUTTON, &ViewManager::OnRefresh, this);
    sizer->Add(this->topWidgets->codeEdit, 0, wxALL, 2);
    sizer->Add(this->topWidgets->btnAddZX, 0, wxALL, 2);
    sizer->Add(this->topWidgets->msgLabel, 1, wxALIGN_CENTER_VERTICAL);
    sizer->Add(topWidgets->backTestDate, 0, wxALIGN_CENTER_VERTICAL);
    sizer->Add(topWidgets->btnBackTest, 0, wxLEFT| wxALIGN_CENTER_VERTICAL, 2);
    sizer->Add(this->topWidgets->refreshBtn, 0, wxALL, 2);
    pancel->SetSizer(sizer);
}
@@ -78,8 +125,6 @@
{
public:
    wxChartsPresentationDatasetTheme10() {
        SetLineChartDatasetOptions(wxLineChartDatasetOptions(
            wxColor(220, 0, 0),
            wxColor(255, 255, 255),
@@ -92,51 +137,19 @@
void ViewManager::initTickView(wxPanel* panel)
{
    wxString st = "";
    tickWidgets->tickChart = new TickChart(panel, wxID_ANY,60,TIME_SPACE_BAR,"09:25:00","15:00:00");
    tickWidgets->codeInfoLabel = new wxRichTextCtrl(panel, wxID_ANY, st, wxDefaultPosition,wxSize(-1,90), wxTE_MULTILINE| wxTE_READONLY| wxBORDER_NONE);
    wxFont font = tickWidgets->codeInfoLabel->GetFont();
    font.SetPointSize(10);
    tickWidgets->codeInfoLabel->SetFont(font);
    if (1 > 0) {
        return;
    }
    wxBoxSizer* panelSizer = new wxBoxSizer(wxVERTICAL);
    wxBoxSizer *sizer = new wxBoxSizer(wxHORIZONTAL);
    sizer->Add(tickWidgets->codeInfoLabel,1, wxEXPAND);
    // è®¾ç½®ä¸»é¢˜
    wxChartsDefaultTheme->SetDatasetTheme(wxChartsDatasetId::CreateImplicitId(0), wxSharedPtr<wxChartsDatasetTheme>(new wxChartsPresentationDatasetTheme10()));
    wxVector<wxString> labels;
    labels.push_back("January");
    labels.push_back("February");
    labels.push_back("March");
    labels.push_back("April");
    labels.push_back("May");
    labels.push_back("June");
    labels.push_back("July");
    wxChartsCategoricalData::ptr chartData = wxChartsCategoricalData::make_shared(labels);
    // Add the first dataset
    wxVector<wxDouble> points1;
    points1.push_back(3);
    points1.push_back(-2.5);
    points1.push_back(-1.2);
    points1.push_back(3);
    points1.push_back(6);
    points1.push_back(5);
    points1.push_back(1);
    wxChartsDoubleDataset::ptr dataset1(new wxChartsDoubleDataset("id0", points1));
    chartData->AddDataset(dataset1);
    // Create the line chart widget from the constructed data
    const wxLineChartOptions *options = new wxLineChartOptions();
    wxLineChartCtrl* lineChartCtrl = new wxLineChartCtrl(panel, wxID_ANY, chartData,
        wxCHARTSLINETYPE_STRAIGHT, *options, wxDefaultPosition, wxDefaultSize, wxBORDER_NONE);
    lineChartCtrl->SetBackgroundColour(*wxBLACK);
    wxBoxSizer* panelSizer = new wxBoxSizer(wxHORIZONTAL);
    panelSizer->Add(lineChartCtrl, 1, wxEXPAND);
    //panelSizer->Add(legendCtrl, 1, wxEXPAND);
    panelSizer->Add(sizer, 0, wxEXPAND, 2);
    panelSizer->Add(tickWidgets->tickChart, 1, wxEXPAND);
    panel->SetSizer(panelSizer);
}
void ViewManager::initMoneyView(wxPanel* panel)
@@ -208,8 +221,11 @@
class ButtonRenderer : public wxDataViewCustomRenderer
{
private:
    MyButton info;
public:
    ButtonRenderer(const wxString& varianttype = "string")
    ButtonRenderer(const wxString& varianttype = "wxObject")
        : wxDataViewCustomRenderer(varianttype, wxDATAVIEW_CELL_ACTIVATABLE)
    {
@@ -219,17 +235,13 @@
    {
        // è®¾ç½®ç»˜åˆ¶æŒ‰é’®çš„位置和大小
        wxRect buttonRect(cell.GetPosition(), wxSize(40, 20));
        dc->SetTextForeground(wxColour(64, 64, 64));
        dc->SetTextForeground(info.getTextColor());
        // ç»˜åˆ¶æŒ‰é’®çš„外框
        dc->SetPen(wxColour(225, 225, 225));
        dc->SetBrush(wxColour(225, 225, 225));
        dc->SetPen(info.getBgColor());
        dc->SetBrush(info.getBgColor());
        dc->DrawRectangle(buttonRect);
        // ç»˜åˆ¶æŒ‰é’®çš„æ–‡æœ¬
        dc->DrawLabel("查看", buttonRect, wxALIGN_CENTER);
        dc->DrawLabel(info.getText(), buttonRect, wxALIGN_CENTER);
        return false;
    }
@@ -237,7 +249,13 @@
    bool ActivateCell(const wxRect& WXUNUSED(cell), wxDataViewModel* WXUNUSED(model), const wxDataViewItem& WXUNUSED(item), unsigned int WXUNUSED(col), const wxMouseEvent* mouseEvent) override {
        // å¤„理点击事件
        if (mouseEvent->LeftDown()) {
            wxMessageBox("单元格被点击");
            try {
                thread t(Win32Util::addToTHS, info.getCode().ToStdString());
                t.detach();
            }
            catch (...) {
            }
        }
        return false; // è¿”回 true è¡¨ç¤ºå·²ç»å¤„理了点击事件
    }
@@ -249,7 +267,7 @@
    }
    virtual bool SetValue(const wxVariant& value) {
        info << value;
        return true;
    }
    virtual bool GetValue(wxVariant& value) const {
@@ -258,48 +276,113 @@
    }
};
class ColorTextRenderer : public wxDataViewCustomRenderer
{
private:
    MyColorText  colorText;
public:
    ColorTextRenderer(const wxString& varianttype = wxS("wxObject"))
        : wxDataViewCustomRenderer(varianttype, wxDATAVIEW_CELL_ACTIVATABLE)
    {
    }
    virtual bool Render(wxRect cell, wxDC* dc, int state)
    {
        dc->SetTextForeground(colorText.getColor());
        // ç»˜åˆ¶æŒ‰é’®çš„外框
        dc->SetPen(wxColour(225, 225, 225));
        dc->SetBrush(wxColour(225, 225, 225));
        // ç»˜åˆ¶æŒ‰é’®çš„æ–‡æœ¬
        dc->DrawLabel(colorText.getText(), cell, wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL);
        return false;
    }
    virtual wxSize GetSize() const
    {
        // è¿”回按钮的大小
        return wxSize(-1, -1);
    }
    virtual bool SetValue(const wxVariant& value)  wxOVERRIDE {
        cout << value.GetType() << endl;
        //colorText = (ColorText) value.GetType();
        colorText << value;
        return true;
    }
    virtual bool GetValue(wxVariant& value) const wxOVERRIDE {
        return true;
    }
    wxString GetAccessibleDescription() const wxOVERRIDE
    {
        return wxEmptyString;
    }
};
void ViewManager::initPositionView(wxPanel* panel)
{
    wxDataViewListCtrl* listCtrl = new wxDataViewListCtrl(
        panel, wxID_ANY, wxDefaultPosition, wxSize(-1, -1),
        wxLC_REPORT | wxBORDER_NONE);
    // è®¾ç½®æ•´ä½“的字体大小
    wxFont font  = listCtrl->GetFont();
    font.SetPointSize(10);
    listCtrl->SetFont(font);
    listCtrl->Bind(wxEVT_DATAVIEW_SELECTION_CHANGED, &ViewManager::OnPositionSelectionChanged, this);
    const int COL_COUNT = 10;
    std::string headers[COL_COUNT] = { "名称","涨幅","现价","L1现手","剩余持仓","持仓金额","盈亏","盈亏比","正股名称","更多" };
    int colWidths[COL_COUNT] = { 70,50 ,60 ,50 ,70 ,100 ,90 ,50 ,80 ,50 };
    const int COL_COUNT = 13;
    std::string headers[COL_COUNT] = { "名称","涨幅","现价","现手","正股涨幅","正股买一","持仓金额","成本价","盈亏比","更多","持仓","盈亏","正股名称" };
    list<int> widths= MyConfigUtil::getPositionColumnWidth();
    for (int i = 0; i < COL_COUNT; i++) {
        if (i < COL_COUNT - 1) {
            listCtrl->AppendTextColumn(headers[i], wxDATAVIEW_CELL_INERT, colWidths[i]);
        int width = -1;
        if (widths.size() > i) {
            list<int>::iterator e =    widths.begin();
            std::advance(e,i);
            width = *e;
        }
        cout << "持仓列宽度:" << i << "-" << width << endl;
        if (i != 9) {
            auto ctr = new ColorTextRenderer();
            listCtrl->AppendColumn(new wxDataViewColumn(headers[i], ctr, i, width < 0 ? 50 : width, i == 0 ? wxALIGN_LEFT : wxALIGN_RIGHT, wxDATAVIEW_COL_RESIZABLE));
        }
        else {
            auto bc = new ButtonRenderer();
            listCtrl->AppendColumn(new wxDataViewColumn(headers[i], bc, 9, colWidths[i], wxALIGN_LEFT, wxDATAVIEW_COL_RESIZABLE));
            listCtrl->AppendColumn(new wxDataViewColumn(headers[i], bc,i, width < 0? 50:width, i == 0 ? wxALIGN_LEFT : wxALIGN_RIGHT, wxDATAVIEW_COL_RESIZABLE));
        }
    }
    for (int i = 0; i < 5; i++) {
    for (int i = 0; i < 1; i++) {
        wxVector<wxVariant> data;
        data.push_back(wxVariant("美的转债"));
        data.push_back(wxVariant("10.2%"));
        data.push_back(wxVariant("10.20%"));
        data.push_back(wxVariant("123.123"));
        data.push_back(wxVariant("452"));
        data.push_back(wxVariant("30"));
        data.push_back(wxVariant("2000.00Ôª"));
        data.push_back(wxVariant("+20000.10Ôª"));
        data.push_back(wxVariant("10.02%"));
        data.push_back(wxVariant("12312万"));
        data.push_back(wxVariant("100000.00"));
        data.push_back(wxVariant("123.123"));
        data.push_back(wxVariant("1.01%"));
        data.push_back(wxVariant("美的集团"));
        data.push_back("");
        data.push_back(wxVariant("1000"));
        data.push_back(wxVariant("+20000.10"));
        listCtrl->AppendItem(data);
    }
    listCtrl->Refresh();
    positionWidgets->listCtrlReport = listCtrl;
    wxBoxSizer* sizer = new wxBoxSizer(wxVERTICAL);
@@ -314,13 +397,13 @@
    const int COLUMN_SPACE = 8;
    auto btnSizer = new wxBoxSizer(wxHORIZONTAL);
    wxPanel* btnPannel = new wxPanel(panel, wxID_ANY, wxDefaultPosition, wxSize(-1, 55));
    wxPanel* btnPannel = new wxPanel(panel, wxID_ANY, wxDefaultPosition, wxSize(-1, 70));
    btnPannel->SetSizer(btnSizer);
    sellWidgets->buyLock = new wxCheckBox(btnPannel, wxID_ANY, "买锁定");
    sellWidgets->buyMoney = new wxTextCtrl(btnPannel, wxID_ANY, "", wxDefaultPosition, wxSize(60, -1));
    sellWidgets->buyMoney = new wxTextCtrl(btnPannel, wxID_ANY, "", wxDefaultPosition, wxSize(90, -1), wxTE_PROCESS_ENTER);
    sellWidgets->sellLock = new wxCheckBox(btnPannel, wxID_ANY, "卖锁定");
    sellWidgets->sellMoney = new wxTextCtrl(btnPannel, wxID_ANY, "", wxDefaultPosition, wxSize(60, -1));
    sellWidgets->sellMoney = new wxTextCtrl(btnPannel, wxID_ANY, "", wxDefaultPosition, wxSize(90, -1), wxTE_PROCESS_ENTER);
    auto bv = new wxBoxSizer(wxVERTICAL);
    bv->Add(sellWidgets->buyLock, 0, wxTOP, 5);
    bv->AddStretchSpacer();
@@ -336,8 +419,8 @@
    // å¼€å¯/关闭交易
    sellWidgets->openTrade = new wxButton(btnPannel, wxID_ANY, "开启交易", wxDefaultPosition, wxSize(60, -1));
    sellWidgets->closeTrade = new wxButton(btnPannel, wxID_ANY, "关闭交易", wxDefaultPosition, wxSize(60, -1));
    sellWidgets->openTrade = new wxButton(btnPannel, wxID_ANY, "开启交易", wxDefaultPosition, wxSize(80, -1));
    sellWidgets->closeTrade = new wxButton(btnPannel, wxID_ANY, "关闭交易", wxDefaultPosition, wxSize(80, -1));
    bv = new wxBoxSizer(wxVERTICAL);
    bv->Add(sellWidgets->openTrade, 0);
    bv->AddStretchSpacer();
@@ -364,23 +447,23 @@
    // è‡ªåŠ¨æ’¤å•/参数设置
    sellWidgets->autoCancel = new wxCheckBox(btnPannel, wxID_ANY, "自动撤单");
    sellWidgets->setting = new wxButton(btnPannel, wxID_ANY, "参数设置", wxDefaultPosition, wxSize(70, -1));
    sellWidgets->setting = new wxButton(btnPannel, wxID_ANY, "参数设置", wxDefaultPosition, wxSize(80, -1));
    bv = new wxBoxSizer(wxVERTICAL);
    bv->Add(sellWidgets->autoCancel, 0);
    bv->AddStretchSpacer();
    bv->Add(sellWidgets->setting, 0);
    btnSizer->Add(bv, 0, wxEXPAND | wxLEFT, COLUMN_SPACE);
    // ä¹°ä»·/卖价设置
    // ä¹°ä»·/卖价设置  0-价格笼子 1-跌停价  2-涨停价 3-现价 4-ä¹°5ä»·
    const wxString prices_buy[] = { "笼子价", "跌停价","涨停价","现价","ä¹°5ä»·" };
    const wxString prices_sell[] = { "笼子价", "跌停价","涨停价","现价","卖5ä»·" };
    sellWidgets->sellPrice = new wxChoice(btnPannel, wxID_ANY, wxDefaultPosition, wxSize(70, -1));
    sellWidgets->buyPrice = new wxChoice(btnPannel, wxID_ANY, wxDefaultPosition, wxSize(70, -1));
    sellWidgets->sellPrice = new wxChoice(btnPannel, wxID_ANY, wxDefaultPosition, wxSize(90, -1));
    sellWidgets->buyPrice = new wxChoice(btnPannel, wxID_ANY, wxDefaultPosition, wxSize(90, -1));
    for (int i = 0; i < 5; i++) {
        sellWidgets->sellPrice->Append(prices_sell[i]);
        sellWidgets->buyPrice->Append(prices_buy[i]);
    }
    sellWidgets->sellPrice->SetSelection(1);
    sellWidgets->sellPrice->SetSelection(0);
    sellWidgets->buyPrice->SetSelection(2);
    bv = new wxBoxSizer(wxVERTICAL);
@@ -396,9 +479,15 @@
    btnSizer->Add(bv, 0, wxEXPAND | wxLEFT, COLUMN_SPACE);
    sellWidgets->showAllPosition = new wxCheckBox(btnPannel, wxID_ANY, "显示无持仓");
    sellWidgets->showAllPosition->SetValue(TRUE);
    btnSizer->Add(sellWidgets->showAllPosition, 0,  wxLEFT, COLUMN_SPACE);
    // ä¹°å…¥
    btnSizer->AddStretchSpacer();
    sellWidgets->buyBtn = new wxButton(btnPannel, wxID_ANY, "买入", wxDefaultPosition, wxSize(50, -1));
    sellWidgets->buyBtn = new wxButton(btnPannel, wxID_ANY, "买入", wxDefaultPosition, wxSize(80, -1));
    sellWidgets->buyBtn->SetFont(font);
    btnSizer->Add(sellWidgets->buyBtn, 0, wxEXPAND | wxLEFT, COLUMN_SPACE);
@@ -407,7 +496,7 @@
    //------- å–金额区域
    const int sellNumCount = sizeof(moneys) / sizeof(moneys[0]);
    for (int i = 0; i < sellNumCount; i++) {
        sellWidgets->sellNums.push_back(new wxButton(panel, wxID_ANY, std::to_string(moneys[i]), wxDefaultPosition, wxSize(-1, 30)));
        sellWidgets->sellNums.push_back(new wxButton(panel, wxID_ANY, std::to_string(moneys[i]), wxDefaultPosition, wxSize(-1, 50)));
    }
    auto sellNumsSizer = new wxBoxSizer(wxHORIZONTAL);
@@ -421,8 +510,10 @@
    panel->SetSizer(rootSizer);
}
void ViewManager::OnPositionSelectionChanged(wxDataViewEvent& event)
void ViewManager::OnRefresh(wxCommandEvent& event)
{
    event.Skip();
    //event.Veto();
    MyNetworkApi::get_all_positions();
}
CBTrade/ViewManager.h
@@ -3,25 +3,151 @@
#include <wx/listctrl.h>
#include <wx/dataview.h>
#include <list>
#define MAIN_WINDOW_WIDTH 720
#define PANNEL_TOP_HEIGHT 30
#define PANNEL_TICK_HEIGHT 360
#define PANNEL_MONEY_HEIGHT 60
#define PANNEL_POSITION_HEIGHT 310
#define PANNEL_SELL_HEIGHT 90
#define MAIN_WINDOW_HEIGHT (PANNEL_TOP_HEIGHT + PANNEL_TICK_HEIGHT + PANNEL_MONEY_HEIGHT + PANNEL_POSITION_HEIGHT + PANNEL_SELL_HEIGHT + 38 + 5*2)
#include "TickChart.h"
#include <wx/richtext/richtextctrl.h>
#define DPI 1
#define MAIN_WINDOW_WIDTH (int)(720*DPI)
#define PANNEL_TOP_HEIGHT (int)(30*DPI)
#define PANNEL_TICK_HEIGHT (int)(500*DPI)
#define PANNEL_MONEY_HEIGHT (int)(60*DPI)
#define PANNEL_POSITION_HEIGHT (int)(310*DPI)
#define PANNEL_SELL_HEIGHT (int)(120*DPI)
#define MAIN_WINDOW_HEIGHT (PANNEL_TOP_HEIGHT + PANNEL_TICK_HEIGHT + PANNEL_MONEY_HEIGHT + PANNEL_POSITION_HEIGHT + PANNEL_SELL_HEIGHT + (int)((38 + 5*2 + 20) * DPI) ) // 20为菜单高度
class  MyColorText : public wxObject {
public:
    MyColorText(){
    }
    MyColorText(wxString text, wxColor color):m_text(text), m_color(color){
    }
    void setText(wxString text) {
        m_text = text;
    }
    void setColor(wxColor color) {
        m_color = color;
    }
    wxString getText() {
        return m_text;
    }
    wxColor getColor() {
        return m_color;
    }
    bool IsSameAs(const MyColorText& other) const
    {
        return m_text == other.m_text && m_color.IsSameAs(other.m_color);
    }
    bool operator==(const MyColorText& other) const
    {
        return IsSameAs(other);
    }
    bool operator!=(const MyColorText& other) const
    {
        return !IsSameAs(other);
    }
private:
    wxString m_text;
    wxColor m_color;
};
DECLARE_VARIANT_OBJECT(MyColorText)
class  MyButton : public wxObject {
public:
    MyButton() {
    }
    MyButton(wxString code, wxString text, wxColor textColor, wxColor bgColor) :m_code(code),m_text(text), m_text_color(textColor), m_bg_color(bgColor) {
    }
    void setCode(wxString code) {
        m_code = code;
    }
    void setText(wxString text) {
        m_text = text;
    }
    void setBgColor(wxColor color) {
        m_bg_color = color;
    }
    void setTextColor(wxColor color) {
        m_text_color = color;
    }
    wxString getText() {
        return m_text;
    }
    wxColor getBgColor() {
        return m_bg_color;
    }
    wxColor getTextColor() {
        return m_text_color;
    }
    wxString getCode() {
        return m_code;
    }
    bool IsSameAs(const MyButton& other) const
    {
        return m_text == other.m_text && m_bg_color.IsSameAs(other.m_bg_color) && m_text_color.IsSameAs(other.m_text_color);
    }
    bool operator==(const MyButton& other) const
    {
        return IsSameAs(other);
    }
    bool operator!=(const MyButton& other) const
    {
        return !IsSameAs(other);
    }
private:
    wxString m_code;
    wxString m_text;
    wxColor m_text_color;
    wxColor m_bg_color;
};
DECLARE_VARIANT_OBJECT(MyButton)
struct TopWidgets
{
    wxButton* refreshBtn;
    wxTextCtrl* codeEdit;
    wxStaticText* msgLabel;
    wxTextCtrl* backTestDate;// å›žæµ‹æ—¥æœŸ
    wxButton* btnBackTest;//回测按钮
    wxButton* btnAddZX;// åŠ è‡ªé€‰
};
struct TickWidgets
{
    TickChart* tickChart;
    wxRichTextCtrl* codeInfoLabel;// ä»£ç ä¿¡æ¯
};
struct MoneyWidgets
@@ -64,6 +190,8 @@
    wxButton* sellBtn;
    wxButton* buyBtn;
    wxCheckBox* showAllPosition;
    std::list<wxButton*> sellNums;
};
@@ -71,7 +199,8 @@
class ViewManager
{
private:
public:
        wxMenuBar* menuBar;
        TopWidgets* topWidgets;
        TickWidgets* tickWidgets;
        MoneyWidgets* moneyWidgets;
@@ -81,16 +210,23 @@
    ViewManager();
    static wxPanel* createSplitLine(wxWindow* parent);
    void initView(wxWindow* window);
private:
    /// <summary>
    /// æ˜¾ç¤ºæŽ˜é‡‘参数设置
    /// </summary>
    /// <param name="event"></param>
    void ShowJueJinSetting(wxCommandEvent& event);
private:
    void initMenu(wxFrame* window);
    void initTopView(wxPanel* pancel);
    void initTickView(wxPanel* panel);
    void initMoneyView(wxPanel* panel);
    void initPositionView(wxPanel* panel);
    void initSellView(wxPanel* panel);
    void OnPositionSelectionChanged(wxDataViewEvent& event);
    void OnRefresh(wxCommandEvent& event);
CBTrade/config.cfg
New file
@@ -0,0 +1,6 @@
juejin_params = "[\n    \"77fa387b37e9bc1586ae1135827e2ccb3e7cd4e4\",\n    \"95a982ce-fc2d-11ec-8ff3-0a0027000010\"\n]";
buy_money = 2000;
sell_money = 60000;
main_window_info = "[\n    -1292,\n    25,\n    963,\n    1037\n]";
tick_window_info = "[\n    -932,\n    366,\n    555,\n    428\n]";
position_view_column_width = "80,71,74,52,88,92,80,127,78,80,69,181,225";
CBTrade/gmcache/cedb649398358db74e367c6655061303
Binary files differ
CBTrade/gmcache/cedb649398358db74e367c6655061303.inf
New file
@@ -0,0 +1,6 @@
start_datatime = 2024-05-27 09:25:00
end_datatime = 2024-05-27 11:00:00
adjust = 0
[tick] = SZSE.127101
[172590s] = SHSE.000000
CBTrade/logo.ico
CBTrade/main.cpp
@@ -4,6 +4,8 @@
#include "MainFrame.h"
#include "MyConfigUtil.h"
class App :public wxApp {
@@ -14,14 +16,38 @@
    /// åˆå§‹åŒ–函数
    /// </summary>
    void InitData() {
        MyNetworkApi::set_server_info("43.138.167.68", 13008,"43.138.167.68", 13008);
        //MyNetworkApi::set_server_info("192.168.3.122", 13008, "192.168.3.122", 13008);
        MyNetworkApi::get_all_positions();
    }
    static void unhandled_exception_handler() {
        try {
            throw;  // Re-throw the exception to handle it
        }
        catch (const std::exception& e) {
            std::cerr << "Caught std::exception: " << e.what() << std::endl;
        }
        catch (...) {
            std::cerr << "Caught unknown exception" << std::endl;
        }
        std::abort();  // Terminate the program
    }
    bool OnInit() {
        std::set_terminate(unhandled_exception_handler);
        InitData();
        MainFrame* window = new MainFrame("可转债交易");
        SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2);
        MainFrame* window;
        WindowPosSize rect = MyConfigUtil::getMainWindowPos();
        cout << "获取到的坐标:" << rect.x << "  " << rect.y << endl;
        if (rect.x == -1 && rect.y == -1) {
            window = new MainFrame("可转债交易");
        }
        else {
            wxPoint    p = wxPoint(rect.x, rect.y);
            cout << "设置的坐标:" << p.x << "  " << p.y << endl;
            wxSize    s = wxSize(rect.width, rect.height);
            window = new MainFrame("可转债交易",p,s);
        }
        window->Show();
        return true;
    }
DelegateQueue/DataStruct.h
@@ -19,6 +19,7 @@
    wxString id;
    wxString code;
    wxString codeName;
    wxString buy1_money;
    int big_num_count;
    wxString big_num_money;
@@ -34,5 +35,7 @@
    float limit_up_price;//涨停价
    bool is_near_big_order; // æ˜¯å¦é è¿‘大单
    wxString block;// æ¿å—
    wxString limit_up_time; //
    std::list<TradeQueue> tradeQueueList;
    wxString zyltgb;
};
DelegateQueue/MainFrame.cpp
@@ -31,6 +31,10 @@
    CLICK_TYPE_QUEUE,
};
struct ViewDetailData {
    string code;
};
// å§”托信息数据
class DelegateInfoRenderer : public wxDataViewCustomRenderer
@@ -44,7 +48,7 @@
    map<wxString, wxRect> cancelBtnRectMap;
    map<wxString, wxRect> queueRectMap;
    map<wxString, wxRect> gridPostionMap;
public:
    /*static void addDelegateInfo(DelegateInfo info) {
        delegateMap[info.id] = info;
@@ -55,8 +59,8 @@
    wxString floatToString(float value) {
        std::ostringstream ss;
         ss << std::fixed << std::setprecision(2) << std::round(value * 100) / 100;
         return ss.str();
        ss << std::fixed << std::setprecision(2) << std::round(value * 100) / 100;
        return ss.str();
    }
    void loadContent() {
@@ -72,8 +76,8 @@
            colorInfo0.color = *wxRED;
            delegateColors.push_back(colorInfo0);
        }
        delegateInfoStr.Append("笔 ");
        ColorIndexInfo colorInfo1;
@@ -85,10 +89,18 @@
            delegateColors.push_back(colorInfo1);
        }
        delegateInfoStr.Append("/").Append("封单").Append(delegateInfo.buy1_money);
        delegateInfoStr.Append(" ã€æ¯”例: ").Append(floatToString(delegateInfo.trade_progress_percent)).Append("%").Append("】,");
        delegateInfoStr.Append(" ã€æ¯”例: ");
        ColorIndexInfo colorInfo2;
        colorInfo2.start_index = delegateInfoStr.Length();
        delegateInfoStr.Append(floatToString(delegateInfo.trade_progress_percent)).Append("%");
        colorInfo2.end_index = delegateInfoStr.Length() - 1;
        colorInfo2.color = wxColor(206, 14, 95);
        delegateColors.push_back(colorInfo2);
        delegateInfoStr.Append("】,");
        delegateInfoStr.Append("已成大单").Append(to_string(delegateInfo.big_num_count)).Append("笔").Append(delegateInfo.big_num_money).Append("  ");
@@ -108,13 +120,25 @@
        delegateInfoStr.Append("笔").Append(delegateInfo.not_deal_big_num_money_after).Append(",");
        delegateInfoStr.Append("涨停价:").Append(floatToString(delegateInfo.limit_up_price)).Append("元").Append(",");
        delegateInfoStr.Append(delegateInfo.block);
        delegateInfoStr.Append("涨停价:");
        ColorIndexInfo colorInfo3;
        colorInfo3.start_index = delegateInfoStr.Length();
        delegateInfoStr.Append(floatToString(delegateInfo.limit_up_price)).Append("Ôª");
        colorInfo3.end_index = delegateInfoStr.Length();
        if (delegateInfo.limit_up_price < 3) {
            colorInfo3.color = *wxRED;
            delegateColors.push_back(colorInfo3);
        }
        delegateInfoStr.Append(",");
        delegateInfoStr.Append(delegateInfo.block).Append(",");
        delegateInfoStr.Append(" æ¶¨åœæ—¶é—´ï¼š").Append(delegateInfo.limit_up_time);
    }
    float parseMoneyAsW(wxString st) {
        wxString money= st;
        if (st.Find("万")>=0) {
        wxString money = st;
        if (st.Find("万") >= 0) {
            money = st.Mid(0, st.Find("万"));
            double d;
            money.ToDouble(&d);
@@ -124,7 +148,7 @@
            money = st.Mid(0, st.Find("亿"));
            double d;
            money.ToDouble(&d);
            return d*10000;
            return d * 10000;
        }
        else {
            double d;
@@ -136,35 +160,39 @@
    void drawOperateLine(wxDC* dc, int startx, int starty, int line_width) {
        //绘制红点
        /*  wxFont font(dc->GetFont().GetPixelSize(), wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT), wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL);*/
        // ç»˜åˆ¶åå­—
        wxString codeName = "";
        codeName.Append(delegateInfo.code).Append("(").Append(delegateInfo.codeName).Append(")");
        wxString codeInfo = "";
        codeInfo.Append(delegateInfo.code).Append("(").Append(delegateInfo.codeName).Append(")");
        WidgetsRenderUtil::drawText(dc, codeName, wxPoint(startx, starty + 3),line_width, TEXT_LINE_HEIGHT);
        codeInfo.Append("  ").Append(delegateInfo.zyltgb);
        if (delegateInfo.pay_attention) {
            wxSize textSize = dc->GetTextExtent(codeName);
            WidgetsRenderUtil::drawText(dc, "****", wxPoint(startx + textSize.GetWidth() + 5*DPI/100, starty + 5*DPI/100), line_width, TEXT_LINE_HEIGHT, std::list<ColorIndexInfo>(), *wxRED);
            WidgetsRenderUtil::drawText(dc, codeInfo, wxPoint(startx, starty + 3), line_width, TEXT_LINE_HEIGHT, std::list<ColorIndexInfo>(), *wxRED);
            wxSize textSize = dc->GetTextExtent(codeInfo);
            WidgetsRenderUtil::drawText(dc, "****", wxPoint(startx + textSize.GetWidth() + 5 * DPI / 100, starty + 5 * DPI / 100), line_width, TEXT_LINE_HEIGHT, std::list<ColorIndexInfo>(), *wxRED);
        }
        else {
            WidgetsRenderUtil::drawText(dc, codeInfo, wxPoint(startx, starty + 3), line_width, TEXT_LINE_HEIGHT);
        }
        // ç»˜åˆ¶æŒ‰é’®
        dc->SetPen(wxColour(225, 225, 225));
        dc->SetBrush(wxColour(225, 225, 225));
        int btnWidth = 50*DPI/100;
        int btnHeight = 25*DPI/100;
        int padding = 10*DPI/100;
        int btnWidth = 50 * DPI / 100;
        int btnHeight = 25 * DPI / 100;
        int padding = 10 * DPI / 100;
        viewBtnRectMap[delegateInfo.id] = wxRect({ startx + line_width - btnWidth, starty, btnWidth, btnHeight });
        WidgetsRenderUtil::drawBtn(dc, "查看", viewBtnRectMap[delegateInfo.id], *wxWHITE, wxColour(0, 150, 136));
        // ç›¸é‚»çš„æ’¤å•错位显示
        cancelBtnRectMap[delegateInfo.id] = wxRect({ startx + line_width - viewBtnRectMap[delegateInfo.id].GetWidth() - btnWidth - padding - (delegateInfo.index%2==0?0: btnWidth + 5*DPI/100), starty, btnWidth, btnHeight });
        cout << "撤单位置渲染:"<< delegateInfo.index << " - "<< cancelBtnRectMap[delegateInfo.id].x << ":" << cancelBtnRectMap[delegateInfo.id].y <<endl;
        cancelBtnRectMap[delegateInfo.id] = wxRect({ startx + line_width - viewBtnRectMap[delegateInfo.id].GetWidth() - btnWidth - padding - (delegateInfo.index % 2 == 0 ? 0 : btnWidth + 5 * DPI / 100), starty, btnWidth, btnHeight });
        cout << "撤单位置渲染:" << delegateInfo.index << " - " << cancelBtnRectMap[delegateInfo.id].x << ":" << cancelBtnRectMap[delegateInfo.id].y << endl;
        WidgetsRenderUtil::drawBtn(dc, "撤单", cancelBtnRectMap[delegateInfo.id], *wxWHITE, wxColour(255, 87, 34));
    }
@@ -179,7 +207,7 @@
        //gc->SetFont(font,*wxRED);
        wxSize queueSize(43*DPI/100, 22*DPI/100);
        wxSize queueSize(43 * DPI / 100, 22 * DPI / 100);
        // ç»˜åˆ¶èƒŒæ™¯é¢œè‰²
        wxRect queueRect = wxRect(start, wxSize(line_width, queueSize.y));
@@ -190,7 +218,7 @@
        queueRectMap[delegateInfo.id] = queueRect;
        int padding = 5*DPI/100;
        int padding = 5 * DPI / 100;
        int countPerLine = (line_width - padding) / (queueSize.x + padding);
@@ -275,12 +303,12 @@
    virtual bool Render(wxRect cell, wxDC* dc, int state)
    {
        cout <<"内存地址:"<< this << endl;
        cout << "内存地址:" << this << endl;
        dc->Clear();
        dc->SetUserScale(1,1);
        dc->SetUserScale(1, 1);
        gridPostionMap[delegateInfo.id] = wxRect(cell.GetPosition(), cell.GetSize());
        //// è®¾ç½®ç»˜åˆ¶æŒ‰é’®çš„位置和大小
@@ -292,14 +320,14 @@
        loadContent();
        int start_y = cell.GetPosition().y + 3*DPI/100;
        int start_y = cell.GetPosition().y + 3 * DPI / 100;
        int start_x = cell.GetPosition().x;
        // ç»˜åˆ¶æ“ä½œåŒºåŸŸ
        drawOperateLine(dc, start_x, start_y, cell.GetSize().GetWidth());
        // ç»˜åˆ¶ç®€ä»‹åŒº
        int infoWidth = cell.GetSize().GetWidth();
        int infoHeight = WidgetsRenderUtil::drawText(dc, delegateInfoStr, wxPoint(start_x, start_y + 25*DPI/100), infoWidth, TEXT_LINE_HEIGHT, delegateColors);
        int infoHeight = WidgetsRenderUtil::drawText(dc, delegateInfoStr, wxPoint(start_x, start_y + 25 * DPI / 100), infoWidth, TEXT_LINE_HEIGHT, delegateColors);
        // ç»˜åˆ¶é˜Ÿåˆ—,给文字信息留3排左右的位置
        drawDelegateQueue(dc, wxPoint(start_x, TEXT_LINE_HEIGHT * 3 + start_y + 30 * DPI / 100), infoWidth);
@@ -309,25 +337,25 @@
    }
    void cancelOrder(string code) {
     string results =    MyNetworkApi::cancel_order(code);
     auto doc = JsonUtil::parseUTF16(results);
     if (doc.IsObject()) {
         if (doc[L"code"].GetInt() == 0) {
             showMsg(wxString(delegateInfo.codeName).Append(":撤单提交成功").ToStdString(), MSG_TYPE_INFO);
             MainFrame* mainFrame = getWindowFrame();
             if (mainFrame) {
                 mainFrame->requestDelegatedInfoList();
             }
         }
         else {
             showMsg(wxString(doc[L"msg"].GetString()).ToStdString(), MSG_TYPE_WARNING);
         }
     }
     else {
         showMsg("网络请求失败", MSG_TYPE_ERROR);
     }
        string results = MyNetworkApi::cancel_order(code);
        auto doc = JsonUtil::parseUTF16(results);
        if (doc.IsObject()) {
            if (doc[L"code"].GetInt() == 0) {
                showMsg(wxString(delegateInfo.codeName).Append(":撤单提交成功").ToStdString(), MSG_TYPE_INFO);
                MainFrame* mainFrame = getWindowFrame();
                if (mainFrame) {
                    mainFrame->requestDelegatedInfoList();
                }
            }
            else {
                showMsg(wxString(doc[L"msg"].GetString()).ToStdString(), MSG_TYPE_WARNING);
            }
        }
        else {
            showMsg("网络请求失败", MSG_TYPE_ERROR);
        }
    }
@@ -345,11 +373,32 @@
        }
    }
    void showMsg(string msg,MsgTypeEnum type) {
    void showMsg(string msg, MsgTypeEnum type) {
        MainFrame* mainFrame = getWindowFrame();
        if (mainFrame)
        {
            mainFrame->showMsg(msg, type);
        }
    }
    /// <summary>
    /// æŸ¥çœ‹è¯¦æƒ…
    /// </summary>
    /// <param name="code"></param>
    static void viewDetail(wxString code) {
        try {
            Win32Util::addToTHS(code.ToStdString());
            list<HWND> hwnds = Win32Util::searchWindow("看盘副屏");
            if (hwnds.size() > 0) {
                for (list<HWND>::iterator e = hwnds.begin(); e != hwnds.end(); ++e) {
                    HWND hwnd = *e;
                    ViewDetailData* data = new ViewDetailData();
                    data->code = code.ToStdString();
                    SendMessage(hwnd, WM_USER + 1024, 0, reinterpret_cast<LPARAM>(&data));
                }
            }
        }
        catch (...) {
        }
    }
@@ -362,13 +411,13 @@
            switch (clickType)
            {
            case CLICK_TYPE_CANCEL_BUY:
                cancelOrder(delegateInfo.code.ToStdString());
                break;
            case CLICK_TYPE_VIEW_DETAIL:
                try {
                    Win32Util::addToTHS(delegateInfo.code.ToStdString());
                    thread t(viewDetail, delegateInfo.code);
                    t.detach();
                }
                catch (string msg) {
                    wxMessageBox(msg.c_str());
@@ -377,12 +426,12 @@
            default:
                break;
            }
        }
        }
        if (mouseEvent->LeftDClick()) {
            BtnClickType clickType = getClickType(mouseEvent->GetX(), mouseEvent->GetY());
            if (clickType == CLICK_TYPE_QUEUE)
            {
                WindowPosSize r = MyConfigUtil::getTradeQueueWindowPos();
                if (r.x == -1 && r.y == -1 && r.width == -1 && r.height == -1) {
                    // é»˜è®¤çš„尺寸与位置
@@ -390,11 +439,11 @@
                    RECT rect;
                    Win32Util::getWindowRect(framePos, &rect);
                    TradeQueueFrame* tradeQueueFrame = new TradeQueueFrame(delegateInfo.codeName, delegateInfo.code, wxPoint(rect.left, rect.top), wxSize(350,400));
                    TradeQueueFrame* tradeQueueFrame = new TradeQueueFrame(delegateInfo.codeName, delegateInfo.code, wxPoint(rect.left, rect.top), wxSize(350, 400));
                    tradeQueueFrame->Show(true);
                }
                else {
                    TradeQueueFrame* tradeQueueFrame = new TradeQueueFrame(delegateInfo.codeName, delegateInfo.code, wxPoint(r.x,r.y), wxSize(r.width, r.height));
                    TradeQueueFrame* tradeQueueFrame = new TradeQueueFrame(delegateInfo.codeName, delegateInfo.code, wxPoint(r.x, r.y), wxSize(r.width, r.height));
                    tradeQueueFrame->Show(true);
                }
                // é»˜è®¤æŸ¥çœ‹
@@ -406,7 +455,7 @@
                }
            }
        }
@@ -435,7 +484,8 @@
MainFrame::MainFrame(const wxString& title, wxPoint position, wxSize size) :wxFrame(NULL, wxID_ANY, title, position, size) {
    // ç½®é¡¶
    SetWindowStyle(GetWindowStyle() | wxSTAY_ON_TOP);
    // åˆå§‹åŒ–
    killed = false;
    Bind(wxEVT_CLOSE_WINDOW, &MainFrame::OnClose, this);
@@ -445,20 +495,19 @@
    SetTransparent(225);
    SetWindowStyle(GetWindowStyle() | wxSTAY_ON_TOP);
    wxPanel* panel = new wxPanel(this, wxID_ANY);
    // åˆ›å»º wxDataViewListCtrl æŽ§ä»¶
     m_listCtrl = new wxDataViewListCtrl(panel, wxID_ANY, wxDefaultPosition, wxDefaultSize,  wxDV_SINGLE| wxDV_NO_HEADER);
     m_listCtrl->SetBackgroundColour(wxColor(242, 242, 242));
     // ç»‘定没行的选中事件
     m_listCtrl->Bind(wxEVT_DATAVIEW_SELECTION_CHANGED, &MainFrame::OnSelectionChanged, this);
    m_listCtrl = new wxDataViewListCtrl(panel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxDV_SINGLE | wxDV_NO_HEADER);
    m_listCtrl->SetBackgroundColour(wxColor(242, 242, 242));
    // ç»‘定没行的选中事件
    m_listCtrl->Bind(wxEVT_DATAVIEW_SELECTION_CHANGED, &MainFrame::OnSelectionChanged, this);
    // æ·»åŠ åˆ—
    auto bc = new DelegateInfoRenderer();
    wxDataViewColumn *delegateColumn =  new wxDataViewColumn("委托信息", bc, 0, ROW_WIDTH_DELEGATE_INFO, wxALIGN_LEFT);
    wxDataViewColumn* delegateColumn = new wxDataViewColumn("委托信息", bc, 0, ROW_WIDTH_DELEGATE_INFO, wxALIGN_LEFT);
    m_listCtrl->AppendColumn(delegateColumn);
@@ -468,22 +517,26 @@
    wxBoxSizer* sizer = new wxBoxSizer(wxVERTICAL);
    // æç¤ºä¿¡æ¯
    msgCtrl = new wxStaticText(panel,wxID_ANY,"");
    msgCtrl = new wxStaticText(panel, wxID_ANY, "");
    wxButton *openTradeQueueBtn =new wxButton(panel, wxID_ANY,"查看全部");
    wxButton* openTradeQueueBtn = new wxButton(panel, wxID_ANY, "查看全部");
    wxBoxSizer *topSizer=new wxBoxSizer(wxHORIZONTAL);
    avaiableMoneyLabel = new wxStaticText(panel, wxID_ANY, "0.00", wxDefaultPosition, wxSize(80 * DPI / 100, -1));
    wxBoxSizer* topSizer = new wxBoxSizer(wxHORIZONTAL);
    topSizer->Add(msgCtrl, 1, wxEXPAND);
    topSizer->Add(avaiableMoneyLabel, 0, wxEXPAND | wxALL, 3);
    topSizer->Add(openTradeQueueBtn, 0);
    sizer->Add(topSizer, 0, wxEXPAND | wxLEFT|wxTOP|wxRIGHT, 5);
    sizer->Add(topSizer, 0, wxEXPAND | wxLEFT | wxTOP | wxRIGHT, 5);
    sizer->Add(m_listCtrl, 1, wxEXPAND | wxALL, 5);
    panel->SetSizerAndFit(sizer);
    openTradeQueueBtn->Bind(wxEVT_BUTTON, &MainFrame::OnButtonOpenTradeQueueClick,this);
    openTradeQueueBtn->Bind(wxEVT_BUTTON, &MainFrame::OnButtonOpenTradeQueueClick, this);
    std::thread t1(startRequestDelegatedInfoListTask, this);
@@ -515,9 +568,9 @@
}
void MainFrame::clearMsg( MainFrame* context)
void MainFrame::clearMsg(MainFrame* context)
{
    Sleep(15* 1000);
    Sleep(15 * 1000);
    if (TimeUtil::getNowTimeStamp() > context->msgExpireTime) {
        context->msgCtrl->SetLabelText("");
    }
@@ -533,6 +586,7 @@
void MainFrame::refresh()
{
    cout << "刷新时间:" << TimeUtil::getNowTimeStamp() << " æ•°é‡ï¼š" << delegateList.size() << endl;
    m_listCtrl->DeleteAllItems();
    for (list<DelegateInfo>::iterator e = delegateList.begin(); e != delegateList.end(); ++e) {
        DelegateInfo info = *e;
@@ -541,17 +595,19 @@
        data.push_back(info.id);
        m_listCtrl->AppendItem(data);
    }
    m_listCtrl->Refresh();
}
list<DelegateInfo> MainFrame::parseDelegates(string result)
DelegateResult MainFrame::parseDelegates(string result)
{
    list<DelegateInfo> fresults;
    wxString available_money = "";
    auto doc = JsonUtil::parseUTF16(result);
    if (doc.IsObject() && doc[L"code"].GetInt() == 0) {
        auto root = doc[L"data"].GetObject();
        auto delegates = root[L"delegates"].GetArray();
        auto money = root[L"account_available_money"].GetString();
        double money = root[L"account_available_money"].GetDouble();
        available_money = StringUtil::to_string(money);
        for (int i = 0; i < delegates.Size(); i++) {
            auto doc = delegates[i].GetObject();
@@ -582,15 +638,21 @@
            delegateInfo.limit_up_price = doc[L"limit_up_price"].GetFloat();
            delegateInfo.is_near_big_order = doc[L"is_near_big_order"].GetString();
            delegateInfo.block = doc[L"block"].GetString();
            if (doc.HasMember(L"limit_up_time")) {
                delegateInfo.limit_up_time = doc[L"limit_up_time"].GetString();
            }
            array=doc[L"trade_queue"].GetArray();
            array = doc[L"trade_queue"].GetArray();
            list<TradeQueue> queueList;
            for (int j = 0; j < array.Size(); j++) {
                int num = array[j].GetArray()[0].GetInt();
                int type = array[j].GetArray()[1].GetInt();
                queueList.push_back(TradeQueue({to_string(num),type}));
                queueList.push_back(TradeQueue({ to_string(num),type }));
            }
            delegateInfo.tradeQueueList = queueList;
            if (doc.HasMember(L"zyltgb"))
                delegateInfo.zyltgb = doc[L"zyltgb"].GetString();
            fresults.push_back(delegateInfo);
        }
@@ -598,45 +660,56 @@
    else {
        throw string("网络请求出错");
    }
    return fresults;
    return DelegateResult({ fresults ,available_money });
}
void MainFrame::startRequestDelegatedInfoListTask(MainFrame* context)
{
    while (TRUE) {
        if (context->killed) {
            break;
        }
        try {
            context->requestDelegatedInfoList();
        }
        catch (string st) {
            while (TRUE) {
                if (context->killed) {
                    break;
                }
                try {
                    context->requestDelegatedInfoList();
                }
                catch (string st) {
                }
                catch (...) {
                }
                Sleep(2000);
            }
        }
        catch (...) {
        }
        Sleep(2000);
    }
}
void MainFrame::requestDelegatedInfoList()
{
    try {
        cout <<"请求委托列表"<< endl;
        auto start_time = TimeUtil::getNowTimeStamp();
        string result = MyNetworkApi::get_delegated_buy_code_infos();
        if (killed) {
            return;
        }
        cout << "请求委托列表耗时:" << TimeUtil::getNowTimeStamp() - start_time << endl;
        start_time = TimeUtil::getNowTimeStamp();
        auto doc = JsonUtil::parseUTF8(result);
        auto delegateList = parseDelegates(result);
        auto delegateResult = parseDelegates(result);
        cout << "解析数据耗时:" << TimeUtil::getNowTimeStamp() - start_time << endl;
        start_time = TimeUtil::getNowTimeStamp();
        // æ ¹æ®ID
        if (this != nullptr) {
            this->delegateList = delegateList;
            this->delegateList = delegateResult.delegates;
            this->avaiableMoneyLabel->SetLabelText(delegateResult.money);
            this->refresh();
            cout << "刷新UI耗时:" << TimeUtil::getNowTimeStamp() - start_time << endl;
        }
    }
    catch (string st) {
@@ -653,8 +726,7 @@
void MainFrame::OnButtonOpenTradeQueueClick(wxCommandEvent& event)
{
    if (delegateList.size()>0) {
    if (delegateList.size() > 0) {
        WindowPosSize r = MyConfigUtil::getTradeQueueWindowPos();
        if (r.x == -1 && r.y == -1) {
            r.x = 0;
DelegateQueue/MainFrame.h
@@ -12,6 +12,12 @@
#define FRAME_HEIGHT 660*DPI/100
using namespace std;
struct DelegateResult
{
    list<DelegateInfo> delegates;
    wxString money;
};
@@ -21,6 +27,7 @@
private:
    wxDataViewListCtrl* m_listCtrl;
    wxStaticText* msgCtrl;
    wxStaticText* avaiableMoneyLabel;
    list<DelegateInfo> delegateList;
    bool killed;
    long msgExpireTime;
@@ -48,7 +55,7 @@
    void refresh();
    static list<DelegateInfo> parseDelegates(string result);
    static DelegateResult parseDelegates(string result);
    static void startRequestDelegatedInfoListTask(MainFrame* context);
DelegateQueue/MyNetworkApi.cpp
@@ -59,4 +59,24 @@
    string result = base_trade_request(std::string(json_content));
    return result;
}
}
string MyNetworkApi::get_deal_big_money_list(string code)
{
    rapidjson::StringBuffer buf;
    rapidjson::PrettyWriter<rapidjson::StringBuffer> writer(buf);
    writer.StartObject();
    writer.Key("type");
    writer.String("common");
    writer.Key("data");
    writer.StartObject();
    writer.Key("ctype");
    writer.String("get_deal_big_money_list");
    writer.Key("code");
    writer.String(code.c_str());
    writer.EndObject();
    writer.EndObject();
    const char* json_content = buf.GetString();
    string result = base_trade_request(std::string(json_content));
    return result;
}
DelegateQueue/MyNetworkApi.h
@@ -7,5 +7,12 @@
    static string get_trade_queue(string code);
    static string cancel_order(string code);
    /// <summary>
    /// èŽ·å–æˆäº¤å¤§å•åˆ—è¡¨
    /// </summary>
    /// <param name="code"></param>
    /// <returns></returns>
    static string get_deal_big_money_list(string code);
};
DelegateQueue/TradeQueueFrame.cpp
@@ -10,14 +10,31 @@
    //SetTransparent(225);
    this->killed = false;
    Bind(wxEVT_CLOSE_WINDOW, &TradeQueueFrame::OnClose, this);
    listControl = new TradeQueueListControl(this, wxID_ANY);
    Bind(wxEVT_SIZE, &TradeQueueFrame::OnSize, this);
    scrolledWindow = new wxScrolledWindow(this, wxID_ANY);
    listControl = new TradeQueueListControl(scrolledWindow, wxID_ANY, wxDefaultPosition,wxSize(-1, size.GetHeight()-35));
    dealBigMoneyListControl = new TradeQueueListControl(scrolledWindow, wxID_ANY, wxDefaultPosition, wxSize(-1, size.GetHeight() - 35), wxSize(75,22));
    wxBoxSizer* sizer = new wxBoxSizer(wxVERTICAL);
    sizer->Add(dealBigMoneyListControl, 0, wxEXPAND | wxBottom, 10);
    sizer->Add(listControl, 1, wxEXPAND);
    SetSizer(sizer);
    //SetSizer(sizer);
    SetBackgroundColour(*wxBLACK);
    scrolledWindow->SetScrollbars(1, dealBigMoneyListControl->GetSize().GetHeight(), 0, 2);
    scrolledWindow->SetSizer(sizer);
    scrolledWindow->SetScrollRate(0, dealBigMoneyListControl->GetSize().GetHeight());
    scrolledWindow->Scroll(0, 1);
    wxBoxSizer* rootSizer = new wxBoxSizer(wxVERTICAL);
    rootSizer->Add(scrolledWindow, 1, wxEXPAND);
    SetSizer(rootSizer);
    requestThread = new std::thread(requestTradeQueue, code, this);
    requestThread->detach();
    std::thread* t1 = new std::thread(requestDealBigList, code, this);
    t1->detach();
}
TradeQueueFrame::~TradeQueueFrame()
@@ -37,6 +54,31 @@
    MyConfigUtil::setTradeQueueWindowPos(GetPosition(), GetSize());
    // æ­£å¸¸å…³é—­
    event.Skip();
}
void TradeQueueFrame::OnSize(wxSizeEvent& event)
{
    event.Skip();
    wxSize size = GetClientSize();
    cout <<"窗口大小:"<< size.GetWidth()<<"-"<<size.GetHeight()<< endl;
    listControl->SetSize(size);
    dealBigMoneyListControl->SetSize(size);
    //resetScrollInfo();
}
void TradeQueueFrame::resetScrollInfo()
{
    int height = dealBigMoneyListControl->getContentHeight();
    int pos = scrolledWindow->GetScrollPos(wxVERTICAL);
    scrolledWindow->AdjustScrollbars();
    scrolledWindow->SetScrollbars(1, dealBigMoneyListControl->GetSize().GetHeight(), 0, 1);
    scrolledWindow->SetScrollRate(0, dealBigMoneyListControl->GetSize().GetHeight());
    //scrolledWindow->Layout();
    scrolledWindow->Scroll(0, pos);
    cout << "成交队列的高度:" << listControl->GetClientRect().GetHeight() << endl;
    cout << "scrollwindow的高度:" << scrolledWindow->GetSize().GetHeight() << endl;
    Refresh();
}
void TradeQueueFrame::requestTradeQueue(wxString code, TradeQueueFrame* context)
@@ -73,18 +115,72 @@
                                int type = array[i][1].GetInt();
                                queueList.push_back(TradeQueue({ to_string(num),type }));
                            }
                            if (context != nullptr && context->listControl != nullptr)
                            {
                                context->listControl->setTradeQueue(queueList);
                                context->latest_request_result = result;
                            }
                        }
                        else {
                            cout << "code!=0" << endl;
                        }
                    }
                    cout << code << endl;
                    if (context != nullptr && context->listControl != nullptr)
                    {
                        context->listControl->setTradeQueue(queueList);
                        context->latest_request_result = result;
                }
            }
            catch (string st) {
                cout << "出错"<< endl;
            }
        }
        count++;
        Sleep(100);
    }
}
void TradeQueueFrame::requestDealBigList(wxString code, TradeQueueFrame* context)
{
    int count = 0;
    while (TRUE) {
        if (context->killed) {
            break;
        }
        if (count % 30 == 0) {
            count = 1;
            try {
                list<TradeQueue> moneyList;
                string result = MyNetworkApi::get_deal_big_money_list(code.ToStdString());
                if (context->killed) {
                    break;
                }
                auto doc = JsonUtil::parseUTF16(result);
                if (doc.IsObject()) {
                    if (doc[L"code"].GetInt() == 0) {
                        auto array = doc[L"data"].GetArray();
                        for (int i = 0; i < array.Size(); i++) {
                            wxString money = array[i].GetString();
                            int type = 3;
                            moneyList.push_back(TradeQueue({ money,type }));
                        }
                        if (context != nullptr && context->listControl != nullptr)
                        {
                            bool lengthChange = moneyList.size() != context->dealBigMoneyListControl->getDataCount();
                            context->dealBigMoneyListControl->setTradeQueue(moneyList);
                            if (lengthChange)
                            {
                                context->resetScrollInfo();
                            }
                        }
                    }
                }
            }
            catch (string st) {
            }
        }
        count++;
DelegateQueue/TradeQueueFrame.h
@@ -31,17 +31,30 @@
{
private:
    TradeQueueListControl* listControl;
    TradeQueueListControl* dealBigMoneyListControl;
    bool killed;
    wxScrolledWindow* scrolledWindow;
    string latest_request_result;
    std::thread *requestThread;
public:
    TradeQueueFrame(const wxString& title, wxString code, wxPoint position=wxDefaultPosition, wxSize size = wxDefaultSize);
    ~TradeQueueFrame();
    void OnClose(wxCloseEvent& event);
    void OnSize(wxSizeEvent& event);
private:
    /// <summary>
    /// é‡æ–°è®¾ç½®æ»šåŠ¨ä¿¡æ¯
    /// </summary>
    void resetScrollInfo();
    // è¯·æ±‚列表
        // èŽ·å–äº¤æ˜“é˜Ÿåˆ—
    static void requestTradeQueue(wxString code, TradeQueueFrame* context);
    static void requestDealBigList(wxString code, TradeQueueFrame* context);
};
DelegateQueue/TradeQueueListControl.cpp
@@ -1,5 +1,6 @@
#include "TradeQueueListControl.h"
#include "common.h"
#include <wx\dcbuffer.h>
using namespace std;
//wxDEFINE_EVENT(wxEVT_UPDATE_UI, wxCommandEvent);
@@ -10,26 +11,23 @@
TradeQueueListControl::TradeQueueListControl(wxWindow* parent, wxWindowID id,
    const wxPoint& pos, const wxSize& size)
    : wxControl(parent, id, pos, size, wxBORDER_NONE) {
    const wxPoint& pos, const wxSize& size, wxSize queueItemSize)
    : wxControl(parent, id, pos, size, wxBORDER_NONE), suitHeight(false),queueItemSize(queueItemSize){
    Bind(wxEVT_PAINT, &TradeQueueListControl::OnPaint, this);
}
void TradeQueueListControl::OnPaint(wxPaintEvent& event) {
    cout <<"OnPaint"<< endl;
    try {
        wxPaintDC dc(this);
        dc.SetBackground(wxBrush(GetBackgroundColour()));
        wxBufferedPaintDC  dc(this);
        PrepareDC(dc);
        dc.SetBackground(wxBrush(*wxBLACK));
        dc.Clear();
        dc.SetPen(*wxBLACK_PEN);
        dc.SetBrush(*wxLIGHT_GREY_BRUSH);
        dc.DrawRectangle(GetClientRect());
        wxSize queueSize(50*DPI/100, 22*DPI/100);
        wxSize queueSize(queueItemSize.GetWidth() *DPI/100, queueItemSize.GetHeight() *DPI/100);
        // ç»˜åˆ¶èƒŒæ™¯é¢œè‰²
        wxRect    queueRect = wxRect(GetPosition(), GetSize());
        wxRect    queueRect = wxRect(wxPoint(0, 0), GetSize());//wxRect(GetPosition(), GetSize());
        dc.SetPen(*wxBLACK);
        dc.SetBrush(*wxBLACK);
        dc.DrawRectangle(queueRect);
@@ -39,19 +37,24 @@
        int padding = 3*DPI/100;
        int countPerLine = (width+padding) / (queueSize.x+padding);
        if (countPerLine == 0) {
            countPerLine = 1;
        }
        int lineCount = queueList.size() % countPerLine == 0 ? queueList.size() / countPerLine : queueList.size() / countPerLine + 1;
        std::list<TradeQueue>::iterator e = queueList.begin();
        int startx = GetPosition().x + padding;
        int starty = GetPosition().y + padding;
        int startx = padding;
        int starty = padding;
        wxFont font = dc.GetFont();
        //font.SetNumericWeight(wxFONTWEIGHT_BOLD);
        font.SetPointSize(10);
        dc.SetFont(font);
        int height = startx;
        for (int r = 0; r < lineCount; r++) {
@@ -76,16 +79,25 @@
                case 2:
                    color = wxColor(209, 135, 252);
                    break;
                case 3:
                    color = wxColor(225, 225, 225);
                    break;
                default:
                    color = *wxRED;
                    break;
                }
                // wxColor(66,32,33)
                WidgetsRenderUtil::drawBtn(&dc, (*e).num, rect, color, *wxBLACK);
                WidgetsRenderUtil::drawBtn(&dc, (*e).num, rect, color, *wxBLACK,wxALIGN_RIGHT);
                if (e != queueList.end()) {
                    ++e;
                }
                height = rect.y + rect.GetHeight() + padding;
            }
        }
        this->contentHeight = height;
        if (suitHeight) {
            //GetSize().SetHeight(height);
        }
        dc.SetTextForeground(*wxBLACK);
@@ -104,3 +116,13 @@
        Refresh();
    }
}
int TradeQueueListControl::getContentHeight()
{
    return this->contentHeight;
}
int TradeQueueListControl::getDataCount()
{
    return this->queueList.size();
}
DelegateQueue/TradeQueueListControl.h
@@ -6,17 +6,24 @@
class TradeQueueListControl : public wxControl {
private:
    std::list<TradeQueue> queueList;
    int contentHeight;// å†…容的高度
    bool suitHeight;
    wxSize queueItemSize;
public:
    TradeQueueListControl(wxWindow* parent, wxWindowID id,
        const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize);
        const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize,wxSize queueItemSize = wxSize(50,22));
    void OnPaint(wxPaintEvent& event);
    void setTradeQueue(std::list<TradeQueue> queueList);
    int getContentHeight();
    int getDataCount();
};
DelegateQueue/config.cfg
@@ -1,2 +1,2 @@
trade_queue_window = "[\n    -1130,\n    376,\n    565,\n    483\n]";
main_window = "[\n    132,\n    240,\n    600,\n    660\n]";
trade_queue_window = "[\n    -998,\n    123,\n    500,\n    466\n]";
main_window = "[\n    773,\n    205,\n    600,\n    660\n]";
FloatTrade/FloatTradeDlg.cpp
@@ -34,6 +34,9 @@
const int HOT_KEY_CANCEL = 2;
const int HOT_KEY_BUY = 3;
// å¯è½¬å€ºæ¶ˆæ¯
#define WM_CB_WINDOW (WM_APP + 1000)
bool CFloatTradeDlg::breakCancelMsg;
@@ -814,6 +817,7 @@
}
void CFloatTradeDlg::OnHotKey(UINT nHotKeyId, UINT nKey, UINT nModifiers) {
    if (!checkTradeQuickKey.GetCheck()) {
@@ -822,8 +826,34 @@
    }
    if (nHotKeyId == HOT_KEY_SELL_ALL) {
        cout << "卖" << endl;
        OnClickedBtnSell();
        list<HWND> hwnds =    Win32Util::searchWindow("可转债交易");
        HWND cbHwnd = 0;
        if (hwnds.size() > 0) {
            for (list<HWND>::iterator e = hwnds.begin(); e != hwnds.end(); ++e) {
                HWND hwnd = *e;
                if (string("可转债交易")._Equal(Win32Util::getWindowName(hwnd))) {
                    auto fw = ::GetForegroundWindow();
                    if (fw == hwnd) {
                        cbHwnd = hwnd;
                    }
                    break;
                }
            }
        }
        if (cbHwnd>0) {
            string data = "你是不是傻";
            COPYDATASTRUCT cds;
            cds.dwData = 100; // å¯ä»¥è‡ªå®šä¹‰æ ‡è¯†æ•°æ®
            cds.cbData = (DWORD)data.size() + 1; // å­—符串数据长度
            cds.lpData = (PVOID)data.c_str();
            ::SendMessage(cbHwnd, WM_COPYDATA, NULL, (LPARAM)&cds);
        }
        else {
            cout << "卖" << endl;
            OnClickedBtnSell();
        }
    }
    else if (nHotKeyId == HOT_KEY_CANCEL) {
        cout << "撤当前" << endl;
FloatTrade/config.cfg
@@ -1,4 +1,4 @@
window_pos = "[670,245]";
window_pos = "[-1249,215]";
trade_quick_key = 1;
sell_rule_show_pos = "-733,208";
ths_auto_click_time_space = 2000;
Monitor/Monitor.aps
Binary files differ
Monitor/Monitor.rc
Binary files differ
Monitor/MonitorDlg.cpp
@@ -469,6 +469,13 @@
            dlg->labelColors[IDC_STATIC_HUAXIN_TRADE_CHANNEL] =  RGB(255, 0, 0);
            dlg->labelHXTradeChannel.SetWindowTextW(st);
        }
        catch (wstring st) {
            dlg->labelColors[IDC_STATIC_HUAXIN_TRADE_CHANNEL] = RGB(255, 0, 0);
            dlg->labelHXTradeChannel.SetWindowTextW(st.c_str());
        }
        catch (...) {
        }
        if (kill) {
@@ -593,6 +600,19 @@
                            dlg->labelTradeChannelState.SetWindowTextW(L"异常");
                        }
                    }
                    if (data.HasMember(L"today_zylt_updated_count")) {
                        int count = data[L"today_zylt_updated_count"].GetInt();
                        dlg->labelTodayZyltVolumeCount.SetWindowTextW(to_wstring(count).c_str());
                    }
                    if (data.HasMember(L"today_history_k_bar_count")) {
                        int count = data[L"today_history_k_bar_count"].GetInt();
                        dlg->labelTodayKBarsCount.SetWindowTextW(to_wstring(count).c_str());
                    }
                }
                else {
                    dlg->labelColors[IDC_STATIC_JUEJIN_STATE] = RGB(255, 0, 0);
@@ -603,6 +623,10 @@
        catch (CString st) {
            dlg->labelColors[IDC_STATIC_JUEJIN_STATE] = RGB(255, 0, 0);
            dlg->labelJueJinState.SetWindowTextW(st);
        }
        catch (wstring st) {
            dlg->labelColors[IDC_STATIC_JUEJIN_STATE] = RGB(255, 0, 0);
            dlg->labelJueJinState.SetWindowTextW(CString(st.c_str()));
        }
        if (kill) {
            break;
@@ -807,6 +831,10 @@
    DDX_Control(pDX, IDC_STATIC_L2_LISTEN_ACTIVE, labelL2ListenData);
    DDX_Control(pDX, IDC_LIST_L2_POSITION_CODES, listL2PositionCodes);
    DDX_Control(pDX, IDC_STATIC_L2_POSITION_SUBSCRIPT_CODES_UPDATE_TIME2, labelL2PositionSubscriptCodesUpdateTime);
    DDX_Control(pDX, IDC_STATIC_TODAY_ZYLT_VOLUME_COUNT, labelTodayZyltVolumeCount);
    DDX_Control(pDX, IDC_EDIT_CODE_FOR_SEARCH, editSearchCode);
    DDX_Control(pDX, IDC_BUTTON_SEARCH, btnSearch);
    DDX_Control(pDX, IDC_STATIC_TODAY_K_BARS_COUNT, labelTodayKBarsCount);
}
@@ -824,6 +852,9 @@
    ON_BN_CLICKED(IDC_BUTTON_SYNC_SHSZ_CODES, &MonitorDlg::OnBnClickedButtonSyncShszCodes)
    ON_BN_CLICKED(IDC_BUTTON_SAVE_RUNNING_DATA, &MonitorDlg::OnBnClickedButtonSaveRunningData)
    ON_BN_CLICKED(IDC_BUTTON_REPAIRE_TASK, &MonitorDlg::OnBnClickedButtonRepaireTask)
    ON_BN_CLICKED(IDC_BUTTON_SYNC_ZYLT_VOLUME, &MonitorDlg::OnBnClickedButtonSyncZyltVolume)
    ON_BN_CLICKED(IDC_BUTTON_SEARCH, &MonitorDlg::OnBnClickedButtonSearch)
    ON_BN_CLICKED(IDC_BUTTON_SYNC_K_BARS, &MonitorDlg::OnBnClickedButtonSyncKBars)
END_MESSAGE_MAP()
@@ -1075,3 +1106,61 @@
    }
}
void MonitorDlg::OnBnClickedButtonSyncZyltVolume()
{
    // åŒæ­¥è‡ªç”±æµé€šé‡
    string result = NetworkApi::sync_zylt_volume();
    auto doc = JsonUtil::parseUTF16(result);
    if (doc.IsObject()) {
        if (doc[L"code"].GetInt() == 0) {
            MessageBox(doc[L"msg"].GetString(), L"提示");
        }
        else {
            AfxMessageBox(doc[L"msg"].GetString());
        }
    }
    else {
        AfxMessageBox(L"网络请求出错");
    }
}
void MonitorDlg::OnBnClickedButtonSearch()
{
    CString code;
    editSearchCode.GetWindowTextW(code);
    searchCode = code;
    int itemCount = listL2Codes.GetItemCount(); // èŽ·å–åˆ—è¡¨é¡¹æ•°é‡
    for (int i = 0; i < itemCount; ++i) {
        CString strItemText = listL2Codes.GetItemText(i, 0);
        if (strItemText.Find(searchCode) >= 0) {
            listL2Codes.SetItemState(i, LVIS_SELECTED | LVIS_FOCUSED, LVIS_SELECTED | LVIS_FOCUSED);
            listL2Codes.SetSelectionMark(i);
            break;
        }
    }
}
void MonitorDlg::OnBnClickedButtonSyncKBars()
{
    // åŒæ­¥è‡ªç”±æµé€šé‡
    string result = NetworkApi::sync_history_k_bars();
    auto doc = JsonUtil::parseUTF16(result);
    if (doc.IsObject()) {
        if (doc[L"code"].GetInt() == 0) {
            MessageBox(doc[L"msg"].GetString(), L"提示");
        }
        else {
            AfxMessageBox(doc[L"msg"].GetString());
        }
    }
    else {
        AfxMessageBox(L"网络请求出错");
    }
}
Monitor/MonitorDlg.h
@@ -42,6 +42,8 @@
private:
    //开盘啦数据警告
    bool kplDataWarning;
    CString searchCode;
    
    const int MAX_LOG_LINES = 100;
    map<int,COLORREF> labelColors;
@@ -98,7 +100,7 @@
    afx_msg void OnBnClickedButtonRefreshMoney();
    afx_msg void OnBnClickedButtonFloatFrame();
    afx_msg void OnBnClickedButtonTradeRecord();
    CMyListCtrl listL2Codes;
    CListCtrl listL2Codes;
    CMyListCtrl listDelegate;
    CMyListCtrl listDeal;
    virtual BOOL OnInitDialog();
@@ -125,4 +127,11 @@
    CListCtrl listL2PositionCodes;
    CStatic labelL2PositionSubscriptCodesUpdateTime;
    afx_msg void OnBnClickedButtonRepaireTask();
    afx_msg void OnBnClickedButtonSyncZyltVolume();
    CStatic labelTodayZyltVolumeCount;
    CEdit editSearchCode;
    CButton btnSearch;
    afx_msg void OnBnClickedButtonSearch();
    CStatic labelTodayKBarsCount;
    afx_msg void OnBnClickedButtonSyncKBars();
};
Monitor/resource.h
@@ -20,9 +20,13 @@
#define IDC_STATIC_L2_SUBSCRIPT_CODES_UPDATE_TIME 1013
#define IDC_EDIT1                       1014
#define IDC_STATIC_L2_LISTEN_ACTIVE     1015
#define IDC_STATIC_TODAY_ZYLT_VOLUME_COUNT 1016
#define IDC_LIST_L2_POSITION_CODES      1017
#define IDC_STATIC_L2_SUBSCRIPT_CODES_UPDATE_TIME2 1018
#define IDC_STATIC_L2_POSITION_SUBSCRIPT_CODES_UPDATE_TIME2 1018
#define IDC_EDIT_CODE_FOR_SEARCH        1019
#define IDC_STATIC_TODAY_ZYLT_VOLUME_COU 1020
#define IDC_STATIC_TODAY_K_BARS_COUNT   1020
#define IDC_BUTTON_REFRESH_DELEGATE     1038
#define IDC_BUTTON_REFRESH_DEAL         1039
#define IDC_BUTTON_REFRESH_POSITION     1040
@@ -34,8 +38,10 @@
#define IDC_BUTTON_REDIS_TEST           1045
#define IDC_BUTTON_SYNC_SHSZ_CODES      1046
#define IDC_BUTTON_SAVE_RUNNING_DATA    1047
#define IDC_BUTTON_SAVE_RUNNING_DATA2   1048
#define IDC_BUTTON_REPAIRE_TASK         1048
#define IDC_BUTTON_SYNC_ZYLT_VOLUME     1049
#define IDC_BUTTON_SEARCH               1050
#define IDC_BUTTON_SYNC_K_BARS          1051
// Next default values for new objects
// 
MonitorSetup/MonitorSetup.vdproj
@@ -880,7 +880,7 @@
        {
            "{5259A561-127C-4D43-A0A1-72F10C7B3BF8}:_0CBCA946446C44638333507C894C0E0D"
            {
            "SourcePath" = "8:..\\x64\\Debug\\Monitor.exe"
            "SourcePath" = "8:..\\x64\\Release\\Monitor.exe"
            "TargetName" = "8:"
            "Tag" = "8:"
            "Folder" = "8:_FBB3BE7EF7B54479A324C4719BB35A6C"
SetupCBTrade/SetupCBTrade.vdproj
@@ -15,56 +15,32 @@
    {
        "Entry"
        {
        "MsmKey" = "8:_0F6F6FB11BB5B04B2FC88C3DE8F60B3D"
        "OwnerKey" = "8:_FFFFDB2ACD1F4C92B11F59958EDA2540"
        "MsmKey" = "8:_351E2C6402784AB1BA66DFEA28EA1B15"
        "OwnerKey" = "8:_UNDEFINED"
        "MsmSig" = "8:_UNDEFINED"
        }
        "Entry"
        {
        "MsmKey" = "8:_5345A483EDAA068D4ECD46E43B44CB14"
        "OwnerKey" = "8:_FFFFDB2ACD1F4C92B11F59958EDA2540"
        "MsmKey" = "8:_78B761D1C46A47D582FF5FF7A853FFA4"
        "OwnerKey" = "8:_UNDEFINED"
        "MsmSig" = "8:_UNDEFINED"
        }
        "Entry"
        {
        "MsmKey" = "8:_59D015A90A16B1ABD3D979AD6468EDE8"
        "OwnerKey" = "8:_FFFFDB2ACD1F4C92B11F59958EDA2540"
        "MsmKey" = "8:_9CFF5151D67A47A3995920D4AA159223"
        "OwnerKey" = "8:_UNDEFINED"
        "MsmSig" = "8:_UNDEFINED"
        }
        "Entry"
        {
        "MsmKey" = "8:_748C0CFF0B301DD2DF3EE16E835A686C"
        "OwnerKey" = "8:_FFFFDB2ACD1F4C92B11F59958EDA2540"
        "MsmKey" = "8:_C20E0E53F5FC4235B2E9FDDC48F0AC3F"
        "OwnerKey" = "8:_UNDEFINED"
        "MsmSig" = "8:_UNDEFINED"
        }
        "Entry"
        {
        "MsmKey" = "8:_806BCE58ED916D481C2248D65B3D0601"
        "OwnerKey" = "8:_FFFFDB2ACD1F4C92B11F59958EDA2540"
        "MsmSig" = "8:_UNDEFINED"
        }
        "Entry"
        {
        "MsmKey" = "8:_84F38A3DCB9A3927A2AB617FE7FB9F0C"
        "OwnerKey" = "8:_FFFFDB2ACD1F4C92B11F59958EDA2540"
        "MsmSig" = "8:_UNDEFINED"
        }
        "Entry"
        {
        "MsmKey" = "8:_8F870806ED5B4E9C1FDBE30D24BB7885"
        "OwnerKey" = "8:_FFFFDB2ACD1F4C92B11F59958EDA2540"
        "MsmSig" = "8:_UNDEFINED"
        }
        "Entry"
        {
        "MsmKey" = "8:_A49EA12BB1477DD472735269247207E0"
        "OwnerKey" = "8:_FFFFDB2ACD1F4C92B11F59958EDA2540"
        "MsmSig" = "8:_UNDEFINED"
        }
        "Entry"
        {
        "MsmKey" = "8:_B345A65FB682CB0D48B8479967B84DF8"
        "OwnerKey" = "8:_FFFFDB2ACD1F4C92B11F59958EDA2540"
        "MsmKey" = "8:_DBBBA2E304CC4FF3A410726CC23C0F04"
        "OwnerKey" = "8:_UNDEFINED"
        "MsmSig" = "8:_UNDEFINED"
        }
        "Entry"
@@ -91,6 +67,22 @@
        "PrivateKeyFile" = "8:"
        "TimeStampServer" = "8:"
        "InstallerBootstrapper" = "3:2"
            "BootstrapperCfg:{63ACBE69-63AA-4F98-B2B6-99F9E24495F2}"
            {
            "Enabled" = "11:TRUE"
            "PromptEnabled" = "11:TRUE"
            "PrerequisitesLocation" = "2:1"
            "Url" = "8:"
            "ComponentsUrl" = "8:"
                "Items"
                {
                    "{EDC2488A-8267-493A-A98E-7D9C3B36CDF3}:.NETFramework,Version=v4.7.2"
                    {
                    "Name" = "8:Microsoft .NET Framework 4.7.2 (x86 and x64)"
                    "ProductCode" = "8:.NETFramework,Version=v4.7.2"
                    }
                }
            }
        }
        "Release"
        {
@@ -107,6 +99,22 @@
        "PrivateKeyFile" = "8:"
        "TimeStampServer" = "8:"
        "InstallerBootstrapper" = "3:2"
            "BootstrapperCfg:{63ACBE69-63AA-4F98-B2B6-99F9E24495F2}"
            {
            "Enabled" = "11:TRUE"
            "PromptEnabled" = "11:TRUE"
            "PrerequisitesLocation" = "2:1"
            "Url" = "8:"
            "ComponentsUrl" = "8:"
                "Items"
                {
                    "{EDC2488A-8267-493A-A98E-7D9C3B36CDF3}:.NETFramework,Version=v4.7.2"
                    {
                    "Name" = "8:Microsoft .NET Framework 4.7.2 (x86 and x64)"
                    "ProductCode" = "8:.NETFramework,Version=v4.7.2"
                    }
                }
            }
        }
    }
    "Deployable"
@@ -128,10 +136,10 @@
        }
        "File"
        {
            "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_0F6F6FB11BB5B04B2FC88C3DE8F60B3D"
            "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_351E2C6402784AB1BA66DFEA28EA1B15"
            {
            "SourcePath" = "8:VCRUNTIME140D.dll"
            "TargetName" = "8:VCRUNTIME140D.dll"
            "SourcePath" = "8:..\\gmsdk\\lib\\win64\\gmsdk.lib"
            "TargetName" = "8:gmsdk.lib"
            "Tag" = "8:"
            "Folder" = "8:_8A6F5952B3214448ACB2B8EAE71DC5B9"
            "Condition" = "8:"
@@ -145,13 +153,13 @@
            "PackageAs" = "3:1"
            "Register" = "3:1"
            "Exclude" = "11:FALSE"
            "IsDependency" = "11:TRUE"
            "IsDependency" = "11:FALSE"
            "IsolateTo" = "8:"
            }
            "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_5345A483EDAA068D4ECD46E43B44CB14"
            "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_78B761D1C46A47D582FF5FF7A853FFA4"
            {
            "SourcePath" = "8:MSIMG32.dll"
            "TargetName" = "8:MSIMG32.dll"
            "SourcePath" = "8:..\\lib_config\\x64\\libconfig++.dll"
            "TargetName" = "8:libconfig++.dll"
            "Tag" = "8:"
            "Folder" = "8:_8A6F5952B3214448ACB2B8EAE71DC5B9"
            "Condition" = "8:"
@@ -165,13 +173,13 @@
            "PackageAs" = "3:1"
            "Register" = "3:1"
            "Exclude" = "11:FALSE"
            "IsDependency" = "11:TRUE"
            "IsDependency" = "11:FALSE"
            "IsolateTo" = "8:"
            }
            "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_59D015A90A16B1ABD3D979AD6468EDE8"
            "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_9CFF5151D67A47A3995920D4AA159223"
            {
            "SourcePath" = "8:VERSION.dll"
            "TargetName" = "8:VERSION.dll"
            "SourcePath" = "8:..\\CBTrade\\logo.ico"
            "TargetName" = "8:logo.ico"
            "Tag" = "8:"
            "Folder" = "8:_8A6F5952B3214448ACB2B8EAE71DC5B9"
            "Condition" = "8:"
@@ -185,33 +193,13 @@
            "PackageAs" = "3:1"
            "Register" = "3:1"
            "Exclude" = "11:FALSE"
            "IsDependency" = "11:TRUE"
            "IsDependency" = "11:FALSE"
            "IsolateTo" = "8:"
            }
            "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_748C0CFF0B301DD2DF3EE16E835A686C"
            "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_C20E0E53F5FC4235B2E9FDDC48F0AC3F"
            {
            "SourcePath" = "8:UxTheme.dll"
            "TargetName" = "8:UxTheme_.dll"
            "Tag" = "8:"
            "Folder" = "8:_8A6F5952B3214448ACB2B8EAE71DC5B9"
            "Condition" = "8:"
            "Transitive" = "11:FALSE"
            "Vital" = "11:TRUE"
            "ReadOnly" = "11:FALSE"
            "Hidden" = "11:FALSE"
            "System" = "11:FALSE"
            "Permanent" = "11:FALSE"
            "SharedLegacy" = "11:FALSE"
            "PackageAs" = "3:1"
            "Register" = "3:4"
            "Exclude" = "11:TRUE"
            "IsDependency" = "11:TRUE"
            "IsolateTo" = "8:"
            }
            "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_806BCE58ED916D481C2248D65B3D0601"
            {
            "SourcePath" = "8:OLEACC.dll"
            "TargetName" = "8:OLEACC.dll"
            "SourcePath" = "8:..\\gmsdk\\lib\\win64\\gmsdk.dll"
            "TargetName" = "8:gmsdk.dll"
            "Tag" = "8:"
            "Folder" = "8:_8A6F5952B3214448ACB2B8EAE71DC5B9"
            "Condition" = "8:"
@@ -225,13 +213,13 @@
            "PackageAs" = "3:1"
            "Register" = "3:1"
            "Exclude" = "11:FALSE"
            "IsDependency" = "11:TRUE"
            "IsDependency" = "11:FALSE"
            "IsolateTo" = "8:"
            }
            "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_84F38A3DCB9A3927A2AB617FE7FB9F0C"
            "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_DBBBA2E304CC4FF3A410726CC23C0F04"
            {
            "SourcePath" = "8:MSVCP140D.dll"
            "TargetName" = "8:MSVCP140D.dll"
            "SourcePath" = "8:..\\lib_config\\x64\\libconfig++.lib"
            "TargetName" = "8:libconfig++.lib"
            "Tag" = "8:"
            "Folder" = "8:_8A6F5952B3214448ACB2B8EAE71DC5B9"
            "Condition" = "8:"
@@ -245,67 +233,7 @@
            "PackageAs" = "3:1"
            "Register" = "3:1"
            "Exclude" = "11:FALSE"
            "IsDependency" = "11:TRUE"
            "IsolateTo" = "8:"
            }
            "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_8F870806ED5B4E9C1FDBE30D24BB7885"
            {
            "SourcePath" = "8:ucrtbased.dll"
            "TargetName" = "8:ucrtbased.dll"
            "Tag" = "8:"
            "Folder" = "8:_8A6F5952B3214448ACB2B8EAE71DC5B9"
            "Condition" = "8:"
            "Transitive" = "11:FALSE"
            "Vital" = "11:TRUE"
            "ReadOnly" = "11:FALSE"
            "Hidden" = "11:FALSE"
            "System" = "11:FALSE"
            "Permanent" = "11:FALSE"
            "SharedLegacy" = "11:FALSE"
            "PackageAs" = "3:1"
            "Register" = "3:1"
            "Exclude" = "11:FALSE"
            "IsDependency" = "11:TRUE"
            "IsolateTo" = "8:"
            }
            "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_A49EA12BB1477DD472735269247207E0"
            {
            "SourcePath" = "8:RPCRT4.dll"
            "TargetName" = "8:RPCRT4.dll"
            "Tag" = "8:"
            "Folder" = "8:_8A6F5952B3214448ACB2B8EAE71DC5B9"
            "Condition" = "8:"
            "Transitive" = "11:FALSE"
            "Vital" = "11:TRUE"
            "ReadOnly" = "11:FALSE"
            "Hidden" = "11:FALSE"
            "System" = "11:FALSE"
            "Permanent" = "11:FALSE"
            "SharedLegacy" = "11:FALSE"
            "PackageAs" = "3:1"
            "Register" = "3:1"
            "Exclude" = "11:FALSE"
            "IsDependency" = "11:TRUE"
            "IsolateTo" = "8:"
            }
            "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_B345A65FB682CB0D48B8479967B84DF8"
            {
            "SourcePath" = "8:COMDLG32.dll"
            "TargetName" = "8:COMDLG32.dll"
            "Tag" = "8:"
            "Folder" = "8:_8A6F5952B3214448ACB2B8EAE71DC5B9"
            "Condition" = "8:"
            "Transitive" = "11:FALSE"
            "Vital" = "11:TRUE"
            "ReadOnly" = "11:FALSE"
            "Hidden" = "11:FALSE"
            "System" = "11:FALSE"
            "Permanent" = "11:FALSE"
            "SharedLegacy" = "11:FALSE"
            "PackageAs" = "3:1"
            "Register" = "3:1"
            "Exclude" = "11:FALSE"
            "IsDependency" = "11:TRUE"
            "IsDependency" = "11:FALSE"
            "IsolateTo" = "8:"
            }
        }
@@ -364,15 +292,15 @@
        {
        "Name" = "8:Microsoft Visual Studio"
        "ProductName" = "8:可转债交易"
        "ProductCode" = "8:{E5807677-104F-4B02-B41D-0673E2C89C93}"
        "PackageCode" = "8:{EB9C1AD3-23C1-40ED-AF9E-094DF2D3E0B2}"
        "ProductCode" = "8:{D8A9380B-DEDF-40D5-B571-75A5D2C9C6F1}"
        "PackageCode" = "8:{DC79D12F-7BC8-4269-A033-E1FD2ED83B23}"
        "UpgradeCode" = "8:{7AED08B9-77D2-4CCC-84A2-A70E4F56F632}"
        "AspNetVersion" = "8:4.0.30319.0"
        "RestartWWWService" = "11:FALSE"
        "RemovePreviousVersions" = "11:FALSE"
        "DetectNewerInstalledVersion" = "11:TRUE"
        "InstallAllUsers" = "11:FALSE"
        "ProductVersion" = "8:1.0.2"
        "ProductVersion" = "8:1.0.16"
        "Manufacturer" = "8:yeshi"
        "ARPHELPTELEPHONE" = "8:"
        "ARPHELPLINK" = "8:"
@@ -496,7 +424,7 @@
            "Target" = "8:_FFFFDB2ACD1F4C92B11F59958EDA2540"
            "Folder" = "8:_2E737A90AAC8423086D151253B929BC0"
            "WorkingFolder" = "8:_8A6F5952B3214448ACB2B8EAE71DC5B9"
            "Icon" = "8:"
            "Icon" = "8:_9CFF5151D67A47A3995920D4AA159223"
            "Feature" = "8:"
            }
        }
@@ -900,7 +828,7 @@
        {
            "{5259A561-127C-4D43-A0A1-72F10C7B3BF8}:_FFFFDB2ACD1F4C92B11F59958EDA2540"
            {
            "SourcePath" = "8:..\\Debug\\CBTrade.exe"
            "SourcePath" = "8:..\\x64\\Release\\CBTrade.exe"
            "TargetName" = "8:"
            "Tag" = "8:"
            "Folder" = "8:_8A6F5952B3214448ACB2B8EAE71DC5B9"
SetupDelegateQueue/SetupDelegateQueue.vdproj
@@ -21,14 +21,122 @@
        }
        "Entry"
        {
        "MsmKey" = "8:_1363EF3D678BE2295C663A8EF5310B2C"
        "OwnerKey" = "8:_F90404B788AC4087AF60D784E637AD65"
        "MsmSig" = "8:_UNDEFINED"
        }
        "Entry"
        {
        "MsmKey" = "8:_21A7FD9C204969C58CA58F1BF7BDE293"
        "OwnerKey" = "8:_F90404B788AC4087AF60D784E637AD65"
        "MsmSig" = "8:_UNDEFINED"
        }
        "Entry"
        {
        "MsmKey" = "8:_2578ED1FAB7562F055333270704E73CE"
        "OwnerKey" = "8:_F90404B788AC4087AF60D784E637AD65"
        "MsmSig" = "8:_UNDEFINED"
        }
        "Entry"
        {
        "MsmKey" = "8:_2CE4DFFC287966D397D05C94E8AADEE4"
        "OwnerKey" = "8:_F90404B788AC4087AF60D784E637AD65"
        "MsmSig" = "8:_UNDEFINED"
        }
        "Entry"
        {
        "MsmKey" = "8:_33BDD7AE31660A8C9CCBC36F65D1AB58"
        "OwnerKey" = "8:_F90404B788AC4087AF60D784E637AD65"
        "MsmSig" = "8:_UNDEFINED"
        }
        "Entry"
        {
        "MsmKey" = "8:_3B6303C71CEEF3001B06E953C6615B8C"
        "OwnerKey" = "8:_F90404B788AC4087AF60D784E637AD65"
        "MsmSig" = "8:_UNDEFINED"
        }
        "Entry"
        {
        "MsmKey" = "8:_43E1818F5A404EB2D0E61D0D5108F894"
        "OwnerKey" = "8:_F90404B788AC4087AF60D784E637AD65"
        "MsmSig" = "8:_UNDEFINED"
        }
        "Entry"
        {
        "MsmKey" = "8:_48DFEB5F8CD76FB301C4A8D95FB25736"
        "OwnerKey" = "8:_F90404B788AC4087AF60D784E637AD65"
        "MsmSig" = "8:_UNDEFINED"
        }
        "Entry"
        {
        "MsmKey" = "8:_5B12CF05354C46439C741376BE82F040"
        "OwnerKey" = "8:_UNDEFINED"
        "MsmSig" = "8:_UNDEFINED"
        }
        "Entry"
        {
        "MsmKey" = "8:_5E425828EC446A62AF151B593F600AEF"
        "OwnerKey" = "8:_F90404B788AC4087AF60D784E637AD65"
        "MsmSig" = "8:_UNDEFINED"
        }
        "Entry"
        {
        "MsmKey" = "8:_653E5CB6193FF54008F84A7F20A34E0E"
        "OwnerKey" = "8:_F90404B788AC4087AF60D784E637AD65"
        "MsmSig" = "8:_UNDEFINED"
        }
        "Entry"
        {
        "MsmKey" = "8:_8CAA875C2A43AB861E47C96176ADF4D7"
        "OwnerKey" = "8:_F90404B788AC4087AF60D784E637AD65"
        "MsmSig" = "8:_UNDEFINED"
        }
        "Entry"
        {
        "MsmKey" = "8:_9F52C026C48ECA02499B97222CFCEA57"
        "OwnerKey" = "8:_F90404B788AC4087AF60D784E637AD65"
        "MsmSig" = "8:_UNDEFINED"
        }
        "Entry"
        {
        "MsmKey" = "8:_9F5B7DBE4B9E956A15039C5613B1CE18"
        "OwnerKey" = "8:_F90404B788AC4087AF60D784E637AD65"
        "MsmSig" = "8:_UNDEFINED"
        }
        "Entry"
        {
        "MsmKey" = "8:_B88B5AC28A97048575656A10A2703EA2"
        "OwnerKey" = "8:_F90404B788AC4087AF60D784E637AD65"
        "MsmSig" = "8:_UNDEFINED"
        }
        "Entry"
        {
        "MsmKey" = "8:_D6F02B1CED3FCF3EE03D11CF3150890A"
        "OwnerKey" = "8:_F90404B788AC4087AF60D784E637AD65"
        "MsmSig" = "8:_UNDEFINED"
        }
        "Entry"
        {
        "MsmKey" = "8:_DB7B2490A88F29E995A2CA61BD34D4F9"
        "OwnerKey" = "8:_F90404B788AC4087AF60D784E637AD65"
        "MsmSig" = "8:_UNDEFINED"
        }
        "Entry"
        {
        "MsmKey" = "8:_F76A847C8D8ACCAB20FC72B9298CB00D"
        "OwnerKey" = "8:_F90404B788AC4087AF60D784E637AD65"
        "MsmSig" = "8:_UNDEFINED"
        }
        "Entry"
        {
        "MsmKey" = "8:_F90404B788AC4087AF60D784E637AD65"
        "OwnerKey" = "8:_UNDEFINED"
        "MsmSig" = "8:_UNDEFINED"
        }
        "Entry"
        {
        "MsmKey" = "8:_FEAFFB9DDDC2B5318A096A2F4B98BC63"
        "OwnerKey" = "8:_F90404B788AC4087AF60D784E637AD65"
        "MsmSig" = "8:_UNDEFINED"
        }
    }
@@ -138,6 +246,166 @@
            "IsDependency" = "11:FALSE"
            "IsolateTo" = "8:"
            }
            "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_1363EF3D678BE2295C663A8EF5310B2C"
            {
            "SourcePath" = "8:api-ms-win-crt-time-l1-1-0.dll"
            "TargetName" = "8:api-ms-win-crt-time-l1-1-0.dll"
            "Tag" = "8:"
            "Folder" = "8:_4EA0775CF71F431190DF96911735DD19"
            "Condition" = "8:"
            "Transitive" = "11:FALSE"
            "Vital" = "11:TRUE"
            "ReadOnly" = "11:FALSE"
            "Hidden" = "11:FALSE"
            "System" = "11:FALSE"
            "Permanent" = "11:FALSE"
            "SharedLegacy" = "11:FALSE"
            "PackageAs" = "3:1"
            "Register" = "3:1"
            "Exclude" = "11:FALSE"
            "IsDependency" = "11:TRUE"
            "IsolateTo" = "8:"
            }
            "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_21A7FD9C204969C58CA58F1BF7BDE293"
            {
            "SourcePath" = "8:api-ms-win-crt-runtime-l1-1-0.dll"
            "TargetName" = "8:api-ms-win-crt-runtime-l1-1-0.dll"
            "Tag" = "8:"
            "Folder" = "8:_4EA0775CF71F431190DF96911735DD19"
            "Condition" = "8:"
            "Transitive" = "11:FALSE"
            "Vital" = "11:TRUE"
            "ReadOnly" = "11:FALSE"
            "Hidden" = "11:FALSE"
            "System" = "11:FALSE"
            "Permanent" = "11:FALSE"
            "SharedLegacy" = "11:FALSE"
            "PackageAs" = "3:1"
            "Register" = "3:1"
            "Exclude" = "11:FALSE"
            "IsDependency" = "11:TRUE"
            "IsolateTo" = "8:"
            }
            "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_2578ED1FAB7562F055333270704E73CE"
            {
            "SourcePath" = "8:OLEACC.dll"
            "TargetName" = "8:OLEACC.dll"
            "Tag" = "8:"
            "Folder" = "8:_4EA0775CF71F431190DF96911735DD19"
            "Condition" = "8:"
            "Transitive" = "11:FALSE"
            "Vital" = "11:TRUE"
            "ReadOnly" = "11:FALSE"
            "Hidden" = "11:FALSE"
            "System" = "11:FALSE"
            "Permanent" = "11:FALSE"
            "SharedLegacy" = "11:FALSE"
            "PackageAs" = "3:1"
            "Register" = "3:1"
            "Exclude" = "11:FALSE"
            "IsDependency" = "11:TRUE"
            "IsolateTo" = "8:"
            }
            "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_2CE4DFFC287966D397D05C94E8AADEE4"
            {
            "SourcePath" = "8:api-ms-win-crt-locale-l1-1-0.dll"
            "TargetName" = "8:api-ms-win-crt-locale-l1-1-0.dll"
            "Tag" = "8:"
            "Folder" = "8:_4EA0775CF71F431190DF96911735DD19"
            "Condition" = "8:"
            "Transitive" = "11:FALSE"
            "Vital" = "11:TRUE"
            "ReadOnly" = "11:FALSE"
            "Hidden" = "11:FALSE"
            "System" = "11:FALSE"
            "Permanent" = "11:FALSE"
            "SharedLegacy" = "11:FALSE"
            "PackageAs" = "3:1"
            "Register" = "3:1"
            "Exclude" = "11:FALSE"
            "IsDependency" = "11:TRUE"
            "IsolateTo" = "8:"
            }
            "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_33BDD7AE31660A8C9CCBC36F65D1AB58"
            {
            "SourcePath" = "8:api-ms-win-crt-filesystem-l1-1-0.dll"
            "TargetName" = "8:api-ms-win-crt-filesystem-l1-1-0.dll"
            "Tag" = "8:"
            "Folder" = "8:_4EA0775CF71F431190DF96911735DD19"
            "Condition" = "8:"
            "Transitive" = "11:FALSE"
            "Vital" = "11:TRUE"
            "ReadOnly" = "11:FALSE"
            "Hidden" = "11:FALSE"
            "System" = "11:FALSE"
            "Permanent" = "11:FALSE"
            "SharedLegacy" = "11:FALSE"
            "PackageAs" = "3:1"
            "Register" = "3:1"
            "Exclude" = "11:FALSE"
            "IsDependency" = "11:TRUE"
            "IsolateTo" = "8:"
            }
            "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_3B6303C71CEEF3001B06E953C6615B8C"
            {
            "SourcePath" = "8:COMDLG32.dll"
            "TargetName" = "8:COMDLG32.dll"
            "Tag" = "8:"
            "Folder" = "8:_4EA0775CF71F431190DF96911735DD19"
            "Condition" = "8:"
            "Transitive" = "11:FALSE"
            "Vital" = "11:TRUE"
            "ReadOnly" = "11:FALSE"
            "Hidden" = "11:FALSE"
            "System" = "11:FALSE"
            "Permanent" = "11:FALSE"
            "SharedLegacy" = "11:FALSE"
            "PackageAs" = "3:1"
            "Register" = "3:1"
            "Exclude" = "11:FALSE"
            "IsDependency" = "11:TRUE"
            "IsolateTo" = "8:"
            }
            "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_43E1818F5A404EB2D0E61D0D5108F894"
            {
            "SourcePath" = "8:api-ms-win-crt-environment-l1-1-0.dll"
            "TargetName" = "8:api-ms-win-crt-environment-l1-1-0.dll"
            "Tag" = "8:"
            "Folder" = "8:_4EA0775CF71F431190DF96911735DD19"
            "Condition" = "8:"
            "Transitive" = "11:FALSE"
            "Vital" = "11:TRUE"
            "ReadOnly" = "11:FALSE"
            "Hidden" = "11:FALSE"
            "System" = "11:FALSE"
            "Permanent" = "11:FALSE"
            "SharedLegacy" = "11:FALSE"
            "PackageAs" = "3:1"
            "Register" = "3:1"
            "Exclude" = "11:FALSE"
            "IsDependency" = "11:TRUE"
            "IsolateTo" = "8:"
            }
            "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_48DFEB5F8CD76FB301C4A8D95FB25736"
            {
            "SourcePath" = "8:api-ms-win-crt-math-l1-1-0.dll"
            "TargetName" = "8:api-ms-win-crt-math-l1-1-0.dll"
            "Tag" = "8:"
            "Folder" = "8:_4EA0775CF71F431190DF96911735DD19"
            "Condition" = "8:"
            "Transitive" = "11:FALSE"
            "Vital" = "11:TRUE"
            "ReadOnly" = "11:FALSE"
            "Hidden" = "11:FALSE"
            "System" = "11:FALSE"
            "Permanent" = "11:FALSE"
            "SharedLegacy" = "11:FALSE"
            "PackageAs" = "3:1"
            "Register" = "3:1"
            "Exclude" = "11:FALSE"
            "IsDependency" = "11:TRUE"
            "IsolateTo" = "8:"
            }
            "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_5B12CF05354C46439C741376BE82F040"
            {
            "SourcePath" = "8:..\\DelegateQueue\\icon.ico"
@@ -156,6 +424,206 @@
            "Register" = "3:1"
            "Exclude" = "11:FALSE"
            "IsDependency" = "11:FALSE"
            "IsolateTo" = "8:"
            }
            "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_5E425828EC446A62AF151B593F600AEF"
            {
            "SourcePath" = "8:VCRUNTIME140.dll"
            "TargetName" = "8:VCRUNTIME140.dll"
            "Tag" = "8:"
            "Folder" = "8:_4EA0775CF71F431190DF96911735DD19"
            "Condition" = "8:"
            "Transitive" = "11:FALSE"
            "Vital" = "11:TRUE"
            "ReadOnly" = "11:FALSE"
            "Hidden" = "11:FALSE"
            "System" = "11:FALSE"
            "Permanent" = "11:FALSE"
            "SharedLegacy" = "11:FALSE"
            "PackageAs" = "3:1"
            "Register" = "3:1"
            "Exclude" = "11:FALSE"
            "IsDependency" = "11:TRUE"
            "IsolateTo" = "8:"
            }
            "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_653E5CB6193FF54008F84A7F20A34E0E"
            {
            "SourcePath" = "8:MSVCP140.dll"
            "TargetName" = "8:MSVCP140.dll"
            "Tag" = "8:"
            "Folder" = "8:_4EA0775CF71F431190DF96911735DD19"
            "Condition" = "8:"
            "Transitive" = "11:FALSE"
            "Vital" = "11:TRUE"
            "ReadOnly" = "11:FALSE"
            "Hidden" = "11:FALSE"
            "System" = "11:FALSE"
            "Permanent" = "11:FALSE"
            "SharedLegacy" = "11:FALSE"
            "PackageAs" = "3:1"
            "Register" = "3:1"
            "Exclude" = "11:FALSE"
            "IsDependency" = "11:TRUE"
            "IsolateTo" = "8:"
            }
            "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_8CAA875C2A43AB861E47C96176ADF4D7"
            {
            "SourcePath" = "8:RPCRT4.dll"
            "TargetName" = "8:RPCRT4.dll"
            "Tag" = "8:"
            "Folder" = "8:_4EA0775CF71F431190DF96911735DD19"
            "Condition" = "8:"
            "Transitive" = "11:FALSE"
            "Vital" = "11:TRUE"
            "ReadOnly" = "11:FALSE"
            "Hidden" = "11:FALSE"
            "System" = "11:FALSE"
            "Permanent" = "11:FALSE"
            "SharedLegacy" = "11:FALSE"
            "PackageAs" = "3:1"
            "Register" = "3:1"
            "Exclude" = "11:FALSE"
            "IsDependency" = "11:TRUE"
            "IsolateTo" = "8:"
            }
            "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_9F52C026C48ECA02499B97222CFCEA57"
            {
            "SourcePath" = "8:api-ms-win-crt-heap-l1-1-0.dll"
            "TargetName" = "8:api-ms-win-crt-heap-l1-1-0.dll"
            "Tag" = "8:"
            "Folder" = "8:_4EA0775CF71F431190DF96911735DD19"
            "Condition" = "8:"
            "Transitive" = "11:FALSE"
            "Vital" = "11:TRUE"
            "ReadOnly" = "11:FALSE"
            "Hidden" = "11:FALSE"
            "System" = "11:FALSE"
            "Permanent" = "11:FALSE"
            "SharedLegacy" = "11:FALSE"
            "PackageAs" = "3:1"
            "Register" = "3:1"
            "Exclude" = "11:FALSE"
            "IsDependency" = "11:TRUE"
            "IsolateTo" = "8:"
            }
            "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_9F5B7DBE4B9E956A15039C5613B1CE18"
            {
            "SourcePath" = "8:MSIMG32.dll"
            "TargetName" = "8:MSIMG32.dll"
            "Tag" = "8:"
            "Folder" = "8:_4EA0775CF71F431190DF96911735DD19"
            "Condition" = "8:"
            "Transitive" = "11:FALSE"
            "Vital" = "11:TRUE"
            "ReadOnly" = "11:FALSE"
            "Hidden" = "11:FALSE"
            "System" = "11:FALSE"
            "Permanent" = "11:FALSE"
            "SharedLegacy" = "11:FALSE"
            "PackageAs" = "3:1"
            "Register" = "3:1"
            "Exclude" = "11:FALSE"
            "IsDependency" = "11:TRUE"
            "IsolateTo" = "8:"
            }
            "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_B88B5AC28A97048575656A10A2703EA2"
            {
            "SourcePath" = "8:UxTheme.dll"
            "TargetName" = "8:UxTheme.dll"
            "Tag" = "8:"
            "Folder" = "8:_4EA0775CF71F431190DF96911735DD19"
            "Condition" = "8:"
            "Transitive" = "11:FALSE"
            "Vital" = "11:TRUE"
            "ReadOnly" = "11:FALSE"
            "Hidden" = "11:FALSE"
            "System" = "11:FALSE"
            "Permanent" = "11:FALSE"
            "SharedLegacy" = "11:FALSE"
            "PackageAs" = "3:1"
            "Register" = "3:4"
            "Exclude" = "11:FALSE"
            "IsDependency" = "11:TRUE"
            "IsolateTo" = "8:"
            }
            "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_D6F02B1CED3FCF3EE03D11CF3150890A"
            {
            "SourcePath" = "8:api-ms-win-crt-string-l1-1-0.dll"
            "TargetName" = "8:api-ms-win-crt-string-l1-1-0.dll"
            "Tag" = "8:"
            "Folder" = "8:_4EA0775CF71F431190DF96911735DD19"
            "Condition" = "8:"
            "Transitive" = "11:FALSE"
            "Vital" = "11:TRUE"
            "ReadOnly" = "11:FALSE"
            "Hidden" = "11:FALSE"
            "System" = "11:FALSE"
            "Permanent" = "11:FALSE"
            "SharedLegacy" = "11:FALSE"
            "PackageAs" = "3:1"
            "Register" = "3:1"
            "Exclude" = "11:FALSE"
            "IsDependency" = "11:TRUE"
            "IsolateTo" = "8:"
            }
            "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_DB7B2490A88F29E995A2CA61BD34D4F9"
            {
            "SourcePath" = "8:api-ms-win-crt-stdio-l1-1-0.dll"
            "TargetName" = "8:api-ms-win-crt-stdio-l1-1-0.dll"
            "Tag" = "8:"
            "Folder" = "8:_4EA0775CF71F431190DF96911735DD19"
            "Condition" = "8:"
            "Transitive" = "11:FALSE"
            "Vital" = "11:TRUE"
            "ReadOnly" = "11:FALSE"
            "Hidden" = "11:FALSE"
            "System" = "11:FALSE"
            "Permanent" = "11:FALSE"
            "SharedLegacy" = "11:FALSE"
            "PackageAs" = "3:1"
            "Register" = "3:1"
            "Exclude" = "11:FALSE"
            "IsDependency" = "11:TRUE"
            "IsolateTo" = "8:"
            }
            "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_F76A847C8D8ACCAB20FC72B9298CB00D"
            {
            "SourcePath" = "8:api-ms-win-crt-convert-l1-1-0.dll"
            "TargetName" = "8:api-ms-win-crt-convert-l1-1-0.dll"
            "Tag" = "8:"
            "Folder" = "8:_4EA0775CF71F431190DF96911735DD19"
            "Condition" = "8:"
            "Transitive" = "11:FALSE"
            "Vital" = "11:TRUE"
            "ReadOnly" = "11:FALSE"
            "Hidden" = "11:FALSE"
            "System" = "11:FALSE"
            "Permanent" = "11:FALSE"
            "SharedLegacy" = "11:FALSE"
            "PackageAs" = "3:1"
            "Register" = "3:1"
            "Exclude" = "11:FALSE"
            "IsDependency" = "11:TRUE"
            "IsolateTo" = "8:"
            }
            "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_FEAFFB9DDDC2B5318A096A2F4B98BC63"
            {
            "SourcePath" = "8:api-ms-win-crt-utility-l1-1-0.dll"
            "TargetName" = "8:api-ms-win-crt-utility-l1-1-0.dll"
            "Tag" = "8:"
            "Folder" = "8:_4EA0775CF71F431190DF96911735DD19"
            "Condition" = "8:"
            "Transitive" = "11:FALSE"
            "Vital" = "11:TRUE"
            "ReadOnly" = "11:FALSE"
            "Hidden" = "11:FALSE"
            "System" = "11:FALSE"
            "Permanent" = "11:FALSE"
            "SharedLegacy" = "11:FALSE"
            "PackageAs" = "3:1"
            "Register" = "3:1"
            "Exclude" = "11:FALSE"
            "IsDependency" = "11:TRUE"
            "IsolateTo" = "8:"
            }
        }
@@ -214,15 +682,15 @@
        {
        "Name" = "8:Microsoft Visual Studio"
        "ProductName" = "8:加贝控制中心"
        "ProductCode" = "8:{9587EF51-BE60-4CD7-B9D3-BAB49B2753B6}"
        "PackageCode" = "8:{0340833E-FA61-4054-B31D-2EB066D049CF}"
        "ProductCode" = "8:{1E9B7BC6-51CD-46DE-9CB5-9B19EAB574DF}"
        "PackageCode" = "8:{3262651E-838E-4856-964A-99E45988FE16}"
        "UpgradeCode" = "8:{AF39AD88-3496-4F57-94FF-39A72C912FB3}"
        "AspNetVersion" = "8:4.0.30319.0"
        "RestartWWWService" = "11:FALSE"
        "RemovePreviousVersions" = "11:FALSE"
        "DetectNewerInstalledVersion" = "11:TRUE"
        "InstallAllUsers" = "11:FALSE"
        "ProductVersion" = "8:1.2.0"
        "ProductVersion" = "8:1.2.7"
        "Manufacturer" = "8:yeshi"
        "ARPHELPTELEPHONE" = "8:"
        "ARPHELPLINK" = "8:"
TradeDesk.sln
@@ -17,6 +17,14 @@
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AndroidChannelPackage", "AndroidChannelPackage\AndroidChannelPackage.vcxproj", "{20E052B6-33FB-4495-A337-62CB70306CC7}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CBTrade", "CBTrade\CBTrade.vcxproj", "{8BFF1459-65B0-4A91-B278-D1EF8FA3E031}"
EndProject
Project("{54435603-DBB4-11D2-8724-00A0C9A8B90C}") = "SetupCBTrade", "SetupCBTrade\SetupCBTrade.vdproj", "{8251B028-53A6-4DC7-97DB-067F036883D5}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DelegateQueue", "DelegateQueue\DelegateQueue.vcxproj", "{E145394E-FF3E-4C4A-B76E-19C4E70153AF}"
EndProject
Project("{54435603-DBB4-11D2-8724-00A0C9A8B90C}") = "SetupDelegateQueue", "SetupDelegateQueue\SetupDelegateQueue.vdproj", "{20F1D622-53F8-4BC8-855E-468DFA7D7FFD}"
EndProject
Global
    GlobalSection(SolutionConfigurationPlatforms) = preSolution
        Debug|x64 = Debug|x64
@@ -69,6 +77,30 @@
        {20E052B6-33FB-4495-A337-62CB70306CC7}.Release|x64.Build.0 = Release|x64
        {20E052B6-33FB-4495-A337-62CB70306CC7}.Release|x86.ActiveCfg = Release|Win32
        {20E052B6-33FB-4495-A337-62CB70306CC7}.Release|x86.Build.0 = Release|Win32
        {8BFF1459-65B0-4A91-B278-D1EF8FA3E031}.Debug|x64.ActiveCfg = Debug|x64
        {8BFF1459-65B0-4A91-B278-D1EF8FA3E031}.Debug|x64.Build.0 = Debug|x64
        {8BFF1459-65B0-4A91-B278-D1EF8FA3E031}.Debug|x86.ActiveCfg = Debug|Win32
        {8BFF1459-65B0-4A91-B278-D1EF8FA3E031}.Debug|x86.Build.0 = Debug|Win32
        {8BFF1459-65B0-4A91-B278-D1EF8FA3E031}.Release|x64.ActiveCfg = Release|x64
        {8BFF1459-65B0-4A91-B278-D1EF8FA3E031}.Release|x64.Build.0 = Release|x64
        {8BFF1459-65B0-4A91-B278-D1EF8FA3E031}.Release|x86.ActiveCfg = Release|Win32
        {8BFF1459-65B0-4A91-B278-D1EF8FA3E031}.Release|x86.Build.0 = Release|Win32
        {8251B028-53A6-4DC7-97DB-067F036883D5}.Debug|x64.ActiveCfg = Debug
        {8251B028-53A6-4DC7-97DB-067F036883D5}.Debug|x86.ActiveCfg = Debug
        {8251B028-53A6-4DC7-97DB-067F036883D5}.Release|x64.ActiveCfg = Release
        {8251B028-53A6-4DC7-97DB-067F036883D5}.Release|x86.ActiveCfg = Release
        {E145394E-FF3E-4C4A-B76E-19C4E70153AF}.Debug|x64.ActiveCfg = Debug|x64
        {E145394E-FF3E-4C4A-B76E-19C4E70153AF}.Debug|x64.Build.0 = Debug|x64
        {E145394E-FF3E-4C4A-B76E-19C4E70153AF}.Debug|x86.ActiveCfg = Debug|Win32
        {E145394E-FF3E-4C4A-B76E-19C4E70153AF}.Debug|x86.Build.0 = Debug|Win32
        {E145394E-FF3E-4C4A-B76E-19C4E70153AF}.Release|x64.ActiveCfg = Release|x64
        {E145394E-FF3E-4C4A-B76E-19C4E70153AF}.Release|x64.Build.0 = Release|x64
        {E145394E-FF3E-4C4A-B76E-19C4E70153AF}.Release|x86.ActiveCfg = Release|Win32
        {E145394E-FF3E-4C4A-B76E-19C4E70153AF}.Release|x86.Build.0 = Release|Win32
        {20F1D622-53F8-4BC8-855E-468DFA7D7FFD}.Debug|x64.ActiveCfg = Debug
        {20F1D622-53F8-4BC8-855E-468DFA7D7FFD}.Debug|x86.ActiveCfg = Debug
        {20F1D622-53F8-4BC8-855E-468DFA7D7FFD}.Release|x64.ActiveCfg = Release
        {20F1D622-53F8-4BC8-855E-468DFA7D7FFD}.Release|x86.ActiveCfg = Release
    EndGlobalSection
    GlobalSection(SolutionProperties) = preSolution
        HideSolutionNode = FALSE
common/NetworkApi.cpp
@@ -1149,6 +1149,79 @@
    return result;
}
string NetworkApi::sync_zylt_volume()
{
    rapidjson::StringBuffer buf;
    rapidjson::PrettyWriter<rapidjson::StringBuffer> writer(buf);
    writer.StartObject();
    writer.Key("type");
    writer.String("common");
    writer.Key("data");
    writer.StartObject();
    writer.Key("ctype");
    writer.String("refresh_zylt_volume");
    writer.EndObject();
    writer.EndObject();
    const char* json_content = buf.GetString();
    string result = base_request(std::string(json_content));
    return result;
}
string NetworkApi::get_today_updated_zylt_volume_count()
{
    rapidjson::StringBuffer buf;
    rapidjson::PrettyWriter<rapidjson::StringBuffer> writer(buf);
    writer.StartObject();
    writer.Key("type");
    writer.String("common");
    writer.Key("data");
    writer.StartObject();
    writer.Key("ctype");
    writer.String("get_today_updated_zylt_volume_count");
    writer.EndObject();
    writer.EndObject();
    const char* json_content = buf.GetString();
    string result = base_request(std::string(json_content));
    return result;
}
string NetworkApi::sync_history_k_bars()
{
    rapidjson::StringBuffer buf;
    rapidjson::PrettyWriter<rapidjson::StringBuffer> writer(buf);
    writer.StartObject();
    writer.Key("type");
    writer.String("common");
    writer.Key("data");
    writer.StartObject();
    writer.Key("ctype");
    writer.String("update_history_k_bars");
    writer.EndObject();
    writer.EndObject();
    const char* json_content = buf.GetString();
    string result = base_request(std::string(json_content));
    return result;
}
string NetworkApi::get_today_updated_history_k_bars_count()
{
    rapidjson::StringBuffer buf;
    rapidjson::PrettyWriter<rapidjson::StringBuffer> writer(buf);
    writer.StartObject();
    writer.Key("type");
    writer.String("common");
    writer.Key("data");
    writer.StartObject();
    writer.Key("ctype");
    writer.String("get_history_bars_codes_count");
    writer.EndObject();
    writer.EndObject();
    const char* json_content = buf.GetString();
    string result = base_request(std::string(json_content));
    return result;
}
string NetworkApi::list_delegate_records(CString updateTime,bool canCancel)
{
    rapidjson::StringBuffer buf;
common/NetworkApi.h
@@ -218,8 +218,16 @@
    static string repaire_task();
    
    // åŒæ­¥è‡ªç”±æµé€šé‡
    static string sync_zylt_volume();
    
    // èŽ·å–ä»Šæ—¥å·²ç»æ›´æ–°çš„è‡ªç”±æµé€šé‡çš„æ•°é‡
    static string get_today_updated_zylt_volume_count();
    // åŒæ­¥åŽ†å²K线数据
    static string sync_history_k_bars();
    // èŽ·å–ä»Šæ—¥å·²ç»æ›´æ–°çš„K线的数据
    static string get_today_updated_history_k_bars_count();
};
common/Win32Util.cpp
@@ -112,6 +112,11 @@
    SetFocus(hwnd);
}
bool Win32Util::hasFocus(HWND hwnd)
{
    return GetFocus() ==hwnd;
}
//键盘输入数字
common/Win32Util.h
@@ -26,6 +26,9 @@
    //获取焦点
    static void focus(HWND hwnd);
    // æ˜¯å¦æœ‰ç„¦ç‚¹
    static bool hasFocus(HWND hwnd);
    //键盘输入数字
    static void keyboardNum(string num, int delay=0);
common_nopch/StringUtil.h
@@ -35,9 +35,9 @@
    }
    static string to_string(double val) {
    static string to_string(double val,int precision = 2) {
        std::stringstream stream;
        stream << std::fixed << std::setprecision(2) << val;
        stream << std::fixed << std::setprecision(precision) << val;
        return stream.str();
    }
common_nopch/TimeUtil.h
@@ -4,13 +4,25 @@
public:
    // èŽ·å–å½“å‰æ—¶é—´æˆ³
    static UINT16 getNowTimeStamp() {
    static long getNowTimeStamp() {
        auto now = std::chrono::system_clock::now();
        // è½¬æ¢ä¸ºæ—¶é—´æˆ³
        auto now_ms = std::chrono::time_point_cast<std::chrono::milliseconds>(now);
        // èŽ·å–æ—¶é—´æˆ³å€¼
        auto value = now_ms.time_since_epoch().count();
        return value;
        auto now_s = std::chrono::duration_cast<std::chrono::seconds>(now.time_since_epoch()).count();
        return now_s;
    }
    static string format(long timestamp, string format="%Y-%m-%d %H:%M:%S") {
        time_t rawtime = static_cast<time_t>(timestamp);
        // ä½¿ç”¨localtime函数将time_t类型转换为struct tm结构体,获取本地时间
        struct tm* timeinfo;
        timeinfo = localtime(&rawtime);
        char buffer[80];
        strftime(buffer, sizeof(buffer), format.c_str(), timeinfo);
        // å°†char数组转换为string
        return std::string(buffer);
    }
common_nopch/WidgetsRenderUtil.cpp
@@ -293,7 +293,7 @@
    return 0;
}
void WidgetsRenderUtil::drawBtn(wxDC* dc, wxString st, wxRect rect, wxColour textColor, wxColour bgColor)
void WidgetsRenderUtil::drawBtn(wxDC* dc, wxString st, wxRect rect, wxColour textColor, wxColour bgColor, wxAlignment align)
{
    // ç»˜åˆ¶æŒ‰é’®
    dc->SetPen(bgColor);
@@ -301,7 +301,7 @@
    dc->SetTextForeground(textColor);
    dc->DrawRectangle(rect);
    // ç»˜åˆ¶æŒ‰é’®çš„æ–‡æœ¬
    dc->DrawLabel(st, rect, wxALIGN_CENTER);
    dc->DrawLabel(st, rect, align);
}
void WidgetsRenderUtil::drawBtnByGC(wxGraphicsContext* gc, wxString st, wxRect rect, wxColour textColor, wxColour bgColor)
common_nopch/WidgetsRenderUtil.h
@@ -25,7 +25,7 @@
    static int drawText(wxGraphicsContext* gc, wxString st, wxPoint startP, int lineWidth, int lineHeight, std::list<ColorIndexInfo> colors = std::list<ColorIndexInfo>(), wxColour defaultColor = *wxBLACK);
    // ç»˜åˆ¶æŒ‰é’®
    static void drawBtn(wxDC* dc, wxString st, wxRect rect,wxColour textColor, wxColour bgColor);
    static void drawBtn(wxDC* dc, wxString st, wxRect rect,wxColour textColor, wxColour bgColor, wxAlignment align = wxALIGN_CENTER);
    // ç»˜åˆ¶æŒ‰é’®
    static void drawBtnByGC(wxGraphicsContext* gc, wxString st, wxRect rect, wxColour textColor, wxColour bgColor);
common_nopch/Win32Util.cpp
@@ -285,7 +285,7 @@
    }
    input_num(origin_hwnd, code.substr(0, 1));
    Sleep(100);
    Sleep(200);
    hwnds.clear();
    HWND topHwnd = GetDesktopWindow();
@@ -293,7 +293,12 @@
    HWND temp = 0;
    int f_count = 0;
    while (TRUE) {
        if (f_count > 100000) {
            break;
        }
        f_count += 1;
        if (temp > 0 && isWindowShow(temp)) {
            string className = getClassName(temp);
            if (className.find("Afx:") == 0) {
hqChart/dll/HQChart_Dll.dll
Binary files differ
hqChart/dll/HQChart_Dll.lib
Binary files differ
hqChart/dll/HQChart_Dll.pdb
Binary files differ
hqChart/dll/libcrypto-1_1-x64.dll
Binary files differ
hqChart/dll/libssl-1_1-x64.dll
Binary files differ
hqChart/include/HQChart.Dll.h
New file
@@ -0,0 +1,109 @@
#pragma once
#ifdef _WIN32
#ifdef HQCHART_DLL_EXPORTS
#define HQCHART_DLL_API extern "C" __declspec(dllexport)
#else
#define HQCHART_DLL_API extern "C" __declspec(dllimport)
#endif
#else
#define HQCHART_DLL_API extern "C"
#endif
#include "HQChart.KLineData.h"
#pragma pack(push,1)
//K线数据
typedef HQChart::Complier::HISTORY_ITEM HQCHART_KDATA;
typedef HQChart::Complier::KDATA_INFO HQCHART_KDATA_INFO;
typedef struct tagHQChartKDataResult
{
    HQCHART_KDATA*     _pData;
    int                _lCount;
    wchar_t*        _pszName;        //股票名称
    bool            _bResult;
    wchar_t*        _pszError;
    int                _lPeriod;        //周期
    int                _lRight;        //复权
    int                _exData[4];
}HQCHART_KDATA_RESULT, * PHQCHART_KDATA_RESULT;
typedef struct tagValueItem
{
    double  _dValue;
    long    _lDate;
    long    _lTime;
    char    _exData[6];
}VALUE_ITEM, * PVALUE_ITEM;
typedef struct tagHQChartValueResult
{
    int _lType;    //0=单值 1=数组 2=带日期的需要自己拟合数据
    //单值
    double _dValue;
    //数组数据
    VALUE_ITEM* _pData;
    int            _lCount;
    bool        _bResult;
    wchar_t*    _pszError;
}HQCHART_VALUE_RESULT,*PHQCHART_VALUE_RESULT;
typedef struct tagCustomFunctionArgment
{
    double    _dValue[20];
    int        _lCount;
}CUSTOM_FUNCTION_ARGUMENT,*PCUSTOM_FUNCTION_ARGUMENT;
typedef bool(_stdcall *pHQChart_LoadKData)(const wchar_t* lpSymbol, long lPeriod, long lRight, HQCHART_KDATA_RESULT* pResult, const wchar_t* pstrGuid);
typedef bool(_stdcall *pHQChart_LoadKData2)(const wchar_t* lpSymbol, long lPeriod, long lRight, const wchar_t* lpCallInfo, const HQCHART_KDATA_INFO* kDataInfo, HQCHART_KDATA_RESULT* pResult, const wchar_t* pstrGuid);
typedef bool(_stdcall *pHQChart_GetDataByNumber)(const wchar_t* lpSymbol, const wchar_t* pFunctionName, long lParam, long lPeriod, long lRight, const HQCHART_KDATA_INFO* pKDataInfo, HQCHART_VALUE_RESULT* pResult, const wchar_t* pstrGuid);
typedef bool(_stdcall *pHQChart_GetDataByNumbers)(const wchar_t* lpSymbol, const wchar_t* pFunctionName, const CUSTOM_FUNCTION_ARGUMENT* pArgument,  long lPeriod, long lRight, const HQCHART_KDATA_INFO* pKDataInfo, HQCHART_VALUE_RESULT* pResult, const wchar_t* pstrGuid);
typedef bool(_stdcall *pHQChart_GetDataByName)(const wchar_t* lpSymbol, const wchar_t* pFunctionName, long lPeriod, long lRight, const HQCHART_KDATA_INFO* pKDataInfo, HQCHART_VALUE_RESULT* pResult, const wchar_t* pstrGuid);
typedef const wchar_t* (_stdcall* pHQChart_GetIndexScript)(const wchar_t* lpName, const wchar_t* lpCallInfo, const wchar_t* pstrGuid);
typedef void(_stdcall *pHQChart_Success)(const wchar_t* lpSymbol, const wchar_t* lpJSResul, const wchar_t* pstrGuidt);
typedef void(_stdcall *pHQChart_Failed)(const wchar_t* lpCode, const wchar_t* lpSymbol, const wchar_t* lpError, const wchar_t* pstrGuid);
typedef bool(_stdcall* pHQChart_Test)(const wchar_t* lpSymbol);
typedef struct HQCHART_CALLBACK_PTR
{
    pHQChart_LoadKData            _pLoadKData;
    pHQChart_LoadKData2            _pLoadKData2;
    pHQChart_GetDataByNumber    _pGetDataByNumber;
    pHQChart_GetDataByNumbers    _pGetDataByNumbers;
    pHQChart_GetDataByName        _pGetDataByName;
    pHQChart_GetIndexScript        _pGetIndexScript;
    pHQChart_Success            _pSuccess;
    pHQChart_Failed                _pFailed;
    pHQChart_Test                _pTest;
}HQCHART_CALLBACK_PTR,*PHQCHART_CALLBACK_PTR;
#pragma pack(pop)
HQCHART_DLL_API bool __stdcall Run(const wchar_t* pJonsConfig, HQCHART_CALLBACK_PTR callback);
HQCHART_DLL_API bool __stdcall Authorize(const wchar_t* pContent);    //授权
HQCHART_DLL_API const wchar_t* __stdcall GetAuthorizeError();
HQCHART_DLL_API int __stdcall MainVersion();
HQCHART_DLL_API int __stdcall MinVersion();
HQCHART_DLL_API const wchar_t* __stdcall GenerateAuthorize(const wchar_t* pStrKey, const wchar_t* pStrContent);
hqChart/include/HQChart.KLineData.h
New file
@@ -0,0 +1,549 @@
/*
    Copyright (c) 2018 jones
    http://www.apache.org/licenses/LICENSE-2.0
    å¼€æºé¡¹ç›® https://github.com/jones2000/HQChart
    jones_2000@163.com
    è‚¡ç¥¨æ•°æ®ç±»åŠå¯¹å¤–接口类 (c++)
*/
#pragma once
#include "zwldef.h"
#include <vector>
#include <map>
#include <string>
#include <set>
#ifdef _WIN32
#define REGISTER_HISTORYDATA(__class__)\
    HQChart::Complier::IHistoryData* Create##__class__(const std::wstring& strSymbol, long lPeriod, long lRight)\
    {\
        return new __class__(strSymbol, lPeriod, lRight);\
    }\
    void Delete##__class__(HQChart::Complier::IHistoryData*& pHistoryData)\
    {\
        if (pHistoryData) { delete pHistoryData; pHistoryData = NULL; }\
    }\
    const bool bRegisteredCreate##__class__ = HQChart::Complier::DataCreateFactory::GetInstance().RegisterHistoryData(L#__class__, Create##__class__, Delete##__class__);\
#else
#define REGISTER_HISTORYDATA(__class__)\
    HQChart::Complier::IHistoryData* Create__class__(const std::wstring& strSymbol, long lPeriod, long lRight)\
    {\
        return new __class__(strSymbol, lPeriod, lRight);\
    }\
    void Delete__class__(HQChart::Complier::IHistoryData*& pHistoryData)\
    {\
        if (pHistoryData) { delete pHistoryData; pHistoryData = NULL; }\
    }\
    const bool bRegisteredCreate__class__ = HQChart::Complier::DataCreateFactory::GetInstance().RegisterHistoryData(L"_class__", Create__class__, Delete__class__);\
#endif
namespace HQChart { namespace Complier {
#pragma pack(push,1)
struct HISTORY_ITEM
{
    int _nDate=0;        //日期  yyyymmdd
    int _nTime=0;        //时间  hhmmss
    double _dYClose=0;    //算复权用
    double _dOpen=0;
    double _dHigh=0;
    double _dLow=0;
    double _dClose=0;
    double _dVol=0;
    double _dAmount=0;
    int    _nAdvance = 0;    //周期上涨家数. åˆ†ç¬” B/S
    int _nDecline = 0;    //周期下跌家数.
};
//K线信息
struct KDATA_INFO
{
    long _lPeriod;    //周期
    long _lRight;    //复权
    //起始日期
    long _lStartDate;
    long _lStartTime;
    //结束日期
    long _lEndDate;
    long _lEndTime;
    long _lCount;    //K线个数
};
#pragma pack(pop)
//周期
enum PERIOD_TYPE_ID
{
    PERIOD_DAY_ID=0,
    PERIOD_WEEK_ID=1,
    PERIOD_MONTH_ID=2,
    PERIOD_YEAR_ID=3,
    PERIOD_QUARTER_ID=9,    //å­£
    PERIOD_TWO_WEEK_ID=21,    //双周
    PERIOD_MIN1_ID=4,
    PERIOD_MIN5_ID=5,
    PERIOD_MIN15_ID=6,
    PERIOD_MIN30_ID=7,
    PERIOD_MIN60_ID=8,
    PERIOD_TICK_ID=10,    //分笔
};
//复权
enum RIGHT_TYPE_ID
{
    RIGHT_NONE_ID = 0, //不复权
    RIGHT_BEFORE_ID = 1,//前复权
    RIGHT_AFTER_ID= 2,  //后复权
};
class Variant;
class Node;
struct FIT_DATETIME_ITEM;
class VariantCacheManage;
class ScriptIndex;
class IHistoryData
{
public:
    IHistoryData();
    virtual ~IHistoryData();
    typedef std::vector<Variant*> ARRAY_VARIANT;
    typedef std::vector<Variant* > ARRAY_CALL_ARGUMENT;
    typedef std::vector<HISTORY_ITEM> ARRAY_KDATA;
    typedef std::vector<FIT_DATETIME_ITEM> ARRAY_FIT_DATETIME_DATA;
    virtual void Initialization(void* pData) = 0;    //初始化
    virtual bool LoadKData() = 0;    //加载K线
    virtual bool LoadKData(const std::wstring& strSymbol, long lPeriod, long lRight, Node* pNode, const std::wstring& strCallInfo) =0;    //K线下载
    virtual Variant* GetClose() const =0;    //收盘价
    virtual Variant* GetOpen() const =0;    //开盘
    virtual Variant* GetHigh() const =0;    //最高
    virtual Variant* GetLow() const =0;        //最低
    virtual Variant* GetVol() const =0;        //量
    virtual Variant* GetAmount() const =0;    //金额
    virtual Variant* GetDate() const = 0;    //日期
    virtual Variant* GetTime() const =0;    //时间
    virtual Variant* GetMonth() const=0;    //月
    virtual Variant* GetDay() const = 0;    //天
    virtual Variant* GetYear() const=0;        //å¹´
    virtual Variant* GetWeekDay() const=0;    //星期几
    virtual Variant* GetHour() const=0;        //Сʱ
    virtual Variant* GetMinute() const=0;    //分钟
    virtual Variant* GetCurrBarsCount() const = 0;    //到最后交易日的周期数
    virtual Variant* GetTotalBarsCount() const = 0;
    virtual Variant* GetFromOpen(Node* pNode) const = 0;
    virtual Variant* GetAdvance() const = 0;
    virtual Variant* GetDecline() const = 0;
    virtual const ARRAY_KDATA* GetKData(const std::wstring& strSymbol, long lPeriod, long lRight) const = 0;
    virtual Variant* GetKDataItem(const ARRAY_KDATA& aryData, const std::wstring& strVarName) const = 0;
    virtual Variant* GetCustomValue(const std::wstring& strName, Node* pNode) const = 0;
    virtual Variant* CallCustomFunction(const std::wstring& strName, const std::vector<double>& args, Node* pNode) const = 0;
    virtual const HISTORY_ITEM* GetKItem(int nIndex) const = 0;    //获取索引对应的K线数据
    virtual long GetKCount() const = 0;
    virtual const bool GetKMaxMin(double& dMax, double& dMin) const = 0;        // èŽ·å–K线最大,最小值
    virtual const bool GetKMaxMin(long lStart, long lEnd, double& dMax, double& dMin) const = 0;
    virtual long FindByDate(long lDate) const { return -1; }    //查找某一天K线日期的索引
    virtual Variant* GetBlockMemberCount(const ARRAY_CALL_ARGUMENT& args, Node* pNode) const = 0;    //板块股票个数
    virtual Variant* GetBlockCalculate(const ARRAY_CALL_ARGUMENT& args, Node* pNode) const =0 ;        //多股统计
    //其他行情数据
    virtual Variant* GetFinance(const ARRAY_CALL_ARGUMENT& args, Node* pNode) const = 0;    //财务数据
    virtual Variant* GetCapital(Node* pNode) const = 0;            //CAPITAL å½“前流通股本 æ‰‹
    virtual Variant* GetTotalCaptialAll(Node* pNode) const = 0;    //TOTALCAPITAL  å½“前总股本 æ‰‹
    virtual Variant* GetHisCapital(Node* pNode) const = 0;    //历史流通股本 è‚¡
    virtual Variant* GetExchange(Node* pNode) const = 0;    //换手率
    virtual Variant* GetDynaInfo(const ARRAY_CALL_ARGUMENT& args, Node* pNode) const = 0;    //个股最新数据
    virtual Variant* GetIndexData(const std::wstring& strName, Node* pNode) const = 0;    //获取大盘数据
    virtual Variant* GetName() const = 0;        //股票名称
    virtual Variant* GetSymbol(long lType) const = 0;        //股票代码
    virtual const std::wstring& GetSymbolString() const = 0;//股票代码
    virtual Variant* GetCategroyName(long lType) const = 0;    //板块名称
    virtual Variant* IsInCategroy(long lType, const std::wstring& strName) const = 0; //是否板块成员
    virtual Variant* GetMarketName() const = 0;    //市场代码
    virtual Variant* GetMarketCNName() const = 0;    //市场名称
    virtual Variant* GetPeriodID() const = 0; //分时线=1,分笔成交=2,1分钟线=3,5分钟线=4,15分钟线=5,30分钟线=6,60分钟线=7,日线=8,周线=9,月线=10,多日线=11,年线=12,季线=13,半年线=14。
    virtual Variant* GetSymbolTypeID() const = 0;
    virtual Variant* GetDrawNULL() const = 0;
    virtual bool GetIndexScript(const std::wstring& strName, const std::wstring& strCallInfo, ScriptIndex& script, Node* pNode) const = 0;    //获取系统指标脚本
    virtual long GetPeriod() const = 0;
    virtual long GetRight() const = 0;
    virtual ARRAY_KDATA& GetData() = 0;
    virtual const ARRAY_KDATA& GetData() const = 0;
    virtual bool IsMinutePeriod() const=0;
    virtual bool IsDayPeriod() const=0;
    virtual bool IsTickPeriod() const = 0;
    virtual bool ConvertToDayPeriod(const ARRAY_KDATA& aryDay, ARRAY_KDATA& dest, long lPeriod) const;
    virtual bool ConvertToMinutePeriod(const ARRAY_KDATA& aryOneMinute, ARRAY_KDATA& dest, long lPeriod) const;
    virtual bool ConvertToRight(ARRAY_KDATA& aryData, long lRight) const;    //复权计算
    inline const std::wstring& GetClassName() const { return m_strClassName; }
    void ClearCache();
    void SetCacheManage(VariantCacheManage* pVariantCacheManage);
    static void FitDateTime(const IHistoryData* pDestHistoryData, const IHistoryData* pHistoryData, ARRAY_FIT_DATETIME_DATA& aryDateTime);        //日期拟合 (pDestHistoryData éœ€è¦è½¬æ¢çš„K
    static bool IsMinutePeriod(long lPeriod);
    static bool IsDayPeriod(long lPeriod);
    static bool IsTickPeriod(long lPeriod);
    static bool IsSZSHStock(const std::wstring& strSymbol);    //是否为上海/深证股票
protected:
    Variant* Create() const;
    static long GetFriday(long lDate);
    mutable ARRAY_VARIANT m_VariantCache;    //保存所有创建的变量数据
    VariantCacheManage*    m_pVariantCacheManage = NULL;
    std::wstring m_strClassName = L"IHistoryData";
};
class VariantCacheManage
{
public:
    typedef std::vector<Variant*> ARRAY_VARIANT;
    VariantCacheManage();
    ~VariantCacheManage();
    Variant* Create();
    void FreeVariant();
    void Clear();
private:
    ARRAY_VARIANT m_aryUsedVariant;
    ARRAY_VARIANT m_aryFreeVariant;
};
#pragma pack(push,1)
struct FINANCE_ITEM
{
    int _nDate;            //日期
    double _dValue;        //某一个财务指标
};
enum FINANCE_ID        //财务数据ID
{
    TOTAL_EQUITY_ID = 0, //总股本
    FLOW_EQUITY_ID=7,     //流通股本
    SHAREHOLDER_ID=8,     //股东人数
    AL_RATIO=9,             //资产负债率(asset-liability ratio)
};
struct HISTORY_EXTEND_ITEM
{
    int _nDate;        //K线日期
    int _nTime = 0;    //K线时间
    double _dValue;    //数据
    int _nExDate;    //对应扩展数据的日期时间 ï¼ˆè°ƒè¯•用)
    int _nExTime;
};
struct OVERLAY_HISTORY_ITEM
{
    int _nDate;
    int _nTime = 0;
    double _dYClose=0;    //目前没用到
    double _dOpen;
    double _dHigh;
    double _dLow;
    double _dClose;
    double _dVol;
    double _dAmount;
    int    _nAdvance = 0;    //周期上涨家数.
    int _nDecline = 0;    //周期下跌家数.
    int _nExDate;    //对应扩展数据的日期时间 ï¼ˆè°ƒè¯•用)
    int _nExTime;
};
enum DYNAINFO_ID
{
    DYNAINFO_YCLOSE_ID=3,    //前收盘价
    DYNAINFO_OPEN_ID=4,        //开盘价
    DYNAINFO_HIGH_ID=5,        //最高价
    DYNAINFO_LOW_ID=6,        //最低价
    DYNAINFO_PRICE_ID=7,    //现价
    DYNAINFO_VOL_ID=8,        //总量
    DYNAINFO_CVOL_ID=9,        //现量
    DYNAINFO_AMOUNT_ID=10,    //金额
    DYNAINFO_APRICE_ID=11,  //均价
};
#pragma pack(pop)
//行业分类
struct CATEGROY_ITEM
{
    long _lType;            //行业类型
    std::wstring _strName;    //行业名称
    std::wstring _strSymbol;//行业代码
};
struct FIT_DATETIME_ITEM
{
    long _lDate[2];
    long _lTime[2];
    long _lIndex = -1;
    FIT_DATETIME_ITEM()
        :_lIndex(-1)
    {
        _lDate[0] = _lDate[1] = 0;
        _lTime[0] = _lTime[1] = 0;
    }
};
class HistoryDataCache : public IHistoryData
{
public:
    typedef std::vector<HISTORY_ITEM> ARRAY_KDATA;
    typedef std::vector<FINANCE_ITEM> ARRAY_FINANCE_DATA;
    typedef std::vector<HISTORY_EXTEND_ITEM> ARRAY_EXTEND_DATA;
    typedef std::map<long, double> MAP_DYNAINFO_DATA;
    typedef std::vector<OVERLAY_HISTORY_ITEM> ARRAY_OVERLAY_DATA;    //叠加数据
    typedef std::vector<CATEGROY_ITEM> ARRAY_CATEGORY_DATA;            //行业数据
    HistoryDataCache(const std::wstring& strSymbol, long lPeriod, long lRight);
    virtual ~HistoryDataCache();
    virtual void Initialization(void* pData);
    virtual bool LoadKData();                            //加载K线
    virtual bool LoadKData(const std::wstring& strSymbol, long lPeriod, long lRight, Node* pNode, const std::wstring& strCallInfo);
    ARRAY_KDATA& GetData() { return m_aryData; };
    const ARRAY_KDATA& GetData() const { return m_aryData; }
    void SetName(const std::wstring& strName) { m_strName = strName; }    //设置股票名称
    virtual const HISTORY_ITEM* GetKItem(int nIndex) const;
    virtual long GetKCount() const;
    virtual const bool GetKMaxMin(double& dMax, double& dMin) const;
    virtual const bool GetKMaxMin(long lStart, long lEnd, double& dMax, double& dMin) const;
    virtual long FindByDate(long lDate) const;
    virtual Variant* GetClose() const;
    virtual Variant* GetOpen() const;
    virtual Variant* GetHigh() const;
    virtual Variant* GetLow() const;
    virtual Variant* GetVol() const;
    virtual Variant* GetAmount() const;
    virtual Variant* GetDate() const;
    virtual Variant* GetTime() const;
    virtual Variant* GetMonth() const;
    virtual Variant* GetYear() const;
    virtual Variant* GetDay() const;
    virtual Variant* GetWeekDay() const;
    virtual Variant* GetHour() const;
    virtual Variant* GetMinute() const;
    virtual Variant* GetCurrBarsCount() const;
    virtual Variant* GetTotalBarsCount() const;
    virtual Variant* GetFromOpen(Node* pNode) const;
    virtual Variant* GetAdvance() const;
    virtual Variant* GetDecline() const;
    virtual Variant* GetCustomValue(const std::wstring& strName, Node* pNode) const;
    virtual Variant* CallCustomFunction(const std::wstring& strName, const std::vector<double>& args, Node* pNode) const;
    virtual const ARRAY_KDATA* GetKData(const std::wstring& strSymbol, long lPeriod, long lRight) const;
    virtual Variant* GetKDataItem(const ARRAY_KDATA& aryData, const std::wstring& strVarName) const;
    virtual Variant* GetFinance(const ARRAY_CALL_ARGUMENT& args, Node* pNode) const;
    virtual Variant* GetExchange(Node* pNode) const;    //换手率
    virtual Variant* GetCapital(Node* pNode) const;        //获取当前的流通股本 å•位手
    virtual Variant* GetTotalCaptialAll(Node* pNode) const;    //TOTALCAPITAL  å½“前总股本 æ‰‹
    virtual Variant* GetHisCapital(Node* pNode) const;    //获取历史所有的流通股本 å•位股
    virtual Variant* GetDynaInfo(const ARRAY_CALL_ARGUMENT& args, Node* pNode) const;
    virtual Variant* GetIndexData(const std::wstring& strName, Node* pNode) const;
    virtual Variant* GetBlockMemberCount(const ARRAY_CALL_ARGUMENT& args, Node* pNode) const;    //板块股票个数
    virtual Variant* GetBlockCalculate(const ARRAY_CALL_ARGUMENT& args, Node* pNode) const;        //多股统计
    virtual Variant* GetName() const;        //股票名称
    virtual Variant* GetSymbol(long lType) const;        //股票代码
    virtual Variant* GetCategroyName(long lType) const;    //板块名称 lType=-1 å–所有行业
    virtual Variant* IsInCategroy(long lType, const std::wstring& strName) const;
    virtual Variant* GetMarketName() const;
    virtual Variant* GetMarketCNName() const;
    virtual Variant* GetPeriodID() const; //分时线=1,分笔成交=2,1分钟线=3,5分钟线=4,15分钟线=5,30分钟线=6,60分钟线=7,日线=8,周线=9,月线=10,多日线=11,年线=12,季线=13,半年线=14。
    virtual Variant* GetSymbolTypeID() const;
    virtual Variant* GetDrawNULL() const;
    virtual bool GetIndexScript(const std::wstring& strName, const std::wstring& strCallInfo, ScriptIndex& script, Node* pNode) const;    //获取系统指标脚本
    virtual long GetPeriod() const { return m_lPeriod; }
    virtual long GetRight() const { return m_lRight; }
    virtual bool IsMinutePeriod() const;
    virtual bool IsDayPeriod() const;
    virtual bool IsTickPeriod() const;
    bool IsSH() const;        //上海交易所品种
    bool IsSZ() const;        //深圳交易所品种
    bool IsSHSZA() const;        //上海,深圳A股
    bool IsSHSZIndex() const; //上海,深圳指数
    virtual const std::wstring& GetSymbolString() const { return m_strSymbol; }
protected:
    virtual bool LoadFinance(long lType) const;            //加载财务数据 (用到才加载)
    virtual bool LoadDynainfo(long lType) const;        //加载即时行情数据 (用到才加载)
    virtual bool LoadIndexData(const std::wstring& strName, Node* pNode) const;        //加载大盘数据 (用到才加载)
    virtual bool LoadCategoryData() const;                //加载行业分类数据(用到才加载)
    Variant* GetIsPriceDown() const;
    Variant* GetIsPriceUp() const;
    Variant* GetIsPriceEqual() const;
    static void FitExtendData(ARRAY_EXTEND_DATA& dest, const ARRAY_KDATA& kData, const ARRAY_FINANCE_DATA& fData);            //财务数据K线数据拟合
    static void FitExtendData(ARRAY_EXTEND_DATA& dest, const ARRAY_KDATA& kData, long lPeriod, const ARRAY_FINANCE_DATA& fData, double dNUll, bool bExactMatch=true);    ///数据和K线数据拟合,不做平滑处理 bExactMatch ç²¾ç¡®åŒ¹é…
    static void FitOveralyDayData(ARRAY_OVERLAY_DATA& dest, const ARRAY_KDATA& kData, const ARRAY_KDATA& overalyData);        //K线叠加拟合
    static void FitOveralyMinuteData(ARRAY_OVERLAY_DATA& dest, const ARRAY_KDATA& kData, const ARRAY_KDATA& overalyData);    //K线叠加拟合
    static int GetWeek(int nDate);
    mutable ARRAY_FINANCE_DATA m_aryFinance;    //财务数据读取缓存
    mutable MAP_DYNAINFO_DATA m_mapDynainfo;    //即时行情数据
    mutable ARRAY_OVERLAY_DATA m_aryIndex;        //大盘数据
    mutable ARRAY_CATEGORY_DATA m_aryCategory;    //行业分类数据
    std::wstring m_strSymbol;                    //股票代码
    std::wstring m_strName;                        //股票名称
    long m_lPeriod = 0;                            //周期 0=日线 1=周线 2=月线 3=年线 4=1分钟 5=5分钟 6=15分钟 7=30分钟 8=60分钟 9=季线 10=分笔
    long m_lRight = 0;                            //复权 0=不复权 1=前复权 2=后复权
    ARRAY_KDATA m_aryData;                        //K线数据
    KDATA_INFO m_KDataInfo;                        //K线信息
    std::map<std::wstring, ARRAY_KDATA>    m_mapKData;    //其他的K线数据
    XINT64 m_lUpdateTime=0;                        //最后更新时间
};
typedef IHistoryData* (*pCreateHistoryData)(const std::wstring& strSymbol, long lPeriod, long lRight);    //lPeriod=周期 lRight=复权
typedef void(*pDeleteHistoryData)(IHistoryData*& pHistoryData);
struct CREATE_ITEM
{
    std::wstring _strName;
    pCreateHistoryData _pProcCreate = NULL;
    pDeleteHistoryData _pProcDelete = NULL;
};
/////////////////////////////////////////////////////////////////////////////////////////////////////
// æ•°æ®ç±»å·¥åŽ‚
//
/////////////////////////////////////////////////////////////////////////////////////////////////////
class DataCreateFactory
{
public:
    static DataCreateFactory& GetInstance();
    bool RegisterHistoryData(const std::wstring& strClassName, pCreateHistoryData pProcCreate, pDeleteHistoryData pProcDelete);
    IHistoryData* CreateHistoryData(const std::wstring& strClassName, const std::wstring& strSymbol, long lPeriod, long lRight);
    bool DeleteHistoryData(const std::wstring& strClassName, IHistoryData*& pHistoryData);
private:
    DataCreateFactory();
    ~DataCreateFactory();
    typedef std::map<std::wstring, CREATE_ITEM> MAP_CREATE_DATA;
    MAP_CREATE_DATA m_mapCreateData;
};
class AutoPtrHistoryData
{
public:
    AutoPtrHistoryData(const std::wstring& strClassName);
    ~AutoPtrHistoryData();
    IHistoryData* Create(const std::wstring& strSymbol, long lPeriod, long lRight);
    void Release();
private:
    std::wstring m_strClassName;
    IHistoryData* m_pHistoryData=NULL;
};
//////////////////////////////////////////////////////////////////////////////////////////////
//  è‡ªå®šä¹‰å˜é‡,函数接口
//
//
/////////////////////////////////////////////////////////////////////////////////////////////
struct CUSTOM_FUNCTION_ITEM
{
    std::wstring _strName;        //参数名
    int            _nArgCount;    //参数个数
};
class CustomFunction
{
public:
    static CustomFunction& GetInstance();
    bool Get(const std::wstring& strName, CUSTOM_FUNCTION_ITEM& item);
    void Add(const std::wstring& strName, long lArgCount);
private:
    CustomFunction();
    ~CustomFunction();
    std::map<std::wstring, CUSTOM_FUNCTION_ITEM> m_aryCustomFunc;    //自定义函数
};
class CustomVariant
{
public:
    static CustomVariant& GetInstance();
    void Add(const std::wstring& strName);
    bool IsExist(const std::wstring& strName) const;
private:
    CustomVariant();
    ~CustomVariant();
    std::set<std::wstring> m_setVariant;
};
}
}