量化策略之ETF核心资产轮动

这个量化策略的核心在于选择相关性较低的核心资产ETF,主要是商品(黄金、豆粕)、美股(标普500、纳指100)、A股(沪深300、创业板100),通过动量因子来打分进行轮动,每日进行调仓。

回测数据如下:

量化策略之ETF核心资产轮动

*回测数据只作测试用,不代表未来实际收益

定义了ETF基金池、动量参考天数、日调仓时间

    # 参数
    g.etf_pool = [
        '159985.XSHE', #豆粕
        '518880.XSHG', #黄金ETF(大宗商品)
        '159612.XSHE', #标普500
        '513100.XSHG', #纳指100(海外资产)
        '159915.XSHE', #创业板100(成长股,科技股,中小盘)
        '510300.XSHG', #沪深300(价值股,中大盘)
    ]
    g.m_days = 25 #动量参考天数
    run_daily(trade, '10:00') #每天运行确保即时捕捉动量变化

2、选股逻辑

基于年化收益和判定系数打分的动量因子轮动,计算两个值:

年化收益率:250天的年化收益率

高R平方值:用于评估趋势的稳定性,高R平方值意味着价格变动更符合线性趋势,策略信号更可靠,筛选出趋势明显的ETF,避免在波动大或无趋势的市场中交易。

def get_rank(etf_pool):
    score_list = []
    for etf in etf_pool:
        df = attribute_history(etf, g.m_days, '1d', ['close'])
        y = df['log'] = np.log(df.close)
        x = df['num'] = np.arange(df.log.size)
        slope, intercept = np.polyfit(x, y, 1)
        # 250天年化收益率
        annualized_returns = math.pow(math.exp(slope), 250) - 1
        # 高R平方值
        r_squared = 1 - (sum((y - (slope * x + intercept))**2) / ((len(y) - 1) * np.var(y, ddof=1)))
        # 分数
        score = annualized_returns * r_squared
        score_list.append(score)
    df = pd.DataFrame(index=etf_pool, data={'score':score_list})
    df = df.sort_values(by='score', ascending=False)
    rank_list = list(df.index)    
    print(df)  
    record(豆粕 = round(df.loc['159985.XSHE'], 2))   
    record(黄金 = round(df.loc['518880.XSHG'], 2))
    record(标普500 = round(df.loc['159612.XSHE'], 2))
    record(纳指 = round(df.loc['513100.XSHG'], 2))
    record(成长 = round(df.loc['159915.XSHE'], 2))
    record(价值 = round(df.loc['510300.XSHG'], 2))
    return rank_list

3、调仓逻辑

卖出不在目标基金池的ETF,买入目标基金池的ETF

# 交易
def trade(context):
    # 获取动量最高的一只ETF
    target_num = 1    
    target_list = get_rank(g.etf_pool)[:target_num]
    # 卖出    
    hold_list = list(context.portfolio.positions)
    for etf in hold_list:
        if etf not in target_list:
            order_target_value(etf, 0)
            print('卖出' + str(etf))
        else:
            print('继续持有' + str(etf))

    # 买入
    hold_list = list(context.portfolio.positions)
    if len(hold_list) < target_num:
        value = context.portfolio.available_cash / (target_num - len(hold_list))
        for etf in target_list:
            if context.portfolio.positions[etf].total_amount == 0:
                order_target_value(etf, value)
                print('买入' + str(etf))

这篇文章主要分享ETF核心资产轮动,选择相关性比较低的核心资产,每天捕获动量的变化,进行调仓

如果有不懂的,欢迎找我一起交流,加入量化交易大家庭

发布者:股市刺客,转载请注明出处:https://www.95sca.cn/archives/1352302
站内所有文章皆来自网络转载或读者投稿,请勿用于商业用途。如有侵权、不妥之处,请联系站长并出示版权证明以便删除。敬请谅解!

(0)
股市刺客的头像股市刺客
上一篇 2小时前
下一篇 2小时前

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注