小市值策略:挖掘市场潜力
由jliang创建,最终由jliang 被浏览 256 用户
策略介绍
小市值策略是一种经典的量化投资策略,旨在通过筛选市值较小的股票,并根据市值对股票进行排序,选取市值最小的一部分股票进行投资。这种策略基于小市值股票在某些市场条件下可能具有较高的增长潜力和投资回报率。
策略背景
小市值策略的理论基础可以追溯到Fama-French三因素模型。该模型指出,除了市场风险外,股票的收益还与市值和账面市值比有关。具体来说,小市值股票通常具有更高的预期回报,因为小市值公司相对于大市值公司在市场上更容易被低估,从而在未来具有更大的增长潜力。此外,小市值公司通常具有较高的灵活性和创新能力,能够迅速适应市场变化和抓住新的商业机会,这进一步增强了其投资吸引力。
策略优势
小市值策略的主要优势在于其对市场潜力的挖掘能力。相比于大市值股票,小市值股票更容易被市场忽视,因此其价格往往低于其真实价值。通过投资这些被低估的股票,投资者可以获得超额收益。此外,小市值公司通常具有较高的成长性和灵活性,在市场景气时表现出色,从而带来更高的投资回报率。最后,小市值策略相对简单易行,不需要复杂的数学模型和大量的计算资源,适合广泛的投资者使用。
策略核心
小市值策略的核心在于对股票市值的筛选和排序。首先,筛选出市值较小的股票,通过剔除停牌股、ST股和*ST股等方式确保股票池的质量。然后,根据流通市值对股票进行排序,选取市值最小的部分股票进行投资。持仓方面,通常采取等权重分配的方法,以降低单个股票对整体组合的影响。此外,策略需要定期调仓,一般每月调仓一次,确保投资组合始终保持在目标市值范围内。
策略劣势及改进
尽管小市值策略有诸多优点,但也存在一些不足之处。首先,小市值股票的流动性通常较差,可能导致交易成本较高,影响整体收益。其次,小市值公司由于规模较小,抵御市场波动和经济衰退的能力较弱,风险较大。为了弥补这些不足,可以考虑以下改进措施:增加流动性筛选条件,确保选出的股票具有足够的交易量;引入风险管理机制,如设置止盈止损策略,控制投资组合风险;结合其他因子,如成长因子和质量因子,进一步优化选股模型,提高投资组合的稳定性和收益率。
未来展望
随着金融市场的发展和量化投资技术的进步,小市值策略在未来有望继续发挥重要作用。结合大数据和人工智能技术,可以更精确地挖掘市场中的潜在机会,进一步提升策略的收益率和稳定性。此外,随着市场环境的变化,策略需要不断优化和调整,以适应新的市场条件。例如,可以引入机器学习算法,动态调整选股模型和调仓频率,提高策略的灵活性和适应性。总之,小市值策略在未来具有广阔的发展前景,值得投资者持续关注和研究。
策略流程
小市值策略的具体流程如下:
- 股票池筛选:筛选A股市场中的所有股票,剔除停牌股、ST股和*ST股,确保股票池的质量。
- 排序条件:根据流通市值(float_market_cap)从小到大排序,选取市值最小的部分股票。
- 持仓设置:选择市值最小的50只股票,等权重分配持仓,降低单个股票对整体组合的影响。
- 交易逻辑:每月第一个交易日调仓,卖出不在目标持仓列表中的股票,买入目标持仓列表中的股票,确保投资组合始终保持在目标市值范围内。
- 风险管理:本策略不设置止盈止损策略,但可以根据具体需求引入风险管理机制。
BigQuant 平台策略实现
模块说明
cn_stock_basic_selector:A股-基础选股,用于筛选A股市场中的所有股票。 参数:
exchanges=["上交所", "深交所", "北交所"](选择所有交易所)
indexes=["中证500", "上证指数", "创业板指", "深证成指", "上证50", "科创50", "沪深300", "中证1000", "中证100", "深证100"](选择所有指数)
st_statuses=["正常"](剔除ST和*ST股)
drop_suspended=True(剔除停牌股)
input_features_dai:输入特征,用于构建因子表达式。 参数:
input_1=m1.data(输入上游模块的数据)
mode="表达式"(使用表达式模式)
expr="c_rank(float_market_cap) AS score"(根据流通市值进行排名)
expr_filters=""(无筛选条件)
expr_tables="cn_stock_prefactors"(使用预计算因子表)
extra_fields="date, instrument"(需要额外字段date和instrument)
order_by="date, instrument"(按date和instrument排序)
expr_drop_na=True(丢弃NA值)
score_to_position:仓位分配模块,根据排序规则,仓位规则和持仓股票数量控制仓位。 参数:
input_1=m2.data(输入上游模块的数据)
score_field="score ASC"(根据score从小到大排序)
hold_count=50(持仓股票数量为50)
position_expr="1 AS position"(等权重分配)
extract_data_dai:数据抽取,用于抽取预测数据。 参数:
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(开始日期前的数据)
bigtrader:BigTrader(高性能回测),实现回测逻辑。 参数:
data=m4.data(输入上游模块的数据)
start_date=""(自动获取前面设置的开始日期)
end_date=""(自动获取前面设置的结束日期)
initialize=m5_initialize_bigquant_run(初始化函数)
handle_data=m5_handle_data_bigquant_run(K线处理函数)
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指数"(基准为沪深300指数)
plot_charts=True(绘制图表)
debug=False(调试模式关闭)
backtest_only=False(不仅限于回测)
因子表达式
c_rank(float_market_cap) AS score
因子解释
- c_rank(float_market_cap):对股票的流通市值进行排名,数值越小表示市值越小。
- 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="-437,-854", comment="""使用基本信息对股票池过滤""", comment_collapsed=False)
m1 = M.cn_stock_basic_selector.v6( # type: ignore
exchanges=["上交所", "深交所", "北交所"],
indexes=["中证500", "上证指数", "创业板指", "深证成指", "上证50", "科创50", "沪深300", "中证1000", "中证100", "深证100"],
st_statuses=["正常"],
drop_suspended=True,
m_name="m1"
)
# @module(position="-315,-727", comment="""因子特征""", comment_collapsed=False)
m2 = M.input_features_dai.v29( # type: ignore
input_1=m1.data,
mode="表达式",
expr="""
c_rank(float_market_cap) AS score
""",
expr_filters="",
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 ASC",
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="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="月度交易日",
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>
\