核心提炼:突破传统趋势跟踪的四大战略支点
在资深趋势交易者和基金经理的圈子里,一个共识日益清晰:传统趋势跟踪策略虽然历久弥坚,但其优化之路已不再局限于经典的入场、出场点位微调。精研均线周期、ATR倍数或是指标过滤,往往陷入胜率、赔率、频率的“不可能三角”困境,难以带来质变。真正的突破,在于更宏观、更结构化的策略升级。以下是从讨论中提炼出的四大战略支点:
支点一:战场精选 —— 从“广撒网”到“精准打击” (Universe Intelligence)
- 传统困境: 全品种覆盖虽能保证捕捉到所有大趋势,但伴随高昂的试错成本(交易“垃圾”品种)、低下的资金效率(分散导致单品种仓位不足),整体盈利能力受限。
- 战略升级: 实施动态、智能化的品种筛选机制。目标是将火力集中在最有潜力的10-20个品种上。
- 实现路径:
- 趋势质量甄别: 运用截面排序等方法,定期识别并聚焦于当前趋势性最强、波动最流畅的品种。
- 预期驱动: 结合基本面分析或事件驱动,预判未来可能出现大幅波动的品种,提前布局。
- 核心收益: 提高资金集中度,放大在趋势行情中的盈利;剔除表现不佳的品种,有望降低整体回撤。
- 风险权衡: 方法论至关重要,筛选不当可能错失“黑马”,需要精妙的平衡艺术,是追求超额收益但也可能导致表现不及基准的双刃剑。
- 实现路径:
支点二:兵力调度 —— 让资金管理成为阿尔法来源 (Dynamic Capital Allocation)
- 超越静态: 简单的固定比例或固定手数已不能满足高级需求。资金管理本身就是一门可以深度优化的学科,其对最终资金曲线的影响力不亚于交易信号。
- 战略升级: 建立一套响应式、多维度的资金调配系统。
- 实现路径:
- 风险预算动态化: 根据市场波动率调整风险敞口(例如,波动率上升时是加仓还是减仓?)。
- 绩效反馈: 基于策略或品种的近期表现调整仓位分配(“赢冲输缩”或反之?表现好的品种是加仓还是减仓?)。
- 组合视角: 借鉴现代投资组合理论,根据品种间的相关性进行仓位优化,分散风险。
- 权益曲线交易: 将自身的资金曲线视为交易标的,进行“高抛低吸”式的仓位调节。
- 极端情况预案: 包含手动干预机制,应对类似“双十一”或特定政策冲击等极端市场事件,强制降低风险暴露。
- 核心收益: 在不改变核心交易逻辑的前提下,显著优化风险调整后收益,可能实现“减回撤不减收益”甚至“增收益减回撤”。
- 实现路径:
支点三:时间压缩 —— 探索更高频交易的可行性 (Frequency Optimization & Cost Management)
- 理论优势: 更高的交易频率意味着更快的概率回归(缩短回撤周期)和更频繁的复利效应,理论上可以构建更平滑、更快速增长的资金曲线。
- 现实挑战: 交易成本(手续费和滑点)是高频交易的“拦路虎”,足以扼杀许多看似有效的策略。
- 战略升级: 将交易执行和成本控制提升到战略高度。
- 实现路径:
- 滑点控制: 引入盘口分析、订单簿深度研究、智能订单路由等算法,避免在流动性枯竭或市场冲击时执行,寻找最优成交时机和价格。
- 信号精炼: 并非所有信号都值得交易,需要更精细的过滤逻辑,减少低效、高成本的交易。
- 成本结构优化: 积极寻求手续费返还或更优的经纪商合作模式。
- 核心要求: 需要深厚的市场微观结构理解、强大的编程能力和对细节的极致追求,从“大道至简”转向“精雕细琢”。
- 实现路径:
支点四:武器库扩充 —— 构建多策略协同作战体系 (Multi-Strategy Synergy)
- 单点突破的瓶颈: 将单一策略的夏普比率从0.5提升到1.0极其困难,学习曲线陡峭。
- 战略升级: 拥抱组合投资的“免费午餐”——利用策略间的低相关性。
- 实现路径:
- 闲置资金活化: 将趋势策略通常闲置的大量资金(如70%)投入到其他低相关的策略中。
- 策略搭配: 商品趋势策略可与期权卖方(赚取时间价值,震荡市盈利)、套利(市场中性)、日内短线、ETF轮动、可转债、股票多头/中性等策略进行组合。
- 目标协同: 盈利来源多元化,不同策略在不同市场环境下轮流发力,有效平滑整体资金曲线,实现1+1>2的效果(例如,收益相加,回撤相抵)。
- 核心理念: 不必追求将每个策略都做到极致,而是构建一个由多个“正期望”且“低相关”的策略组成的、更稳健、更强大的整体投资组合。
- 实现路径:
总结:
这次讨论揭示了资深量化交易者在趋势策略上的进化方向:不再沉迷于信号层面的精雕细琢,而是转向更宏大的结构性优化。 通过精选战场(品种)、灵活调度兵力(资金)、优化作战节奏与成本(频率与执行),并最终构建多兵种协同的作战体系(多策略组合),从而在经典趋势策略的坚实基础上,打造出更具竞争力、更能穿越周期的交易系统。这标志着从单一策略工匠到投资组合架构师的思维跃迁。
我们基于之前精炼和重塑的“四大战略支点”内容,用Python勾勒一个概念性的框架代码。
请注意,这份代码是一个高度简化和概念化的示例,旨在演示结构和思想,并非一个完整、精确的回测或交易系统。它省略了许多实际操作中的复杂性(如精确的保证金计算、滑点模型、订单撮合逻辑、数据清洗、风控细节等),但能清晰地展示如何将这四大战略支点融入一个量化交易框架中。
import pandas as pd
import numpy as np
from abc import ABC, abstractmethod
import random
# --- 0. 模拟数据准备 ---
def load_mock_data(symbols, start_date, end_date):
"""加载模拟OHLCV数据及基本指标"""
dates = pd.date_range(start_date, end_date, freq='B') # 使用工作日频率
data = {}
for symbol in symbols:
price = 100 + np.random.randn(len(dates)).cumsum() * 0.3 # 模拟价格路径
volume = np.random.randint(10000, 50000, size=len(dates))
df = pd.DataFrame({
'open': price - np.random.rand(len(dates)) * 0.2,
'high': price + np.random.rand(len(dates)) * 0.3,
'low': price - np.random.rand(len(dates)) * 0.3,
'close': price,
'volume': volume
}, index=dates)
# 简单计算指标用于示例
df['ma_fast'] = df['close'].rolling(window=10).mean()
df['ma_slow'] = df['close'].rolling(window=30).mean()
high_low = df['high'] - df['low']
high_close = np.abs(df['high'] - df['close'].shift())
low_close = np.abs(df['low'] - df['close'].shift())
tr = pd.concat([high_low, high_close, low_close], axis=1).max(axis=1)
df['atr'] = tr.rolling(window=14).mean() # 计算ATR
df['momentum'] = df['close'].pct_change(periods=20) # 简单动量指标
data[symbol] = df.dropna()
return data
# --- 支点一:战场精选 (Universe Intelligence) ---
class UniverseSelector:
"""品种筛选器基类"""
@abstractmethod
def select(self, data_dict, current_date, top_n=15):
"""
根据当前数据和日期,筛选出交易的品种列表
:param data_dict: 所有潜在品种的数据字典 {symbol: pd.DataFrame}
:param current_date: 当前日期
:param top_n: 期望选择的品种数量
:return: list of selected symbols
"""
pass
class MomentumUniverseSelector(UniverseSelector):
"""示例:基于动量排名的品种筛选器"""
def select(self, data_dict, current_date, top_n=15):
scores = {}
for symbol, df in data_dict.items():
if current_date in df.index and 'momentum' in df.columns:
momentum_score = df.loc[current_date, 'momentum']
if pd.notna(momentum_score):
scores[symbol] = momentum_score
# 按动量得分降序排序,选择前N个
sorted_symbols = sorted(scores.items(), key=lambda item: item[1], reverse=True)
selected = [symbol for symbol, score in sorted_symbols[:top_n]]
# print(f"{current_date} [战场精选]: 选出 {len(selected)} 个品种: {selected[:5]}...") # 调试信息
return selected
# --- 支点二:兵力调度 (Dynamic Capital Allocation) ---
class PositionSizer(ABC):
"""仓位管理器基类"""
@abstractmethod
def calculate_size(self, symbol, symbol_data, strategy_equity, risk_fraction, current_date, portfolio_equity_curve=None):
"""
计算单个品种的仓位大小
:param symbol: 品种代码
:param symbol_data: 该品种的DataFrame数据
:param strategy_equity: 分配给该策略的资金
:param risk_fraction: 单笔交易愿意承担的策略资金风险比例 (可动态调整)
:param current_date: 当前日期
:param portfolio_equity_curve: (可选) 整个投资组合的历史权益曲线,用于权益曲线交易等高级逻辑
:return: position size (e.g., number of contracts)
"""
pass
class VolatilityAdjustedPositionSizer(PositionSizer):
"""示例:基于ATR波动率调整的仓位管理器"""
def calculate_size(self, symbol, symbol_data, strategy_equity, risk_fraction, current_date, portfolio_equity_curve=None):
if current_date not in symbol_data.index:
return 0
# --- 动态风险因子演示 ---
# 简单的权益曲线交易概念:如果组合总权益最近在下跌,减少风险暴露
dynamic_risk_factor = 1.0
if portfolio_equity_curve is not None and len(portfolio_equity_curve) > 10: # 需要足够数据
recent_equity = portfolio_equity_curve.iloc[-10:]
if recent_equity.iloc[-1] < recent_equity.mean(): # 如果当前权益低于近期均值
dynamic_risk_factor = 0.8 # 减少风险暴露 (示例)
# print(f"{current_date} [兵力调度]: 权益曲线表现不佳,风险因子调整为 {dynamic_risk_factor}")
adjusted_risk_fraction = risk_fraction * dynamic_risk_factor
# 基于ATR计算仓位
atr = symbol_data.loc[current_date, 'atr']
close_price = symbol_data.loc[current_date, 'close']
if pd.isna(atr) or atr == 0 or pd.isna(close_price) or close_price == 0:
# print(f"Warning: Missing ATR or Price for {symbol} on {current_date}")
return 0
# 假设合约乘数/点值 (需要根据实际品种配置)
point_value = 10 # 例如: 股指期货一点10元
# 假设止损距离为 2 * ATR (这应由策略本身定义)
risk_per_contract = 2 * atr * point_value
if risk_per_contract <= 0:
return 0
risk_amount_per_trade = strategy_equity * adjusted_risk_fraction
position_size = int(risk_amount_per_trade / risk_per_contract)
# print(f"{current_date} [兵力调度] {symbol}: 策略资金={strategy_equity:.0f}, 风险比例={adjusted_risk_fraction:.3f}, ATR={atr:.2f}, 计算仓位={position_size}")
return max(0, position_size)
# --- 交易策略基类 ---
class TradingStrategyBase(ABC):
"""交易策略基类"""
def __init__(self, name):
self.name = name
@abstractmethod
def generate_signals(self, symbol, symbol_data, current_date):
"""
为单个品种生成交易信号
:param symbol: 品种代码
:param symbol_data: 该品种的DataFrame数据
:param current_date: 当前日期
:return: signal (1 for long, -1 for short, 0 for flat)
"""
pass
# --- 示例策略 1: 趋势跟踪 ---
class TrendFollowingStrategy(TradingStrategyBase):
"""示例:简单的均线交叉趋势跟踪策略"""
def __init__(self, name="趋势策略"):
super().__init__(name)
self.fast_ma_col = 'ma_fast'
self.slow_ma_col = 'ma_slow'
def generate_signals(self, symbol, symbol_data, current_date):
if current_date not in symbol_data.index:
return 0
row = symbol_data.loc[current_date]
if pd.isna(row[self.fast_ma_col]) or pd.isna(row[self.slow_ma_col]):
return 0
if row[self.fast_ma_col] > row[self.slow_ma_col]:
return 1 # 金叉,做多信号
elif row[self.fast_ma_col] < row[self.slow_ma_col]:
return -1 # 死叉,做空信号
else:
return 0 # 均线粘合或相等,无信号/平仓 (取决于具体规则)
# --- 示例策略 2: 模拟低相关性策略 (如均值回归) ---
class MeanReversionStrategy(TradingStrategyBase):
"""示例:模拟一个与趋势低相关的均值回归策略"""
def __init__(self, name="均值回归模拟"):
super().__init__(name)
# 注意:这是一个非常简化的模拟,真实均值回归策略复杂得多
def generate_signals(self, symbol, symbol_data, current_date):
# 简单逻辑:价格远低于慢速均线时尝试做多,远高于时尝试做空 (与趋势策略倾向相反)
if current_date not in symbol_data.index:
return 0
row = symbol_data.loc[current_date]
if pd.isna(row['close']) or pd.isna(row['ma_slow']) or pd.isna(row['atr']):
return 0
threshold = 1.5 # 假设偏离1.5倍ATR为入场阈值
if row['close'] < row['ma_slow'] - threshold * row['atr']:
return 1 # 价格过低,尝试做多 (均值回归)
elif row['close'] > row['ma_slow'] + threshold * row['atr']:
return -1 # 价格过高,尝试做空 (均值回归)
else:
# 在均线附近可能需要平仓逻辑
return 0
# --- 支点三:时间压缩 (Frequency Optimization & Cost Management - 概念演示) ---
def conceptual_execution_optimizer(symbol, signal, current_date, order_type="Market"):
"""
概念性函数:演示高频策略中执行优化的位置和思路
在真实系统中,这里会接入盘口数据、逐笔数据等进行分析
"""
optimized_order_type = order_type
limit_price = None
cancel_signal = False
# 伪代码:模拟检查市场微观结构
# micro_structure_data = get_market_microstructure(symbol, current_date) # 获取盘口、tick等
# if signal == 1 and micro_structure_data['ask_pressure'] > threshold:
# print(f"{current_date} [执行优化] {symbol}: 检测到卖压较大,考虑转为限价单或延迟")
# optimized_order_type = "Limit"
# # limit_price = micro_structure_data['best_bid'] # 示例:尝试在买一挂单
# elif signal != 0 and micro_structure_data['liquidity'] < min_liquidity:
# print(f"{current_date} [执行优化] {symbol}: 流动性不足,取消信号")
# cancel_signal = True
if cancel_signal:
return 0, None, None # 返回调整后的信号、订单类型、限价
# print(f"{current_date} [执行优化] {symbol}: (概念) 执行优化检查完成,信号={signal}, 订单类型={optimized_order_type}")
return signal, optimized_order_type, limit_price
def calculate_trade_costs(symbol, trade_size, price):
"""
简化模拟交易成本(滑点 + 手续费)
真实模型会更复杂,区分开平仓、考虑价格冲击等
"""
if trade_size == 0:
return 0
# 假设参数 (应根据品种和经纪商配置)
slippage_per_unit = price * 0.0002 # 按价格比例模拟滑点 (万分之二)
commission_rate = 0.00025 # 按成交额模拟手续费 (万分之二点五)
point_value = 10 # 假设合约乘数/点值
# 简化成本计算
slippage_cost = abs(trade_size) * slippage_per_unit * point_value
commission_cost = abs(trade_size) * price * point_value * commission_rate * 2 # 开平双边收取
total_cost = slippage_cost + commission_cost
# print(f" 交易成本: 数量={trade_size}, 滑点={slippage_cost:.2f}, 手续费={commission_cost:.2f}, 总计={total_cost:.2f}")
return total_cost
# --- 支点四:武器库扩充 (Multi-Strategy Synergy) ---
class PortfolioManager:
"""投资组合管理器(集成四大支点)"""
def __init__(self, initial_equity, all_symbols_data):
self.initial_equity = initial_equity
self.equity = initial_equity
self.cash = initial_equity
self.positions = {} # {symbol: {'size': int, 'entry_price': float}}
self.equity_curve = pd.Series(dtype=float)
self.all_symbols_data = all_symbols_data
self.strategies = {} # {name: {'strategy': TradingStrategyBase, 'weight': float, 'sizer': PositionSizer, 'filter': UniverseSelector, 'risk_per_trade': float}}
self.daily_log = [] # 记录每日操作
def add_strategy(self, strategy, weight, sizer, risk_per_trade, universe_filter=None):
"""添加策略及其配置到投资组合"""
if not (0 <= weight <= 1):
raise ValueError("策略权重必须在0到1之间")
self.strategies[strategy.name] = {
'strategy': strategy,
'weight': weight,
'sizer': sizer,
'filter': universe_filter,
'risk_per_trade': risk_per_trade # 该策略下单笔愿意承担的风险比例
}
print(f"已添加策略 '{strategy.name}',权重 {weight*100:.1f}%,单笔风险 {risk_per_trade*100:.2f}%")
def run_simulation(self, start_date, end_date):
"""运行回测模拟"""
# 获取模拟时间范围内的所有交易日
simulation_dates = pd.date_range(start_date, end_date, freq='B')
self.equity_curve = pd.Series(index=simulation_dates, dtype=float)
for current_date in simulation_dates:
if current_date not in next(iter(self.all_symbols_data.values())).index: # 跳过数据缺失的日期
if not self.equity_curve.empty:
self.equity_curve[current_date] = self.equity_curve.iloc[-1] # 用前一天权益填充
continue
# 1. 更新当日开盘前的组合价值 (基于昨日收盘价和持仓) - 简化处理
# 实际应更精确计算 PnL
self.update_portfolio_value(current_date, 'open') # 使用开盘价更新一下初始价值 (非常简化)
current_day_log = {'date': current_date, 'equity_start': self.equity, 'trades': [], 'costs': 0}
# 2. 动态分配资金给各策略
total_weight = sum(s['weight'] for s in self.strategies.values())
# 注意:这里可以做更复杂的资金分配,比如根据策略表现动态调整权重
strategy_allocations = {}
for name, config in self.strategies.items():
# 按初始权重分配,如果总权重大于1,则按比例缩放
allocated = self.equity * config['weight'] / max(1, total_weight)
strategy_allocations[name] = allocated
# 3. 为每个策略生成目标仓位
aggregate_target_positions = {} # {symbol: target_size} 汇总所有策略的目标仓位
for name, config in self.strategies.items():
strategy = config['strategy']
strategy_equity = strategy_allocations[name]
sizer = config['sizer']
risk_per_trade = config['risk_per_trade']
universe_filter = config['filter']
# a. 品种过滤 (支点一)
tradable_universe = list(self.all_symbols_data.keys())
if universe_filter:
selected_symbols = universe_filter.select(self.all_symbols_data, current_date)
else:
selected_symbols = tradable_universe # 如果没配置过滤器,则使用全品种
# b. 信号生成 & c. 仓位计算 (支点二)
for symbol in selected_symbols:
if symbol not in self.all_symbols_data: continue
symbol_data = self.all_symbols_data[symbol]
# 生成原始信号
signal = strategy.generate_signals(symbol, symbol_data, current_date)
# d. 计算目标仓位大小
target_size_abs = 0
if signal != 0 and sizer:
# 传入组合权益曲线用于可能的动态调整
target_size_abs = sizer.calculate_size(symbol, symbol_data, strategy_equity, risk_per_trade, current_date, self.equity_curve[:current_date])
strategy_target_size = signal * target_size_abs
# 合并到总目标仓位 (简单相加,实际可能需要更复杂的净额结算或优先级规则)
aggregate_target_positions[symbol] = aggregate_target_positions.get(symbol, 0) + strategy_target_size
# 4. 执行交易 (生成交易指令,考虑成本 - 支点三)
total_trade_cost = 0
all_symbols_involved = set(self.positions.keys()) | set(aggregate_target_positions.keys())
for symbol in all_symbols_involved:
current_size = self.positions.get(symbol, {}).get('size', 0)
target_size = aggregate_target_positions.get(symbol, 0)
trade_size = target_size - current_size
if trade_size != 0:
# --- 概念性执行优化 (支点三) ---
# 假设以当日收盘价成交 (简化)
if current_date in self.all_symbols_data[symbol].index:
execution_price = self.all_symbols_data[symbol].loc[current_date, 'close']
if pd.isna(execution_price): continue # 价格无效则跳过
# 调用概念性的执行优化器
# 实际这里会是下单逻辑,比如市价、限价、IOC、FOK等
final_signal = 1 if trade_size > 0 else -1 if trade_size < 0 else 0
optimized_signal, order_type, limit_price = conceptual_execution_optimizer(symbol, final_signal, current_date)
if optimized_signal == 0: # 如果优化器建议取消
print(f" {current_date} [执行优化] {symbol}: 交易信号被优化取消")
continue # 不执行此交易
# --- 计算交易成本 (支点三) ---
cost = calculate_trade_costs(symbol, trade_size, execution_price)
total_trade_cost += cost
# 更新持仓 (简化:不记录入场价,实际需要)
if target_size == 0:
if symbol in self.positions: del self.positions[symbol]
else:
self.positions[symbol] = {'size': target_size, 'entry_price': execution_price} # 简化记录
current_day_log['trades'].append({
'symbol': symbol, 'from': current_size, 'to': target_size,
'size': trade_size, 'price': execution_price, 'cost': cost
})
else:
print(f"Warning: No price data for {symbol} on {current_date} to execute trade.")
# 5. 更新当日收盘后的组合价值和权益曲线
self.cash -= total_trade_cost # 从现金中扣除交易成本
self.update_portfolio_value(current_date, 'close') # 用收盘价更新最终权益
self.equity_curve[current_date] = self.equity
current_day_log['costs'] = total_trade_cost
current_day_log['equity_end'] = self.equity
self.daily_log.append(current_day_log)
# print(f"{current_date}: Equity={self.equity:.2f}, Cash={self.cash:.2f}, Positions={len(self.positions)}, Costs={total_trade_cost:.2f}")
# 6. 计算最终性能指标
self.calculate_performance_metrics()
def update_portfolio_value(self, date, price_type='close'):
"""简化版:根据持仓和当日价格更新组合总权益"""
position_value = 0
for symbol, pos_info in self.positions.items():
if date in self.all_symbols_data[symbol].index:
price = self.all_symbols_data[symbol].loc[date, price_type]
if pd.notna(price):
point_value = 10 # 假设点值
position_value += pos_info['size'] * price * point_value
else:
# 价格缺失处理:可以用前一天的价格估算,或标记错误
pass # 简化处理,忽略该持仓价值变动
else:
# 日期不存在处理
pass
# 简化:权益 = 现金 + 持仓市值 (未考虑保证金)
# 正确的计算应该是:昨日权益 + 今日持仓盈亏 - 今日交易成本
# 这里仅做示意性更新
# 注意:self.cash 已经在 execute_trades 中减去了成本
self.equity = self.cash + position_value # 非常简化的权益计算
def calculate_performance_metrics(self):
"""计算并打印基本性能指标"""
print("\n--- 投资组合表现评估 ---")
if self.equity_curve.empty or self.equity_curve.isna().all():
print("无法计算指标:权益曲线数据不足或无效。")
return
self.equity_curve = self.equity_curve.dropna() # 去掉可能的NA值
if len(self.equity_curve) < 2:
print("无法计算指标:有效数据点过少。")
return
returns = self.equity_curve.pct_change().fillna(0)
total_return = (self.equity_curve.iloc[-1] / self.initial_equity - 1) * 100
# 简单计算年化收益(假设每年252交易日)
holding_period_days = (self.equity_curve.index[-1] - self.equity_curve.index[0]).days
years = max(1, holding_period_days) / 252 # 避免除零
annualized_return = ((1 + returns.mean())**252 - 1) * 100 # 基于日均收益率
annualized_volatility = returns.std() * np.sqrt(252) * 100
sharpe_ratio = (annualized_return / annualized_volatility) if annualized_volatility != 0 else 0 # 假设无风险利率为0
cumulative_returns = (1 + returns).cumprod()
peak = cumulative_returns.cummax()
drawdown = (cumulative_returns - peak) / peak
max_drawdown = drawdown.min() * 100
print(f"初始资金: {self.initial_equity:,.2f}")
print(f"最终权益: {self.equity_curve.iloc[-1]:,.2f}")
print(f"总回报率: {total_return:.2f}%")
print(f"年化回报率 (估算): {annualized_return:.2f}%")
print(f"年化波动率 (估算): {annualized_volatility:.2f}%")
print(f"夏普比率 (估算): {sharpe_ratio:.2f}")
print(f"最大回撤: {max_drawdown:.2f}%")
# 可以选择性地绘制权益曲线
try:
import matplotlib.pyplot as plt
plt.figure(figsize=(12, 6))
self.equity_curve.plot(title='投资组合权益曲线 (概念演示)')
plt.xlabel("日期")
plt.ylabel("权益")
plt.grid(True)
plt.show()
except ImportError:
print("未安装matplotlib,无法绘制权益曲线图。")
# --- 主程序入口 ---
if __name__ == "__main__":
# 0. 准备全局数据
all_symbols = [f'商品{i:02d}' for i in range(1, 31)] # 模拟30个商品期货品种
start_date = '2022-01-01'
end_date = '2023-12-31'
print("正在加载模拟数据...")
market_data = load_mock_data(all_symbols, start_date, end_date)
print("数据加载完毕。")
# 1. 初始化投资组合管理器
portfolio = PortfolioManager(initial_equity=10_000_000, all_symbols_data=market_data)
# 2. 配置并添加策略 (支点四:多策略组合)
# 策略A: 主力趋势跟踪策略
trend_strategy = TrendFollowingStrategy(name="核心趋势策略")
trend_filter = MomentumUniverseSelector() # 使用动量筛选器 (支点一)
trend_sizer = VolatilityAdjustedPositionSizer() # 使用波动率调整仓位 (支点二)
portfolio.add_strategy(
strategy=trend_strategy,
weight=0.6, # 分配60%资金
sizer=trend_sizer,
risk_per_trade=0.01, # 单笔交易风险占策略资金的1%
universe_filter=trend_filter # 应用品种筛选
)
# 策略B: 辅助均值回归策略 (模拟低相关性)
mean_reversion_strategy = MeanReversionStrategy(name="辅助均值回归")
# 这个策略可以不用过滤器,做全品种;或者用不同的过滤器
# 也可以用不同的仓位管理器,或者更激进/保守的风险参数
reversion_sizer = VolatilityAdjustedPositionSizer()
portfolio.add_strategy(
strategy=mean_reversion_strategy,
weight=0.3, # 分配30%资金
sizer=reversion_sizer,
risk_per_trade=0.005, # 单笔风险占策略资金的0.5% (假设更保守)
universe_filter=None # 不使用品种筛选,交易所有品种
)
# 剩余10%资金作为现金缓冲或用于未来扩展
# 3. 运行回测模拟
print("\n开始运行回测模拟...")
portfolio.run_simulation(start_date, end_date)
print("回测模拟结束。")
# 可以进一步分析 portfolio.daily_log 查看每日详情
# log_df = pd.DataFrame(portfolio.daily_log)
# print("\n每日日志概览:")
# print(log_df.head())
代码关键点与四大支点的对应关系:
-
战场精选 (Universe Intelligence - 支点一):
- 体现在
UniverseSelector
基类和MomentumUniverseSelector
实现类。 - 在
PortfolioManager
的run_simulation
循环中,每个策略可以选择性地调用其配置的universe_filter.select()
方法,从而只在筛选出的品种上生成信号和计算仓位。
- 体现在
-
兵力调度 (Dynamic Capital Allocation - 点二):
- 体现在
PositionSizer
基类和VolatilityAdjustedPositionSizer
实现类。 calculate_size
方法根据分配给该策略的资金 (strategy_equity
)、风险比例 (risk_fraction
) 和市场波动率 (ATR) 来计算仓位。- 示例中还加入了基于整体组合权益曲线表现动态调整风险因子的概念 (
dynamic_risk_factor
),展示了更高级的动态调仓思路。
- 体现在
-
时间压缩 (Frequency Optimization & Cost Management - 支点三):
- 概念性演示: 通过
conceptual_execution_optimizer
函数模拟了在执行前对信号进行检查、可能调整订单类型或取消交易的逻辑。这代表了高频交易中对微观结构敏感的执行优化思路。 - 成本模拟:
calculate_trade_costs
函数明确地模拟了滑点和手续费,并将其从账户现金中扣除。在高频策略中,对这部分成本的精确建模和控制至关重要。
- 概念性演示: 通过
-
武器库扩充 (Multi-Strategy Synergy - 支点四):
- 核心体现:
PortfolioManager
类本身就是多策略组合的容器。 add_strategy
方法允许将多个不同类型的策略(如TrendFollowingStrategy
和MeanReversionStrategy
)及其独立的配置(权重、筛选器、仓位管理器、风险参数)添加到组合中。run_simulation
循环会分别处理每个策略的信号生成和目标仓位计算(基于其分配的资金),然后汇总所有策略的意图,最终计算出需要执行的净交易。- 通过分配不同的
weight
,实现了在策略间分配资金,利用它们可能的低相关性来平滑整体权益曲线。
- 核心体现:
这个框架提供了一个将讨论中的高级优化思想融入实际代码结构的蓝图。你可以基于此,逐步替换模拟数据为真实数据,实现更复杂的策略、筛选器、仓位管理器,并不断完善回测引擎的细节和精度。