量化策略之连板龙头

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

回测数据如下:

量化策略之连板龙头

*回测数据只作测试用,不代表未来实际收益

主要定义了持股的龙头数量、选股因子、运行周期等等

# 分仓数量
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
站内所有文章皆来自网络转载或读者投稿,请勿用于商业用途。如有侵权、不妥之处,请联系站长并出示版权证明以便删除。敬请谅解!

(0)
股市刺客的头像股市刺客
上一篇 7小时前
下一篇 2小时前

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注