#!/usr/bin/env python3 """ 在Docker容器内直接运行回测 - 不经过HTTP API 针对 510300.SSE 的单票回测 """ # ============================================ # 1. 风控模块代码 (risk_control.py) # ============================================ RISK_CONTROL_CODE = ''' """ 风控模块 - 量化策略风控系统 功能: 1. 单票15%止损规则 2. 整体回撤分级风控(10%/20%/25% 分级降仓) 3. 黑天鹅过滤(ST、跌停、财务造假排除) Author: 关羽(云长) Date: 2026-03-27 """ from dataclasses import dataclass import pandas as pd @dataclass class StockInfo: """单票基本信息""" code: str name: str cost_price: float current_price: float is_st: bool = False is_limit_down: bool = False is_fraud: bool = False volume: float = 0.0 # 日成交额(亿) @dataclass class PortfolioInfo: """组合信息""" total_capital: float current_capital: float positions: dict[str, float] # code -> position_size class SingleStockRiskControl: """单票风控:15%止损规则""" def __init__(self, stop_loss_pct: float = 0.15): self.stop_loss_pct = stop_loss_pct def check_stop_loss(self, stock: StockInfo) -> bool: """检查是否触发止损""" if stock.cost_price <= 0: return False drawdown = (stock.current_price - stock.cost_price) / stock.cost_price return drawdown <= -self.stop_loss_pct def get_drawdown(self, stock: StockInfo) -> float: """计算单票当前回撤""" if stock.cost_price <= 0: return 0.0 return (stock.current_price - stock.cost_price) / stock.cost_price class PortfolioDrawdownRiskControl: """整体回撤分级风控""" def __init__(self, drawdown_levels=None, reduce_ratios=None): self.drawdown_levels = drawdown_levels or [0.10, 0.20, 0.25] self.reduce_ratios = reduce_ratios or [0.50, 0.25, 0.00] def calculate_total_drawdown(self, portfolio: PortfolioInfo) -> float: """计算组合总回撤""" if portfolio.total_capital <= 0: return 0.0 return (portfolio.total_capital - portfolio.current_capital) / portfolio.total_capital def get_target_position_ratio(self, portfolio: PortfolioInfo) -> float: """获取目标仓位比例""" drawdown = self.calculate_total_drawdown(portfolio) for level, ratio in reversed(list(zip(self.drawdown_levels, self.reduce_ratios))): if drawdown >= level: return ratio return 1.0 class RiskController: """总风控控制器""" def __init__(self): self.single_stock_rc = SingleStockRiskControl() self.portfolio_rc = PortfolioDrawdownRiskControl() ''' # ============================================ # 2. 简化策略代码 (回测510300.SSE单票) # ============================================ SIMPLE_STRATEGY_CODE = ''' """ 简化版策略 - 针对510300.SSE的单票回测测试 """ from vnpy.app.cta_strategy import CtaTemplate class SingleStockStopLossStrategy(CtaTemplate): """ 简化版单票策略 - 测试510300.SSE """ parameters = ["fast_window", "slow_window", "stop_loss_pct"] variables = ["stop_loss_triggered"] def __init__(self, cta_engine, strategy_name, setting_dict): super().__init__(cta_engine, strategy_name, setting_dict) self.fast_window = getattr(self, 'fast_window', 5) self.slow_window = getattr(self, 'slow_window', 20) self.stop_loss_pct = getattr(self, 'stop_loss_pct', 0.15) self.stop_loss_triggered = False def on_init(self): self.write_log("策略初始化") self.load_bar(100) def on_bar(self, bar): # 检查止损 if self.pos > 0: profit = (bar.close_price - self.avg_price) / self if profit <= -self.stop_loss_pct: self.write_log(f"触发止损: {bar.datetime}, 回撤: {profit:.2%}") self.stop_loss_triggered = True self.sell(bar.close_price, abs(self.pos)) return # 简单均线策略 if not self.stop_loss_triggered: if bar.close_price > self.amo(bar.close_price, self.fast_window): if self.pos == 0: self.buy(bar.close_price, 10000) elif bar.close_price < self.amo(bar.close_price, self.slow_window): if self.pos > 0: self.sell(bar.close_price, abs(self.pos)) ''' # ============================================ # 3. 执行回测 # ============================================ # 导入必要模块 import types import sys print("=" * 80) print("🚀 在Docker容器内直接运行回测") print("=" * 80) # 加载vnpy.app兼容性模块 vnpy_app_module = types.ModuleType('vnpy.app') sys.modules['vnpy.app'] = vnpy_app_module submodules = ['cta_strategy', 'cta_backtester', 'data_manager'] for name in submodules: full_name = f'vnpy.app.{name}' submodule = types.ModuleType(full_name) sys.modules[full_name] = submodule setattr(vnpy_app_module, name, submodule) from vnpy_ctastrategy import CtaTemplate, BarData sys.modules['vnpy.app.cta_strategy'].CtaTemplate = CtaTemplate from vnpy_ctabacktester import BacktesterEngine sys.modules['vnpy.app.cta_backtester'].BacktesterEngine = BacktesterEngine print("✅ vnpy.app兼容性模块加载完成") # 执行风控代码 exec(RISK_CONTROL_CODE, globals()) # 执行策略代码 exec(SIMPLE_STRATEGY_CODE, globals()) # 运行回测 from vnpy.event import EventEngine from vnpy.trader.engine import MainEngine from vnpy.trader.constant import Exchange, Interval from datetime import datetime print("\n" + "=" * 80) print("初始化回测引擎...") print("=" * 80) event_engine = EventEngine() main_engine = MainEngine(event_engine) # 手动实例化BacktesterEngine backtester_engine = BacktesterEngine(main_engine, event_engine) backtester_engine.classes["SingleStockStopLossStrategy"] = SingleStockStopLossStrategy print("✅ BacktesterEngine 初始化完成") # 加载数据 print("\n" + "=" * 80) print("加载数据...") print("=" * 80) from vnpy.trader.database import get_database db = get_database() symbol = "510300" exchange = Exchange.SSE interval = Interval.DAILY start = datetime(2021, 1, 1) end = datetime(2026, 3, 1) bars = db.load_bar_data(symbol, exchange, interval, start, end) print(f"✅ 加载了 {len(bars)} 条bar数据") if len(bars) == 0: [TRUNCATED]