714 lines
29 KiB
Python
714 lines
29 KiB
Python
|
#!/usr/bin/env python
|
|||
|
# -*- coding: utf-8 -*-
|
|||
|
"""
|
|||
|
@Time : 2020-08-27 12:00
|
|||
|
@Author : Merlin
|
|||
|
@File : hl_clienttrader.py
|
|||
|
@Software: PyCharm
|
|||
|
"""
|
|||
|
import pywinauto
|
|||
|
import re
|
|||
|
import requests
|
|||
|
from pywinauto import keyboard
|
|||
|
import pandas as pd
|
|||
|
from skimage import io
|
|||
|
import win32api
|
|||
|
import time
|
|||
|
from PIL import ImageGrab
|
|||
|
import win32com.client
|
|||
|
import getpass
|
|||
|
import pytesseract
|
|||
|
import warnings
|
|||
|
import pyautogui
|
|||
|
import datetime
|
|||
|
from sqlalchemy import create_engine
|
|||
|
warnings.filterwarnings('ignore')
|
|||
|
|
|||
|
from tools import *
|
|||
|
from connect_wifi import connect_wifi
|
|||
|
from iptest import get_proxy_ip,set_global_proxy,get_ip_data
|
|||
|
|
|||
|
import logging
|
|||
|
|
|||
|
logger = logging.getLogger(__name__)
|
|||
|
|
|||
|
pc_name111 = getpass.getuser() #返回用户名
|
|||
|
|
|||
|
shell = win32com.client.Dispatch("WScript.Shell") #使用启动独立的进程
|
|||
|
shortcut = shell.CreateShortCut(f"C:\\Users\\{pc_name111}\\Desktop\\华林证券金融终端.lnk")
|
|||
|
|
|||
|
path1 = shortcut.Targetpath
|
|||
|
path = path1
|
|||
|
|
|||
|
|
|||
|
class HLClientTrader:
|
|||
|
"""
|
|||
|
基于华林网上交易金融终端v7.01委托下单程序的 华林证券自动交易程序
|
|||
|
"""
|
|||
|
|
|||
|
def __init__(self, account_name, exe_path=path):
|
|||
|
|
|||
|
self.path = exe_path
|
|||
|
# 左边栏33010001
|
|||
|
self.left_wnd_operate_group = {
|
|||
|
'买入': ['1'], '卖出': ['2'], '撤单': ['5'],
|
|||
|
'资金股份': ['7','5'], '当日委托': ['7', '2'],
|
|||
|
'当日成交': ['7', '7'], '未交收成交': ['7', '5'],
|
|||
|
}
|
|||
|
self.As_Of_Date = datetime.datetime.today().strftime('%Y%m%d')
|
|||
|
self.today = datetime.datetime.today().strftime('%Y-%m-%d')
|
|||
|
self.account_name = account_name
|
|||
|
|
|||
|
# 用户券商信息
|
|||
|
sql = f"select * from ainvest_usercount where username='{account_name}'"
|
|||
|
df_count = self.download_data_from_db(sql, 'ai_strategy_update_iddb')
|
|||
|
self.securities_name = str(list(df_count['securities_username'])[0])
|
|||
|
self.securities_password = str(list(df_count['securities_password'])[0])
|
|||
|
self.communication_password = str(list(df_count['communication_password'])[0])
|
|||
|
|
|||
|
# 从数据库获取数据
|
|||
|
def download_data_from_db(self, sql, schema_name):
|
|||
|
"""
|
|||
|
create connection with DB
|
|||
|
阿里云数据库连接
|
|||
|
:param sql: 查询语句
|
|||
|
:param schema_name: 数据库名称
|
|||
|
:return: 查询结果数据
|
|||
|
"""
|
|||
|
cnx = create_engine(
|
|||
|
'mysql+pymysql://cn_ainvest_db:cn_ainvest_sd3a1@rm-2zewagytttzk6f24xno.'
|
|||
|
'mysql.rds.aliyuncs.com:3306/%s?charset=utf8' %
|
|||
|
schema_name, encoding="utf-8", echo=False)
|
|||
|
df = pd.read_sql(sql, con=cnx)
|
|||
|
return df
|
|||
|
|
|||
|
|
|||
|
# 登陆
|
|||
|
def login(self):
|
|||
|
#检查进程,如果开启,关闭后重新打开
|
|||
|
try:
|
|||
|
self._app = pywinauto.Application().connect(
|
|||
|
path=self.path, timeout=1
|
|||
|
)
|
|||
|
self._app.kill()
|
|||
|
time.sleep(5)
|
|||
|
except Exception:
|
|||
|
pass
|
|||
|
|
|||
|
# 启动软件进程,输入账号密码
|
|||
|
logger.info('Start login')
|
|||
|
broker = '华龙证券'
|
|||
|
start_time = time.time()
|
|||
|
reset_proxy_to_default() # 初始化proxy信息
|
|||
|
|
|||
|
# 重置mac
|
|||
|
set_mac = SetMac()
|
|||
|
set_mac.run()
|
|||
|
if not connect_wifi('Redmi K40', '123456789'): # 'Redmi K40','123456789'
|
|||
|
logger.error("无法建立网络连接,请检查配置")
|
|||
|
else:
|
|||
|
logger.info("网络已就绪")
|
|||
|
|
|||
|
get_ip_times = 0
|
|||
|
writer = ExcelDataWriter() # 初始化ip_records 表格
|
|||
|
used_ip = writer.get_unavailable_ips('华龙证券', self.account_name)
|
|||
|
while get_ip_times < 3:
|
|||
|
try:
|
|||
|
item = get_ip_data() # 获取动态IP
|
|||
|
if item['ip'] in used_ip:
|
|||
|
get_ip_times += 1
|
|||
|
else:
|
|||
|
logger.info(f'代理IP已经获取{item}')
|
|||
|
break
|
|||
|
except Exception as e:
|
|||
|
logger.error(f'获取IP失败,请检查网络连接{e}')
|
|||
|
raise ConnectionError(f"获取IP失败,请检查网络连接。错误详情: {e}")
|
|||
|
|
|||
|
# 设置全局代理
|
|||
|
proxy_ip = item['ip']
|
|||
|
proxy_port = item['port']
|
|||
|
# set_global_proxy(proxy_ip, proxy_port, enable=True)
|
|||
|
# exit_ip = get_proxy_ip(proxy_ip, proxy_port)
|
|||
|
time_with_change_proxy = time.time() - start_time
|
|||
|
logger.info('全局代理设置成功')
|
|||
|
|
|||
|
insert_data = {'as_of_date': datetime.datetime.fromtimestamp(start_time).strftime('%Y-%m-%d %H:%M:%S.%f'),
|
|||
|
'broker': broker,
|
|||
|
'account': self.account_name,
|
|||
|
'proxy_ip': proxy_ip,
|
|||
|
'proxy_port': proxy_port,
|
|||
|
'ip_location': item['prov'] + ':' + item['city'],
|
|||
|
# 'exit_ip': exit_ip,
|
|||
|
'ip_cross_check_result': '一致',
|
|||
|
'ip_switch_time': time_with_change_proxy,
|
|||
|
# 'ip_expire_time':item['expire']
|
|||
|
'ip_survival_time': '3min'
|
|||
|
}
|
|||
|
# 写入数据表
|
|||
|
writer = ExcelDataWriter() # 初始化ip_records 表格
|
|||
|
writer.write_data(insert_data)
|
|||
|
|
|||
|
self._app = pywinauto.Application().start(self.path)
|
|||
|
|
|||
|
# wait login window ready
|
|||
|
while True:
|
|||
|
try:
|
|||
|
self._app.window(title='华林证券金融终端V7.01').wait("ready")
|
|||
|
break
|
|||
|
except RuntimeError:
|
|||
|
pass
|
|||
|
|
|||
|
# 独立交易登陆
|
|||
|
self._app.top_window().window(control_id=0x16E, class_name='AfxWnd42').click(double=True)
|
|||
|
time.sleep(1)
|
|||
|
|
|||
|
# 登陆
|
|||
|
self.login_window = self._app.window(title='华林证券金融终端V7.01')
|
|||
|
time.sleep(0.5)
|
|||
|
|
|||
|
# 输入账号
|
|||
|
self._app.top_window().window(control_id=0x3E9, class_name='Edit').click(double=True)
|
|||
|
pyautogui.typewrite(self.securities_name, interval=0.1)
|
|||
|
|
|||
|
# 输入密码
|
|||
|
self.login_window.window(control_id=0xEC, class_name='SafeEdit').click()
|
|||
|
pyautogui.typewrite(self.securities_password, interval=0.1)
|
|||
|
time.sleep(0.5)
|
|||
|
|
|||
|
# 输入验证码
|
|||
|
while True:
|
|||
|
try:
|
|||
|
id_code = self.verify_code()
|
|||
|
id_code = id_code.strip('_')
|
|||
|
time.sleep(0.2)
|
|||
|
self.login_window.window(control_id=0xED, class_name='SafeEdit').click()
|
|||
|
time.sleep(0.2)
|
|||
|
pyautogui.typewrite(id_code, interval=0.1)
|
|||
|
time.sleep(0.2)
|
|||
|
pywinauto.keyboard.send_keys("{ENTER}")
|
|||
|
time.sleep(3.0)
|
|||
|
except Exception as err:
|
|||
|
print('成功登陆!')
|
|||
|
break
|
|||
|
time.sleep(1.0)
|
|||
|
self.main_wnd = self._app.TdxW_MainFrame_Class
|
|||
|
self.left_wnd = self.main_wnd.window(class_name='SysTreeView32', control_id=0xE900)
|
|||
|
|
|||
|
|
|||
|
# 获取验证码
|
|||
|
def verify_code(self):
|
|||
|
time.sleep(0.5)
|
|||
|
self._app.top_window().set_focus()
|
|||
|
time.sleep(0.5)
|
|||
|
self._app.top_window().window(control_id=0xED, class_name='SafeEdit').click_input(button=u'left', double=False, wheel_dist=0, pressed=u'')
|
|||
|
|
|||
|
# 获取验证码截图
|
|||
|
x, y = win32api.GetCursorPos()
|
|||
|
x_1 = x + 52
|
|||
|
x_2 = x + 120
|
|||
|
y_1 = y - 16
|
|||
|
y_2 = y + 16
|
|||
|
ImageGrab.grab(bbox=(x_1, y_1, x_2, y_2)).save(r'temp.png')
|
|||
|
im = io.imread(r'temp.png')
|
|||
|
time.sleep(0.5)
|
|||
|
|
|||
|
# 识别验证码
|
|||
|
id_code = pytesseract.image_to_string(im, lang='eng', config='--psm 6 --oem 3 -c tessedit_char_whitelist=0123456789').strip()
|
|||
|
id_code = id_code.replace(' ', '')
|
|||
|
print('识别验证码为:', id_code)
|
|||
|
return id_code
|
|||
|
|
|||
|
# 复制数据时获取验证码
|
|||
|
def get_copy_date_verify_code(self):
|
|||
|
time.sleep(1)
|
|||
|
self._app.top_window().Static.click()
|
|||
|
time.sleep(0.2)
|
|||
|
self._app.top_window().window(control_id=0x965, class_name='Static').capture_as_image().save(
|
|||
|
r'copy.png')
|
|||
|
time.sleep(0.2)
|
|||
|
im = io.imread(r'copy.png')
|
|||
|
id_code = pytesseract.image_to_string(im, lang='eng',
|
|||
|
config='--psm 6 --oem 3 -c tessedit_char_whitelist=0123456789').strip()
|
|||
|
id_code = id_code.replace(' ', '')
|
|||
|
return id_code
|
|||
|
|
|||
|
def _close_prompt_windows(self):
|
|||
|
time.sleep(1)
|
|||
|
for window in self._app.windows(class_name="#32770"):
|
|||
|
if window.window_text() != '国信金太阳网上交易专业版V7.20':
|
|||
|
window.close()
|
|||
|
time.sleep(1)
|
|||
|
|
|||
|
# 程序退出
|
|||
|
def exit(self):
|
|||
|
self._app.kill()
|
|||
|
|
|||
|
# 交易
|
|||
|
def __trade(self, stock_no, price, amount):
|
|||
|
time.sleep(1)
|
|||
|
|
|||
|
# 设置股票代码
|
|||
|
self.main_wnd.window(control_id=0x2EE5, class_name="Edit").set_text(str(stock_no))
|
|||
|
time.sleep(0.5)
|
|||
|
|
|||
|
# 设置价格
|
|||
|
self.main_wnd.window(control_id=0x2EE6, class_name="Edit").set_text(str(price))
|
|||
|
time.sleep(0.5)
|
|||
|
|
|||
|
# 设置股数目
|
|||
|
self.main_wnd.window(control_id=0x2EE7, class_name="Edit").set_text(str(amount))
|
|||
|
time.sleep(0.5)
|
|||
|
# exit()
|
|||
|
|
|||
|
# 点击卖出or买入
|
|||
|
self.main_wnd.window(control_id=0x7DA, class_name="Button").click()
|
|||
|
time.sleep(1)
|
|||
|
# exit()
|
|||
|
|
|||
|
# 确认买入
|
|||
|
pywinauto.keyboard.send_keys("{ENTER}")
|
|||
|
time.sleep(1)
|
|||
|
|
|||
|
# 确认合同
|
|||
|
pywinauto.keyboard.send_keys("{ENTER}")
|
|||
|
time.sleep(0.5)
|
|||
|
|
|||
|
# 卖
|
|||
|
def sell(self, stock_no, price, num):
|
|||
|
path = self.left_wnd_operate_group['卖出']
|
|||
|
# 点击卖出
|
|||
|
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 buy(self, stock_no, price, num):
|
|||
|
time.sleep(1)
|
|||
|
path = self.left_wnd_operate_group['买入']
|
|||
|
# 点击买入
|
|||
|
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 cancel_entrust(self):
|
|||
|
time.sleep(0.5)
|
|||
|
|
|||
|
time.sleep(0.5)
|
|||
|
path = self.left_wnd_operate_group['撤单']
|
|||
|
# 点击撤单
|
|||
|
self.left_wnd.get_item(path, exact=False).click_input(button=u'left', double=False, wheel_dist=0, pressed=u'')
|
|||
|
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 _output_data(self, path):
|
|||
|
time.sleep(1)
|
|||
|
self.left_wnd.get_item(path, exact=False).click_input(button=u'left', double=False, wheel_dist=0, pressed=u'')
|
|||
|
time.sleep(1)
|
|||
|
# 刷新
|
|||
|
# self.main_wnd.window(control_id=0x474, class_name='Button').click()
|
|||
|
time.sleep(1)
|
|||
|
# 输出
|
|||
|
try:
|
|||
|
self.main_wnd.window(control_id=0x47F, class_name='Button').click()
|
|||
|
time.sleep(1)
|
|||
|
except Exception:
|
|||
|
print('无输出的数据!')
|
|||
|
return 0
|
|||
|
# 点击输出到Excel表格
|
|||
|
self._app['输出'].window(control_id=0xE9, class_name='Button').click()
|
|||
|
# 确认
|
|||
|
pywinauto.keyboard.send_keys("{ENTER}")
|
|||
|
time.sleep(0.5)
|
|||
|
return 1
|
|||
|
|
|||
|
# 获取未成交单
|
|||
|
def get_unsettled_trades(self):
|
|||
|
time.sleep(0.5)
|
|||
|
path = self.left_wnd_operate_group['撤单']
|
|||
|
# 导出数据
|
|||
|
result = self._output_data(path)
|
|||
|
if result == 0:
|
|||
|
self.df_unsettled = []
|
|||
|
return self.df_unsettled
|
|||
|
# 读文件
|
|||
|
self.df_unsettled = pd.read_csv(f'C:\\Users\\Administrator\\Documents\\{self.As_Of_Date} 撤单查询.xls',
|
|||
|
encoding='gbk', sep='\t', engine='python')
|
|||
|
|
|||
|
# 处理未成交单格式
|
|||
|
self.df_unsettled.rename(columns={'="证券代码"': "证券代码",
|
|||
|
'="证券名称"': "证券名称",
|
|||
|
'="买卖标志"': "买卖标志",
|
|||
|
'="委托数量"': "委托数量",
|
|||
|
'="委托价格" ': "委托价格",
|
|||
|
'="成交数量"': "成交数量",
|
|||
|
'="撤单数量"': "撤单数量",
|
|||
|
'="委托时间"': "委托时间",
|
|||
|
'="委托编号"': "委托编号",
|
|||
|
'="隔夜委托标识"': "隔夜委托标识",
|
|||
|
}, inplace=True)
|
|||
|
self.df_unsettled['证券代码'] = self.df_unsettled['证券代码'].map(lambda x: x.strip('=').strip('"'))
|
|||
|
return self.df_unsettled
|
|||
|
|
|||
|
|
|||
|
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_position(self):
|
|||
|
time.sleep(0.5)
|
|||
|
path = self.left_wnd_operate_group['资金股份']
|
|||
|
# 导出数据
|
|||
|
result = self._output_data(path)
|
|||
|
filenme = f'C:\\Users\\Administrator\\Documents\\{self.As_Of_Date} 资金股份查询.xls'
|
|||
|
self._delete_first_lines(filenme, 1)
|
|||
|
# 读文件
|
|||
|
self.df_position = pd.read_csv(filenme, encoding='gbk', sep='\t', engine='python', error_bad_lines=False)
|
|||
|
if len(self.df_position) == 0:
|
|||
|
self.df_position = []
|
|||
|
return self.df_position
|
|||
|
|
|||
|
# 处理self.df_position格式
|
|||
|
# del (self.df_position['="Unnamed: 16"'])
|
|||
|
del (self.df_position['="股份昨余"'])
|
|||
|
del (self.df_position['="今买数量"'])
|
|||
|
del (self.df_position['="买入均价"'])
|
|||
|
del (self.df_position['="股东代码"'])
|
|||
|
del (self.df_position['="持仓盈亏"'])
|
|||
|
del (self.df_position['="交易所名称"'])
|
|||
|
|
|||
|
self.df_position.rename(columns={'="证券代码"': "Ticker",
|
|||
|
'="证券名称"': "Ticker_name",
|
|||
|
'="实际数量"': "Number_transactions",
|
|||
|
'="可卖数量"': "cash",
|
|||
|
'="冻结数量"': "frozen_quantity",
|
|||
|
'="持仓成本价"': "cost_price",
|
|||
|
'="当前价"': "market_price",
|
|||
|
'="最新市值"': "market_value",
|
|||
|
'="当日盈亏"': "profit_and_loss",
|
|||
|
'="盈亏比例(%)"': "profit_loss_ratio",
|
|||
|
}, inplace=True)
|
|||
|
|
|||
|
self.df_position['Ticker'] = self.df_position['Ticker'].map(lambda x: x.strip('=').strip('"'))
|
|||
|
self.df_position['Ticker_name'] = self.df_position['Ticker_name'].map(lambda x: x.strip('=').strip('"'))
|
|||
|
self.df_position['Number_transactions'] = self.df_position['Number_transactions'].map(
|
|||
|
lambda x: str(x).strip('=').strip('"'))
|
|||
|
self.df_position['cash'] = self.df_position['cash'].map(lambda x: str(x).strip('=').strip('"'))
|
|||
|
self.df_position['profit_and_loss'] = self.df_position['profit_and_loss'].map(
|
|||
|
lambda x: str(x).strip('=').strip('"'))
|
|||
|
self.df_position['profit_loss_ratio'] = self.df_position['profit_loss_ratio'].map(
|
|||
|
lambda x: str(x).strip('=').strip('"'))
|
|||
|
self.df_position['market_value'] = self.df_position['market_value'].map(lambda x: str(x).strip('=').strip('"'))
|
|||
|
self.df_position = self.df_position.loc[:, ~self.df_position.columns.str.contains("^Unnamed")]
|
|||
|
print('=============================================')
|
|||
|
return self.df_position
|
|||
|
|
|||
|
# 获取资金情况
|
|||
|
def get_balance(self):
|
|||
|
time.sleep(0.5)
|
|||
|
path = self.left_wnd_operate_group['资金股份']
|
|||
|
# 点击资金股份
|
|||
|
self.left_wnd.get_item(path, exact=False).click_input(button=u'left', double=False, wheel_dist=0, pressed=u'')
|
|||
|
time.sleep(1)
|
|||
|
# 获取资金
|
|||
|
balance_text = self.main_wnd.window(control_id=0x628, class_name='Static').window_text()
|
|||
|
print(balance_text)
|
|||
|
balance_text = balance_text.strip(' ')
|
|||
|
balance_text = balance_text.split(' ')
|
|||
|
|
|||
|
result_2 = {}
|
|||
|
result = {}
|
|||
|
for i in balance_text:
|
|||
|
i_dict = i.split(':')
|
|||
|
k = i_dict[0]
|
|||
|
v = i_dict[1]
|
|||
|
result_2[k] = v
|
|||
|
result['可用金额'] = result_2['可用']
|
|||
|
result['股票市值'] = result_2['参考市值']
|
|||
|
result['总资产'] = result_2['资产']
|
|||
|
print('=============================================')
|
|||
|
return result
|
|||
|
|
|||
|
# 获取委托单
|
|||
|
def get_order(self):
|
|||
|
time.sleep(0.5)
|
|||
|
path = self.left_wnd_operate_group['当日委托']
|
|||
|
# 导出数据
|
|||
|
result = self._output_data(path)
|
|||
|
if result == 0:
|
|||
|
self.df = []
|
|||
|
return self.df
|
|||
|
# 读文件
|
|||
|
self.df = pd.read_csv(f'C:\\Users\\Administrator\\Documents\\{self.As_Of_Date} 当日委托查询.xls',
|
|||
|
encoding='gbk', sep='\t', engine='python', error_bad_lines=False)
|
|||
|
# print(self.df)
|
|||
|
|
|||
|
# 处理委托单格式
|
|||
|
self.df.rename(columns={'="证券代码"': "证券代码",
|
|||
|
'="证券名称"': "证券名称",
|
|||
|
'="买卖标志"': "买卖标志",
|
|||
|
'="委托数量"': "委托数量",
|
|||
|
'="委托价格" ': "委托价格",
|
|||
|
'="成交数量"': "成交数量",
|
|||
|
'="撤单数量"': "撤单数量",
|
|||
|
'="委托时间"': "委托时间",
|
|||
|
'="委托编号"': "委托编号",
|
|||
|
'="隔夜委托标识"': "隔夜委托标识",
|
|||
|
}, inplace=True)
|
|||
|
self.df['证券代码'] = self.df['证券代码'].map(lambda x: x.strip('=').strip('"'))
|
|||
|
print('=============================================')
|
|||
|
return self.df
|
|||
|
|
|||
|
# 获取当日成交
|
|||
|
def trade_record(self):
|
|||
|
time.sleep(1)
|
|||
|
path = self.left_wnd_operate_group['当日成交']
|
|||
|
# 导出数据
|
|||
|
result = self._output_data(path)
|
|||
|
if result == 0:
|
|||
|
self.df = []
|
|||
|
return self.df
|
|||
|
# 读文件
|
|||
|
self.df = pd.read_csv(f'C:\\Users\\Administrator\\Documents\\{self.As_Of_Date} 当日成交查询.xls',
|
|||
|
encoding='gbk', sep='\t', engine='python', error_bad_lines=False)
|
|||
|
return self.df
|
|||
|
|
|||
|
# 当日交易记录入库
|
|||
|
def save_trades_sql(self):
|
|||
|
self.trade_record()
|
|||
|
if len(self.df) == 0:
|
|||
|
print('无当日成交---------------------')
|
|||
|
|
|||
|
else:
|
|||
|
# 处理当日成交入库格式
|
|||
|
import datetime
|
|||
|
self.df['As_Of_Date'] = datetime.date.today()
|
|||
|
self.df['Account_name'] = self.account_name
|
|||
|
self.df.rename(columns={'="证券代码"': "证券代码", '="证券名称"': "证券名称",
|
|||
|
'="买卖标志"': "买卖标志", '="成交数量"': "成交数量",
|
|||
|
'="成交价格"': "成交价格", '="成交金额"': "成交金额",
|
|||
|
'="成交编号"': "成交编号", '="成交时间"': "成交时间",
|
|||
|
}, inplace=True)
|
|||
|
self.df['证券名称'] = self.df['证券名称'].map(lambda x: str(x).strip('=').strip('"'))
|
|||
|
self.df['证券代码'] = self.df['证券代码'].map(lambda x: str(x).strip('=').strip('"'))
|
|||
|
self.df['成交金额'] = self.df['成交金额'].apply(float)
|
|||
|
self.df.rename(
|
|||
|
columns={'证券代码': 'Ticker', '证券名称': 'Ticker_name',
|
|||
|
'买卖标志': 'Operate', '成交数量': 'Number_transactions',
|
|||
|
'成交均价': 'Average_price'}, inplace=True)
|
|||
|
|
|||
|
def bu(x):
|
|||
|
x = str(x)
|
|||
|
if len(x) < 6:
|
|||
|
num = 6 - len(x)
|
|||
|
ticker = "0" * num + x
|
|||
|
else:
|
|||
|
ticker = x
|
|||
|
return ticker
|
|||
|
|
|||
|
self.df['Ticker'] = self.df['Ticker'].apply(bu)
|
|||
|
self.df['Operate'] = self.df['Operate'].apply(lambda x: '买' if x == '="限价买入"' else '卖')
|
|||
|
df_num = self.df.groupby(['Ticker', 'Operate'])['Number_transactions'].sum().reset_index()
|
|||
|
df_mean = self.df.groupby(['Ticker', 'Operate'])['成交金额'].sum().reset_index()
|
|||
|
|
|||
|
del self.df['Number_transactions']
|
|||
|
del self.df['成交金额']
|
|||
|
self.df = pd.merge(self.df, df_num)
|
|||
|
self.df = pd.merge(self.df, df_mean)
|
|||
|
self.df['Average_price'] = self.df['成交金额'] / self.df['Number_transactions']
|
|||
|
|
|||
|
del (self.df['="摘要"'])
|
|||
|
del (self.df['="委托编号"'])
|
|||
|
del (self.df['="交易所名称"'])
|
|||
|
del (self.df['="备注"'])
|
|||
|
del (self.df['Unnamed: 13'])
|
|||
|
del (self.df['="股东代码"'])
|
|||
|
del (self.df['成交编号'])
|
|||
|
del self.df['成交时间']
|
|||
|
del self.df['成交金额']
|
|||
|
self.df.drop_duplicates(subset=['Ticker', 'Ticker_name', 'Operate'], inplace=True)
|
|||
|
self.df['Number_transactions'] = self.df['Number_transactions'].apply(abs)
|
|||
|
|
|||
|
def fuc(x):
|
|||
|
if str(x).startswith('6'):
|
|||
|
x = 'SH' + str(x)
|
|||
|
elif str(x).startswith('0') or str(x).startswith('159'):
|
|||
|
x = 'SZ' + str(x)
|
|||
|
else:
|
|||
|
x = x
|
|||
|
return x
|
|||
|
|
|||
|
self.df['Ticker'] = self.df['Ticker'].apply(fuc)
|
|||
|
self.df = self.df[self.df['Average_price'] != 0.0]
|
|||
|
|
|||
|
# 入库
|
|||
|
try:
|
|||
|
return self.df
|
|||
|
# engine_auto_update_web_strategy = create_engine(
|
|||
|
# 'mysql+pymysql://cn_ainvest_db:cn_ainvest_sd3a1@rm-2zewagytttzk6f24xno.mysql.rds.aliyuncs.com:3306/auto_update_web_strategy',
|
|||
|
# encoding="utf-8", echo=False)
|
|||
|
# self.df.to_sql('daily_transaction_record', engine_auto_update_web_strategy, if_exists='append',
|
|||
|
# index=False, chunksize=1000)
|
|||
|
print('=======================')
|
|||
|
print('入库表:\n', self.df)
|
|||
|
print(self.account_name, "的当日成交入库成功!")
|
|||
|
print('------------------------------------------------')
|
|||
|
except Exception as e:
|
|||
|
print(self.account_name, "的当日成交入库失败!!!!!!!!!!!!!!!!!!!!!!!!!!")
|
|||
|
print('------------------------------------------------')
|
|||
|
|
|||
|
# 交易记录存表
|
|||
|
def save_trade_table(self):
|
|||
|
self.trade_record()
|
|||
|
if len(self.df) == 0:
|
|||
|
return
|
|||
|
else:
|
|||
|
# 设置交易记录存表格式
|
|||
|
self.df.rename(columns={'="证券代码"': "证券代码", '="证券名称"': "证券名称",
|
|||
|
'="买卖标志"': "买卖标志", '="成交数量"': "成交数量",
|
|||
|
'="成交价格"': "成交价格", '="成交金额"': "成交金额",
|
|||
|
'="成交编号"': "成交编号", '="成交时间"': "成交时间",
|
|||
|
'="交易所名称"': "交易所名称", '="摘要"': "摘要",
|
|||
|
'="委托编号"': "委托编号", '="股东代码"': "股东代码",
|
|||
|
'="股东代码"': "股东代码", '="备注"': "备注",
|
|||
|
}, inplace=True)
|
|||
|
self.df['证券名称'] = self.df['证券名称'].map(lambda x: str(x).strip('=').strip('"'))
|
|||
|
self.df['买卖标志'] = self.df['买卖标志'].map(lambda x: str(x).strip('=').strip('"'))
|
|||
|
self.df['摘要'] = self.df['摘要'].map(lambda x: str(x).strip('=').strip('"'))
|
|||
|
self.df['委托编号'] = self.df['委托编号'].map(lambda x: str(x).strip('=').strip('"'))
|
|||
|
self.df['成交编号'] = self.df['成交编号'].map(lambda x: str(x).strip('=').strip('"'))
|
|||
|
self.df['成交时间'] = self.df['成交时间'].map(lambda x: str(x).strip('=').strip('"'))
|
|||
|
self.df['股东代码'] = self.df['股东代码'].map(lambda x: str(x).strip('=').strip('"'))
|
|||
|
self.df['证券代码'] = self.df['证券代码'].map(lambda x: str(x).strip('=').strip('"'))
|
|||
|
self.df['交易所名称'] = self.df['交易所名称'].map(lambda x: str(x).strip('=').strip('"'))
|
|||
|
# 获取当日成交
|
|||
|
print(self.df)
|
|||
|
As_Of_Date = datetime.datetime.today().strftime('%Y%m%d')
|
|||
|
As_Of_Date = As_Of_Date[-4:]
|
|||
|
df_trade = self._get_df_trade()
|
|||
|
print(df_trade)
|
|||
|
# pc_name111 = getpass.getuser() # 返回用户名
|
|||
|
# df_trade = pd.read_excel(f'C:\\Users\\{pc_name111}\\Desktop\\{self.today}_股票交易列表.xls')
|
|||
|
df_trade['用户名'] = df_trade['用户名'].map(lambda x: str(x))
|
|||
|
df_user = df_trade[df_trade['用户名'].isin([self.account_name])]
|
|||
|
df_user = df_user.drop_duplicates('股票代码')
|
|||
|
df_user['股票代码'] = df_user['股票代码'].map(lambda x: str(x).strip('SH').strip('SZ'))
|
|||
|
strategy_ticker_list = df_user['股票代码'].tolist()
|
|||
|
self.df['证券代码'] = self.df['证券代码'].map(lambda x: str(x))
|
|||
|
self.df['备注'] = '客户操作'
|
|||
|
self.df.loc[self.df['证券代码'].isin(strategy_ticker_list), '备注'] = '策略选股'
|
|||
|
self.df = self.df.loc[:, ~self.df.columns.str.contains("^Unnamed")]
|
|||
|
print('=======================')
|
|||
|
print('本地存表:\n', self.df)
|
|||
|
return self.df
|
|||
|
# self.df.to_excel(f'C:\\Users\\{pc_name111}\\Desktop\\{self.account_name}_{As_Of_Date}.xls')
|
|||
|
# self.df.to_excel(f'C:\\Users\\{pc_name111}\\Desktop\\{As_Of_Date}_交易记录\\{self.account_name}_{As_Of_Date}.xls')
|
|||
|
# self.df.to_excel(f'F:\\AINVEST\\works\\trade_records\\{user}_{today}.xls', encoding='utf-8', index=False)
|
|||
|
print('存表成功')
|
|||
|
|
|||
|
# 读取交易指令表
|
|||
|
def _get_df_trade(self):
|
|||
|
engine_user_center = create_engine(
|
|||
|
'mysql+pymysql://cn_ainvest_db:cn_ainvest_sd3a1@rm-2zewagytttzk6f24xno.mysql.rds.aliyuncs.com:3306/user_center',
|
|||
|
encoding="utf-8", echo=False)
|
|||
|
today = str(datetime.date.today())
|
|||
|
df_trade = pd.read_sql(f'select * from trade_instruction where As_Of_Date = "{today}"', engine_user_center)
|
|||
|
return df_trade
|
|||
|
|
|||
|
# 解析合同
|
|||
|
@staticmethod
|
|||
|
def __parse_contract(result):
|
|||
|
""" 解析买入卖出的结果 """
|
|||
|
|
|||
|
# 股东帐号:A217477596
|
|||
|
# 证券代码:600000
|
|||
|
# 买入价格:3.330
|
|||
|
# 买入数量:100
|
|||
|
result_list = result.split('\n')
|
|||
|
for i in result_list[:-1]:
|
|||
|
print(i, end=', ')
|
|||
|
|
|||
|
|
|||
|
if __name__ == '__main__':
|
|||
|
account_name = str('13700579177')
|
|||
|
user_main = HLClientTrader(account_name)
|
|||
|
user_main.login()
|
|||
|
|
|||
|
# 买入
|
|||
|
# a.buy('600000', '10.67','100')
|
|||
|
|
|||
|
# 卖出
|
|||
|
# a.sell('600000', '10.67','100')
|
|||
|
|
|||
|
# 全撤单
|
|||
|
# a.cancel_entrust()
|
|||
|
|
|||
|
# 获取未成交单
|
|||
|
# print('未成交单:\n', a.get_unsettled_trades())
|
|||
|
|
|||
|
# 获取当日实际持仓
|
|||
|
# print('当日实际持仓:\n', a.get_position())
|
|||
|
|
|||
|
# 获取资金情况
|
|||
|
# print('当日资金情况:\n', a.get_balance())
|
|||
|
|
|||
|
# 获取委托单
|
|||
|
# print('委托单:\n',a.get_order())
|
|||
|
|
|||
|
# 获取当日成交
|
|||
|
# print('当日成交情况:\n', a.trade_record())
|
|||
|
#
|
|||
|
# 交易记录入库
|
|||
|
# a.save_trades_sql()
|
|||
|
|
|||
|
# 交易记录存表
|
|||
|
# a.save_trade_table()
|
|||
|
|