《掘金量化实战系列》果仁网策略复现第一篇

今天,公众号将为全网读者带来掘金量化复现果仁策略系列!

公众号将为大家多维度、多策略、多场景来讲述掘金量化平台的实践应用。同时,我们对每段代码都做了解读说明,愿你在Quant的道路上学有所获!

此系列将由浅入深,每月1~2期,大家敬请期待!

今日复现策略:《小市值择时策略,模型Ⅰ--定期轮动》

果仁网策略定义


投资域:
股票池:全部股票
系统股票池:全部股票
指数:全部
板块:全部
行业标准:申万 2014
行业:全部
二级行业:全部
交易所:全部
地区省份:全部
企业性质:全部
融资融券:全部
ST:排除ST
科创板:排除科创板
过滤停牌股票:是
筛选条件:
去14月后半月10天大于0
排名条件:
总市值从小到大全部1
交易模型:
模型:I
调仓周期:1
调仓价格:收盘价
空闲资金配置:无
实时选股:未勾选
最大持仓股票数:5
备选买入股票数:5
个股最大买入仓位:100%
个股仓位权重:平权
大盘择时:
无

掘金复现过程

step 1:筛选条件

  • 排除ST

  • 排除科创板

  • 过滤停牌股票

  • 去14月后半月10天

    定义:and(   not(  and ( MonthY()=4,dayM(0)   >10) ),   not(  and ( MonthY()=1,dayM(0)   >10) )    )

date = pd.Timestamp(date).replace(tzinfo=None)
    # A股,剔除停牌和ST股票  https://www.myquant.cn/docs2/sdk/python/API 介绍/通用数据函数(免费).html#get-symbols-查询指定交易日多标的交易信息
    stocks_info = get_symbols(sec_type1=1010, sec_type2=101001, skip_suspended=skip_suspended, skip_st=skip_st, trade_date=date.strftime('%Y-%m-%d'), df=True)
    # 剔除次新股和退市股
    stocks_info['listed_date'] = stocks_info['listed_date'].apply(lambda x:x.replace(tzinfo=None))
    stocks_info['delisted_date'] = stocks_info['delisted_date'].apply(lambda x:x.replace(tzinfo=None))
    stocks_info = stocks_info[(stocks_info['listed_date']<=date-datetime.timedelta(days=new_days))&(stocks_info['delisted_date']>date)]
    # 排除科创板股票(代码以 SHSE.688 开头)
    stocks_info = stocks_info[~stocks_info['symbol'].str.startswith('SHSE.688')]
    # 一四月择时
    stocks_info =  pd.DataFrame(columns=['symbol']) if not (not ((context.current_month == 4 and context.current_day > 10) or (context.current_month == 1 and context.current_day > 10))) else stocks_info
step 2:排序条件
  • 总市值从小到大全部1
 # 配置排序条件(示例:A股总市值+A股流通市值)
    indicators = [
        {'field': 'tot_mv', 'direction': 'asc', 'weight': 1},  # A股总市值
        #  {'field': 'a_mv_ex_ltd', 'direction': 'asc', 'weight': 1}  # A股流通市值
    ]
    # 获取所有字段数据
    fields = [ind['field'] for ind in indicators]
    df = stk_get_daily_mktvalue_pt(symbols=stocks, trade_date=date,
                                   fields=','.join(fields), df=True)
    # 空值处理(空值排最后)
    for ind in indicators:
        field = ind['field']
        if ind['direction'] == 'asc':
            df[field] = df[field].fillna(float('inf'))  # 升序时空值用极大值填充
        else:
            df[field] = df[field].fillna(float('-inf'))  # 降序时用极小值填充
    # 计算综合得分
    total_score = pd.Series(0, index=df.index)
    for ind in indicators:
        field = ind['field']
        weight = ind['weight']
        # 计算排名(升序时直接排序,降序时取负数)
        if ind['direction'] == 'asc':
            sorted_col = df[field]
        else:
            sorted_col = -df[field]
        # 计算排名分
        ranks = sorted_col.rank(method='min', ascending=True)
        score = ((len(df) - ranks + 1) / len(df) * 100).round(2)
        df[f'{field}_score'] = score
        total_score += score * weight
    # 按综合得分排序
    df['total_score'] = total_score
    ranked = df.sort_values(by='total_score', ascending=False)
step 2:交易模型I
在每个调仓日,卖出不满足选股条件的股票,买进满足选股条件的股票, 所有仓内股票在调仓日重新平衡为等权重
 # 筛选
    all_stock,all_stock_str =  filter_stocks(context,last_date)
    # 排序
    target_position = [] if not all_stock else rank_stocks(context, last_date, all_stock)
    # 获取当前持仓
    positions = get_position()
    # 平不在标的池的股票(注:本策略交易以收盘价为交易价格,当调整定时任务时间时,需调整对应价格)
    for position in positions:
        symbol = position['symbol']
        if symbol not in target_position:
            new_price = \
            history_n(symbol=symbol, frequency='1d', count=1, end_time=now_str, fields='close', adjust=ADJUST_PREV,
                      adjust_end_time=context.backtest_end_time, df=False)[0]['close']
            order_target_percent(symbol=symbol, percent=0, order_type=OrderType_Limit, position_side=PositionSide_Long,
                                 price=new_price)
    # 获取股票的权重(预留出1%资金,防止剩余资金不够手续费抵扣)
    if len(target_position)>0:
        percent = 0.99 / len(target_position)
        # 买在标的池中的股票(注:本策略交易以收盘价为交易价格,当调整定时任务时间时,需调整对应价格)
        for symbol in target_position:
            # 收盘价(日频数据)
            new_price = \
            history_n(symbol=symbol, frequency='1d', count=1, end_time=now_str, fields='close', adjust=ADJUST_PREV,
                      adjust_end_time=context.backtest_end_time, df=False)[0]['close']
            order_target_percent(symbol=symbol, percent=percent, order_type=OrderType_Limit,
                                 position_side=PositionSide_Long, price=new_price)

复现结果验证

完整代码获取

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值