初学股票策略代码编写,跑回测后无成交,策略收益为0,请教学习

用户头像sh_****631fye
2026-06-20 发布

-- coding: utf-8 --

"""
同花顺SuperMind量化选股策略
基本面选股 + 30%止盈 + 8%止损 + 自动调仓 + 备选宽松条件 + 股票黑名单
核心规则:

  1. 市值20亿~500亿,优质财务指标选股,剔除ST/*ST
  2. 每日开盘前选股,最多持仓50只,等权分配资金
  3. 单只个股持仓成本价对比,涨幅达到30%止盈清仓,跌幅达到8%止损清仓
  4. 严格条件选股数量不足时自动放宽财务门槛,防止长期空仓
    """
    import pandas as pd

全局自定义参数(单位:元)

MIN_MARKET_VALUE = 20 * 108 # 最小市值20亿
MAX_MARKET_VALUE = 500 * 10
8 # 最大市值500亿
MAX_SELECT_NUM = 50 # 最多持仓50只股票
BLACK_LIST = [] # 自定义股票黑名单,示例:["600000.XSHG"]

选股过少时的宽松备用阈值

RELAX_ROE = 10
RELAX_GROSS_MARGIN = 25
RELAX_REVENUE_YOY = 5

止盈止损比例

PROFIT_RATE = 0.30
LOSS_RATE = -0.08

def init(context):
"""策略初始化函数"""
context.hold_stocks = []
context.target_stocks = [] # 新增:盘前选股结果缓存
context.cost_price = dict() # 记录每只股票建仓成本价

def before_trading_start(context, bar_dict):
"""每个交易日开盘前执行选股,只做筛选,不交易"""
def get_stock_data(roe_limit, margin_limit, yoy_limit):
q = query(
supermind_valuation.code,
supermind_valuation.market_cap,
supermind_fin_indicator.net_profit_parent,
supermind_fin_indicator.operating_revenue,
supermind_fin_indicator.roe,
supermind_fin_indicator.gross_margin_ratio,
supermind_valuation.pe_ttm,
supermind_fin_indicator.revenue_yoy
).filter(
supermind_valuation.market_cap >= MIN_MARKET_VALUE,
supermind_valuation.market_cap <= MAX_MARKET_VALUE,
supermind_fin_indicator.net_profit_parent > 0,
supermind_fin_indicator.operating_revenue > 1 * 10**8,
supermind_fin_indicator.roe > roe_limit,
supermind_fin_indicator.gross_margin_ratio > margin_limit,
supermind_fin_indicator.revenue_yoy > yoy_limit,
supermind_valuation.pe_ttm >= 0,
supermind_valuation.pe_ttm <= 30,
)
df = get_fundamentals(q, date=context.current_dt.date())
df = df.dropna()
df = df[~df["code"].isin(BLACK_LIST)]

手动过滤ST风险警示股票(标准方案)

df = df[~df['code'].str.match(r'^[0,3,6]{6}[.XSHE|.XSHG]*ST')]
return df

严格条件筛选

df_result = get_stock_data(15, 30, 10)
if len(df_result) < 5:
print("严格筛选标的不足,自动放宽财务筛选条件")
df_result = get_stock_data(RELAX_ROE, RELAX_GROSS_MARGIN, RELAX_REVENUE_YOY)

if df_result.empty:
print("当前筛选条件下无符合要求的股票,全部空仓")
target_stocks = []
else:
df_result = df_result.head(MAX_SELECT_NUM)
raw_codes = df_result["code"].tolist()
temp_stocks = []
for code in raw_codes:
if code.startswith(('0','3')):
temp_stocks.append(code + '.XSHE')
elif code.startswith('6'):
temp_stocks.append(code + '.XSHG')
target_stocks = temp_stocks
print(f"筛选出{len(target_stocks)}只标的股票:{target_stocks}")

仅缓存选股结果,移到handle_bar做调仓

context.target_stocks = target_stocks
context.hold_stocks = target_stocks
def rebalance_position(context, bar_dict, target_codes):
"""等权仓位分配、自动调仓平仓函数"""
total_target_num = len(target_codes)
current_hold = set(context.portfolio.positions.keys())
target_set = set(target_codes)

调出池的个股清仓

for stock_code in current_hold:
if stock_code not in target_set and stock_code != "cash":
order_target_percent(stock_code, 0)
print(f"调出选股池,卖出 {stock_code}")
if stock_code in context.cost_price:
del context.cost_price[stock_code]

if total_target_num == 0:
return

single_weight = 1.0 / total_target_num

执行仓位配置,建仓时记录成本价(使用当日收盘价)

for stock_code in target_codes:
order_target_percent(stock_code, single_weight)
print(f"调仓买入 {stock_code},单只仓位:{single_weight:.2%}")
if stock_code not in context.cost_price:
# 使用当前bar收盘价作为建仓成本,解决盘前取不到价格的问题
context.cost_price[stock_code] = bar_dict[stock_code].close
def handle_bar(context, bar_dict):
"""主线程:先执行每日调仓,再监控止盈止损"""

第一步:每日开盘后执行调仓

rebalance_position(context, bar_dict, context.target_stocks)

第二步:监控止盈止损

current_positions = context.portfolio.positions
for stock_code in list(current_positions.keys()):
if stock_code == "cash":
continue
if stock_code not in context.cost_price:
continue
cost = context.cost_price[stock_code]
current_price = bar_dict[stock_code].close
profit_ratio = (current_price - cost) / cost

30%止盈

if profit_ratio >= PROFIT_RATE:
print(f"{stock_code} 收益率{profit_ratio:.2%},触发30%止盈,清仓")
order_target_percent(stock_code, 0)
del context.cost_price[stock_code]
if stock_code in context.hold_stocks:
context.hold_stocks.remove(stock_code)

8%止损

elif profit_ratio <= LOSS_RATE:
print(f"{stock_code} 收益率{profit_ratio:.2%},触发8%止损,清仓")
order_target_percent(stock_code, 0)
del context.cost_price[stock_code]
if stock_code in context.hold_stocks:
context.hold_stocks.remove(stock_code)

评论