提交新建内容
This commit is contained in:
290
order_executor.py
Normal file
290
order_executor.py
Normal file
@@ -0,0 +1,290 @@
|
||||
import subprocess
|
||||
import time
|
||||
import pygetwindow as gw
|
||||
import win32gui
|
||||
import win32con
|
||||
import cv2
|
||||
import os
|
||||
import pyautogui
|
||||
# from logger_utils import log_info, log_warning, log_error, log_trigger
|
||||
from logger_utils_new import log_info, log_warning, log_error, log_trigger, log_debug, setup_logger, LOG_STYLES
|
||||
|
||||
|
||||
# 移除 pyautogui 导入
|
||||
|
||||
|
||||
class OrderExecutor:
|
||||
def __init__(self, target_window_titles=None):
|
||||
if target_window_titles is None:
|
||||
# 默认支持的行情软件列表
|
||||
self.target_window_titles = ["东方财富终端", "通达信金融终端", "同花顺"]
|
||||
else:
|
||||
self.target_window_titles = target_window_titles
|
||||
|
||||
self.current_software = None
|
||||
self.order_window_title = 'FlashTradeDlgDlg'
|
||||
self.order_count_window_title = '提示'
|
||||
self.ahk_script_path = "D:/gp_data/order_executor.ahk"
|
||||
|
||||
def detect_trading_software(self):
|
||||
"""检测当前运行的行情软件"""
|
||||
for title in self.target_window_titles:
|
||||
window_list = gw.getWindowsWithTitle(title)
|
||||
if window_list:
|
||||
self.current_software = title
|
||||
log_info(f"检测到行情软件: {title}")
|
||||
return title
|
||||
log_warning("未检测到支持的行情软件")
|
||||
return None
|
||||
|
||||
def run_ahk_script(self, command):
|
||||
"""执行AHK脚本命令"""
|
||||
try:
|
||||
# 尝试查找AHK安装路径
|
||||
ahk_path = None
|
||||
# 常见安装路径
|
||||
possible_paths = [
|
||||
"C:\\Program Files\\AutoHotkey\\v2\\AutoHotkey.exe", # v2版本
|
||||
"C:\\Program Files\\AutoHotkey\\AutoHotkey.exe",
|
||||
"AutoHotkey.exe" # 如果在PATH环境变量中
|
||||
]
|
||||
|
||||
for path in possible_paths:
|
||||
if os.path.exists(path):
|
||||
ahk_path = path
|
||||
break
|
||||
|
||||
if not ahk_path:
|
||||
log_error("未找到AutoHotkey安装路径")
|
||||
return False
|
||||
|
||||
subprocess.Popen(
|
||||
[ahk_path, '/restart', self.ahk_script_path, command],
|
||||
creationflags=subprocess.CREATE_NO_WINDOW
|
||||
)
|
||||
return True
|
||||
except Exception as e:
|
||||
log_error(f"执行AHK脚本失败: {e}")
|
||||
return False
|
||||
|
||||
def click_confirm_button(self, window_title, confirm_ratio=(0.8, 0.8), delay=0.3):
|
||||
"""
|
||||
修改为使用AHK点击确认按钮
|
||||
"""
|
||||
try:
|
||||
time.sleep(delay)
|
||||
window_list = gw.getWindowsWithTitle(window_title)
|
||||
if not window_list:
|
||||
log_warning(f"未找到行情软件 '{window_title}' 的窗口")
|
||||
return False
|
||||
|
||||
window = window_list[0]
|
||||
left, top, width, height = window.left, window.top, window.width, window.height
|
||||
x = left + int(width * confirm_ratio[0])
|
||||
y = top + int(height * confirm_ratio[1])
|
||||
|
||||
# 使用AHK执行点击
|
||||
command = f"click {x} {y}"
|
||||
self.run_ahk_script(command)
|
||||
log_trigger(f"AHK点击 '{window_title}' ,位置: ({x}, {y})")
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
log_error(f"点击确认按钮失败: {e}")
|
||||
return False
|
||||
|
||||
def click_button_by_image(self, image_path, window_title=None,
|
||||
timeout=10, retry_interval=0.5,
|
||||
confidence=0.8, move_duration=0.2):
|
||||
"""
|
||||
修改为使用AHK进行图像识别点击
|
||||
"""
|
||||
log_info(f"开始AHK图像识别: {image_path}")
|
||||
|
||||
# 构建AHK命令
|
||||
command = f"image_click {image_path}"
|
||||
if window_title:
|
||||
command += f" {window_title}"
|
||||
command += f" {confidence}"
|
||||
|
||||
# 执行AHK命令
|
||||
success = self.run_ahk_script(command)
|
||||
if success:
|
||||
log_trigger(f"AHK成功识别并点击图像 '{image_path}'")
|
||||
return True, (0, 0) # AHK不返回坐标,用(0,0)占位
|
||||
else:
|
||||
log_warning(f"AHK未能识别图像 '{image_path}'")
|
||||
return False, None
|
||||
|
||||
def place_order_tongdaxin(self, pure_code, auto_push):
|
||||
"""通达信下单方法"""
|
||||
try:
|
||||
# 获取所有匹配标题的窗口
|
||||
window_list = gw.getWindowsWithTitle(self.current_software)
|
||||
if not window_list:
|
||||
log_warning(f"未找到标题为 '{self.current_software}' 的窗口")
|
||||
return False
|
||||
|
||||
# 筛选逻辑:优先选择可见且活动的窗口
|
||||
target_window = None
|
||||
|
||||
def is_window_visible(hwnd):
|
||||
return win32gui.IsWindowVisible(hwnd) and win32gui.IsWindowEnabled(hwnd)
|
||||
|
||||
for window in window_list:
|
||||
hwnd = window._hWnd
|
||||
if is_window_visible(hwnd) and window.isActive:
|
||||
target_window = window
|
||||
break
|
||||
# 如果没有活动窗口,选择第一个可见窗口
|
||||
if not target_window:
|
||||
for window in window_list:
|
||||
hwnd = window._hWnd
|
||||
if is_window_visible(hwnd):
|
||||
target_window = window
|
||||
break
|
||||
# 如果都没有,选择第一个匹配的窗口
|
||||
if not target_window:
|
||||
target_window = window_list[0]
|
||||
|
||||
# 使用筛选后的目标窗口进行操作
|
||||
hwnd = target_window._hWnd
|
||||
log_info(f"找到窗口句柄: {hwnd}")
|
||||
target_window.restore()
|
||||
target_window.maximize()
|
||||
target_window.activate()
|
||||
time.sleep(0.2)
|
||||
|
||||
# 通达信操作方式:先按F1进入买入界面
|
||||
self.run_ahk_script("press f1")
|
||||
time.sleep(0.1)
|
||||
|
||||
# 输入代码
|
||||
self.run_ahk_script(f"type {pure_code}")
|
||||
self.run_ahk_script("press enter")
|
||||
time.sleep(0.1)
|
||||
|
||||
# 判断是否自动下单
|
||||
if auto_push == 1:
|
||||
# 在通达信中直接按F2进行全仓买入
|
||||
self.run_ahk_script("press f2")
|
||||
time.sleep(0.1)
|
||||
self.run_ahk_script("press enter")
|
||||
time.sleep(0.5)
|
||||
|
||||
# 判断是否弹出仓位的框
|
||||
if self.is_window_exists(self.order_count_window_title, 0.5):
|
||||
log_error(f"剩余金额不满足购买{pure_code}最低需求。")
|
||||
|
||||
except Exception as e:
|
||||
log_error(f"通达信下单失败: {str(e)}")
|
||||
return False
|
||||
|
||||
def place_order_eastmoney(self, pure_code, auto_push):
|
||||
"""东方财富下单方法"""
|
||||
try:
|
||||
# 获取所有匹配标题的窗口
|
||||
window_list = gw.getWindowsWithTitle(self.current_software)
|
||||
if not window_list:
|
||||
log_warning(f"未找到标题为 '{self.current_software}' 的窗口")
|
||||
return False
|
||||
|
||||
# 筛选逻辑:优先选择可见且活动的窗口
|
||||
target_window = None
|
||||
|
||||
def is_window_visible(hwnd):
|
||||
return win32gui.IsWindowVisible(hwnd) and win32gui.IsWindowEnabled(hwnd)
|
||||
|
||||
for window in window_list:
|
||||
hwnd = window._hWnd
|
||||
if is_window_visible(hwnd) and window.isActive:
|
||||
target_window = window
|
||||
break
|
||||
# 如果没有活动窗口,选择第一个可见窗口
|
||||
if not target_window:
|
||||
for window in window_list:
|
||||
hwnd = window._hWnd
|
||||
if is_window_visible(hwnd):
|
||||
target_window = window
|
||||
break
|
||||
# 如果都没有,选择第一个匹配的窗口
|
||||
if not target_window:
|
||||
target_window = window_list[0]
|
||||
|
||||
# 使用筛选后的目标窗口进行操作
|
||||
hwnd = target_window._hWnd
|
||||
log_info(f"找到窗口句柄: {hwnd}")
|
||||
target_window.restore()
|
||||
target_window.maximize()
|
||||
target_window.activate()
|
||||
time.sleep(0.2)
|
||||
|
||||
# 使用AHK点击中心位置
|
||||
self.click_confirm_button(self.current_software, (0.5, 0.5), 0.1)
|
||||
|
||||
# 使用AHK输入代码
|
||||
self.run_ahk_script(f"type {pure_code}")
|
||||
self.run_ahk_script("press enter")
|
||||
time.sleep(0.1)
|
||||
|
||||
# 判断是否自动下单
|
||||
if auto_push == 1:
|
||||
self.run_ahk_script("type 21")
|
||||
self.run_ahk_script("press enter")
|
||||
time.sleep(0.1)
|
||||
|
||||
# 点击全仓按钮
|
||||
success, pos = self.click_button_by_image(
|
||||
image_path="../images/full_position.png",
|
||||
window_title=self.order_window_title,
|
||||
timeout=10,
|
||||
retry_interval=0.3,
|
||||
confidence=0.9
|
||||
)
|
||||
|
||||
if success:
|
||||
log_info("已点击全仓按钮")
|
||||
# 判断是否弹出仓位的框
|
||||
if self.is_window_exists(self.order_count_window_title, 0.5):
|
||||
log_error(f"剩余金额不满足购买{pure_code}最低需求。")
|
||||
else:
|
||||
log_warning("未找到全仓按钮图像")
|
||||
|
||||
except Exception as e:
|
||||
log_error(f"东方财富下单失败: {str(e)}")
|
||||
return False
|
||||
|
||||
def place_order(self, pure_code, auto_push):
|
||||
"""
|
||||
根据检测到的行情软件选择相应的下单方法
|
||||
"""
|
||||
# 检测当前运行的行情软件
|
||||
if not self.current_software:
|
||||
self.detect_trading_software()
|
||||
|
||||
if not self.current_software:
|
||||
log_error("未找到支持的行情软件窗口")
|
||||
return False
|
||||
|
||||
# 根据不同的行情软件调用不同的下单方法
|
||||
if "通达信" in self.current_software:
|
||||
return self.place_order_tongdaxin(pure_code, auto_push)
|
||||
elif "东方财富" in self.current_software:
|
||||
return self.place_order_eastmoney(pure_code, auto_push)
|
||||
else:
|
||||
# 默认使用东方财富的方法
|
||||
log_warning(f"未针对 {self.current_software} 实现行情软件的特殊操作,使用默认方法")
|
||||
return self.place_order_eastmoney(pure_code, auto_push)
|
||||
|
||||
def is_window_exists(self, window_title, timeout=1.0):
|
||||
"""
|
||||
检查窗口是否存在
|
||||
"""
|
||||
start_time = time.time()
|
||||
while time.time() - start_time < timeout:
|
||||
window_list = gw.getWindowsWithTitle(window_title)
|
||||
if window_list:
|
||||
return True
|
||||
time.sleep(0.1)
|
||||
return False
|
||||
|
||||
Reference in New Issue
Block a user