水激石则鸣,人激志则宏。

违法和不良信息举报邮箱:230098551@qq.com

沪市在线

量化策略核心:5 因子加权选股,牛熊控仓实现低回撤,每日调仓

· ·

这个量化策略的核心在于5个因子(总市值,流通市值,最新价格,5日平均成交量,60日涨幅)加权打分选股,然后通过牛熊来控制仓位,牛市全仓,熊市30%仓位,通过仓位控制实现低回撤,每日进行调仓。

回测数据如下:

量化_量化对冲和量化阿尔法_矢量量化的量化过程

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

1、策略初始化配置

主要定义了牛熊市分界的参数以及仓位参数,5因子权重参数,择时参数等等

g.isbull = False # 是否牛市
g.chosen_stock_list = [] # 目标股票池
g.nohold = True # 是否空仓
g.sold_stock = {} # 近期卖出的股票及卖出天数
g.stocknum = 4 # 理想持股数量
g.bearpercent = 0.3 # 熊市仓位
g.bearposition = True # 熊市是否持仓
# 初始筛选
g.increase1d = 0.087 # 前一日涨幅
# 排名条件及权重,正数代表从小到大,负数表示从大到小
# 各因子权重:总市值,流通市值,最新价格,5日平均成交量,60日涨幅
g.weights = [5,5,8,4,10]
    
# 配置择时
g.MA = ['000001.XSHG', 10] # 均线择时
g.choose_time_signal = True # 启用择时信号
g.threshold = 0.003 # 牛熊切换阈值
g.buyagain = 5 # 再次买入的间隔时间

2、选股逻辑

(1)判断牛熊市

默认以上证指数10日线为依据,0.3%是过滤日线级别以内的随机波动

现价 > 10日均线*(1+0.3%) → 牛市

现价 < 10日均线*(1-0.3%) → 熊市

def get_bull_bear_signal_minute():
    nowindex = get_close_price(g.MA[0], 1, '1m')
    MAold = (attribute_history(g.MA[0], g.MA[1] - 1, '1d', 'close', True)['close'].sum() + nowindex) / g.MA[1]
    if g.isbull:
        if nowindex * (1 + g.threshold) <= MAold:
            g.isbull = False
    else:
        if nowindex > MAold * (1 + g.threshold):
            g.isbull = True

(2)基础过滤

过滤创业板、ST、停牌、当日涨停、次新股、昨日涨幅过高8.7%

stock_list = filter_gem_stock(context, stock_list)
stock_list = filter_st_stock(stock_list)
stock_list = filter_paused_stock(stock_list)
stock_list = filter_limitup_stock(context, stock_list)
stock_list = filter_new_stock(context, stock_list)
stock_list = filter_increase1d(stock_list)
stock_list = filter_buyagain(stock_list)

(3)5因子加权打分

得分 = 5 x (最小总市值/当前总市值) +5 x (最小流通市值/当前流通市值) + 8 x (最低价/当前价)+ 4 x (最小成交量/当前成交量) +10 x (最小60日涨幅/当前60日涨幅)

所有比值采用最小值/当前值,当前值越小,得分越高,说明有较大的价格发现空间

rank_stock_list = get_fundamentals(query(
        valuation.code, valuation.market_cap, valuation.circulating_market_cap
        ).filter(valuation.code.in_(stock_list)
        ).order_by(valuation.circulating_market_cap.asc()).limit(100))
    # 5日成交量
    volume5d = [attribute_history(stock, 1200, '1m', 'volume', df=False)['volume'].sum() for stock in rank_stock_list['code']]
    # 60日涨幅
    increase60d = [get_growth_rate60(stock) for stock in rank_stock_list['code']]
    # 当前价格
    current_price = [get_close_price(stock, 1, '1m') for stock in rank_stock_list['code']]
    min_price = min(current_price)
    min_increase60d = min(increase60d)
    min_circulating_market_cap = min(rank_stock_list['circulating_market_cap'])
    min_market_cap = min(rank_stock_list['market_cap'])
    min_volume = min(volume5d)
    totalcount = [[i, math.log(min_volume / volume5d[i]) * g.weights[3] + math.log(min_price / current_price[i]) * g.weights[2] + math.log(min_circulating_market_cap / rank_stock_list['circulating_market_cap'][i]) * g.weights[1] + math.log(min_market_cap / rank_stock_list['market_cap'][i]) * g.weights[0] + math.log(min_increase60d / increase60d[i]) * g.weights[4]] for i in rank_stock_list.index]
    totalcount.sort(key=lambda x:x[1]) 

3、调仓逻辑

(1)调仓卖出,仓位调整

熊市仓位调整为总仓位的30%,个股最大仓位不超过个股平均仓位的130%,牛市则为全仓

卖出不在目标股票池的股票,超过个股最大仓位限制时,调整为限制仓位值

if g.choose_time_signal and (not g.isbull):
        free_value = context.portfolio.total_value * g.bearpercent # 熊市可用资金=总资产*30%
        maxpercent = 1.3 / g.stocknum * g.bearpercent # 个股最大仓位=1.3/4*0.3≈9.75%
else:
        free_value = context.portfolio.total_value # 牛市用全部资金
        maxpercent = 1.3 / g.stocknum # 正常最大仓位32.5%
    buycash = free_value / g.stocknum
    
...    
current_percent = context.portfolio.positions[stock].value / context.portfolio.total_value
# 超过最大仓位限制,调整到目标仓位
if current_percent > maxpercent:order_target_value(stock, buycash)

(2)买入股票

熊市仓位调整为总仓位的30%,个股最小仓位不低于个股平均仓位的70%,牛市则为全仓

0.7设置的目的是防止因短期波动触发强制平仓,允许优质股票自然突破理论仓位下限

if g.choose_time_signal and (not g.isbull):
    free_value = context.portfolio.total_value * g.bearpercent # 可用资金
    minpercent = 0.7 / g.stocknum * g.bearpercent # 最小持仓比例 0.7/4*0.3 ≈5.25%
else:
    free_value = context.portfolio.total_value # 全仓操作
    minpercent = 0.7 / g.stocknum # 最小持仓比例 0.7/4 = 17.5%
buycash = free_value / g.stocknum # 每支股票理论仓位
...
if hold_stocks[i] in context.portfolio.positions.keys(): # 实时可用资金
    current_percent = context.portfolio.positions[hold_stocks[i]].value / context.portfolio.total_value
    if  current_percent >= minpercent:continue # 当前仓位 ≥ minpercent,跳过
        # 补仓金额 = min(可用资金, 理论仓位-当前仓位)
        tobuy = min(free_cash, buycash - context.portfolio.positions[hold_stocks[i]].value)
    else:
        tobuy = min(buycash, free_cash)
order_value(hold_stocks[i], tobuy)

(3)再次买入的间隔时间

for stock in g.sold_stock.keys():
        if g.sold_stock[stock] >= g.buyagain - 1:
            del g.sold_stock[stock]
        else:
            g.sold_stock[stock] += 1

这篇文章主要分享5因子加权选股以及牛熊控制仓位策略,主要的逻辑在因子加权选股和牛熊市仓位控制上面,量化交易的回测和实盘,可以在量化交易软件中进行,大家可以去体验下量化交易的魅力

如果有不懂的,欢迎找我一起交流,加入量化交易大家庭

相关内容

热门文章

Puma重新定义游戏规则:通过“Go Wild”品牌宣传活动发布大胆战略与品牌定位

Puma重新定义游戏规则:通过“Go Wild”品牌宣传活动发布大胆战略与品牌定位