532 lines
18 KiB
Python
532 lines
18 KiB
Python
|
# -*- coding: utf-8 -*-
|
||
|
"""
|
||
|
Created on Fri Aug 5 15:29:12 2022
|
||
|
|
||
|
@author: MINGL
|
||
|
"""
|
||
|
import pandas as pd
|
||
|
import pyautogui as pyautogui
|
||
|
import pywinauto
|
||
|
from pywinauto import clipboard
|
||
|
from pywinauto import keyboard
|
||
|
from skimage import io
|
||
|
import time
|
||
|
import io as mio
|
||
|
import pytesseract
|
||
|
import warnings
|
||
|
import datetime
|
||
|
from tools import *
|
||
|
|
||
|
|
||
|
from connect_wifi import connect_wifi
|
||
|
from iptest import get_proxy_ip,set_global_proxy,get_ip_data
|
||
|
|
||
|
warnings.filterwarnings('ignore')
|
||
|
scripts_path = os.path.dirname(os.path.realpath(__file__))
|
||
|
root_path = scripts_path[:scripts_path.find(project_name)+len(project_name)]
|
||
|
|
||
|
path = r'C:\trade_software1\trade_software\zd_zsone\TdxW.exe'
|
||
|
|
||
|
|
||
|
class ZSClientTrader:
|
||
|
"""
|
||
|
基于通达信程序国信金太阳专业版自动交易程序
|
||
|
"""
|
||
|
|
||
|
def __init__(self, account_name, exe_path=path):
|
||
|
self.path = exe_path
|
||
|
self.account_name = account_name
|
||
|
self.log = Logger(f'{root_path}/logs',self.account_name)
|
||
|
self.As_Of_Date = datetime.datetime.today().strftime('%Y%m%d')
|
||
|
# 用户券商信息
|
||
|
sql = f"select * from ainvest_usercount where username='{account_name}'"
|
||
|
df_count = download_data_from_db(sql, 'ai_strategy_update_iddb')
|
||
|
self.securities_name = str(df_count['securities_username'].tolist()[0])
|
||
|
self.securities_password = str(df_count['securities_password'].tolist()[0])
|
||
|
self.communication_password = str(df_count['communication_password'].tolist()[0])
|
||
|
self.trade_control_id_group = {
|
||
|
's1': 0x3FD, 's2': 0x3FE, 's3': 0x3FF, 's4': 0x409, 's5': 0x408,
|
||
|
'b1': 0x3FA, 'b2': 0x401, 'b3': 0x402, 'b4': 0x40B, 'b5': 0x40C,
|
||
|
}
|
||
|
def exit(self):
|
||
|
'''
|
||
|
结束进程
|
||
|
|
||
|
Returns
|
||
|
-------
|
||
|
None.
|
||
|
|
||
|
'''
|
||
|
self._app.kill()
|
||
|
def _close_prompt_windows(self):
|
||
|
time.sleep(0.1)
|
||
|
for window in self._app.windows(class_name="#32770"):
|
||
|
if window.window_text() != '网上股票交易系统*':
|
||
|
window.close()
|
||
|
time.sleep(0.1)
|
||
|
def login(self):
|
||
|
'''
|
||
|
启动软件并登录
|
||
|
|
||
|
Returns
|
||
|
-------
|
||
|
None.
|
||
|
|
||
|
'''
|
||
|
#软件启动判断,若有进行中进程,先关闭再重启
|
||
|
try:
|
||
|
self._app = pywinauto.Application().connect(
|
||
|
path=self.path, timeout=1
|
||
|
)
|
||
|
self.exit()
|
||
|
self.log.warn('There are running programs, and there are processes in retreat')
|
||
|
except Exception:
|
||
|
pass
|
||
|
|
||
|
#启动软件进程,输入账号密码
|
||
|
self.log.info('Start login')
|
||
|
self._app = pywinauto.Application().start(self.path)
|
||
|
while True:
|
||
|
try:
|
||
|
self._app.window(title_re='招商证券.*').wait("ready")
|
||
|
break
|
||
|
except RuntimeError:
|
||
|
pass
|
||
|
time.sleep(1)
|
||
|
self._app.window(title_re='招商证券.*').window(control_id = 0xE9,class_name = 'SafeEdit').click()
|
||
|
pyautogui.typewrite(self.securities_name)
|
||
|
time.sleep(1)
|
||
|
self._app.window(title_re='招商证券.*').window(control_id = 0xEA,class_name = 'SafeEdit').click()
|
||
|
pyautogui.typewrite(self.securities_password)
|
||
|
# 登录
|
||
|
pywinauto.keyboard.send_keys("{ENTER}")
|
||
|
|
||
|
# while True:
|
||
|
# try:
|
||
|
# # self._app['国信证券消息中心'].wait("ready")
|
||
|
# self._app['招商证券智远一户通V6.72 - [版面-自选股股]'].wait("ready")
|
||
|
# break
|
||
|
# except RuntimeError:
|
||
|
# pass
|
||
|
time.sleep(12)
|
||
|
tryrun2(self._app['招商证券智远一户通V6.72 - [版面-自选股股]'].wait("ready"))
|
||
|
# time.sleep(2)
|
||
|
#关闭弹窗
|
||
|
# self._close_prompt_windows()
|
||
|
|
||
|
for i in range(3):
|
||
|
self._turn_off_advertising()
|
||
|
# self._close_prompt_windows()
|
||
|
#设置主窗口及菜单窗口
|
||
|
self.main_wnd = self._app.TdxW_MainFrame_Class
|
||
|
self.left_wnd = self._app.TdxW_MainFrame_Class.window(class_name='SysTreeView32', control_id=0xE900)
|
||
|
|
||
|
def _turn_off_advertising(self):
|
||
|
'''
|
||
|
关闭弹窗
|
||
|
|
||
|
Returns
|
||
|
-------
|
||
|
None.
|
||
|
|
||
|
'''
|
||
|
try:
|
||
|
self._app.top_window().set_focus()
|
||
|
time.sleep(0.5)
|
||
|
pywinauto.keyboard.send_keys("{ESC}")
|
||
|
pywinauto.keyboard.send_keys("{ENTER}")
|
||
|
pywinauto.keyboard.send_keys("{ESC}")
|
||
|
except Exception as e:
|
||
|
pass
|
||
|
def buy(self, stock_no, price, num):
|
||
|
'''
|
||
|
买入股票
|
||
|
|
||
|
Parameters
|
||
|
----------
|
||
|
stock_no : TYPE
|
||
|
DESCRIPTION.
|
||
|
price : TYPE
|
||
|
DESCRIPTION.
|
||
|
num : TYPE
|
||
|
DESCRIPTION.
|
||
|
|
||
|
Returns
|
||
|
-------
|
||
|
None.
|
||
|
|
||
|
'''
|
||
|
time.sleep(0.5)
|
||
|
path = ['买入']
|
||
|
# 点击买入
|
||
|
self.left_wnd.get_item(path, exact=False).click_input(button=u'left', double=False, wheel_dist=0,
|
||
|
pressed=u'')
|
||
|
time.sleep(1)
|
||
|
self.__trade(stock_no, price, num)
|
||
|
|
||
|
def sell(self, stock_no, price, num):
|
||
|
'''
|
||
|
卖出股票
|
||
|
|
||
|
Parameters
|
||
|
----------
|
||
|
stock_no : TYPE
|
||
|
DESCRIPTION.
|
||
|
price : TYPE
|
||
|
DESCRIPTION.
|
||
|
num : TYPE
|
||
|
DESCRIPTION.
|
||
|
|
||
|
Returns
|
||
|
-------
|
||
|
None.
|
||
|
|
||
|
'''
|
||
|
time.sleep(0.5)
|
||
|
path = ['卖出']
|
||
|
# 点击卖出
|
||
|
self.left_wnd.get_item(path, exact=False).click_input(button=u'left', double=False, wheel_dist=0,
|
||
|
pressed=u'')
|
||
|
time.sleep(1)
|
||
|
self.__trade(stock_no, price, num)
|
||
|
|
||
|
def purchase_stocks(self):
|
||
|
|
||
|
self.left_wnd.get_item([5,2]).click_input()
|
||
|
time.sleep(1)
|
||
|
self.main_wnd.window(control_id=0x9876,class_name='Button').click()
|
||
|
|
||
|
one_text = str(self._app.window(control_id=0x0, class_name="#32770",found_index=0).children()[4].context_help_id).split("'")[1].split("'")[0]
|
||
|
self.log.info(one_text.replace('/n', ' '))
|
||
|
|
||
|
while True:
|
||
|
try:
|
||
|
self._app.window(control_id=0x0, class_name="#32770", found_index=0).window(control_id=0x1B67,class_name="Button").click_input()
|
||
|
|
||
|
self.log.info(str(self._app.window(title='提示', class_name="#32770", found_index=0).children()[4].context_help_id).split("'")[1].split("'")[0])
|
||
|
|
||
|
except:
|
||
|
break
|
||
|
|
||
|
def cancel_entrust(self):
|
||
|
'''
|
||
|
全撤
|
||
|
|
||
|
Returns
|
||
|
-------
|
||
|
None.
|
||
|
|
||
|
'''
|
||
|
# # 进入撤单页面
|
||
|
time.sleep(0.5)
|
||
|
self.left_wnd.get_item([4]).click_input() # 点击撤单
|
||
|
time.sleep(1)
|
||
|
# 刷新
|
||
|
try:
|
||
|
self.main_wnd.window(control_id=0x474, class_name='Button').click_input()
|
||
|
except:
|
||
|
self.main_wnd.window(control_id=0x474, class_name='Button').click()
|
||
|
|
||
|
time.sleep(1)
|
||
|
try:
|
||
|
# 全选中
|
||
|
self.main_wnd.window(control_id=0xE, class_name='Button').click()
|
||
|
except:
|
||
|
self.main_wnd.window(control_id=0xE, class_name='Button').click_input()
|
||
|
|
||
|
time.sleep(1)
|
||
|
# exit()
|
||
|
# 全撤
|
||
|
try:
|
||
|
self.main_wnd.window(control_id=0x470, class_name='Button').click_input()
|
||
|
except:
|
||
|
self.main_wnd.window(control_id=0x470, class_name='Button').click()
|
||
|
|
||
|
time.sleep(1)
|
||
|
|
||
|
# 确认撤单
|
||
|
pywinauto.keyboard.send_keys("{ENTER}")
|
||
|
time.sleep(5)
|
||
|
# 确认撤单2
|
||
|
pywinauto.keyboard.send_keys("{ENTER}")
|
||
|
time.sleep(5)
|
||
|
# 确认撤单2
|
||
|
pywinauto.keyboard.send_keys("{ESC}")
|
||
|
time.sleep(0.5)
|
||
|
pywinauto.keyboard.send_keys("{ENTER}")
|
||
|
|
||
|
def _delete_first_lines(self,filename,pp):
|
||
|
fin = open(filename, 'r')
|
||
|
a = fin.readlines()
|
||
|
fout = open(filename, 'w')
|
||
|
if pp==0:
|
||
|
b = ''.join(a[:3])
|
||
|
else:
|
||
|
b = ''.join(a[3:])
|
||
|
fout.write(b)
|
||
|
|
||
|
def get_balance(self):
|
||
|
'''
|
||
|
获取资金情况
|
||
|
|
||
|
Returns
|
||
|
-------
|
||
|
record : TYPE
|
||
|
DESCRIPTION.
|
||
|
|
||
|
'''
|
||
|
self.left_wnd.get_item([3, 0]).click_input()
|
||
|
time.sleep(1)
|
||
|
self._copy_data([3, 0])
|
||
|
filenme = f'C:\\Users\\Administrator\\Documents\\{self.As_Of_Date} 资金股份查询.xls'
|
||
|
self.df_balance = pd.read_csv(filenme, encoding='gbk', sep='\t', engine='python', error_bad_lines=False)
|
||
|
# print(self.df_balance)
|
||
|
self.df_balance['="可用"'] = self.df_balance['="可用"'].map(lambda x: x.strip('=').strip('"'))
|
||
|
self.df_balance['="参考市值"'] = self.df_balance['="参考市值"'].map(lambda x: x.strip('=').strip('"'))
|
||
|
self.df_balance['="资产"'] = self.df_balance['="资产"'].map(lambda x: x.strip('=').strip('"'))
|
||
|
|
||
|
result = {}
|
||
|
result['Cash'] = list(self.df_balance['="可用"'].values)[0]
|
||
|
result['Position_amount'] = list(self.df_balance['="参考市值"'].values)[0]
|
||
|
result['Total_account'] = list(self.df_balance['="资产"'].values)[0]
|
||
|
result = pd.DataFrame(result, index=[0])
|
||
|
result['Account_Name'] = self.account_name
|
||
|
result['As_Of_Date'] = datetime.date.today()
|
||
|
return result
|
||
|
|
||
|
def get_position(self):
|
||
|
'''
|
||
|
获取持仓情况
|
||
|
|
||
|
Returns
|
||
|
-------
|
||
|
df_position : TYPE
|
||
|
DESCRIPTION.
|
||
|
|
||
|
'''
|
||
|
self.left_wnd.get_item([3, 0]).click_input()
|
||
|
# 复制表格数据
|
||
|
time.sleep(1)
|
||
|
self._copy_data([3, 0])
|
||
|
|
||
|
|
||
|
filenme = f'C:\\Users\\Administrator\\Documents\\{str(datetime.date.today()).replace("-","")} 资金股份查询.xls'
|
||
|
self._delete_first_lines(filenme, 1)
|
||
|
# 读文件
|
||
|
df_position = pd.read_csv(filenme, encoding='gbk', sep='\t', engine='python', error_bad_lines=False)
|
||
|
os.remove(filenme)
|
||
|
if len(df_position) == 0:
|
||
|
return pd.DataFrame()
|
||
|
else:
|
||
|
df_position.columns = [i.strip('=').strip('"') for i in list(df_position.columns)]
|
||
|
df_position = df_position.applymap(lambda x: x.strip('=').strip('"') if isinstance(x, str) else x)
|
||
|
df_position['证券代码'] = df_position['证券代码'].apply(lambda x: tranTicker(x))
|
||
|
df_position = df_position[
|
||
|
['证券代码', '证券名称', '证券数量', '可卖数量', '成本价', '当前价', '最新市值',
|
||
|
'持仓盈亏', '持仓盈亏比例(%)']]
|
||
|
|
||
|
df_position.rename(columns={"证券代码": "Ticker",
|
||
|
"证券名称": "Ticker_name",
|
||
|
"证券数量": "Number_transactions",
|
||
|
"可卖数量": "cash",
|
||
|
"成本价": "cost_price",
|
||
|
"当前价": "market_price",
|
||
|
"最新市值": "market_value",
|
||
|
"持仓盈亏": "profit_and_loss",
|
||
|
"持仓盈亏比例(%)": "profit_loss_ratio",
|
||
|
}, inplace=True)
|
||
|
df_position['frozen_quantity'] = 0
|
||
|
df_position['As_Of_Date'] = datetime.date.today()
|
||
|
df_position['Account_Name'] = self.account_name
|
||
|
|
||
|
return df_position
|
||
|
|
||
|
|
||
|
|
||
|
def get_order(self):
|
||
|
'''
|
||
|
获取委托情况
|
||
|
|
||
|
Returns
|
||
|
-------
|
||
|
TYPE
|
||
|
DESCRIPTION.
|
||
|
|
||
|
'''
|
||
|
self.left_wnd.get_item([6, 1]).click_input()
|
||
|
# 复制表格数据
|
||
|
time.sleep(1)
|
||
|
self._copy_data([6, 1])
|
||
|
try:
|
||
|
filenme = f'C:\\Users\\Administrator\\Documents\\{str(datetime.date.today()).replace("-", "")} 当日委托查询.xls'
|
||
|
self._delete_first_lines(filenme, 0)
|
||
|
# 读文件
|
||
|
df_order = pd.read_csv(filenme, encoding='gbk', sep='\t', engine='python', error_bad_lines=False)
|
||
|
os.remove(filenme)
|
||
|
except:
|
||
|
self.log.info('--------------------------------------无当日委托--------------------------------------')
|
||
|
return pd.DataFrame()
|
||
|
df_order.columns = [i.strip('=').strip('"') for i in list(df_order.columns)]
|
||
|
df_order = df_order.applymap(lambda x: x.strip('=').strip('"') if isinstance(x, str) else x)
|
||
|
df_order['证券代码'] = df_order['证券代码'].apply(lambda x: tranTicker(x))
|
||
|
return df_order
|
||
|
|
||
|
def get_today_trades(self):
|
||
|
'''
|
||
|
获取当日成交
|
||
|
|
||
|
Returns
|
||
|
-------
|
||
|
TYPE
|
||
|
DESCRIPTION.
|
||
|
|
||
|
'''
|
||
|
self.left_wnd.get_item([3, 2]).click_input()
|
||
|
# 复制表格数据
|
||
|
time.sleep(1)
|
||
|
self._copy_data([3, 2])
|
||
|
try:
|
||
|
filenme = f'C:\\Users\\Administrator\\Documents\\{str(datetime.date.today()).replace("-", "")} 当日成交查询.xls'
|
||
|
self._delete_first_lines(filenme, 0)
|
||
|
# 读文件
|
||
|
df = pd.read_csv(filenme, encoding='gbk', sep='\t', engine='python', error_bad_lines=False)
|
||
|
os.remove(filenme)
|
||
|
df.columns = [i.strip('=').strip('"') for i in list(df.columns)]
|
||
|
df = df.applymap(lambda x: x.strip('=').strip('"') if isinstance(x, str) else x)
|
||
|
df['证券代码'] = df['证券代码'].apply(lambda x: tranTicker(x))
|
||
|
|
||
|
df = df[['成交时间', '证券代码', '证券名称', '买卖标志', '成交数量', '成交价格']]
|
||
|
df['Account_Name'] = self.account_name
|
||
|
df['As_Of_Date'] = datetime.date.today()
|
||
|
df.rename(columns={'成交时间': 'Trade_time', '证券代码': 'Ticker', '证券名称': 'Ticker_name',
|
||
|
'买卖标志': 'Operate',
|
||
|
'成交数量': 'Number_transactions',
|
||
|
'成交价格': 'Average_price'}, inplace=True)
|
||
|
df['Operate'] = df['Operate'].apply(lambda x: '卖' if '卖' in x else '买')
|
||
|
|
||
|
df['Ticker'] = df['Ticker'].apply(lambda x: tranTicker(str(x).replace('="', '').replace('"', '')))
|
||
|
|
||
|
return df
|
||
|
except:
|
||
|
self.log.info('--------------------------------------无当日成交--------------------------------------')
|
||
|
return pd.DataFrame()
|
||
|
|
||
|
|
||
|
def __trade(self, stock_no, price, amount):
|
||
|
'''
|
||
|
交易输入函数
|
||
|
|
||
|
Parameters
|
||
|
----------
|
||
|
stock_no : TYPE
|
||
|
DESCRIPTION.
|
||
|
price : TYPE
|
||
|
DESCRIPTION.
|
||
|
amount : TYPE
|
||
|
DESCRIPTION.
|
||
|
|
||
|
Returns
|
||
|
-------
|
||
|
None.
|
||
|
|
||
|
'''
|
||
|
time.sleep(1)
|
||
|
# 设置股票代码
|
||
|
pyautogui.typewrite(str(stock_no))
|
||
|
time.sleep(0.5)
|
||
|
|
||
|
if price in ['b1', 'b2', 'b3', 'b4', 'b5', 's1', 's2', 's3', 's4', 's5']:
|
||
|
price = float(
|
||
|
self.main_wnd.window(control_id=self.trade_control_id_group[price], class_name="Static").window_text())
|
||
|
|
||
|
# 设置价格
|
||
|
# pyautogui.typewrite(str(price), interval=0.1)
|
||
|
self.main_wnd.window(control_id=0x2EE6, class_name="Edit").set_text(str(price))
|
||
|
# self.main_wnd.Edit4.set_text(str(price))
|
||
|
time.sleep(1)
|
||
|
|
||
|
# 设置股数目
|
||
|
self.main_wnd.window(control_id=0x2EE7, class_name="Edit").set_text(str(amount))
|
||
|
time.sleep(1)
|
||
|
# exit()
|
||
|
|
||
|
# 点击卖出or买入
|
||
|
try:
|
||
|
self.main_wnd.window(control_id=0x7DA, class_name="Button").click()
|
||
|
except:
|
||
|
self.main_wnd.window(control_id=0x7DA, class_name="Button").click_input()
|
||
|
|
||
|
time.sleep(1)
|
||
|
|
||
|
# # 摘取合同信息
|
||
|
# # result_1 = self._app['买入交易确认'].child_window(class_name='Static',control_id=0x1B65).window_text()
|
||
|
# result_1 = self._app['买入交易确认'].window_text()
|
||
|
# self.__parse_contract(result_1)
|
||
|
# time.sleep(0.2)
|
||
|
|
||
|
# 确认买入
|
||
|
# pywinauto.keyboard.send_keys("{ENTER}")
|
||
|
self._app.window(class_name='#32770', control_id=0x0, found_index=0).window(control_id=0x1B67,
|
||
|
class_name='Button').click()
|
||
|
time.sleep(1)
|
||
|
|
||
|
# # 摘取合同信息2
|
||
|
# # result_2 = self._app['提示'].child_window(control_id=0x1B65, class_name='Static').window_text()
|
||
|
# result_2 = self._app['提示'].Static1.window_text()
|
||
|
# print(result_2)
|
||
|
|
||
|
# 确认合同
|
||
|
# pywinauto.keyboard.send_keys("{ENTER}")
|
||
|
self._app.window(class_name='#32770', control_id=0x0, found_index=0).window(control_id=0x1B67,
|
||
|
class_name='Button').click()
|
||
|
time.sleep(0.5)
|
||
|
|
||
|
|
||
|
def _copy_data(self, path):
|
||
|
self.left_wnd.get_item(path, exact=False).click_input(button=u'left', double=False, wheel_dist=0, pressed=u'')
|
||
|
time.sleep(0.5)
|
||
|
try:
|
||
|
self.main_wnd.window(control_id=0x47F, class_name='Button').click()
|
||
|
time.sleep(0.5)
|
||
|
|
||
|
self._app['输出'].window(control_id=0xE9, class_name='Button').click()
|
||
|
except Exception:
|
||
|
print('无输出的数据!')
|
||
|
# 确认
|
||
|
pywinauto.keyboard.send_keys("{ENTER}")
|
||
|
|
||
|
def _delete_first_lines(self, filename, pp):
|
||
|
|
||
|
fin = open(filename, 'r')
|
||
|
a = fin.readlines()
|
||
|
fout = open(filename, 'w')
|
||
|
if pp == 0:
|
||
|
b = ''.join(a)
|
||
|
else:
|
||
|
b = ''.join(a[3:])
|
||
|
fout.write(b)
|
||
|
|
||
|
if __name__ == '__main__':
|
||
|
|
||
|
account_name = str('13240313541')
|
||
|
a = ZSClientTrader(account_name)
|
||
|
a.login()
|
||
|
|
||
|
# 买入
|
||
|
# a.buy('600000', '7','100')
|
||
|
|
||
|
# 卖出
|
||
|
# a.sell('600835', '12.45','900')
|
||
|
# print(a.get_order())
|
||
|
|
||
|
# a.purchase_stocks()
|
||
|
|
||
|
# # 获取当日实际持仓
|
||
|
# print(a.get_position())
|
||
|
#
|
||
|
# # 获取资金情况
|
||
|
# print(a.get_balance())
|
||
|
#
|
||
|
# # 获取当日成交
|
||
|
# print(a.get_today_trades())
|