量化交易系统,基于迅投QMT交易API,实现了您需要的所有功能。系统有六个主要模块,各自负责不同功能,同时支持React前端界面交互。
-
核心模块:
config.py- 集中管理所有配置参数logger.py- 日志管理,包括日志自动清理main.py- 系统主入口,负责初始化和管理各模块utils.py- 工具函数集合
-
数据处理:
data_manager.py- 负责历史数据获取与存储indicator_calculator.py- 计算各种技术指标(MACD、均线等)
-
交易策略:
strategy.py- 实现核心交易策略position_manager.py- 持仓管理和监控trading_executor.py- 交易执行和订单管理
-
Web服务:
web_server.py- 提供RESTful API接口供React前端调用
系统严格遵循您提出的交易策略规则:
-
分仓买入
- 每次买入固定金额(默认20000元)
- 根据建仓成本价格比例(93%、86%等)设置补仓点位
- 达到仓位上限(默认50000元)后停止买入
- 总持仓成本损失超过9.5%时全仓止损
-
动态止盈
- 实现浮盈比例与止盈位动态关联
- 首次盈利达到5%时卖出半仓保证胜率
- 余下仓位根据动态止盈位置卖出,盈利越多回调空间越大
-
网格交易
- 对持仓个股进行自动网格交易
- 可调整网格幅度和每格交易量
-
自动日志管理
- 自动清理过期日志文件,不占用存储空间
- 模块化设计:每个功能独立成模块,代码结构清晰
- 参数可配置:所有交易参数集中管理,易于调整
- RESTful API:提供完整API供前端调用
- 丰富的日志:详细记录系统运行和交易过程
- 错误处理:完善的异常处理机制
- 自动化运行:支持无人值守的自动交易
- 手动交易接口:支持人工干预和操作
-
确保安装了必要的Python包:
pip install pandas numpy talib flask flask-cors xtquant -
创建账户配置文件
account_config.json:{ "account_id": "你的交易账号", "account_type": "STOCK" } -
启动系统:
python main.py -
访问Web界面(React前端):
http://localhost:5000
- 可以增强交易策略,加入更多技术指标
- 增加回测功能,评估策略效果
- 优化网格交易算法
- 添加风控模块,加强交易安全性
- 增加数据分析和可视化功能
这个系统设计已经考虑了QMT API的特性,并实现了完整的交易生命周期管理,可以有效地支持量化交易策略的执行。
好的,我来解读一下 position_manager.py 文件中的 PositionManager 类,并尽量用简洁的中文进行说明。
PositionManager 类:持仓管理的核心
这个类主要负责管理股票的持仓信息,包括:
持仓数据的存储和获取:
使用 SQLite 数据库来存储持仓信息,包括股票代码、数量、成本价、当前价格、市值、盈亏比例等。 提供 get_all_positions() 和 get_position() 方法来获取所有持仓或指定股票的持仓信息。 _sync_real_positions_to_db() 方法负责将实盘交易账户的持仓数据同步到数据库中,保持数据一致性。 _update_stock_positions_file() 方法负责更新 stock_positions.json 文件,记录当前持仓的股票代码。 持仓信息的更新:
update_position() 方法用于更新或新增持仓信息。它会自动计算市值、盈亏比例,并记录最后更新时间。 update_all_positions_price() 方法用于批量更新所有持仓的最新价格。 update_all_positions_highest_price() 方法用于批量更新所有持仓的最高价。 remove_position() 方法用于删除持仓记录(例如清仓时)。 止损止盈策略的检查:
check_stop_loss() 方法用于检查是否触发止损条件。 check_dynamic_take_profit() 方法用于检查是否触发动态止盈条件。 calculate_stop_loss_price() 方法用于计算止损价格,支持固定止损和动态止损。 mark_profit_triggered() 方法用于标记股票已触发首次止盈。 网格交易的管理:
get_grid_trades() 方法用于获取指定股票的网格交易记录。 add_grid_trade() 方法用于添加新的网格交易记录。 update_grid_trade_status() 方法用于更新网格交易的状态(例如:PENDING, ACTIVE, COMPLETED)。 check_grid_trade_signals() 方法用于检查网格交易的买入/卖出信号。 监控线程:
start_position_monitor_thread() 方法用于启动一个后台线程,定期监控持仓状态,包括更新价格、检查止损止盈条件、检查网格交易信号等。 stop_position_monitor_thread() 方法用于停止监控线程。 _position_monitor_loop() 方法是监控线程的循环体,负责执行监控任务。 与实盘交易账户的交互
使用了easy_qmt_trader类,通过self.qmt_trader对象与QMT实盘交易账户进行交互,获取实盘持仓数据。 _is_test_environment() 方法用于判断是否在测试环境中,如果在测试环境,则不进行实盘数据同步。 与数据管理模块的交互
使用了data_manager模块,通过self.data_manager对象获取最新行情数据。 核心功能总结:
存储和管理持仓数据。 实时更新持仓信息(价格、市值、盈亏等)。 实现止损止盈策略。 管理网格交易。 后台监控持仓状态。 与实盘交易账户进行交互,同步持仓数据。 与数据管理模块进行交互,获取最新行情。 总而言之,PositionManager 类是整个量化交易系统中负责持仓管理的核心组件,它提供了完善的持仓数据管理、止损止盈策略、网格交易管理和监控功能。
我希望在代码运行时增加一个position_manager的内存数据库,用于实时保存和更新持仓数据所有记录,内存数据库的结构与data_manager的持仓表positions保持一致,
- stock_code, volume, available, cost_price,market_value 以easy_qmt_trader.position方法作为权威数据来源,是从xtquant接口获得的账号实时持仓真实数据
- current_price, 通过data_manager的get_latest_data方法获得股票的最新价格,盘中时间用xtdata的tick数据,盘后时间用mootdx的历史数据
- highest_price, 通过position_manager.update_all_positions_highest_price方法获得
- profit_ratio,以 current_price, cost_price, volume为数据源,通过计算得到
- open_date, profit_triggered, highest_price, stop_loss_price需要通过sqlite数据库实现持久化,一旦数据发生变更就要将它们更新到数据库里,并在last_update里记录操作时间
总而言之,内存数据库的关键持仓信息来自xtquant接口,其他需要高频次更新的数据来自data_manager,数据库里保存了需要持久化的内容。 最简单的修改方式,是把所有对sqlite数据库进行操作的函数,修改为对内存数据库的操作,每隔一段时间(如5秒),把内存数据库里需要持久化的内容保存到sqlite数据库里。
| 方面 | 模拟交易 | 实盘交易 |
|---|---|---|
| 数据存储 | 仅内存数据库 | 内存数据库 + SQLite持久化 |
| 资金来源 | config.SIMULATION_BALANCE | 实际交易账户资金 |
| 订单执行 | 生成模拟订单ID, 不调用交易API | 调用实际交易API执行订单 |
| 订单记录 | strategy='simu'标记 | 正常交易策略名称 |
| API调用 | 绕过实际交易API | 正常调用交易API |
| 数据标签 | 数据来源 | 更新方式 |
|---|---|---|
| stock_code | QMT实盘交易系统 | 从qmt_trader.position()的'证券代码'字段获取 |
| volume | QMT实盘交易系统 | 从qmt_trader.position()的'股票余额'字段获取;交易成交后更新 |
| available | QMT实盘交易系统 | 从qmt_trader.position()的'可用余额'字段获取;交易委托和撤单后更新 |
| cost_price | QMT实盘交易系统 | 从qmt_trader.position()的'成本价'字段获取;新增或平均持仓成本时更新 |
| current_price | 行情API | 从data_manager.get_latest_data()获取最新价格,优先使用xtquant,备选Mootdx |
| market_value | 计算值 | 实时计算:volume * current_price |
| profit_ratio | 计算值 | 实时计算:(current_price - cost_price) / cost_price * 100 |
| last_update | 系统时间 | 每次更新持仓数据时写入当前系统时间 |
| open_date | 多来源 | 新建仓位时为当前时间;或从SQLite数据库同步;避免被覆盖 |
| profit_triggered | 策略逻辑 | 根据check_dynamic_take_profit函数判断是否触发首次止盈 |
| highest_price | 历史数据+实时行情 | 从历史K线获取最高价(Methods.getStockData),与当前价格比较后更新 |
| stop_loss_price | 策略计算 | 根据calculate_stop_loss_price函数基于成本价、最高价和止盈状态计算 |
- 定时刷新:
update_all_positions_price函数定期更新所有持仓的价格相关数据 - 实盘同步:
_sync_real_positions_to_memory从QMT交易系统同步最新持仓数据 - 交易触发:买入/卖出成交后通过
_update_position_after_trade更新持仓 - 策略执行:持仓监控线程
_position_monitor_loop检查止盈止损条件并更新相关标记 - 手动更新:通过Web接口的API请求手动更新持仓参数
系统会在交易时间内更频繁地刷新行情相关字段,而持仓基础信息则在交易成交后才会更新。
根据代码审查,我将分析用户从网页触发买入和卖出操作(包括模拟和实盘模式),以及"全局监控开关"启用时的自动仓位管理操作(包括网格策略和动态止盈止损策略)。
网页触发买入流程:
- 用户在页面选择买入策略(随机池或自定义股票)
- 设置买入数量并点击"一键买入"按钮
- 前端发送请求到
/api/actions/execute_buy接口 - 服务器处理请求并调用
trading_strategy.manual_buy方法 trading_strategy.manual_buy调用trading_executor.buy_stock执行实际交易
网页触发卖出操作:
由于前端页面没有显式的卖出按钮,可能通过持仓列表中的操作来触发,后端相应调用trading_strategy.manual_sell方法,最终通过trading_executor.sell_stock执行交易。
当全局监控开关(config.ENABLE_AUTO_TRADING)打开时,系统会启动策略线程(strategy._strategy_loop),定期执行以下策略:
- 止损策略:当股票价格跌至止损价以下时,执行全仓卖出
- 动态止盈策略:
- 首次止盈:当利润达到设定阈值(默认5%)时,卖出部分持仓(默认50%)
- 动态止盈:根据历史最高价设定止盈线,价格回落到止盈线以下时卖出
- 网格交易策略:根据预设的价格网格,在价格达到网格点位时执行买入或卖出
- 技术指标买入策略:基于MACD金叉等技术指标,在满足条件时执行买入
- 技术指标卖出策略:基于MACD死叉等技术指标,在满足条件时执行卖出
| 模拟交易模式 | 实盘交易模式 |
|---|---|
| 交易记录和持仓变化仅在内存中记录 | 通过实际交易接口(QMT)提交订单 |
模拟资金从config.SIMULATION_BALANCE中扣除或增加 |
使用实际账户资金 |
| 可以忽略交易时间限制 | 必须在交易时间内才能交易 |
| 可以放宽买卖权限限制 | 严格受买卖权限限制 |
生成虚拟订单ID:SIM[时间戳][计数器] |
使用实际交易接口返回的订单ID |
| 使用模拟手续费率(买入0.0003,卖出0.0013) | 使用实际交易的手续费 |
| 特性 | 网页触发交易 | 全局监控开关自动交易 |
|---|---|---|
| 触发方式 | 用户手动点击按钮 | 系统自动定期检查触发条件 |
| 交易时间 | 模拟模式下可忽略交易时间限制 | 仅在交易时间内执行 |
| 买入策略 | 从股票池中选择或自定义 | 基于技术指标和网格策略 |
| 买入金额 | 固定为config.POSITION_UNIT |
根据不同买入级别动态调整 |
| 卖出策略 | 用户指定卖出数量或比例 | 基于止损、止盈或网格策略 |
| 交易接口 | 根据模式调用不同交易函数 | 相同,但添加信号去重逻辑 |
| 异常处理 | 即时返回错误给用户 | 日志记录错误并继续处理其他股票 |
| 策略应用 | 单一交易,无策略组合 | 多策略按优先级顺序执行 |
| 风控机制 | 基本检查(资金、持仓、交易规则) | 完整的止损、止盈和仓位控制 |
| 初次买入后 | 可选择性初始化网格交易 | 自动初始化网格交易(如启用) |
网页触发买入调用链:
前端点击 → API(/api/actions/execute_buy) → trading_strategy.manual_buy → trading_executor.buy_stock → 模拟交易或实盘交易接口
自动交易买入调用链: 执行调用流程 信号检测流程 position_monitor_loop() ↓ check_trading_signals() [position_manager] ↓ {signal_type, signal_info} → latest_signals队列 策略执行流程 check_and_execute_strategies() [strategy] ↓ get_pending_signals() ↓ execute_trading_signal_direct() ↓ 模拟交易: simulate_sell_position() [position_manager] 实盘交易: sell_stock() [trading_executor] → QMT API 模拟交易执行路径 python# 模拟交易直接操作内存数据库 simulate_sell_position() → _save_simulated_trade_record() # 保存记录 → _simulate_update_position() # 更新持仓 → config.SIMULATION_BALANCE += revenue # 更新资金 实盘交易执行路径 python# 实盘交易通过QMT接口 sell_stock() [trading_executor] → qmt_trader.sell() # QMT API调用 → _save_trade_record() # 成交后回调保存