这个量化策略的核心在于选取最高连板数的股票作为龙头,开盘就买入,第二天尾盘如果是涨停的就继续拿着;如果不涨停,有盈利就卖出,持仓超过两天也卖出
回测数据如下:

*回测数据只作测试用,不代表未来实际收益
主要定义了持股的龙头数量、选股因子、运行周期等等
# 分仓数量
g.ps = 10 # 最高板龙头一般不会超过10个
g.jqfactor = 'VOL5' #5日平均换手率(只是做为示例)
g.sort = True #选取因子值最小
# 每日运行
run_daily(get_stock_list, '9:01')
run_daily(buy, '09:30')
run_daily(sell, '14:50')
2、选股逻辑
(1)过滤科创北交、次新股、st、停牌的股票
initial_list = get_all_securities('stock', date).index.tolist()
initial_list = filter_kcbj_stock(initial_list)
initial_list = filter_new_stock(initial_list, date)
initial_list = filter_st_stock(initial_list, date)
initial_list = filter_paused_stock(initial_list, date)
(2)选出最高板龙头股票
先计算出20天内的连板股票,然后在筛选出最高连板的龙头股票,可能有很多只
# 当日涨停
hl_list = get_hl_stock(initial_list, date)
# 全部连板股票
ccd = get_continue_count_df(hl_list, date, 20) if len(hl_list) != 0 else pd.DataFrame(index=[], data={'count':[],'extreme_count':[]})
# 最高连板
M = ccd['count'].max() if len(ccd) != 0 else 0
# 龙头
ccd0 = pd.DataFrame(index=[], data={'count':[],'extreme_count':[]})
CCD = ccd[ccd['count'] == M] if M != 0 else ccd0
lt = list(CCD.index)
(2.1)计算涨停数
# 计算涨停数
def get_hl_count_df(hl_list, date, watch_days):
# 获取watch_days长度(观察周期)的行情数据
# 包含low(最低价)、close(收盘价)、high_limit(涨停价)三个字段
df = get_price(hl_list, end_date=date, frequency='daily', fields=['low','close','high_limit'], count=watch_days, panel=False, fill_paused=False, skip_paused=False)
df.index = df.code # 将股票代码设为索引
hl_count_list = [] # 普通涨停天数
extreme_hl_count_list = [] # 一字涨停天数
for stock in hl_list:
df_sub = df.loc[stock] # 获取单只股票数据
hl_days = df_sub[df_sub.close==df_sub.high_limit].high_limit.count() # 计算普通涨停天数(收盘价=涨停价)
extreme_hl_days = df_sub[df_sub.low==df_sub.high_limit].high_limit.count() # 计算一字涨停天数(最低价=涨停价)
hl_count_list.append(hl_days) # 记录普通涨停天数
extreme_hl_count_list.append(extreme_hl_days) # 记录一字涨停天数
#创建df记录
df = pd.DataFrame(index=hl_list, data={'count':hl_count_list, 'extreme_count':extreme_hl_count_list})
return df
(2.2)计算连板数
# 计算连板数
def get_continue_count_df(hl_list, date, watch_days):
df = pd.DataFrame()
for d in range(2, watch_days+1): # 从2天开始,一直到观察周期结束
HLC = get_hl_count_df(hl_list, date, d) # 计算连板数
CHLC = HLC[HLC['count'] == d] # 筛选出连续d天涨停的股票
df = df.append(CHLC) # 记录连续d天涨停的股票
stock_list = list(set(df.index))
ccd = pd.DataFrame()
for s in stock_list:
tmp = df.loc[[s]]
if len(tmp) > 1:
M = tmp['count'].max() # 计算最大连板数
tmp = tmp[tmp['count'] == M]
ccd = ccd.append(tmp)
if len(ccd) != 0:
ccd = ccd.sort_values(by='count', ascending=False) # 按照连板数降序排列
return ccd
(3)筛选5日平均换手率最低的股票
这类股票封板质量高
df = get_factor_filter_df(context, lt, 'VOL5', g.sort)
stock_list = list(df.index)
# 按因子筛选股票
def get_factor_filter_df(context, stock_list, 'VOL5', sort):
if len(stock_list) != 0:
yesterday = context.previous_date
score_list = get_factor_values(stock_list, jqfactor, end_date=yesterday, count=1)[jqfactor].iloc[0].tolist()
df = pd.DataFrame(index=stock_list, data={'score':score_list}).dropna()
df = df.sort_values(by='score', ascending=sort)
else:
df = pd.DataFrame(index=[], data={'score':[]})
return df
3、买入逻辑
开盘涨停,涨停价买入,开盘未涨停,最新价买入
for s in g.target_list:
if context.portfolio.available_cash/current_data[s].last_price>100:
# 如果开盘涨停,用限价单排板
if current_data[s].last_price == current_data[s].high_limit:
order_value(s, value, LimitOrderStyle(current_data[s].day_open))
print('买入' + s)
print('———————————————————————————————————')
# 如果开盘未涨停,用市价单即刻买入
else:
order_value(s, value, MarketOrderStyle(current_data[s].day_open))
print('买入' + s)
print('———————————————————————————————————')
4、卖出逻辑
尾盘判断,涨停就一直持有,如果不涨停,分两种情况:
有盈利,直接卖出
持仓超过2天,直接卖出
for s in hold_list:
# 条件1:不涨停
if not (current_data[s].last_price == current_data[s].high_limit):
if context.portfolio.positions[s].closeable_amount != 0:
# 条件2.1:持有一定时间
start_date = transform_date(context.portfolio.positions[s].init_time, 'str')
target_date = get_shifted_date(start_date, 2, 'T')
current_date = transform_date(context.current_dt, 'str')
# 条件2.2:已经盈利
cost = context.portfolio.positions[s].avg_cost
price = context.portfolio.positions[s].price
ret = 100 * (price/cost-1)
# 在满足条件1的前提下,条件2中只要满足一个即卖出
if current_date >= target_date or ret > 0:
if current_data[s].last_price > current_data[s].low_limit:
order_target_value(s, 0)
print('卖出' + s)
print('———————————————————————————————————')
这篇文章主要分享连板龙头策略,主要的逻辑在连板龙头的选取和卖出逻辑上面,后续优化可以考虑加入情绪筛选和概念筛选。
发布者:股市刺客,转载请注明出处:https://www.95sca.cn/archives/1352300
站内所有文章皆来自网络转载或读者投稿,请勿用于商业用途。如有侵权、不妥之处,请联系站长并出示版权证明以便删除。敬请谅解!