Skip to content

七星ETF动量轮动:固定池打分换仓(QMT / PTrade)

七星是一套固定 ETF 池 + 日更动量打分的轮动。池子覆盖黄金、海外宽基、A 股宽基、原油等方向,每天(或每个调仓点)只留分数最高的一只;分数落空就切避险 ETF。分数天数和阈值是示例,不是操作指令。不构成投资建议,不代操盘。

手册:get-market-data-ex · get_history · ss-vs-sh

逻辑简述

  1. 池子固定。黄金、纳指、日经、港股、上证、国债、创业板、原油等写死在代码里,不按成交额动态扩池。
  2. 打分。回看约 25 根日线,对 log(close) 做加权回归:年化斜率 × R²。分数要落在 (0, 阈值) 里才进候选。
  3. 持仓。常见实现只持 1 只。没有合格标的就买避险(国债 / 货币一类)。
  4. 调仓。先卖后买。同一天回调可能进多次,必须用日期戳卡住。

PTrade 七星 v1.7 池子更大,还多了短动量过滤、溢价率、盘中利润保护;QMT 跟单版池子更短,实盘用 run_time 对准 10:30。口径可以自己对齐,不要混用后缀。

QMT 版本

上交所用 .SH。日线用 get_market_data_exend_time 截到上一交易日,不要拿盘中未收盘的 close 当定稿。实盘调仓挂 run_time;回测 run_time 不跑,逻辑仍要能从 handlebar 走进去。见 run_time 回测不跑

七星一类 ETF 轮动 QMT 回测示意

客户端回测截图,用来对照曲线长什么样。区间、资金、滑点和成交假设跟你本机不会一样。不是实盘,不能当收益预期,不构成投资建议。

python
#encoding:gbk
def init(C):
    try:
        A.acct = account
        A.acct_type = accountType
    except NameError:
        A.acct = ''
        A.acct_type = 'STOCK'
    C.set_account(A.acct)
    A.m_days = 25
    A.m_score = 5.0
    A.etf_pool = ['518880.SH', '513100.SH', '510180.SH']  # 示例,完整池见附件
    A.safe_haven_etf = '511010.SH'
    A.rebalance_time = '10:30'
    C.last_rebalance_date = ''
    start = datetime.now().strftime('%Y-%m-%d 09:30:00')
    C.run_time('rebalance_task', '60nSecond', start)

def get_etf_rank(C, etf_pool, current_date):
    # 日线 close -> log -> 加权回归;score = 年化收益 * R2
    # 完整计算见星球附件 QMT_ETF动量轮动.txt
    return []

def rebalance_task(C):
    if C.do_back_test:
        return
    now = datetime.now()
    c_date = now.strftime('%Y%m%d')
    if C.last_rebalance_date == c_date:
        return
    # 到 A.rebalance_time 才打分、先卖后买

passorder 返回不等于成交。持仓 json 放在 QMT 能写的目录,重启后先对一次账户。

PTrade 版本

上交所用 .SS(聚宽源码里的 .XSHG 先换成 .SS)。set_universe 要把池子和防御 ETF 都加进去。常见调度:盘中利润保护、14:00 卖掉不在目标里的、14:01 按排名买入。

七星一类 ETF 轮动 PTrade 回测示意

客户端回测截图。长区间数字会被复权和撮合放大,只看曲线形态,不要对收益。不是实盘,不构成投资建议。

python
def initialize(context):
    g.etf_pool_3 = ['518880.SS', '513100.SS', '510300.SS']  # 示例
    g.lookback_days = 25
    g.holdings_num = 1
    g.defensive_etf = '511880.SS'
    set_universe(g.etf_pool_3 + [g.defensive_etf])
    run_daily(context, sell_not_in_target, time='14:00')
    run_daily(context, buy_by_rank, time='14:01')

def handle_data(context, data):
    pass

order 不传限价时看快照。快照空就等下一拍。ETF 限价常见三位,按股票两位取整会废单。

两边都容易踩的坑

  1. 从 QMT 拷到 PTrade,先全局换 .SH.SS
  2. 回测和实盘不要共用同一份状态 json。
  3. 分数天数、阈值、池子都是示例,先仿真对账再改。
  4. 同一分钟 handlebar / 定时器可能进多次,日期戳写在模块级变量上更稳。

完整源码见知识星球附件,这里只放逻辑和片段。

相关:API 查询 · 热门问题 · 关注 / 知识星球

完整讨论和附件在 知识星球 Kimi量化研究所