微盘反转策略 v1
2 min read
import pandas as pd
==================== 可调参数 ====================
g_pool_size = 400 # 微盘股池大小 g_buy_count = 20 # 买入股票数量 g_look_back = 5 # 反转回看天数
def init(context): context.pool_size = g_pool_size context.buy_count = g_buy_count context.look_back = g_look_back context.micro_stocks = []
# 每周第1个交易日调仓
scheduler.run_weekly(rebalance, tradingday=1)
logger.info("策略初始化完成")
def before_trading(context): """盘前获取微盘股池"""
# 获取全市场股票
all_stocks = all_instruments('CS').order_book_id.tolist()
# 获取市值数据
df = get_factor(all_stocks, 'a_share_market_val_3')
if df is None or df.empty:
logger.warn("获取市值数据失败")
context.micro_stocks = []
return
# 处理索引
if isinstance(df.index, pd.MultiIndex):
df = df.reset_index(level=1, drop=True)
# 删除空值
df = df.dropna()
if df.empty:
context.micro_stocks = []
return
# 按市值升序排序(小市值在前)
df = df.sort_values(ascending=True)
# 取市值最小的N只
df = df.head(context.pool_size)
context.micro_stocks = df.index.tolist()
logger.info("微盘股池数量: {}".format(len(context.micro_stocks)))
def rebalance(context, bar_dict): """周度调仓"""
if len(context.micro_stocks) == 0:
logger.warn("微盘股池为空")
return
# 计算反转因子
stock_returns = {}
for stock in context.micro_stocks:
try:
hist = history_bars(stock, context.look_back + 1, '1d', 'close')
if hist is not None and len(hist) >= 2:
ret = float(hist[-1]) / float(hist[0]) - 1.0
stock_returns[stock] = ret
except:
pass
if len(stock_returns) == 0:
logger.warn("无法计算收益率")
return
# 按收益率升序排序(跌幅最大在前)
sorted_returns = sorted(stock_returns.items(), key=lambda x: x[1])
candidates = [s[0] for s in sorted_returns[:context.buy_count * 2]]
# 过滤可交易股票
target_list = []
for stock in candidates:
if can_trade(stock, bar_dict):
target_list.append(stock)
if len(target_list) >= context.buy_count:
break
if len(target_list) == 0:
logger.warn("无可交易股票")
return
logger.info("本周选中: {} 只".format(len(target_list)))
# 先卖
for stock in list(context.portfolio.positions.keys()):
if stock not in target_list:
if stock in bar_dict and bar_dict[stock].is_trading:
order_target_percent(stock, 0)
# 后买
weight = 0.95 / len(target_list)
for stock in target_list:
order_target_percent(stock, weight)
def can_trade(stock, bar_dict): """检查是否可交易""" try: # 检查ST if is_st_stock(stock): return False
# 检查是否在bar_dict中
if stock not in bar_dict:
return False
# 检查是否停牌
if not bar_dict[stock].is_trading:
return False
# 检查涨跌停
hist = history_bars(stock, 2, '1d', 'close')
if hist is None or len(hist) < 1:
return True
yesterday_close = hist[-1]
zt = round(1.10 * yesterday_close, 2)
dt = round(0.90 * yesterday_close, 2)
current = bar_dict[stock].close
if current >= zt or current <= dt:
return False
return True
except:
return False
def handle_bar(context, bar_dict): pass