3 分钟快速生成代码
输入想法,AI 即刻生成可运行代码
编写基于市销率(Price-to-Sales Ratio, PS)的选股策略,核心逻辑是寻找营收能力强但市场估值相对较低的股票。PS = 总市值 / 主营业务收入。这种策略常用于评估尚未盈利但有营收增长的成长型公司,或者周期性行业。
以下是一个完整的聚宽(JoinQuant)策略代码。
# -*- 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')
# 设定股票交易手续费:买入万分之三,卖出万分之三加千分之一印花税,最低5元
set_order_cost(OrderCost(close_tax=0.001, open_commission=0.0003, close_commission=0.0003, min_commission=5), type='stock')
# 设定全局变量:持仓数量
g.stock_num = 10
# 设定按月运行,每月第一个交易日开盘后运行
run_monthly(weekly_selection, monthday=1, time='09:30')
def weekly_selection(context):
"""
选股与调仓主逻辑
"""
# 1. 获取股票池:沪深300
target_index = '000300.XSHG'
initial_list = get_index_stocks(target_index)
# 2. 过滤掉 ST 和 停牌 的股票
current_data = get_current_data()
valid_list = []
for code in initial_list:
# 剔除停牌 和 ST
if not current_data[code].paused and not current_data[code].is_st:
valid_list.append(code)
# 3. 查询财务数据:市销率 (PS)
# valuation.ps_ratio: 市销率(TTM)
q = query(
valuation.code,
valuation.ps_ratio
).filter(
valuation.code.in_(valid_list),
valuation.ps_ratio > 0 # 剔除无效或负值
).order_by(
valuation.ps_ratio.asc() # 按 PS 从小到大排序
).limit(g.stock_num) # 取前 N 只
df = get_fundamentals(q)
# 获取最终的目标股票列表
target_list = list(df['code'])
# 4. 执行调仓
rebalance(context, target_list)
def rebalance(context, target_list):
"""
调仓执行函数
"""
# 获取当前持仓
current_holdings = list(context.portfolio.positions.keys())
# 1. 卖出不在目标列表中的股票
for stock in current_holdings:
if stock not in target_list:
order_target_value(stock, 0)
# 2. 买入目标列表中的股票
if len(target_list) > 0:
# 等权重分配资金
# 注意:这里简单处理,用总资产除以目标数量。实际交易中可能需要预留少量现金防止手续费不够
value_per_stock = context.portfolio.total_value / len(target_list)
for stock in target_list:
order_target_value(stock, value_per_stock)
log.info("本月调仓完成,持有股票数量: %d" % len(target_list))
log.info("持有列表: %s" % target_list)
get_fundamentals 与 query:
valuation.ps_ratio:代表市销率(TTM,滚动12个月)。.filter(valuation.ps_ratio > 0):排除掉数据异常或营收为负的情况。.order_by(valuation.ps_ratio.asc()):核心策略逻辑,即选择 PS 值最小的股票。get_current_data:
paused)和 ST 股票(is_st),防止买入无法交易或风险过大的标的。order_target_value:
run_monthly:
Q1: 为什么要用市销率(PS)而不是市盈率(PE)?
A: 市盈率依赖于净利润,而很多高成长公司(如科技股)或者周期性低谷的公司可能暂时亏损(PE为负或极高),但营收依然在增长。市销率相对于净利润更稳定,不易被会计手段操纵,适合评估这类公司。
Q2: 代码中的 valuation.ps_ratio 是静态的还是动态的?
A: 在聚宽的 valuation 表中,ps_ratio 默认通常是 TTM(Trailing Twelve Months,滚动12个月),即使用最近4个季度的财务数据计算,这样能更及时地反映公司当前的估值状态。
Q3: 如何修改持仓数量?
A: 修改 initialize 函数中的 g.stock_num = 10,将 10 改为您想要的数量即可。
Q4: 如何更换股票池?
A: 修改 weekly_selection 函数中的 target_index。例如,改为 '000905.XSHG' 即可基于中证500指数进行选股。