代码拉取完成,页面将自动刷新
同步操作将从 老张/puppet 强制同步,此操作会覆盖自 Fork 仓库以来所做的任何修改,且无法恢复!!!
确定后同步将在后台操作,完成时将刷新页面,请耐心等待。
"""puppetrader for ths client uniform"""
__author__ = '睿瞳深邃(https://github.com/Raytone-D)'
__project__ = '扯线木偶(puppetrader for ths client unity)'
__version__ = "0.3.5"
'推荐使用:anaconda3 最新版,或者Python >= 3.6'
# coding: utf-8
import ctypes
from functools import reduce
import time
import pyperclip
import json
WM_COMMAND, WM_SETTEXT, WM_GETTEXT, WM_KEYDOWN, WM_KEYUP = \
273, 12, 13, 256, 257 # 命令
F1, F2, F3, F4, F5, F6 = \
112, 113, 114, 115, 116, 117 # keyCode(按键代码)
op = ctypes.windll.user32
wait_a_second = lambda sec= 0.1: time.sleep(sec)
def keystroke(hCtrl, keyCode, param=0): # 单击
op.PostMessageW(hCtrl, WM_KEYDOWN, keyCode, param)
op.PostMessageW(hCtrl, WM_KEYUP, keyCode, param)
class unity():
''' 多账户交易集中处理 '''
def __init__(self, main):
self.main = main
keystroke(main, F6) # 切换到双向委托
wait_a_second() # 可调整区间值(0.01~0.5)
self.buff = ctypes.create_unicode_buffer(32)
# 代码,价格,数量,买入,代码,价格,数量,卖出,全撤, 撤买, 撤卖
id_members = 1032, 1033, 1034, 1006, 1035, 1058, 1039, 1008, 30001, 30002, 30003, \
32790, 1038, 1047, 2053, 30022, 1019 # 刷新,余额、表格、最后一笔、撤相同
self.path_custom = 1047, 200, 1047
self.two_way = reduce(op.GetDlgItem, (59648, 59649), main)
self.members = {i: op.GetDlgItem(self.two_way, i) for i in id_members}
self.custom = reduce(op.GetDlgItem, self.path_custom, self.two_way)
# 获取登录账号
self.account = reduce(op.GetDlgItem, (59392, 0, 1711), main)
op.SendMessageW(self.account, WM_GETTEXT, 32, self.buff)
self.account = self.buff.value
# 撤单工具条
self.id_toolbar = {'全选': 1098, \
'撤单': 1099, \
'全撤': 30001, \
'撤买': 30002, \
'撤卖': 30003, \
'填单': 3348, \
'查单': 3349} #'撤尾单': 2053, '撤相同': 30022} # 华泰独有
op.SendMessageW(main, WM_COMMAND, 163, 0) # 切换到撤单操作台
wait_a_second()
self.cancel_panel = reduce(op.GetDlgItem, (59648, 59649), main)
self.cancel_toolbar = {k: op.GetDlgItem(self.cancel_panel, v) for k, v in self.id_toolbar.items()}
keystroke(main, F6) # 切换到双向委托
def buy(self, symbol, price, qty): # 买入(B)
# buy = order('b')
op.SendMessageW(self.members[1032], WM_SETTEXT, 0, symbol)
op.SendMessageW(self.members[1033], WM_SETTEXT, 0, price)
op.SendMessageW(self.members[1034], WM_SETTEXT, 0, qty)
op.PostMessageW(self.two_way, WM_COMMAND, 1006, self.members[1006])
def sell(self, symbol, price, qty): # 卖出(S)
# buy = order('s')
op.SendMessageW(self.members[1035], WM_SETTEXT, 0, symbol)
op.SendMessageW(self.members[1058], WM_SETTEXT, 0, price)
op.SendMessageW(self.members[1039], WM_SETTEXT, 0, qty)
op.PostMessageW(self.two_way, WM_COMMAND, 1008, self.members[1008])
def refresh(self): # 刷新(F5)
op.PostMessageW(self.two_way, WM_COMMAND, 32790, self.members[32790])
def cancel_order(self, symbol=''): # 撤单
op.SendMessageW(main, WM_COMMAND, 163, 0) # 切换到撤单操作台
if symbol:
op.SendMessageW(self.cancel_toolbar['填单'], WM_SETTEXT, 0, symbol)
sleep(0.1) # 必须有
op.PostMessageW(self.cancel_panel, WM_COMMAND, self.id_toolbar['查单'], self.cancel_toolbar['查单'])
op.PostMessageW(self.cancel_panel, WM_COMMAND, self.id_toolbar['撤单'], self.cancel_toolbar['撤单'])
keystroke(self.main, F6) # 必须返回双向委托操作台!
def cancelAll(self): # 全撤(Z)
op.PostMessageW(self.two_way, WM_COMMAND, 30001, self.members[30001])
def cancelBuy(self): # 撤买(X)
op.PostMessageW(self.two_way, WM_COMMAND, 30002, self.members[30002])
def cancelSell(self): # 撤卖(C)
op.PostMessageW(self.two_way, WM_COMMAND, 30003, self.members[30003])
def cancelLast(self): # 撤最后一笔,仅限华泰定制版有效
op.PostMessageW(self.two_way, WM_COMMAND, 2053, self.members[2053])
def cancelSame(self): # 撤相同代码,仅限华泰定制版
#op.PostMessageW(self.two_way, WM_COMMAND, 30022, self.members[30022])
pass
def balance(self): # 可用余额
op.SendMessageW(self.members[1038], WM_GETTEXT, 32, self.buff)
return self.buff.value
def get_data(self, key='W'):
"将CVirtualGridCtrl|Custom<n>的数据复制到剪贴板,默认取持仓记录"
keystroke(self.two_way, ord(key)) # 切换到持仓('W')、成交('E')、委托('R')
wait_a_second() # 等待券商的数据返回...
op.SendMessageW(self.custom, WM_COMMAND, 57634, self.path_custom[-1]) # background mode
return pyperclip.paste()
def finder():
""" 枚举所有已登录的交易端并将其实例化 """
team = set()
buff = ctypes.create_unicode_buffer(32)
@ctypes.WINFUNCTYPE(ctypes.wintypes.BOOL, ctypes.wintypes.HWND, ctypes.wintypes.LPARAM)
def check(hwnd, extra):
if op.IsWindowVisible(hwnd):
op.GetWindowTextW(hwnd, buff, 32)
if '交易系统' in buff.value:
team.add(hwnd)
return 1
op.EnumWindows(check, 0)
return {unity(main) for main in team if team}
def to_dict(raw):
x = [row.split() for row in raw.splitlines()]
data = {}
for y in x[1:]:
data.update({y[0]: dict(zip(x[0], y))})
return data
if __name__ == '__main__':
myRegister = {'券商登录号': '自定义名称', \
'617145470': '东方不败', \
'20941552121212': '西门吹雪'}
ret = finder()
if ret:
# 如果没取到余额,尝试修改_init_函数里面sleep的值,或者查余额的id是不是变了。
trader = {myRegister[broker.account]: broker for broker in ret} # 给账户一个易记的外号
trader1 = {broker.account[-3:]: broker.balance() for broker in ret} # 以登录号3位尾数作代号
profile = {solo: {"交易帐号": trader[solo].account, \
"可用余额": trader[solo].balance()} \
for solo in trader}
print(profile)
#print(json.dumps(profile, indent=4, ensure_ascii=False, sort_keys=True))
raw = trader['东方不败'].get_data() # 只能“大写字母”,小写字母THS会崩溃,无语!
print(raw)
#print(to_dict(raw))
raw = trader['东方不败'].get_data('R')
print(raw)
#print(json.dumps(to_dict(raw), indent=4, ensure_ascii=False))
trader['东方不败'].cancel_order('')
else: print("老板,没发现已登录的交易端!")
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。