3 分钟快速生成代码
输入想法,AI 即刻生成可运行代码
编写一个结合**财务状况(基本面)与近期股价表现(技术面)**的选股策略,通常被称为“基本面+技术面”双驱动策略。
为了实现这一目标,我们可以设计如下逻辑:
以下是基于聚宽(JoinQuant)API 的完整策略代码:
# -*- 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 = 10 # 最大持仓数量
# 设定按月运行,每月第一个交易日进行调仓
run_monthly(trade, monthday=1, time='09:30')
def trade(context):
"""
交易函数,包含选股和调仓逻辑
"""
# 1. 获取初始股票池(沪深300)
initial_pool = get_index_stocks('000300.XSHG')
# 2. 基本面筛选(财务状况)
# 查询条件:PE在0-50之间,ROE大于8%
# 排序:按ROE从高到低排序
q = query(
valuation.code,
valuation.pe_ratio,
indicator.roe
).filter(
valuation.code.in_(initial_pool),
valuation.pe_ratio > 0,
valuation.pe_ratio < 50,
indicator.roe > 8
).order_by(
indicator.roe.desc()
).limit(50) # 初选前50只
df_fund = get_fundamentals(q, date=context.previous_date)
if len(df_fund) == 0:
return
fundamental_list = list(df_fund['code'])
# 3. 技术面筛选(近期股价表现)
# 逻辑:当前价格站上60日均线
final_buy_list = []
for stock in fundamental_list:
# 获取过去60天的收盘价数据
# 注意:为了计算MA60,我们需要取60天的数据
h_data = attribute_history(stock, 60, '1d', ['close'], skip_paused=True)
# 如果数据不足60天(如新股),跳过
if len(h_data) < 60:
continue
close_price = h_data['close'][-1] # 当前收盘价(前一分钟/前一天)
ma60 = h_data['close'].mean() # 60日均线
# 如果股价在60日均线之上,加入最终买入列表
if close_price > ma60:
final_buy_list.append(stock)
# 如果选够了目标数量,停止筛选
if len(final_buy_list) >= g.stock_num:
break
# 4. 执行调仓操作
# 获取当前持仓
current_holdings = list(context.portfolio.positions.keys())
# 卖出不在目标列表中的股票
for stock in current_holdings:
if stock not in final_buy_list:
order_target_value(stock, 0)
log.info("卖出 %s" % stock)
# 买入目标列表中的股票
if len(final_buy_list) > 0:
# 等权重分配资金
# 注意:这里简单处理,用总资产除以目标数量。实际交易中可能需要考虑保留现金等。
value_per_stock = context.portfolio.total_value / g.stock_num
for stock in final_buy_list:
order_target_value(stock, value_per_stock)
log.info("买入/调整 %s" % stock)
def after_code_changed(context):
"""
模拟交易更换代码后运行函数
"""
# 可以在这里重置参数或更新设置
pass
initialize (初始化):
run_monthly 设定策略为月度调仓,避免频繁交易产生过高手续费。trade (核心逻辑):
get_fundamentals 函数查询财务数据。
valuation.pe_ratio:市盈率,用于过滤高估值泡沫股。indicator.roe:净资产收益率,衡量公司利用股东资本赚钱的效率,是巴菲特最看重的指标之一。attribute_history 获取历史行情。
ma60 (60日均线),这是股市的“生命线”。股价在均线之上通常意味着中期趋势向好。风险控制:
g.stock_num = 10,实现分散投资,避免单只股票暴雷导致账户重创。Q: 为什么要结合基本面和技术面?
A: 仅看基本面(财务)容易买入“价值陷阱”,即公司很好但股价一直不涨甚至阴跌;仅看技术面(股价)容易买入“垃圾概念股”,一旦炒作结束会面临暴跌。结合两者可以在公司质地优良的基础上,选择市场认可(趋势向上)的时机介入。
Q: 如何调整策略的激进程度?
A:
Q: 策略中的 order_target_value 是什么意思?
A: 这是一个非常实用的下单函数。它的意思是“将某只股票的持仓调整到指定金额”。如果当前没持仓,它会买入;如果持仓不足,它会补仓;如果持仓过多,它会卖出部分。这自动帮我们完成了调仓和再平衡的操作。