核心思想
买入动量最强的两名ETF
# 初始化函数,全局只运行一次
def init(context):
# 设置基准收益:沪深300指数
set_benchmark('000300.SH')
# 打印日志
log.info('策略开始运行,初始化函数全局只运行一次')
# 设置股票每笔交易的手续费为万分之二(手续费在买卖成交后扣除,不包括税费,税费在卖出成交后扣除)
set_commission(PerShare(type='stock', cost=0.0002))
# 设置股票交易滑点0.5%,表示买入价为实际价格乘1.005,卖出价为实际价格乘0.995
set_slippage(PriceSlippage(0.002))
# 设置日级最大成交比例25%,分钟级最大成交比例50%
set_volume_limit(daily=0.25, minute=0.5)
# 设置指数池
context.index_pool = [
'159915.SZ', # 创业板ETF
'513050.SH', # 中概互联
'159941.SZ', # 中证500ETF
'518880.SH', # 黄金ETF
'511010.SH' # 国债ETF
# '510300.SH' # 沪深300
]
# 设置动量参数和均线参数
context.momentum_period = 20
context.ma_period = 28
# 设置当前持仓状态
context.holding = {}
# 每日开盘前9:00被调用一次,用于储存自定义参数、全局变量,执行盘前选股等
def before_trading(context):
# 获取日期
date = get_datetime().strftime('%Y-%m-%d %H:%M:%S')
# 打印日期
log.info('{} 盘前运行'.format(date))
# 计算指数池中每个指数的动量和均线
context.momentum_dict = {}
context.ma_dict = {}
for index in context.index_pool:
# 获取历史价格数据
data = history(symbol_list=index, fields=['close'], bar_count=context.momentum_period + context.ma_period, fre_step='1d', skip_paused=False, fq='pre')
prices = data['close']
# 计算动量
momentum = (prices.iloc[-1] - prices.iloc[-context.momentum_period]) / prices.iloc[-context.momentum_period]
context.momentum_dict[index] = momentum
# 计算均线
ma = prices.iloc[-context.ma_period:].mean()
context.ma_dict[index] = ma
# 打印动量和均线数据(动量以百分比形式打印)
log.info(f"指数 {index} 的动量为 {momentum * 100:.2f}%, 均线为 {ma:.4f}")
# 开盘时运行函数
def handle_bar(context, bar_dict):
# 获取时间
time = get_datetime().strftime('%Y-%m-%d %H:%M:%S')
# 打印时间
log.info('{} 盘中运行'.format(time))
# 筛选符合条件的标的
buy_candidates = []
for index in context.index_pool:
if context.momentum_dict[index] > 0 and bar_dict[index].close > context.ma_dict[index]:
buy_candidates.append((index, context.momentum_dict[index]))
# 按动量排序,取动量最高的两个标的
if buy_candidates:
buy_candidates.sort(key=lambda x: x[1], reverse=True) # 从大到小排序
top_candidates = buy_candidates[:2] # 取动量最高的两个标的
log.info(f"动量最高的两个标的为:")
for candidate in top_candidates:
index = candidate[0]
momentum = candidate[1]
log.info(f"标的 {index},动量为 {momentum * 100:.2f}%")
# 检查当前持仓是否需要调整
for holding in list(context.holding.keys()):
if holding not in [x[0] for x in top_candidates]:
log.info(f"标的 {holding} 动量 {context.holding[holding] * 100:.2f}% 退出前两名,需要清仓")
order_target_value(holding, 0) # 卖出持仓
del context.holding[holding]
# 调整或买入新的标的
for candidate in top_candidates:
index = candidate[0]
momentum = candidate[1]
if index not in context.holding:
log.info(f"标的 {index} 动量 {momentum * 100:.2f}% 进入前两名,需要买入")
context.holding[index] = momentum
# 确保每个标的的目标金额为总金额的50%
target_amount = context.portfolio.total_value / 2
order_target_value(index, target_amount)
log.info(f"调整标的 {index} 的目标金额为 {target_amount:.2f} 元")
else:
log.info("无符合条件的标的,保持空仓")
# 收盘后运行函数,用于储存自定义参数、全局变量,执行盘后选股等
def after_trading(context):
# 获取时间
time = get_datetime().strftime('%Y-%m-%d %H:%M:%S')
# 打印时间
log.info('{} 盘后运行'.format(time))
log.info('一天结束')
年化19% 简简单单