├── Doc └── PowerGate.png ├── README.md └── Src ├── Dark.thm ├── Gray.thm ├── Letter-A-black-icon.ico ├── Letter-A-black-icon.png ├── Letter-P-black-icon.ico ├── Letter-P-black-icon.png ├── Light.thm ├── PowerGate.ini ├── PowerGate.pro ├── PowerGate.qm ├── PowerGate.qrc ├── PowerGate.ts ├── QtATS.sln ├── QtATS.vcxproj ├── QtATS.vcxproj.filters ├── RestartAPI.cpp ├── RestartAPI.h ├── Semaphore.h ├── TinyCrypt.cpp ├── TinyCrypt.h ├── WinResource.rc ├── apptheme.cpp ├── apptheme.h ├── authdialog.cpp ├── authdialog.h ├── authdialog.ui ├── authentication.cpp ├── authentication.h ├── circular.h ├── connect.png ├── disconnect.png ├── dock_host.cpp ├── dock_host.h ├── editbkrdialog.cpp ├── editbkrdialog.h ├── editbkrdialog.ui ├── logindialog.cpp ├── logindialog.h ├── logindialog.ui ├── loginsettingsdialog.cpp ├── loginsettingsdialog.h ├── loginsettingsdialog.ui ├── logmodel.cpp ├── logmodel.h ├── main.cpp ├── main.h ├── ordermodel.cpp ├── ordermodel.h ├── posmodel.cpp ├── posmodel.h ├── powergate.cpp ├── powergate.h ├── powergate.ui ├── quickmail.c ├── quickmail.h ├── quotedialog.cpp ├── quotedialog.h ├── quotedialog.ui ├── quotemodel.cpp ├── quotemodel.h ├── resource.h ├── smtpsocket.c ├── smtpsocket.h ├── stratcmd.ui ├── stratcmddialog.cpp ├── stratcmddialog.h ├── stratlog.ui ├── stratlogdialog.cpp ├── stratlogdialog.h ├── stratlogmodel.cpp ├── stratlogmodel.h ├── stratmodel.cpp ├── stratmodel.h ├── stratparams.ui ├── stratparamsdialog.cpp ├── stratparamsdialog.h ├── stratparamsmodel.cpp ├── stratparamsmodel.h ├── stratpos.ui ├── stratposdialog.cpp ├── stratposdialog.h ├── stratposmodel.cpp ├── stratposmodel.h ├── subscribedialog.cpp ├── subscribedialog.h ├── subscribedialog.ui ├── tinyxml2.cpp ├── tinyxml2.h ├── tradepanel.cpp ├── tradepanel.h ├── tradepanel.ui └── warning.wav /Doc/PowerGate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/algosenses/PowerGate/7996dec6889ce59f5dc1c145aebd61b7ab28f031/Doc/PowerGate.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # PowerGate: AlgoSE算法策略引擎图形前端 2 | PowerGate是AlgoSE引擎的图形前端,它基于Qt编写,方便用户以图形界面的方式管理交易策略。 3 | ## 功能 4 | PowerGate的主要目的是帮助用户管理交易策略,它的功能包括: 5 | 1. 配置交易账户。 6 | 2. 加载和控制用户的交易策略。 7 | 3. 查看账户、行情、报单、持仓、通道连接状态等信息。 8 | 4. 手工交易。 9 | 5. 每日定时重启,做到无人值守。 10 | 6. 异常情况邮件报警。 11 | 7. 可设置认证服务器,只有通过认证才能启动。 12 | 8. ... 13 | ## 下载 14 | 在[www.algo.trade]()可以找到一个可运行的版本。 15 | ## 界面 16 | PowerGate的主界面如下: 17 | ![](Doc/PowerGate.png) 18 | -------------------------------------------------------------------------------- /Src/Dark.thm: -------------------------------------------------------------------------------- 1 | [General] 2 | Gray="150,150,150,255" 3 | Red="255,100,100,255" 4 | Green="100,255,100,255" 5 | Blue="50,150,255,255" 6 | LightRed="0,55,55,255" 7 | LightGreen="55,0,55,255" 8 | LightBlue="55,55,0,255" 9 | LightGreenBlue="55,0,0,255" 10 | LightRedBlue="0,55,0,255" 11 | DarkRedBlue="222,127,124,255" 12 | LightRedGreen="0,0,55,255" 13 | DarkRed="255,100,100,255" 14 | DarkGreen="100,200,100,255" 15 | DarkBlue="20,20,180,255" 16 | Black="255,255,255,255" 17 | White="50,50,50,255" 18 | 19 | [Normal] 20 | Color_0_WindowText="255,255,255,255" 21 | Color_1_Button="120,120,120,255" 22 | Color_2_Light="0,0,0,255" 23 | Color_3_Midlight="127,127,127,255" 24 | Color_4_Dark="200,200,200,255" 25 | Color_5_Mid="230,230,230,255" 26 | Color_6_Text="255,255,255,255" 27 | Color_7_BrightText="0,0,0,255" 28 | Color_8_ButtonText="255,255,255,255" 29 | Color_9_Base="60,60,60,255" 30 | Color_10_Window="40,40,40,255" 31 | Color_11_Shadow="150,150,150,255" 32 | Color_12_Highlight="51,153,255,255" 33 | Color_13_HighlightedText="255,255,255,255" 34 | Color_14_Link="50,150,255,255" 35 | Color_15_LinkVisited="255,0,255,255" 36 | Color_16_AlternateBase="40,40,40,255" 37 | Color_17_NoRole="255,255,255,255" 38 | Color_18_ToolTipBase="80,80,80,255" 39 | Color_19_ToolTipText="255,255,255,255" 40 | 41 | [Disabled] 42 | Color_0_WindowText="120,120,120,255" 43 | Color_1_Button="100,100,100,255" 44 | Color_2_Light="55,55,55,255" 45 | Color_3_Midlight="147,147,147,255" 46 | Color_4_Dark="200,200,200,255" 47 | Color_5_Mid="140,140,140,255" 48 | Color_6_Text="120,120,120,255" 49 | Color_7_BrightText="55,55,55,255" 50 | Color_8_ButtonText="120,120,120,255" 51 | Color_9_Base="60,60,60,255" 52 | Color_10_Window="40,40,40,255" 53 | Color_11_Shadow="0,0,0,255" 54 | Color_12_Highlight="51,153,255,255" 55 | Color_13_HighlightedText="255,255,255,255" 56 | Color_14_Link="0,0,255,255" 57 | Color_15_LinkVisited="255,0,255,255" 58 | Color_16_AlternateBase="40,40,40,255" 59 | Color_17_NoRole="255,255,255,255" 60 | Color_18_ToolTipBase="80,80,80,255" 61 | Color_19_ToolTipText="255,255,255,255" 62 | 63 | [Inactive] 64 | Color_0_WindowText="255,255,255,255" 65 | Color_1_Button="120,120,120,255" 66 | Color_2_Light="0,0,0,255" 67 | Color_3_Midlight="127,127,127,255" 68 | Color_4_Dark="200,200,200,255" 69 | Color_5_Mid="230,230,230,255" 70 | Color_6_Text="255,255,255,255" 71 | Color_7_BrightText="0,0,0,255" 72 | Color_8_ButtonText="255,255,255,255" 73 | Color_9_Base="60,60,60,255" 74 | Color_10_Window="40,40,40,255" 75 | Color_11_Shadow="150,150,150,255" 76 | Color_12_Highlight="51,153,255,255" 77 | Color_13_HighlightedText="255,255,255,255" 78 | Color_14_Link="50,150,255,255" 79 | Color_15_LinkVisited="255,0,255,255" 80 | Color_16_AlternateBase="40,40,40,255" 81 | Color_17_NoRole="255,255,255,255" 82 | Color_18_ToolTipBase="80,80,80,255" 83 | Color_19_ToolTipText="255,255,255,255" 84 | -------------------------------------------------------------------------------- /Src/Gray.thm: -------------------------------------------------------------------------------- 1 | [General] 2 | Gray="88,88,88,255" 3 | Red="255,0,0,255" 4 | Green="0,255,0,255" 5 | Blue="0,0,255,255" 6 | LightRed="255,200,200,255" 7 | LightGreen="200,255,200,255" 8 | LightBlue="200,200,255,255" 9 | LightGreenBlue="200,255,255,255" 10 | DarkRedBlue="125,0,125,255" 11 | LightRedBlue="255,100,255,255" 12 | LightRedGreen="255,255,200,255" 13 | DarkRed="255,100,100,255" 14 | DarkGreen="0,160,0,255" 15 | DarkBlue="20,20,180,255" 16 | Black="0,0,0,255" 17 | White="225,225,225,255" 18 | 19 | [Normal] 20 | Color_0_WindowText="0,0,0,255" 21 | Color_10_Window="200,200,200,255" 22 | Color_11_Shadow="105,105,105,255" 23 | Color_12_Highlight="51,153,255,255" 24 | Color_13_HighlightedText="255,255,255,255" 25 | Color_14_Link="0,0,255,255" 26 | Color_15_LinkVisited="255,0,255,255" 27 | Color_16_AlternateBase="246,246,246,255" 28 | Color_17_NoRole="0,0,0,255" 29 | Color_18_ToolTipBase="255,255,220,255" 30 | Color_19_ToolTipText="0,0,0,255" 31 | Color_1_Button="220,220,220,255" 32 | Color_2_Light="255,255,255,255" 33 | Color_3_Midlight="207,207,207,255" 34 | Color_4_Dark="160,160,160,255" 35 | Color_5_Mid="100,100,100,255" 36 | Color_6_Text="0,0,0,255" 37 | Color_7_BrightText="255,255,255,255" 38 | Color_8_ButtonText="0,0,0,255" 39 | Color_9_Base="245,245,245,255" 40 | 41 | [Disabled] 42 | Color_0_WindowText="120,120,120,255" 43 | Color_10_Window="200,200,200,255" 44 | Color_11_Shadow="0,0,0,255" 45 | Color_12_Highlight="51,153,255,255" 46 | Color_13_HighlightedText="255,255,255,255" 47 | Color_14_Link="0,0,255,255" 48 | Color_15_LinkVisited="255,0,255,255" 49 | Color_16_AlternateBase="246,246,246,255" 50 | Color_17_NoRole="0,0,0,255" 51 | Color_18_ToolTipBase="255,255,220,255" 52 | Color_19_ToolTipText="0,0,0,255" 53 | Color_1_Button="180,180,180,255" 54 | Color_2_Light="255,255,255,255" 55 | Color_3_Midlight="247,247,247,255" 56 | Color_4_Dark="160,160,160,255" 57 | Color_5_Mid="160,160,160,255" 58 | Color_6_Text="120,120,120,255" 59 | Color_7_BrightText="255,255,255,255" 60 | Color_8_ButtonText="120,120,120,255" 61 | Color_9_Base="200,200,200,255" 62 | 63 | [Inactive] 64 | Color_0_WindowText="0,0,0,255" 65 | Color_10_Window="200,200,200,255" 66 | Color_11_Shadow="105,105,105,255" 67 | Color_12_Highlight="200,200,200,255" 68 | Color_13_HighlightedText="0,0,0,255" 69 | Color_14_Link="0,0,255,255" 70 | Color_15_LinkVisited="255,0,255,255" 71 | Color_16_AlternateBase="246,246,246,255" 72 | Color_17_NoRole="0,0,0,255" 73 | Color_18_ToolTipBase="255,255,220,255" 74 | Color_19_ToolTipText="0,0,0,255" 75 | Color_1_Button="220,220,220,255" 76 | Color_2_Light="255,255,255,255" 77 | Color_3_Midlight="227,227,227,255" 78 | Color_4_Dark="160,160,160,255" 79 | Color_5_Mid="160,160,160,255" 80 | Color_6_Text="0,0,0,255" 81 | Color_7_BrightText="255,255,255,255" 82 | Color_8_ButtonText="0,0,0,255" 83 | Color_9_Base="235,235,235,255" -------------------------------------------------------------------------------- /Src/Letter-A-black-icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/algosenses/PowerGate/7996dec6889ce59f5dc1c145aebd61b7ab28f031/Src/Letter-A-black-icon.ico -------------------------------------------------------------------------------- /Src/Letter-A-black-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/algosenses/PowerGate/7996dec6889ce59f5dc1c145aebd61b7ab28f031/Src/Letter-A-black-icon.png -------------------------------------------------------------------------------- /Src/Letter-P-black-icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/algosenses/PowerGate/7996dec6889ce59f5dc1c145aebd61b7ab28f031/Src/Letter-P-black-icon.ico -------------------------------------------------------------------------------- /Src/Letter-P-black-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/algosenses/PowerGate/7996dec6889ce59f5dc1c145aebd61b7ab28f031/Src/Letter-P-black-icon.png -------------------------------------------------------------------------------- /Src/Light.thm: -------------------------------------------------------------------------------- 1 | [General] 2 | Gray="128,128,128,255" 3 | Red="255,0,0,255" 4 | Green="0,255,0,255" 5 | Blue="0,0,255,255" 6 | LightRed="255,200,200,255" 7 | LightGreen="200,255,200,255" 8 | LightBlue="200,200,255,255" 9 | LightGreenBlue="200,255,255,255" 10 | DarkRedBlue="125,0,125,255" 11 | LightRedBlue="255,100,255,255" 12 | LightRedGreen="255,255,200,255" 13 | DarkRed="255,100,100,255" 14 | DarkGreen="0,160,0,255" 15 | DarkBlue="20,20,180,255" 16 | Black="0,0,0,255" 17 | White="255,255,255,255" 18 | 19 | [Normal] 20 | Color_0_WindowText="0,0,0,255" 21 | Color_10_Window="240,240,240,255" 22 | Color_11_Shadow="105,105,105,255" 23 | Color_12_Highlight="51,153,255,255" 24 | Color_13_HighlightedText="255,255,255,255" 25 | Color_14_Link="0,0,255,255" 26 | Color_15_LinkVisited="255,0,255,255" 27 | Color_16_AlternateBase="246,246,246,255" 28 | Color_17_NoRole="0,0,0,255" 29 | Color_18_ToolTipBase="255,255,220,255" 30 | Color_19_ToolTipText="0,0,0,255" 31 | Color_1_Button="240,240,240,255" 32 | Color_2_Light="255,255,255,255" 33 | Color_3_Midlight="227,227,227,255" 34 | Color_4_Dark="160,160,160,255" 35 | Color_5_Mid="160,160,160,255" 36 | Color_6_Text="0,0,0,255" 37 | Color_7_BrightText="255,255,255,255" 38 | Color_8_ButtonText="0,0,0,255" 39 | Color_9_Base="255,255,255,255" 40 | 41 | [Disabled] 42 | Color_0_WindowText="120,120,120,255" 43 | Color_10_Window="240,240,240,255" 44 | Color_11_Shadow="0,0,0,255" 45 | Color_12_Highlight="51,153,255,255" 46 | Color_13_HighlightedText="255,255,255,255" 47 | Color_14_Link="0,0,255,255" 48 | Color_15_LinkVisited="255,0,255,255" 49 | Color_16_AlternateBase="246,246,246,255" 50 | Color_17_NoRole="0,0,0,255" 51 | Color_18_ToolTipBase="255,255,220,255" 52 | Color_19_ToolTipText="0,0,0,255" 53 | Color_1_Button="200,200,200,255" 54 | Color_2_Light="255,255,255,255" 55 | Color_3_Midlight="247,247,247,255" 56 | Color_4_Dark="160,160,160,255" 57 | Color_5_Mid="160,160,160,255" 58 | Color_6_Text="120,120,120,255" 59 | Color_7_BrightText="255,255,255,255" 60 | Color_8_ButtonText="120,120,120,255" 61 | Color_9_Base="240,240,240,255" 62 | 63 | [Inactive] 64 | Color_0_WindowText="0,0,0,255" 65 | Color_10_Window="240,240,240,255" 66 | Color_11_Shadow="105,105,105,255" 67 | Color_12_Highlight="240,240,240,255" 68 | Color_13_HighlightedText="0,0,0,255" 69 | Color_14_Link="0,0,255,255" 70 | Color_15_LinkVisited="255,0,255,255" 71 | Color_16_AlternateBase="246,246,246,255" 72 | Color_17_NoRole="0,0,0,255" 73 | Color_18_ToolTipBase="255,255,220,255" 74 | Color_19_ToolTipText="0,0,0,255" 75 | Color_1_Button="240,240,240,255" 76 | Color_2_Light="255,255,255,255" 77 | Color_3_Midlight="227,227,227,255" 78 | Color_4_Dark="160,160,160,255" 79 | Color_5_Mid="160,160,160,255" 80 | Color_6_Text="0,0,0,255" 81 | Color_7_BrightText="255,255,255,255" 82 | Color_8_ButtonText="0,0,0,255" 83 | Color_9_Base="255,255,255,255" -------------------------------------------------------------------------------- /Src/PowerGate.ini: -------------------------------------------------------------------------------- 1 | [Strategies] 2 | e:/Workshop/YuanLang/Strategies/LiveTrading/commander/Random.strat 3 | e:/Workshop/YuanLang/Strategies/LiveTrading/commander/Commander.strat 4 | -------------------------------------------------------------------------------- /Src/PowerGate.pro: -------------------------------------------------------------------------------- 1 | #------------------------------------------------- 2 | # 3 | # Project created by QtCreator 2014-10-31T21:23:59 4 | # 5 | #------------------------------------------------- 6 | 7 | QT += core gui 8 | 9 | greaterThan(QT_MAJOR_VERSION, 4): QT += widgets 10 | 11 | TRANSLATIONS += PowerGate.ts 12 | 13 | TARGET = PowerGate 14 | TEMPLATE = app 15 | 16 | INCLUDEPATH += e:/Workshop/YuanLang/Solution/ATS-SDK/Inc 17 | 18 | LIBS += e:/Workshop/YuanLang/Solution/ATS-SDK/Lib/AlgoSE.lib 19 | 20 | SOURCES += main.cpp \ 21 | apptheme.cpp \ 22 | dock_host.cpp \ 23 | logmodel.cpp \ 24 | posmodel.cpp \ 25 | ordermodel.cpp \ 26 | stratmodel.cpp \ 27 | quotemodel.cpp \ 28 | stratparamsdialog.cpp \ 29 | stratparamsmodel.cpp \ 30 | stratposmodel.cpp \ 31 | stratposdialog.cpp \ 32 | stratlogmodel.cpp \ 33 | powergate.cpp \ 34 | authdialog.cpp \ 35 | quotedialog.cpp \ 36 | stratcmddialog.cpp \ 37 | subscribedialog.cpp \ 38 | logindialog.cpp \ 39 | loginsettingsdialog.cpp \ 40 | editbkrdialog.cpp \ 41 | tradepanel.cpp \ 42 | main.cpp 43 | 44 | HEADERS += apptheme.h \ 45 | dock_host.h \ 46 | logmodel.h \ 47 | posmodel.h \ 48 | ordermodel.h \ 49 | stratmodel.h \ 50 | quotemodel.h \ 51 | stratparamsdialog.h \ 52 | stratparamsmodel.h \ 53 | stratposdialog.h \ 54 | powergate.h \ 55 | authdialog.h \ 56 | quotedialog.h \ 57 | stratcmddialog.h \ 58 | subscribedialog.h 59 | 60 | FORMS += \ 61 | powergate.ui \ 62 | stratparams.ui \ 63 | stratpos.ui \ 64 | authdialog.ui \ 65 | quotedialog.ui \ 66 | stratcmd.ui \ 67 | subscribedialog.ui \ 68 | stratlog.ui \ 69 | logindialog.ui \ 70 | loginsettingsdialog.ui \ 71 | editbkrdialog.ui \ 72 | tradepanel.ui 73 | 74 | RESOURCES = PowerGate.qrc 75 | -------------------------------------------------------------------------------- /Src/PowerGate.qm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/algosenses/PowerGate/7996dec6889ce59f5dc1c145aebd61b7ab28f031/Src/PowerGate.qm -------------------------------------------------------------------------------- /Src/PowerGate.qrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | Dark.thm 4 | Light.thm 5 | Gray.thm 6 | 7 | 8 | disconnect.png 9 | connect.png 10 | Letter-P-black-icon.png 11 | 12 | 13 | PowerGate.qm 14 | 15 | 16 | -------------------------------------------------------------------------------- /Src/QtATS.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 2013 4 | VisualStudioVersion = 12.0.21005.1 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "QtATS", "QtATS.vcxproj", "{D0F157EE-0BA5-3243-88B9-CA658635A816}" 7 | EndProject 8 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Commander", "Commander\Commander.vcxproj", "{12871BF0-8E10-4384-BF1C-E88A1F6172C5}" 9 | EndProject 10 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Random", "Random\Random.vcxproj", "{F70DF40F-0C32-440C-9CCA-B7834ECC15A0}" 11 | EndProject 12 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MMAD", "..\..\Strategies\LiveTrading\MMAD\MMAD.vcxproj", "{4AE3D5AA-9FC6-4688-9CA4-03C84FD11B02}" 13 | EndProject 14 | Global 15 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 16 | Debug|Win32 = Debug|Win32 17 | Release|Win32 = Release|Win32 18 | EndGlobalSection 19 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 20 | {D0F157EE-0BA5-3243-88B9-CA658635A816}.Debug|Win32.ActiveCfg = Debug|Win32 21 | {D0F157EE-0BA5-3243-88B9-CA658635A816}.Debug|Win32.Build.0 = Debug|Win32 22 | {D0F157EE-0BA5-3243-88B9-CA658635A816}.Release|Win32.ActiveCfg = Release|Win32 23 | {D0F157EE-0BA5-3243-88B9-CA658635A816}.Release|Win32.Build.0 = Release|Win32 24 | {12871BF0-8E10-4384-BF1C-E88A1F6172C5}.Debug|Win32.ActiveCfg = Debug|Win32 25 | {12871BF0-8E10-4384-BF1C-E88A1F6172C5}.Debug|Win32.Build.0 = Debug|Win32 26 | {12871BF0-8E10-4384-BF1C-E88A1F6172C5}.Release|Win32.ActiveCfg = Release|Win32 27 | {12871BF0-8E10-4384-BF1C-E88A1F6172C5}.Release|Win32.Build.0 = Release|Win32 28 | {F70DF40F-0C32-440C-9CCA-B7834ECC15A0}.Debug|Win32.ActiveCfg = Debug|Win32 29 | {F70DF40F-0C32-440C-9CCA-B7834ECC15A0}.Debug|Win32.Build.0 = Debug|Win32 30 | {F70DF40F-0C32-440C-9CCA-B7834ECC15A0}.Release|Win32.ActiveCfg = Release|Win32 31 | {F70DF40F-0C32-440C-9CCA-B7834ECC15A0}.Release|Win32.Build.0 = Release|Win32 32 | {4AE3D5AA-9FC6-4688-9CA4-03C84FD11B02}.Debug|Win32.ActiveCfg = Debug|Win32 33 | {4AE3D5AA-9FC6-4688-9CA4-03C84FD11B02}.Debug|Win32.Build.0 = Debug|Win32 34 | {4AE3D5AA-9FC6-4688-9CA4-03C84FD11B02}.Release|Win32.ActiveCfg = Release|Win32 35 | {4AE3D5AA-9FC6-4688-9CA4-03C84FD11B02}.Release|Win32.Build.0 = Release|Win32 36 | EndGlobalSection 37 | GlobalSection(SolutionProperties) = preSolution 38 | HideSolutionNode = FALSE 39 | EndGlobalSection 40 | EndGlobal 41 | -------------------------------------------------------------------------------- /Src/RestartAPI.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "RestartAPI.h" 6 | 7 | #pragma comment(lib, "Shlwapi.lib") 8 | 9 | // Global Variables 10 | HANDLE g_RA_hMutexOtherRestarting = NULL; // Mutex 11 | BOOL g_RA_bWasRestarted = FALSE; // Restarted Flag 12 | 13 | BOOL RA_CheckProcessWasRestarted() 14 | { 15 | return g_RA_bWasRestarted; 16 | } 17 | 18 | BOOL RA_CheckForRestartProcessStart() 19 | { 20 | // Simple find substring in command line 21 | LPTSTR szCmdLine = ::GetCommandLine(); 22 | 23 | return ::StrStr(szCmdLine, RA_CMDLINE_RESTART_PROCESS) != NULL; 24 | } 25 | 26 | BOOL RA_WaitForPreviousProcessFinish() 27 | { 28 | TCHAR szAppPath[MAX_PATH] = { 0 }; 29 | ::GetModuleFileName(NULL, szAppPath, MAX_PATH); 30 | 31 | // http://stackoverflow.com/questions/20714120/could-not-find-a-part-of-the-path-error-while-creating-mutex/20714164#20714164 32 | /* On a server that is running Terminal Services, a named system mutex can have two levels of visibility. 33 | If its name begins with the prefix "Global\", the mutex is visible in all terminal server sessions. 34 | If its name begins with the prefix "Local\", the mutex is visible only in the terminal server session 35 | where it was created. In that case, a separate mutex with the same name can exist in each of the other 36 | terminal server sessions on the server. If you do not specify a prefix when you create a named mutex, 37 | it takes the prefix "Local\". Within a terminal server session, two mutexes whose names differ only by 38 | their prefixes are separate mutexes, and both are visible to all processes in the terminal server session. 39 | That is, the prefix names "Global\" and "Local\" describe the scope of the mutex name relative to terminal 40 | server sessions, not relative to processes. 41 | 42 | Because there were backslash in szAppPath (\) it assumes you are trying to specify a visibility level, 43 | and then discovers it isn't a valid visibility level - hence generating the exception. 44 | In short, mutex name had '\' in it, which windows was interpreting as a path character. So we replace all 45 | '\' with '-'. 46 | */ 47 | LPTSTR ptr = ::StrChr(szAppPath, TEXT('\\')); 48 | while (ptr != NULL) { 49 | *ptr = TEXT('-'); 50 | ptr = ::StrChr(szAppPath, TEXT('\\')); 51 | } 52 | 53 | // App restarting 54 | BOOL AlreadyRunning; 55 | // Try to Create Mutex 56 | g_RA_hMutexOtherRestarting = ::CreateMutex( NULL, FALSE, szAppPath); 57 | DWORD dwLastError = ::GetLastError(); 58 | AlreadyRunning = (dwLastError == ERROR_ALREADY_EXISTS || dwLastError == ERROR_ACCESS_DENIED); 59 | if ( AlreadyRunning ) 60 | { 61 | // Waiting for previous instance release mutex 62 | ::WaitForSingleObject(g_RA_hMutexOtherRestarting, INFINITE); 63 | ::ReleaseMutex(g_RA_hMutexOtherRestarting); 64 | g_RA_bWasRestarted = TRUE; 65 | } 66 | ::CloseHandle(g_RA_hMutexOtherRestarting); 67 | g_RA_hMutexOtherRestarting = NULL; 68 | return TRUE; 69 | } 70 | 71 | BOOL RA_DoRestartProcessFinish() 72 | { 73 | // Releasing mutex signal that process finished 74 | DWORD dwWaitResult = WaitForSingleObject(g_RA_hMutexOtherRestarting, 0); 75 | if (dwWaitResult == WAIT_TIMEOUT) 76 | ::ReleaseMutex(g_RA_hMutexOtherRestarting); 77 | ::CloseHandle(g_RA_hMutexOtherRestarting); 78 | g_RA_hMutexOtherRestarting = NULL; 79 | return (dwWaitResult == WAIT_TIMEOUT); 80 | } 81 | 82 | BOOL RA_ActivateRestartProcess() 83 | { 84 | TCHAR szAppPath[MAX_PATH] = {0}; 85 | ::GetModuleFileName(NULL, szAppPath, MAX_PATH); 86 | 87 | LPTSTR ptr = ::StrChr(szAppPath, TEXT('\\')); 88 | while (ptr != NULL) { 89 | *ptr = TEXT('-'); 90 | ptr = ::StrChr(szAppPath, TEXT('\\')); 91 | } 92 | 93 | // Restart App 94 | BOOL AlreadyRunning; 95 | g_RA_hMutexOtherRestarting = ::CreateMutex( NULL, TRUE, szAppPath); 96 | DWORD dwLastError = ::GetLastError(); 97 | AlreadyRunning = (dwLastError == ERROR_ALREADY_EXISTS || dwLastError == ERROR_ACCESS_DENIED); 98 | if (AlreadyRunning) 99 | { 100 | ::WaitForSingleObject(g_RA_hMutexOtherRestarting, INFINITE); 101 | ::ReleaseMutex(g_RA_hMutexOtherRestarting); 102 | ::CloseHandle(g_RA_hMutexOtherRestarting); 103 | return FALSE; 104 | } 105 | 106 | STARTUPINFO si = {0}; 107 | PROCESS_INFORMATION pi = {0}; 108 | si.cb = sizeof(STARTUPINFO); 109 | // Create New Instance command line 110 | ::GetModuleFileName(NULL, szAppPath, MAX_PATH); 111 | ::PathQuoteSpaces(szAppPath); 112 | ::lstrcat(szAppPath, _T(" ")); 113 | ::lstrcat(szAppPath, RA_CMDLINE_RESTART_PROCESS); // Add command line key for restart 114 | // Create another copy of processS 115 | return ::CreateProcess(NULL, szAppPath, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi); 116 | } 117 | -------------------------------------------------------------------------------- /Src/RestartAPI.h: -------------------------------------------------------------------------------- 1 | #ifndef RESTART_API_H 2 | #define RESTART_API_H 3 | 4 | // Command line switch for restarted application 5 | #ifndef RA_CMDLINE_RESTART_PROCESS 6 | #define RA_CMDLINE_RESTART_PROCESS TEXT("--Restart") 7 | #endif 8 | 9 | // Mutex unique name 10 | #ifndef RA_MUTEX_OTHER_RESTARTING 11 | #define RA_MUTEX_OTHER_RESTARTING TEXT("YOUR_RESTART-MUTEX_NAME") 12 | #endif 13 | 14 | // Return TRUE if Process was restarted 15 | BOOL RA_CheckProcessWasRestarted(); 16 | 17 | // Check process command line for restart switch 18 | // Call this function to check that is restarted instance 19 | BOOL RA_CheckForRestartProcessStart(); 20 | 21 | // Wait till previous instance of process finish 22 | BOOL RA_WaitForPreviousProcessFinish(); 23 | 24 | // Call it when process finish 25 | BOOL RA_DoRestartProcessFinish(); 26 | 27 | // Call this function when you need restart application 28 | // After call you must close an active instance of your application 29 | BOOL RA_ActivateRestartProcess(); 30 | 31 | #endif // RESTART_API_H 32 | -------------------------------------------------------------------------------- /Src/Semaphore.h: -------------------------------------------------------------------------------- 1 | //--------------------------------------------------------- 2 | // For conditions of distribution and use, see 3 | // https://github.com/preshing/cpp11-on-multicore/blob/master/LICENSE 4 | //--------------------------------------------------------- 5 | 6 | #ifndef __CPP11OM_SEMAPHORE_H__ 7 | #define __CPP11OM_SEMAPHORE_H__ 8 | 9 | #include 10 | #include 11 | 12 | namespace Utils 13 | { 14 | 15 | #if defined(_WIN32) 16 | //--------------------------------------------------------- 17 | // Semaphore (Windows) 18 | //--------------------------------------------------------- 19 | 20 | #include 21 | #undef min 22 | #undef max 23 | 24 | class Semaphore 25 | { 26 | private: 27 | HANDLE m_hSema; 28 | 29 | Semaphore(const Semaphore& other) = delete; 30 | Semaphore& operator=(const Semaphore& other) = delete; 31 | 32 | public: 33 | Semaphore(int initialCount = 0) 34 | { 35 | assert(initialCount >= 0); 36 | m_hSema = CreateSemaphore(NULL, initialCount, MAXLONG, NULL); 37 | } 38 | 39 | ~Semaphore() 40 | { 41 | CloseHandle(m_hSema); 42 | } 43 | 44 | void wait() 45 | { 46 | WaitForSingleObject(m_hSema, INFINITE); 47 | } 48 | 49 | void signal(int count = 1) 50 | { 51 | ReleaseSemaphore(m_hSema, count, NULL); 52 | } 53 | }; 54 | 55 | 56 | #elif defined(__MACH__) 57 | //--------------------------------------------------------- 58 | // Semaphore (Apple iOS and OSX) 59 | // Can't use POSIX semaphores due to http://lists.apple.com/archives/darwin-kernel/2009/Apr/msg00010.html 60 | //--------------------------------------------------------- 61 | 62 | #include 63 | 64 | class Semaphore 65 | { 66 | private: 67 | semaphore_t m_sema; 68 | 69 | Semaphore(const Semaphore& other) = delete; 70 | Semaphore& operator=(const Semaphore& other) = delete; 71 | 72 | public: 73 | Semaphore(int initialCount = 0) 74 | { 75 | assert(initialCount >= 0); 76 | semaphore_create(mach_task_self(), &m_sema, SYNC_POLICY_FIFO, initialCount); 77 | } 78 | 79 | ~Semaphore() 80 | { 81 | semaphore_destroy(mach_task_self(), m_sema); 82 | } 83 | 84 | void wait() 85 | { 86 | semaphore_wait(m_sema); 87 | } 88 | 89 | void signal() 90 | { 91 | semaphore_signal(m_sema); 92 | } 93 | 94 | void signal(int count) 95 | { 96 | while (count-- > 0) 97 | { 98 | semaphore_signal(m_sema); 99 | } 100 | } 101 | }; 102 | 103 | 104 | #elif defined(__unix__) 105 | //--------------------------------------------------------- 106 | // Semaphore (POSIX, Linux) 107 | //--------------------------------------------------------- 108 | 109 | #include 110 | 111 | class Semaphore 112 | { 113 | private: 114 | sem_t m_sema; 115 | 116 | Semaphore(const Semaphore& other) = delete; 117 | Semaphore& operator=(const Semaphore& other) = delete; 118 | 119 | public: 120 | Semaphore(int initialCount = 0) 121 | { 122 | assert(initialCount >= 0); 123 | sem_init(&m_sema, 0, initialCount); 124 | } 125 | 126 | ~Semaphore() 127 | { 128 | sem_destroy(&m_sema); 129 | } 130 | 131 | void wait() 132 | { 133 | // http://stackoverflow.com/questions/2013181/gdb-causes-sem-wait-to-fail-with-eintr-error 134 | int rc; 135 | do 136 | { 137 | rc = sem_wait(&m_sema); 138 | } while (rc == -1 && errno == EINTR); 139 | } 140 | 141 | void signal() 142 | { 143 | sem_post(&m_sema); 144 | } 145 | 146 | void signal(int count) 147 | { 148 | while (count-- > 0) 149 | { 150 | sem_post(&m_sema); 151 | } 152 | } 153 | }; 154 | 155 | 156 | #else 157 | 158 | #error Unsupported platform! 159 | 160 | #endif 161 | 162 | 163 | //--------------------------------------------------------- 164 | // LightweightSemaphore 165 | //--------------------------------------------------------- 166 | class LightweightSemaphore 167 | { 168 | private: 169 | std::atomic m_count; 170 | Semaphore m_sema; 171 | 172 | void waitWithPartialSpinning() 173 | { 174 | int oldCount; 175 | // Is there a better way to set the initial spin count? 176 | // If we lower it to 1000, testBenaphore becomes 15x slower on my Core i7-5930K Windows PC, 177 | // as threads start hitting the kernel semaphore. 178 | int spin = 10000; 179 | while (spin--) 180 | { 181 | oldCount = m_count.load(std::memory_order_relaxed); 182 | if ((oldCount > 0) && m_count.compare_exchange_strong(oldCount, oldCount - 1, std::memory_order_acquire)) 183 | return; 184 | std::atomic_signal_fence(std::memory_order_acquire); // Prevent the compiler from collapsing the loop. 185 | } 186 | oldCount = m_count.fetch_sub(1, std::memory_order_acquire); 187 | if (oldCount <= 0) 188 | { 189 | m_sema.wait(); 190 | } 191 | } 192 | 193 | public: 194 | LightweightSemaphore(int initialCount = 0) : m_count(initialCount) 195 | { 196 | assert(initialCount >= 0); 197 | } 198 | 199 | bool tryWait() 200 | { 201 | int oldCount = m_count.load(std::memory_order_relaxed); 202 | return (oldCount > 0 && m_count.compare_exchange_strong(oldCount, oldCount - 1, std::memory_order_acquire)); 203 | } 204 | 205 | void wait() 206 | { 207 | if (!tryWait()) 208 | waitWithPartialSpinning(); 209 | } 210 | 211 | void signal(int count = 1) 212 | { 213 | int oldCount = m_count.fetch_add(count, std::memory_order_release); 214 | int toRelease = -oldCount < count ? -oldCount : count; 215 | if (toRelease > 0) 216 | { 217 | m_sema.signal(toRelease); 218 | } 219 | } 220 | }; 221 | 222 | 223 | typedef LightweightSemaphore DefaultSemaphoreType; 224 | 225 | } // namespace Utils 226 | 227 | #endif // __CPP11OM_SEMAPHORE_H__ -------------------------------------------------------------------------------- /Src/TinyCrypt.h: -------------------------------------------------------------------------------- 1 | #ifndef TINY_CRYPT_H 2 | #define TINY_CRYPT_H 3 | 4 | #include 5 | 6 | namespace TinyCrypt 7 | { 8 | 9 | class CryptObject { 10 | public: 11 | CryptObject(const unsigned char* key); 12 | ~CryptObject(); 13 | std::string encrypt(const std::string& text); 14 | std::string decrypt(const std::string& text); 15 | 16 | private: 17 | void* m_ctx; 18 | }; 19 | 20 | } // namespace TinyCrypt 21 | 22 | #endif // TINY_CRYPT_H -------------------------------------------------------------------------------- /Src/WinResource.rc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/algosenses/PowerGate/7996dec6889ce59f5dc1c145aebd61b7ab28f031/Src/WinResource.rc -------------------------------------------------------------------------------- /Src/apptheme.cpp: -------------------------------------------------------------------------------- 1 | // This file is part of Qt Bitcion Trader 2 | // https://github.com/JulyIGHOR/QtBitcoinTrader 3 | // Copyright (C) 2013-2014 July IGHOR 4 | // 5 | // This program is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // In addition, as a special exception, the copyright holders give 11 | // permission to link the code of portions of this program with the 12 | // OpenSSL library under certain conditions as described in each 13 | // individual source file, and distribute linked combinations including 14 | // the two. 15 | // 16 | // You must obey the GNU General Public License in all respects for all 17 | // of the code used other than OpenSSL. If you modify file(s) with this 18 | // exception, you may extend this exception to your version of the 19 | // file(s), but you are not obligated to do so. If you do not wish to do 20 | // so, delete this exception statement from your version. If you delete 21 | // this exception statement from all source files in the program, then 22 | // also delete it here. 23 | // 24 | // This program is distributed in the hope that it will be useful, 25 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 26 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 27 | // GNU General Public License for more details. 28 | // 29 | // You should have received a copy of the GNU General Public License 30 | // along with this program. If not, see . 31 | 32 | #include "apptheme.h" 33 | #include 34 | 35 | AppTheme::AppTheme() 36 | { 37 | gray=Qt::gray; 38 | altRowColor=QColor(240,240,240); 39 | lightGray=Qt::lightGray; 40 | red=Qt::red; 41 | green=Qt::green; 42 | blue=Qt::blue; 43 | lightRed.setRgb(255,200,200); 44 | lightGreen.setRgb(200,255,200); 45 | lightBlue.setRgb(200,200,255); 46 | lightGreenBlue.setRgb(200,255,255); 47 | lightRedBlue.setRgb(255,200,255); 48 | darkRedBlue.setRgb(155,100,155); 49 | lightRedGreen.setRgb(255,255,200); 50 | darkRed=Qt::darkRed; 51 | darkGreen=Qt::darkGreen; 52 | darkBlue=Qt::darkBlue; 53 | black=Qt::black; 54 | white=Qt::white; 55 | } 56 | 57 | QColor AppTheme::getColor(QString str) 58 | { 59 | QStringList colorList=str.split(","); 60 | if(colorList.count()<3)return Qt::black; 61 | if(colorList.count()<4)colorList<<"255"; 62 | return QColor(colorList.at(0).toInt(),colorList.at(1).toInt(),colorList.at(2).toInt(),colorList.at(3).toInt()); 63 | } 64 | 65 | void AppTheme::loadTheme(QString name) 66 | { 67 | // QSettings themeLoad(name+".thm",QSettings::IniFormat); 68 | QSettings themeLoad(QString(":/theme/") + name + ".thm", QSettings::IniFormat); 69 | 70 | themeLoad.beginGroup("Normal"); 71 | QStringList colorList=themeLoad.childKeys(); 72 | themeLoad.endGroup(); 73 | for(int n=0;n=20)continue; 80 | 81 | palette.setColor(QPalette::Normal,QPalette::ColorRole(colNum),getColor(themeLoad.value("Normal/"+colorList.at(n)).toString())); 82 | } 83 | 84 | themeLoad.beginGroup("Disabled"); 85 | colorList=themeLoad.childKeys(); 86 | themeLoad.endGroup(); 87 | for(int n=0;n=20)continue; 94 | 95 | palette.setColor(QPalette::Disabled,QPalette::ColorRole(colNum),getColor(themeLoad.value("Disabled/"+colorList.at(n)).toString())); 96 | } 97 | 98 | themeLoad.beginGroup("Inactive"); 99 | colorList=themeLoad.childKeys(); 100 | themeLoad.endGroup(); 101 | for(int n=0;n=20)continue; 108 | 109 | palette.setColor(QPalette::Inactive,QPalette::ColorRole(colNum),getColor(themeLoad.value("Inactive/"+colorList.at(n)).toString())); 110 | } 111 | 112 | altRowColor=palette.color(QPalette::AlternateBase); 113 | gray=getColor(themeLoad.value("Gray").toString()); 114 | red=getColor(themeLoad.value("Red").toString()); 115 | green=getColor(themeLoad.value("Green").toString()); 116 | blue=getColor(themeLoad.value("Blue").toString()); 117 | lightRed=getColor(themeLoad.value("LightRed").toString()); 118 | lightGreen=getColor(themeLoad.value("LightGreen").toString()); 119 | lightBlue=getColor(themeLoad.value("LightRedBlue").toString()); 120 | lightGreenBlue=getColor(themeLoad.value("LightGreenBlue").toString()); 121 | lightRedBlue=getColor(themeLoad.value("LightRedBlue").toString()); 122 | darkRedBlue=getColor(themeLoad.value("DarkRedBlue").toString()); 123 | lightRedGreen=getColor(themeLoad.value("LightRedGreen").toString()); 124 | darkRed=getColor(themeLoad.value("DarkRed").toString()); 125 | darkGreen=getColor(themeLoad.value("DarkGreen").toString()); 126 | darkBlue=getColor(themeLoad.value("DarkBlue").toString()); 127 | black=getColor(themeLoad.value("Black").toString()); 128 | white=getColor(themeLoad.value("White").toString()); 129 | 130 | palette.setColor(QPalette::Text,black); 131 | 132 | styleSheet="QHeaderView::section {color: "+black.name()+";}" 133 | "QToolButton {color: "+black.name()+";}" 134 | "QPushButton {color: "+black.name()+";}" 135 | "QGroupBox {background: rgba(255,255,255,60); color: "+black.name()+"; border: 1px solid "+gray.name()+";border-radius: 3px;margin-top: 8px;}" 136 | "QGroupBox:title {subcontrol-origin: margin; position: relative; left: 6px; color: "+black.name()+"; background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 transparent, stop: 0.45 "+white.name()+", stop: 0.5 "+white.name()+", stop: 0.55 "+white.name()+", stop: 1.0 transparent); padding-left: 2px;} QLabel {color: "+black.name()+";}" 137 | "QTabBar::tab {color: "+black.name()+";}" 138 | "QRadioButton {color: "+black.name()+";}" 139 | "QDoubleSpinBox {background: "+white.name()+";}" 140 | "QTextEdit {background: "+white.name()+";}" 141 | "QPlainTextEdit {background: "+white.name()+";}" 142 | "QCheckBox {color: "+black.name()+";}" 143 | "QLineEdit {color: "+black.name()+"; background: "+white.name()+"; border: 1px solid "+gray.name()+";}"; 144 | } 145 | -------------------------------------------------------------------------------- /Src/apptheme.h: -------------------------------------------------------------------------------- 1 | // This file is part of Qt Bitcion Trader 2 | // https://github.com/JulyIGHOR/QtBitcoinTrader 3 | // Copyright (C) 2013-2014 July IGHOR 4 | // 5 | // This program is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // In addition, as a special exception, the copyright holders give 11 | // permission to link the code of portions of this program with the 12 | // OpenSSL library under certain conditions as described in each 13 | // individual source file, and distribute linked combinations including 14 | // the two. 15 | // 16 | // You must obey the GNU General Public License in all respects for all 17 | // of the code used other than OpenSSL. If you modify file(s) with this 18 | // exception, you may extend this exception to your version of the 19 | // file(s), but you are not obligated to do so. If you do not wish to do 20 | // so, delete this exception statement from your version. If you delete 21 | // this exception statement from all source files in the program, then 22 | // also delete it here. 23 | // 24 | // This program is distributed in the hope that it will be useful, 25 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 26 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 27 | // GNU General Public License for more details. 28 | // 29 | // You should have received a copy of the GNU General Public License 30 | // along with this program. If not, see . 31 | 32 | #ifndef APPTHEME_H 33 | #define APPTHEME_H 34 | 35 | #include 36 | #include 37 | #include 38 | #include 39 | 40 | struct AppTheme 41 | { 42 | AppTheme(); 43 | void loadTheme(QString); 44 | QString styleSheet; 45 | QColor getColor(QString); 46 | QPalette palette; 47 | QColor swapColor(QColor color); 48 | QColor altRowColor; 49 | QColor gray; 50 | QColor lightGray; 51 | QColor red; 52 | QColor green; 53 | QColor blue; 54 | QColor lightRed; 55 | QColor lightGreen; 56 | QColor lightBlue; 57 | QColor darkRed; 58 | QColor darkGreen; 59 | QColor darkBlue; 60 | QColor lightRedGreen; 61 | QColor lightGreenBlue; 62 | QColor lightRedBlue; 63 | QColor darkRedBlue; 64 | QColor black; 65 | QColor white; 66 | }; 67 | 68 | #endif // APPTHEME_H 69 | -------------------------------------------------------------------------------- /Src/authdialog.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "authdialog.h" 3 | #include "config.h" 4 | #include "authentication.h" 5 | 6 | AuthDialog::AuthDialog(QWidget* parent) 7 | : QDialog(parent) 8 | { 9 | ui.setupUi(this); 10 | connect(ui.okBtn, SIGNAL(clicked()), this, SLOT(buttonOkClicked())); 11 | connect(ui.cancelBtn, SIGNAL(clicked()), this, SLOT(buttonCancelClicked())); 12 | 13 | srvIp[0] = '\0'; 14 | 15 | rude::Config config; 16 | if (config.load("QtATS.ini")) { 17 | config.setSection("Authentication"); 18 | const char* ip = config.getStringValue("SrvIp"); 19 | if (ip) { 20 | strcpy(srvIp, ip); 21 | srvPort = config.getIntValue("SrvPort"); 22 | } 23 | } 24 | } 25 | 26 | AuthDialog::~AuthDialog() 27 | { 28 | } 29 | 30 | void AuthDialog::buttonOkClicked() 31 | { 32 | std::string username = ui.username->text().toStdString(); 33 | std::string passwd = ui.passwd->text().toStdString(); 34 | 35 | if (srvIp[0] != '\0') { 36 | char name[32] = { 0 }; 37 | char pwd[32] = { 0 }; 38 | strncpy(name, username.c_str(), sizeof(name)-1); 39 | strncpy(pwd, passwd.c_str(), sizeof(pwd)-1); 40 | 41 | ui.username->setDisabled(true); 42 | ui.passwd->setDisabled(true); 43 | ui.okBtn->setDisabled(true); 44 | ui.cancelBtn->setDisabled(true); 45 | 46 | if (authenticate(username.c_str(), passwd.c_str(), srvIp, srvPort) == 1) { 47 | setWindowTitle("Authenticated!"); 48 | accept(); 49 | } else { 50 | setWindowTitle("Authenticate failed!"); 51 | } 52 | 53 | ui.username->setEnabled(true); 54 | ui.passwd->setEnabled(true); 55 | ui.okBtn->setEnabled(true); 56 | ui.cancelBtn->setEnabled(true); 57 | } 58 | } 59 | 60 | void AuthDialog::buttonCancelClicked() 61 | { 62 | reject(); 63 | } -------------------------------------------------------------------------------- /Src/authdialog.h: -------------------------------------------------------------------------------- 1 | #ifndef AUTH_DIALOG_H 2 | #define AUTH_DIALOG_H 3 | 4 | #include 5 | #include "ui_authdialog.h" 6 | 7 | class AuthDialog : public QDialog 8 | { 9 | Q_OBJECT 10 | 11 | public: 12 | AuthDialog(QWidget* parent = 0); 13 | ~AuthDialog(); 14 | 15 | private: 16 | Ui::AuthDlg ui; 17 | char srvIp[64]; 18 | int srvPort; 19 | 20 | private slots: 21 | void buttonOkClicked(); 22 | void buttonCancelClicked(); 23 | }; 24 | 25 | #endif // AUTH_DIALOG_H -------------------------------------------------------------------------------- /Src/authdialog.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | AuthDlg 4 | 5 | 6 | 7 | 0 8 | 0 9 | 300 10 | 112 11 | 12 | 13 | 14 | 15 | 0 16 | 0 17 | 18 | 19 | 20 | 21 | 300 22 | 112 23 | 24 | 25 | 26 | 27 | 300 28 | 112 29 | 30 | 31 | 32 | Authentication 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | Qt::Horizontal 41 | 42 | 43 | 44 | 40 45 | 20 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | Ok 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 0 62 | 1 63 | 64 | 65 | 66 | Cancle 67 | 68 | 69 | 70 | 71 | 72 | 73 | Qt::Horizontal 74 | 75 | 76 | 77 | 40 78 | 20 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | Username: 91 | 92 | 93 | Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 1677721 102 | 16777215 103 | 104 | 105 | 106 | Password: 107 | 108 | 109 | Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 0 118 | 1 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 0 128 | 1 129 | 130 | 131 | 132 | QLineEdit::Password 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | username 142 | passwd 143 | okBtn 144 | cancelBtn 145 | 146 | 147 | 148 | 149 | -------------------------------------------------------------------------------- /Src/authentication.h: -------------------------------------------------------------------------------- 1 | #ifndef AUTHENTICATION_H 2 | #define AUTHENTICATION_H 3 | 4 | int authenticate(const char* username, const char* passwd, const char* srvIp, int port); 5 | 6 | #endif 7 | -------------------------------------------------------------------------------- /Src/connect.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/algosenses/PowerGate/7996dec6889ce59f5dc1c145aebd61b7ab28f031/Src/connect.png -------------------------------------------------------------------------------- /Src/disconnect.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/algosenses/PowerGate/7996dec6889ce59f5dc1c145aebd61b7ab28f031/Src/disconnect.png -------------------------------------------------------------------------------- /Src/dock_host.cpp: -------------------------------------------------------------------------------- 1 | // This file is part of Qt Bitcion Trader 2 | // https://github.com/JulyIGHOR/QtBitcoinTrader 3 | // Copyright (C) 2013-2015 July IGHOR 4 | // 5 | // This program is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // In addition, as a special exception, the copyright holders give 11 | // permission to link the code of portions of this program with the 12 | // OpenSSL library under certain conditions as described in each 13 | // individual source file, and distribute linked combinations including 14 | // the two. 15 | // 16 | // You must obey the GNU General Public License in all respects for all 17 | // of the code used other than OpenSSL. If you modify file(s) with this 18 | // exception, you may extend this exception to your version of the 19 | // file(s), but you are not obligated to do so. If you do not wish to do 20 | // so, delete this exception statement from your version. If you delete 21 | // this exception statement from all source files in the program, then 22 | // also delete it here. 23 | // 24 | // This program is distributed in the hope that it will be useful, 25 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 26 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 27 | // GNU General Public License for more details. 28 | // 29 | // You should have received a copy of the GNU General Public License 30 | // along with this program. If not, see . 31 | 32 | #include "dock_host.h" 33 | 34 | #include 35 | #include 36 | #include 37 | #include 38 | 39 | 40 | DockHost::DockHost(QObject* parent) : 41 | QObject (parent), 42 | widgets (), 43 | dockToggling (NULL) 44 | { 45 | // 46 | } 47 | 48 | DockHost::~DockHost() 49 | { 50 | // 51 | } 52 | 53 | QDockWidget* DockHost::createDock(QWidget* parent, QWidget* widget, const QString &title) 54 | { 55 | static int counter = 0; 56 | QDockWidget* dock = new QDockWidget(parent); 57 | dock->setObjectName(QString("dock%1").arg(++counter)); 58 | 59 | QMargins widgetMargins = widget->layout()->contentsMargins(); 60 | widgetMargins.setTop(widgetMargins.top()+2); 61 | widget->layout()->setContentsMargins(widgetMargins); 62 | dock->setWidget(widget); 63 | dock->setWindowTitle(title); 64 | 65 | QObject::connect(dock, &QDockWidget::topLevelChanged, this, &DockHost::onDockTopLevelChanged); 66 | QObject::connect(dock, &QDockWidget::visibilityChanged, this, &DockHost::onDockVisibilityChanged); 67 | QObject::connect(dock, &QDockWidget::featuresChanged, this, &DockHost::onDockFeaturesChanged); 68 | 69 | QAction* action = dock->toggleViewAction(); 70 | action->disconnect(); 71 | QObject::connect(action, &QAction::triggered, this, &DockHost::onDockActionTriggered); 72 | 73 | dock->installEventFilter(this); 74 | 75 | widgets << widget; 76 | return dock; 77 | } 78 | 79 | void DockHost::lockDocks(bool lock) 80 | { 81 | Q_FOREACH(QWidget* widget, widgets) { 82 | QDockWidget* dock = static_cast(widget->parentWidget()); 83 | if (dock) { 84 | if (lock) { 85 | if (dock->isFloating()) { 86 | dock->setFeatures(QDockWidget::DockWidgetFloatable); 87 | dock->setAllowedAreas(Qt::NoDockWidgetArea); 88 | } else { 89 | dock->setFeatures(QDockWidget::NoDockWidgetFeatures); 90 | dock->setAllowedAreas(Qt::AllDockWidgetAreas); 91 | } 92 | } else { 93 | dock->setFeatures(QDockWidget::AllDockWidgetFeatures); 94 | dock->setAllowedAreas(Qt::AllDockWidgetAreas); 95 | } 96 | adjustFloatingWindowFlags(dock); 97 | } 98 | } 99 | } 100 | 101 | void DockHost::setFloatingVisible(bool visible) 102 | { 103 | Q_FOREACH(QWidget* widget, widgets) { 104 | QDockWidget* dock = static_cast(widget->parentWidget()); 105 | if (dock && dock->isFloating()) { 106 | dock->setVisible(visible); 107 | } 108 | } 109 | } 110 | 111 | bool DockHost::eventFilter(QObject* obj, QEvent* event) 112 | { 113 | QDockWidget* dock = static_cast(obj); 114 | if (dock && dock->isFloating() && event->type() == QEvent::NonClientAreaMouseButtonDblClick) { 115 | if (!isConstrained(dock)) { 116 | return true; // handled. allow to minimize/maximize dock 117 | } 118 | if (dock->allowedAreas() == Qt::NoDockWidgetArea) { 119 | return true; // handled. forbid floating toggling. 120 | } 121 | } 122 | return QObject::eventFilter(obj, event); 123 | } 124 | 125 | void DockHost::onDockActionTriggered(bool checked) 126 | { 127 | Q_UNUSED(checked); 128 | QAction* action = static_cast(sender()); 129 | QDockWidget* dock = static_cast(action->parent()); 130 | if (dock) { 131 | if (dock->isVisible()) { 132 | dock->close(); 133 | } else { 134 | dockToggling = dock; 135 | dock->show(); 136 | dockToggling = NULL; 137 | } 138 | } 139 | } 140 | 141 | void DockHost::onDockTopLevelChanged() 142 | { 143 | QDockWidget* dock = static_cast(sender()); 144 | if (!dock->isFloating()) { 145 | selectTab(dock); 146 | } else { 147 | adjustFloatingWindowFlags(dock); 148 | } 149 | } 150 | 151 | void DockHost::onDockVisibilityChanged() 152 | { 153 | QDockWidget* dock = static_cast(sender()); 154 | if (!dock->isFloating() && dock->isVisible() && dockToggling == dock) { 155 | selectTab(dock); 156 | } 157 | } 158 | 159 | void DockHost::onDockFeaturesChanged(QDockWidget::DockWidgetFeatures features) 160 | { 161 | Q_UNUSED(features) 162 | QDockWidget* dock = static_cast(sender()); 163 | if (dock->isFloating() && dock->isVisible()) { 164 | adjustFloatingWindowFlags(dock); 165 | } 166 | } 167 | 168 | void DockHost::selectTab(QDockWidget* dock) 169 | { 170 | Q_FOREACH(QTabBar* tabBar, parent()->findChildren()) { 171 | for (int i = 0; i < tabBar->count(); ++i) { 172 | if (dock == (QWidget*) tabBar->tabData(i).toULongLong()) { 173 | tabBar->setCurrentIndex(i); 174 | tabBar->sizePolicy().setVerticalPolicy(QSizePolicy::Expanding); 175 | return; 176 | } 177 | } 178 | } 179 | } 180 | 181 | void DockHost::adjustFloatingWindowFlags(QDockWidget* dock) 182 | { 183 | if (dock->isFloating()) { 184 | Qt::WindowFlags flags = Qt::Window | Qt::CustomizeWindowHint | Qt::WindowTitleHint; 185 | if (dock->features() & QDockWidget::DockWidgetClosable) { 186 | flags |= Qt::WindowCloseButtonHint; 187 | } 188 | if (!isConstrained(dock)) { 189 | flags |= Qt::WindowMinMaxButtonsHint; 190 | } 191 | dock->setWindowFlags(flags); 192 | dock->show(); 193 | } 194 | } 195 | 196 | bool DockHost::isConstrained(QDockWidget* dock) 197 | { 198 | QSize size = dock->widget()->maximumSize(); 199 | return size.width() != QWIDGETSIZE_MAX || size.height() != QWIDGETSIZE_MAX; 200 | } 201 | -------------------------------------------------------------------------------- /Src/dock_host.h: -------------------------------------------------------------------------------- 1 | // This file is part of Qt Bitcion Trader 2 | // https://github.com/JulyIGHOR/QtBitcoinTrader 3 | // Copyright (C) 2013-2015 July IGHOR 4 | // 5 | // This program is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // In addition, as a special exception, the copyright holders give 11 | // permission to link the code of portions of this program with the 12 | // OpenSSL library under certain conditions as described in each 13 | // individual source file, and distribute linked combinations including 14 | // the two. 15 | // 16 | // You must obey the GNU General Public License in all respects for all 17 | // of the code used other than OpenSSL. If you modify file(s) with this 18 | // exception, you may extend this exception to your version of the 19 | // file(s), but you are not obligated to do so. If you do not wish to do 20 | // so, delete this exception statement from your version. If you delete 21 | // this exception statement from all source files in the program, then 22 | // also delete it here. 23 | // 24 | // This program is distributed in the hope that it will be useful, 25 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 26 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 27 | // GNU General Public License for more details. 28 | // 29 | // You should have received a copy of the GNU General Public License 30 | // along with this program. If not, see . 31 | 32 | #pragma once 33 | 34 | #include 35 | #include 36 | 37 | 38 | class QDockWidget; 39 | 40 | 41 | class DockHost : public QObject 42 | { 43 | Q_OBJECT 44 | 45 | public: 46 | DockHost(QObject* parent = NULL); 47 | ~DockHost(); 48 | 49 | public: 50 | QDockWidget* createDock(QWidget* parent, QWidget* widget, const QString& title); 51 | void lockDocks(bool lock); 52 | void setFloatingVisible(bool visible); 53 | 54 | protected: 55 | bool eventFilter(QObject* obj, QEvent* event) Q_DECL_OVERRIDE; 56 | 57 | private Q_SLOTS: 58 | void onDockActionTriggered(bool checked = false); 59 | void onDockTopLevelChanged(); 60 | void onDockVisibilityChanged(); 61 | void onDockFeaturesChanged(QDockWidget::DockWidgetFeatures features); 62 | 63 | private: 64 | void selectTab(QDockWidget* dock); 65 | void adjustFloatingWindowFlags(QDockWidget* dock); 66 | bool isConstrained(QDockWidget* dock); 67 | 68 | private: 69 | QList widgets; 70 | QDockWidget* dockToggling; 71 | }; 72 | -------------------------------------------------------------------------------- /Src/editbkrdialog.h: -------------------------------------------------------------------------------- 1 | #ifndef EDIT_BROKER_DIALOG_H 2 | #define EDIT_BROKER_DIALOG_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include "ui_editbkrdialog.h" 8 | #include "logindialog.h" 9 | 10 | class BrokerServersDelegate : public QStyledItemDelegate 11 | { 12 | Q_OBJECT 13 | 14 | public: 15 | BrokerServersDelegate(QObject *parent = 0); 16 | 17 | QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, 18 | const QModelIndex &index) const; 19 | 20 | void setEditorData(QWidget *editor, const QModelIndex &index) const; 21 | void setModelData(QWidget *editor, QAbstractItemModel *model, 22 | const QModelIndex &index) const; 23 | 24 | void updateEditorGeometry(QWidget *editor, 25 | const QStyleOptionViewItem &option, const QModelIndex &index) const; 26 | }; 27 | 28 | class BrokerServersModel : public QAbstractItemModel 29 | { 30 | Q_OBJECT 31 | 32 | public: 33 | BrokerServersModel(std::vector& srvs, QObject* parent); 34 | ~BrokerServersModel(); 35 | 36 | QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const; 37 | QModelIndex parent(const QModelIndex &index) const; 38 | 39 | QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; 40 | bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole); 41 | Qt::ItemFlags flags(const QModelIndex &index) const; 42 | QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; 43 | 44 | int rowCount(const QModelIndex &parent = QModelIndex()) const; 45 | int columnCount(const QModelIndex &parent = QModelIndex()) const; 46 | 47 | void insertNewRow(); 48 | void removeRow(int row); 49 | void reset(); 50 | int getServerList(std::vector& out); 51 | 52 | private: 53 | QStringList headerLabels; 54 | QList itemsList; 55 | }; 56 | 57 | class EditBkrDialog : public QDialog 58 | { 59 | Q_OBJECT 60 | 61 | public: 62 | EditBkrDialog(std::list& brokers, 63 | std::string& bkrName, std::string& bkrID, std::string& srvName, 64 | QWidget* parent = 0); 65 | ~EditBkrDialog(); 66 | const std::string& getCurrBkrName() const; 67 | const std::string& getCurrBkrID() const; 68 | const std::string& getCurrSrvName() const; 69 | 70 | private slots: 71 | void tradingAddBtnClicked(); 72 | void tradingDeleteBtnClicked(); 73 | void mdAddBtnClicked(); 74 | void mdDeleteBtnClicked(); 75 | void createNewBtnClicked(); 76 | void deleteBtnClicked(); 77 | void okBtnClicked(); 78 | void cancelBtnClicked(); 79 | 80 | private: 81 | void showErrorTips(QString& tips); 82 | bool checkFieldsValue(); 83 | void deleteBrokerConfig(); 84 | void motifyBrokerConfig(); 85 | void addBrokerConfig(); 86 | 87 | private: 88 | Ui::EditBkrDlg ui; 89 | 90 | std::list& brokers; 91 | 92 | BrokerServersModel* tradingSrvsModel; 93 | BrokerServersDelegate* tradingSrvsDelegate; 94 | 95 | BrokerServersModel* mdSrvsModel; 96 | BrokerServersDelegate* mdSrvsDelegate; 97 | 98 | enum { 99 | MODE_MOTIFY, 100 | MODE_CREATE_NEW, 101 | }; 102 | 103 | int currEditMode; 104 | 105 | std::string origBkrName; 106 | std::string origBkrID; 107 | std::string origSrvName; 108 | 109 | std::string currBkrName; 110 | std::string currBkrID; 111 | std::string currSrvName; 112 | }; 113 | 114 | #endif // EDIT_BROKER_DIALOG_H -------------------------------------------------------------------------------- /Src/editbkrdialog.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | EditBkrDlg 4 | 5 | 6 | 7 | 0 8 | 0 9 | 564 10 | 623 11 | 12 | 13 | 14 | Edit 15 | 16 | 17 | 18 | 19 | 20 | Qt::Horizontal 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | Broker ID: 33 | 34 | 35 | Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter 36 | 37 | 38 | 39 | 40 | 41 | 42 | Qt::Horizontal 43 | 44 | 45 | 46 | 40 47 | 20 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | Server Name: 56 | 57 | 58 | Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | Qt::Horizontal 69 | 70 | 71 | 72 | 40 73 | 20 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | Broker Name: 82 | 83 | 84 | Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | Qt::Horizontal 95 | 96 | 97 | 98 | 40 99 | 20 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | Trading 110 | 111 | 112 | 113 | 114 | 115 | QFrame::NoFrame 116 | 117 | 118 | QFrame::Plain 119 | 120 | 121 | true 122 | 123 | 124 | false 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | Qt::Horizontal 134 | 135 | 136 | 137 | 40 138 | 20 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | Add 147 | 148 | 149 | 150 | 151 | 152 | 153 | Delete 154 | 155 | 156 | 157 | 158 | 159 | 160 | Qt::Horizontal 161 | 162 | 163 | 164 | 40 165 | 20 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | MarketData 179 | 180 | 181 | 182 | 183 | 184 | QFrame::NoFrame 185 | 186 | 187 | QFrame::Plain 188 | 189 | 190 | true 191 | 192 | 193 | false 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | Qt::Horizontal 203 | 204 | 205 | 206 | 40 207 | 20 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | Add 216 | 217 | 218 | 219 | 220 | 221 | 222 | Delete 223 | 224 | 225 | 226 | 227 | 228 | 229 | Qt::Horizontal 230 | 231 | 232 | 233 | 40 234 | 20 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | Qt::Horizontal 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | Qt::Horizontal 257 | 258 | 259 | 260 | 40 261 | 20 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | Create New 270 | 271 | 272 | 273 | 274 | 275 | 276 | Delete 277 | 278 | 279 | 280 | 281 | 282 | 283 | Ok 284 | 285 | 286 | 287 | 288 | 289 | 290 | Cancel 291 | 292 | 293 | 294 | 295 | 296 | 297 | Qt::Horizontal 298 | 299 | 300 | 301 | 40 302 | 20 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | bkrNameLineEdit 313 | bkrIDLineEdit 314 | srvNameLineEdit 315 | tradingSrvs 316 | tradingAddBtn 317 | tradingDeleteBtn 318 | mdSrvs 319 | mdAddBtn 320 | mdDeleteBtn 321 | createNewBtn 322 | deleteBtn 323 | okBtn 324 | cancelBtn 325 | 326 | 327 | 328 | 329 | -------------------------------------------------------------------------------- /Src/logindialog.h: -------------------------------------------------------------------------------- 1 | #ifndef LOGIN_DIALOG_H 2 | #define LOGIN_DIALOG_H 3 | 4 | #include 5 | #include "Defines.h" 6 | #include "Engine.h" 7 | #include "ui_logindialog.h" 8 | 9 | using namespace AlgoSE; 10 | 11 | typedef struct { 12 | std::string address; 13 | int port; 14 | } ServerItem; 15 | 16 | typedef struct { 17 | std::string name; 18 | std::vector tradingSrvs; 19 | std::vector marketdataSrvs; 20 | } BrokerServer; 21 | 22 | typedef struct { 23 | std::string ID; 24 | std::string name; 25 | std::vector servers; 26 | } Broker; 27 | 28 | typedef struct { 29 | std::string displayName; 30 | std::string brokerName; 31 | std::string brokerID; 32 | std::string bkrSrvName; 33 | } BrokerSrvDisplayName; 34 | 35 | class LoginDialog : public QDialog 36 | { 37 | Q_OBJECT 38 | 39 | public: 40 | LoginDialog(Engine* engine, QWidget* parent = 0); 41 | ~LoginDialog(); 42 | 43 | private slots: 44 | void recvSystemLog(SystemLog log); 45 | void btnLoginClicked(); 46 | void btnExitClicked(); 47 | void btnEditBkrClicked(); 48 | void btnSettingsClicked(); 49 | void runAlgoSE(); 50 | 51 | private: 52 | bool parseBrokerXml(const char* file); 53 | void saveBrokerXml(const char* file); 54 | void readSettingsXml(const char* file); 55 | void saveSettingsXml(const char* file); 56 | void generateBkrDisplayNames(); 57 | void parseLogText(const char* log); 58 | void loadLocalStrategies(); 59 | 60 | private: 61 | Ui::LoginDlg ui; 62 | 63 | Engine* pAlgoSE; 64 | bool inprogress; 65 | 66 | const char* settingsFile; 67 | const char* bkrXmlFile; 68 | 69 | typedef struct { 70 | std::string brokerid; 71 | std::string username; 72 | std::string password; 73 | std::string mdfront; 74 | std::string tradefront; 75 | bool remoteMgrEnabled; 76 | int remotePort; 77 | } LoginData; 78 | 79 | LoginData loginData; 80 | 81 | std::list brokers; 82 | 83 | std::vector bkrDispalyNames; 84 | }; 85 | 86 | #endif // LOGIN_DIALOG_H -------------------------------------------------------------------------------- /Src/logindialog.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | LoginDlg 4 | 5 | 6 | 7 | 0 8 | 0 9 | 368 10 | 182 11 | 12 | 13 | 14 | 15 | 0 16 | 0 17 | 18 | 19 | 20 | 21 | 368 22 | 182 23 | 24 | 25 | 26 | 27 | 368 28 | 182 29 | 30 | 31 | 32 | Login 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | User: 41 | 42 | 43 | Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter 44 | 45 | 46 | 47 | 48 | 49 | 50 | Password: 51 | 52 | 53 | Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter 54 | 55 | 56 | 57 | 58 | 59 | 60 | Edit 61 | 62 | 63 | 64 | 65 | 66 | 67 | Broker: 68 | 69 | 70 | Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 0 79 | 0 80 | 81 | 82 | 83 | Qt::TabFocus 84 | 85 | 86 | 87 | 88 | 89 | 90 | Qt::StrongFocus 91 | 92 | 93 | QLineEdit::Password 94 | 95 | 96 | 97 | 98 | 99 | 100 | Qt::StrongFocus 101 | 102 | 103 | 104 | 105 | 106 | 107 | Qt::StrongFocus 108 | 109 | 110 | Remember 111 | 112 | 113 | true 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | Qt::Vertical 123 | 124 | 125 | 126 | 20 127 | 40 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | Qt::Horizontal 138 | 139 | 140 | 141 | 40 142 | 20 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | Login 151 | 152 | 153 | 154 | 155 | 156 | 157 | Exit 158 | 159 | 160 | 161 | 162 | 163 | 164 | Settings 165 | 166 | 167 | 168 | 169 | 170 | 171 | Qt::Horizontal 172 | 173 | 174 | 175 | 40 176 | 20 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 0 194 | 195 | 196 | false 197 | 198 | 199 | 200 | 201 | 202 | 203 | userLineEdit 204 | passwdLineEdit 205 | loginBtn 206 | exitBtn 207 | settingsBtn 208 | brokerComboBox 209 | editBkrBtn 210 | remCheckBox 211 | 212 | 213 | 214 | 215 | -------------------------------------------------------------------------------- /Src/loginsettingsdialog.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "loginsettingsdialog.h" 3 | 4 | LoginSettingsDialog::LoginSettingsDialog(QWidget* parent) 5 | : QDialog(parent) 6 | { 7 | ui.setupUi(this); 8 | 9 | port = 5501; 10 | remoteMrgEnabled = true; 11 | 12 | ui.portLineEdit->setText(QString().number(port)); 13 | QIntValidator* validator = new QIntValidator(0, 0xffff, parent); 14 | ui.portLineEdit->setValidator(validator); 15 | 16 | connect(ui.remoteCheckBox, SIGNAL(toggled(bool)), this, SLOT(portCheckBoxToggled(bool))); 17 | 18 | ui.srvsCBox->addItem("CTP [Ctp.dll]"); 19 | ui.srvsCBox->addItem("SGIT* [Sgit.dll]"); 20 | ui.srvsCBox->addItem("TDX* [TDX.dll]"); 21 | ui.srvsCBox->addItem("LMAX* [LMAX.dll]"); 22 | ui.srvsCBox->addItem("Femas* [Femas.dll]"); 23 | ui.srvsCBox->addItem("Zeusing* [Zeusing.dll]"); 24 | ui.srvsCBox->addItem("UT* [UT.dll]"); 25 | ui.srvsCBox->addItem("IB* [IB.dll]"); 26 | ui.srvsCBox->addItem("BTCC* [BTCC.dll]"); 27 | 28 | QStandardItemModel* model = qobject_cast(ui.srvsCBox->model()); 29 | bool disabled = true; 30 | int rows = ui.srvsCBox->count(); 31 | for (int i = 1; i < rows; i++) { 32 | QStandardItem* item = model->item(i); 33 | item->setFlags(disabled ? item->flags() & ~Qt::ItemIsEnabled : 34 | item->flags() | Qt::ItemIsEnabled); 35 | } 36 | 37 | ui.algoCBox->addItem(tr("Disabled")); 38 | ui.algoCBox->addItem(tr("Enabled*")); 39 | model = qobject_cast(ui.algoCBox->model()); 40 | disabled = true; 41 | QStandardItem* item = model->item(1); 42 | item->setFlags(disabled ? item->flags() & ~Qt::ItemIsEnabled : item->flags() | Qt::ItemIsEnabled); 43 | 44 | ui.multiAcctCBox->addItem(tr("Disabled")); 45 | ui.multiAcctCBox->addItem(tr("Enabled*")); 46 | model = qobject_cast(ui.multiAcctCBox->model()); 47 | disabled = true; 48 | item = model->item(1); 49 | item->setFlags(disabled ? item->flags() & ~Qt::ItemIsEnabled : item->flags() | Qt::ItemIsEnabled); 50 | 51 | ui.localLoadCBox->addItem(tr("Disabled")); 52 | ui.localLoadCBox->addItem(tr("Enabled*")); 53 | model = qobject_cast(ui.localLoadCBox->model()); 54 | disabled = true; 55 | item = model->item(1); 56 | item->setFlags(disabled ? item->flags() & ~Qt::ItemIsEnabled : item->flags() | Qt::ItemIsEnabled); 57 | 58 | connect(ui.okBtn, SIGNAL(clicked()), this, SLOT(btnOkClicked())); 59 | connect(ui.cancelBtn, SIGNAL(clicked()), this, SLOT(btnCancelClicked())); 60 | } 61 | 62 | LoginSettingsDialog::~LoginSettingsDialog() 63 | { 64 | } 65 | 66 | bool LoginSettingsDialog::isRemoteMgrEnabled() const 67 | { 68 | return remoteMrgEnabled; 69 | } 70 | 71 | void LoginSettingsDialog::setRemoteMgrEnabled(bool enable) 72 | { 73 | remoteMrgEnabled = enable; 74 | if (enable) { 75 | ui.remoteCheckBox->setChecked(true); 76 | ui.portLineEdit->setEnabled(true); 77 | } else { 78 | ui.remoteCheckBox->setChecked(false); 79 | ui.portLineEdit->setDisabled(true); 80 | } 81 | } 82 | 83 | void LoginSettingsDialog::setPort(int port) 84 | { 85 | this->port = port; 86 | ui.portLineEdit->setText(QString().number(port)); 87 | } 88 | 89 | int LoginSettingsDialog::getPort() const 90 | { 91 | return port; 92 | } 93 | 94 | void LoginSettingsDialog::btnOkClicked() 95 | { 96 | port = ui.portLineEdit->text().toInt(); 97 | 98 | accept(); 99 | } 100 | 101 | void LoginSettingsDialog::btnCancelClicked() 102 | { 103 | reject(); 104 | } 105 | 106 | void LoginSettingsDialog::portCheckBoxToggled(bool toggled) 107 | { 108 | if (toggled) { 109 | ui.portLineEdit->setEnabled(true); 110 | remoteMrgEnabled = true; 111 | } else { 112 | ui.portLineEdit->setDisabled(true); 113 | remoteMrgEnabled = false; 114 | } 115 | } -------------------------------------------------------------------------------- /Src/loginsettingsdialog.h: -------------------------------------------------------------------------------- 1 | #ifndef LOGIN_SETTINGS_DIALOG_H 2 | #define LOGIN_SETTINGS_DIALOG_H 3 | 4 | #include 5 | #include "ui_loginsettingsdialog.h" 6 | 7 | class LoginSettingsDialog : public QDialog 8 | { 9 | Q_OBJECT 10 | 11 | public: 12 | LoginSettingsDialog(QWidget* parent = 0); 13 | ~LoginSettingsDialog(); 14 | 15 | bool isRemoteMgrEnabled() const; 16 | void setRemoteMgrEnabled(bool enable); 17 | void setPort(int port); 18 | int getPort() const; 19 | 20 | private slots: 21 | void btnOkClicked(); 22 | void btnCancelClicked(); 23 | void portCheckBoxToggled(bool); 24 | 25 | private: 26 | Ui::LoginSettingsDlg ui; 27 | int port; 28 | bool remoteMrgEnabled; 29 | }; 30 | 31 | #endif // LOGIN_SETTINGS_DIALOG_H -------------------------------------------------------------------------------- /Src/loginsettingsdialog.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | LoginSettingsDlg 4 | 5 | 6 | 7 | 0 8 | 0 9 | 367 10 | 185 11 | 12 | 13 | 14 | Settings 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | Qt::Horizontal 23 | 24 | 25 | 26 | 40 27 | 20 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | Ok 36 | 37 | 38 | 39 | 40 | 41 | 42 | Cancel 43 | 44 | 45 | 46 | 47 | 48 | 49 | Qt::Horizontal 50 | 51 | 52 | 53 | 40 54 | 20 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | Multi-Account: 70 | 71 | 72 | Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | true 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | AlgoTrader: 93 | 94 | 95 | Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter 96 | 97 | 98 | 99 | 100 | 101 | 102 | Enable 103 | 104 | 105 | true 106 | 107 | 108 | 109 | 110 | 111 | 112 | Service: 113 | 114 | 115 | Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter 116 | 117 | 118 | 119 | 120 | 121 | 122 | Remote Port: 123 | 124 | 125 | Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter 126 | 127 | 128 | 129 | 130 | 131 | 132 | Local Load: 133 | 134 | 135 | Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | Qt::Vertical 148 | 149 | 150 | 151 | 20 152 | 40 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | -------------------------------------------------------------------------------- /Src/logmodel.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "main.h" 6 | #include "logmodel.h" 7 | 8 | LogModel::LogModel(QObject* parent) 9 | : QAbstractItemModel(parent) 10 | { 11 | headerLabels << tr("DateTime"); 12 | headerLabels << tr("Level"); 13 | headerLabels << tr("Text"); 14 | 15 | dateWidth = qMax(QApplication::fontMetrics().width("2000/12/30 23:59:59.999"), QApplication::fontMetrics().width("2000/12/30 12:59:59.999")) + 10; 16 | levelWidth = 60; 17 | } 18 | 19 | LogModel::~LogModel() 20 | { 21 | itemsList.clear(); 22 | } 23 | 24 | QModelIndex LogModel::index(int row, int column, const QModelIndex &parent) const 25 | { 26 | if (!hasIndex(row, column, parent))return QModelIndex(); 27 | return createIndex(row, column); 28 | } 29 | 30 | QModelIndex LogModel::parent(const QModelIndex &index) const 31 | { 32 | return QModelIndex(); 33 | } 34 | 35 | QString LogModel::getLogLevelStr(int level) const 36 | { 37 | switch (level) { 38 | default: 39 | case AlgoSE::LogLevel::LOG_INFO: 40 | return "INFO"; 41 | 42 | case AlgoSE::LogLevel::LOG_DEBUG: 43 | return "DBG"; 44 | 45 | case AlgoSE::LogLevel::LOG_WARN: 46 | return "WARN"; 47 | 48 | case AlgoSE::LogLevel::LOG_ERROR: 49 | return "ERR"; 50 | 51 | case AlgoSE::LogLevel::LOG_FATAL: 52 | return "FATAL"; 53 | } 54 | 55 | return ""; 56 | } 57 | 58 | QVariant LogModel::data(const QModelIndex &index, int role) const 59 | { 60 | int currentRow = itemsList.count() - index.row() - 1; 61 | if (currentRow < 0 || currentRow >= itemsList.count()) return QVariant(); 62 | 63 | if (role == Qt::ToolTipRole) { 64 | return QString(itemsList.at(currentRow).datetime) + "\t" + getLogLevelStr(itemsList.at(currentRow).log.level) + "\t" + QString().fromLocal8Bit(itemsList.at(currentRow).log.text); 65 | } 66 | 67 | if (role != Qt::DisplayRole && 68 | role != Qt::ToolTipRole && 69 | role != Qt::ForegroundRole && 70 | role != Qt::TextAlignmentRole && 71 | role != Qt::BackgroundRole) { 72 | return QVariant(); 73 | } 74 | 75 | int indexRow = index.row(); 76 | if (role == Qt::BackgroundRole) 77 | { 78 | if (!(indexRow % 2)) { 79 | return appGlobalData.appTheme.altRowColor; 80 | } else { 81 | return QVariant(); 82 | } 83 | } 84 | 85 | if (role == Qt::ForegroundRole) { 86 | if (currentRow < itemsList.size()) { 87 | int level = itemsList.at(currentRow).log.level; 88 | if (level == AlgoSE::LogLevel::LOG_WARN || 89 | level == AlgoSE::LogLevel::LOG_ERROR || 90 | level == AlgoSE::LogLevel::LOG_FATAL) { 91 | return appGlobalData.appTheme.red; 92 | } 93 | } 94 | 95 | return appGlobalData.appTheme.black; 96 | } 97 | 98 | if (role == Qt::TextAlignmentRole) { 99 | return Qt::AlignLeft | Qt::AlignVCenter; 100 | } 101 | 102 | if (role == Qt::DisplayRole) { 103 | int indexColumn = index.column(); 104 | 105 | switch (indexColumn) { 106 | case 0: 107 | return itemsList.at(currentRow).datetime; 108 | case 1: 109 | return getLogLevelStr(itemsList.at(currentRow).log.level); 110 | case 2: 111 | return QString().fromLocal8Bit(itemsList.at(currentRow).log.text); 112 | 113 | default: 114 | break; 115 | } 116 | } 117 | 118 | return QVariant(); 119 | } 120 | 121 | Qt::ItemFlags LogModel::flags(const QModelIndex &index) const 122 | { 123 | return Qt::ItemIsSelectable|Qt::ItemIsEnabled; 124 | } 125 | 126 | QVariant LogModel::headerData(int section, Qt::Orientation orientation, int role) const 127 | { 128 | if (orientation != Qt::Horizontal)return QVariant(); 129 | 130 | if (role == Qt::SizeHintRole) 131 | { 132 | switch (section) 133 | { 134 | case 0: return QSize(dateWidth, defaultHeightForRow); //DateTime 135 | case 1: return QSize(levelWidth, defaultHeightForRow); // Level 136 | } 137 | return QVariant(); 138 | } 139 | 140 | if (role == Qt::TextAlignmentRole) { 141 | switch (section) { 142 | case 0: 143 | case 1:return Qt::AlignLeft | Qt::AlignVCenter; 144 | } 145 | } 146 | 147 | if (role != Qt::DisplayRole) return QVariant(); 148 | if (section >= headerLabels.count()) return QVariant(); 149 | 150 | return headerLabels.at(section); 151 | } 152 | 153 | int LogModel::rowCount(const QModelIndex &parent) const 154 | { 155 | return itemsList.count(); 156 | } 157 | 158 | int LogModel::columnCount(const QModelIndex &parent) const 159 | { 160 | return headerLabels.count(); 161 | } 162 | 163 | void LogModel::insertLogItem(const AlgoSE::SystemLog& log) 164 | { 165 | int currentIndex = itemsList.size(); 166 | beginInsertRows(QModelIndex(), currentIndex, currentIndex); 167 | LogItem item; 168 | item.log = log; 169 | int year, month, day, hour, minute, sec, ms; 170 | DateTime(log.timestamp).getFields(year, month, day, hour, minute, sec, ms); 171 | sprintf(item.datetime, "%04d/%02d/%02d %02d:%02d:%02d.%03d", 172 | year, month, day, hour, minute, sec, ms); 173 | itemsList.push_front(item); 174 | endInsertRows(); 175 | } -------------------------------------------------------------------------------- /Src/logmodel.h: -------------------------------------------------------------------------------- 1 | #ifndef LOG_MODEL_H 2 | #define LOG_MODEL_H 3 | 4 | #include 5 | #include "Defines.h" 6 | 7 | class LogModel : public QAbstractItemModel 8 | { 9 | Q_OBJECT 10 | 11 | public: 12 | LogModel(QObject *parent); 13 | ~LogModel(); 14 | 15 | void insertLogItem(const AlgoSE::SystemLog& log); 16 | 17 | QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const; 18 | QModelIndex parent(const QModelIndex &index) const; 19 | 20 | QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; 21 | Qt::ItemFlags flags(const QModelIndex &index) const; 22 | QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; 23 | 24 | int rowCount(const QModelIndex &parent = QModelIndex()) const; 25 | int columnCount(const QModelIndex &parent = QModelIndex()) const; 26 | 27 | private: 28 | QString getLogLevelStr(int level) const; 29 | 30 | private: 31 | int dateWidth; 32 | int levelWidth; 33 | QStringList headerLabels; 34 | 35 | typedef struct { 36 | char datetime[32]; 37 | AlgoSE::SystemLog log; 38 | } LogItem; 39 | 40 | QList itemsList; 41 | }; 42 | 43 | #endif // LOG_MODEL_H 44 | -------------------------------------------------------------------------------- /Src/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "main.h" 8 | #include "authdialog.h" 9 | #include "RestartAPI.h" 10 | 11 | #ifdef _DEBUG 12 | #if !_WIN64 13 | #include "vld.h" 14 | #endif 15 | #endif 16 | 17 | AppGlobalData* appGlobalData_; 18 | 19 | void AppGlobalData::Construct() 20 | { 21 | currentTheme = 0; 22 | timeFormat = QLocale().timeFormat(QLocale::LongFormat).replace(" ", "").replace("t", ""); 23 | dateTimeFormat = QLocale().dateFormat(QLocale::ShortFormat) + " " + timeFormat; 24 | defaultHeightForRow_ = 22; 25 | translateLang = true; 26 | requestAuth = false; 27 | requestLogin = false; 28 | localLoading = true; 29 | } 30 | 31 | int main(int argc, char *argv[]) 32 | { 33 | #if _DEBUG 34 | if (!AllocConsole()) { 35 | return 0; 36 | } 37 | 38 | freopen("CONIN$", "rb", stdin); 39 | freopen("CONOUT$", "wb", stdout); 40 | freopen("CONOUT$", "wb", stderr); 41 | #endif 42 | 43 | // Initialize restart code 44 | // Check if this instance is restarted and 45 | // wait while previous instance finish 46 | if (RA_CheckForRestartProcessStart()) { 47 | RA_WaitForPreviousProcessFinish(); 48 | } 49 | 50 | // It is important to put QApplication into a local domain, thus ui widgets 51 | // will be totally released before exit main function. 52 | int ret = 0; 53 | { 54 | 55 | appGlobalData_ = new AppGlobalData(); 56 | appGlobalData.Construct(); 57 | 58 | QTextCodec::setCodecForLocale(QTextCodec::codecForName("system")); 59 | 60 | QApplication app(argc, argv); 61 | QApplication::setOrganizationName("Algo.Trade"); 62 | QApplication::setApplicationName("PowerGate"); 63 | QApplication::setApplicationVersion("0.1"); 64 | 65 | if (appGlobalData.translateLang) { 66 | QTranslator* translator = new QTranslator(&app); 67 | translator->load(":/trans/PowerGate.qm"); 68 | app.installTranslator(translator); 69 | } 70 | 71 | #if QT_VERSION >= 0x050000 72 | app.setStyle(QStyleFactory::create("Fusion")); 73 | #endif 74 | 75 | #ifdef Q_OS_WIN//DPI Fix 76 | QFont font = app.font(); 77 | QFontDatabase database; 78 | QStringList fntList = database.families(); 79 | if (fntList.contains("Consolas")) { 80 | font.setFamily("Consolas"); 81 | } 82 | font.setPointSize(9); 83 | app.setFont(font); 84 | #endif 85 | 86 | app.setApplicationName("PowerGate"); 87 | appGlobalData.fontMetrics_ = new QFontMetrics(app.font()); 88 | 89 | #if QT_VERSION < 0x050000 90 | appGlobalData.tempLocation = QDesktopServices::storageLocation(QDesktopServices::TempLocation).replace('\\', '/') + "/"; 91 | appGlobalData.desktopLocation = QDesktopServices::storageLocation(QDesktopServices::DesktopLocation).replace('\\', '/') + "/"; 92 | #else 93 | appGlobalData.tempLocation = QStandardPaths::standardLocations(QStandardPaths::TempLocation).first().replace('\\', '/') + "/"; 94 | appGlobalData.desktopLocation = QStandardPaths::standardLocations(QStandardPaths::DesktopLocation).first().replace('\\', '/') + "/"; 95 | #endif 96 | 97 | #if 1 98 | appGlobalData.appTheme.palette = app.palette(); 99 | appGlobalData.appTheme.loadTheme("Dark"); 100 | app.setPalette(appGlobalData.appTheme.palette); 101 | app.setStyleSheet(appGlobalData.appTheme.styleSheet); 102 | #endif 103 | 104 | app.setWindowIcon(QIcon(":/icon/Letter-P-black-icon.png")); 105 | 106 | if (appGlobalData.requestAuth) { 107 | AuthDialog dlg; 108 | if (dlg.exec() != QDialog::Accepted) { 109 | app.exit(); 110 | return 0; 111 | } 112 | } 113 | 114 | appGlobalData.mainWindow_ = new PowerGate(); 115 | app.installEventFilter(appGlobalData.mainWindow_); 116 | 117 | if (!appGlobalData.requestLogin) { 118 | mainWindow.showMaximized(); 119 | } 120 | 121 | ret = app.exec(); 122 | 123 | delete appGlobalData.mainWindow_; 124 | delete appGlobalData.fontMetrics_; 125 | delete appGlobalData_; 126 | } 127 | 128 | // Finish restarting process if needed 129 | RA_DoRestartProcessFinish(); 130 | 131 | return ret; 132 | } -------------------------------------------------------------------------------- /Src/main.h: -------------------------------------------------------------------------------- 1 | #ifndef MAIN_H 2 | #define MAIN_H 3 | 4 | #include 5 | #include "apptheme.h" 6 | #include "powergate.h" 7 | 8 | #define mainWindow (*appGlobalData_->mainWindow_) 9 | #define defaultHeightForRow appGlobalData_->defaultHeightForRow_ 10 | 11 | typedef struct { 12 | void Construct(); 13 | 14 | QString osStyle; 15 | 16 | int currentTheme; 17 | AppTheme appTheme; 18 | int defaultHeightForRow_; 19 | QFontMetrics *fontMetrics_; 20 | QString themeFolder; 21 | QString timeFormat; 22 | QString dateTimeFormat; 23 | QString appDataDir_; 24 | QByteArray appVerStr; 25 | QString iniFileName; 26 | QString desktopLocation; 27 | QString tempLocation; 28 | bool translateLang; 29 | bool requestLogin; 30 | bool requestAuth; 31 | bool localLoading; 32 | 33 | PowerGate* mainWindow_; 34 | 35 | } AppGlobalData; 36 | 37 | #define appGlobalData (*appGlobalData_) 38 | extern AppGlobalData *appGlobalData_; 39 | 40 | #endif // MAIN_H -------------------------------------------------------------------------------- /Src/ordermodel.cpp: -------------------------------------------------------------------------------- 1 | #include "main.h" 2 | #include "ordermodel.h" 3 | 4 | OrderModel::OrderModel(QObject* parent) 5 | : QAbstractItemModel(parent) 6 | { 7 | headerLabels << tr("ID"); 8 | headerLabels << tr("Strategy"); 9 | headerLabels << tr("Instrument"); 10 | headerLabels << tr("Side"); 11 | headerLabels << tr("Action"); 12 | headerLabels << tr("Status"); 13 | headerLabels << tr("Price"); 14 | headerLabels << tr("AvgPrice"); 15 | headerLabels << tr("Quantity"); 16 | headerLabels << tr("Traded"); 17 | headerLabels << tr("DateTime"); 18 | headerLabels << tr("StatusMsg"); 19 | headerLabels << ""; 20 | 21 | headerNum = headerLabels.size() - 1; 22 | 23 | idWidth = 90; 24 | instrumentWidth = 80; 25 | stratWidth = 90; 26 | priceWidth = 80; 27 | quantityWidth = 60; 28 | statusWidth = 80; 29 | actionWidth = 50; 30 | sideWidth = 50; 31 | datetimeWidth = 170; 32 | statusMsgWidth = 500; 33 | } 34 | 35 | OrderModel::~OrderModel() 36 | { 37 | itemsList.clear(); 38 | } 39 | 40 | const QStringList& OrderModel::getHeaderLabels() const 41 | { 42 | return headerLabels; 43 | } 44 | 45 | int OrderModel::getHeaderNumber() const 46 | { 47 | return headerNum; 48 | } 49 | 50 | QModelIndex OrderModel::index(int row, int column, const QModelIndex &parent) const 51 | { 52 | if (!hasIndex(row, column, parent)) return QModelIndex(); 53 | return createIndex(row, column); 54 | } 55 | 56 | QModelIndex OrderModel::parent(const QModelIndex &index) const 57 | { 58 | return QModelIndex(); 59 | } 60 | 61 | QVariant OrderModel::data(const QModelIndex &index, int role) const 62 | { 63 | int currentRow = itemsList.count() - index.row() - 1; 64 | if (currentRow < 0 || currentRow >= itemsList.count()) 65 | return QVariant(); 66 | 67 | if (role != Qt::DisplayRole && 68 | role != Qt::ToolTipRole && 69 | role != Qt::ForegroundRole && 70 | role != Qt::BackgroundRole && 71 | role != Qt::TextAlignmentRole) { 72 | return QVariant(); 73 | } 74 | 75 | int indexColumn = index.column(); 76 | int indexRow = index.row(); 77 | 78 | if (role == Qt::TextAlignmentRole) { 79 | return Qt::AlignLeft | Qt::AlignVCenter; 80 | } 81 | 82 | if (role == Qt::BackgroundRole) 83 | { 84 | if (!(indexRow % 2)) { 85 | return appGlobalData.appTheme.altRowColor; 86 | } else { 87 | return QVariant(); 88 | } 89 | } 90 | 91 | if (role == Qt::ForegroundRole) { 92 | if (indexColumn == 3 && indexRow < itemsList.size()) { 93 | if (itemsList[indexRow].action == OrderAction::BUY || 94 | itemsList[indexRow].action == OrderAction::BUY_TO_COVER) { 95 | return appGlobalData.appTheme.red; 96 | } else if (itemsList[indexRow].action == OrderAction::SELL || 97 | itemsList[indexRow].action == OrderAction::SELL_SHORT) { 98 | return appGlobalData.appTheme.darkGreen; 99 | } 100 | } 101 | 102 | if (indexColumn == 5 && indexRow < itemsList.size()) { 103 | const OrderStatusItem& item = itemsList[indexRow]; 104 | if (item.status == OrderState::CANCELED || 105 | item.status == OrderState::REJECTED) { 106 | return appGlobalData.appTheme.red; 107 | } else if (item.status == OrderState::FILLED) { 108 | return appGlobalData.appTheme.darkGreen; 109 | } 110 | } 111 | 112 | return appGlobalData.appTheme.black; 113 | } 114 | 115 | if (role == Qt::DisplayRole && indexRow < itemsList.size()) { 116 | const OrderStatusItem& item = itemsList[indexRow]; 117 | switch (indexColumn) { 118 | case 0: 119 | return item.id; 120 | case 1: 121 | return item.stratName; 122 | case 2: 123 | return item.instrument; 124 | case 3: 125 | return (item.action == OrderAction::BUY || item.action == OrderAction::BUY_TO_COVER) ? tr("Buy") : tr("Sell"); 126 | case 4: 127 | return (item.action == OrderAction::BUY || item.action == OrderAction::SELL_SHORT) ? tr("Open") : 128 | ((item.closeEffect == CloseEffect::CLOSE_YESTERDAY) ? tr("CloseYd") : 129 | (item.closeEffect == CloseEffect::CLOSE_TODAY) ? tr("CloseToday") : tr("Close")); 130 | case 5: // status 131 | switch (item.status) { 132 | case OrderState::ACCEPTED: 133 | return tr("Accepted"); 134 | case OrderState::CANCELED: 135 | return tr("Canceled"); 136 | case OrderState::FILLED: 137 | return tr("Filled"); 138 | case OrderState::PARTIALLY_FILLED: 139 | return tr("Part_Filled"); 140 | case OrderState::PENDING_CANCEL: 141 | return tr("Pending_Cancel"); 142 | case OrderState::PENDING_NEW: 143 | return tr("Pending_New"); 144 | case OrderState::REJECTED: 145 | return tr("Rejected"); 146 | case OrderState::SUBMITTED: 147 | return tr("Submitted"); 148 | default: 149 | case OrderState::UNKNOWN: 150 | return tr("Unknown"); 151 | } 152 | break; 153 | case 6: 154 | return item.price; 155 | case 7: 156 | if (fabs(item.avgPrice) < 0.000001) { 157 | return "-"; 158 | } else { 159 | return item.avgPrice; 160 | } 161 | case 8: 162 | return item.quantity; 163 | case 9: 164 | return item.traded; 165 | case 10: 166 | return item.datetime; 167 | case 11: 168 | return item.statusMsg; 169 | default: 170 | return QVariant(); 171 | } 172 | } 173 | 174 | return QVariant(); 175 | } 176 | 177 | Qt::ItemFlags OrderModel::flags(const QModelIndex &index) const 178 | { 179 | return Qt::ItemIsSelectable | Qt::ItemIsEnabled; 180 | } 181 | 182 | QVariant OrderModel::headerData(int section, Qt::Orientation orientation, int role) const 183 | { 184 | if (orientation != Qt::Horizontal) return QVariant(); 185 | 186 | if (role == Qt::TextAlignmentRole) { 187 | return Qt::AlignLeft; 188 | } 189 | 190 | if (role == Qt::SizeHintRole) 191 | { 192 | switch (section) 193 | { 194 | case 0: return QSize(idWidth, defaultHeightForRow); 195 | case 1: return QSize(stratWidth, defaultHeightForRow); 196 | case 2: return QSize(instrumentWidth, defaultHeightForRow); 197 | case 3: return QSize(sideWidth, defaultHeightForRow); 198 | case 4: return QSize(actionWidth, defaultHeightForRow); 199 | case 5: return QSize(statusWidth, defaultHeightForRow); 200 | case 6: 201 | case 7: return QSize(priceWidth, defaultHeightForRow); 202 | case 8: 203 | case 9: 204 | return QSize(quantityWidth, defaultHeightForRow); 205 | case 10: 206 | return QSize(datetimeWidth, defaultHeightForRow); 207 | case 11: 208 | return QSize(statusMsgWidth, defaultHeightForRow); 209 | } 210 | return QVariant(); 211 | } 212 | 213 | if (role != Qt::DisplayRole) return QVariant(); 214 | if (section >= headerLabels.count()) return QVariant(); 215 | 216 | return headerLabels.at(section); 217 | } 218 | 219 | int OrderModel::rowCount(const QModelIndex &parent) const 220 | { 221 | return itemsList.count(); 222 | } 223 | 224 | void OrderModel::getAllOrderItems(std::vector& orders) 225 | { 226 | for (auto& item : itemsList) { 227 | orders.push_back(item); 228 | } 229 | } 230 | 231 | void OrderModel::getAllPendingOrders(std::vector& orders) 232 | { 233 | for (auto& item : itemsList) { 234 | int status = item.status; 235 | if (status != OrderState::CANCELED && 236 | status != OrderState::FILLED && 237 | status != OrderState::REJECTED && 238 | status != OrderState::UNKNOWN) { 239 | orders.push_back(item); 240 | } 241 | } 242 | } 243 | 244 | bool OrderModel::getPendingOrder(int row, OrderStatusItem& order) 245 | { 246 | if (row < 0 || row >= itemsList.size()) { 247 | return false; 248 | } 249 | int status = itemsList[row].status; 250 | if (status != OrderState::CANCELED && 251 | status != OrderState::FILLED && 252 | status != OrderState::REJECTED && 253 | status != OrderState::UNKNOWN) { 254 | order = itemsList[row]; 255 | return true; 256 | } 257 | 258 | return false; 259 | } 260 | 261 | int OrderModel::columnCount(const QModelIndex &parent) const 262 | { 263 | return headerLabels.count(); 264 | } 265 | 266 | void OrderModel::copyOrderItem(OrderStatusItem& item, const AlgoSE::Order& status) 267 | { 268 | item.srvId = status.srvId; 269 | strcpy(item.clOrdId, status.clOrdId); 270 | strcpy(item.ordId, status.ordId); 271 | sprintf(item.id, "%02d:%s", status.srvId, status.ordId); 272 | strcpy(item.instrument, status.instrument); 273 | item.statusMsg = QString().fromLocal8Bit(status.stateMsg); 274 | item.action = status.action; 275 | item.price = status.price; 276 | item.quantity = status.quantity; 277 | item.traded = status.tradedQty; 278 | item.avgPrice = status.avgTradedPx; 279 | item.status = status.status; 280 | item.closeEffect = status.closeEffect; 281 | int year, month, day, hour, minute, sec, ms; 282 | DateTime(status.timestamp).getFields(year, month, day, hour, minute, sec, ms); 283 | sprintf(item.datetime, "%04d-%02d-%02d %02d:%02d:%02d", year, month, day, hour, minute, sec); 284 | 285 | if (status.ownerId >= 0) { 286 | auto it = stratNames.find(status.ownerId); 287 | if (it != stratNames.end()) { 288 | strcpy(item.stratName, it->second.c_str()); 289 | } 290 | } 291 | } 292 | 293 | void OrderModel::updateOrderStatus(const AlgoSE::Order& order) 294 | { 295 | if (order.ordId[0] == '\0' || order.srvId < 0) { 296 | // We receive an unknown order. 297 | if (order.stateMsg[0] != '\0') { 298 | PowerGate* gate = qobject_cast(QObject::parent()); 299 | AlgoSE::SystemLog sysLog = { 0 }; 300 | sysLog.level = LogLevel::LOG_ERROR; 301 | SYSTEMTIME lt; 302 | GetLocalTime(<); 303 | sysLog.timestamp = DateTime().toTimeStamp(); 304 | strncpy(sysLog.text, order.stateMsg, sizeof(sysLog.text) - 1); 305 | 306 | gate->onSystemLog(sysLog); 307 | } 308 | 309 | return; 310 | } 311 | 312 | int i = 0; 313 | int size = itemsList.size(); 314 | for (i = 0; i < size; i++) { 315 | if (!strcmp(itemsList[i].ordId, order.ordId) && 316 | itemsList[i].srvId == order.srvId) { 317 | break; 318 | } 319 | } 320 | 321 | if (i == size) { 322 | int currentIndex = size; 323 | beginInsertRows(QModelIndex(), currentIndex, currentIndex); 324 | OrderStatusItem item = { 0 }; 325 | copyOrderItem(item, order); 326 | itemsList.push_front(item); 327 | endInsertRows(); 328 | // emit dataChanged(index(itemsList.size() - 1, 0), index(itemsList.size() - 1, headerLabels.size() - 1)); 329 | } else { 330 | copyOrderItem(itemsList[i], order); 331 | emit dataChanged(index(i, 0), index(i, headerLabels.size() - 1)); 332 | } 333 | } 334 | 335 | void OrderModel::updateStratStatus(const AlgoSE::StrategyStatus& state) 336 | { 337 | if (state.strategyId <= 0) { 338 | return; 339 | } 340 | 341 | if (state.name == nullptr || state.name[0] == '\0') { 342 | return; 343 | } 344 | 345 | auto it = stratNames.find(state.strategyId); 346 | if (it == stratNames.end()) { 347 | stratNames.insert(std::make_pair(state.strategyId, state.name)); 348 | } 349 | } 350 | 351 | void OrderModel::updateExecution(const AlgoSE::Execution& exec) 352 | { 353 | 354 | } -------------------------------------------------------------------------------- /Src/ordermodel.h: -------------------------------------------------------------------------------- 1 | #ifndef ORDER_MODEL_H 2 | #define ORDER_MODEL_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include "Defines.h" 8 | 9 | typedef struct { 10 | char id[32]; 11 | int srvId; 12 | char clOrdId[32]; 13 | char ordId[32]; 14 | char stratName[32]; // strategy name 15 | char instrument[32]; 16 | int action; 17 | int quantity; 18 | double price; 19 | double cost; 20 | int traded; 21 | int status; 22 | double avgPrice; 23 | char datetime[32]; 24 | int closeEffect; 25 | QString statusMsg; 26 | } OrderStatusItem; 27 | 28 | class OrderModel : public QAbstractItemModel 29 | { 30 | Q_OBJECT 31 | 32 | public: 33 | OrderModel(QObject* parent); 34 | ~OrderModel(); 35 | 36 | void updateOrderStatus(const AlgoSE::Order& order); 37 | void updateExecution(const AlgoSE::Execution& execution); 38 | void updateStratStatus(const AlgoSE::StrategyStatus& state); 39 | const QStringList& getHeaderLabels() const; 40 | int getHeaderNumber() const; 41 | 42 | QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const; 43 | QModelIndex parent(const QModelIndex &index) const; 44 | 45 | QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; 46 | Qt::ItemFlags flags(const QModelIndex &index) const; 47 | QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; 48 | 49 | int rowCount(const QModelIndex &parent = QModelIndex()) const; 50 | int columnCount(const QModelIndex &parent = QModelIndex()) const; 51 | 52 | void getAllOrderItems(std::vector& orders); 53 | void getAllPendingOrders(std::vector& orders); 54 | bool getPendingOrder(int row, OrderStatusItem& order); 55 | 56 | private: 57 | void copyOrderItem(OrderStatusItem& item, const AlgoSE::Order& status); 58 | 59 | private: 60 | QStringList headerLabels; 61 | int headerNum; 62 | QList itemsList; 63 | 64 | std::unordered_map stratNames; 65 | 66 | int idWidth; 67 | int instrumentWidth; 68 | int stratWidth; 69 | int priceWidth; 70 | int quantityWidth; 71 | int statusWidth; 72 | int actionWidth; 73 | int sideWidth; 74 | int datetimeWidth; 75 | int statusMsgWidth; 76 | }; 77 | 78 | #endif // ORDER_MODEL_H -------------------------------------------------------------------------------- /Src/posmodel.cpp: -------------------------------------------------------------------------------- 1 | #include "main.h" 2 | #include "posmodel.h" 3 | 4 | PositionModel::PositionModel(QObject* parent) 5 | : QAbstractItemModel(parent) 6 | { 7 | headerLabels << tr("ServiceID"); 8 | headerLabels << tr("Instrument"); 9 | headerLabels << tr("Side"); 10 | headerLabels << tr("Price"); 11 | headerLabels << tr("Total"); 12 | headerLabels << tr("Yesterday"); 13 | headerLabels << tr("Today"); 14 | headerLabels << tr("Closable"); 15 | headerLabels << tr("MTM PnL"); 16 | headerLabels << ""; 17 | 18 | srvIdWidth = 40; 19 | instrumentWidth = 100; 20 | priceWidth = 80; 21 | quantityWidth = 80; 22 | actionWidth = 60; 23 | sideWidth = 30; 24 | pnlWidth = 120; 25 | } 26 | 27 | PositionModel::~PositionModel() 28 | { 29 | } 30 | 31 | const QStringList& PositionModel::getHeaderLabels() const 32 | { 33 | return headerLabels; 34 | } 35 | 36 | QModelIndex PositionModel::index(int row, int column, const QModelIndex &parent) const 37 | { 38 | if (!hasIndex(row, column, parent)) return QModelIndex(); 39 | return createIndex(row, column); 40 | } 41 | 42 | QModelIndex PositionModel::parent(const QModelIndex &index) const 43 | { 44 | return QModelIndex(); 45 | } 46 | 47 | QVariant PositionModel::data(const QModelIndex &index, int role) const 48 | { 49 | int currentRow = itemsList.count() - index.row() - 1; 50 | if (currentRow < 0 || currentRow >= itemsList.count()) 51 | return QVariant(); 52 | 53 | if (role != Qt::DisplayRole && 54 | role != Qt::ToolTipRole && 55 | role != Qt::ForegroundRole && 56 | role != Qt::BackgroundRole && 57 | role != Qt::TextAlignmentRole) { 58 | return QVariant(); 59 | } 60 | 61 | int indexColumn = index.column(); 62 | int indexRow = index.row(); 63 | 64 | if (role == Qt::TextAlignmentRole) { 65 | return Qt::AlignLeft | Qt::AlignVCenter; 66 | } 67 | 68 | if (role == Qt::BackgroundRole) 69 | { 70 | if (!(indexRow % 2)) { 71 | return appGlobalData.appTheme.altRowColor; 72 | } else { 73 | return QVariant(); 74 | } 75 | } 76 | 77 | if (role == Qt::ForegroundRole) { 78 | if (indexRow < itemsList.size()) { 79 | if (indexColumn == 2) { 80 | if (itemsList[indexRow].side == PositionSide::POSITION_SIDE_LONG) { 81 | return appGlobalData.appTheme.red; 82 | } else if (itemsList[indexRow].side == PositionSide::POSITION_SIDE_SHORT) { 83 | return appGlobalData.appTheme.darkGreen; 84 | } 85 | } else if (indexColumn == 8) { 86 | if (itemsList[indexRow].posPnL >= 0) { 87 | return appGlobalData.appTheme.red; 88 | } else { 89 | return appGlobalData.appTheme.darkGreen; 90 | } 91 | } 92 | } 93 | 94 | return appGlobalData.appTheme.black; 95 | } 96 | 97 | if (role == Qt::DisplayRole && indexRow < itemsList.size()) { 98 | const PositionItem& item = itemsList[indexRow]; 99 | switch (indexColumn) { 100 | case 0: 101 | return item.srvId; 102 | case 1: 103 | return item.instrument; 104 | case 2: 105 | return item.side == PositionSide::POSITION_SIDE_LONG ? tr("Buy") : tr("Sell"); 106 | case 3: 107 | return item.price; 108 | case 4: 109 | return item.total; 110 | case 5: 111 | return item.yesterday; 112 | case 6: 113 | return item.today; 114 | case 7: 115 | return item.closable; 116 | case 8: 117 | return item.posPnL; 118 | } 119 | } 120 | 121 | return QVariant(); 122 | } 123 | 124 | Qt::ItemFlags PositionModel::flags(const QModelIndex &index) const 125 | { 126 | return Qt::ItemIsSelectable | Qt::ItemIsEnabled; 127 | } 128 | 129 | QVariant PositionModel::headerData(int section, Qt::Orientation orientation, int role) const 130 | { 131 | if (orientation != Qt::Horizontal)return QVariant(); 132 | 133 | if (role == Qt::TextAlignmentRole) { 134 | return Qt::AlignLeft; 135 | } 136 | 137 | if (role == Qt::SizeHintRole) 138 | { 139 | switch (section) 140 | { 141 | case 0: return QSize(srvIdWidth, defaultHeightForRow); 142 | case 1: return QSize(instrumentWidth, defaultHeightForRow); 143 | case 2: return QSize(sideWidth, defaultHeightForRow); 144 | case 3: return QSize(priceWidth, defaultHeightForRow); 145 | case 4: 146 | case 5: 147 | case 6: 148 | case 7: return QSize(quantityWidth, defaultHeightForRow); 149 | case 8: return QSize(pnlWidth, defaultHeightForRow); 150 | default: 151 | break; 152 | } 153 | return QVariant(); 154 | } 155 | 156 | if (role != Qt::DisplayRole) return QVariant(); 157 | if (section >= headerLabels.count()) return QVariant(); 158 | 159 | return headerLabels.at(section); 160 | } 161 | 162 | int PositionModel::rowCount(const QModelIndex &parent) const 163 | { 164 | return itemsList.count(); 165 | } 166 | 167 | int PositionModel::columnCount(const QModelIndex &parent) const 168 | { 169 | return headerLabels.count(); 170 | } 171 | 172 | bool PositionModel::getPosItem(const char* instrument, PositionItem& item) 173 | { 174 | for (auto& elem : itemsList) { 175 | if (!_stricmp(elem.instrument, instrument)) { 176 | item = elem; 177 | return true; 178 | } 179 | } 180 | 181 | return false; 182 | } 183 | 184 | bool PositionModel::getPosItem(int row, PositionItem& item) 185 | { 186 | if (row < 0 || row >= itemsList.size()) { 187 | return false; 188 | } 189 | 190 | item = itemsList[row]; 191 | 192 | return true; 193 | } 194 | 195 | void PositionModel::getAllPosItems(std::vector& items) 196 | { 197 | for (auto& item : itemsList) { 198 | items.push_back(item); 199 | } 200 | } 201 | 202 | void PositionModel::copyPosItem(PositionItem& item, const AlgoSE::AccountPosition& pos) 203 | { 204 | item.srvId = pos.srvId; 205 | strcpy(item.instrument, pos.instrument); 206 | item.side = pos.side; 207 | item.total = pos.cumQty; 208 | item.today = pos.todayQty; 209 | item.yesterday = pos.histQty; 210 | item.closable = pos.cumQty - pos.frozen; 211 | item.price = pos.avgPx; 212 | item.realPnL = pos.realizedPnL; 213 | item.posPnL = pos.unrealizedPnL; 214 | } 215 | 216 | void PositionModel::updatePosition(const AlgoSE::AccountPosition& pos) 217 | { 218 | int i = 0; 219 | int size = itemsList.size(); 220 | for (i = 0; i < size; i++) { 221 | if (itemsList[i].srvId == pos.srvId && 222 | !strcmp(pos.instrument, itemsList[i].instrument) && 223 | itemsList[i].side == pos.side) { 224 | break; 225 | } 226 | } 227 | 228 | if (i == size) { 229 | if (pos.cumQty > 0) { 230 | int currentIndex = size; 231 | int offset = 0; 232 | for (auto& elem : itemsList) { 233 | int cmp = strcmp(pos.instrument, elem.instrument); 234 | if (cmp < 0) { 235 | offset++; 236 | continue; 237 | } else { 238 | if (cmp == 0) { 239 | if (pos.side > elem.side) { 240 | offset++; 241 | } 242 | } 243 | break; 244 | } 245 | } 246 | 247 | if (offset > itemsList.size()) { 248 | assert(false); 249 | } 250 | 251 | beginInsertRows(QModelIndex(), currentIndex, currentIndex); 252 | PositionItem item = { 0 }; 253 | copyPosItem(item, pos); 254 | // itemsList.push_back(item); 255 | itemsList.insert(offset, item); 256 | endInsertRows(); 257 | } 258 | } else { 259 | copyPosItem(itemsList[i], pos); 260 | if (itemsList[i].total > 0) { 261 | emit dataChanged(index(i, 0), index(i, headerLabels.size() - 1)); 262 | } else { 263 | beginRemoveRows(QModelIndex(), i, i); 264 | itemsList.removeAt(i); 265 | endRemoveRows(); 266 | // emit dataChanged(index(0, 0), index(itemsList.size(), headerLabels.size() - 1)); 267 | } 268 | } 269 | } -------------------------------------------------------------------------------- /Src/posmodel.h: -------------------------------------------------------------------------------- 1 | #ifndef POSITION_MODEL_H 2 | #define POSITION_MODEL_H 3 | 4 | #include 5 | #include "Defines.h" 6 | 7 | typedef struct { 8 | int srvId; 9 | char instrument[32]; 10 | int side; 11 | int total; 12 | int yesterday; 13 | int today; 14 | int closable; 15 | int own; 16 | double price; 17 | double margin; 18 | double posPnL; 19 | double realPnL; 20 | } PositionItem; 21 | 22 | class PositionModel : public QAbstractItemModel 23 | { 24 | Q_OBJECT 25 | 26 | public: 27 | PositionModel(QObject* parent); 28 | ~PositionModel(); 29 | 30 | void updatePosition(const AlgoSE::AccountPosition& pos); 31 | const QStringList& getHeaderLabels() const; 32 | 33 | QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const; 34 | QModelIndex parent(const QModelIndex &index) const; 35 | 36 | QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; 37 | Qt::ItemFlags flags(const QModelIndex &index) const; 38 | QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; 39 | 40 | int rowCount(const QModelIndex &parent = QModelIndex()) const; 41 | int columnCount(const QModelIndex &parent = QModelIndex()) const; 42 | 43 | bool getPosItem(const char* instrument, PositionItem& item); 44 | bool getPosItem(int row, PositionItem& item); 45 | void getAllPosItems(std::vector& items); 46 | 47 | private: 48 | void copyPosItem(PositionItem& item, const AlgoSE::AccountPosition& pos); 49 | 50 | private: 51 | QStringList headerLabels; 52 | QList itemsList; 53 | 54 | int srvIdWidth; 55 | int instrumentWidth; 56 | int priceWidth; 57 | int quantityWidth; 58 | int actionWidth; 59 | int sideWidth; 60 | int pnlWidth; 61 | }; 62 | 63 | #endif // POSITION_MODEL_H -------------------------------------------------------------------------------- /Src/powergate.h: -------------------------------------------------------------------------------- 1 | #ifndef POWER_GATE_H 2 | #define POWER_GATE_H 3 | 4 | #include 5 | #include 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include "ui_powergate.h" 18 | #include "quotemodel.h" 19 | #include "quotedialog.h" 20 | #include "logmodel.h" 21 | #include "stratmodel.h" 22 | #include "ordermodel.h" 23 | #include "posmodel.h" 24 | #include "stratlogdialog.h" 25 | #include "logindialog.h" 26 | #include "tradepanel.h" 27 | #include "Semaphore.h" 28 | 29 | #include "Defines.h" 30 | #include "Engine.h" 31 | #include "Service.h" 32 | #include "Strategy.h" 33 | 34 | using namespace AlgoSE; 35 | 36 | using std::vector; 37 | using std::unordered_map; 38 | 39 | class DockHost; 40 | 41 | #define APP_CONFIG_FILE_NAME ("PowerGate.ini") 42 | #define APP_ENCRYPT_KEY "APP_ENCRYPT_KEY" 43 | #define SCHED_TASKS_TIMER_INTERVAL (2000) // ms 44 | 45 | enum { 46 | STRATEGY_SCHED_START, 47 | STRATEGY_SCHED_PAUSE, 48 | STRATEGY_SCHED_RESUME, 49 | STRATEGY_SCHED_STOP, 50 | }; 51 | 52 | class SrvStLabelCtxMenu : public QMenu 53 | { 54 | Q_OBJECT 55 | public: 56 | explicit SrvStLabelCtxMenu(int srvType, int srvId, QWidget *parent = 0); 57 | int getSrvType() const { return srvType; } 58 | int getSrvId() const { return srvId; } 59 | 60 | public slots : 61 | void showMenu(const QPoint &pos); 62 | 63 | private: 64 | int srvType; 65 | int srvId; 66 | }; 67 | 68 | class ClickableLabel : public QLabel 69 | { 70 | Q_OBJECT 71 | 72 | public: 73 | explicit ClickableLabel(const QString& text = "", QWidget* parent = 0) 74 | : QLabel(parent) 75 | { 76 | setText(text); 77 | } 78 | 79 | ~ClickableLabel() {} 80 | 81 | signals: 82 | void clicked(); 83 | 84 | protected: 85 | void mousePressEvent(QMouseEvent* event) 86 | { 87 | emit clicked(); 88 | } 89 | }; 90 | 91 | //////////////////////////////////////////////////////////////////////////////// 92 | class AlertManager 93 | { 94 | public: 95 | AlertManager(); 96 | static AlertManager* getInstance(); 97 | int generateAlertId(); 98 | void addAlert(int alertId); 99 | void cancelAlert(int alertId); 100 | void stop(); 101 | 102 | private: 103 | void alert(); 104 | 105 | private: 106 | unsigned long m_nextAlertId; 107 | 108 | std::mutex m_alertsLock; 109 | std::set m_alerts; 110 | 111 | std::thread* m_alertThread; 112 | bool m_alertStop; 113 | Utils::DefaultSemaphoreType m_signal; 114 | 115 | static AlertManager* m_instance; 116 | }; 117 | 118 | //////////////////////////////////////////////////////////////////////////////// 119 | class Mailer 120 | { 121 | public: 122 | Mailer(); 123 | bool readConfig(const char* file); 124 | bool sendMail(const char* subject, const std::vector& body); 125 | 126 | private: 127 | bool sendMail(const char* subject, char* body); 128 | 129 | private: 130 | bool m_enable; 131 | std::string m_sender; 132 | std::string m_from; 133 | std::string m_to; 134 | std::string m_username; 135 | std::string m_passwd; 136 | std::string m_smtpSrv; 137 | int m_smtpPort; 138 | std::string m_computerName; 139 | std::string m_computerUser; 140 | }; 141 | 142 | //////////////////////////////////////////////////////////////////////////////// 143 | class PowerGate : public QMainWindow, AlgoSE::IEngine::Listener 144 | { 145 | Q_OBJECT 146 | 147 | public: 148 | PowerGate(); 149 | ~PowerGate(); 150 | 151 | void closeEvent(QCloseEvent *event); 152 | 153 | // callbacks 154 | void onSystemLog(const SystemLog& log); 155 | void onServiceStatus(const ServiceStatus& state); 156 | void onAccountDetails(const AccountDetails& account); 157 | void onAccountPosition(const AccountPosition& position); 158 | void onStrategyParameter(const StrategyParam& param); 159 | void onStrategyPosition(const StrategyPosition& position); 160 | void onStrategyLog(const StrategyLog& log); 161 | void onTick(const Tick& tick); 162 | void onOrderStatus(const Order& order); 163 | void onExecutionReport(const Execution& exec); 164 | void onStrategyStatus(const StrategyStatus& state); 165 | 166 | bool eventFilter(QObject *target, QEvent *event); 167 | 168 | private: 169 | void moveWidgetsToSplitter(); 170 | void fixTableViews(QWidget *wid); 171 | void setColumnResizeMode(QTableView*, int, QHeaderView::ResizeMode); 172 | void setColumnResizeMode(QTableView*, QHeaderView::ResizeMode); 173 | void saveAppLayout(); 174 | bool confirmExitApp(); 175 | bool writeUILog(int level, const char* msgFmt, ...); 176 | 177 | private slots: 178 | void restoreAppLayout(); 179 | void startLogin(); 180 | void initAlgoSE(); 181 | void updateSystemLog(SystemLog log); 182 | void updateServiceStatus(ServiceStatus status); 183 | void updateAccountDetails(AccountDetails acct); 184 | void updateStratParams(StrategyParam param); 185 | void updateStratPositions(StrategyPosition pos); 186 | void updateStratLog(StrategyLog log); 187 | void updateOrderStatus(Order order); 188 | void updateStratStatus(StrategyStatus state); 189 | void updateExecution(Execution exec); 190 | void updatePosition(AccountPosition pos); 191 | void updateQuote(Tick tick); 192 | void sendReportMail(); 193 | void closeApp(); 194 | void exitApp(); 195 | void onStratTableViewClicked(const QModelIndex &index); 196 | void onStratTableViewDoubleClicked(const QModelIndex &index); 197 | void onQuoteTableViewDoubleClicked(const QModelIndex &index); 198 | void onPosTableViewDoubleClicked(const QModelIndex &index); 199 | void onOrderTableViewDoubleClicked(const QModelIndex &index); 200 | void onOrderTableViewMenuRequested(const QPoint& pos); 201 | void onQuoteTableViewMenuRequested(QPoint pos); 202 | void onQuoteDlgExit(const string& instrumet); 203 | void onStartAllStrategiesBtnClicked(); 204 | void onStopAllStrategiesBtnClicked(); 205 | void onTradePanelBtnClicked(); 206 | void onCancelAllOrdersBtnClicked(); 207 | void onCloseAllPosBtnClicked(); 208 | void onVerboseLogCBClicked(bool toggled); 209 | void onStratLogDlgExit(int stratId); 210 | void timeElapsed(); 211 | void reloadService(); 212 | void subscribeQuote(); 213 | void unsubscribeQuote(); 214 | void popupDepthQuoteDialog(); 215 | void popupTradePanelFromQuoteTableView(); 216 | void exportOrderList(); 217 | 218 | signals: 219 | void signalSystemLog(SystemLog); 220 | void signalServiceStatus(ServiceStatus); 221 | void signalAccountDetails(AccountDetails); 222 | void signalStratParams(StrategyParam); 223 | void signalStratPositions(StrategyPosition); 224 | void signalStratLog(StrategyLog); 225 | void signalOrderStatus(Order); 226 | void signalStratStatus(StrategyStatus); 227 | void signalExecutionReport(Execution); 228 | void signalPosition(AccountPosition); 229 | void signalQuote(Tick); 230 | 231 | 232 | private: 233 | void updateQuoteDialogs(const Tick& tick); 234 | 235 | void onParamCellClicked(const QModelIndex& index); 236 | void onStartCellClicked(const QModelIndex& index); 237 | void onPauseCellClicked(const QModelIndex& index); 238 | void onLongPosCellClicked(const QModelIndex& index); 239 | void onShortPosCellClicked(const QModelIndex& index); 240 | void onShowLogCellClicked(const QModelIndex& index); 241 | void onStratLogCellClicked(const QModelIndex& index); 242 | void onStratCmdCellClicked(const QModelIndex& index); 243 | 244 | void showDepthQuoteDialog(const string& instrument); 245 | void showStratLogDlg(int stratId, QString& stratName); 246 | void showTradePanel(const string& instrument, int side, int quantity); 247 | void installSchedTask(); 248 | void checkSchedTask(); 249 | void readRestartTime(); 250 | bool checkRestartTask(); 251 | void readStrategiesSchedTime(); 252 | void readSendReportMailTime(); 253 | bool checkStrategiesSchedTask(); 254 | bool checkSendMailSchedTask(); 255 | 256 | private: 257 | Engine* pAlgoSE; 258 | 259 | QuoteModel* quoteModel; 260 | LogModel* logModel; 261 | StratModel* stratModel; 262 | OrderModel* orderModel; 263 | PositionModel* posModel; 264 | AlgoSE::AccountDetails acctDetails; 265 | 266 | std::unordered_map lastQuotes; 267 | typedef struct { 268 | int time; 269 | double price; 270 | int volume; 271 | } TradeItem; 272 | std::unordered_map > lastTrades; 273 | 274 | std::unordered_map depthQuoteDialogs; 275 | 276 | TradePanel* tradePanel; 277 | 278 | QWidget *windowWidget; 279 | QSplitter* splitterMain; 280 | QSplitter* splitterCenter; 281 | QSplitter* splitterBottom; 282 | 283 | typedef struct { 284 | int id; 285 | StrategyStatus status; 286 | vector pos; 287 | vector params; 288 | int alertId; 289 | } StratItem; 290 | 291 | std::vector strategies; 292 | 293 | std::unordered_map > strategiesLog; 294 | std::unordered_map stratLogDlgs; 295 | 296 | typedef struct { 297 | ServiceStatus status; 298 | ClickableLabel* label; 299 | int alertId; 300 | } SrvStatus; 301 | 302 | vector srvStatus; 303 | 304 | private: 305 | QString appDir; 306 | 307 | Ui::PowerGate ui; 308 | 309 | bool titleShowed; 310 | bool verboseLog; 311 | bool subscribeDlgShowed; 312 | 313 | AlertManager* m_alertMgr; 314 | 315 | std::string m_initMailSubject; 316 | std::vector m_initMailLogs; 317 | bool m_reportMailSent; 318 | Mailer m_mailer; 319 | 320 | QTimer* m_timer; 321 | 322 | 323 | unsigned long m_schedLastSec; 324 | unsigned long m_schedCurrSec; 325 | unsigned long m_restartSecs; 326 | 327 | std::vector m_restartTime; 328 | std::vector m_stopTime; 329 | 330 | std::vector m_sendReportMailTime; 331 | 332 | typedef struct { 333 | bool executed; 334 | int type; 335 | unsigned long execSecs; 336 | } StrategySchedTask; 337 | 338 | vector m_strategiesSchedTasks; 339 | }; 340 | 341 | #endif // POWER_GATE_H -------------------------------------------------------------------------------- /Src/quotedialog.h: -------------------------------------------------------------------------------- 1 | #ifndef QUOTE_DIALOG_H 2 | #define QUOTE_DIALOG_H 3 | 4 | #include 5 | #include 6 | #include "quotemodel.h" 7 | #include "ui_quotedialog.h" 8 | 9 | using std::string; 10 | 11 | class QuoteDialog : public QDialog 12 | { 13 | Q_OBJECT 14 | 15 | public: 16 | QuoteDialog(const string& instrument, QWidget* parent = 0); 17 | ~QuoteDialog(); 18 | const string& getInstrument() const; 19 | void notifyNewQuote(const Tick& tick); 20 | void closeEvent(QCloseEvent *event); 21 | void reject(); 22 | 23 | signals: 24 | void closeEvt(const string&); 25 | 26 | private: 27 | void printPx(char* text, double price); 28 | 29 | private: 30 | Ui::QuoteDialog ui; 31 | 32 | string instrument; 33 | double lastAsk1Px; 34 | double lastBid1Px; 35 | TradesModel* tradesModel; 36 | }; 37 | 38 | #endif // QUOTE_DIALOG_H -------------------------------------------------------------------------------- /Src/quotemodel.h: -------------------------------------------------------------------------------- 1 | #ifndef QUOTE_MODEL_H 2 | #define QUOTE_MODEL_H 3 | 4 | #include 5 | #include 6 | #include "Engine.h" 7 | #include "circular.h" 8 | 9 | using std::string; 10 | 11 | using namespace AlgoSE; 12 | 13 | typedef struct { 14 | char instrument[32]; 15 | char updateTime[32]; 16 | double open; 17 | double price; 18 | int change; 19 | double close; 20 | double highest; 21 | double lowest; 22 | double upperLimit; 23 | double lowerLimit; 24 | long long openInt; 25 | long long volume; 26 | double bidPrice1; 27 | int bidVolume1; 28 | double askPrice1; 29 | int askVolume1; 30 | } QuoteItem; 31 | 32 | class QuoteModel : public QAbstractItemModel 33 | { 34 | Q_OBJECT 35 | 36 | public: 37 | QuoteModel(QObject *parent); 38 | ~QuoteModel(); 39 | 40 | QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const; 41 | QModelIndex parent(const QModelIndex &index) const; 42 | 43 | QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; 44 | // Qt::ItemFlags flags(const QModelIndex &index) const; 45 | QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; 46 | 47 | int rowCount(const QModelIndex &parent = QModelIndex()) const; 48 | int columnCount(const QModelIndex &parent = QModelIndex()) const; 49 | 50 | void clear(); 51 | void notifyNewQuote(const AlgoSE::Tick& tick); 52 | QStringList& getHeaderLabels(); 53 | 54 | private: 55 | void copyQuoteItem(QuoteItem& quote, const AlgoSE::Tick& tick, bool newQuote); 56 | 57 | private: 58 | QStringList m_headerLabels; 59 | QList m_quotes; 60 | 61 | int updateTimeWidth; 62 | int defaultWidth; 63 | }; 64 | 65 | #define MAX_TRADE_ITEM_SIZE (20) 66 | 67 | class TradesModel : public QAbstractItemModel 68 | { 69 | Q_OBJECT 70 | 71 | public: 72 | 73 | typedef struct { 74 | char type; 75 | double preClosePx; 76 | double lastPx; 77 | char time[16]; 78 | char price[16]; 79 | int volume; 80 | } TradesItem; 81 | 82 | TradesModel(QObject *parent); 83 | ~TradesModel(); 84 | 85 | QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const; 86 | QModelIndex parent(const QModelIndex &index) const; 87 | 88 | QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; 89 | // Qt::ItemFlags flags(const QModelIndex &index) const; 90 | QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; 91 | 92 | int rowCount(const QModelIndex &parent = QModelIndex()) const; 93 | int columnCount(const QModelIndex &parent = QModelIndex()) const; 94 | 95 | void clear(); 96 | void setInstrument(const string& instrument); 97 | const string& getInstrument() const; 98 | void notifyNewQuote(const AlgoSE::Tick& tick); 99 | 100 | private: 101 | string instrument; 102 | QStringList m_headerLabels; 103 | 104 | circular_buffer m_tradeList; 105 | 106 | int updateTimeWidth; 107 | int priceWidth; 108 | int defaultWidth; 109 | }; 110 | 111 | #endif // QUOTE_MODEL_H -------------------------------------------------------------------------------- /Src/resource.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/algosenses/PowerGate/7996dec6889ce59f5dc1c145aebd61b7ab28f031/Src/resource.h -------------------------------------------------------------------------------- /Src/smtpsocket.c: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of libquickmail. 3 | 4 | libquickmail is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | libquickmail is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with libquickmail. If not, see . 16 | */ 17 | 18 | #include "smtpsocket.h" 19 | #include 20 | #include 21 | #include 22 | #if _MSC_VER 23 | #define strdup _strdup 24 | #define va_copy(dst,src) ((dst) = (src)) 25 | #endif 26 | 27 | //////////////////////////////////////////////////////////////////////// 28 | 29 | #define DEBUG_ERROR(errmsg) 30 | static const char* ERRMSG_MEMORY_ALLOCATION_ERROR = "Memory allocation error"; 31 | 32 | //////////////////////////////////////////////////////////////////////// 33 | 34 | SOCKET socket_open (const char* smtpserver, unsigned int smtpport, char** errmsg) 35 | { 36 | struct in_addr ipv4addr; 37 | SOCKET sock; 38 | struct sockaddr_in remote_sock_addr; 39 | static const struct linger linger_option = {-1, 2}; //linger 2 seconds when disconnecting 40 | //determine IPv4 address of SMTP server 41 | ipv4addr.s_addr = inet_addr(smtpserver); 42 | if (ipv4addr.s_addr == INADDR_NONE) { 43 | struct hostent* addr; 44 | if ((addr = gethostbyname(smtpserver)) != NULL && (addr->h_addrtype == AF_INET && addr->h_length >= 1 && ((struct in_addr*)addr->h_addr)->s_addr != 0)) 45 | memcpy(&ipv4addr, addr->h_addr, sizeof(ipv4addr)); 46 | } 47 | if (ipv4addr.s_addr == INADDR_NONE) { 48 | if (errmsg) 49 | *errmsg = "Unable to resolve SMTP server host name"; 50 | return INVALID_SOCKET; 51 | } 52 | //create socket 53 | sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 54 | if (sock == INVALID_SOCKET) { 55 | if (errmsg) 56 | *errmsg = "Error creating socket for SMTP connection"; 57 | return INVALID_SOCKET; 58 | } 59 | //connect 60 | remote_sock_addr.sin_family = AF_INET; 61 | remote_sock_addr.sin_port = htons(smtpport); 62 | remote_sock_addr.sin_addr.s_addr = ipv4addr.s_addr; 63 | if (connect(sock, (struct sockaddr*)&remote_sock_addr, sizeof(remote_sock_addr)) != 0) { 64 | if (errmsg) 65 | *errmsg = "Error connecting to SMTP server"; 66 | socket_close(sock); 67 | return INVALID_SOCKET; 68 | } 69 | //set linger option 70 | setsockopt(sock, SOL_SOCKET, SO_LINGER, (const char*)&linger_option, sizeof(linger_option)); 71 | return sock; 72 | } 73 | 74 | void socket_close (SOCKET sock) 75 | { 76 | #ifndef _WIN32 77 | shutdown(sock, 2); 78 | #else 79 | closesocket(sock); 80 | #endif 81 | } 82 | 83 | int socket_send (SOCKET sock, const char* buf, int len) 84 | { 85 | int total_sent = 0; 86 | int l = 0; 87 | if (sock == 0 || !buf) 88 | return 0; 89 | if (len < 0) 90 | len = strlen(buf); 91 | while (len > 0 && (l = send(sock, buf, len, 0)) < len) { 92 | if (l == SOCKET_ERROR || l > len) 93 | return (total_sent > 0 ? total_sent : -1); 94 | total_sent += l; 95 | buf += l; 96 | len -= l; 97 | } 98 | return total_sent + l; 99 | } 100 | 101 | int socket_data_waiting (SOCKET sock, int timeoutseconds) 102 | { 103 | fd_set rfds; 104 | struct timeval tv; 105 | if (sock == 0) 106 | return 0; 107 | //make a set with only this socket 108 | FD_ZERO(&rfds); 109 | FD_SET(sock, &rfds); 110 | //make a timeval with the supplied timeout 111 | tv.tv_sec = timeoutseconds; 112 | tv.tv_usec = 0; 113 | //check the socket 114 | return (select(1, &rfds, NULL, NULL, &tv) > 0); 115 | } 116 | 117 | char* socket_receive_smtp (SOCKET sock) 118 | { 119 | char* buf = NULL; 120 | int bufsize = READ_BUFFER_CHUNK_SIZE; 121 | int pos = 0; 122 | int linestart; 123 | int n; 124 | if ((buf = (char*)malloc(bufsize)) == NULL) { 125 | DEBUG_ERROR(ERRMSG_MEMORY_ALLOCATION_ERROR) 126 | return NULL; 127 | } 128 | do { 129 | //insert line break if response is multiple lines 130 | if (pos > 0) { 131 | buf[pos++] = '\n'; 132 | if (pos >= bufsize) { 133 | char* newbuf; 134 | if ((newbuf = (char*)realloc(buf, bufsize + READ_BUFFER_CHUNK_SIZE)) == NULL) { 135 | free(buf); 136 | DEBUG_ERROR(ERRMSG_MEMORY_ALLOCATION_ERROR) 137 | return NULL; 138 | } 139 | buf = newbuf; 140 | bufsize += READ_BUFFER_CHUNK_SIZE; 141 | } 142 | } 143 | //add each character read until it is a line break 144 | linestart = pos; 145 | while ((n = recv(sock, buf + pos, 1, 0)) == 1) { 146 | //detect optional carriage return (CR) 147 | if (buf[pos] == '\r') 148 | if (recv(sock, buf + pos, 1, 0) < 1) 149 | return NULL; 150 | //detect line feed (LF) 151 | if (buf[pos] == '\n') 152 | break; 153 | //enlarge buffer if necessary 154 | if (++pos >= bufsize) { 155 | char* newbuf; 156 | if ((newbuf = (char*)realloc(buf, bufsize + READ_BUFFER_CHUNK_SIZE)) == NULL) { 157 | free(buf); 158 | DEBUG_ERROR(ERRMSG_MEMORY_ALLOCATION_ERROR) 159 | return NULL; 160 | } 161 | buf = newbuf; 162 | bufsize += READ_BUFFER_CHUNK_SIZE; 163 | } 164 | } 165 | //exit on error (e.g. if connection is closed) 166 | if (n < 1) 167 | return NULL; 168 | } while (!isdigit(buf[linestart]) || !isdigit(buf[linestart + 1]) || !isdigit(buf[linestart + 2]) || buf[linestart + 3] != ' '); 169 | buf[pos] = 0; 170 | return buf; 171 | } 172 | 173 | int socket_get_smtp_code (SOCKET sock, char** message) 174 | { 175 | int code; 176 | char* buf = socket_receive_smtp(sock); 177 | if (!buf || strlen(buf) < 4 || (buf[3] != ' ' && buf[3] != '-')) { 178 | free(buf); 179 | return 999; 180 | } 181 | //get code 182 | buf[3] = 0; 183 | code = atoi(buf); 184 | //get error message (if needed) 185 | if (message /*&& code >= 400*/) 186 | *message = strdup(buf + 4); 187 | //clean up and return 188 | free(buf); 189 | return code; 190 | } 191 | 192 | int socket_smtp_command (SOCKET sock, FILE* debuglog, const char* template, ...) 193 | { 194 | char* message; 195 | int statuscode; 196 | //send command (if one is supplied) 197 | if (template) { 198 | va_list ap; 199 | va_list aq; 200 | char* cmd; 201 | int cmdlen; 202 | va_start(ap, template); 203 | //construct command to send 204 | va_copy(aq, ap); 205 | cmdlen = vsnprintf(NULL, 0, template, aq); 206 | va_end(aq); 207 | if ((cmd = (char*)malloc(cmdlen + 3)) == NULL) { 208 | DEBUG_ERROR(ERRMSG_MEMORY_ALLOCATION_ERROR) 209 | if (debuglog) 210 | fprintf(debuglog, "%s\n", ERRMSG_MEMORY_ALLOCATION_ERROR); 211 | va_end(ap); 212 | return 999; 213 | } 214 | vsnprintf(cmd, cmdlen + 1, template, ap); 215 | //log command to send 216 | if (debuglog) 217 | fprintf(debuglog, "SMTP> %s\n", cmd); 218 | //append CR+LF 219 | strcpy(cmd + cmdlen, "\r\n"); 220 | cmdlen += 2; 221 | //send command 222 | statuscode = socket_send(sock, cmd, cmdlen); 223 | //clean up 224 | free(cmd); 225 | va_end(ap); 226 | if (statuscode < 0) 227 | return 999; 228 | } 229 | //receive result 230 | message = NULL; 231 | statuscode = socket_get_smtp_code(sock, &message); 232 | if (debuglog) 233 | fprintf(debuglog, "SMTP< %i %s\n", statuscode, (message ? message : "")); 234 | free(message); 235 | return statuscode; 236 | } 237 | -------------------------------------------------------------------------------- /Src/smtpsocket.h: -------------------------------------------------------------------------------- 1 | /*! \file smtpsocket.h 2 | * \brief header file for TCP/IP socket and SMTP communication functions 3 | * \author Brecht Sanders 4 | * \date 2012-2013 5 | * \copyright GPL 6 | */ 7 | /* 8 | This file is part of libquickmail. 9 | 10 | libquickmail is free software: you can redistribute it and/or modify 11 | it under the terms of the GNU General Public License as published by 12 | the Free Software Foundation, either version 3 of the License, or 13 | (at your option) any later version. 14 | 15 | libquickmail is distributed in the hope that it will be useful, 16 | but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with libquickmail. If not, see . 22 | */ 23 | 24 | #ifndef __INCLUDED_SMTPSOCKET_H 25 | #define __INCLUDED_SMTPSOCKET_H 26 | 27 | #ifdef _WIN32 28 | #include 29 | #else 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #ifndef SOCKET 36 | #define SOCKET int 37 | #endif 38 | #ifndef INVALID_SOCKET 39 | #define INVALID_SOCKET -1 40 | #endif 41 | #ifndef SOCKET_ERROR 42 | #define SOCKET_ERROR -1 43 | #endif 44 | #endif 45 | #include 46 | #include 47 | 48 | #define READ_BUFFER_CHUNK_SIZE 128 49 | #define WRITE_BUFFER_CHUNK_SIZE 128 50 | 51 | #ifdef __cplusplus 52 | extern "C" { 53 | #endif 54 | 55 | /*! \brief connect network socket 56 | * \param smtpserver hostname or IP address of server 57 | * \param smtpport TCP port to connect to 58 | * \param errmsg optional pointer to where error message will be stored (must not be freed by caller) 59 | * \return open network socket or INVALID_SOCKET on error 60 | */ 61 | SOCKET socket_open (const char* smtpserver, unsigned int smtpport, char** errmsg); 62 | 63 | /*! \brief disconnect network socket 64 | * \param sock open network socket 65 | */ 66 | void socket_close (SOCKET sock); 67 | 68 | /*! \brief send data to a network socket 69 | * \param sock open network socket 70 | * \param buf buffer containing data 71 | * \param len size of buffer in bytes 72 | * \return number of bytes sent 73 | */ 74 | int socket_send (SOCKET sock, const char* buf, int len); 75 | 76 | /*! \brief check if data is waiting to be read from network socket 77 | * \param sock open network socket 78 | * \param timeoutseconds number of seconds to wait (0 to return immediately) 79 | * \return nonzero if data is waiting 80 | */ 81 | int socket_data_waiting (SOCKET sock, int timeoutseconds); 82 | 83 | /*! \brief read SMTP response from network socket 84 | * \param sock open network socket 85 | * \return null-terminated string containing received data (must be freed by caller), or NULL 86 | */ 87 | char* socket_receive_stmp (SOCKET sock); 88 | 89 | /*! \brief read SMTP response from network socket 90 | * \param sock open network socket 91 | * \param errmsg optional pointer to where error message will be stored (must be freed by caller) 92 | * \return SMTP status code (code >= 400 means error) 93 | */ 94 | int socket_get_smtp_code (SOCKET sock, char** errmsg); 95 | 96 | /*! \brief send SMTP command and return status code 97 | * \param sock open network socket 98 | * \param debuglog file handle to write debugging information to (NULL for no debugging) 99 | * \param template printf style formatting template 100 | * \return SMTP status code (code >= 400 means error) 101 | */ 102 | int socket_smtp_command (SOCKET sock, FILE* debuglog, const char* template, ...); 103 | 104 | #ifdef __cplusplus 105 | } 106 | #endif 107 | 108 | #endif //__INCLUDED_SMTPSOCKET_H 109 | -------------------------------------------------------------------------------- /Src/stratcmd.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | StratCmd 4 | 5 | 6 | 7 | 0 8 | 0 9 | 433 10 | 82 11 | 12 | 13 | 14 | 15 | 433 16 | 82 17 | 18 | 19 | 20 | Strategy Command 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | Command: 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | Qt::Horizontal 43 | 44 | 45 | 46 | 40 47 | 20 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | Ok 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 0 64 | 0 65 | 66 | 67 | 68 | Cancel 69 | 70 | 71 | 72 | 73 | 74 | 75 | Qt::Horizontal 76 | 77 | 78 | 79 | 40 80 | 20 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /Src/stratcmddialog.cpp: -------------------------------------------------------------------------------- 1 | #include "stratcmddialog.h" 2 | 3 | StratCmdDialog::StratCmdDialog(QWidget* parent) 4 | : QDialog(parent) 5 | { 6 | ui.setupUi(this); 7 | 8 | connect(ui.okBtn, SIGNAL(clicked()), this, SLOT(buttonOkClicked())); 9 | connect(ui.cancelBtn, SIGNAL(clicked()), this, SLOT(buttonCancelClicked())); 10 | } 11 | 12 | StratCmdDialog::~StratCmdDialog() 13 | { 14 | } 15 | 16 | QString StratCmdDialog::getCommand() const 17 | { 18 | return ui.cmdLine->text(); 19 | } 20 | 21 | void StratCmdDialog::buttonOkClicked() 22 | { 23 | QDialog::accept(); 24 | } 25 | 26 | void StratCmdDialog::buttonCancelClicked() 27 | { 28 | QDialog::reject(); 29 | } 30 | -------------------------------------------------------------------------------- /Src/stratcmddialog.h: -------------------------------------------------------------------------------- 1 | #ifndef STRATEGY_CMD_DIALOG_H 2 | #define STRATEGY_CMD_DIALOG_H 3 | 4 | #include 5 | #include "ui_stratcmd.h" 6 | 7 | class StratCmdDialog : public QDialog 8 | { 9 | Q_OBJECT 10 | 11 | public: 12 | StratCmdDialog(QWidget* parent = 0); 13 | ~StratCmdDialog(); 14 | QString getCommand() const; 15 | 16 | private: 17 | Ui::StratCmd ui; 18 | 19 | private slots: 20 | void buttonOkClicked(); 21 | void buttonCancelClicked(); 22 | }; 23 | 24 | #endif // STRATEGY_CMD_DIALOG_H -------------------------------------------------------------------------------- /Src/stratlog.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | StratLog 4 | 5 | 6 | 7 | 0 8 | 0 9 | 774 10 | 396 11 | 12 | 13 | 14 | Form 15 | 16 | 17 | 18 | 19 | 20 | QAbstractItemView::NoEditTriggers 21 | 22 | 23 | QAbstractItemView::SelectRows 24 | 25 | 26 | false 27 | 28 | 29 | false 30 | 31 | 32 | false 33 | 34 | 35 | false 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /Src/stratlogdialog.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "stratlogdialog.h" 4 | 5 | StratLogDialog::StratLogDialog(int stratId, QWidget* parent) 6 | : QDialog(parent) 7 | { 8 | ui.setupUi(this); 9 | 10 | this->stratId = stratId; 11 | 12 | stratLogModel = new StratLogModel(this); 13 | ui.logsTableView->setModel(stratLogModel); 14 | ui.logsTableView->horizontalHeader()->setSectionResizeMode(0, QHeaderView::ResizeToContents); 15 | ui.logsTableView->horizontalHeader()->setSectionResizeMode(1, QHeaderView::ResizeToContents); 16 | ui.logsTableView->horizontalHeader()->setSectionResizeMode(2, QHeaderView::Stretch); 17 | ui.logsTableView->horizontalHeader()->setMinimumSectionSize(0); 18 | QObject::connect(stratLogModel, &StratLogModel::rowsInserted, [this]() 19 | { 20 | if (ui.logsTableView->indexAt(ui.logsTableView->rect().bottomLeft()).row() == stratLogModel->rowCount() - 1) { 21 | QTimer::singleShot(0, ui.logsTableView, SLOT(scrollToBottom())); 22 | } 23 | }); 24 | } 25 | 26 | StratLogDialog::~StratLogDialog() 27 | { 28 | } 29 | 30 | void StratLogDialog::clear() 31 | { 32 | stratLogModel->clear(); 33 | } 34 | 35 | void StratLogDialog::appendLog(const AlgoSE::StrategyLog& log) 36 | { 37 | stratLogModel->insertLogItem(log); 38 | } 39 | 40 | void StratLogDialog::reject() 41 | { 42 | close(); 43 | } 44 | 45 | void StratLogDialog::closeEvent(QCloseEvent *event) 46 | { 47 | event->accept(); 48 | emit closeEvt(stratId); 49 | } -------------------------------------------------------------------------------- /Src/stratlogdialog.h: -------------------------------------------------------------------------------- 1 | #ifndef STRATEGY_LOG_DIALOG_H 2 | #define STRATEGY_LOG_DIALOG_H 3 | 4 | #include 5 | #include "Defines.h" 6 | #include "stratlogmodel.h" 7 | #include "ui_stratlog.h" 8 | 9 | class StratLogDialog : public QDialog 10 | { 11 | Q_OBJECT 12 | 13 | public: 14 | StratLogDialog(int stratId, QWidget* parent = 0); 15 | ~StratLogDialog(); 16 | void clear(); 17 | void appendLog(const AlgoSE::StrategyLog& log); 18 | void closeEvent(QCloseEvent *event); 19 | void reject(); 20 | 21 | signals: 22 | void closeEvt(int); 23 | 24 | private: 25 | Ui::StratLog ui; 26 | 27 | int stratId; 28 | StratLogModel* stratLogModel; 29 | }; 30 | 31 | #endif // STRATEGY_LOG_DIALOG_H -------------------------------------------------------------------------------- /Src/stratlogmodel.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "main.h" 6 | #include "stratlogmodel.h" 7 | 8 | StratLogModel::StratLogModel(QObject* parent) 9 | : QAbstractItemModel(parent) 10 | { 11 | headerLabels << tr("DateTime"); 12 | headerLabels << tr("Level"); 13 | headerLabels << tr("Text"); 14 | 15 | dateWidth = qMax(QApplication::fontMetrics().width("2000/12/30 23:59:59.999"), QApplication::fontMetrics().width("2000/12/30 12:59:59.999")) + 10; 16 | } 17 | 18 | StratLogModel::~StratLogModel() 19 | { 20 | itemsList.clear(); 21 | } 22 | 23 | QModelIndex StratLogModel::index(int row, int column, const QModelIndex &parent) const 24 | { 25 | if (!hasIndex(row, column, parent))return QModelIndex(); 26 | return createIndex(row, column); 27 | } 28 | 29 | QModelIndex StratLogModel::parent(const QModelIndex &index) const 30 | { 31 | return QModelIndex(); 32 | } 33 | 34 | QString StratLogModel::getLogLevelStr(int level) const 35 | { 36 | switch (level) { 37 | default: 38 | case AlgoSE::LogLevel::LOG_INFO: 39 | return "INFO"; 40 | 41 | case AlgoSE::LogLevel::LOG_DEBUG: 42 | return "DBG"; 43 | 44 | case AlgoSE::LogLevel::LOG_WARN: 45 | return "WARN"; 46 | 47 | case AlgoSE::LogLevel::LOG_ERROR: 48 | return "ERR"; 49 | 50 | case AlgoSE::LogLevel::LOG_FATAL: 51 | return "FATAL"; 52 | } 53 | 54 | return ""; 55 | } 56 | 57 | QVariant StratLogModel::data(const QModelIndex &index, int role) const 58 | { 59 | int currentRow = itemsList.count() - index.row() - 1; 60 | if (currentRow < 0 || currentRow >= itemsList.count()) return QVariant(); 61 | 62 | if (role == Qt::ToolTipRole) { 63 | return QString(itemsList.at(currentRow).datetime) + "\t" + getLogLevelStr(itemsList.at(currentRow).log.level) + "\t" + QString().fromLocal8Bit(itemsList.at(currentRow).log.text); 64 | } 65 | 66 | if (role != Qt::DisplayRole && 67 | role != Qt::ToolTipRole && 68 | role != Qt::ForegroundRole && 69 | role != Qt::TextAlignmentRole && 70 | role != Qt::BackgroundRole) { 71 | return QVariant(); 72 | } 73 | 74 | int indexRow = index.row(); 75 | if (role == Qt::BackgroundRole) 76 | { 77 | if (!(indexRow % 2)) { 78 | return appGlobalData.appTheme.altRowColor; 79 | } 80 | else { 81 | return QVariant(); 82 | } 83 | } 84 | 85 | if (role == Qt::ForegroundRole) { 86 | if (currentRow < itemsList.size()) { 87 | int level = itemsList.at(currentRow).log.level; 88 | if (level == AlgoSE::LogLevel::LOG_WARN || 89 | level == AlgoSE::LogLevel::LOG_ERROR || 90 | level == AlgoSE::LogLevel::LOG_FATAL) { 91 | return appGlobalData.appTheme.red; 92 | } 93 | } 94 | 95 | return appGlobalData.appTheme.black; 96 | } 97 | 98 | if (role == Qt::TextAlignmentRole) { 99 | return Qt::AlignLeft | Qt::AlignVCenter; 100 | } 101 | 102 | if (role == Qt::DisplayRole) { 103 | int indexColumn = index.column(); 104 | 105 | switch (indexColumn) { 106 | case 0: 107 | return itemsList.at(currentRow).datetime; 108 | case 1: 109 | return getLogLevelStr(itemsList.at(currentRow).log.level); 110 | case 2: 111 | return QString().fromLocal8Bit(itemsList.at(currentRow).log.text); 112 | 113 | default: 114 | break; 115 | } 116 | } 117 | 118 | return QVariant(); 119 | } 120 | 121 | Qt::ItemFlags StratLogModel::flags(const QModelIndex &index) const 122 | { 123 | return Qt::ItemIsSelectable | Qt::ItemIsEnabled; 124 | } 125 | 126 | QVariant StratLogModel::headerData(int section, Qt::Orientation orientation, int role) const 127 | { 128 | if (orientation != Qt::Horizontal)return QVariant(); 129 | 130 | if (role == Qt::SizeHintRole) 131 | { 132 | switch (section) 133 | { 134 | case 0: return QSize(dateWidth, defaultHeightForRow);//DateTime 135 | } 136 | return QVariant(); 137 | } 138 | 139 | if (role != Qt::DisplayRole) return QVariant(); 140 | if (section >= headerLabels.count()) return QVariant(); 141 | 142 | return headerLabels.at(section); 143 | } 144 | 145 | int StratLogModel::rowCount(const QModelIndex &parent) const 146 | { 147 | return itemsList.count(); 148 | } 149 | 150 | int StratLogModel::columnCount(const QModelIndex &parent) const 151 | { 152 | return headerLabels.count(); 153 | } 154 | 155 | void StratLogModel::clear() 156 | { 157 | beginResetModel(); 158 | itemsList.clear(); 159 | endResetModel(); 160 | } 161 | 162 | void StratLogModel::insertLogItem(const AlgoSE::StrategyLog& log) 163 | { 164 | int currentIndex = itemsList.size(); 165 | beginInsertRows(QModelIndex(), currentIndex, currentIndex); 166 | LogItem item; 167 | item.log = log; 168 | int year, month, day, hour, minute, sec, ms; 169 | DateTime(log.timestamp).getFields(year, month, day, hour, minute, sec, ms); 170 | sprintf(item.datetime, "%04d/%02d/%02d %02d:%02d:%02d.%03d", 171 | year, month, day, hour, minute, sec, ms); 172 | itemsList.push_front(item); 173 | endInsertRows(); 174 | } -------------------------------------------------------------------------------- /Src/stratlogmodel.h: -------------------------------------------------------------------------------- 1 | #ifndef STRATEGY_LOG_MODEL_H 2 | #define STRATEGY_LOG_MODEL_H 3 | 4 | #include 5 | #include "Defines.h" 6 | 7 | class StratLogModel : public QAbstractItemModel 8 | { 9 | Q_OBJECT 10 | 11 | public: 12 | StratLogModel(QObject *parent); 13 | ~StratLogModel(); 14 | 15 | void clear(); 16 | void insertLogItem(const AlgoSE::StrategyLog& log); 17 | 18 | QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const; 19 | QModelIndex parent(const QModelIndex &index) const; 20 | 21 | QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; 22 | Qt::ItemFlags flags(const QModelIndex &index) const; 23 | QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; 24 | 25 | int rowCount(const QModelIndex &parent = QModelIndex()) const; 26 | int columnCount(const QModelIndex &parent = QModelIndex()) const; 27 | 28 | private: 29 | QString getLogLevelStr(int level) const; 30 | 31 | private: 32 | int dateWidth; 33 | QStringList headerLabels; 34 | 35 | typedef struct { 36 | char datetime[32]; 37 | AlgoSE::StrategyLog log; 38 | } LogItem; 39 | 40 | QList itemsList; 41 | }; 42 | 43 | #endif // STRATEGY_LOG_MODEL_H 44 | -------------------------------------------------------------------------------- /Src/stratmodel.cpp: -------------------------------------------------------------------------------- 1 | #include "main.h" 2 | #include "stratmodel.h" 3 | 4 | const int StrategyAlertColumn = 11; 5 | 6 | StratModel::StratModel(QObject* parent) 7 | : QAbstractItemModel(parent) 8 | { 9 | headerLabels << tr("ID"); 10 | headerLabels << tr("Name"); 11 | headerLabels << tr("Params"); 12 | headerLabels << tr("Start"); 13 | headerLabels << tr("Pause"); 14 | headerLabels << tr("Submit"); 15 | headerLabels << tr("Cancel"); 16 | headerLabels << tr("Long"); 17 | headerLabels << tr("Short"); 18 | headerLabels << tr("Verbose"); 19 | headerLabels << tr("Command"); 20 | headerLabels << tr("Message"); 21 | 22 | idWidth = 50; 23 | nameWidth = 100; 24 | paramWidth = 50; 25 | ctrlWidth = 60; 26 | pauseWidth = 60; 27 | submitWidth = 70; 28 | cancelWidth = 70; 29 | longWidth = 50; 30 | shortWidth = 50; 31 | showWidth = 70; 32 | } 33 | 34 | StratModel::~StratModel() 35 | { 36 | } 37 | 38 | const QStringList& StratModel::getHeaderLabels() const 39 | { 40 | return headerLabels; 41 | } 42 | 43 | QModelIndex StratModel::index(int row, int column, const QModelIndex &parent) const 44 | { 45 | if (!hasIndex(row, column, parent)) return QModelIndex(); 46 | return createIndex(row, column); 47 | } 48 | 49 | QModelIndex StratModel::parent(const QModelIndex &index) const 50 | { 51 | return QModelIndex(); 52 | } 53 | 54 | QVariant StratModel::data(const QModelIndex &index, int role) const 55 | { 56 | int currentRow = itemsList.count() - index.row() - 1; 57 | if (currentRow < 0 || currentRow >= itemsList.count()) 58 | return QVariant(); 59 | 60 | if (role != Qt::DisplayRole && 61 | role != Qt::ToolTipRole && 62 | role != Qt::ForegroundRole && 63 | role != Qt::BackgroundRole && 64 | role != Qt::TextAlignmentRole) { 65 | return QVariant(); 66 | } 67 | 68 | int indexColumn = index.column(); 69 | int indexRow = index.row(); 70 | 71 | if (role == Qt::ForegroundRole) { 72 | // alert column 73 | if (indexColumn == StrategyAlertColumn) { 74 | if (itemsList[indexRow].redAlert) { 75 | return appGlobalData.appTheme.red; 76 | } else { 77 | return appGlobalData.appTheme.gray; 78 | } 79 | } 80 | 81 | return appGlobalData.appTheme.black; 82 | } 83 | 84 | if (role == Qt::TextAlignmentRole) { 85 | return Qt::AlignLeft | Qt::AlignVCenter; 86 | } 87 | 88 | if (role == Qt::BackgroundRole) 89 | { 90 | if (!(indexRow % 2)) { 91 | return appGlobalData.appTheme.altRowColor; 92 | } else { 93 | return QVariant(); 94 | } 95 | } 96 | 97 | if (role == Qt::ToolTipRole) { 98 | if (indexColumn == 1) { 99 | return QString(itemsList.at(indexRow).name); 100 | } else if (indexColumn == 11) { 101 | return QString().fromLocal8Bit(itemsList.at(indexRow).log); 102 | } 103 | } 104 | 105 | if (role == Qt::DisplayRole && indexRow < itemsList.size()) { 106 | const StratItem& item = itemsList[indexRow]; 107 | switch (indexColumn) { 108 | case 0: 109 | return item.strategyId; 110 | case 1: 111 | return item.name; 112 | case 2: 113 | return headerLabels.at(2); 114 | case 3: 115 | if (item.status == Strategy::STOPPED) { 116 | return tr("Start"); 117 | } else { 118 | return tr("Stop"); 119 | } 120 | case 4: 121 | if (item.status != Strategy::PAUSED) { 122 | return tr("Pause"); 123 | } else { 124 | return tr("Resume"); 125 | } 126 | case 5: 127 | return item.submittion; 128 | case 6: 129 | return item.cancellation; 130 | case 7: { 131 | int size = 0; 132 | for (auto& pos : item.posLongList) { 133 | size += pos.size; 134 | } 135 | return size; 136 | } 137 | case 8: { 138 | int size = 0; 139 | for (auto& pos : item.posShortList) { 140 | size += pos.size; 141 | } 142 | return size; 143 | } 144 | case 9: 145 | if (item.verbose) { 146 | return tr("Hide"); 147 | } else { 148 | return tr("Show"); 149 | } 150 | case 10: 151 | return headerLabels.at(10); 152 | case 11: 153 | return QString().fromLocal8Bit(item.log); 154 | default: 155 | return QVariant(); 156 | } 157 | } 158 | 159 | return QVariant(); 160 | } 161 | 162 | Qt::ItemFlags StratModel::flags(const QModelIndex &index) const 163 | { 164 | return Qt::ItemIsSelectable | Qt::ItemIsEnabled; 165 | } 166 | 167 | QVariant StratModel::headerData(int section, Qt::Orientation orientation, int role) const 168 | { 169 | if (orientation != Qt::Horizontal) return QVariant(); 170 | 171 | if (role == Qt::TextAlignmentRole) { 172 | // message 173 | if (section != 11) { 174 | return Qt::AlignLeft; 175 | } 176 | } 177 | 178 | if (role == Qt::SizeHintRole) 179 | { 180 | switch (section) 181 | { 182 | case 0: return QSize(idWidth, defaultHeightForRow); 183 | case 1: return QSize(nameWidth, defaultHeightForRow); 184 | case 2: return QSize(paramWidth, defaultHeightForRow); 185 | case 3: return QSize(ctrlWidth, defaultHeightForRow); 186 | case 4: return QSize(pauseWidth, defaultHeightForRow); 187 | case 5: return QSize(submitWidth, defaultHeightForRow); 188 | case 6: return QSize(cancelWidth, defaultHeightForRow); 189 | case 7: return QSize(longWidth, defaultHeightForRow); 190 | case 8: return QSize(shortWidth, defaultHeightForRow); 191 | case 9: return QSize(showWidth, defaultHeightForRow); 192 | } 193 | return QVariant(); 194 | } 195 | 196 | if (role != Qt::DisplayRole) return QVariant(); 197 | if (section >= headerLabels.count()) return QVariant(); 198 | 199 | return headerLabels.at(section); 200 | } 201 | 202 | int StratModel::rowCount(const QModelIndex &parent) const 203 | { 204 | return itemsList.count(); 205 | } 206 | 207 | int StratModel::columnCount(const QModelIndex &parent) const 208 | { 209 | return headerLabels.count(); 210 | } 211 | 212 | void StratModel::getAllStratItems(std::vector& strategies) 213 | { 214 | for (auto& item : itemsList) { 215 | strategies.push_back(item); 216 | } 217 | } 218 | 219 | void StratModel::copyStratItem(StratItem& item, const AlgoSE::StrategyStatus& state) 220 | { 221 | item.strategyId = state.strategyId; 222 | strcpy(item.name, state.name); 223 | item.status = state.state; 224 | item.verbose = state.verbose; 225 | item.submittion = state.submittion; 226 | item.cancellation = state.cancellation; 227 | } 228 | 229 | void StratModel::updateStratStatus(const AlgoSE::StrategyStatus& state) 230 | { 231 | int i = 0; 232 | int size = itemsList.size(); 233 | for (i = 0; i < size; i++) { 234 | if (itemsList[i].strategyId == state.strategyId) { 235 | break; 236 | } 237 | } 238 | 239 | if (i == size && state.state != Strategy::UNLOADED) { 240 | int currentIndex = size; 241 | beginInsertRows(QModelIndex(), currentIndex, currentIndex); 242 | StratItem item = { 0 }; 243 | copyStratItem(item, state); 244 | itemsList.push_back(item); 245 | endInsertRows(); 246 | emit dataChanged(index(itemsList.size() - 1, 0), index(itemsList.size() - 1, headerLabels.size() - 1)); 247 | } else { 248 | if (state.state != Strategy::UNLOADED) { 249 | copyStratItem(itemsList[i], state); 250 | emit dataChanged(index(i, 0), index(i, headerLabels.size() - 1)); 251 | } else { 252 | beginRemoveRows(QModelIndex(), i, i); 253 | itemsList.removeAt(i); 254 | endRemoveRows(); 255 | } 256 | } 257 | } 258 | 259 | void StratModel::updateStratPositions(const AlgoSE::StrategyPosition& pos) 260 | { 261 | int i = 0; 262 | int size = itemsList.size(); 263 | for (i = 0; i < size; i++) { 264 | if (itemsList[i].strategyId == pos.strategyId) { 265 | break; 266 | } 267 | } 268 | 269 | if (i == size) { 270 | return; 271 | } 272 | 273 | if (pos.side == PositionSide::POSITION_SIDE_LONG) { 274 | PosList& posList = itemsList[i].posLongList; 275 | size_t j = 0; 276 | for (; j < posList.size(); j++) { 277 | PosItem& item = posList[j]; 278 | if (!stricmp(pos.instrument, item.instrument)) { 279 | item.size = pos.quantity; 280 | break; 281 | } 282 | } 283 | if (j == posList.size()) { 284 | PosItem item; 285 | strcpy(item.instrument, pos.instrument); 286 | item.size = pos.quantity; 287 | posList.push_back(item); 288 | } 289 | } else if (pos.side == PositionSide::POSITION_SIDE_SHORT) { 290 | PosList& posList = itemsList[i].posShortList; 291 | size_t j = 0; 292 | for (; j < posList.size(); j++) { 293 | PosItem& item = posList[j]; 294 | if (!stricmp(pos.instrument, item.instrument)) { 295 | item.size = pos.quantity; 296 | break; 297 | } 298 | } 299 | if (j == posList.size()) { 300 | PosItem item; 301 | strcpy(item.instrument, pos.instrument); 302 | item.size = pos.quantity; 303 | posList.push_back(item); 304 | } 305 | } 306 | 307 | emit dataChanged(index(i, 0), index(i, headerLabels.size() - 1)); 308 | } 309 | 310 | void StratModel::updateStratLog(const AlgoSE::StrategyLog& log) 311 | { 312 | if (log.text == nullptr || log.text[0] == '\0') { 313 | return; 314 | } 315 | 316 | int i = 0; 317 | int size = itemsList.size(); 318 | for (i = 0; i < size; i++) { 319 | if (itemsList[i].strategyId == log.strategyId) { 320 | break; 321 | } 322 | } 323 | 324 | if (i == size) { 325 | return; 326 | } 327 | 328 | strncpy(itemsList[i].log, log.text, sizeof(itemsList[i].log)); 329 | itemsList[i].redAlert = true; 330 | 331 | emit dataChanged(index(i, 0), index(i, headerLabels.size() - 1)); 332 | } 333 | 334 | void StratModel::clearRedAlert(int stratId) 335 | { 336 | int i = 0; 337 | int size = itemsList.size(); 338 | for (i = 0; i < size; i++) { 339 | if (itemsList[i].strategyId == stratId) { 340 | break; 341 | } 342 | } 343 | 344 | if (i == size) { 345 | return; 346 | } 347 | 348 | itemsList[i].redAlert = false; 349 | 350 | emit dataChanged(index(i, StrategyAlertColumn), index(i, StrategyAlertColumn)); 351 | } -------------------------------------------------------------------------------- /Src/stratmodel.h: -------------------------------------------------------------------------------- 1 | #ifndef STRATEGY_MODEL_H 2 | #define STRATEGY_MODEL_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include "Defines.h" 9 | 10 | using std::string; 11 | using std::vector; 12 | 13 | typedef struct { 14 | char instrument[32]; 15 | int size; 16 | } PosItem; 17 | 18 | typedef vector PosList; 19 | 20 | class StratModel : public QAbstractItemModel 21 | { 22 | Q_OBJECT 23 | 24 | public: 25 | typedef struct { 26 | int strategyId; 27 | char name[32]; 28 | char desc[64]; 29 | int status; 30 | bool verbose; 31 | int submittion; 32 | int cancellation; 33 | PosList posLongList; 34 | PosList posShortList; 35 | char log[512]; 36 | bool redAlert; 37 | } StratItem; 38 | 39 | StratModel(QObject* parent); 40 | ~StratModel(); 41 | 42 | void updateStratStatus(const AlgoSE::StrategyStatus& state); 43 | void updateStratPositions(const AlgoSE::StrategyPosition& pos); 44 | void updateStratLog(const AlgoSE::StrategyLog& log); 45 | void clearRedAlert(int stratId); 46 | const QStringList& getHeaderLabels() const; 47 | 48 | QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const; 49 | QModelIndex parent(const QModelIndex &index) const; 50 | 51 | QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; 52 | Qt::ItemFlags flags(const QModelIndex &index) const; 53 | QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; 54 | 55 | int rowCount(const QModelIndex &parent = QModelIndex()) const; 56 | int columnCount(const QModelIndex &parent = QModelIndex()) const; 57 | void getAllStratItems(std::vector& strategies); 58 | 59 | private: 60 | void copyStratItem(StratItem& item, const AlgoSE::StrategyStatus& state); 61 | 62 | private: 63 | QStringList headerLabels; 64 | QList itemsList; 65 | 66 | int idWidth; 67 | int nameWidth; 68 | int paramWidth; 69 | int ctrlWidth; 70 | int pauseWidth; 71 | int submitWidth; 72 | int cancelWidth; 73 | int longWidth; 74 | int shortWidth; 75 | int showWidth; 76 | }; 77 | 78 | #endif // STRATEGY_MODEL_H -------------------------------------------------------------------------------- /Src/stratparams.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | StratParams 4 | 5 | 6 | 7 | 0 8 | 0 9 | 617 10 | 610 11 | 12 | 13 | 14 | Form 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | Qt::Horizontal 23 | 24 | 25 | 26 | 40 27 | 20 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | OK 36 | 37 | 38 | 39 | 40 | 41 | 42 | Cancel 43 | 44 | 45 | 46 | 47 | 48 | 49 | Qt::Horizontal 50 | 51 | 52 | 53 | 40 54 | 20 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | AlgoTrader 70 | 71 | 72 | 73 | 74 | 75 | QAbstractItemView::NoSelection 76 | 77 | 78 | false 79 | 80 | 81 | false 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | User 92 | 93 | 94 | 95 | 96 | 97 | QAbstractItemView::NoSelection 98 | 99 | 100 | false 101 | 102 | 103 | false 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | System 114 | 115 | 116 | 117 | 118 | 119 | QAbstractItemView::NoSelection 120 | 121 | 122 | false 123 | 124 | 125 | false 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | -------------------------------------------------------------------------------- /Src/stratparamsdialog.cpp: -------------------------------------------------------------------------------- 1 | #include "stratparamsdialog.h" 2 | 3 | StratParamsDialog::StratParamsDialog( 4 | const QString& strategy, 5 | vector& params, 6 | vector& outParams, 7 | QWidget* parent) 8 | : QDialog(parent) 9 | , touchedParams(outParams) 10 | { 11 | ui.setupUi(this); 12 | 13 | setWindowTitle(strategy); 14 | setWindowFlags(Qt::WindowCloseButtonHint | parent->windowFlags()); 15 | setWindowModality(Qt::ApplicationModal); 16 | setAttribute(Qt::WA_DeleteOnClose, true); 17 | 18 | connect(ui.okBtn, SIGNAL(clicked()), this, SLOT(buttonOkClicked())); 19 | connect(ui.cancelBtn, SIGNAL(clicked()), this, SLOT(buttonCancelClicked())); 20 | 21 | algoTraderParamModel = new StratParamsModel(StrategyParamCategory::PARAM_CATEGORY_ALGO_TRADER, this); 22 | algoTraderParamDelegate = new StratParamsDelegate(this); 23 | ui.algoTraderParamTableView->setModel(algoTraderParamModel); 24 | ui.algoTraderParamTableView->setItemDelegate(algoTraderParamDelegate); 25 | ui.algoTraderParamTableView->horizontalHeader()->setSectionResizeMode(0, QHeaderView::ResizeToContents); 26 | ui.algoTraderParamTableView->horizontalHeader()->setSectionResizeMode(1, QHeaderView::Stretch); 27 | ui.algoTraderGroupBox->hide(); 28 | 29 | userParamModel = new StratParamsModel(StrategyParamCategory::PARAM_CATEGORY_USER, this); 30 | userParamDelegate = new StratParamsDelegate(this); 31 | ui.userParamTableView->setModel(userParamModel); 32 | ui.userParamTableView->setItemDelegate(userParamDelegate); 33 | ui.userParamTableView->horizontalHeader()->setSectionResizeMode(0, QHeaderView::ResizeToContents); 34 | ui.userParamTableView->horizontalHeader()->setSectionResizeMode(1, QHeaderView::Stretch); 35 | // ui.userGroupBox->hide(); 36 | 37 | sysParamModel = new StratParamsModel(StrategyParamCategory::PARAM_CATEGORY_SYSTEM, this); 38 | sysParamDelegate = new StratParamsDelegate(this); 39 | ui.systemParamTableView->setModel(sysParamModel); 40 | ui.systemParamTableView->setItemDelegate(sysParamDelegate); 41 | ui.systemParamTableView->horizontalHeader()->setSectionResizeMode(0, QHeaderView::ResizeToContents); 42 | ui.systemParamTableView->horizontalHeader()->setSectionResizeMode(1, QHeaderView::Stretch); 43 | ui.systemGroupBox->hide(); 44 | 45 | bool hasParam = false; 46 | for (size_t i = 0; i < params.size(); i++) { 47 | if (params[i].category == StrategyParamCategory::PARAM_CATEGORY_ALGO_TRADER) { 48 | hasParam = true; 49 | algoTraderParamModel->updateParamItem(params[i]); 50 | } 51 | } 52 | if (hasParam) { 53 | ui.algoTraderGroupBox->show(); 54 | } 55 | 56 | hasParam = false; 57 | for (size_t i = 0; i < params.size(); i++) { 58 | if (params[i].category == StrategyParamCategory::PARAM_CATEGORY_USER) { 59 | hasParam = true; 60 | userParamModel->updateParamItem(params[i]); 61 | } 62 | } 63 | if (hasParam) { 64 | ui.userGroupBox->show(); 65 | } 66 | 67 | hasParam = false; 68 | for (size_t i = 0; i < params.size(); i++) { 69 | if (params[i].category == StrategyParamCategory::PARAM_CATEGORY_SYSTEM) { 70 | hasParam = true; 71 | sysParamModel->updateParamItem(params[i]); 72 | } 73 | } 74 | if (hasParam) { 75 | ui.systemGroupBox->show(); 76 | } 77 | } 78 | 79 | StratParamsDialog::~StratParamsDialog() 80 | { 81 | } 82 | 83 | void StratParamsDialog::showWindow() 84 | { 85 | show(); 86 | } 87 | 88 | void StratParamsDialog::buttonOkClicked() 89 | { 90 | algoTraderParamModel->getTouchedParams(touchedParams); 91 | userParamModel->getTouchedParams(touchedParams); 92 | 93 | QDialog::accept(); 94 | } 95 | 96 | void StratParamsDialog::buttonCancelClicked() 97 | { 98 | QDialog::reject(); 99 | } -------------------------------------------------------------------------------- /Src/stratparamsdialog.h: -------------------------------------------------------------------------------- 1 | #ifndef STRATEGY_PARAMS_DIALOG_H 2 | #define STRATEGY_PARAMS_DIALOG_H 3 | 4 | #include 5 | #include 6 | #include "ui_stratparams.h" 7 | #include "stratparamsmodel.h" 8 | 9 | using std::vector; 10 | 11 | class StratParamsDialog : public QDialog 12 | { 13 | Q_OBJECT 14 | 15 | public: 16 | void showWindow(); 17 | StratParamsDialog( 18 | const QString& strategy, 19 | vector& params, 20 | vector& outParams, 21 | QWidget* parent = 0); 22 | ~StratParamsDialog(); 23 | 24 | private: 25 | Ui::StratParams ui; 26 | 27 | StratParamsModel* algoTraderParamModel; 28 | StratParamsDelegate* algoTraderParamDelegate; 29 | 30 | StratParamsModel* userParamModel; 31 | StratParamsDelegate* userParamDelegate; 32 | 33 | StratParamsModel* sysParamModel; 34 | StratParamsDelegate* sysParamDelegate; 35 | 36 | vector& touchedParams; 37 | 38 | private slots: 39 | void buttonOkClicked(); 40 | void buttonCancelClicked(); 41 | }; 42 | 43 | #endif // STRATEGY_PARAMS_DIALOG_H -------------------------------------------------------------------------------- /Src/stratparamsmodel.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "main.h" 3 | #include "stratparamsmodel.h" 4 | 5 | StratParamsDelegate::StratParamsDelegate(QObject *parent) 6 | : QStyledItemDelegate(parent) 7 | { 8 | } 9 | 10 | QWidget *StratParamsDelegate::createEditor(QWidget *parent, 11 | const QStyleOptionViewItem &/* option */, 12 | const QModelIndex &/* index */) const 13 | { 14 | QLineEdit *editor = new QLineEdit(parent); 15 | editor->setFrame(false); 16 | 17 | return editor; 18 | } 19 | 20 | void StratParamsDelegate::setEditorData(QWidget *editor, 21 | const QModelIndex &index) const 22 | { 23 | QString value = index.model()->data(index, Qt::EditRole).toString(); 24 | 25 | QLineEdit *lineEdit = static_cast(editor); 26 | lineEdit->setText(value); 27 | } 28 | 29 | void StratParamsDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, 30 | const QModelIndex &index) const 31 | { 32 | QLineEdit *lineEdit = static_cast(editor); 33 | QString text = lineEdit->text(); 34 | 35 | model->setData(index, text, Qt::EditRole); 36 | } 37 | 38 | void StratParamsDelegate::updateEditorGeometry(QWidget *editor, 39 | const QStyleOptionViewItem &option, const QModelIndex &/* index */) const 40 | { 41 | editor->setGeometry(option.rect); 42 | } 43 | 44 | //////////////////////////////////////////////////////////////////////////////// 45 | StratParamsModel::StratParamsModel(int category, QObject *parent) 46 | : QAbstractItemModel(parent) 47 | { 48 | paramCategory = category; 49 | 50 | headerLabels << "Name"; 51 | headerLabels << "Value"; 52 | } 53 | 54 | StratParamsModel::~StratParamsModel() 55 | { 56 | } 57 | 58 | const QStringList& StratParamsModel::getHeaderLabels() const 59 | { 60 | return headerLabels; 61 | } 62 | 63 | QModelIndex StratParamsModel::index(int row, int column, const QModelIndex &parent) const 64 | { 65 | if (!hasIndex(row, column, parent)) return QModelIndex(); 66 | return createIndex(row, column); 67 | } 68 | 69 | QModelIndex StratParamsModel::parent(const QModelIndex &index) const 70 | { 71 | return QModelIndex(); 72 | } 73 | 74 | QVariant StratParamsModel::data(const QModelIndex &index, int role) const 75 | { 76 | int currentRow = itemsList.count() - index.row() - 1; 77 | if (currentRow < 0 || currentRow >= itemsList.count()) 78 | return QVariant(); 79 | 80 | if (role != Qt::DisplayRole && 81 | role != Qt::ToolTipRole && 82 | role != Qt::EditRole && 83 | role != Qt::ForegroundRole && 84 | role != Qt::BackgroundRole && 85 | role != Qt::TextAlignmentRole) { 86 | return QVariant(); 87 | } 88 | 89 | int indexColumn = index.column(); 90 | int indexRow = index.row(); 91 | 92 | if (role == Qt::TextAlignmentRole) { 93 | return Qt::AlignLeft | Qt::AlignVCenter; 94 | } 95 | 96 | if (role == Qt::BackgroundRole) { 97 | if (!(indexRow % 2)) { 98 | return appGlobalData.appTheme.altRowColor; 99 | } else { 100 | return QVariant(); 101 | } 102 | } 103 | 104 | if (role == Qt::DisplayRole || role == Qt::EditRole) { 105 | if (indexRow < itemsList.size()) { 106 | const StrategyParam& item = itemsList[indexRow].param; 107 | switch (indexColumn) { 108 | case 0: 109 | return QString().fromUtf8(item.name); 110 | case 1: 111 | return QString().fromUtf8(item.value); 112 | } 113 | } 114 | } 115 | 116 | return QVariant(); 117 | } 118 | 119 | bool StratParamsModel::setData(const QModelIndex &index, const QVariant &value, int role) 120 | { 121 | if (role != Qt::EditRole) { 122 | return false; 123 | } 124 | 125 | int indexColumn = index.column(); 126 | int indexRow = index.row(); 127 | if (indexRow >= itemsList.size() || indexColumn != 1) { 128 | return false; 129 | } 130 | 131 | strcpy(itemsList[indexRow].param.value, value.toString().toStdString().c_str()); 132 | itemsList[indexRow].touch = true; 133 | 134 | return true; 135 | } 136 | 137 | Qt::ItemFlags StratParamsModel::flags(const QModelIndex &index) const 138 | { 139 | if (index.column() == 1) { 140 | return Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsEditable; 141 | } 142 | 143 | return Qt::ItemIsSelectable | Qt::ItemIsEnabled; 144 | } 145 | 146 | QVariant StratParamsModel::headerData(int section, Qt::Orientation orientation, int role) const 147 | { 148 | if (orientation != Qt::Horizontal) return QVariant(); 149 | 150 | if (role != Qt::DisplayRole) return QVariant(); 151 | if (section >= headerLabels.count()) return QVariant(); 152 | 153 | return headerLabels.at(section); 154 | } 155 | 156 | int StratParamsModel::rowCount(const QModelIndex &parent) const 157 | { 158 | return itemsList.count(); 159 | } 160 | 161 | int StratParamsModel::columnCount(const QModelIndex &parent) const 162 | { 163 | return headerLabels.count(); 164 | } 165 | 166 | void StratParamsModel::updateParamItem(const AlgoSE::StrategyParam& param) 167 | { 168 | if (param.category != paramCategory) { 169 | return; 170 | } 171 | 172 | int i = 0; 173 | int size = itemsList.size(); 174 | for (i = 0; i < size; i++) { 175 | if (itemsList[i].param.strategyId == param.strategyId && 176 | !stricmp(itemsList[i].param.name, param.name)) { 177 | break; 178 | } 179 | } 180 | 181 | if (i == size) { 182 | int currentIndex = size; 183 | beginInsertRows(QModelIndex(), currentIndex, currentIndex); 184 | StratParamItem item; 185 | item.touch = false; 186 | memcpy(&item.param, ¶m, sizeof(StrategyParam)); 187 | itemsList.push_back(item); 188 | endInsertRows(); 189 | emit dataChanged(index(itemsList.size() - 1, 0), index(itemsList.size() - 1, headerLabels.size() - 1)); 190 | } else { 191 | itemsList[i].param = param; 192 | emit dataChanged(index(i, 0), index(i, headerLabels.size() - 1)); 193 | } 194 | } 195 | 196 | void StratParamsModel::getTouchedParams(std::vector& params) 197 | { 198 | for (int i = 0; i < itemsList.size(); i++) { 199 | if (itemsList[i].touch) { 200 | params.push_back(itemsList[i].param); 201 | } 202 | } 203 | } -------------------------------------------------------------------------------- /Src/stratparamsmodel.h: -------------------------------------------------------------------------------- 1 | #ifndef STRATEGY_PARAMS_MODEL_H 2 | #define STRATEGY_PARAMS_MODEL_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include "Defines.h" 8 | 9 | using std::vector; 10 | 11 | using namespace AlgoSE; 12 | 13 | class StratParamsDelegate : public QStyledItemDelegate 14 | { 15 | Q_OBJECT 16 | 17 | public: 18 | StratParamsDelegate(QObject *parent = 0); 19 | 20 | QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, 21 | const QModelIndex &index) const; 22 | 23 | void setEditorData(QWidget *editor, const QModelIndex &index) const; 24 | void setModelData(QWidget *editor, QAbstractItemModel *model, 25 | const QModelIndex &index) const; 26 | 27 | void updateEditorGeometry(QWidget *editor, 28 | const QStyleOptionViewItem &option, const QModelIndex &index) const; 29 | }; 30 | 31 | class StratParamsModel : public QAbstractItemModel 32 | { 33 | Q_OBJECT 34 | 35 | public: 36 | StratParamsModel(int category, QObject *parent = 0); 37 | ~StratParamsModel(); 38 | 39 | void updateParamItem(const AlgoSE::StrategyParam& param); 40 | const QStringList& getHeaderLabels() const; 41 | void getTouchedParams(vector& params); 42 | 43 | QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const; 44 | QModelIndex parent(const QModelIndex &index) const; 45 | 46 | QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; 47 | bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole); 48 | Qt::ItemFlags flags(const QModelIndex &index) const; 49 | QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; 50 | 51 | int rowCount(const QModelIndex &parent = QModelIndex()) const; 52 | int columnCount(const QModelIndex &parent = QModelIndex()) const; 53 | 54 | private: 55 | typedef struct { 56 | bool touch; 57 | StrategyParam param; 58 | } StratParamItem; 59 | 60 | QStringList headerLabels; 61 | QList itemsList; 62 | int paramCategory; 63 | }; 64 | 65 | #endif // STRATEGY_PARAMS_MODEL_H -------------------------------------------------------------------------------- /Src/stratpos.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | StratPos 4 | 5 | 6 | 7 | 0 8 | 0 9 | 433 10 | 200 11 | 12 | 13 | 14 | 15 | 0 16 | 0 17 | 18 | 19 | 20 | 21 | 433 22 | 200 23 | 24 | 25 | 26 | Form 27 | 28 | 29 | 30 | 31 | 32 | QLayout::SetFixedSize 33 | 34 | 35 | 36 | 37 | false 38 | 39 | 40 | false 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | Qt::Horizontal 50 | 51 | 52 | 53 | 40 54 | 20 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | Insert 63 | 64 | 65 | 66 | 67 | 68 | 69 | Delete 70 | 71 | 72 | 73 | 74 | 75 | 76 | Ok 77 | 78 | 79 | 80 | 81 | 82 | 83 | Cancel 84 | 85 | 86 | 87 | 88 | 89 | 90 | Qt::Horizontal 91 | 92 | 93 | 94 | 40 95 | 20 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | cancelBtn 108 | okBtn 109 | insertBtn 110 | deleteBtn 111 | tableView 112 | 113 | 114 | 115 | 116 | -------------------------------------------------------------------------------- /Src/stratposdialog.cpp: -------------------------------------------------------------------------------- 1 | #include "stratposdialog.h" 2 | 3 | StratPosDialog::StratPosDialog( 4 | int stratId, 5 | vector& position, 6 | QWidget* parent) 7 | : pos(position) 8 | , QDialog(parent) 9 | { 10 | ui.setupUi(this); 11 | 12 | posModel = new StratPosModel(position, this); 13 | posDelegate = new StratPosDelegate(this); 14 | 15 | ui.tableView->setModel(posModel); 16 | ui.tableView->setItemDelegate(posDelegate); 17 | ui.tableView->horizontalHeader()->setStretchLastSection(true); 18 | 19 | connect(ui.insertBtn, SIGNAL(clicked()), this, SLOT(buttonInsertClicked())); 20 | connect(ui.deleteBtn, SIGNAL(clicked()), this, SLOT(buttonDeleteClicked())); 21 | connect(ui.okBtn, SIGNAL(clicked()), this, SLOT(buttonOkClicked())); 22 | connect(ui.cancelBtn, SIGNAL(clicked()), this, SLOT(buttonCancelClicked())); 23 | } 24 | 25 | StratPosDialog::~StratPosDialog() 26 | { 27 | } 28 | 29 | void StratPosDialog::buttonInsertClicked() 30 | { 31 | posModel->insertNewRow(); 32 | } 33 | 34 | void StratPosDialog::buttonDeleteClicked() 35 | { 36 | posModel->removeRow(ui.tableView->currentIndex().row()); 37 | } 38 | 39 | void StratPosDialog::buttonOkClicked() 40 | { 41 | pos.clear(); 42 | QList& all = posModel->getAllPositions(); 43 | for (int i = 0; i < all.count(); i++) { 44 | pos.push_back(all[i]); 45 | } 46 | 47 | QDialog::accept(); 48 | } 49 | 50 | void StratPosDialog::buttonCancelClicked() 51 | { 52 | QDialog::reject(); 53 | } 54 | -------------------------------------------------------------------------------- /Src/stratposdialog.h: -------------------------------------------------------------------------------- 1 | #ifndef STRATEGY_POS_DIALOG_H 2 | #define STRATEGY_POS_DIALOG_H 3 | 4 | #include 5 | #include 6 | #include "ui_stratpos.h" 7 | #include "stratposmodel.h" 8 | 9 | using std::vector; 10 | 11 | class StratPosDialog : public QDialog 12 | { 13 | Q_OBJECT 14 | 15 | public: 16 | StratPosDialog( 17 | int stratId, 18 | // Input and Output 19 | vector& position, 20 | QWidget* parent = 0); 21 | ~StratPosDialog(); 22 | 23 | private: 24 | Ui::StratPos ui; 25 | 26 | vector& pos; 27 | StratPosModel* posModel; 28 | StratPosDelegate* posDelegate; 29 | 30 | private slots: 31 | void buttonInsertClicked(); 32 | void buttonDeleteClicked(); 33 | void buttonOkClicked(); 34 | void buttonCancelClicked(); 35 | }; 36 | 37 | #endif // STRATEGY_POS_DIALOG_H -------------------------------------------------------------------------------- /Src/stratposmodel.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "main.h" 3 | #include "stratposmodel.h" 4 | 5 | StratPosDelegate::StratPosDelegate(QObject *parent) 6 | : QStyledItemDelegate(parent) 7 | { 8 | } 9 | 10 | QWidget *StratPosDelegate::createEditor(QWidget *parent, 11 | const QStyleOptionViewItem &/* option */, 12 | const QModelIndex &/* index */) const 13 | { 14 | QLineEdit *editor = new QLineEdit(parent); 15 | editor->setFrame(false); 16 | 17 | return editor; 18 | } 19 | 20 | void StratPosDelegate::setEditorData(QWidget *editor, 21 | const QModelIndex &index) const 22 | { 23 | QString value = index.model()->data(index, Qt::EditRole).toString(); 24 | 25 | QLineEdit *lineEdit = static_cast(editor); 26 | lineEdit->setText(value); 27 | } 28 | 29 | void StratPosDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, 30 | const QModelIndex &index) const 31 | { 32 | QLineEdit *lineEdit = static_cast(editor); 33 | QString text = lineEdit->text(); 34 | 35 | model->setData(index, text, Qt::EditRole); 36 | } 37 | 38 | void StratPosDelegate::updateEditorGeometry(QWidget *editor, 39 | const QStyleOptionViewItem &option, const QModelIndex &/* index */) const 40 | { 41 | editor->setGeometry(option.rect); 42 | } 43 | 44 | //////////////////////////////////////////////////////////////////////////////// 45 | StratPosModel::StratPosModel(vector& position, QObject *parent) 46 | : QAbstractItemModel(parent) 47 | { 48 | for (size_t i = 0; i < position.size(); i++) { 49 | itemsList.append(position[i]); 50 | } 51 | 52 | headerLabels << tr("Instrument"); 53 | headerLabels << tr("Quantity"); 54 | headerLabels << tr("Price"); 55 | } 56 | 57 | StratPosModel::~StratPosModel() 58 | { 59 | } 60 | 61 | QModelIndex StratPosModel::index(int row, int column, const QModelIndex &parent) const 62 | { 63 | if (!hasIndex(row, column, parent)) return QModelIndex(); 64 | return createIndex(row, column); 65 | } 66 | 67 | QModelIndex StratPosModel::parent(const QModelIndex &index) const 68 | { 69 | return QModelIndex(); 70 | } 71 | 72 | QVariant StratPosModel::data(const QModelIndex &index, int role) const 73 | { 74 | int currentRow = itemsList.size() - index.row() - 1; 75 | if (currentRow < 0 || currentRow >= itemsList.size()) 76 | return QVariant(); 77 | 78 | if (role != Qt::DisplayRole && 79 | role != Qt::ToolTipRole && 80 | role != Qt::EditRole && 81 | role != Qt::ForegroundRole && 82 | role != Qt::BackgroundRole && 83 | role != Qt::TextAlignmentRole) { 84 | return QVariant(); 85 | } 86 | 87 | int indexColumn = index.column(); 88 | int indexRow = index.row(); 89 | 90 | if (role == Qt::TextAlignmentRole) { 91 | return Qt::AlignLeft | Qt::AlignVCenter; 92 | } 93 | 94 | if (role == Qt::BackgroundRole) { 95 | if (!(indexRow % 2)) { 96 | return appGlobalData.appTheme.altRowColor; 97 | } else { 98 | return QVariant(); 99 | } 100 | } 101 | 102 | if (role == Qt::DisplayRole || role == Qt::EditRole) { 103 | if (indexRow < itemsList.size()) { 104 | const StrategyPosition& item = itemsList[indexRow]; 105 | switch (indexColumn) { 106 | case 0: 107 | return item.instrument; 108 | case 1: 109 | return item.quantity; 110 | case 2: 111 | return item.avgPx; 112 | } 113 | } 114 | } 115 | 116 | return QVariant(); 117 | } 118 | 119 | bool StratPosModel::setData(const QModelIndex &index, const QVariant &value, int role) 120 | { 121 | if (role != Qt::EditRole) { 122 | return false; 123 | } 124 | 125 | int indexColumn = index.column(); 126 | int indexRow = index.row(); 127 | if (indexRow >= itemsList.size()) { 128 | return false; 129 | } 130 | 131 | if (indexColumn == 0) { 132 | strncpy(itemsList[indexRow].instrument, value.toString().toStdString().c_str(), sizeof(itemsList[indexRow].instrument)); 133 | } else if (indexColumn == 1) { 134 | itemsList[indexRow].quantity = value.toInt(); 135 | } else if (indexColumn == 2) { 136 | itemsList[indexRow].avgPx = value.toDouble(); 137 | } 138 | 139 | return true; 140 | } 141 | 142 | Qt::ItemFlags StratPosModel::flags(const QModelIndex &index) const 143 | { 144 | if (index.column() == 0) { 145 | int row = index.row(); 146 | if (row < itemsList.count()) { 147 | if (string(DefaultInstrumentName) == itemsList[row].instrument) { 148 | return Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsEditable; 149 | } else { 150 | return Qt::ItemIsSelectable | Qt::ItemIsEnabled; 151 | } 152 | } 153 | } else { 154 | return Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsEditable; 155 | } 156 | 157 | return Qt::ItemIsSelectable | Qt::ItemIsEnabled; 158 | } 159 | 160 | QVariant StratPosModel::headerData(int section, Qt::Orientation orientation, int role) const 161 | { 162 | if (orientation != Qt::Horizontal) return QVariant(); 163 | 164 | if (role != Qt::DisplayRole) return QVariant(); 165 | if (section >= headerLabels.count()) return QVariant(); 166 | 167 | return headerLabels.at(section); 168 | } 169 | 170 | int StratPosModel::rowCount(const QModelIndex &parent) const 171 | { 172 | return itemsList.size(); 173 | } 174 | 175 | int StratPosModel::columnCount(const QModelIndex &parent) const 176 | { 177 | return headerLabels.count(); 178 | } 179 | 180 | void StratPosModel::insertNewRow() 181 | { 182 | for (size_t i = 0; i < itemsList.size(); i++) { 183 | if (string("instrument") == itemsList[i].instrument) { 184 | return; 185 | } 186 | } 187 | 188 | int currentIndex = itemsList.size(); 189 | beginInsertRows(QModelIndex(), currentIndex, currentIndex); 190 | StrategyPosition pos = { 0 }; 191 | strcpy(pos.instrument, DefaultInstrumentName); 192 | itemsList.push_back(pos); 193 | endInsertRows(); 194 | } 195 | 196 | void StratPosModel::removeRow(int row) 197 | { 198 | if (row < 0 || row >= itemsList.size()) { 199 | return; 200 | } 201 | 202 | beginRemoveRows(QModelIndex(), row, row); 203 | itemsList.removeAt(row); 204 | endRemoveRows(); 205 | } 206 | 207 | QList& StratPosModel::getAllPositions() 208 | { 209 | return itemsList; 210 | } -------------------------------------------------------------------------------- /Src/stratposmodel.h: -------------------------------------------------------------------------------- 1 | #ifndef STRATEGY_POS_MODEL_H 2 | #define STRATEGY_POS_MODEL_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include "Defines.h" 8 | 9 | using std::vector; 10 | 11 | using namespace AlgoSE; 12 | 13 | #define DefaultInstrumentName "instrument" 14 | 15 | class StratPosDelegate : public QStyledItemDelegate 16 | { 17 | Q_OBJECT 18 | 19 | public: 20 | StratPosDelegate(QObject *parent = 0); 21 | 22 | QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, 23 | const QModelIndex &index) const; 24 | 25 | void setEditorData(QWidget *editor, const QModelIndex &index) const; 26 | void setModelData(QWidget *editor, QAbstractItemModel *model, 27 | const QModelIndex &index) const; 28 | 29 | void updateEditorGeometry(QWidget *editor, 30 | const QStyleOptionViewItem &option, const QModelIndex &index) const; 31 | }; 32 | 33 | class StratPosModel : public QAbstractItemModel 34 | { 35 | Q_OBJECT 36 | 37 | public: 38 | StratPosModel(vector& position, QObject *parent = 0); 39 | ~StratPosModel(); 40 | 41 | QList& getAllPositions(); 42 | 43 | QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const; 44 | QModelIndex parent(const QModelIndex &index) const; 45 | 46 | QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; 47 | bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole); 48 | Qt::ItemFlags flags(const QModelIndex &index) const; 49 | QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; 50 | 51 | int rowCount(const QModelIndex &parent = QModelIndex()) const; 52 | int columnCount(const QModelIndex &parent = QModelIndex()) const; 53 | 54 | void insertNewRow(); 55 | void removeRow(int row); 56 | 57 | private: 58 | QStringList headerLabels; 59 | QList itemsList; 60 | }; 61 | 62 | #endif // STRATEGY_POS_MODEL_H -------------------------------------------------------------------------------- /Src/subscribedialog.cpp: -------------------------------------------------------------------------------- 1 | #include "subscribedialog.h" 2 | 3 | SubscribeDialog::SubscribeDialog(QWidget* parent) 4 | : QDialog(parent) 5 | { 6 | ui.setupUi(this); 7 | connect(ui.okBtn, SIGNAL(clicked()), this, SLOT(buttonOkClicked())); 8 | connect(ui.cancelBtn, SIGNAL(clicked()), this, SLOT(buttonCancelClicked())); 9 | } 10 | 11 | SubscribeDialog::~SubscribeDialog() 12 | { 13 | } 14 | 15 | QString SubscribeDialog::getInstrument() const 16 | { 17 | return ui.instrument->text(); 18 | } 19 | 20 | void SubscribeDialog::setInstrument(const QString& text) 21 | { 22 | ui.instrument->setText(text); 23 | } 24 | 25 | void SubscribeDialog::buttonOkClicked() 26 | { 27 | QDialog::accept(); 28 | } 29 | 30 | void SubscribeDialog::buttonCancelClicked() 31 | { 32 | QDialog::reject(); 33 | } 34 | -------------------------------------------------------------------------------- /Src/subscribedialog.h: -------------------------------------------------------------------------------- 1 | #ifndef SUBSCRIBE_DIALOG_H 2 | #define SUBSCRIBE_DIALOG_H 3 | 4 | #include 5 | #include "ui_subscribedialog.h" 6 | 7 | class SubscribeDialog : public QDialog 8 | { 9 | Q_OBJECT 10 | 11 | public: 12 | SubscribeDialog(char initKey, QWidget* parent = 0); 13 | SubscribeDialog(QWidget* parent = 0); 14 | ~SubscribeDialog(); 15 | QString getInstrument() const; 16 | void setInstrument(const QString& text); 17 | 18 | private: 19 | Ui::SubscribeDlg ui; 20 | 21 | private slots: 22 | void buttonOkClicked(); 23 | void buttonCancelClicked(); 24 | }; 25 | 26 | #endif // SUBSCRIBE_DIALOG_H -------------------------------------------------------------------------------- /Src/subscribedialog.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | SubscribeDlg 4 | 5 | 6 | 7 | 0 8 | 0 9 | 433 10 | 82 11 | 12 | 13 | 14 | 15 | 433 16 | 82 17 | 18 | 19 | 20 | Subscribe 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | Instrument: 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | Qt::Horizontal 43 | 44 | 45 | 46 | 40 47 | 20 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | Ok 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 0 64 | 0 65 | 66 | 67 | 68 | Cancel 69 | 70 | 71 | 72 | 73 | 74 | 75 | Qt::Horizontal 76 | 77 | 78 | 79 | 40 80 | 20 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /Src/tradepanel.cpp: -------------------------------------------------------------------------------- 1 | #include "tradepanel.h" 2 | 3 | TradePanel::TradePanel(AlgoSE::Engine* engine, QWidget* parent) 4 | : QDialog(parent) 5 | { 6 | pAlogSE = engine; 7 | pMktDataApi = pAlogSE->getMarketDataAPI(); 8 | pTradingApi = pAlogSE->getTradingAPI(); 9 | 10 | ui.setupUi(this); 11 | 12 | QObject::connect(ui.qtySpinBox, SIGNAL(valueChanged(int)), this, SLOT(posQtyValueChanged(int))); 13 | QObject::connect(ui.pxTypeBtn, SIGNAL(clicked()), this, SLOT(pxTypeBtnClicked())); 14 | QObject::connect(ui.askBtn, SIGNAL(clicked()), this, SLOT(askBtnClicked())); 15 | QObject::connect(ui.bidBtn, SIGNAL(clicked()), this, SLOT(bidBtnClicked())); 16 | QObject::connect(ui.lastBtn, SIGNAL(clicked()), this, SLOT(lastBtnClicked())); 17 | QObject::connect(ui.upperBtn, SIGNAL(clicked()), this, SLOT(upperBtnClicked())); 18 | QObject::connect(ui.lowerBtn, SIGNAL(clicked()), this, SLOT(lowerBtnClicked())); 19 | QObject::connect(ui.buyBtn, SIGNAL(clicked()), this, SLOT(buyBtnClicked())); 20 | QObject::connect(ui.shortBtn, SIGNAL(clicked()), this, SLOT(shortBtnClicked())); 21 | QObject::connect(ui.closeBtn, SIGNAL(clicked()), this, SLOT(closeBtnClicked())); 22 | 23 | pxType = PX_TYPE_LIMIT; 24 | openVol = 1; 25 | closeVol = 0; 26 | } 27 | 28 | TradePanel::~TradePanel() 29 | { 30 | } 31 | 32 | void TradePanel::setPosition(const char* instrument, int side, int quantity) 33 | { 34 | if (instrument == nullptr) { 35 | return; 36 | } 37 | 38 | posSide = side; 39 | closeVol = quantity; 40 | 41 | if (instrument[0] == '\0') { 42 | this->instrument = ""; 43 | lastPx = 0; 44 | } else { 45 | this->instrument = instrument; 46 | lastPx = pMktDataApi->getLastPrice(instrument); 47 | ui.symbolLineEdit->setText(instrument); 48 | ui.askBtn->setText(QString().number(pMktDataApi->getAskPrice(instrument))); 49 | ui.bidBtn->setText(QString().number(pMktDataApi->getBidPrice(instrument))); 50 | ui.lastBtn->setText(QString().number(pMktDataApi->getLastPrice(instrument))); 51 | ui.upperBtn->setText(QString().number(pMktDataApi->getUpperLimitPrice(instrument))); 52 | ui.lowerBtn->setText(QString().number(pMktDataApi->getLowerLimitPrice(instrument))); 53 | } 54 | 55 | double tickSize = pMktDataApi->getTickSize(instrument); 56 | if (tickSize == 0) { 57 | tickSize = 1.0; 58 | } 59 | 60 | ui.qtySpinBox->setValue(quantity); 61 | ui.priceSpinBox->setSingleStep(tickSize); 62 | ui.priceSpinBox->setValue(lastPx); 63 | 64 | ui.buyBtn->setText(tr("Buy(") + QString().number(quantity) + ")"); 65 | ui.shortBtn->setText(tr("Short(") + QString().number(quantity) + ")"); 66 | if (quantity > 0) { 67 | if (side == AlgoSE::PositionSide::POSITION_SIDE_LONG) { 68 | ui.closeBtn->setText(tr("Sell(") + QString().number(quantity) + ")"); 69 | } else if (side == AlgoSE::PositionSide::POSITION_SIDE_SHORT) { 70 | ui.closeBtn->setText(tr("Cover(") + QString().number(quantity) + ")"); 71 | } 72 | } else { 73 | ui.closeBtn->setText(tr("Close(0)")); 74 | } 75 | 76 | ui.pxTypeBtn->setText(tr("LIMIT")); 77 | ui.priceSpinBox->setValue(lastPx); 78 | } 79 | 80 | void TradePanel::updateMarketData(const AlgoSE::Tick& tick) 81 | { 82 | if (instrument != tick.instrument) { 83 | return; 84 | } 85 | 86 | askPx = tick.askPrice1; 87 | askVol = tick.askVolume1; 88 | bidPx = tick.bidPrice1; 89 | bidVol = tick.bidVolume1; 90 | upperLimit = tick.upperLimitPrice; 91 | lowerLimit = tick.lowerLimitPrice; 92 | 93 | ui.askBtn->setText(QString().number(tick.askPrice1)); 94 | ui.bidBtn->setText(QString().number(tick.bidPrice1)); 95 | ui.lastBtn->setText(QString().number(tick.lastPrice)); 96 | ui.upperBtn->setText(QString().number(tick.upperLimitPrice)); 97 | ui.lowerBtn->setText(QString().number(tick.lowerLimitPrice)); 98 | } 99 | 100 | void TradePanel::updatePxType(int type) 101 | { 102 | pxType = type; 103 | 104 | if (pxType == PX_TYPE_LIMIT) { 105 | ui.pxTypeBtn->setText(tr("LIMIT")); 106 | ui.priceSpinBox->setEnabled(true); 107 | } else if (pxType == PX_TYPE_MARKET) { 108 | ui.pxTypeBtn->setText(tr("MARKET")); 109 | ui.priceSpinBox->cleanText(); 110 | ui.priceSpinBox->setDisabled(true); 111 | } else if (pxType == PX_TYPE_OPPOSITE) { 112 | ui.pxTypeBtn->setText(tr("OPPOSITE")); 113 | ui.priceSpinBox->cleanText(); 114 | ui.priceSpinBox->setDisabled(true); 115 | } 116 | } 117 | 118 | void TradePanel::askBtnClicked() 119 | { 120 | ui.priceSpinBox->setValue(askPx); 121 | updatePxType(PX_TYPE_LIMIT); 122 | } 123 | 124 | void TradePanel::bidBtnClicked() 125 | { 126 | ui.priceSpinBox->setValue(bidPx); 127 | updatePxType(PX_TYPE_LIMIT); 128 | } 129 | 130 | void TradePanel::lastBtnClicked() 131 | { 132 | ui.priceSpinBox->setValue(lastPx); 133 | updatePxType(PX_TYPE_LIMIT); 134 | } 135 | 136 | void TradePanel::upperBtnClicked() 137 | { 138 | ui.priceSpinBox->setValue(upperLimit); 139 | updatePxType(PX_TYPE_LIMIT); 140 | } 141 | 142 | void TradePanel::lowerBtnClicked() 143 | { 144 | ui.priceSpinBox->setValue(lowerLimit); 145 | updatePxType(PX_TYPE_LIMIT); 146 | } 147 | 148 | void TradePanel::buyBtnClicked() 149 | { 150 | double qty = ui.qtySpinBox->value(); 151 | double price = ui.priceSpinBox->value(); 152 | 153 | if (pxType == PX_TYPE_LIMIT) { 154 | pTradingApi->buy(instrument.c_str(), qty, price, nullptr, 0); 155 | } else if (pxType == PX_TYPE_OPPOSITE) { 156 | price = pMktDataApi->getAskPrice(instrument.c_str()); 157 | pTradingApi->buy(instrument.c_str(), qty, price, nullptr, 0); 158 | } 159 | } 160 | 161 | void TradePanel::shortBtnClicked() 162 | { 163 | double qty = ui.qtySpinBox->value(); 164 | double price = ui.priceSpinBox->value(); 165 | 166 | if (pxType == PX_TYPE_LIMIT) { 167 | pTradingApi->sellShort(instrument.c_str(), qty, price, nullptr, 0); 168 | } else if (pxType == PX_TYPE_OPPOSITE) { 169 | price = pMktDataApi->getBidPrice(instrument.c_str()); 170 | pTradingApi->sellShort(instrument.c_str(), qty, price, nullptr, 0); 171 | } 172 | } 173 | 174 | void TradePanel::closeBtnClicked() 175 | { 176 | if (closeVol > 0) { 177 | double price = ui.priceSpinBox->value(); 178 | double qty = ui.qtySpinBox->value(); 179 | if (qty <= 0 || qty > closeVol) { 180 | return; 181 | } 182 | 183 | if (posSide == AlgoSE::PositionSide::POSITION_SIDE_LONG) { 184 | if (pxType == PX_TYPE_LIMIT) { 185 | pTradingApi->sell(instrument.c_str(), qty, price, nullptr, 0); 186 | } else if (pxType == PX_TYPE_OPPOSITE) { 187 | price = pMktDataApi->getBidPrice(instrument.c_str()); 188 | pTradingApi->sell(instrument.c_str(), qty, price, nullptr, 0); 189 | } 190 | } else if (posSide == AlgoSE::PositionSide::POSITION_SIDE_SHORT) { 191 | if (pxType == PX_TYPE_LIMIT) { 192 | pTradingApi->buyToCover(instrument.c_str(), qty, price, nullptr, 0); 193 | } else if (pxType == PX_TYPE_OPPOSITE) { 194 | price = pMktDataApi->getAskPrice(instrument.c_str()); 195 | pTradingApi->buyToCover(instrument.c_str(), qty, price, nullptr, 0); 196 | } 197 | } 198 | } 199 | } 200 | 201 | void TradePanel::posQtyValueChanged(int qty) 202 | { 203 | ui.buyBtn->setText(tr("Buy(") + QString().number(qty) + ")"); 204 | ui.shortBtn->setText(tr("Short(") + QString().number(qty) + ")"); 205 | if (qty <= closeVol) { 206 | if (posSide == AlgoSE::PositionSide::POSITION_SIDE_LONG) { 207 | ui.closeBtn->setText(tr("Sell(") + QString().number(qty) + ")"); 208 | } else if (posSide == AlgoSE::PositionSide::POSITION_SIDE_SHORT) { 209 | ui.closeBtn->setText(tr("Cover(") + QString().number(qty) + ")"); 210 | } 211 | } 212 | } 213 | 214 | void TradePanel::pxTypeBtnClicked() 215 | { 216 | pxType++; 217 | if (pxType > PX_TYPE_OPPOSITE) { 218 | pxType = PX_TYPE_LIMIT; 219 | } 220 | 221 | updatePxType(pxType); 222 | } -------------------------------------------------------------------------------- /Src/tradepanel.h: -------------------------------------------------------------------------------- 1 | #ifndef TRADE_PANEL_H 2 | #define TRADE_PANEL_H 3 | 4 | #include 5 | #include 6 | #include "Defines.h" 7 | #include "Engine.h" 8 | #include "ui_tradepanel.h" 9 | 10 | class TradePanel : public QDialog 11 | { 12 | Q_OBJECT 13 | 14 | public: 15 | TradePanel(AlgoSE::Engine* engine, QWidget* parent = 0); 16 | ~TradePanel(); 17 | void setPosition(const char* instrument, int side, int quantity); 18 | void updateMarketData(const AlgoSE::Tick& tick); 19 | 20 | private slots: 21 | void posQtyValueChanged(int); 22 | void pxTypeBtnClicked(); 23 | void askBtnClicked(); 24 | void bidBtnClicked(); 25 | void lastBtnClicked(); 26 | void upperBtnClicked(); 27 | void lowerBtnClicked(); 28 | void buyBtnClicked(); 29 | void shortBtnClicked(); 30 | void closeBtnClicked(); 31 | 32 | private: 33 | void updatePxType(int type); 34 | 35 | private: 36 | Ui::TradePanel ui; 37 | 38 | AlgoSE::Engine* pAlogSE; 39 | AlgoSE::IEngine::MarketDataAPI* pMktDataApi; 40 | AlgoSE::IEngine::TradingAPI* pTradingApi; 41 | 42 | enum { 43 | PX_TYPE_LIMIT = 0, 44 | PX_TYPE_MARKET, 45 | PX_TYPE_OPPOSITE, 46 | }; 47 | 48 | std::string instrument; 49 | int pxType; 50 | int posSide; 51 | int openVol; 52 | int closeVol; 53 | double priceUnit; 54 | double lastPx; 55 | double askPx; 56 | unsigned long askVol; 57 | double bidPx; 58 | unsigned long bidVol; 59 | double upperLimit; 60 | double lowerLimit; 61 | }; 62 | 63 | #endif // TRADE_PANEL_H -------------------------------------------------------------------------------- /Src/warning.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/algosenses/PowerGate/7996dec6889ce59f5dc1c145aebd61b7ab28f031/Src/warning.wav --------------------------------------------------------------------------------