可直接回测!Ptrade 强势 ETF 周度轮动程序化交易策略全解

可直接回测!Ptrade 强势 ETF 周度轮动程序化交易策略全解
文章简介本文基于 Ptrade 量化平台搭建一套可直接回测、仿真运行的周度强势 ETF 轮动策略。核心逻辑每周筛选 20 日涨幅最强 2 只 ETF7:3 资金配比买入每周最后一个交易日全部清仓循环滚动做趋势短线。全文附带完整可运行代码、函数拆解、节假日自动适配逻辑与实操避坑要点新手也能快速上手改造。适用人群Ptrade 量化学习者、ETF 趋势交易者、程序化自动化交易爱好者平台 Ptrade Python 量化接口策略类型周度趋势轮动、动量策略一、策略核心逻辑整套策略极简易懂完全贴合 A 股 ETF T1 交易规则无日内频繁交易风险选股规则每周首个交易日遍历 ETF 候选池计算所有标的近 20 个交易日涨跌幅取涨幅前 2 名强势标的资金分配第一名分配 70% 可用资金第二名分配 30%可自行修改权重卖出规则每周最后一个交易日 14:55 统一清仓全部持仓预留 5 分钟成交时间循环执行次周重复选股、买入、清仓流程持续跟踪市场强势板块 ETF特色适配内置交易日判断函数自动跳过周末、法定节假日周一休市则顺延至节后首个交易日。二、完整策略代码# 1. 导入依赖库 import datetime import pandas as pd from datetime import date from datetime import timedelta import numpy as np # 2. 策略初始化函数程序启动仅执行一次 def initialize(context): # ETF候选池自行填充沪市/深市ETF代码示例[510300.SS,159915.SZ] g.security_list [] set_universe(g.security_list) # 全局缓存变量 g.trade_days_list get_trade_days(2015-01-01, 2025-10-31) # 交易日期总表 g.selected_stocks [] # 每周筛选出的2只ETF g.weights [0.7, 0.3] # 资金分配比例 g.hold_positions context.portfolio.positions # 当前持仓 # 定时任务每日固定时间执行对应函数 run_daily(context, buy_function, time9:31) # 周初9:31执行买入 run_daily(context, sell_function, time14:55) # 周末14:55执行清仓 # 3. 每日盘前执行筛选强势ETF、标记本周首尾交易日 def before_trading_start(context, data): today get_trading_day(0) # 判断是否本周第一个/最后一个交易日 g.is_first is_first_trading_day_of_week(today) g.is_last is_last_trading_day_of_week(today) print({}是否为本周首个交易日: {}.format(today, g.is_first)) print({}是否为本周最后一个交易日: {}.format(today, g.is_last)) # 仅周初执行选股逻辑 if g.is_first: returns {} for stock in g.security_list: # 获取近20日收盘价 history get_history(20, 1d, close, stock, fqpre) # 计算20日涨跌幅 ret (history.iloc[-1, 0] - history.iloc[0, 0]) / history.iloc[0, 0] returns[stock] ret log.info(各ETF20日涨跌幅, returns) # 按涨幅降序排序取前2只 sorted_returns sorted(returns.items(), keylambda x: x[1], reverseTrue) g.selected_stocks [item[0] for item in sorted_returns[:2]] else: pass # 4. 买入函数周初开盘后按比例下单 def buy_function(context): if g.is_first: total_available_cash context.portfolio.cash for i in range(len(g.selected_stocks)): # 获取最新1分钟收盘价 history_1 get_history(1, 1m, close, g.selected_stocks[i], fqpre) current_price history_1.iloc[0] # 分配对应资金 buy_cash total_available_cash * g.weights[i] # A股ETF一手100份计算可买整数手 amount int(buy_cash / current_price / 100) * 100 if amount 0: order(g.selected_stocks[i], amount) else: log.info(今日不是本周第一个交易日不执行买入) # 5. 卖出函数周末收盘前全部清仓 def sell_function(context): if g.is_last: g.current_holdings {} # 遍历全部持仓 for sid, position in context.portfolio.positions.items(): if position.amount 0: g.current_holdings[sid] position.amount sell_list list(g.current_holdings.keys()) # 清仓所有持仓 for code in sell_list: if g.current_holdings[code] 0: order_target(code, 0) log.info(卖出{}共{}份.format(code, g.current_holdings[code])) else: log.info(今日不是本周最后一个交易日不执行卖出) # 辅助函数1判断当日是否为本周第一个交易日自动适配节假日 def is_first_trading_day_of_week(today): one_day timedelta(days1) yesterday today - one_day # 向前寻找上一个有效交易日 while yesterday.strftime(%Y-%m-%d) not in g.trade_days_list: yesterday - one_day # 周数不同则代表今天是本周首个交易日 return today.isocalendar()[1] yesterday.isocalendar()[1] or today.year yesterday.year # 辅助函数2判断当日是否为本周最后一个交易日自动适配节假日 def is_last_trading_day_of_week(today): one_day timedelta(days1) tomorrow today one_day # 向后寻找下一个有效交易日 while tomorrow.strftime(%Y-%m-%d) not in g.trade_days_list: tomorrow one_day # 周数不同则代表今天是本周最后一个交易日 return today.isocalendar()[1] tomorrow.isocalendar()[1] or today.year tomorrow.year三、代码逐模块详细解析3.1 依赖库导入模块import datetime import pandas as pd from datetime import date from datetime import timedelta import numpy as npdatetime/timedelta处理日期、交易日偏移、节假日判断pandas行情数据表格处理numpy数值计算、涨跌幅运算 所有 Ptrade 策略必备基础库缺失会导致行情获取、日期计算报错。3.2 initialize 初始化函数程序启动仅运行一次负责全局变量、候选池、定时任务配置g.security_listETF 标的池必须手动填充代码沪市后缀.SS、深市后缀.SZget_trade_days拉取指定区间全部交易日用于节假日判断run_daily定时触发器固定时间自动执行买卖函数无需人工盯盘3.3 before_trading_start 盘前选股函数每个交易日开盘前自动执行核心完成两件事调用is_first_trading_day_of_week标记周初交易日遍历候选池 ETF拉取 20 日收盘价计算动量涨幅降序排序选出前 2 只强势标的存入全局变量注意此函数仅做数据计算不会发起交易下单。3.4 buy_function 买入下单函数仅每周首个交易日 9:31 执行获取账户可用现金按 7:3 权重分配资金读取实时 1 分钟收盘价计算可买入份数int(xxx/100)*100强制保证下单数量为 100 的整数倍符合 A 股 ETF 交易规则order(标的, 数量)Ptrade 原生限价下单接口。3.5 sell_function 清仓卖出函数仅每周最后一个交易日 14:55 执行遍历账户全部持仓筛选持有数量大于 0 的 ETForder_target(code, 0)一键清仓接口目标持仓设为 0无需手动计算卖出数量14:55 操作预留 5 分钟收盘缓冲避免尾盘流动性不足无法成交。3.6 交易日判断辅助函数策略核心适配工具解决节假日、长假休市问题is_first_trading_day_of_week向前回溯查找上一个交易日对比周数自动识别节后首个交易日is_last_trading_day_of_week向后查找下一个交易日识别节前最后一个交易日 无需手动调整日期回测、实盘均可自动适配。四、策略实操关键注意事项4.1 ETF 候选池配置g.security_list []为空列表必须填充标的推荐宽基、行业 ETF 混合建议 20~40 只格式区分沪深市场代码后缀写错会导致行情拉取失败。4.2 回测时间区间匹配代码内get_trade_days(2015-01-01, 2025-10-31)回测起止时间不能超出该区间可自行修改结束年份拓展数据范围。4.3 资金权重自定义g.weights [0.7, 0.3]风险偏好保守可改为[0.5,0.5]均衡分配仅支持 2 个数值对应选出的 2 只 ETF。4.4 A 股交易规则适配ETF 实行 T1 交易本策略每周买入、次周卖出完全规避日内交易限制不存在当日买入无法卖出的逻辑 bug。4.5 回测优先谨慎实盘先用 Ptrade 仿真终端长期回测观察不同牛熊周期收益、最大回撤可自行调参20 日动量周期改为 10/30 日、增减持仓数量实盘前小资金试运行 1~2 个月验证成交滑点、手续费对收益的影响。五、策略优化拓展思路增加止损逻辑在每日盘后增加持仓跌幅判断单只 ETF 回撤超 5% 强制卖出多周期动量过滤叠加 60 日中长期趋势仅在大盘上行时执行轮动仓位动态调整根据市场波动率自动调整总仓位高位降仓、低位加仓扩大持仓数量修改代码选取前 3~4 只 ETF分散单一标的风险过滤低流动性标的增加日均成交额筛选剔除成交量低迷的小盘 ETF。六、总结本套 Ptrade ETF 周度动量轮动策略代码完整、逻辑轻量化内置节假日自动适配、合规交易数量处理、定时自动交易能力新手可直接复用平台回测。 策略核心依靠动量效应捕捉中期强势板块 ETF每周调仓频率适中不会产生过高交易手续费适合中长期自动化定投 趋势交易结合的投资者。风险提示本文仅为量化代码教学分享不构成任何投资建议。量化策略存在历史回测不代表未来收益市场波动、流动性风险、手续费滑点均会影响实际收益请谨慎使用。