3 分钟快速生成代码
输入想法,AI 即刻生成可运行代码
这是一个非常经典的Alpha策略(或称为市场中性策略)的雏形。其核心逻辑是:
下面是一个完整的策略代码示例。
# -*- coding: utf-8 -*-
from jqdata import *
def initialize(context):
"""
初始化函数,设定基准、手续费、资金分配等
"""
# 设定基准为沪深300指数
set_benchmark('000300.XSHG')
# 开启动态复权模式(真实价格)
set_option('use_real_price', True)
# 过滤掉order系列API产生的比error级别低的log
log.set_level('order', 'error')
# 设定股票和期货的手续费
# 股票:买入万三,卖出万三加千一印花税
set_order_cost(OrderCost(open_tax=0, close_tax=0.001, open_commission=0.0003, close_commission=0.0003, close_today_commission=0, min_commission=5), type='stock')
# 期货:万分之0.23
set_order_cost(OrderCost(open_tax=0, close_tax=0, open_commission=0.000023, close_commission=0.000023, close_today_commission=0.0023, min_commission=0), type='index_futures')
# 设定保证金比例,股指期货一般为10%-15%,这里设为15%
set_option('futures_margin_rate', 0.15)
# 关键步骤:设置子账户
# subportfolios[0]: 股票账户,分配80%资金
# subportfolios[1]: 期货账户,分配20%资金
total_cash = context.portfolio.starting_cash
set_subportfolios([
SubPortfolioConfig(cash=total_cash * 0.8, type='stock'),
SubPortfolioConfig(cash=total_cash * 0.2, type='index_futures')
])
# 定义全局变量
g.stock_pool = [] # 选出的股票列表
g.future_code = None # 当前主力合约代码
g.stock_num = 20 # 持仓股票数量
# 设置定时运行:每月第一个交易日进行调仓
run_monthly(rebalance, 1, time='09:30')
# 每天开盘前更新主力合约
run_daily(update_future_contract, time='09:00')
def update_future_contract(context):
"""
每天更新当月的主力合约代码
"""
# 获取沪深300股指期货的主力合约
dominant = get_dominant_future('IF')
if dominant:
g.future_code = dominant
def rebalance(context):
"""
调仓主函数:先调整股票仓位,再调整期货对冲仓位
"""
if g.future_code is None:
log.warn("未获取到主力合约,跳过调仓")
return
# 1. 选股逻辑
select_stocks(context)
# 2. 交易股票
trade_stocks(context)
# 3. 交易期货进行对冲
hedge_futures(context)
def select_stocks(context):
"""
选股函数:选取沪深300中PE最低的股票
"""
# 获取沪深300成分股
index_stocks = get_index_stocks('000300.XSHG')
# 查询财务数据:市值和PE
q = query(
valuation.code,
valuation.pe_ratio
).filter(
valuation.code.in_(index_stocks),
valuation.pe_ratio > 0 # 过滤亏损股
).order_by(
valuation.pe_ratio.asc() # 按PE从小到大排序
).limit(g.stock_num)
df = get_fundamentals(q)
g.stock_pool = list(df['code'])
log.info("今日选股: %s" % g.stock_pool)
def trade_stocks(context):
"""
股票交易函数
"""
# 获取股票子账户
stock_account = context.subportfolios[0]
# 卖出不在股票池中的股票
for stock in list(stock_account.long_positions.keys()):
if stock not in g.stock_pool:
order_target_value(stock, 0, pindex=0)
# 买入股票池中的股票
# 简单的等权重分配
if len(g.stock_pool) > 0:
# 计算每只股票的目标价值 = 股票账户总资产 / 股票数量
target_value = stock_account.total_value / len(g.stock_pool)
for stock in g.stock_pool:
order_target_value(stock, target_value, pindex=0)
def hedge_futures(context):
"""
期货对冲函数
"""
# 获取股票账户和期货账户
stock_account = context.subportfolios[0]
future_account = context.subportfolios[1]
# 1. 计算股票组合的总市值
stock_value = stock_account.positions_value
# 如果股票市值为0,平掉所有期货空单
if stock_value == 0:
for code in future_account.short_positions.keys():
order_target(code, 0, side='short', pindex=1)
return
# 2. 处理主力合约换月
# 如果持仓中有非当前主力合约的空单,先平仓
for code in list(future_account.short_positions.keys()):
if code != g.future_code:
order_target(code, 0, side='short', pindex=1)
log.info("平掉旧合约: %s" % code)
# 3. 计算需要对冲的手数
# 获取期货当前价格
future_price = get_price(g.future_code, count=1, end_date=context.current_dt, fields=['close'])['close'][0]
# 合约乘数,IF是300元/点
multiplier = 300
# 计算合约价值
contract_value = future_price * multiplier
# 计算需做空的手数 = 股票总市值 / 单张合约价值
# 这里采用完全对冲(1:1),也可以根据Beta调整
short_amount = int(stock_value / contract_value)
# 4. 下单调整期货仓位
# 注意:pindex=1 使用期货子账户
# side='short' 表示操作空单
# order_target 调整到目标持仓量
order_target(g.future_code, short_amount, side='short', pindex=1)
log.info("股票市值: %.2f, 期货价格: %.2f, 对冲手数: %d" % (stock_value, future_price, short_amount))
子账户设置 (set_subportfolios):
pindex=0 用于股票,pindex=1 用于期货。'stock',期货账户类型设为 'index_futures'。主力合约切换 (get_dominant_future):
hedge_futures 里检查持仓合约是否等于当前主力合约,如果不等则平掉旧合约,并在后续步骤开新合约。对冲数量计算:
手数 = 股票总市值 / (期货价格 * 合约乘数)。手数 = (股票市值 * Beta) / 合约价值。下单函数 (order_target):
side='short'。order_target 会自动计算当前持仓和目标持仓的差额进行买卖,非常适合调仓逻辑。Q: 为什么我的策略回测时,期货账户经常爆仓?
A: 可能是资金分配问题。如果股票满仓,期货端只留了刚好够开仓的保证金,一旦指数上涨,期货空单会亏损,导致保证金不足。建议在 set_subportfolios 中给期货账户分配更多现金(如20%-30%),或者降低股票仓位。
Q: 如何更换为中证500对冲?
A:
'000905.XSHG'。get_index_stocks 改为 '000905.XSHG'。get_dominant_future('IC')。multiplier 改为 200。Q: 什么是基差风险?
A: 股指期货价格通常和现货指数价格不一致(通常是贴水,即期货比现货便宜)。如果贴水幅度扩大,即使股票跑赢了指数,总收益也可能因为期货端的额外亏损而减少。这是此类策略的主要风险之一。