大类资产配置-长期均衡策略(年化收益8.83\%)
之前ptrade的账号销号了,导致很多策略源码丢了。翻了翻在其他平台写的代码,和ptrade的结构差不多,供大家参考。也欢迎大家讨论。
一、策略原理:
1、黄金ETF、国债ETF、300ETF和纳指ETF月度调仓,长期均衡配置
2、每月第一个交易日调仓
3、根据300指数历史分位决定仓位:
| 300指数分位数 | 黄金ETF | 国债ETF | 300ETF | 纳指ETF | 
|---|---|---|---|---|
| 大于80 | 37% | 37% | 13% | 13% | 
| [40,80] | 33% | 33% | 17% | 17% | 
| [20,40) | 29% | 29% | 21% | 21% | 
| [10,20) | 25% | 25% | 25% | 25% | 
| [0,10) | 21% | 21% | 29% | 29% | 
二、回测结果:

三、源码(共参考学习思路,用于ptrade需要修改部分函数名):
# 股票策略模版
# 初始化函数,全局只运行一次
def init(context):
    # 设置基准收益:沪深300指数
    set_benchmark('000300.SH')
    # 打印日志
    log.info('策略开始运行,初始化函数全局只运行一次')
    # 设置股票每笔交易的手续费为万分之二(手续费在买卖成交后扣除,不包括税费,税费在卖出成交后扣除)
    set_commission(PerShare(type='stock',cost=0.0002))
    # 设置股票交易滑点0.5%,表示买入价为实际价格乘1.005,卖出价为实际价格乘0.995
    set_slippage(PriceSlippage(0.005))
    # 设置日级最大成交比例25%,分钟级最大成交比例50%
    # 日频运行时,下单数量超过当天真实成交量25%,则全部不成交
    # 分钟频运行时,下单数量超过当前分钟真实成交量50%,则全部不成交
    set_volume_limit(0.25,0.5)
    # 设置要操作的标的:
    context.security = ['511010.SH','518880.SH','510300.SH','513100.SH']
    # 回测区间、初始资金、运行频率请在右上方设置
    # 记录最近一次调仓日期
    g.modify_date=get_datetime().date()
#每日开盘前9:00被调用一次,用于储存自定义参数、全局变量,执行盘前选股等
def before_trading(context):
    # 获取日期
     date = get_datetime().strftime('%Y-%m-%d %H:%M:%S')
    # 打印日期
    # log.info('{} 盘前运行'.format(date))
## 开盘时运行函数
def handle_bar(context, bar_dict):
    # 获取时间
    time = get_datetime().strftime('%Y-%m-%d %H:%M:%S')
    # 打印时间
    log.info('{} 盘中运行'.format(time))
    if is_change_date():
        log.info("==============调仓日==============")
        pct = get_his_pct("000300.SH")
        target_pct = 0.17
        if pct > 80:
            target_pct = 0.13
        if pct<40:
            target_pct = 0.21
        if pct<20:
            target_pct = 0.25
        if pct<10:
            target_pct = 0.29
            
        target_pct_main = (1-target_pct*2)/2
        log.info("pct:",pct)
        log.info("rp:",target_pct)
        log.info("rpm:",target_pct_main)
        g.modify_date=get_datetime().date()
        for stock_code in context.security:
            if stock_code in  ['511010.SH','518880.SH']:
                order_id = order_target_percent(stock_code,target_pct_main)
            if stock_code in  ['510300.SH','513100.SH']:
                order_id = order_target_percent(stock_code,target_pct)
                
            
   
## 收盘后运行函数,用于储存自定义参数、全局变量,执行盘后选股等
def after_trading(context):
    # # 获取时间
    time = get_datetime().strftime('%Y-%m-%d %H:%M:%S')
    # # 打印时间
    # log.info('{} 盘后运行'.format(time))
    # log.info('一天结束')
    
## 判断当日是不是需要调仓
def is_change_date():
    the_day = get_datetime().date()
    delta_day = (the_day - g.modify_date).days
    if the_day.day == 1 or delta_day>=31:
        return True
    else:
        return False
## 获取指定标的的历史分位数        
def get_his_pct(stock_code):
    price = history(stock_code, ['close'], 1800, '1d', True, 'pre', is_panel=1)['close']
    last = price[-1]
    price_sorted = sorted(price)
    position  = 0
    for i, value in enumerate(price_sorted):
        if value >= last:
            position = i+1
            break
    percentile_rank = (position / len(price)) * 100
    return percentile_rank
 
                                 
                 
                 
                 
                
2024-12-09 14:17
2024-12-09 12:03