xinxin
This commit is contained in:
parent
c1325e1396
commit
0010be1b6b
BIN
__pycache__/config.cpython-312.pyc
Normal file
BIN
__pycache__/config.cpython-312.pyc
Normal file
Binary file not shown.
Binary file not shown.
BIN
autobasic/__pycache__/dw_clienttrader.cpython-312.pyc
Normal file
BIN
autobasic/__pycache__/dw_clienttrader.cpython-312.pyc
Normal file
Binary file not shown.
@ -24,7 +24,7 @@ path = os.path.join(root_path,'broker_xiadan','东吴证券金融终端独立下
|
|||||||
global engine
|
global engine
|
||||||
engine = create_engine(
|
engine = create_engine(
|
||||||
'mysql+pymysql://cn_ainvest_db:cn_ainvest_sd3a1@rm-2zewagytttzk6f24xno.mysql.rds.aliyuncs.com:3306/',
|
'mysql+pymysql://cn_ainvest_db:cn_ainvest_sd3a1@rm-2zewagytttzk6f24xno.mysql.rds.aliyuncs.com:3306/',
|
||||||
encoding="utf-8", echo=False)
|
echo=False)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -37,7 +37,13 @@ class DongWuClientTrader:
|
|||||||
|
|
||||||
self.path = exe_path
|
self.path = exe_path
|
||||||
self.account_name = account_name
|
self.account_name = account_name
|
||||||
self.log = Logger(f'{root_path}/logs',self.account_name)
|
|
||||||
|
# 确保logs目录存在
|
||||||
|
logs_dir = root_path / 'logs'
|
||||||
|
logs_dir.mkdir(exist_ok=True)
|
||||||
|
|
||||||
|
# 初始化日志系统
|
||||||
|
self._setup_logging()
|
||||||
|
|
||||||
# 用户券商信息
|
# 用户券商信息
|
||||||
sql = f"select * from ainvest_usercount where username='{account_name}'"
|
sql = f"select * from ainvest_usercount where username='{account_name}'"
|
||||||
@ -46,6 +52,42 @@ class DongWuClientTrader:
|
|||||||
self.securities_password = str(df_count['securities_password'].tolist()[0])
|
self.securities_password = str(df_count['securities_password'].tolist()[0])
|
||||||
self.communication_password = str(df_count['communication_password'].tolist()[0])
|
self.communication_password = str(df_count['communication_password'].tolist()[0])
|
||||||
|
|
||||||
|
def _setup_logging(self):
|
||||||
|
"""设置日志系统"""
|
||||||
|
import logging
|
||||||
|
import os
|
||||||
|
|
||||||
|
# 获取当前模块的logger
|
||||||
|
self.logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
# 为当前账户添加文件处理器,记录到logs目录
|
||||||
|
logs_file = os.path.join(root_path, 'logs', f'{self.account_name}.log')
|
||||||
|
|
||||||
|
# 检查是否已经有针对这个账户的处理器,避免重复添加
|
||||||
|
account_handler_exists = False
|
||||||
|
for handler in self.logger.handlers:
|
||||||
|
if hasattr(handler, 'baseFilename') and handler.baseFilename == os.path.abspath(logs_file):
|
||||||
|
account_handler_exists = True
|
||||||
|
break
|
||||||
|
|
||||||
|
if not account_handler_exists:
|
||||||
|
formatter = logging.Formatter('[%(asctime)s] [%(levelname)s] %(message)s', '%Y-%m-%d %H:%M:%S')
|
||||||
|
file_handler = logging.FileHandler(logs_file, encoding='utf-8')
|
||||||
|
file_handler.setFormatter(formatter)
|
||||||
|
file_handler.setLevel(logging.DEBUG)
|
||||||
|
self.logger.addHandler(file_handler)
|
||||||
|
|
||||||
|
# 如果根logger没有处理器(单独运行时),添加控制台处理器
|
||||||
|
root_logger = logging.getLogger()
|
||||||
|
if not root_logger.handlers:
|
||||||
|
console_handler = logging.StreamHandler()
|
||||||
|
console_handler.setFormatter(logging.Formatter('[%(asctime)s] [%(levelname)s] %(message)s', '%Y-%m-%d %H:%M:%S'))
|
||||||
|
console_handler.setLevel(logging.INFO)
|
||||||
|
self.logger.addHandler(console_handler)
|
||||||
|
|
||||||
|
# 设置logger级别
|
||||||
|
self.logger.setLevel(logging.DEBUG)
|
||||||
|
|
||||||
def exit(self):
|
def exit(self):
|
||||||
'''
|
'''
|
||||||
结束进程
|
结束进程
|
||||||
@ -74,12 +116,12 @@ class DongWuClientTrader:
|
|||||||
path=self.path, timeout=1
|
path=self.path, timeout=1
|
||||||
)
|
)
|
||||||
self.exit()
|
self.exit()
|
||||||
self.log.warn('There are running programs, and there are processes in retreat')
|
self.logger.warning('There are running programs, and there are processes in retreat')
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
#启动软件进程,输入账号密码
|
#启动软件进程,输入账号密码
|
||||||
self.log.info('Start login')
|
self.logger.info('Start login')
|
||||||
start_time = time.time()
|
start_time = time.time()
|
||||||
|
|
||||||
# 重置mac
|
# 重置mac
|
||||||
@ -96,12 +138,12 @@ class DongWuClientTrader:
|
|||||||
item = get_ip_data() #获取动态IP
|
item = get_ip_data() #获取动态IP
|
||||||
if item['ip'] in used_ip:
|
if item['ip'] in used_ip:
|
||||||
get_ip_times += 1
|
get_ip_times += 1
|
||||||
self.log.warn(f'代理IP重复,重新获取IP')
|
self.logger.warning(f'代理IP重复,重新获取IP')
|
||||||
else:
|
else:
|
||||||
self.log.info(f'代理IP已经获取{item}')
|
self.logger.info(f'代理IP已经获取{item}')
|
||||||
break
|
break
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.log.error(f'获取IP失败,请检查网络连接{e}')
|
self.logger.error(f'获取IP失败,请检查网络连接{e}')
|
||||||
time.sleep(5)
|
time.sleep(5)
|
||||||
# raise ConnectionError(f"获取IP失败,请检查网络连接。错误详情: {e}")
|
# raise ConnectionError(f"获取IP失败,请检查网络连接。错误详情: {e}")
|
||||||
|
|
||||||
@ -113,7 +155,7 @@ class DongWuClientTrader:
|
|||||||
|
|
||||||
# exit_ip = get_proxy_ip(proxy_ip,proxy_port)
|
# exit_ip = get_proxy_ip(proxy_ip,proxy_port)
|
||||||
time_with_change_proxy = time.time()-start_time
|
time_with_change_proxy = time.time()-start_time
|
||||||
self.log.info('全局代理设置成功')
|
self.logger.info('全局代理设置成功')
|
||||||
|
|
||||||
insert_data= {'as_of_date':datetime.datetime.fromtimestamp(start_time).strftime('%Y-%m-%d %H:%M:%S.%f'),
|
insert_data= {'as_of_date':datetime.datetime.fromtimestamp(start_time).strftime('%Y-%m-%d %H:%M:%S.%f'),
|
||||||
'broker':broker,
|
'broker':broker,
|
||||||
@ -328,7 +370,7 @@ class DongWuClientTrader:
|
|||||||
one_text = self._app.window(control_id=0x0, class_name='#32770').window(control_id=0x410,
|
one_text = self._app.window(control_id=0x0, class_name='#32770').window(control_id=0x410,
|
||||||
class_name='Static').window_text()
|
class_name='Static').window_text()
|
||||||
# 摘取合同信息
|
# 摘取合同信息
|
||||||
self.log.info(one_text.replace('/n', ' '))
|
self.logger.info(one_text.replace('/n', ' '))
|
||||||
time.sleep(0.2)
|
time.sleep(0.2)
|
||||||
# 确认申购委托
|
# 确认申购委托
|
||||||
self._app.window(control_id=0x0, class_name="#32770", found_index=0).window(control_id=0x6,
|
self._app.window(control_id=0x0, class_name="#32770", found_index=0).window(control_id=0x6,
|
||||||
@ -337,7 +379,7 @@ class DongWuClientTrader:
|
|||||||
# self._app.top_window().set_focus()
|
# self._app.top_window().set_focus()
|
||||||
one_text = self._app.window(control_id=0x0, class_name='#32770').window(control_id=0x3EC,
|
one_text = self._app.window(control_id=0x0, class_name='#32770').window(control_id=0x3EC,
|
||||||
class_name='Static').window_text()
|
class_name='Static').window_text()
|
||||||
self.log.info(one_text.replace('/n', ' '))
|
self.logger.info(one_text.replace('/n', ' '))
|
||||||
time.sleep(0.2)
|
time.sleep(0.2)
|
||||||
self._app.window(control_id=0x0, class_name="#32770", found_index=0).window(control_id=0x2,
|
self._app.window(control_id=0x0, class_name="#32770", found_index=0).window(control_id=0x2,
|
||||||
class_name='Button').click()
|
class_name='Button').click()
|
||||||
@ -379,7 +421,7 @@ class DongWuClientTrader:
|
|||||||
|
|
||||||
#获取弹窗信息
|
#获取弹窗信息
|
||||||
result = self._app.top_window().window(control_id=0x3EC, class_name='Static').window_text()
|
result = self._app.top_window().window(control_id=0x3EC, class_name='Static').window_text()
|
||||||
self.log.info(result)
|
self.logger.info(result)
|
||||||
pywinauto.keyboard.send_keys("{ENTER}")
|
pywinauto.keyboard.send_keys("{ENTER}")
|
||||||
time.sleep(0.2)
|
time.sleep(0.2)
|
||||||
pywinauto.keyboard.send_keys("{ESC}")
|
pywinauto.keyboard.send_keys("{ESC}")
|
||||||
@ -470,7 +512,7 @@ class DongWuClientTrader:
|
|||||||
self._copy_data()
|
self._copy_data()
|
||||||
df_position = self._data_to_df()
|
df_position = self._data_to_df()
|
||||||
if len(df_position) == 0:
|
if len(df_position) == 0:
|
||||||
self.log.info('--------------------------------------无当日持仓--------------------------------------')
|
self.logger.info('--------------------------------------无当日持仓--------------------------------------')
|
||||||
return pd.DataFrame()
|
return pd.DataFrame()
|
||||||
df_position['证券代码'] = df_position['证券代码'].apply(lambda x: tranTicker(str(x).replace('="', '').replace('"', '')))
|
df_position['证券代码'] = df_position['证券代码'].apply(lambda x: tranTicker(str(x).replace('="', '').replace('"', '')))
|
||||||
df_position = df_position[['证券代码','证券名称','股票余额','可用余额','冻结数量','成本价','市价','市值','盈亏','盈亏比例(%)']]
|
df_position = df_position[['证券代码','证券名称','股票余额','可用余额','冻结数量','成本价','市价','市值','盈亏','盈亏比例(%)']]
|
||||||
@ -508,7 +550,7 @@ class DongWuClientTrader:
|
|||||||
self._copy_data()
|
self._copy_data()
|
||||||
df = self._data_to_df()
|
df = self._data_to_df()
|
||||||
if len(df) == 0:
|
if len(df) == 0:
|
||||||
self.log.info('--------------------------------------无当日委托--------------------------------------')
|
self.logger.info('--------------------------------------无当日委托--------------------------------------')
|
||||||
return pd.DataFrame()
|
return pd.DataFrame()
|
||||||
else:
|
else:
|
||||||
df = df[['委托时间', '证券代码', '证券名称', '操作', '委托价格', '委托数量', '成交数量', '成交均价', '股票成交金额']]
|
df = df[['委托时间', '证券代码', '证券名称', '操作', '委托价格', '委托数量', '成交数量', '成交均价', '股票成交金额']]
|
||||||
@ -544,7 +586,7 @@ class DongWuClientTrader:
|
|||||||
self._copy_data()
|
self._copy_data()
|
||||||
df = self._data_to_df()
|
df = self._data_to_df()
|
||||||
if len(df) == 0:
|
if len(df) == 0:
|
||||||
self.log.info('--------------------------------------无当日成交--------------------------------------')
|
self.logger.info('--------------------------------------无当日成交--------------------------------------')
|
||||||
return pd.DataFrame()
|
return pd.DataFrame()
|
||||||
else:
|
else:
|
||||||
df = df[['成交时间','证券代码','证券名称','操作','成交数量','成交均价']]
|
df = df[['成交时间','证券代码','证券名称','操作','成交数量','成交均价']]
|
||||||
@ -603,8 +645,8 @@ class DongWuClientTrader:
|
|||||||
# one_text = self._app.top_window().window(control_id=0x410, class_name='Static').window_text()
|
# one_text = self._app.top_window().window(control_id=0x410, class_name='Static').window_text()
|
||||||
|
|
||||||
if '委托价格的小数部分应该为2位' in one_text:
|
if '委托价格的小数部分应该为2位' in one_text:
|
||||||
# 点击“否”
|
# 点击"否"
|
||||||
self.log.warn(one_text.replace('/n',' '))
|
self.logger.warning(one_text.replace('/n',' '))
|
||||||
self._app.top_window().window(control_id=0x7, class_name='Button').click()
|
self._app.top_window().window(control_id=0x7, class_name='Button').click()
|
||||||
# 保留两位小数截断
|
# 保留两位小数截断
|
||||||
price = str(price)[:-1]
|
price = str(price)[:-1]
|
||||||
@ -618,7 +660,7 @@ class DongWuClientTrader:
|
|||||||
one_text = self._app.top_window().window(control_id=0x410, class_name='Static').window_text()
|
one_text = self._app.top_window().window(control_id=0x410, class_name='Static').window_text()
|
||||||
else:
|
else:
|
||||||
# 摘取合同信息
|
# 摘取合同信息
|
||||||
self.log.info(one_text.replace('/n',' '))
|
self.logger.info(one_text.replace('/n',' '))
|
||||||
time.sleep(0.2)
|
time.sleep(0.2)
|
||||||
|
|
||||||
# 确认买入
|
# 确认买入
|
||||||
@ -634,7 +676,7 @@ class DongWuClientTrader:
|
|||||||
class_name='Static').window_text()
|
class_name='Static').window_text()
|
||||||
# self._app.top_window().set_focus()
|
# self._app.top_window().set_focus()
|
||||||
# one_text2 = self._app.top_window().window(control_id=0x3EC, class_name='Static').window_text()
|
# one_text2 = self._app.top_window().window(control_id=0x3EC, class_name='Static').window_text()
|
||||||
self.log.info(one_text2.replace('/n', ' '))
|
self.logger.info(one_text2.replace('/n', ' '))
|
||||||
time.sleep(0.5)
|
time.sleep(0.5)
|
||||||
# 确认合同
|
# 确认合同
|
||||||
# self._app.top_window().set_focus()
|
# self._app.top_window().set_focus()
|
||||||
@ -668,9 +710,9 @@ class DongWuClientTrader:
|
|||||||
try:
|
try:
|
||||||
self._app.top_window().set_focus()
|
self._app.top_window().set_focus()
|
||||||
result_idcode = self._app.top_window().window(control_id=0x966, class_name='Static').window_text()
|
result_idcode = self._app.top_window().window(control_id=0x966, class_name='Static').window_text()
|
||||||
self.log.softInfo(result_idcode)
|
self.logger.info(result_idcode)
|
||||||
if '验证码错误' in result_idcode:
|
if '验证码错误' in result_idcode:
|
||||||
self.log.warn('Verification code error')
|
self.logger.warning('Verification code error')
|
||||||
self._app.top_window().window(control_id=0x2, class_name="Button").click()
|
self._app.top_window().window(control_id=0x2, class_name="Button").click()
|
||||||
time.sleep(0.5)
|
time.sleep(0.5)
|
||||||
else:
|
else:
|
||||||
|
@ -1,107 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
"""
|
|
||||||
定时执行 init_proxy.py 脚本
|
|
||||||
每整十分钟执行一次(00、10、20、30、40、50分)
|
|
||||||
"""
|
|
||||||
|
|
||||||
import time
|
|
||||||
import datetime
|
|
||||||
import subprocess
|
|
||||||
import sys
|
|
||||||
import os
|
|
||||||
import logging
|
|
||||||
from pathlib import Path
|
|
||||||
|
|
||||||
# 设置日志
|
|
||||||
logging.basicConfig(
|
|
||||||
level=logging.INFO,
|
|
||||||
format='%(asctime)s - %(levelname)s - %(message)s',
|
|
||||||
handlers=[
|
|
||||||
logging.FileHandler('scheduler_init_proxy.log', encoding='utf-8'),
|
|
||||||
logging.StreamHandler()
|
|
||||||
]
|
|
||||||
)
|
|
||||||
logger = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
def execute_init_proxy():
|
|
||||||
"""执行 init_proxy.py 脚本"""
|
|
||||||
try:
|
|
||||||
script_path = Path(__file__).parent / "init_proxy.py"
|
|
||||||
if not script_path.exists():
|
|
||||||
logger.error(f"脚本文件不存在: {script_path}")
|
|
||||||
return False
|
|
||||||
|
|
||||||
# 使用当前 Python 解释器执行脚本 - 兼容老版本Python
|
|
||||||
result = subprocess.run(
|
|
||||||
[sys.executable, str(script_path)],
|
|
||||||
stdout=subprocess.PIPE,
|
|
||||||
stderr=subprocess.PIPE,
|
|
||||||
universal_newlines=True
|
|
||||||
)
|
|
||||||
|
|
||||||
if result.returncode == 0:
|
|
||||||
logger.info("init_proxy.py 执行成功")
|
|
||||||
if result.stdout and result.stdout.strip():
|
|
||||||
logger.info(f"输出: {result.stdout.strip()}")
|
|
||||||
else:
|
|
||||||
logger.error(f"init_proxy.py 执行失败,返回码: {result.returncode}")
|
|
||||||
if result.stderr and result.stderr.strip():
|
|
||||||
logger.error(f"错误信息: {result.stderr.strip()}")
|
|
||||||
|
|
||||||
return result.returncode == 0
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
logger.error(f"执行 init_proxy.py 时发生异常: {e}")
|
|
||||||
return False
|
|
||||||
|
|
||||||
def wait_for_next_execution():
|
|
||||||
"""等待到下一个整十分钟"""
|
|
||||||
now = datetime.datetime.now()
|
|
||||||
current_minute = now.minute
|
|
||||||
|
|
||||||
# 计算下一个整十分钟
|
|
||||||
next_minute = ((current_minute // 10) + 1) * 10
|
|
||||||
|
|
||||||
# 处理小时进位
|
|
||||||
if next_minute >= 60:
|
|
||||||
next_minute = 0
|
|
||||||
next_execution = now.replace(minute=0, second=0, microsecond=0) + datetime.timedelta(hours=1)
|
|
||||||
else:
|
|
||||||
next_execution = now.replace(minute=next_minute, second=0, microsecond=0)
|
|
||||||
|
|
||||||
wait_seconds = (next_execution - now).total_seconds()
|
|
||||||
logger.info(f"当前时间: {now.strftime('%Y-%m-%d %H:%M:%S')}")
|
|
||||||
logger.info(f"下次执行时间: {next_execution.strftime('%Y-%m-%d %H:%M:%S')}")
|
|
||||||
logger.info(f"等待 {wait_seconds:.0f} 秒")
|
|
||||||
|
|
||||||
return wait_seconds
|
|
||||||
|
|
||||||
def main():
|
|
||||||
"""主函数"""
|
|
||||||
logger.info("代理重置定时器启动")
|
|
||||||
logger.info("脚本将在每整十分钟执行一次 init_proxy.py")
|
|
||||||
|
|
||||||
# 首次执行
|
|
||||||
logger.info("执行首次代理重置...")
|
|
||||||
execute_init_proxy()
|
|
||||||
|
|
||||||
# 定时循环
|
|
||||||
while True:
|
|
||||||
try:
|
|
||||||
wait_seconds = wait_for_next_execution()
|
|
||||||
time.sleep(wait_seconds)
|
|
||||||
|
|
||||||
logger.info("开始执行定时任务...")
|
|
||||||
execute_init_proxy()
|
|
||||||
|
|
||||||
except KeyboardInterrupt:
|
|
||||||
logger.info("接收到中断信号,程序退出")
|
|
||||||
break
|
|
||||||
except Exception as e:
|
|
||||||
logger.error(f"定时器运行异常: {e}")
|
|
||||||
# 发生异常时等待60秒后继续
|
|
||||||
time.sleep(60)
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
main()
|
|
32
tools.py
32
tools.py
@ -633,46 +633,60 @@ class Logger():
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, path, name, Flevel=logging.DEBUG):
|
def __init__(self, path, name, Flevel=logging.DEBUG):
|
||||||
|
import os
|
||||||
|
# 确保日志目录存在
|
||||||
|
os.makedirs(path, exist_ok=True)
|
||||||
|
|
||||||
self.time = time.strftime("%Y-%m-%d")
|
self.time = time.strftime("%Y-%m-%d")
|
||||||
self.fileName = path + '/' + name + ".log"
|
self.fileName = os.path.join(path, name + ".log")
|
||||||
self.logger = logging.getLogger(self.fileName)
|
|
||||||
|
# 为每个实例创建唯一的logger名称,避免重复
|
||||||
|
logger_name = f"{name}_{id(self)}"
|
||||||
|
self.logger = logging.getLogger(logger_name)
|
||||||
self.logger.setLevel(Flevel)
|
self.logger.setLevel(Flevel)
|
||||||
if not self.logger.handlers:
|
|
||||||
|
# 清除已有的处理器,避免重复
|
||||||
|
self.logger.handlers.clear()
|
||||||
|
|
||||||
|
# 设置格式
|
||||||
fmt = logging.Formatter('[%(asctime)s] [%(levelname)s] %(message)s', '%Y-%m-%d %H:%M:%S')
|
fmt = logging.Formatter('[%(asctime)s] [%(levelname)s] %(message)s', '%Y-%m-%d %H:%M:%S')
|
||||||
|
|
||||||
|
# 文件处理器
|
||||||
fh = logging.FileHandler(self.fileName, encoding='utf-8')
|
fh = logging.FileHandler(self.fileName, encoding='utf-8')
|
||||||
fh.setFormatter(fmt)
|
fh.setFormatter(fmt)
|
||||||
fh.setLevel(Flevel)
|
fh.setLevel(Flevel)
|
||||||
self.logger.addHandler(fh)
|
self.logger.addHandler(fh)
|
||||||
|
|
||||||
@output
|
# 控制台处理器
|
||||||
|
ch = logging.StreamHandler()
|
||||||
|
ch.setFormatter(fmt)
|
||||||
|
ch.setLevel(logging.INFO)
|
||||||
|
self.logger.addHandler(ch)
|
||||||
|
|
||||||
def debug(self, message):
|
def debug(self, message):
|
||||||
"""
|
"""
|
||||||
This is debug
|
This is debug
|
||||||
"""
|
"""
|
||||||
self.logger.debug(message)
|
self.logger.debug(message)
|
||||||
|
|
||||||
@output
|
|
||||||
def info(self, message):
|
def info(self, message):
|
||||||
"""
|
"""
|
||||||
This is info
|
This is info
|
||||||
"""
|
"""
|
||||||
self.logger.info(message)
|
self.logger.info(message)
|
||||||
|
|
||||||
@output
|
|
||||||
def warn(self, message):
|
def warn(self, message):
|
||||||
"""
|
"""
|
||||||
This is warn
|
This is warn
|
||||||
"""
|
"""
|
||||||
self.logger.warn(message)
|
self.logger.warning(message)
|
||||||
|
|
||||||
@output
|
|
||||||
def error(self, message):
|
def error(self, message):
|
||||||
"""
|
"""
|
||||||
This is error
|
This is error
|
||||||
"""
|
"""
|
||||||
self.logger.error(message)
|
self.logger.error(message)
|
||||||
|
|
||||||
@output
|
|
||||||
def critical(self, message):
|
def critical(self, message):
|
||||||
"""
|
"""
|
||||||
This is critical
|
This is critical
|
||||||
|
Loading…
x
Reference in New Issue
Block a user