策略分享

全A股小市值与动量因子策略

由polll创建,最终由polll 被浏览 170 用户

策略介绍

全A股市场的量化投资策略在近年来受到越来越多投资者的关注。此次我们介绍的策略主要依赖小市值因子和动量因子进行股票选择,以期在不进行风险控制的情况下最大化年化收益率。小市值因子(Small Size Factor)和动量因子(Momentum Factor)是量化投资中常用的两个因子。

小市值因子基于“规模效应假说”,认为小市值股票往往具有更高的收益潜力,因为它们的增长空间较大且往往被市场低估。动量因子则基于“惯性效应假说”,认为过去表现好的股票在未来一段时间内仍有可能继续表现优异。这两个因子的结合可以在一定程度上兼顾成长性与市场趋势,形成一个较为稳健的投资组合。

然而,这种策略也有其局限性。首先,策略不进行风险控制,这意味着在市场波动较大时,可能会遭受较大的回撤。此外,小市值股票的流动性较差,在大规模资金进出时可能会面临较高的交易成本。为了改进该策略,可以考虑加入风险控制模块,如设置止损线或采用动态仓位管理。

策略流程

  1. 股票池:全A股市场。
  2. 排序条件:使用小市值因子和动量因子进行排序。
  3. 筛选条件:无额外筛选。
  4. 仓位设置:等权重持仓,持仓数量设置为50只股票。
  5. 交易逻辑:每月初进行调仓。
  6. 风险管理:不进行风险管理。

策略实现

模块说明

input_features_dai:输入特征模块,提取小市值因子和动量因子,并计算综合评分因子。

  • 参数:
    • expr:表达式,计算市值、动量和综合评分因子。
    • expr_tables:数据表,使用A股市场数据。
    • extra_fields:额外字段,包含日期和股票代码。
    • order_by:排序条件,按日期和股票代码排序。
    • expr_drop_na:是否去除NA值。
    • extract_data:是否提取数据。

score_to_position:仓位分配模块,根据综合评分因子进行排序,选择前50只股票进行等权重持仓。

  • 参数:
    • score_field:评分字段,按综合评分因子降序排序。
    • hold_count:持仓数量,50只股票。
    • position_expr:仓位表达式,等权重持仓。
    • total_position:总持仓比例,1表示全仓。

bigtrader:高性能回测模块,执行回测逻辑。

  • 参数:
    • rebalance_period_type:调仓周期,月度调仓。
    • initialize:初始化函数。
    • handle_data:交易逻辑函数。
    • capital_base:初始资金,100万元。
    • frequency:交易频率,日线。
    • product_type:产品类型,股票。
    • rebalance_period_days:调仓日,1表示每月1日调仓。
    • backtest_engine_mode:回测引擎模式,标准模式。
    • volume_limit:交易量限制,1表示不限制。
    • order_price_field_buy:买入价,开盘价。
    • order_price_field_sell:卖出价,开盘价。
    • benchmark:基准,沪深300指数。

因子表达式

  1. 小市值因子c_rank(float_market_cap) AS market_cap_rank
  2. 动量因子m_avg(change_ratio, 20) AS momentum_20
  3. 综合评分因子-(market_cap_rank + momentum_20) AS score

策略实现

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="-315,-727", comment=""""因子特征""", comment_collapsed=False)
m2 = M.input_features_dai.v29(  # type: ignore
    mode="表达式",
    expr="""
c_rank(float_market_cap) AS market_cap_rank
m_avg(change_ratio, 20) AS momentum_20
-(market_cap_rank + momentum_20) 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=50,
    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="2020-01-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="月度交易日",
    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}