目录
引言:核心思路与目标
分项策略精细化研究
多策略组合构建与优化
回测与验证
预期效果与目标设定
策略执行与监控
总结与风险提示
1. 引言:核心思路与目标
2. 分项策略精细化研究
2.1 微盘股策略研究
2.1.1 特征分析与选股池构建 (含Python示例)
import akshare as ak
import pandas as pd
def get_micro_cap_pool(bottom_percent=0.20, min_turnover_m=10):
"""
获取初步的微盘股股票池
:param bottom_percent: 市值排名后百分比
:param min_turnover_m: 最低日均成交额(百万元)
:return: DataFrame or None
"""
try:
print("正在获取A股列表及市值/成交额信息...")
# 获取实时行情数据,包含市值和成交额信息
stock_spot_df = ak.stock_zh_a_spot_em()
# 选择需要的列,并重命名方便处理
stock_spot_df = stock_spot_df[['代码', '名称', '总市值', '成交额']].copy()
stock_spot_df.rename(columns={'总市值': 'market_cap', '成交额': 'turnover'}, inplace=True)
# 数据清洗
stock_spot_df['market_cap'] = pd.to_numeric(stock_spot_df['market_cap'], errors='coerce')
stock_spot_df['turnover'] = pd.to_numeric(stock_spot_df['turnover'], errors='coerce')
# 去除科创板、北交所、ST等(简化处理,实际可能需要更精确的板块和状态标识)
stock_spot_df = stock_spot_df[~stock_spot_df['代码'].str.startswith(('68', '8', '4'))]
stock_spot_df = stock_spot_df[~stock_spot_df['名称'].str.contains('ST')]
stock_spot_df = stock_spot_df[~stock_spot_df['名称'].str.contains('\*ST')]
stock_spot_df.dropna(subset=['market_cap', 'turnover'], inplace=True)
stock_spot_df = stock_spot_df[stock_spot_df['market_cap'] > 0]
# 按市值排序
stock_spot_df = stock_spot_df.sort_values(by='market_cap', ascending=True).reset_index(drop=True)
# 选取底部市值股票
total_stocks = len(stock_spot_df)
threshold_index = int(total_stocks * bottom_percent)
micro_cap_pool = stock_spot_df.iloc[:threshold_index]
# 流动性过滤 (成交额单位: 元)
min_turnover_value = min_turnover_m * 1_000_000
micro_cap_pool = micro_cap_pool[micro_cap_pool['turnover'] >= min_turnover_value]
print(f"筛选后微盘股数量 (市值后 {bottom_percent:.0%}, 日成交额 > {min_turnover_m} 百万): {len(micro_cap_pool)}")
print("微盘股池示例:")
print(micro_cap_pool[['代码', '名称', 'market_cap', 'turnover']].head())
return micro_cap_pool[['代码', '名称']] # 返回代码和名称列表
except Exception as e:
print(f"获取或处理微盘股数据时出错: {e}")
return pd.DataFrame() # 返回空DataFrame
# 调用示例
micro_cap_list_df = get_micro_cap_pool(bottom_percent=0.20, min_turnover_m=10)
akshare
数据可能有延迟,仅供研究参考。2.1.2 核心因子与择时信号 (含Python示例)
import pandas as pd
import numpy as np
import akshare as ak
def calculate_momentum(codes, period=20):
"""计算指定周期动量因子 (简单收益率)"""
stock_returns = {}
print(f"正在计算 {len(codes)} 只股票的 {period} 日动量...")
count = 0
for code in codes:
try:
stock_hist = ak.stock_zh_a_hist(symbol=code, period="daily", end_date='20231231', adjust="qfq") # 使用特定结束日期保证可复现
if not stock_hist.empty and len(stock_hist) > period:
stock_hist['return'] = stock_hist['收盘'].pct_change(periods=period)
last_return = stock_hist['return'].iloc[-1]
if pd.notna(last_return):
stock_returns[code] = last_return
except Exception as e:
# print(f"处理股票 {code} 时出错: {e}") # 避免过多打印
pass
count += 1
if count % 50 == 0: print(f"已处理 {count}/{len(codes)}")
print("动量计算完成.")
return sorted(stock_returns.items(), key=lambda item: item[1], reverse=True)
def get_index_timing_signal(index_code="sh000001", short_ma=5, long_ma=20):
"""获取指数均线择时信号"""
try:
print(f"\n正在计算指数 {index_code} 均线择时信号...")
index_hist = ak.stock_zh_index_daily(symbol=index_code)
index_hist['日期'] = pd.to_datetime(index_hist['date'])
index_hist.set_index('日期', inplace=True)
index_hist[f'SMA_{short_ma}'] = index_hist['close'].rolling(window=short_ma).mean()
index_hist[f'SMA_{long_ma}'] = index_hist['close'].rolling(window=long_ma).mean()
# 生成信号
index_hist['Signal'] = 0
condition_buy = (index_hist[f'SMA_{short_ma}'].shift(1) < index_hist[f'SMA_{long_ma}'].shift(1)) & \
(index_hist[f'SMA_{short_ma}'] > index_hist[f'SMA_{long_ma}'])
condition_sell = (index_hist[f'SMA_{short_ma}'].shift(1) > index_hist[f'SMA_{long_ma}'].shift(1)) & \
(index_hist[f'SMA_{short_ma}'] < index_hist[f'SMA_{long_ma}'])
index_hist.loc[condition_buy, 'Signal'] = 1
index_hist.loc[condition_sell, 'Signal'] = -1
latest_signal = index_hist['Signal'].iloc[-1]
print(f"最新的指数择时信号 ({index_code}, MA({short_ma}/{long_ma})): {latest_signal} (1:买入/加仓, -1:卖出/减仓, 0:观望)")
return latest_signal
except Exception as e:
print(f"计算指数择时信号时出错: {e}")
return 0 # 默认观望
# --- 调用示例 ---
if not micro_cap_list_df.empty:
momentum_ranked = calculate_momentum(micro_cap_list_df['代码'].tolist(), period=20)
print("\n动量因子排序 (前5名):")
print(momentum_ranked[:5])
# 可以选取排名前 N% 或 N 个股票
timing_signal = get_index_timing_signal(index_code="sz399300", short_ma=5, long_ma=20) # 以沪深300为例
# timing_signal = get_index_timing_signal(index_code="sz399905", short_ma=5, long_ma=20) # 或用中证500/国证2000
# 结合择时信号和动量因子进行决策...
2.1.3 风险控制
2.1.4 研究与实盘经验洞察
2.2 高股息股策略研究
2.2.1 特征分析与选股池构建 (含Python示例)
import akshare as ak
import pandas as pd
def get_high_dividend_pool(min_dividend_yield=4.0, min_roe=8.0, max_payout_ratio=0.8):
"""
获取初步的高股息股票池
:param min_dividend_yield: 最低股息率 (%)
:param min_roe: 最低净资产收益率 (%)
:param max_payout_ratio: 最高股息支付率
:return: DataFrame or None
"""
try:
print("正在获取A股股息率及基本财务数据...")
# 获取基本信息和股息率 (数据源可能变化,需确认字段)
# 尝试使用包含更多指标的接口,如 stock_financial_analysis_indicator
# 或者分别获取行情和财务数据再合并
stock_spot_df = ak.stock_zh_a_spot_em()
stock_indicator_df = ak.stock_financial_analysis_indicator(stock="all") # 可能非常慢
# 合并数据 (假设基于'代码'列)
# 注意:列名需要根据实际接口确认
stock_spot_df = stock_spot_df[['代码', '名称', '股息率(%)']].copy()
stock_spot_df.rename(columns={'股息率(%)': 'dividend_yield'}, inplace=True)
# 假设财务指标包含 '净资产收益率ROE', '股利支付率'
stock_indicator_df = stock_indicator_df[['证券代码', '净资产收益率ROE(%)', '现金股利支付率(%)']].copy()
stock_indicator_df.rename(columns={'证券代码':'代码', '净资产收益率ROE(%)':'roe', '现金股利支付率(%)':'payout_ratio'}, inplace=True)
# 合并
df = pd.merge(stock_spot_df, stock_indicator_df, on='代码', how='inner')
# 数据清洗
df['dividend_yield'] = pd.to_numeric(df['dividend_yield'], errors='coerce')
df['roe'] = pd.to_numeric(df['roe'], errors='coerce')
# 股利支付率可能是'--'或百分比字符串
df['payout_ratio'] = df['payout_ratio'].astype(str).str.replace('%', '', regex=False)
df['payout_ratio'] = pd.to_numeric(df['payout_ratio'], errors='coerce') / 100 # 转为小数
df.dropna(subset=['dividend_yield', 'roe', 'payout_ratio'], inplace=True)
df = df[~df['名称'].str.contains('ST')] # 再次过滤ST
# 筛选
pool = df[
(df['dividend_yield'] >= min_dividend_yield) &
(df['roe'] >= min_roe) &
(df['payout_ratio'] > 0) & # 支付率需大于0
(df['payout_ratio'] <= max_payout_ratio) # 支付率不能过高
]
# 按股息率排序
pool = pool.sort_values(by='dividend_yield', ascending=False)
print(f"筛选后高股息股票数量 (股息率>={min_dividend_yield}%, ROE>={min_roe}%, 支付率<={max_payout_ratio*100}%): {len(pool)}")
print("高股息池示例:")
print(pool[['代码', '名称', 'dividend_yield', 'roe', 'payout_ratio']].head())
return pool[['代码', '名称']]
except Exception as e:
print(f"获取或处理高股息数据时出错: {e}")
return pd.DataFrame()
# 调用示例
high_dividend_list_df = get_high_dividend_pool(min_dividend_yield=4.0, min_roe=10.0, max_payout_ratio=0.7)
2.2.2 核心因子与择时信号
2.2.3 风险控制
2.2.4 研究与实盘经验洞察
2.3 全天候ETF择时策略研究
2.3.1 10年国债期货ETF择时 (含Python示例)
import akshare as ak
import pandas as pd
def calculate_etf_macd_signal(etf_code="511260", short_ema=12, long_ema=26, signal_ema=9):
"""计算ETF的MACD指标及金叉死叉信号"""
try:
print(f"正在获取ETF {etf_code} 数据并计算MACD信号...")
etf_hist = ak.fund_etf_hist_em(symbol=etf_code, adjust="qfq")
etf_hist['日期'] = pd.to_datetime(etf_hist['日期'])
etf_hist.set_index('日期', inplace=True)
etf_hist.sort_index(inplace=True)
# 计算MACD
etf_hist['EMA_short'] = etf_hist['收盘'].ewm(span=short_ema, adjust=False).mean()
etf_hist['EMA_long'] = etf_hist['收盘'].ewm(span=long_ema, adjust=False).mean()
etf_hist['DIF'] = etf_hist['EMA_short'] - etf_hist['EMA_long']
etf_hist['DEA'] = etf_hist['DIF'].ewm(span=signal_ema, adjust=False).mean()
etf_hist['MACD_Hist'] = (etf_hist['DIF'] - etf_hist['DEA']) * 2
# 生成信号
etf_hist['MACD_Signal'] = 0
condition_buy = (etf_hist['DIF'].shift(1) < etf_hist['DEA'].shift(1)) & (etf_hist['DIF'] > etf_hist['DEA'])
condition_sell = (etf_hist['DIF'].shift(1) > etf_hist['DEA'].shift(1)) & (etf_hist['DIF'] < etf_hist['DEA'])
etf_hist.loc[condition_buy, 'MACD_Signal'] = 1
etf_hist.loc[condition_sell, 'MACD_Signal'] = -1
latest_signal = etf_hist['MACD_Signal'].iloc[-1]
print(f"最新的ETF {etf_code} MACD择时信号: {latest_signal} (1:看多, -1:看空, 0:观望)")
# print(etf_hist[['收盘', 'DIF', 'DEA', 'MACD_Hist', 'MACD_Signal']].tail())
return latest_signal
except Exception as e:
print(f"获取或处理ETF {etf_code} 数据时出错: {e}")
return 0
# 调用示例
bond_etf_signal = calculate_etf_macd_signal(etf_code="511260") # 10年国债ETF
2.3.2 黄金ETF择时
2.3.3 ETF择时共性与风险
2.3.4 研究与实盘经验洞察
2.4 可转债日内短线策略研究
2.4.1 特征分析与标的选择 (含Python示例)
import akshare as ak
import pandas as pd
def get_active_convertible_bonds(min_turnover_m=500, min_price=80, max_price=180):
"""
获取活跃的可转债列表
:param min_turnover_m: 最低日成交额 (百万元)
:param min_price: 最低价格
:param max_price: 最高价格
:return: DataFrame or None
"""
try:
print("正在获取可转债实时行情数据...")
bond_cov_spot_df = ak.bond_zh_cov_spot()
# 选择和重命名
bond_cov_spot_df = bond_cov_spot_df[['代码', '名称', '最新价', '成交额']].copy()
bond_cov_spot_df.rename(columns={'最新价':'price', '成交额':'turnover'}, inplace=True)
# 数据清洗
bond_cov_spot_df['price'] = pd.to_numeric(bond_cov_spot_df['price'], errors='coerce')
bond_cov_spot_df['turnover'] = pd.to_numeric(bond_cov_spot_df['turnover'], errors='coerce')
bond_cov_spot_df.dropna(inplace=True)
# 筛选
min_turnover_value = min_turnover_m * 1_000_000
pool = bond_cov_spot_df[
(bond_cov_spot_df['turnover'] >= min_turnover_value) &
(bond_cov_spot_df['price'] >= min_price) &
(bond_cov_spot_df['price'] <= max_price) # 价格区间过滤,避免极端情况
]
# 按成交额排序
pool = pool.sort_values(by='turnover', ascending=False)
print(f"筛选后活跃可转债数量 (成交额>={min_turnover_m}百万, 价格{min_price}-{max_price}): {len(pool)}")
print("活跃可转债池示例:")
print(pool[['代码', '名称', 'price', 'turnover']].head())
return pool[['代码', '名称']]
except Exception as e:
print(f"获取或处理可转债数据时出错: {e}")
return pd.DataFrame()
# 调用示例
active_bond_list_df = get_active_convertible_bonds(min_turnover_m=300) # 成交额大于3亿
akshare
仅适合研究。实盘需对接券商高速行情接口。波动率计算需要分钟级数据。2.4.2 日内交易信号挖掘
2.4.3 风险控制与执行
2.4.4 研究与实盘经验洞察
3. 多策略组合构建与优化
3.1 资产相关性分析 (含Python示例)
import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['SimHei'] # 中文显示
plt.rcParams['axes.unicode_minus'] = False # 负号显示
# 假设已获取各策略代表指数的日收益率数据
# 这里用随机数据模拟,并加入一些相关性假设
np.random.seed(42)
dates = pd.date_range('2022-01-01', '2023-12-31')
returns = pd.DataFrame(index=dates)
returns['MicroCap'] = np.random.normal(0.001, 0.025, len(dates)) # 微盘,高波动
returns['HighDividend'] = np.random.normal(0.0005, 0.012, len(dates)) + 0.2 * returns['MicroCap'] # 高股息,低波,与微盘弱正相关
returns['BondETF'] = np.random.normal(0.0001, 0.003, len(dates)) - 0.3 * returns['MicroCap'] # 债券,极低波,与微盘负相关
returns['GoldETF'] = np.random.normal(0.0003, 0.01, len(dates)) - 0.1 * returns['MicroCap'] - 0.2 * returns['BondETF'] # 黄金,中波,与微盘弱负相关,与债券弱负相关
returns['ConvertibleDayTrade'] = np.random.normal(0.0008, 0.005, len(dates)) # 可转债日内,低波(指策略净值),与其他低相关
print("策略/资产日收益率数据 (模拟):")
print(returns.head())
# 计算相关系数矩阵
correlation_matrix = returns.corr()
print("\n策略/资产收益率相关系数矩阵:")
print(correlation_matrix)
# 可视化
plt.figure(figsize=(8, 6))
sns.heatmap(correlation_matrix, annot=True, cmap='coolwarm', fmt=".2f", linewidths=.5)
plt.title('策略/资产收益率相关性矩阵 (模拟)')
plt.show()
3.2 资金分配模型
# --- 静态配置示例 ---
static_weights = {
'MicroCap': 0.25, 'HighDividend': 0.25, 'BondETF': 0.20,
'GoldETF': 0.20, 'ConvertibleDayTrade': 0.10
}
print("静态配置权重:", static_weights)
# --- 风险平价思路 (简化说明,非精确计算) ---
# 1. 估算各策略的预期波动率 (例如,基于历史波动率)
strategy_volatility = returns.std() * np.sqrt(252) # 年化波动率
print("\n各策略年化波动率 (模拟):")
print(strategy_volatility)
# 2. 计算初步权重:与波动率成反比
inverse_volatility = 1 / strategy_volatility
initial_weights = inverse_volatility / inverse_volatility.sum()
print("\n基于波动率倒数的初步权重 (未考虑相关性):")
print(initial_weights)
# 注意:真正的风险平价需要考虑资产间的相关性,通过优化算法求解,
# 使得 Risk Contribution = Weight * Marginal Contribution to Risk 相等。
# 这通常需要使用 scipy.optimize 等库。
# 实际应用中,动态配置模型会定期(如每月)运行,生成新的目标权重
3.3 组合层面的风险管理
3.4 研究与实盘经验洞察
4. 回测与验证
4.1 数据准备与清洗: 获取高质量、长周期的历史数据(日线、分钟线、财务、宏观、可转债条款等),进行 دقیق的数据清洗(去重、填补缺失值、异常值处理、复权处理)。数据的质量是回测有效性的基石。
4.2 单策略回测: 对每个子策略独立进行回测,评估其历史绩效和风险特征。
4.3 组合策略回测: 将通过验证的子策略按照选定的资金分配和再平衡规则进行组合回测。
4.4 关键绩效指标(KPI)评估 (含Python示例)
import pandas as pd
import numpy as np
def calculate_portfolio_kpi(daily_returns, risk_free_rate=0.02):
"""计算投资组合的关键绩效指标"""
if not isinstance(daily_returns, pd.Series):
daily_returns = pd.Series(daily_returns)
days_per_year = 252
print("\n--- 关键绩效指标 (KPI) ---")
# 1. 累计收益率 & 年化收益率
cumulative_return = (1 + daily_returns).prod() - 1
total_days = len(daily_returns)
years = total_days / days_per_year
annualized_return = (1 + cumulative_return) ** (1 / years) - 1 if years > 0 else 0
print(f"累计收益率: {cumulative_return:.2%}")
print(f"年化收益率: {annualized_return:.2%}")
# 2. 年化波动率
annualized_volatility = daily_returns.std() * np.sqrt(days_per_year)
print(f"年化波动率: {annualized_volatility:.2%}")
# 3. 夏普比率
sharpe_ratio = (annualized_return - risk_free_rate) / annualized_volatility if annualized_volatility != 0 else 0
print(f"夏普比率 (Rf={risk_free_rate:.1%}): {sharpe_ratio:.2f}")
# 4. 最大回撤
cumulative_curve = (1 + daily_returns).cumprod()
peak = cumulative_curve.cummax()
drawdown = (cumulative_curve - peak) / peak
max_drawdown = drawdown.min()
print(f"最大回撤: {max_drawdown:.2%}")
# 5. 卡玛比率
calmar_ratio = annualized_return / abs(max_drawdown) if max_drawdown != 0 else 0
print(f"卡玛比率: {calmar_ratio:.2f}")
# 6. 索提诺比率 (仅考虑下行风险)
downside_returns = daily_returns[daily_returns < 0]
downside_deviation = downside_returns.std() * np.sqrt(days_per_year)
sortino_ratio = (annualized_return - risk_free_rate) / downside_deviation if downside_deviation != 0 else 0
print(f"索提诺比率: {sortino_ratio:.2f}")
return {
'Annualized Return': annualized_return,
'Annualized Volatility': annualized_volatility,
'Sharpe Ratio': sharpe_ratio,
'Max Drawdown': max_drawdown,
'Calmar Ratio': calmar_ratio,
'Sortino Ratio': sortino_ratio
}
# --- 调用示例 (假设 portfolio_daily_returns 是组合策略的日收益率Series) ---
# 使用前面模拟的等权组合收益率
weights = np.array([0.25, 0.25, 0.20, 0.20, 0.10]) # 使用静态权重
portfolio_daily_returns = returns.dot(weights)
kpi_results = calculate_portfolio_kpi(portfolio_daily_returns, risk_free_rate=0.02)
# 可视化累计收益曲线和回撤 (代码同前)
plt.figure(figsize=(12, 6))
ax1 = plt.subplot(2, 1, 1)
(1 + portfolio_daily_returns).cumprod().plot(ax=ax1, title='组合累计收益曲线 (模拟)')
ax1.set_ylabel('累计净值')
ax2 = plt.subplot(2, 1, 2, sharex=ax1)
drawdown = ((1 + portfolio_daily_returns).cumprod() / (1 + portfolio_daily_returns).cumprod().cummax() - 1)
drawdown.plot(ax=ax2, title='组合回撤曲线 (模拟)', color='red')
ax2.fill_between(drawdown.index, drawdown, 0, color='red', alpha=0.3)
ax2.set_ylabel('回撤')
plt.tight_layout()
plt.show()
4.5 稳健性检验:
4.6 研究与实盘经验洞察
5. 预期效果与目标设定
6. 策略执行与监控
7. 总结与风险提示
最终强调: 这是一个高度复杂的量化投资体系,需要专业的团队、持续的研究投入、强大的技术支持和严格的风险管理流程。在投入实际资金前,必须进行充分的尽职调查、风险评估,并强烈建议从模拟交易或小规模实盘开始,逐步验证和完善策略体系。