forked from zhenyong97/trade_tool
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathGUI_QuantTradeSys.py
278 lines (215 loc) · 11.9 KB
/
GUI_QuantTradeSys.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
# !/usr/bin/python
# -*- coding:utf-8 -*-
"""
界面交互:按键事件、切换页面等
"""
import wx
from wx.adv import DatePickerCtrl, DP_DROPDOWN, DP_SHOWCENTURY, DP_ALLOWNONE
import numpy as np
import matplotlib.pyplot as plt
import datetime
from project.RedefPanelMod import MPL_Panel_Base, Loop_Panel_Base
from project.StockDataMod import GetStockDatPro, format_code_name
from project.IndicatStarteMod import Excave_Indic_Base, QuantPickTimeSys
plt.rcParams['font.sans-serif'] = ['SimHei'] # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False # 用来正常显示负号
class Frame(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, parent=None, title='量化软件', size=(1100, 700))
# 创建显示区面板
self.DispPanel = MPL_Panel_Base(self) # 展示
self.BackPanel = Loop_Panel_Base(self) # 回测
self.am = self.DispPanel.am
self.vol = self.DispPanel.vol
self.devol = self.DispPanel.devol
self.macd = self.DispPanel.macd
# 创建参数区面板
self.ParaPanel = wx.Panel(self, -1)
paraInput_Box = wx.StaticBox(self.ParaPanel, -1, '参数输入')
paraInput_Sizer = wx.StaticBoxSizer(paraInput_Box, wx.VERTICAL)
self.StNameCodedict = {"开山股份": "300257", "浙大网新": "600797", "水晶光电": "002273", "高鸿股份": "000851"}
# 初始化股票代码变量
self.stockName_Val = "开山股份"
self.stockCode_Val = self.StNameCodedict[self.stockName_Val]
self.stockName_CMBO = wx.ComboBox(self.ParaPanel, -1, self.stockName_Val,
choices=list(self.StNameCodedict.keys()),
style=wx.CB_READONLY | wx.CB_DROPDOWN) # 股票名称
stockCode_Text = wx.StaticText(self.ParaPanel, -1, '股票名称')
# 策略选取
strate_Text = wx.StaticText(self.ParaPanel, -1, '策略名称')
strate_Combo_Val = ["双趋势融合", "待添加策略"] # 策略
self.pickstrate_Val = "双趋势融合"
self.pickstrate_CMBO = wx.ComboBox(self.ParaPanel, -1, self.pickstrate_Val, choices=strate_Combo_Val,
style=wx.CB_READONLY | wx.CB_DROPDOWN) # 策略名称
# 日历控件选择数据周期
self.dpcEndTime = DatePickerCtrl(self.ParaPanel, -1, style=DP_DROPDOWN | DP_SHOWCENTURY | DP_ALLOWNONE) # 结束时间
self.dpcStartTime = DatePickerCtrl(self.ParaPanel, -1, style=DP_DROPDOWN | DP_SHOWCENTURY | DP_ALLOWNONE) # 起始时间
DateTimeNow = wx.DateTime.Now() # wx.DateTime格式"03/03/18 00:00:00"
self.dpcEndTime.SetValue(DateTimeNow)
DateTimeNow.SetYear(DateTimeNow.year - 1)
self.dpcStartTime.SetValue(DateTimeNow)
stockData_Text = wx.StaticText(self.ParaPanel, -1, '日期(Start-End)')
# 初始化时间变量
# print('start----------')
dateVal = self.dpcStartTime.GetValue()
# print("dateVal ---> ", dateVal)
# print("dateVal.year ----->", dateVal.year)
# print("dateVal.month ---->", dateVal.month)
# print("dateVal.day ----->", dateVal.day)
self.stockSdate_Val = datetime.datetime(dateVal.year, dateVal.month + 1, dateVal.day)
# print('self.stockSdate_Val----->', self.stockSdate_Val)
dateVal = self.dpcEndTime.GetValue()
# print("dateVal ---> ", dateVal)
self.stockEdate_Val = datetime.datetime(dateVal.year, dateVal.month + 1, dateVal.day)
# print('self.stockEdate_Val ------>', self.stockEdate_Val)
# print('end----------')
paraInput_Sizer.Add(stockCode_Text, proportion=0, flag=wx.EXPAND | wx.ALL, border=2)
paraInput_Sizer.Add(self.stockName_CMBO, 0, wx.EXPAND | wx.ALL | wx.CENTER, 2)
paraInput_Sizer.Add(stockData_Text, proportion=0, flag=wx.EXPAND | wx.ALL, border=2)
paraInput_Sizer.Add(self.dpcStartTime, 0, wx.EXPAND | wx.ALL | wx.CENTER, 2)
paraInput_Sizer.Add(self.dpcEndTime, 0, wx.EXPAND | wx.ALL | wx.CENTER, 2)
paraInput_Sizer.Add(strate_Text, 0, wx.EXPAND | wx.ALL | wx.CENTER, 2)
paraInput_Sizer.Add(self.pickstrate_CMBO, 0, wx.EXPAND | wx.ALL | wx.CENTER, 2)
RadioList = ["不显示", "跳空缺口", "金叉/死叉", "N日突破"]
self.StratInputBox = wx.RadioBox(self.ParaPanel, -1, label='指标提示', choices=RadioList, majorDimension=4,
style=wx.RA_SPECIFY_ROWS)
self.StratInputBox.Bind(wx.EVT_RADIOBOX, self.OnRadioBox_Indicator)
# 初始化指标变量
self.IndicatInput_Val = self.StratInputBox.GetStringSelection()
self.TextAInput = wx.TextCtrl(self.ParaPanel, -1, "交易信息提示:", size=(180, 200),style=wx.TE_MULTILINE | wx.TE_READONLY) # 多行|只读
vboxnetA = wx.BoxSizer(wx.VERTICAL) # 纵向box
vboxnetA.Add(paraInput_Sizer, proportion=0, flag=wx.EXPAND | wx.BOTTOM, border=2) # proportion参数控制容器尺寸比例
vboxnetA.Add(self.StratInputBox, proportion=0, flag=wx.EXPAND | wx.BOTTOM, border=2)
vboxnetA.Add(self.TextAInput, proportion=1, flag=wx.EXPAND | wx.ALL, border=2)
self.ParaPanel.SetSizer(vboxnetA)
# 创建Right面板
self.CtrlPanel = wx.Panel(self, -1)
# 创建FlexGridSizer布局网格
self.FlexGridSizer = wx.FlexGridSizer(rows=3, cols=1, vgap=3, hgap=3)
# 行情按钮
self.Firmoffer = wx.Button(self.CtrlPanel, -1, "行情")
self.Firmoffer.Bind(wx.EVT_BUTTON, self.FirmEvent) # 绑定行情按钮事件
# 回测按钮
self.Backtrace = wx.Button(self.CtrlPanel, -1, "回测")
self.Backtrace.Bind(wx.EVT_BUTTON, self.BackEvent) # 绑定回测按钮事件
# 选股按钮
self.Stockpick = wx.Button(self.CtrlPanel, -1, "选股")
self.Stockpick.Bind(wx.EVT_BUTTON, self.PstockpEvent) # 绑定选股按钮事件
# 加入Sizer中
self.FlexGridSizer.Add(self.Firmoffer, proportion=1, border=5, flag=wx.ALL | wx.EXPAND)
self.FlexGridSizer.Add(self.Backtrace, proportion=1, border=5, flag=wx.ALL | wx.EXPAND)
self.FlexGridSizer.Add(self.Stockpick, proportion=1, border=5, flag=wx.ALL | wx.EXPAND)
self.FlexGridSizer.SetFlexibleDirection(wx.BOTH)
self.CtrlPanel.SetSizer(self.FlexGridSizer)
self.HBoxPanel = wx.BoxSizer()
self.HBoxPanel.Add(self.ParaPanel, proportion=1.5, border=2, flag=wx.EXPAND | wx.ALL)
self.HBoxPanel.Add(self.DispPanel, proportion=8, border=2, flag=wx.EXPAND | wx.ALL)
self.HBoxPanel.Add(self.CtrlPanel, proportion=1, border=2, flag=wx.EXPAND | wx.ALL)
self.SetSizer(self.HBoxPanel)
self.Centre()
def ProcessStock(self):
# df_stockload = web.DataReader("600797.SS", "yahoo", datetime.datetime(2017,1,1), datetime.date.today())
df_stockload = GetStockDatPro(self.stockCode_Val, self.stockSdate_Val, self.stockEdate_Val)
""" 绘制移动平均线图 """
# self.am.plot(self.numic[0:self.butNum],self.close[0:self.butNum],'#0f0ff0',linewidth=1.0)
dispCont_List = []
examp_trade = Excave_Indic_Base()
if self.IndicatInput_Val == "金叉/死叉":
dispCont_pd, dispCont_List = examp_trade.plot_Aver_Cross(df_stockload)
self.DispPanel.draw_avercross(df_stockload, dispCont_pd)
elif self.IndicatInput_Val == "跳空缺口":
dispCont_pd, dispCont_List = examp_trade.plot_Jump_Thrd(df_stockload)
self.DispPanel.draw_jumpgap(df_stockload, dispCont_pd)
elif self.IndicatInput_Val == "N日突破":
dispCont_pd, dispCont_List = examp_trade.plot_Ndays_Break(df_stockload)
self.DispPanel.draw_ndaysbreak(df_stockload, dispCont_pd)
else:
dispCont_List = dispCont_List
self.TextAInput.SetValue("指标提示信息如下:" + '\n')
for i in dispCont_List: self.TextAInput.AppendText(i)
numic = np.arange(0, len(df_stockload.index))
butNum = len(df_stockload.index)
self.DispPanel.xylabel_tick_lim(self.stockName_Val, df_stockload.index)
self.DispPanel.draw_subgraph(df_stockload, numic)
def ProcessLoop(self):
df_stockload = GetStockDatPro(self.stockCode_Val, self.stockSdate_Val, self.stockEdate_Val)
dispCont_List = []
if self.pickstrate_Val == "双趋势融合":
# 多趋势融合策略执行 """
examp_trade = QuantPickTimeSys(df_stockload)
dispCont_List = examp_trade.run_factor_plot(self.BackPanel.trade, self.BackPanel.total,
self.BackPanel.profit)
else:
# 执行其他策略
# 扩展其他策略
pass
self.TextAInput.SetValue(u"策略提示信息如下:" + '\n')
for i in dispCont_List: self.TextAInput.AppendText(i)
self.BackPanel.xylabel_tick_lim(self.stockName_Val)
def reFlashLoop(self):
self.BackPanel.clear_subgraph() # 必须清理图形才能显示下一幅图
self.ProcessLoop()
self.BackPanel.update_subgraph() # 必须刷新才能显示下一幅图
def reFlashFrame(self):
self.DispPanel.clear_subgraph() # 必须清理图形才能显示下一幅图
self.ProcessStock()
self.DispPanel.update_subgraph() # 必须刷新才能显示下一幅图
def FirmEvent(self, event):
# 显示行情面板
self.HBoxPanel.Hide(self.BackPanel)
self.HBoxPanel.Replace(self.BackPanel, self.DispPanel)
self.HBoxPanel.Show(self.DispPanel)
# self.HBoxPanel.Remove(self.BackPanel)
self.SetSizer(self.HBoxPanel)
self.HBoxPanel.Layout()
# 获取列表股票代码和起始时间
self.stockName_Val = self.stockName_CMBO.GetString(self.stockName_CMBO.GetSelection())
self.stockCode_Val = self.StNameCodedict[self.stockName_Val]
dateVal = self.dpcStartTime.GetValue()
# print('------------')
# print('dateVal:', dateVal, type(dateVal))
# print('dateVal.Year:', dateVal.Year, type(dateVal.Year))
self.stockSdate_Val = datetime.datetime(dateVal.year, dateVal.month + 1, dateVal.day)
dateVal = self.dpcEndTime.GetValue()
self.stockEdate_Val = datetime.datetime(dateVal.year, dateVal.month + 1, dateVal.day)
self.reFlashFrame()
def BackEvent(self, event):
# 显示回测面板
self.HBoxPanel.Hide(self.DispPanel)
self.HBoxPanel.Replace(self.DispPanel, self.BackPanel)
self.HBoxPanel.Show(self.BackPanel)
# self.HBoxPanel.Remove(self.DispPanel)
self.SetSizer(self.HBoxPanel)
self.HBoxPanel.Layout()
# 获取策略名称
self.pickstrate_Val = self.pickstrate_CMBO.GetString(self.pickstrate_CMBO.GetSelection())
self.reFlashLoop()
def PstockpEvent(self,event):
"""选股事件触发"""
dlg = wx.TextEntryDialog(self, '输入需要查询的股票代码', '自选窗')
if dlg.ShowModal() == wx.ID_OK:
# 获取代码编号
code = dlg.GetValue()
# 获取名称
stockName = format_code_name(code)
print('股票名称为', stockName)
self.StNameCodedict[stockName] = dlg.GetValue()
self.stockName_CMBO.Append(stockName) # 添加数据
self.stockName_CMBO.Update()
self.stockName_CMBO.Refresh()
self.ParaPanel.Update()
# print("股票池:", self.StNameCodedict)
dlg.Destroy()
# print('销毁对话')
def OnRadioBox_Indicator(self, event):
self.IndicatInput_Val = self.StratInputBox.GetStringSelection()
class App(wx.App):
def OnInit(self):
self.frame = Frame()
self.frame.ProcessStock()
self.frame.Show()
self.SetTopWindow(self.frame)
return True
if __name__ == '__main__':
app = App()
app.MainLoop()