问题描述
解决方案
这是一个基于**高存货周转率(High Inventory Turnover Rate)**的量化选股策略。
策略逻辑说明
- 核心因子:存货周转率 (
inventory_turnover_rate)。- 含义:衡量企业销货能力强弱和存货管理效率高低的指标。通常越高越好,说明存货变现速度快,资金占用水平低。
- 选股范围:全A股(剔除ST、停牌、次新股)。
- 调仓频率:按月调仓(每月第一个交易日)。
- 持仓数量:持有存货周转率最高的 20 只股票。
- 权重分配:等权重买入。
策略代码
# -*- coding: utf-8 -*-
from jqdata import *
def initialize(context):
"""
初始化函数,设定基准、手续费、滑点、运行频率等
"""
# 设定沪深300作为基准
set_benchmark('000300.XSHG')
# 开启动态复权模式(真实价格)
set_option('use_real_price', True)
# 过滤掉order系列API产生的比error级别低的log
log.set_level('order', 'error')
# 设定股票交易手续费:买入万三,卖出万三加千一印花税
set_order_cost(OrderCost(close_tax=0.001, open_commission=0.0003, close_commission=0.0003, min_commission=5), type='stock')
# 设定持仓数量
g.stock_num = 20
# 设定按月运行,每月第一个交易日开盘后运行
run_monthly(rebalance, 1, time='09:30')
def rebalance(context):
"""
调仓主函数
"""
# 1. 获取当前所有股票列表
all_stocks = list(get_all_securities(['stock']).index)
# 2. 过滤掉 ST、停牌、上市不足60天的次新股
feasible_stocks = filter_basic_stock(context, all_stocks)
# 3. 查询财务数据,获取存货周转率最高的股票
# 注意:indicator.inventory_turnover_rate 是存货周转率
q = query(
valuation.code,
indicator.inventory_turnover_rate
).filter(
valuation.code.in_(feasible_stocks)
).order_by(
indicator.inventory_turnover_rate.desc() # 按存货周转率降序排列
).limit(
g.stock_num
)
df = get_fundamentals(q)
if df is None or len(df) == 0:
log.warn("未选出符合条件的股票,本月不调仓")
return
target_list = list(df['code'])
log.info("本月目标持仓: %s" % target_list)
# 4. 执行调仓操作
adjust_position(context, target_list)
def adjust_position(context, target_list):
"""
执行具体的买卖操作
"""
# 获取当前持仓
current_holdings = list(context.portfolio.positions.keys())
# 卖出不在目标列表中的股票
for stock in current_holdings:
if stock not in target_list:
order_target_value(stock, 0)
# 买入目标列表中的股票
# 等权重分配资金
position_count = len(target_list)
if position_count > 0:
# 将总资产平分
value_per_stock = context.portfolio.total_value / position_count
for stock in target_list:
order_target_value(stock, value_per_stock)
def filter_basic_stock(context, stock_list):
"""
基础过滤器:剔除ST、停牌、次新股
"""
current_data = get_current_data()
return [stock for stock in stock_list
if not current_data[stock].is_st
and not current_data[stock].paused
and 'ST' not in current_data[stock].name
and '*' not in current_data[stock].name
and '退' not in current_data[stock].name
and (context.current_dt.date() - get_security_info(stock).start_date).days > 60]
常见问题 (Q&A)
Q: 为什么要使用 get_fundamentals 查询 indicator.inventory_turnover_rate?
A: get_fundamentals 是聚宽提供的财务数据查询接口,indicator 表包含了经过计算的财务指标。inventory_turnover_rate 直接提供了存货周转率数据,避免了手动使用营业成本除以平均存货的计算过程,且该接口会自动匹配当前时间点能获取到的最新财报数据,避免未来函数。
Q: 策略中的 run_monthly 是什么意思?
A: 这是一个定时运行函数。run_monthly(rebalance, 1, time='09:30') 表示在每个月的第 1 个交易日的 09:30 执行 rebalance 函数。财务数据通常按季度更新,按月调仓可以及时捕捉财报发布后的指标变化,同时避免过度频繁交易产生的高额手续费。
Q: 如何优化这个策略?
A: 单一的存货周转率因子可能存在行业偏差(例如零售业通常比制造业周转快)。优化方向包括:
- 行业中性化:在每个行业内分别选取高周转率的股票,而不是在全市场混排。
- 结合其他因子:例如结合 毛利率 (Gross Margin),防止选中虽然周转快但利润极薄甚至亏损甩货的公司;或者结合 ROE 寻找高质量公司。
- 去极值:剔除数据异常的股票。