5
5
import tempfile
6
6
import time
7
7
import traceback
8
- import pyperclip
9
8
import win32api
10
- import win32clipboard as cp
11
9
import win32gui
12
10
from io import StringIO
13
11
14
12
import pandas as pd
13
+ import pyperclip
15
14
import win32com .client
16
15
import win32con
17
16
from PIL import ImageGrab
@@ -24,7 +23,22 @@ class YHClientTrader():
24
23
def __init__ (self ):
25
24
self .Title = '网上股票交易系统5.0'
26
25
27
- def login (self , user , password , exe_path = 'C:\中国银河证券双子星3.2\Binarystar.exe' ):
26
+ def prepare (self , config_path = None , user = None , password = None , exe_path = 'C:\中国银河证券双子星3.2\Binarystar.exe' ):
27
+ """
28
+ 登陆银河客户端
29
+ :param config_path: 银河登陆配置文件,跟参数登陆方式二选一
30
+ :param user: 银河账号
31
+ :param password: 银河明文密码
32
+ :param exe_path: 银河客户端路径
33
+ :return:
34
+ """
35
+ if config_path is not None :
36
+ account = helpers .file2dict (config_path )
37
+ user = account ['user' ]
38
+ password = account ['password' ]
39
+ self .login (user , password , exe_path )
40
+
41
+ def login (self , user , password , exe_path ):
28
42
if self ._has_main_window ():
29
43
self ._get_handles ()
30
44
log .info ('检测到交易客户端已启动,连接完毕' )
@@ -46,15 +60,15 @@ def login(self, user, password, exe_path='C:\中国银河证券双子星3.2\Bina
46
60
self ._set_trade_mode ()
47
61
self ._set_login_name (user )
48
62
self ._set_login_password (password )
49
- for _ in range (3 ):
63
+ for _ in range (10 ):
50
64
self ._set_login_verify_code ()
51
65
self ._click_login_button ()
52
66
time .sleep (3 )
53
67
if not self ._has_login_window ():
54
68
break
55
69
self ._click_login_verify_code ()
56
70
57
- for _ in range (30 ):
71
+ for _ in range (60 ):
58
72
if self ._has_main_window ():
59
73
self ._get_handles ()
60
74
break
@@ -64,7 +78,7 @@ def login(self, user, password, exe_path='C:\中国银河证券双子星3.2\Bina
64
78
log .info ('客户端登陆成功' )
65
79
66
80
def _set_login_verify_code (self ):
67
- verify_code_image = self ._get_verify_code ()
81
+ verify_code_image = self ._grab_verify_code ()
68
82
image_path = tempfile .mktemp () + '.jpg'
69
83
verify_code_image .save (image_path )
70
84
result = helpers .recognize_verify_code (image_path , 'yh_client' )
@@ -89,7 +103,6 @@ def _set_login_password(self, password):
89
103
def _has_login_window (self ):
90
104
for title in [' - 北京电信' , ' - 北京电信 - 北京电信' ]:
91
105
self .login_hwnd = win32gui .FindWindow (None , title )
92
- log .debug ('检测到登陆窗口句柄:{}' .format (self .login_hwnd ))
93
106
if self .login_hwnd != 0 :
94
107
return True
95
108
return False
@@ -101,13 +114,14 @@ def _input_login_verify_code(self, code):
101
114
def _click_login_verify_code (self ):
102
115
input_hwnd = win32gui .GetDlgItem (self .login_hwnd , 0x56ba )
103
116
rect = win32gui .GetWindowRect (input_hwnd )
104
- self .click (rect [0 ] + 5 , rect [1 ] + 5 )
117
+ self ._mouse_click (rect [0 ] + 5 , rect [1 ] + 5 )
118
+
119
+ @staticmethod
120
+ def _mouse_click (x , y ):
121
+ win32api .SetCursorPos ((x , y ))
122
+ win32api .mouse_event (win32con .MOUSEEVENTF_LEFTDOWN , x , y , 0 , 0 )
123
+ win32api .mouse_event (win32con .MOUSEEVENTF_LEFTUP , x , y , 0 , 0 )
105
124
106
- def click (self , x ,y ):
107
- win32api .SetCursorPos ((x ,y ))
108
- win32api .mouse_event (win32con .MOUSEEVENTF_LEFTDOWN ,x ,y ,0 ,0 )
109
- win32api .mouse_event (win32con .MOUSEEVENTF_LEFTUP ,x ,y ,0 ,0 )
110
-
111
125
def _click_login_button (self ):
112
126
time .sleep (1 )
113
127
input_hwnd = win32gui .GetDlgItem (self .login_hwnd , 0x1 )
@@ -120,52 +134,57 @@ def _has_main_window(self):
120
134
return False
121
135
return True
122
136
123
- def _get_verify_code (self ):
137
+ def _grab_verify_code (self ):
124
138
verify_code_hwnd = win32gui .GetDlgItem (self .login_hwnd , 0x56ba )
125
- self .set_foreground_window (self .login_hwnd )
139
+ self ._set_foreground_window (self .login_hwnd )
126
140
time .sleep (1 )
127
141
rect = win32gui .GetWindowRect (verify_code_hwnd )
128
142
return ImageGrab .grab (rect )
129
143
130
144
def _get_handles (self ):
131
- Main = win32gui .FindWindow (0 , self .Title ) # 交易窗口
132
- Frame = win32gui .GetDlgItem (Main , 59648 ) # 操作窗口框架
133
- Afxwnd = win32gui .GetDlgItem (Frame , 59648 ) # 操作窗口框架
134
- Hexin = win32gui .GetDlgItem (Afxwnd , 129 )
135
- Scrolwnd = win32gui .GetDlgItem (Hexin , 200 ) # 左部折叠菜单控件
136
- treev = win32gui .GetDlgItem (Scrolwnd , 129 ) # 左部折叠菜单控件
145
+ trade_main_hwnd = win32gui .FindWindow (0 , self .Title ) # 交易窗口
146
+ operate_frame_hwnd = win32gui .GetDlgItem (trade_main_hwnd , 59648 ) # 操作窗口框架
147
+ operate_frame_afx_hwnd = win32gui .GetDlgItem (operate_frame_hwnd , 59648 ) # 操作窗口框架
148
+ hexin_hwnd = win32gui .GetDlgItem (operate_frame_afx_hwnd , 129 )
149
+ scroll_hwnd = win32gui .GetDlgItem (hexin_hwnd , 200 ) # 左部折叠菜单控件
150
+ tree_view_hwnd = win32gui .GetDlgItem (scroll_hwnd , 129 ) # 左部折叠菜单控件
137
151
138
152
# 获取委托窗口所有控件句柄
139
- win32api .PostMessage (treev , win32con .WM_KEYDOWN , win32con .VK_F1 , 0 )
153
+ win32api .PostMessage (tree_view_hwnd , win32con .WM_KEYDOWN , win32con .VK_F1 , 0 )
140
154
time .sleep (0.5 )
141
- F_Bentrust = win32gui .GetDlgItem (Frame , 59649 ) # 委托窗口框架
142
- self .E_Bsymbol = win32gui .GetDlgItem (F_Bentrust , 1032 ) # 买入代码输入框
143
- self .E_Bprice = win32gui .GetDlgItem (F_Bentrust , 1033 ) # 买入价格输入框
144
- self .E_Bvol = win32gui .GetDlgItem (F_Bentrust , 1034 ) # 买入数量输入框
145
- self .B_Buy = win32gui .GetDlgItem (F_Bentrust , 1006 ) # 买入确认按钮
146
- self .B_refresh = win32gui .GetDlgItem (F_Bentrust , 32790 ) # 刷新持仓按钮
147
- F_Bhexin = win32gui .GetDlgItem (F_Bentrust , 1047 ) # 持仓显示框架
148
- F_Bhexinsub = win32gui .GetDlgItem (F_Bhexin , 200 ) # 持仓显示框架
149
- self .G_position = win32gui .GetDlgItem (F_Bhexinsub , 1047 ) # 持仓列表
150
- win32api .PostMessage (treev , win32con .WM_KEYDOWN , win32con .VK_F2 , 0 )
155
+
156
+ # 买入相关
157
+ entrust_window_hwnd = win32gui .GetDlgItem (operate_frame_hwnd , 59649 ) # 委托窗口框架
158
+ self .buy_stock_code_hwnd = win32gui .GetDlgItem (entrust_window_hwnd , 1032 ) # 买入代码输入框
159
+ self .buy_price_hwnd = win32gui .GetDlgItem (entrust_window_hwnd , 1033 ) # 买入价格输入框
160
+ self .buy_amount_hwnd = win32gui .GetDlgItem (entrust_window_hwnd , 1034 ) # 买入数量输入框
161
+ self .buy_btn_hwnd = win32gui .GetDlgItem (entrust_window_hwnd , 1006 ) # 买入确认按钮
162
+ self .refresh_entrust_hwnd = win32gui .GetDlgItem (entrust_window_hwnd , 32790 ) # 刷新持仓按钮
163
+ entrust_frame_hwnd = win32gui .GetDlgItem (entrust_window_hwnd , 1047 ) # 持仓显示框架
164
+ entrust_sub_frame_hwnd = win32gui .GetDlgItem (entrust_frame_hwnd , 200 ) # 持仓显示框架
165
+ self .position_list_hwnd = win32gui .GetDlgItem (entrust_sub_frame_hwnd , 1047 ) # 持仓列表
166
+ win32api .PostMessage (tree_view_hwnd , win32con .WM_KEYDOWN , win32con .VK_F2 , 0 )
151
167
time .sleep (0.5 )
152
- F_Sentrust = win32gui .GetDlgItem (Frame , 59649 ) # 委托窗口框架
153
- self .E_Ssymbol = win32gui .GetDlgItem (F_Sentrust , 1032 ) # 卖出代码输入框
154
- self .E_Sprice = win32gui .GetDlgItem (F_Sentrust , 1033 ) # 卖出价格输入框
155
- self .E_Svol = win32gui .GetDlgItem (F_Sentrust , 1034 ) # 卖出数量输入框
156
- self .B_Sell = win32gui .GetDlgItem (F_Sentrust , 1006 ) # 卖出确认按钮
168
+
169
+ # 卖出相关
170
+ sell_entrust_frame_hwnd = win32gui .GetDlgItem (operate_frame_hwnd , 59649 ) # 委托窗口框架
171
+ self .sell_stock_code_hwnd = win32gui .GetDlgItem (sell_entrust_frame_hwnd , 1032 ) # 卖出代码输入框
172
+ self .sell_price_hwnd = win32gui .GetDlgItem (sell_entrust_frame_hwnd , 1033 ) # 卖出价格输入框
173
+ self .sell_amount_hwnd = win32gui .GetDlgItem (sell_entrust_frame_hwnd , 1034 ) # 卖出数量输入框
174
+ self .sell_btn_hwnd = win32gui .GetDlgItem (sell_entrust_frame_hwnd , 1006 ) # 卖出确认按钮
157
175
158
176
# 撤单窗口
159
- win32api .PostMessage (treev , win32con .WM_KEYDOWN , win32con .VK_F3 , 0 )
177
+ win32api .PostMessage (tree_view_hwnd , win32con .WM_KEYDOWN , win32con .VK_F3 , 0 )
160
178
time .sleep (0.5 )
161
- F_Centrust = win32gui .GetDlgItem (Frame , 59649 ) # 撤单窗口框架
162
- self .E_Csymbol = win32gui .GetDlgItem (F_Centrust , 3348 ) # 卖出代码输入框
163
- self .B_Csort = win32gui .GetDlgItem (F_Centrust , 3349 ) # 查询代码按钮
164
- self .B_Cbuy = win32gui .GetDlgItem (F_Centrust , 30002 ) # 撤买
165
- self .B_Csell = win32gui .GetDlgItem (F_Centrust , 30003 ) # 撤卖
166
- F_Chexin = win32gui .GetDlgItem (F_Centrust , 1047 )
167
- F_Chexinsub = win32gui .GetDlgItem (F_Chexin , 200 )
168
- self .G_entrust = win32gui .GetDlgItem (F_Chexinsub , 1047 ) # 委托列表
179
+ cancel_entrust_window_hwnd = win32gui .GetDlgItem (operate_frame_hwnd , 59649 ) # 撤单窗口框架
180
+ self .cancel_stock_code_hwnd = win32gui .GetDlgItem (cancel_entrust_window_hwnd , 3348 ) # 卖出代码输入框
181
+ self .cancel_query_hwnd = win32gui .GetDlgItem (cancel_entrust_window_hwnd , 3349 ) # 查询代码按钮
182
+ self .cancel_buy_hwnd = win32gui .GetDlgItem (cancel_entrust_window_hwnd , 30002 ) # 撤买
183
+ self .cancel_sell_hwnd = win32gui .GetDlgItem (cancel_entrust_window_hwnd , 30003 ) # 撤卖
184
+
185
+ chexin_hwnd = win32gui .GetDlgItem (cancel_entrust_window_hwnd , 1047 )
186
+ chexin_sub_hwnd = win32gui .GetDlgItem (chexin_hwnd , 200 )
187
+ self .entrust_list_hwnd = win32gui .GetDlgItem (chexin_sub_hwnd , 1047 ) # 委托列表
169
188
170
189
def buy (self , stock_code , price , amount ):
171
190
"""
@@ -179,12 +198,12 @@ def buy(self, stock_code, price, amount):
179
198
price = str (price )
180
199
181
200
try :
182
- win32gui .SendMessage (self .E_Bsymbol , win32con .WM_SETTEXT , None , stock_code ) # 输入买入代码
183
- win32gui .SendMessage (self .E_Bprice , win32con .WM_SETTEXT , None , price ) # 输入买入价格
201
+ win32gui .SendMessage (self .buy_stock_code_hwnd , win32con .WM_SETTEXT , None , stock_code ) # 输入买入代码
202
+ win32gui .SendMessage (self .buy_price_hwnd , win32con .WM_SETTEXT , None , price ) # 输入买入价格
184
203
time .sleep (0.2 )
185
- win32gui .SendMessage (self .E_Bvol , win32con .WM_SETTEXT , None , amount ) # 输入买入数量
204
+ win32gui .SendMessage (self .buy_amount_hwnd , win32con .WM_SETTEXT , None , amount ) # 输入买入数量
186
205
time .sleep (0.2 )
187
- win32gui .SendMessage (self .B_Buy , win32con .BM_CLICK , None , None ) # 买入确定
206
+ win32gui .SendMessage (self .buy_btn_hwnd , win32con .BM_CLICK , None , None ) # 买入确定
188
207
time .sleep (0.3 )
189
208
except :
190
209
traceback .print_exc ()
@@ -203,14 +222,13 @@ def sell(self, stock_code, price, amount):
203
222
price = str (price )
204
223
205
224
try :
206
- win32gui .SendMessage (self .E_Ssymbol , win32con .WM_SETTEXT , None , stock_code ) # 输入卖出代码
207
- win32gui .SendMessage (self .E_Sprice , win32con .WM_SETTEXT , None , price ) # 输入卖出价格
208
- win32gui .SendMessage (self .E_Sprice , win32con .BM_CLICK , None , None ) # 输入卖出价格
209
- print ('add click' )
225
+ win32gui .SendMessage (self .sell_stock_code_hwnd , win32con .WM_SETTEXT , None , stock_code ) # 输入卖出代码
226
+ win32gui .SendMessage (self .sell_price_hwnd , win32con .WM_SETTEXT , None , price ) # 输入卖出价格
227
+ win32gui .SendMessage (self .sell_price_hwnd , win32con .BM_CLICK , None , None ) # 输入卖出价格
210
228
time .sleep (0.2 )
211
- win32gui .SendMessage (self .E_Svol , win32con .WM_SETTEXT , None , amount ) # 输入卖出数量
229
+ win32gui .SendMessage (self .sell_amount_hwnd , win32con .WM_SETTEXT , None , amount ) # 输入卖出数量
212
230
time .sleep (0.2 )
213
- win32gui .SendMessage (self .B_Sell , win32con .BM_CLICK , None , None ) # 卖出确定
231
+ win32gui .SendMessage (self .sell_btn_hwnd , win32con .BM_CLICK , None , None ) # 卖出确定
214
232
time .sleep (0.3 )
215
233
except :
216
234
traceback .print_exc ()
@@ -227,15 +245,15 @@ def cancel_entrust(self, stock_code, direction):
227
245
direction = 0 if direction == 'buy' else 1
228
246
229
247
try :
230
- win32gui .SendMessage (self .B_refresh , win32con .BM_CLICK , None , None ) # 刷新持仓
248
+ win32gui .SendMessage (self .refresh_entrust_hwnd , win32con .BM_CLICK , None , None ) # 刷新持仓
231
249
time .sleep (0.2 )
232
- win32gui .SendMessage (self .E_Csymbol , win32con .WM_SETTEXT , None , stock_code ) # 输入撤单
233
- win32gui .SendMessage (self .B_Csort , win32con .BM_CLICK , None , None ) # 查询代码
250
+ win32gui .SendMessage (self .cancel_stock_code_hwnd , win32con .WM_SETTEXT , None , stock_code ) # 输入撤单
251
+ win32gui .SendMessage (self .cancel_query_hwnd , win32con .BM_CLICK , None , None ) # 查询代码
234
252
time .sleep (0.2 )
235
253
if direction == 0 :
236
- win32gui .SendMessage (self .B_Cbuy , win32con .BM_CLICK , None , None ) # 撤买
254
+ win32gui .SendMessage (self .cancel_buy_hwnd , win32con .BM_CLICK , None , None ) # 撤买
237
255
elif direction == 1 :
238
- win32gui .SendMessage (self .B_Csell , win32con .BM_CLICK , None , None ) # 撤卖
256
+ win32gui .SendMessage (self .cancel_sell_hwnd , win32con .BM_CLICK , None , None ) # 撤卖
239
257
except :
240
258
traceback .print_exc ()
241
259
return False
@@ -247,11 +265,11 @@ def position(self):
247
265
return self .get_position ()
248
266
249
267
def get_position (self ):
250
- win32gui .SendMessage (self .B_refresh , win32con .BM_CLICK , None , None ) # 刷新持仓
268
+ win32gui .SendMessage (self .refresh_entrust_hwnd , win32con .BM_CLICK , None , None ) # 刷新持仓
251
269
time .sleep (0.1 )
252
- self .set_foreground_window (self .G_position )
270
+ self ._set_foreground_window (self .position_list_hwnd )
253
271
time .sleep (0.1 )
254
- data = self .read_clipboard ()
272
+ data = self ._read_clipboard ()
255
273
return self .project_copy_data (data )
256
274
257
275
@staticmethod
@@ -260,10 +278,9 @@ def project_copy_data(copy_data):
260
278
df = pd .read_csv (reader , delim_whitespace = True )
261
279
return df .to_dict ('records' )
262
280
263
- def read_clipboard (self ):
264
- for _ in range (10 ):
281
+ def _read_clipboard (self ):
282
+ for _ in range (15 ):
265
283
try :
266
- #self.set_foreground_window(self.Main)
267
284
win32api .keybd_event (17 , 0 , 0 , 0 )
268
285
win32api .keybd_event (67 , 0 , 0 , 0 )
269
286
win32api .keybd_event (67 , 0 , win32con .KEYEVENTF_KEYUP , 0 )
@@ -277,13 +294,13 @@ def read_clipboard(self):
277
294
raise Exception ('read clipbord failed' )
278
295
279
296
@staticmethod
280
- def project_position_str (raw ):
297
+ def _project_position_str (raw ):
281
298
reader = StringIO (raw )
282
299
df = pd .read_csv (reader , delim_whitespace = True )
283
300
return df
284
301
285
302
@staticmethod
286
- def set_foreground_window (hwnd ):
303
+ def _set_foreground_window (hwnd ):
287
304
shell = win32com .client .Dispatch ('WScript.Shell' )
288
305
shell .SendKeys ('%' )
289
306
win32gui .SetForegroundWindow (hwnd )
@@ -293,9 +310,9 @@ def entrust(self):
293
310
return self .get_entrust ()
294
311
295
312
def get_entrust (self ):
296
- win32gui .SendMessage (self .B_refresh , win32con .BM_CLICK , None , None ) # 刷新持仓
313
+ win32gui .SendMessage (self .refresh_entrust_hwnd , win32con .BM_CLICK , None , None ) # 刷新持仓
297
314
time .sleep (0.2 )
298
- self .set_foreground_window (self .G_entrust )
315
+ self ._set_foreground_window (self .entrust_list_hwnd )
299
316
time .sleep (0.2 )
300
- data = self .read_clipboard ()
317
+ data = self ._read_clipboard ()
301
318
return self .project_copy_data (data )
0 commit comments