乐于分享
好东西不私藏

ETF MACD 趋势跟踪 策略(聚宽源码)

ETF MACD 趋势跟踪 策略(聚宽源码)
我在逛知乎的一个帖子,有哪些优秀的策略的时候,看到这个:
点了他的源码,进不去,我自己敲。
我贴在这里,想要的自己去拿:
GitHub:https://http://github.com/zjb1976/etf-macd-strategy
因为没有说具体的标的,我就根据他这个8个宽基+4个跨境随便选了点。
8只宽基:
代码
简称
跟踪指数
市场定位
510050
上证 50ETF
上证 50
沪市超大盘蓝筹(金融、消费龙头)
510300
沪深 300ETF
沪深 300
A 股全市场核心资产基准
510500
中证 500ETF
中证 500
A 股中小盘成长
510600
中证 1000ETF
中证 1000
小盘弹性品种
159915
创业板 ETF
创业板指数
创业板创新成长
588000
科创 50ETF
科创 50
科创板硬科技
159361
中证 A500ETF
中证 A500
均衡行业新宽基
159845
科创创业 50ETF
科创创业 50
科创 + 创业板成长集合
4只跨境ETF,支持T+0
代码
简称
跟踪指数
市场定位
513600
恒生指数 ETF
恒生指数
港股大盘宽基
513130
恒生科技 ETF
恒生科技指数
港股互联网科技龙头
513100
纳指 ETF
纳斯达克 100
美股科技巨头(苹果、英伟达等)
513500
标普 500ETF
标普 500
美股全行业均衡龙头
于是根据他的描述,策略思路就是这样的:
买入条件:

两个条件同时满足 → 次日开盘买入

1,当日收盘价 ≥ 20 日均线(MA20),

2,MACD 指标形成 金叉(DIF 上穿 DEA)

卖出条件

收盘价 跌破 20 日均线 → 次日开盘卖出

确实简单,我就写了代码做了回测,回测时间是2020年-2026年6月:

策略收益是61.88%,年化是8.07%,我猜他可能还有科创综指,另外跨境ETF可能加上了中韩半导体这种收益大的,我这边是恒科,所以我这个收益比不上他。

这个回测时间也掐的很好,6月30日,再回测多两个月就大回撤了哦。

今天就是随便搓一个。感兴趣的可以自己试试。

"""import jqdata# 1. 标的池 security_list = [    # 8只 A股宽基ETF    "510050.XSHG", # 上证50ETF    "510300.XSHG", # 沪深300ETF    "510500.XSHG", # 中证500ETF    "510600.XSHG", # 中证1000ETF    "159915.XSHE", # 创业板ETF    "588000.XSHG", # 科创50ETF    "159361.XSHE", # 中证A500ETF    "159845.XSHE", # 科创创业50ETF    # 4只 跨境ETF    "513600.XSHG", # 恒生指数ETF    "513130.XSHG", # 恒生科技ETF    "513100.XSHG", # 纳指100ETF    "513500.XSHG"  # 标普500ETF]# 指标参数MA_period = 20macd_fast = 12macd_slow = 26macd_signal = 9def initialize(context):    set_benchmark('000300.XSHG')    set_option('use_real_price', True)    # ETF交易费率    set_order_cost(OrderCost(open_tax=0, close_tax=0,                              open_commission=0.0001, close_commission=0.0001,                              close_today_commission=0, min_commission=5), type='stock')    g.buy_candidates = []    g.sell_candidates = []    # 收盘计算信号    run_daily(generate_signal, time='15:20', reference_security='000001.XSHE')    # 次日开盘交易    run_daily(execute_trade, time='9:31', reference_security='000001.XSHE')def generate_signal(context):    # 先清空昨日信号    g.buy_candidates = []    g.sell_candidates = []    for stock in security_list:        # 获取日线数据        df = get_price(stock, end_date=context.current_dt, frequency='daily', count=80, fields=['close'])        # 数据长度不足直接跳过        if len(df) < 40:            log.warn(f"{stock} 历史K线数量不足,跳过计算")            continue        close = df['close']        ma20 = close.rolling(window=MA_period).mean()        price_now = close.iloc[-1]        ma20_now = ma20.iloc[-1]        # MACD计算        ema_fast = close.ewm(span=macd_fast, adjust=False).mean()        ema_slow = close.ewm(span=macd_slow, adjust=False).mean()        dif = ema_fast - ema_slow        dea = dif.ewm(span=macd_signal, adjust=False).mean()        dif_now = dif.iloc[-1]        dif_pre = dif.iloc[-2]        dea_now = dea.iloc[-1]        dea_pre = dea.iloc[-2]        # 买入条件:站上20日线 + MACD金叉        cond_buy = (price_now >= ma20_now) and (dif_pre <= dea_pre) and (dif_now > dea_now)        if cond_buy:            g.buy_candidates.append(stock)        # 卖出条件:跌破20日线        cond_sell = price_now < ma20_now        if cond_sell:            g.sell_candidates.append(stock)    log.info("===== 收盘信号 =====")    log.info("待买入标的:", g.buy_candidates)    log.info("待卖出标的:", g.sell_candidates)def execute_trade(context):    positions = context.portfolio.positions    # 卖出持仓中满足条件标的    for stock in g.sell_candidates:        if stock in positions and positions[stock].total_amount > 0:            order_target(stock, 0)            log.info(f"【开盘卖出】{stock} 收盘价跌破MA20")    # 均分资金买入候选标的    buy_list = g.buy_candidates    buy_count = len(buy_list)    if buy_count <= 0:        return    available_cash = context.portfolio.available_cash    each_target_value = available_cash / buy_count    for stock in buy_list:        order_target_value(stock, each_target_value)        log.info(f"【开盘买入】{stock} MA20之上 + MACD金叉")

开通量化软件:零基础量化入门|一文搞懂 PTrade 与 QMT,散户该怎么选?

回首页,搜索你想要的文档

在首页搜索框输入关键词,快速定位资料

文库首页搜索指引 立即搜索

相关学习资料