AI舆情uSmart(盈立)交易系统
系统摘要 盈立证券交易系统是基于OpenAPI开发的证券交易客户端,提供港股和美股交易功能。主要包含账户管理、资金操作、实时行情查询等核心模块,支持持仓管理和AI交易策略。系统采用Python开发,使用tkinter构建GUI界面,具有简洁直观的操作体验。通过API与盈立证券后台服务交互,实现安全可靠的证券交易功能。系统支持测试模式,便于功能验证和开发调试。
系统概述
盈立证券交易系统是基于盈立证券OpenAPI开发的证券交易客户端,支持港股和美股交易。该系统提供账户管理、资金管理、实时行情查询等功能,采用Python开发,使用tkinter构建图形用户界面。
主要功能包括账户登录与管理、港股和美股交易、资金入金/出金操作、持仓查询与管理、实时行情查看、AI交易策略以及API功能测试。系统设计简洁直观,便于用户快速上手操作。

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import tkinter as tk
from tkinter import ttk, messagebox
import webbrowser
import threading
import sys
import os
# 将示例代码路径添加到系统路径中
sys.path.append(os.path.join(os.path.dirname(__file__), '..', 'open_api_demo_python', 'openapi-demo-py'))
from api_client import APIClient
from utils import ConfigUtil
try:
from api import trade as example_trade
except ImportError:
example_trade = None
class MainWindow:
def __init__(self, parent, token):
self.parent = parent
self.token = token
self.api_client = None
self.example_api_client = None
# 加载配置并设置token
try:
config = ConfigUtil.load_config()
self.api_client = APIClient(config)
# 如果不是测试token,则设置实际token
if token != "test_token_123456":
self.api_client.token = token
# 尝试创建示例API客户端
if example_trade:
try:
# 设置环境变量
demo_path = os.path.join(os.path.dirname(__file__), '..', 'open_api_demo_python', 'openapi-demo-py')
os.environ['API_DEMO_HOMEPATH'] = demo_path
# 确保配置文件存在
config_path = os.path.join(demo_path, 'conf', 'config.json')
if os.path.exists(config_path):
self.example_api_client = example_trade.get_context_by_phonenumber(phoneNumber="13750062348")
# 如果我们有实际token,设置到示例客户端中
if token and token != "test_token_123456":
self.example_api_client.token = token
# 如果是测试模式,设置测试token
elif token == "test_token_123456":
self.example_api_client.token = "test_token_123456"
else:
print(f"示例API配置文件不存在: {config_path}")
except Exception as e:
print(f"创建示例API客户端失败: {str(e)}")
except Exception as e:
messagebox.showerror("错误", f"加载配置失败: {str(e)}")
return
# 创建主界面
self.create_widgets()
def create_widgets(self):
# 创建笔记本控件(标签页)
self.notebook = ttk.Notebook(self.parent)
self.notebook.grid(row=0, column=0, sticky=(tk.W, tk.E, tk.N, tk.S))
# 配置网格权重
self.parent.columnconfigure(0, weight=1)
self.parent.rowconfigure(0, weight=1)
# 创建各个功能标签页
self.create_account_frame()
self.create_hk_trade_frame()
self.create_us_trade_frame()
self.create_fund_frame()
self.create_ai_strategy_frame() # 添加AI交易策略页面
self.create_demo_frame()
def create_account_frame(self):
"""创建账户管理标签页"""
self.account_frame = ttk.Frame(self.notebook, padding="10")
self.notebook.add(self.account_frame, text="账户管理")
# 标题
title_label = ttk.Label(self.account_frame, text="账户信息", font=("Arial", 14, "bold"))
title_label.grid(row=0, column=0, columnspan=2, pady=(0, 20))
# 持仓信息
holdings_label = ttk.Label(self.account_frame, text="持仓信息:", font=("Arial", 12))
holdings_label.grid(row=1, column=0, sticky=tk.W, pady=5)
# 持仓列表
self.holdings_tree = ttk.Treeview(self.account_frame, columns=("证券代码", "证券名称", "持仓数量", "可用数量", "成本价", "当前价", "盈亏"), show="headings", height=10)
# 设置列标题
for col in self.holdings_tree["columns"]:
self.holdings_tree.heading(col, text=col)
self.holdings_tree.column(col, width=100)
self.holdings_tree.grid(row=2, column=0, columnspan=2, pady=10, sticky=(tk.W, tk.E))
# 滚动条
holdings_scroll = ttk.Scrollbar(self.account_frame, orient="vertical", command=self.holdings_tree.yview)
holdings_scroll.grid(row=2, column=2, sticky=(tk.N, tk.S))
self.holdings_tree.configure(yscrollcommand=holdings_scroll.set)
# 刷新按钮
refresh_button = ttk.Button(self.account_frame, text="刷新持仓", command=self.refresh_holdings)
refresh_button.grid(row=3, column=0, columnspan=2, pady=10)
# 交易员管理
trader_label = ttk.Label(self.account_frame, text="交易员管理:", font=("Arial", 12))
trader_label.grid(row=4, column=0, sticky=tk.W, pady=(20, 5))
# 交易员列表
self.trader_tree = ttk.Treeview(self.account_frame, columns=("交易员ID", "姓名", "权限"), show="headings", height=5)
# 设置列标题
for col in self.trader_tree["columns"]:
self.trader_tree.heading(col, text=col)
self.trader_tree.column(col, width=150)
self.trader_tree.grid(row=5, column=0, columnspan=2, pady=10, sticky=(tk.W, tk.E))
# 滚动条
trader_scroll = ttk.Scrollbar(self.account_frame, orient="vertical", command=self.trader_tree.yview)
trader_scroll.grid(row=5, column=2, sticky=(tk.N, tk.S))
self.trader_tree.configure(yscrollcommand=trader_scroll.set)
# 添加交易员按钮
add_trader_button = ttk.Button(self.account_frame, text="添加交易员")
add_trader_button.grid(row=6, column=0, pady=5, padx=5, sticky=tk.W)
# 删除交易员按钮
delete_trader_button = ttk.Button(self.account_frame, text="删除交易员")
delete_trader_button.grid(row=6, column=1, pady=5, padx=5, sticky=tk.W)
# 设置列权重
self.account_frame.columnconfigure(0, weight=1)
self.account_frame.columnconfigure(1, weight=1)
def create_hk_trade_frame(self):
"""创建港股交易标签页"""
self.hk_trade_frame = ttk.Frame(self.notebook, padding="10")
self.notebook.add(self.hk_trade_frame, text="港股交易")
# 标题
title_label = ttk.Label(self.hk_trade_frame, text="港股交易", font=("Arial", 14, "bold"))
title_label.grid(row=0, column=0, columnspan=2, pady=(0, 20))
# 股票代码搜索
code_label = ttk.Label(self.hk_trade_frame, text="股票代码:")
code_label.grid(row=1, column=0, sticky=tk.W, pady=5)
self.hk_code_var = tk.StringVar()
self.hk_code_entry = ttk.Entry(self.hk_trade_frame, textvariable=self.hk_code_var, width=20)
self.hk_code_entry.grid(row=1, column=1, sticky=tk.W, pady=5)
# 搜索按钮
search_button = ttk.Button(self.hk_trade_frame, text="搜索", command=self.search_hk_stock)
search_button.grid(row=1, column=2, pady=5, padx=5)
# 股票信息显示
info_frame = ttk.LabelFrame(self.hk_trade_frame, text="股票信息", padding="10")
info_frame.grid(row=2, column=0, columnspan=3, pady=10, sticky=(tk.W, tk.E))
self.hk_stock_info_var = tk.StringVar()
self.hk_stock_info_var.set("请输入股票代码进行搜索")
self.hk_stock_info_label = ttk.Label(info_frame, textvariable=self.hk_stock_info_var)
self.hk_stock_info_label.grid(row=0, column=0)
# 交易信息输入
trade_frame = ttk.LabelFrame(self.hk_trade_frame, text="交易信息", padding="10")
trade_frame.grid(row=3, column=0, columnspan=3, pady=10, sticky=(tk.W, tk.E))
# 交易方向
direction_label = ttk.Label(trade_frame, text="交易方向:")
direction_label.grid(row=0, column=0, sticky=tk.W, pady=5)
self.hk_direction_var = tk.StringVar(value="买入")
ttk.Radiobutton(trade_frame, text="买入", variable=self.hk_direction_var, value="买入").grid(row=0, column=1, sticky=tk.W)
ttk.Radiobutton(trade_frame, text="卖出", variable=self.hk_direction_var, value="卖出").grid(row=0, column=2, sticky=tk.W)
# 数量
quantity_label = ttk.Label(trade_frame, text="数量:")
quantity_label.grid(row=1, column=0, sticky=tk.W, pady=5)
self.hk_quantity_var = tk.StringVar()
self.hk_quantity_entry = ttk.Entry(trade_frame, textvariable=self.hk_quantity_var, width=20)
self.hk_quantity_entry.grid(row=1, column=1, sticky=tk.W, pady=5)
# 价格
price_label = ttk.Label(trade_frame, text="价格:")
price_label.grid(row=2, column=0, sticky=tk.W, pady=5)
self.hk_price_var = tk.StringVar()
self.hk_price_entry = ttk.Entry(trade_frame, textvariable=self.hk_price_var, width=20)
self.hk_price_entry.grid(row=2, column=1, sticky=tk.W, pady=5)
# 下单按钮
self.hk_order_button = ttk.Button(trade_frame, text="下单", command=self.place_hk_order)
self.hk_order_button.grid(row=3, column=0, columnspan=3, pady=20)
# 设置列权重
self.hk_trade_frame.columnconfigure(1, weight=1)
def create_us_trade_frame(self):
"""创建美股交易标签页"""
self.us_trade_frame = ttk.Frame(self.notebook, padding="10")
self.notebook.add(self.us_trade_frame, text="美股交易")
# 标题
title_label = ttk.Label(self.us_trade_frame, text="美股交易", font=("Arial", 14, "bold"))
title_label.grid(row=0, column=0, columnspan=2, pady=(0, 20))
# 股票代码搜索
code_label = ttk.Label(self.us_trade_frame, text="股票代码:")
code_label.grid(row=1, column=0, sticky=tk.W, pady=5)
self.us_code_var = tk.StringVar()
self.us_code_entry = ttk.Entry(self.us_trade_frame, textvariable=self.us_code_var, width=20)
self.us_code_entry.grid(row=1, column=1, sticky=tk.W, pady=5)
# 搜索按钮
search_button = ttk.Button(self.us_trade_frame, text="搜索", command=self.search_us_stock)
search_button.grid(row=1, column=2, pady=5, padx=5)
# 股票信息显示
info_frame = ttk.LabelFrame(self.us_trade_frame, text="股票信息", padding="10")
info_frame.grid(row=2, column=0, columnspan=3, pady=10, sticky=(tk.W, tk.E))
self.us_stock_info_var = tk.StringVar()
self.us_stock_info_var.set("请输入股票代码进行搜索")
self.us_stock_info_label = ttk.Label(info_frame, textvariable=self.us_stock_info_var)
self.us_stock_info_label.grid(row=0, column=0)
# 交易信息输入
trade_frame = ttk.LabelFrame(self.us_trade_frame, text="交易信息", padding="10")
trade_frame.grid(row=3, column=0, columnspan=3, pady=10, sticky=(tk.W, tk.E))
# 交易方向
direction_label = ttk.Label(trade_frame, text="交易方向:")
direction_label.grid(row=0, column=0, sticky=tk.W, pady=5)
self.us_direction_var = tk.StringVar(value="买入")
ttk.Radiobutton(trade_frame, text="买入", variable=self.us_direction_var, value="买入").grid(row=0, column=1, sticky=tk.W)
ttk.Radiobutton(trade_frame, text="卖出", variable=self.us_direction_var, value="卖出").grid(row=0, column=2, sticky=tk.W)
# 数量
quantity_label = ttk.Label(trade_frame, text="数量:")
quantity_label.grid(row=1, column=0, sticky=tk.W, pady=5)
self.us_quantity_var = tk.StringVar()
self.us_quantity_entry = ttk.Entry(trade_frame, textvariable=self.us_quantity_var, width=20)
self.us_quantity_entry.grid(row=1, column=1, sticky=tk.W, pady=5)
# 价格
price_label = ttk.Label(trade_frame, text="价格:")
price_label.grid(row=2, column=0, sticky=tk.W, pady=5)
self.us_price_var = tk.StringVar()
self.us_price_entry = ttk.Entry(trade_frame, textvariable=self.us_price_var, width=20)
self.us_price_entry.grid(row=2, column=1, sticky=tk.W, pady=5)
# 下单按钮
self.us_order_button = ttk.Button(trade_frame, text="下单", command=self.place_us_order)
self.us_order_button.grid(row=3, column=0, columnspan=3, pady=20)
# 设置列权重
self.us_trade_frame.columnconfigure(1, weight=1)
def create_fund_frame(self):
"""创建资金管理标签页"""
self.fund_frame = ttk.Frame(self.notebook, padding="10")
self.notebook.add(self.fund_frame, text="资金管理")
# 标题
title_label = ttk.Label(self.fund_frame, text="资金管理", font=("Arial", 14, "bold"))
title_label.grid(row=0, column=0, columnspan=2, pady=(0, 20))
# 资金操作
operation_frame = ttk.LabelFrame(self.fund_frame, text="资金操作", padding="10")
operation_frame.grid(row=1, column=0, columnspan=2, pady=10, sticky=(tk.W, tk.E))
# 操作类型
type_label = ttk.Label(operation_frame, text="操作类型:")
type_label.grid(row=0, column=0, sticky=tk.W, pady=5)
self.fund_type_var = tk.StringVar(value="入金")
ttk.Radiobutton(operation_frame, text="入金", variable=self.fund_type_var, value="入金").grid(row=0, column=1, sticky=tk.W)
ttk.Radiobutton(operation_frame, text="出金", variable=self.fund_type_var, value="出金").grid(row=0, column=2, sticky=tk.W)
# 金额
amount_label = ttk.Label(operation_frame, text="金额:")
amount_label.grid(row=1, column=0, sticky=tk.W, pady=5)
self.fund_amount_var = tk.StringVar()
self.fund_amount_entry = ttk.Entry(operation_frame, textvariable=self.fund_amount_var, width=20)
self.fund_amount_entry.grid(row=1, column=1, sticky=tk.W, pady=5)
# 银行信息
bank_label = ttk.Label(operation_frame, text="银行:")
bank_label.grid(row=2, column=0, sticky=tk.W, pady=5)
self.bank_var = tk.StringVar()
banks = ["工商银行", "建设银行", "农业银行", "中国银行", "招商银行"]
self.bank_combo = ttk.Combobox(operation_frame, textvariable=self.bank_var, values=banks, state="readonly", width=20)
self.bank_combo.grid(row=2, column=1, sticky=tk.W, pady=5)
self.bank_combo.set(banks[0])
# 确认按钮
confirm_button = ttk.Button(operation_frame, text="确认", command=self.process_fund)
confirm_button.grid(row=3, column=0, columnspan=3, pady=20)
# 资金流水
history_label = ttk.Label(self.fund_frame, text="资金流水:", font=("Arial", 12))
history_label.grid(row=2, column=0, sticky=tk.W, pady=(20, 5))
# 流水列表
self.history_tree = ttk.Treeview(self.fund_frame, columns=("时间", "类型", "金额", "状态"), show="headings", height=8)
# 设置列标题
for col in self.history_tree["columns"]:
self.history_tree.heading(col, text=col)
self.history_tree.column(col, width=150)
self.history_tree.grid(row=3, column=0, columnspan=2, pady=10, sticky=(tk.W, tk.E))
# 滚动条
history_scroll = ttk.Scrollbar(self.fund_frame, orient="vertical", command=self.history_tree.yview)
history_scroll.grid(row=3, column=2, sticky=(tk.N, tk.S))
self.history_tree.configure(yscrollcommand=history_scroll.set)
# 设置列权重
self.fund_frame.columnconfigure(0, weight=1)
def create_ai_strategy_frame(self):
"""创建AI交易策略标签页"""
self.ai_strategy_frame = ttk.Frame(self.notebook, padding="10")
self.notebook.add(self.ai_strategy_frame, text="AI交易策略")
# 标题
title_label = ttk.Label(self.ai_strategy_frame, text="AI交易策略", font=("Arial", 14, "bold"))
title_label.grid(row=0, column=0, columnspan=3, pady=(0, 20))
# AI模型选择框架
model_frame = ttk.LabelFrame(self.ai_strategy_frame, text="AI模型配置", padding="10")
model_frame.grid(row=1, column=0, columnspan=3, pady=10, sticky=(tk.W, tk.E))
# 模型提供商
provider_label = ttk.Label(model_frame, text="模型提供商:")
provider_label.grid(row=0, column=0, sticky=tk.W, pady=5)
self.ai_provider_var = tk.StringVar(value="豆包")
providers = ["豆包", "DeepSeek", "通义千问", "文心一言", "讯飞星火"]
self.provider_combo = ttk.Combobox(model_frame, textvariable=self.ai_provider_var, values=providers, state="readonly", width=20)
self.provider_combo.grid(row=0, column=1, sticky=tk.W, pady=5, padx=(10, 0))
self.provider_combo.set(providers[0])
# API密钥
api_key_label = ttk.Label(model_frame, text="API密钥:")
api_key_label.grid(row=1, column=0, sticky=tk.W, pady=5)
self.api_key_var = tk.StringVar()
self.api_key_entry = ttk.Entry(model_frame, textvariable=self.api_key_var, width=40, show="*")
self.api_key_entry.grid(row=1, column=1, sticky=tk.W, pady=5, padx=(10, 0))
# 模型名称
model_name_label = ttk.Label(model_frame, text="模型名称:")
model_name_label.grid(row=2, column=0, sticky=tk.W, pady=5)
self.model_name_var = tk.StringVar()
self.model_name_entry = ttk.Entry(model_frame, textvariable=self.model_name_var, width=40)
self.model_name_entry.grid(row=2, column=1, sticky=tk.W, pady=5, padx=(10, 0))
self.model_name_entry.insert(0, "default-model") # 默认模型名称
# 策略配置框架
strategy_frame = ttk.LabelFrame(self.ai_strategy_frame, text="策略配置", padding="10")
strategy_frame.grid(row=2, column=0, columnspan=3, pady=10, sticky=(tk.W, tk.E))
# 策略名称
strategy_name_label = ttk.Label(strategy_frame, text="策略名称:")
strategy_name_label.grid(row=0, column=0, sticky=tk.W, pady=5)
self.strategy_name_var = tk.StringVar()
self.strategy_name_entry = ttk.Entry(strategy_frame, textvariable=self.strategy_name_var, width=30)
self.strategy_name_entry.grid(row=0, column=1, sticky=tk.W, pady=5, padx=(10, 0))
# 交易市场
market_label = ttk.Label(strategy_frame, text="交易市场:")
market_label.grid(row=1, column=0, sticky=tk.W, pady=5)
self.market_var = tk.StringVar(value="港股")
ttk.Radiobutton(strategy_frame, text="港股", variable=self.market_var, value="港股").grid(row=1, column=1, sticky=tk.W, padx=(10, 0))
ttk.Radiobutton(strategy_frame, text="美股", variable=self.market_var, value="美股").grid(row=1, column=2, sticky=tk.W)
ttk.Radiobutton(strategy_frame, text="A股", variable=self.market_var, value="A股").grid(row=1, column=3, sticky=tk.W)
# 风险等级
risk_label = ttk.Label(strategy_frame, text="风险等级:")
risk_label.grid(row=2, column=0, sticky=tk.W, pady=5)
self.risk_var = tk.StringVar(value="中等")
risk_levels = ["低", "中等", "高"]
self.risk_combo = ttk.Combobox(strategy_frame, textvariable=self.risk_var, values=risk_levels, state="readonly", width=10)
self.risk_combo.grid(row=2, column=1, sticky=tk.W, pady=5, padx=(10, 0))
self.risk_combo.set(risk_levels[1])
# 策略描述
description_label = ttk.Label(strategy_frame, text="策略描述:")
description_label.grid(row=3, column=0, sticky=tk.NW, pady=5)
self.strategy_description_text = tk.Text(strategy_frame, height=5, width=50)
description_scroll = ttk.Scrollbar(strategy_frame, orient="vertical", command=self.strategy_description_text.yview)
self.strategy_description_text.configure(yscrollcommand=description_scroll.set)
self.strategy_description_text.grid(row=3, column=1, columnspan=2, pady=5, padx=(10, 0), sticky=(tk.W, tk.E))
description_scroll.grid(row=3, column=3, sticky=(tk.N, tk.S))
# 操作按钮框架
button_frame = ttk.Frame(self.ai_strategy_frame)
button_frame.grid(row=3, column=0, columnspan=3, pady=20)
# 保存策略按钮
save_strategy_button = ttk.Button(button_frame, text="保存策略", command=self.save_ai_strategy)
save_strategy_button.grid(row=0, column=0, padx=10)
# 测试策略按钮
test_strategy_button = ttk.Button(button_frame, text="测试策略", command=self.test_ai_strategy)
test_strategy_button.grid(row=0, column=1, padx=10)
# 启动策略按钮
start_strategy_button = ttk.Button(button_frame, text="启动策略", command=self.start_ai_strategy)
start_strategy_button.grid(row=0, column=2, padx=10)
# 停止策略按钮
stop_strategy_button = ttk.Button(button_frame, text="停止策略", command=self.stop_ai_strategy)
stop_strategy_button.grid(row=0, column=3, padx=10)
# 策略状态显示
status_frame = ttk.LabelFrame(self.ai_strategy_frame, text="策略状态", padding="10")
status_frame.grid(row=4, column=0, columnspan=3, pady=10, sticky=(tk.W, tk.E))
self.strategy_status_var = tk.StringVar(value="未启动")
status_label = ttk.Label(status_frame, text="当前状态:")
status_label.grid(row=0, column=0, sticky=tk.W, pady=5)
self.strategy_status_display = ttk.Label(status_frame, textvariable=self.strategy_status_var, foreground="red")
self.strategy_status_display.grid(row=0, column=1, sticky=tk.W, pady=5, padx=(10, 0))
# 策略日志显示
log_frame = ttk.LabelFrame(self.ai_strategy_frame, text="策略日志", padding="10")
log_frame.grid(row=5, column=0, columnspan=3, pady=10, sticky=(tk.W, tk.E, tk.N, tk.S))
self.strategy_log_text = tk.Text(log_frame, height=10, width=80)
log_scroll = ttk.Scrollbar(log_frame, orient="vertical", command=self.strategy_log_text.yview)
self.strategy_log_text.configure(yscrollcommand=log_scroll.set)
self.strategy_log_text.grid(row=0, column=0, sticky=(tk.W, tk.E, tk.N, tk.S))
log_scroll.grid(row=0, column=1, sticky=(tk.N, tk.S))
# 清空日志按钮
clear_log_button = ttk.Button(log_frame, text="清空日志", command=self.clear_ai_strategy_log)
clear_log_button.grid(row=1, column=0, pady=10)
# 设置列权重
self.ai_strategy_frame.columnconfigure(0, weight=1)
self.ai_strategy_frame.rowconfigure(5, weight=1)
log_frame.columnconfigure(0, weight=1)
log_frame.rowconfigure(0, weight=1)
def save_ai_strategy(self):
"""保存AI交易策略"""
# 获取策略配置信息
strategy_name = self.strategy_name_var.get()
provider = self.ai_provider_var.get()
api_key = self.api_key_var.get()
model_name = self.model_name_var.get()
market = self.market_var.get()
risk_level = self.risk_var.get()
description = self.strategy_description_text.get("1.0", tk.END).strip()
# 验证必填字段
if not strategy_name:
messagebox.showwarning("警告", "请输入策略名称")
return
if not api_key:
messagebox.showwarning("警告", "请输入API密钥")
return
# 显示保存成功信息
messagebox.showinfo("成功", f"策略 '{strategy_name}' 已保存")
self.append_ai_strategy_log(f"策略 '{strategy_name}' 已保存")
def test_ai_strategy(self):
"""测试AI交易策略"""
strategy_name = self.strategy_name_var.get()
if not strategy_name:
messagebox.showwarning("警告", "请输入策略名称")
return
self.append_ai_strategy_log(f"正在测试策略 '{strategy_name}'...")
# 这里可以添加实际的测试逻辑
self.append_ai_strategy_log("测试完成")
def start_ai_strategy(self):
"""启动AI交易策略"""
strategy_name = self.strategy_name_var.get()
if not strategy_name:
messagebox.showwarning("警告", "请输入策略名称")
return
self.strategy_status_var.set("运行中")
self.strategy_status_display.config(foreground="green")
self.append_ai_strategy_log(f"策略 '{strategy_name}' 已启动")
def stop_ai_strategy(self):
"""停止AI交易策略"""
strategy_name = self.strategy_name_var.get()
self.strategy_status_var.set("已停止")
self.strategy_status_display.config(foreground="red")
self.append_ai_strategy_log(f"策略 '{strategy_name}' 已停止")
def clear_ai_strategy_log(self):
"""清空AI策略日志"""
self.strategy_log_text.delete(1.0, tk.END)
def append_ai_strategy_log(self, text):
"""添加AI策略日志"""
import datetime
timestamp = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
self.strategy_log_text.insert(tk.END, f"[{timestamp}] {text}\n")
self.strategy_log_text.see(tk.END)
def refresh_holdings(self):
"""刷新持仓信息"""
# 在新线程中获取持仓信息
thread = threading.Thread(target=self._refresh_holdings_thread)
thread.daemon = True
thread.start()
def _refresh_holdings_thread(self):
"""刷新持仓信息线程函数"""
try:
# 获取港股持仓
hk_result = self.api_client.stock_holding("0") # 0表示港股
# 获取美股持仓
us_result = self.api_client.stock_holding("1") # 1表示美股
# 更新UI
self.parent.after(0, lambda: self._update_holdings_ui(hk_result, us_result))
except Exception as e:
self.parent.after(0, lambda: messagebox.showerror("错误", f"获取持仓信息失败: {str(e)}"))
def _update_holdings_ui(self, hk_result, us_result):
"""更新持仓信息UI"""
# 清空现有数据
for item in self.holdings_tree.get_children():
self.holdings_tree.delete(item)
# 添加港股持仓
if hk_result.get("success"):
holdings = hk_result.get("data", [])
for holding in holdings:
self.holdings_tree.insert("", "end", values=(
holding.get("stockCode", ""),
holding.get("stockName", ""),
holding.get("holdingQuantity", ""),
holding.get("availableQuantity", ""),
holding.get("costPrice", ""),
holding.get("currentPrice", ""),
holding.get("profitLoss", "")
))
# 添加美股持仓
if us_result.get("success"):
holdings = us_result.get("data", [])
for holding in holdings:
self.holdings_tree.insert("", "end", values=(
holding.get("stockCode", ""),
holding.get("stockName", ""),
holding.get("holdingQuantity", ""),
holding.get("availableQuantity", ""),
holding.get("costPrice", ""),
holding.get("currentPrice", ""),
holding.get("profitLoss", "")
))
def search_hk_stock(self):
"""搜索港股"""
code = self.hk_code_var.get().strip()
if not code:
messagebox.showwarning("警告", "请输入股票代码")
return
# 模拟搜索结果
self.hk_stock_info_var.set(f"股票代码: {code}\n股票名称: 示例港股\n当前价格: 100.50 HKD")
def search_us_stock(self):
"""搜索美股"""
code = self.us_code_var.get().strip()
if not code:
messagebox.showwarning("警告", "请输入股票代码")
return
# 模拟搜索结果
self.us_stock_info_var.set(f"股票代码: {code}\n股票名称: 示例美股\n当前价格: 150.25 USD")
def place_hk_order(self):
"""下单港股"""
code = self.hk_code_var.get().strip()
quantity = self.hk_quantity_var.get().strip()
price = self.hk_price_var.get().strip()
direction = self.hk_direction_var.get()
if not code or not quantity or not price:
messagebox.showwarning("警告", "请填写完整的交易信息")
return
try:
quantity = int(quantity)
price = float(price)
except ValueError:
messagebox.showwarning("警告", "数量和价格必须为有效数字")
return
# 禁用按钮并显示状态
self.hk_order_button.config(state="disabled")
self.hk_order_button.config(text="下单中...")
self.parent.update()
# 在新线程中下单
thread = threading.Thread(target=self._place_hk_order_thread, args=(code, quantity, price, direction))
thread.daemon = True
thread.start()
def _place_hk_order_thread(self, code, quantity, price, direction):
"""下单港股线程函数"""
try:
# 调用API下单
entrust_type = "0" if direction == "买入" else "1" # 0买入,1卖出
result = self.api_client.entrust_order(
entrust_amount=str(quantity),
entrust_price=str(price),
entrust_prop="0", # 普通委托
entrust_type=entrust_type,
exchange_type="0", # 港股
stock_code=code
)
# 更新UI
if result.get("success"):
self.parent.after(0, lambda: messagebox.showinfo("成功", "下单成功"))
else:
self.parent.after(0, lambda: messagebox.showerror("错误", f"下单失败: {result.get('message')}"))
except Exception as e:
self.parent.after(0, lambda: messagebox.showerror("错误", f"下单异常: {str(e)}"))
finally:
self.parent.after(0, lambda: self.hk_order_button.config(state="normal"))
self.parent.after(0, lambda: self.hk_order_button.config(text="下单"))
def place_us_order(self):
"""下单美股"""
code = self.us_code_var.get().strip()
quantity = self.us_quantity_var.get().strip()
price = self.us_price_var.get().strip()
direction = self.us_direction_var.get()
if not code or not quantity or not price:
messagebox.showwarning("警告", "请填写完整的交易信息")
return
try:
quantity = int(quantity)
price = float(price)
except ValueError:
messagebox.showwarning("警告", "数量和价格必须为有效数字")
return
# 禁用按钮并显示状态
self.us_order_button.config(state="disabled")
self.us_order_button.config(text="下单中...")
self.parent.update()
# 在新线程中下单
thread = threading.Thread(target=self._place_us_order_thread, args=(code, quantity, price, direction))
thread.daemon = True
thread.start()
def _place_us_order_thread(self, code, quantity, price, direction):
"""下单美股线程函数"""
try:
# 调用API下单
entrust_type = "0" if direction == "买入" else "1" # 0买入,1卖出
result = self.api_client.entrust_order(
entrust_amount=str(quantity),
entrust_price=str(price),
entrust_prop="0", # 普通委托
entrust_type=entrust_type,
exchange_type="1", # 美股
stock_code=code
)
# 更新UI
if result.get("success"):
self.parent.after(0, lambda: messagebox.showinfo("成功", "下单成功"))
else:
self.parent.after(0, lambda: messagebox.showerror("错误", f"下单失败: {result.get('message')}"))
except Exception as e:
self.parent.after(0, lambda: messagebox.showerror("错误", f"下单异常: {str(e)}"))
finally:
self.parent.after(0, lambda: self.us_order_button.config(state="normal"))
self.parent.after(0, lambda: self.us_order_button.config(text="下单"))
def process_fund(self):
"""处理资金操作"""
amount = self.fund_amount_var.get().strip()
fund_type = self.fund_type_var.get()
bank = self.bank_var.get()
if not amount:
messagebox.showwarning("警告", "请输入金额")
return
try:
amount = float(amount)
except ValueError:
messagebox.showwarning("警告", "金额必须为有效数字")
return
# 模拟资金操作
messagebox.showinfo("成功", f"{fund_type}操作已提交\n金额: {amount}\n银行: {bank}\n请在银行端确认操作")
def hide(self):
"""隐藏主窗口"""
self.notebook.grid_forget()
def create_demo_frame(self):
"""创建Demo功能测试标签页"""
self.demo_frame = ttk.Frame(self.notebook, padding="10")
self.notebook.add(self.demo_frame, text="Demo功能测试")
# 标题
title_label = ttk.Label(self.demo_frame, text="盈立证券API Demo功能测试", font=("Arial", 14, "bold"))
title_label.grid(row=0, column=0, columnspan=3, pady=(0, 20))
# 创建功能按钮框架
button_frame = ttk.LabelFrame(self.demo_frame, text="API功能测试", padding="10")
button_frame.grid(row=1, column=0, columnspan=3, pady=10, sticky=(tk.W, tk.E))
# 第一行按钮
ttk.Button(button_frame, text="基础信息查询", command=self.test_basicinfo).grid(row=0, column=0, pady=5, padx=5, sticky=tk.W)
ttk.Button(button_frame, text="市场状态查询", command=self.test_marketstate).grid(row=0, column=1, pady=5, padx=5, sticky=tk.W)
ttk.Button(button_frame, text="实时行情查询", command=self.test_realtime).grid(row=0, column=2, pady=5, padx=5, sticky=tk.W)
# 第二行按钮
ttk.Button(button_frame, text="分时数据查询", command=self.test_timeline).grid(row=1, column=0, pady=5, padx=5, sticky=tk.W)
ttk.Button(button_frame, text="K线数据查询", command=self.test_kline).grid(row=1, column=1, pady=5, padx=5, sticky=tk.W)
ttk.Button(button_frame, text="买卖盘查询", command=self.test_orderbook).grid(row=1, column=2, pady=5, padx=5, sticky=tk.W)
# 第三行按钮
ttk.Button(button_frame, text="逐笔成交查询", command=self.test_tick).grid(row=2, column=0, pady=5, padx=5, sticky=tk.W)
ttk.Button(button_frame, text="今日委托查询", command=self.test_today_entrust).grid(row=2, column=1, pady=5, padx=5, sticky=tk.W)
ttk.Button(button_frame, text="持仓查询", command=self.test_stock_holding).grid(row=2, column=2, pady=5, padx=5, sticky=tk.W)
# 第四行按钮
ttk.Button(button_frame, text="IPO列表查询", command=self.test_ipo_list).grid(row=3, column=0, pady=5, padx=5, sticky=tk.W)
ttk.Button(button_frame, text="下单测试", command=self.test_entrust_order).grid(row=3, column=1, pady=5, padx=5, sticky=tk.W)
ttk.Button(button_frame, text="改单测试", command=self.test_modify_order).grid(row=3, column=2, pady=5, padx=5, sticky=tk.W)
# 结果显示区域
result_frame = ttk.LabelFrame(self.demo_frame, text="测试结果", padding="10")
result_frame.grid(row=2, column=0, columnspan=3, pady=20, sticky=(tk.W, tk.E, tk.N, tk.S))
# 创建文本框和滚动条
self.result_text = tk.Text(result_frame, height=15, width=80)
scrollbar = ttk.Scrollbar(result_frame, orient="vertical", command=self.result_text.yview)
self.result_text.configure(yscrollcommand=scrollbar.set)
self.result_text.grid(row=0, column=0, sticky=(tk.W, tk.E, tk.N, tk.S))
scrollbar.grid(row=0, column=1, sticky=(tk.N, tk.S))
# 清空结果按钮
ttk.Button(result_frame, text="清空结果", command=self.clear_result).grid(row=1, column=0, pady=10)
# 设置列权重
self.demo_frame.columnconfigure(0, weight=1)
self.demo_frame.rowconfigure(2, weight=1)
result_frame.columnconfigure(0, weight=1)
result_frame.rowconfigure(0, weight=1)
def clear_result(self):
"""清空测试结果"""
self.result_text.delete(1.0, tk.END)
def append_result(self, text):
"""添加测试结果"""
self.result_text.insert(tk.END, text + "\n")
self.result_text.see(tk.END)
def test_basicinfo(self):
"""测试基础信息查询"""
self.append_result("=== 基础信息查询测试 ===")
# 优先使用示例API
if self.example_api_client:
try:
self.append_result("使用示例API查询基础信息...")
# 示例API不需要token也可以查询基础信息
result = self.example_api_client.basicinfo('us')
# 检查是否是Response对象(表示HTTP错误)
if hasattr(result, 'status_code'):
if result.status_code == 200:
try:
json_result = result.json()
self.append_result(f"结果: {json_result}")
except:
self.append_result(f"结果: {result.text}")
else:
self.append_result(f"示例API返回HTTP错误: {result.status_code}")
# 回退到自定义API
self._fallback_to_custom_api("basicinfo", "us")
return
else:
self.append_result(f"结果: {result}")
return
except Exception as e:
self.append_result(f"示例API调用失败: {str(e)}")
# 回退到自定义API
self._fallback_to_custom_api("basicinfo", "us")
return
# 回退到我们自己的API客户端
self._fallback_to_custom_api("basicinfo", "us")
def _fallback_to_custom_api(self, api_name, *args):
"""回退到自定义API"""
if not self.api_client:
self.append_result("API客户端未初始化")
return
# 在测试模式下,我们已经有模拟数据了
if self.api_client.token == "test_token_123456":
self.append_result(f"测试模式:使用模拟{api_name}数据")
if api_name == "basicinfo":
result = self.api_client.basicinfo(args[0] if args else "us")
elif api_name == "marketstate":
result = self.api_client.marketstate(args[0] if args else "us")
elif api_name == "realtime":
result = self.api_client.realtime(args[0] if args else ["sz000001"])
elif api_name == "timeline":
result = self.api_client.timeline(args[0] if args else "sz000001", args[1] if len(args) > 1 else 0)
elif api_name == "kline":
result = self.api_client.kline(args[0] if args else "sz000001", args[1] if len(args) > 1 else 7,
args[2] if len(args) > 2 else 20240509160000000,
args[3] if len(args) > 3 else 0,
args[4] if len(args) > 4 else 100)
elif api_name == "orderbook":
result = self.api_client.orderbook(args[0] if args else "sz000001")
elif api_name == "tick":
result = self.api_client.tick(args[0] if args else "sz000001",
args[1] if len(args) > 1 else 20201221160000000,
args[2] if len(args) > 2 else 0,
args[3] if len(args) > 3 else 2,
args[4] if len(args) > 4 else 1)
elif api_name == "today_entrust":
result = self.api_client.today_entrust(args[0] if args else "0")
elif api_name == "stock_holding":
result = self.api_client.stock_holding(args[0] if args else "0")
elif api_name == "ipo_list":
result = self.api_client.ipo_list()
elif api_name == "entrust_order":
result = self.api_client.entrust_order(
entrust_amount='100',
entrust_price='250',
entrust_prop='0',
entrust_type='0',
exchange_type='0',
stock_code='03690'
)
elif api_name == "modify_order":
result = self.api_client.modify_order(
action_type='0',
entrust_amount='0',
entrust_id="test_order_id",
entrust_price='0'
)
else:
self.append_result(f"未知的API: {api_name}")
return
self.append_result(f"结果: {result}")
return
if not self.api_client.token:
self.append_result("请先登录再进行测试")
return
# 调用我们自己的API
try:
self.append_result(f"使用自定义API查询{api_name}...")
if api_name == "basicinfo":
result = self.api_client.basicinfo(args[0] if args else "us")
elif api_name == "marketstate":
result = self.api_client.marketstate(args[0] if args else "us")
elif api_name == "realtime":
result = self.api_client.realtime(args[0] if args else ["sz000001"])
elif api_name == "timeline":
result = self.api_client.timeline(args[0] if args else "sz000001", args[1] if len(args) > 1 else 0)
elif api_name == "kline":
result = self.api_client.kline(args[0] if args else "sz000001", args[1] if len(args) > 1 else 7,
args[2] if len(args) > 2 else 20240509160000000,
args[3] if len(args) > 3 else 0,
args[4] if len(args) > 4 else 100)
elif api_name == "orderbook":
result = self.api_client.orderbook(args[0] if args else "sz000001")
elif api_name == "tick":
result = self.api_client.tick(args[0] if args else "sz000001",
args[1] if len(args) > 1 else 20201221160000000,
args[2] if len(args) > 2 else 0,
args[3] if len(args) > 3 else 2,
args[4] if len(args) > 4 else 1)
elif api_name == "today_entrust":
result = self.api_client.today_entrust(args[0] if args else "0")
elif api_name == "stock_holding":
result = self.api_client.stock_holding(args[0] if args else "0")
elif api_name == "ipo_list":
result = self.api_client.ipo_list()
elif api_name == "entrust_order":
result = self.api_client.entrust_order(
entrust_amount='100',
entrust_price='250',
entrust_prop='0',
entrust_type='0',
exchange_type='0',
stock_code='03690'
)
elif api_name == "modify_order":
result = self.api_client.modify_order(
action_type='0',
entrust_amount='0',
entrust_id="test_order_id",
entrust_price='0'
)
else:
self.append_result(f"未知的API: {api_name}")
return
self.append_result(f"结果: {result}")
except Exception as e:
self.append_result(f"自定义API调用失败: {str(e)}")
def test_marketstate(self):
"""测试市场状态查询"""
self.append_result("=== 市场状态查询测试 ===")
# 优先使用示例API
if self.example_api_client:
try:
self.append_result("使用示例API查询市场状态...")
# 示例API不需要token也可以查询市场状态
result = self.example_api_client.marketstate('us')
# 检查是否是Response对象(表示HTTP错误)
if hasattr(result, 'status_code'):
if result.status_code == 200:
try:
json_result = result.json()
self.append_result(f"结果: {json_result}")
except:
self.append_result(f"结果: {result.text}")
else:
self.append_result(f"示例API返回HTTP错误: {result.status_code}")
# 回退到自定义API
self._fallback_to_custom_api("marketstate", "us")
return
else:
self.append_result(f"结果: {result}")
return
except Exception as e:
self.append_result(f"示例API调用失败: {str(e)}")
# 回退到自定义API
self._fallback_to_custom_api("marketstate", "us")
return
# 回退到我们自己的API客户端
self._fallback_to_custom_api("marketstate", "us")
def test_realtime(self):
"""测试实时行情查询"""
self.append_result("=== 实时行情查询测试 ===")
# 优先使用示例API
if self.example_api_client:
try:
self.append_result("使用示例API查询实时行情...")
# 示例API不需要token也可以查询实时行情
result = self.example_api_client.realtime(secuIds=["sz000001"])
# 检查是否是Response对象(表示HTTP错误)
if hasattr(result, 'status_code'):
if result.status_code == 200:
try:
json_result = result.json()
self.append_result(f"结果: {json_result}")
except:
self.append_result(f"结果: {result.text}")
else:
self.append_result(f"示例API返回HTTP错误: {result.status_code}")
# 回退到自定义API
self._fallback_to_custom_api("realtime", ["sz000001"])
return
else:
self.append_result(f"结果: {result}")
return
except Exception as e:
self.append_result(f"示例API调用失败: {str(e)}")
# 回退到自定义API
self._fallback_to_custom_api("realtime", ["sz000001"])
return
# 回退到我们自己的API客户端
self._fallback_to_custom_api("realtime", ["sz000001"])
def test_timeline(self):
"""测试分时数据查询"""
self.append_result("=== 分时数据查询测试 ===")
# 优先使用示例API
if self.example_api_client:
try:
self.append_result("使用示例API查询分时数据...")
# 示例API不需要token也可以查询分时数据
result = self.example_api_client.timeline(secuId="sz000001", type=0)
self.append_result(f"结果: {result}")
return
except Exception as e:
self.append_result(f"示例API调用失败: {str(e)}")
# 回退到我们自己的API客户端
if not self.api_client:
self.append_result("API客户端未初始化")
return
# 在测试模式下,我们已经有模拟数据了
if self.api_client.token == "test_token_123456":
self.append_result("测试模式:使用模拟分时数据")
result = self.api_client.timeline(secuId="sz000001", type=0)
self.append_result(f"结果: {result}")
return
if not self.api_client.token:
self.append_result("请先登录再进行测试")
return
# 调用我们自己的API
try:
self.append_result("使用自定义API查询分时数据...")
result = self.api_client.timeline(secuId="sz000001", type=0)
self.append_result(f"结果: {result}")
except Exception as e:
self.append_result(f"自定义API调用失败: {str(e)}")
def test_kline(self):
"""测试K线数据查询"""
self.append_result("=== K线数据查询测试 ===")
# 优先使用示例API
if self.example_api_client:
try:
self.append_result("使用示例API查询K线数据...")
# 注意:这里需要有效的参数
result = self.example_api_client.kline(secuId="sz000001", type=7, start=20240509160000000, right=0, count=100)
self.append_result(f"结果: {result}")
return
except Exception as e:
self.append_result(f"示例API调用失败: {str(e)}")
# 回退到我们自己的API客户端
if not self.api_client:
self.append_result("API客户端未初始化")
return
# 在测试模式下,我们已经有模拟数据了
if self.api_client.token == "test_token_123456":
self.append_result("测试模式:使用模拟K线数据")
result = self.api_client.kline(secuId="sz000001", type=7, start=20240509160000000, right=0, count=100)
self.append_result(f"结果: {result}")
return
if not self.api_client.token:
self.append_result("请先登录再进行测试")
return
# 调用我们自己的API
try:
self.append_result("使用自定义API查询K线数据...")
result = self.api_client.kline(secuId="sz000001", type=7, start=20240509160000000, right=0, count=100)
self.append_result(f"结果: {result}")
except Exception as e:
self.append_result(f"自定义API调用失败: {str(e)}")
def test_orderbook(self):
"""测试买卖盘查询"""
self.append_result("=== 买卖盘查询测试 ===")
# 优先使用示例API
if self.example_api_client:
try:
self.append_result("使用示例API查询买卖盘...")
# 示例API不需要token也可以查询买卖盘
result = self.example_api_client.orderbook(secuId="sz000001")
# 检查是否是Response对象(表示HTTP错误)
if hasattr(result, 'status_code'):
if result.status_code == 200:
try:
json_result = result.json()
self.append_result(f"结果: {json_result}")
except:
self.append_result(f"结果: {result.text}")
else:
self.append_result(f"示例API返回HTTP错误: {result.status_code}")
# 回退到自定义API
self._fallback_to_custom_api("orderbook", "sz000001")
return
else:
self.append_result(f"结果: {result}")
return
except Exception as e:
self.append_result(f"示例API调用失败: {str(e)}")
# 回退到自定义API
self._fallback_to_custom_api("orderbook", "sz000001")
return
# 回退到我们自己的API客户端
self._fallback_to_custom_api("orderbook", "sz000001")
def test_tick(self):
"""测试逐笔成交查询"""
self.append_result("=== 逐笔成交查询测试 ===")
# 优先使用示例API
if self.example_api_client:
try:
self.append_result("使用示例API查询逐笔成交...")
# 注意:这里需要有效的参数
result = self.example_api_client.tick(secuId="sz000001", tradeTime=20201221160000000, seq=0, count=2, sortDirection=1)
# 检查是否是Response对象(表示HTTP错误)
if hasattr(result, 'status_code'):
if result.status_code == 200:
try:
json_result = result.json()
self.append_result(f"结果: {json_result}")
except:
self.append_result(f"结果: {result.text}")
else:
self.append_result(f"示例API返回HTTP错误: {result.status_code}")
# 回退到自定义API
self._fallback_to_custom_api("tick", "sz000001", 20201221160000000, 0, 2, 1)
return
else:
self.append_result(f"结果: {result}")
return
except Exception as e:
self.append_result(f"示例API调用失败: {str(e)}")
# 回退到自定义API
self._fallback_to_custom_api("tick", "sz000001", 20201221160000000, 0, 2, 1)
return
# 回退到我们自己的API客户端
self._fallback_to_custom_api("tick", "sz000001", 20201221160000000, 0, 2, 1)
def test_today_entrust(self):
"""测试今日委托查询"""
self.append_result("=== 今日委托查询测试 ===")
# 优先使用示例API
if self.example_api_client:
try:
self.append_result("使用示例API查询今日委托...")
result = self.example_api_client.today_entrust(exchangeType='0')
# 检查是否是Response对象(表示HTTP错误)
if hasattr(result, 'status_code'):
if result.status_code == 200:
try:
json_result = result.json()
self.append_result(f"结果: {json_result}")
except:
self.append_result(f"结果: {result.text}")
else:
self.append_result(f"示例API返回HTTP错误: {result.status_code}")
# 回退到自定义API
self._fallback_to_custom_api("today_entrust", "0")
return
else:
self.append_result(f"结果: {result}")
return
except Exception as e:
self.append_result(f"示例API调用失败: {str(e)}")
# 回退到自定义API
self._fallback_to_custom_api("today_entrust", "0")
return
# 回退到我们自己的API客户端
self._fallback_to_custom_api("today_entrust", "0")
def test_stock_holding(self):
"""测试持仓查询"""
self.append_result("=== 持仓查询测试 ===")
# 优先使用示例API
if self.example_api_client:
try:
self.append_result("使用示例API查询持仓...")
result = self.example_api_client.stock_holding('0')
# 检查是否是Response对象(表示HTTP错误)
if hasattr(result, 'status_code'):
if result.status_code == 200:
try:
json_result = result.json()
self.append_result(f"结果: {json_result}")
except:
self.append_result(f"结果: {result.text}")
else:
self.append_result(f"示例API返回HTTP错误: {result.status_code}")
# 回退到自定义API
self._fallback_to_custom_api("stock_holding", "0")
return
else:
self.append_result(f"结果: {result}")
return
except Exception as e:
self.append_result(f"示例API调用失败: {str(e)}")
# 回退到自定义API
self._fallback_to_custom_api("stock_holding", "0")
return
# 在测试模式下,我们已经有模拟数据了
if self.api_client and self.api_client.token == "test_token_123456":
self.append_result("测试模式:使用模拟持仓数据")
result = self.api_client.stock_holding("0")
if result["success"]:
for holding in result["data"]:
self.append_result(f"股票代码: {holding['stockCode']}, 股票名称: {holding['stockName']}, 持仓数量: {holding['holdingQuantity']}")
return
if not self.api_client or not self.api_client.token:
self.append_result("请先登录再进行测试")
return
# 调用我们自己的API
try:
self.append_result("使用自定义API查询持仓...")
result = self.api_client.stock_holding("0")
self.append_result(f"结果: {result}")
except Exception as e:
self.append_result(f"自定义API调用失败: {str(e)}")
def test_ipo_list(self):
"""测试IPO列表查询"""
self.append_result("=== IPO列表查询测试 ===")
# 优先使用示例API
if self.example_api_client:
try:
self.append_result("使用示例API查询IPO列表...")
result = self.example_api_client.ipo_list(status=0)
# 检查是否是Response对象(表示HTTP错误)
if hasattr(result, 'status_code'):
if result.status_code == 200:
try:
json_result = result.json()
self.append_result(f"结果: {json_result}")
except:
self.append_result(f"结果: {result.text}")
else:
self.append_result(f"示例API返回HTTP错误: {result.status_code}")
# 回退到自定义API
self._fallback_to_custom_api("ipo_list", 0)
return
else:
self.append_result(f"结果: {result}")
return
except Exception as e:
self.append_result(f"示例API调用失败: {str(e)}")
# 回退到自定义API
self._fallback_to_custom_api("ipo_list", 0)
return
# 回退到我们自己的API客户端
self._fallback_to_custom_api("ipo_list", 0)
def test_entrust_order(self):
"""测试下单功能"""
self.append_result("=== 下单功能测试 ===")
# 优先使用示例API
if self.example_api_client:
try:
self.append_result("使用示例API进行下单测试...")
# 注意:这里只是测试调用,实际下单需要谨慎
result = self.example_api_client.entrust_order(
entrustAmount='100',
entrustPrice='250',
entrustProp='0',
entrustType='0',
exchangeType='0',
stockCode='03690',
forceEntrustFlag=True
)
# 检查是否是Response对象(表示HTTP错误)
if hasattr(result, 'status_code'):
if result.status_code == 200:
try:
json_result = result.json()
self.append_result(f"结果: {json_result}")
except:
self.append_result(f"结果: {result.text}")
else:
self.append_result(f"示例API返回HTTP错误: {result.status_code}")
# 回退到自定义API
self._fallback_to_custom_api("entrust_order")
return
else:
self.append_result(f"结果: {result}")
return
except Exception as e:
self.append_result(f"示例API调用失败: {str(e)}")
# 回退到自定义API
self._fallback_to_custom_api("entrust_order")
return
# 回退到我们自己的API客户端
self._fallback_to_custom_api("entrust_order")
def test_modify_order(self):
"""测试改单功能"""
self.append_result("=== 改单功能测试 ===")
# 优先使用示例API
if self.example_api_client:
try:
self.append_result("使用示例API进行改单测试...")
# 注意:这里只是测试调用,实际改单需要有效的委托ID
result = self.example_api_client.modify_order(
actionType='0',
entrustAmount='0',
entrustId="test_order_id",
entrustPrice='0',
forceEntrustFlag=True
)
# 检查是否是Response对象(表示HTTP错误)
if hasattr(result, 'status_code'):
if result.status_code == 200:
try:
json_result = result.json()
self.append_result(f"结果: {json_result}")
except:
self.append_result(f"结果: {result.text}")
else:
self.append_result(f"示例API返回HTTP错误: {result.status_code}")
# 回退到自定义API
self._fallback_to_custom_api("modify_order")
return
else:
self.append_result(f"结果: {result}")
return
except Exception as e:
self.append_result(f"示例API调用失败: {str(e)}")
# 回退到自定义API
self._fallback_to_custom_api("modify_order")
return
# 回退到我们自己的API客户端
self._fallback_to_custom_api("modify_order")
def show(self):
"""显示主窗口"""
self.notebook.grid(row=0, column=0, sticky=(tk.W, tk.E, tk.N, tk.S))
# 刷新持仓信息
self.refresh_holdings()
登录界面
系统启动后显示登录界面,用户可选择账号密码登录或短信验证码登录方式。测试模式允许用户跳过登录流程直接进入系统,方便功能测试和演示。
账号密码登录需要输入手机号和密码,点击登录按钮完成验证。短信验证码登录需先输入手机号获取验证码,填写正确验证码后点击验证码登录按钮。测试模式按钮位于登录界面,点击后直接进入系统主界面。
账户管理
账户管理页面展示用户的持仓信息和交易员管理功能。持仓信息板块显示港股和美股持仓详情,包括证券代码、名称、数量、成本价、当前价和盈亏等数据。点击刷新持仓按钮可更新最新持仓数据。
交易员管理功能显示已授权交易员列表,支持添加新交易员或删除现有交易员。该功能便于用户管理账户权限,确保交易安全。
港股交易
港股交易页面提供港股买卖操作功能。股票搜索栏可输入港股代码查询对应股票信息。交易操作板块可选择买入或卖出方向,输入交易数量和价格后点击下单按钮提交委托。
交易界面显示实时行情数据,帮助用户做出交易决策。委托状态区域展示当前委托的执行情况,便于用户跟踪交易进展。
美股交易
美股交易页面功能与港股交易类似,专门针对美股市场设计。用户可通过输入美股代码搜索目标股票,获取实时行情信息。交易操作支持买入和卖出两种方向,需填写交易数量和价格参数。
美股交易遵循当地市场规则,系统会自动处理交易时间限制等特殊要求。交易记录板块保存历史委托信息,方便用户回溯分析。
资金管理
资金管理页面支持入金和出金操作,并显示详细的资金流水记录。资金操作板块可选择入金或出金类型,填写操作金额并选择银行账户后确认提交。
资金流水区域按时间顺序显示历史资金操作记录,包括操作类型、金额、状态等信息。该功能帮助用户清晰掌握资金变动情况,便于财务管理。
AI交易策略
AI交易策略页面为扩展功能模块,支持接入国内主流AI大模型开发交易策略。模型配置区可选择豆包、DeepSeek等提供商,填写API密钥和模型名称完成设置。
策略配置部分需定义策略名称、描述、目标市场和风险等级。操作控制区提供保存策略、测试策略和启停策略等功能。状态监控面板实时显示策略运行状态和详细日志。
Demo功能测试
Demo功能测试页面提供对盈立证券API主要功能的测试入口。行情查询测试包含基础信息、市场状态、实时行情等多项查询功能。交易功能测试覆盖委托查询、持仓查询、IPO查询等核心交易操作。
测试结果会显示在页面日志区域,帮助开发者验证API调用流程。该功能便于系统调试和功能验证,确保交易接口稳定可靠。
系统配置
系统配置文件config.json包含交易主机、行情主机等关键参数。默认用户配置存储了登录所需的手机号、密码和密钥信息。
配置文件采用JSON格式,结构清晰易于修改。用户可根据实际需求调整服务器地址等参数,但修改密钥等安全信息需谨慎操作。
常见问题
登录失败通常由网络问题或凭证错误引起,建议检查网络连接并确认账号密码正确。无法获取行情数据时可检查token状态和股票代码格式。
测试模式使用模拟数据展示系统功能,适合演示和测试场景。AI交易策略功能需要有效API密钥和后续开发支持,当前版本仅提供基础框架。
更多推荐


所有评论(0)