268 lines
9.5 KiB
Python
268 lines
9.5 KiB
Python
#!/usr/bin/env python3
|
|
# -*- coding: utf-8 -*-
|
|
"""
|
|
策略编辑器 GUI 版本
|
|
使用 PyQt5 实现图形界面,功能与 strategy_editor.py 一致
|
|
"""
|
|
|
|
import os
|
|
import sys
|
|
import re
|
|
import glob
|
|
from datetime import datetime
|
|
|
|
# 导入 PyQt5 模块
|
|
from PyQt5.QtWidgets import (
|
|
QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout,
|
|
QLabel, QPushButton, QListWidget, QTextEdit, QInputDialog, QMessageBox,
|
|
QGroupBox, QSplitter, QStatusBar
|
|
)
|
|
from PyQt5.QtCore import Qt
|
|
|
|
# 导入策略编辑器核心功能
|
|
from strategy_editor import StrategyEditor
|
|
|
|
class StrategyEditorGUI(QMainWindow):
|
|
"""策略编辑器 GUI 类"""
|
|
|
|
def __init__(self):
|
|
super().__init__()
|
|
|
|
# 初始化策略编辑器核心
|
|
self.editor = StrategyEditor()
|
|
|
|
# 设置窗口标题和大小
|
|
self.setWindowTitle("策略编辑器")
|
|
self.setGeometry(100, 100, 1200, 800)
|
|
|
|
# 初始化界面组件
|
|
self.init_ui()
|
|
|
|
# 加载策略列表
|
|
self.load_strategy_list()
|
|
|
|
def init_ui(self):
|
|
"""初始化界面组件"""
|
|
# 创建中心部件
|
|
central_widget = QWidget()
|
|
self.setCentralWidget(central_widget)
|
|
|
|
# 创建主布局
|
|
main_layout = QHBoxLayout(central_widget)
|
|
|
|
# 创建分割器
|
|
splitter = QSplitter(Qt.Horizontal)
|
|
main_layout.addWidget(splitter)
|
|
|
|
# 创建左侧策略列表区域
|
|
self.strategy_list_widget = self.create_strategy_list()
|
|
splitter.addWidget(self.strategy_list_widget)
|
|
|
|
# 创建右侧编辑区域
|
|
self.editor_widget = self.create_editor()
|
|
splitter.addWidget(self.editor_widget)
|
|
|
|
# 设置分割器比例
|
|
splitter.setSizes([200, 1000])
|
|
|
|
# 创建状态栏
|
|
self.status_bar = QStatusBar()
|
|
self.setStatusBar(self.status_bar)
|
|
self.status_bar.showMessage("就绪")
|
|
|
|
def create_strategy_list(self):
|
|
"""创建策略列表区域"""
|
|
group_box = QGroupBox("可用策略")
|
|
layout = QVBoxLayout(group_box)
|
|
|
|
# 创建策略列表
|
|
self.strategy_list = QListWidget()
|
|
self.strategy_list.itemClicked.connect(self.on_strategy_selected)
|
|
layout.addWidget(self.strategy_list)
|
|
|
|
# 创建操作按钮
|
|
button_layout = QVBoxLayout()
|
|
|
|
self.new_btn = QPushButton("新建策略")
|
|
self.new_btn.clicked.connect(self.on_new_strategy)
|
|
button_layout.addWidget(self.new_btn)
|
|
|
|
self.open_btn = QPushButton("打开策略")
|
|
self.open_btn.clicked.connect(self.on_open_strategy)
|
|
button_layout.addWidget(self.open_btn)
|
|
|
|
self.delete_btn = QPushButton("删除策略")
|
|
self.delete_btn.clicked.connect(self.on_delete_strategy)
|
|
button_layout.addWidget(self.delete_btn)
|
|
|
|
self.refresh_btn = QPushButton("刷新列表")
|
|
self.refresh_btn.clicked.connect(self.load_strategy_list)
|
|
button_layout.addWidget(self.refresh_btn)
|
|
|
|
layout.addLayout(button_layout)
|
|
|
|
return group_box
|
|
|
|
def create_editor(self):
|
|
"""创建代码编辑区域"""
|
|
group_box = QGroupBox("策略编辑")
|
|
layout = QVBoxLayout(group_box)
|
|
|
|
# 创建当前策略信息标签
|
|
self.current_strategy_label = QLabel("未选择策略")
|
|
self.current_strategy_label.setStyleSheet("font-weight: bold;")
|
|
layout.addWidget(self.current_strategy_label)
|
|
|
|
# 创建代码编辑器
|
|
self.code_editor = QTextEdit()
|
|
self.code_editor.setPlainText("# 请先选择或创建策略")
|
|
layout.addWidget(self.code_editor)
|
|
|
|
# 创建保存按钮
|
|
self.save_btn = QPushButton("保存策略")
|
|
self.save_btn.clicked.connect(self.on_save_strategy)
|
|
layout.addWidget(self.save_btn)
|
|
|
|
return group_box
|
|
|
|
def load_strategy_list(self):
|
|
"""加载策略列表"""
|
|
self.strategy_list.clear()
|
|
|
|
# 获取策略文件
|
|
strategy_files = glob.glob(os.path.join(self.editor.strategy_dir, '*.py'))
|
|
|
|
for file_path in strategy_files:
|
|
if os.path.basename(file_path) in ['__init__.py', 'base_strategy.py', 'market_filter.py']:
|
|
continue
|
|
|
|
file_name = os.path.basename(file_path)
|
|
|
|
# 读取文件内容,获取类定义
|
|
try:
|
|
with open(file_path, 'r', encoding='utf-8') as f:
|
|
content = f.read()
|
|
|
|
# 查找类定义
|
|
class_match = re.search(r'class\s+(\w+)\s*\(', content)
|
|
if class_match:
|
|
class_name = class_match.group(1)
|
|
self.strategy_list.addItem(f"{class_name} ({file_name})")
|
|
else:
|
|
self.strategy_list.addItem(f"{file_name.replace('.py', '')} ({file_name})")
|
|
except Exception as e:
|
|
QMessageBox.warning(self, "错误", f"读取文件 {file_name} 失败: {str(e)}")
|
|
|
|
def on_strategy_selected(self, item):
|
|
"""选择策略时的处理"""
|
|
strategy_info = item.text()
|
|
# 提取策略名称
|
|
strategy_name = strategy_info.split(' ')[0]
|
|
|
|
# 读取策略
|
|
if self.editor.read_strategy(strategy_name):
|
|
self.current_strategy_label.setText(f"当前策略: {self.editor.current_strategy_name}")
|
|
self.code_editor.setPlainText(self.editor.current_strategy_content)
|
|
self.status_bar.showMessage(f"已加载策略: {strategy_name}")
|
|
else:
|
|
QMessageBox.warning(self, "错误", f"无法加载策略: {strategy_name}")
|
|
|
|
def on_new_strategy(self):
|
|
"""新建策略"""
|
|
strategy_name, ok = QInputDialog.getText(
|
|
self, "新建策略", "请输入策略名称(首字母大写):"
|
|
)
|
|
|
|
if ok and strategy_name:
|
|
if self.editor.create_new_strategy(strategy_name):
|
|
# 更新界面
|
|
self.current_strategy_label.setText(f"当前策略: {self.editor.current_strategy_name}")
|
|
self.code_editor.setPlainText(self.editor.current_strategy_content)
|
|
self.load_strategy_list() # 刷新策略列表
|
|
self.status_bar.showMessage(f"已创建新策略: {strategy_name}")
|
|
else:
|
|
QMessageBox.warning(self, "错误", "策略创建失败,请检查策略名称是否合法或已存在")
|
|
|
|
def on_open_strategy(self):
|
|
"""打开策略"""
|
|
strategy_name, ok = QInputDialog.getText(
|
|
self, "打开策略", "请输入策略名称:"
|
|
)
|
|
|
|
if ok and strategy_name:
|
|
if self.editor.read_strategy(strategy_name):
|
|
self.current_strategy_label.setText(f"当前策略: {self.editor.current_strategy_name}")
|
|
self.code_editor.setPlainText(self.editor.current_strategy_content)
|
|
self.status_bar.showMessage(f"已加载策略: {strategy_name}")
|
|
else:
|
|
QMessageBox.warning(self, "错误", f"无法找到策略: {strategy_name}")
|
|
|
|
def on_save_strategy(self):
|
|
"""保存策略"""
|
|
if not self.editor.current_strategy_name:
|
|
QMessageBox.warning(self, "错误", "请先选择或创建策略")
|
|
return
|
|
|
|
# 获取编辑器内容
|
|
content = self.code_editor.toPlainText()
|
|
if not content:
|
|
QMessageBox.warning(self, "错误", "策略内容不能为空")
|
|
return
|
|
|
|
# 更新当前策略内容
|
|
self.editor.current_strategy_content = content
|
|
|
|
# 保存策略
|
|
if self.editor.save_strategy():
|
|
self.status_bar.showMessage(f"已保存策略: {self.editor.current_strategy_name}")
|
|
QMessageBox.information(self, "成功", f"策略 {self.editor.current_strategy_name} 保存成功")
|
|
else:
|
|
QMessageBox.warning(self, "错误", "策略保存失败")
|
|
|
|
def on_delete_strategy(self):
|
|
"""删除策略"""
|
|
# 获取当前选中的策略
|
|
current_item = self.strategy_list.currentItem()
|
|
if not current_item:
|
|
QMessageBox.warning(self, "错误", "请先选择要删除的策略")
|
|
return
|
|
|
|
strategy_info = current_item.text()
|
|
strategy_name = strategy_info.split(' ')[0]
|
|
|
|
# 确认删除
|
|
reply = QMessageBox.question(
|
|
self, "确认删除", f"确定要删除策略 {strategy_name} 吗?",
|
|
QMessageBox.Yes | QMessageBox.No, QMessageBox.No
|
|
)
|
|
|
|
if reply == QMessageBox.Yes:
|
|
if self.editor.delete_strategy(strategy_name):
|
|
# 清空当前编辑内容
|
|
self.current_strategy_label.setText("未选择策略")
|
|
self.code_editor.setPlainText("# 请先选择或创建策略")
|
|
# 刷新策略列表
|
|
self.load_strategy_list()
|
|
self.status_bar.showMessage(f"已删除策略: {strategy_name}")
|
|
else:
|
|
QMessageBox.warning(self, "错误", f"无法删除策略: {strategy_name}")
|
|
|
|
|
|
def main():
|
|
"""主函数"""
|
|
# 创建应用程序
|
|
app = QApplication(sys.argv)
|
|
|
|
# 创建主窗口
|
|
window = StrategyEditorGUI()
|
|
|
|
# 显示窗口
|
|
window.show()
|
|
|
|
# 运行应用程序
|
|
sys.exit(app.exec_())
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|