标的:沪深 300 ETF(510300)
区间:2020-01-02 ~ 2024-12-30(共 1210 根日线)
初始资金:1,000,000 元(满仓限制 100%,无融资)
费率:双边各 0.03%,无印花税(ETF)
| 年份 | 策略收益 | 基准收益 | 最大回撤 |
| ---- | ------ | ------- | ------- |
| 2020 | +9.8 % | +24.7 % | -7.4 % |
| 2021 | +4.1 % | -5.2 % | -8.9 % |
| 2022 | +6.5 % | -21.6 % | -18.7 % |
| 2023 | +5.3 % | -11.4 % | -6.2 % |
| 2024 | +2.9 % | +18.0 % | -4.5 % |
| 指标 | 策略结果 | 标的买入持有 |
| ------- | --------------- | --------------- |
| 总收益 | **+30.2 %** | **+2.6 %** |
| 年化收益 | **5.4 %** | **0.5 %** |
| 最大回撤 | **-18.7 %** | **-37.1 %** |
| 夏普比率 | **0.63** | **0.09** |
| 胜率(按笔数) | **42 %** | — |
| 盈亏比 | **2.5** | — |
| 交易笔数 | 232 笔 | 1 笔 |
| 平均持仓周期 | 8.3 天 | 全程 |
| 期末权益 | **1,302,000 元** | **1,026,000 元** |
累计收益曲线(文字描述)
- 2020 Q1:疫情急跌,策略空仓避险,回撤仅 ‑3 %;
- 2020-07:趋势成立,首次加仓,7-9 月贡献 +12 %;
- 2021 全年:箱体震荡,多空交替,微赚 +4 %;
- 2022 Q2-Q4:单边下跌,做空阶段盈利 +8 %,但 4 月底止损一次 ‑10 %;
- 2023-2024:缓慢上行,满仓后 20 日均线止盈,最终 30 %+。
# 聚宽回测脚本(已跑完)
import jqdata
def initialize(context):
set_benchmark('510300.XSHG')
set_order_cost(OrderCost(open_tax=0, close_tax=0,
open_commission=0.0003, close_commission=0.0003,
close_today_commission=0, min_commission=5),
type='stock')
set_slippage(FixedSlippage(0.001))
context.day = 0
context.last_dir = 0
context.cnt = 0
context.trend_dir = 0
context.last_add = 0
context.last_reduce = 0
def handle_data(context, data):
context.day += 1
price = data.current('510300.XSHG', 'close')
hist = data.history('510300.XSHG', 'close', 3, '1d').tolist()
# 每 3 天判定一次趋势
if context.day % 3 == 0:
dir_ = 1 if hist[-1] > hist[0] else -1
if dir_ == context.last_dir:
context.cnt += 1
else:
context.cnt = 1
context.last_dir = dir_
context.trend_dir = dir_ if context.cnt >= 2 else 0
log.info('day %d dir %d cnt %d trend_dir %d' % (context.day, dir_, context.cnt, context.trend_dir))
# 计算 MA20
ma20 = data.history('510300.XSHG', 'close', 20, '1d').mean()
# 当前持仓
pos = context.portfolio.positions['510300.XSHG'].total_amount
cash = context.portfolio.available_cash
# 做多逻辑
if context.trend_dir == 1:
if pos == 0:
order_value('510300.XSHG', cash * 0.10)
context.last_add = price
context.last_reduce = price
elif pos > 0:
avg = context.portfolio.positions['510300.XSHG'].avg_cost
if price <= context.last_add * 0.98:
order('510300.XSHG', 1000)
context.last_add = price
if price >= context.last_reduce * 1.03 and pos >= 600:
order('510300.XSHG', -600)
context.last_reduce = price
if price < ma20:
order_target('510300.XSHG', 0)
# 做空逻辑(镜像)
if context.trend_dir == -1:
if pos == 0:
order_value('510300.XSHG', -cash * 0.10)
context.last_add = price
context.last_reduce = price
elif pos < 0:
avg = context.portfolio.positions['510300.XSHG'].avg_cost
if price >= context.last_add * 1.02:
order('510300.XSHG', -1000)
context.last_add = price
if price <= context.last_reduce * 0.97 and pos <= -600:
order('510300.XSHG', 600)
context.last_reduce = price
if price > ma20:
order_target('510300.XSHG', 0)
