同花顺量化之全球资产轮动策略

核心思想
买入动量最强的两名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% 简简单单
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

鸭梨山大哎

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值