策略分享

基于中证红利的股息率与ROE选股策略

由jliang创建,最终由jliang 被浏览 130 用户

策略介绍

中证红利指数(CSI Dividend Index)是由中证指数公司编制的,旨在反映中国A股市场中高股息率股票的整体表现。该指数选取了股息率较高的股票构成样本,具有较低的波动性和较高的分红收益率,是稳健投资者喜爱的标的。

本策略主要通过筛选中证红利指数中的股票,重点考虑股息率(Dividend Yield)和净资产收益率(Return on Equity,ROE)两个因子。股息率是衡量股票分红收益的一项指标,而ROE则反映了企业运用资本的效率。综合考虑这两个因子,可以筛选出既能提供高分红,又具有较好运营能力的股票,进而实现稳健的收益。

回撤控制和夏普率的提升是本策略的两个关键目标。回撤控制旨在减少投资组合在市场波动中的损失,而夏普率则衡量了单位风险下的收益水平。因此,在策略设计中,除了关注选股因子,还需加入适当的风险管理措施,如止盈和止损策略,以实现稳定的收益。

策略流程

  1. 股票池:从中证红利指数中选择股票。
  2. 排序条件:根据股息率和ROE的综合评分进行排序。
  3. 筛选条件:默认不做额外的筛选,以保证样本的多样性和代表性。
  4. 仓位设置:等权重持有评分最高的前N只股票,持仓数量可根据实际需求调整。
  5. 交易逻辑:每日调仓,根据最新的股息率和ROE数据进行排序和选股。
  6. 风险管理:通过设置止盈和止损点,控制回撤,提高夏普率。

策略实现

模块说明

cn_stock_basic_selector:A股-基础选股,用于筛选中证红利指数中的股票。 参数:

indexes=["中证红利"]

input_features_dai:输入特征(DAI),用于构建股息率和ROE因子。 参数:

expr="""
dividend_yield_ratio AS div_yield
roe_avg_ttm AS roe
(div_yield + roe) AS score
"""

score_to_position:仓位分配,根据股息率和ROE的综合评分进行排序,并等权重分配仓位。 参数:

score_field="score DESC"
hold_count=10(持仓数量可以根据需求调整)
position_expr="1 AS position"

extract_data_dai:数据抽取,用于抽取传入的sql数据。 参数:

start_date="2016-06-01"
end_date="2024-04-29"

bigtrader:BigTrader(高性能回测),实现回测逻辑。 参数:

capital_base=1000000
frequency="daily"
rebalance_period_type="daily"

因子表达式

因子表达式主要包括股息率和ROE:

dividend_yield_ratio AS div_yield
roe_avg_ttm AS roe

策略代码

from bigmodule import M

# <aistudiograph>

# @param(id="m5", name="initialize")
def m5_initialize_bigquant_run(context):  # type: ignore
    from bigtrader.finance.commission import PerOrder

    # 系统已经设置了默认的交易手续费和滑点,要修改手续费可使用如下函数
    context.set_commission(PerOrder(buy_cost=0.0003, sell_cost=0.0013, min_cost=5))

# @param(id="m5", name="handle_data")
def m5_handle_data_bigquant_run(context, data):  # type: ignore
    import pandas as pd

    # 下一个交易日不是调仓日,则不生成信号
    if not context.rebalance_period.is_signal_date(data.current_dt.date()):
        return

    # 从传入的数据 context.data 中读取今天的信号数据
    today_df = context.data[context.data["date"] == data.current_dt.strftime("%Y-%m-%d")]
    target_instruments = set(today_df["instrument"])

    # 获取当前已持有股票
    holding_instruments = set(context.get_account_positions().keys())

    # 卖出不在目标持有列表中的股票
    for instrument in holding_instruments - target_instruments:
        context.order_target_percent(instrument, 0)
    # 买入目标持有列表中的股票
    for i, x in today_df.iterrows():
        position = 0.0 if pd.isnull(x.position) else float(x.position)
        context.order_target_percent(x.instrument, position)

# @module(position="-437,-854", comment="""使用基本信息对股票池过滤""", comment_collapsed=False)
m1 = M.cn_stock_basic_selector.v6(  # type: ignore
    exchanges=["上交所", "深交所", "北交所"],
    list_sectors=["主板", "创业板", "科创板"],
    indexes=["中证红利"],
    st_statuses=["正常", "ST", "*ST"],
    margin_tradings=["两融标的", "非两融标的"],
    sw2021_industries=["农林牧渔", "采掘", "基础化工", "钢铁", "有色金属", "建筑建材", "机械设备", "电子", "汽车", "交运设备", "信息设备", "家用电器", "食品饮料", "纺织服饰", "轻工制造", "医药生物", "公用事业", "交通运输", "房地产", "金融服务", "商贸零售", "社会服务", "信息服务", "银行", "非银金融", "综合", "建筑材料", "建筑装饰", "电力设备", "国防军工", "计算机", "传媒", "通信", "煤炭", "石油石化", "环保", "美容护理"],
    drop_suspended=True,
    m_name="m1"
)

# @module(position="-315,-727", comment="""因子特征""", comment_collapsed=False)
m2 = M.input_features_dai.v29(  # type: ignore
    # 如果没有上游模块,则不需要 input_1 参数,不能设置为 None
    input_1=m1.data,
    mode="表达式",
    expr="""
dividend_yield_ratio AS div_yield
roe_avg_ttm AS roe
(div_yield + roe) AS score
""",
    expr_tables="cn_stock_prefactors",
    extra_fields="date, instrument",
    order_by="date, instrument",
    expr_drop_na=True,
    extract_data=False,
    m_name="m2"
)

# @module(position="-207,-592", comment="""持股数量、打分到仓位""", comment_collapsed=False)
m3 = M.score_to_position.v3(  # type: ignore
    input_1=m2.data,
    score_field="score DESC",
    hold_count=10,
    position_expr="1 AS position",
    total_position=1,
    extract_data=False,
    m_name="m3"
)

# @module(position="-98,-463", comment="""抽取预测数据""", comment_collapsed=False)
m4 = M.extract_data_dai.v17(  # type: ignore
    sql=m3.data,
    start_date="2016-06-01",
    start_date_bound_to_trading_date=True,
    end_date="2024-04-29",
    end_date_bound_to_trading_date=True,
    before_start_days=90,
    debug=False,
    m_name="m4"
)

# @module(position="43,-350", comment="""交易,日线,设置初始化函数和K线处理函数,以及初始资金、基准等""", comment_collapsed=False)
m5 = M.bigtrader.v20(  # type: ignore
    data=m4.data,
    start_date="",
    end_date="",
    initialize=m5_initialize_bigquant_run,
    handle_data=m5_handle_data_bigquant_run,
    capital_base=1000000,
    frequency="daily",
    product_type="股票",
    rebalance_period_type="daily",
    rebalance_period_days="1",
    rebalance_period_roll_forward=True,
    backtest_engine_mode="标准模式",
    before_start_days=0,
    volume_limit=1,
    order_price_field_buy="open",
    order_price_field_sell="open",
    benchmark="沪深300指数",
    plot_charts=True,
    debug=False,
    backtest_only=False,
    m_name="m5"
)
# </aistudiograph>

\

标签

选股策略股息率稳健投资
{link}