![](https://img.haomeiwen.com/i5787343/377cb45b49b56b3c.png)
本文章的学习内容参考自 https://www.joinquant.com/post/6596?f=18newyearjx 感谢 @JoinQuant-TWist 和 @聚宽小秘书
根据个人习惯,对代码进行了调整😁
策略说明
每隔10个交易日,等金额持有市值排名最小的前5只股票,卖出其他股票
回测和源代码如下:
![](https://img.haomeiwen.com/i5787343/17d5adab56e23446.png)
def initialize(context):
g.stocksnum = 5 # 持有最小市值股票数
g.period = 10 # 轮动频率
run_daily(daily,time='every_bar')# 周期循环daily
g.days = 1 # 记录策略进行到第几天,初始为1
def daily(context):
# 判断策略进行天数是否能被轮动频率整除余1
if g.days % g.period == 1:
# 获取当前时间
date=context.current_dt.strftime("%Y-%m-%d")
# 获取上证指数和深证综指的成分股代码并连接,即为全A股市场所有股票
scu = get_index_stocks('000001.XSHG')+get_index_stocks('399106.XSHE')
# 选出在scu内的股票的股票代码,并按照当前时间市值从小到大排序
df = get_fundamentals(query(
valuation.code,valuation.market_cap
).filter(
valuation.code.in_(scu)
).order_by(
valuation.market_cap.asc()
), date=date
)
# 取出前g.stocksnum名的股票代码,并转成list类型,buylist为选中的股票
buylist =list(df['code'][:g.stocksnum])
# 对于每个当下持有的股票进行判断:现在是否已经不在buylist里,如果是则卖出
for stock in context.portfolio.positions:
if stock not in buylist: #如果stock不在buylist
order_target(stock, 0) #调整stock的持仓为0,即卖出
# 将资金分成g.stocksnum份
position_per_stk = context.portfolio.cash/g.stocksnum
# 用position_per_stk大小的g.stocksnum份资金去买buylist中的股票
for stock in buylist:
order_value(stock, position_per_stk)
else:
pass # 什么也不做
g.days = g.days + 1 # 策略经过天数增加1
经过思考🤔,我认为这个策略可以改进
- 如果买入列表中的股票有停牌的,不仅无法买入,还会影响资金利用率,所以我讲买入列表中的停牌股票剔除掉
- 资金分配不是按照固定持股数进行等额分配,而是根据经过筛选实际可以买入的数量来分配
- 如果已经持仓的股票,不会被二次买入
- 由于经过筛选后,可买入的股票将会变少,在概率上来讲是这样,所以我讲持股数量提升为10
改进代码如下,包括回测结果
![](https://img.haomeiwen.com/i5787343/3824679f675a4964.png)
def initialize(context):
"""初始化函数"""
# 持有最小市值股票数
g.stocksnum = 10
# 轮动频率
g.period = 10
# 记录策略进行到第几天
g.days = 0
# 周期循环daily
run_daily(daily,time='every_bar')
def daily(context):
"""交易函数"""
# 每运行一天加一
g.days += 1
# 判断策略进行天数是否能被轮动频率整除余1
if g.days % g.period != 1:
return
# 获取当前时间
date=context.current_dt.strftime("%Y-%m-%d")
# 获取上证指数和深证综指的成分股代码并连接,即为全A股市场所有股票
# 这里股票池不放在全局中是因为总有新发型股票出现,所以要动态获取股票池
scu = get_index_stocks('000001.XSHG') + get_index_stocks('399106.XSHE')
# 选出在scu内的股票的股票代码,并按照当前时间市值从小到大排序
df = get_fundamentals(query(
valuation.code,
valuation.market_cap
).filter(
valuation.code.in_(scu)
).order_by(
valuation.market_cap.asc()
), date=date
)
# 取出前g.stocksnum名的股票代码,并转成list类型,buylist为选中的股票
buylist =list(df['code'][:g.stocksnum])
# 对于每个当下持有的股票进行判断:现在是否已经不在buylist里,如果是则卖出
if stock not in buylist: #如果stock不在buylist
order_target(stock, 0) #调整stock的持仓为0,即卖出
# 已经持仓的不会再被买入
buy_list = list(set(buylist) - set(context.portfolio.positions.keys()))
# 当日停牌的股票不交易
current_data = get_current_data()
buy_list = [stock for stock in buylist if not current_data[stock].paused]
# 如果没有需要买进的股票,就返回
if len(buy_list) <= 0:
return
# 动态分配资金
position_per_stk = context.portfolio.cash/len(buy_list)
# 动态买入股票
for stock in buy_list:
order_value(stock, position_per_stk)
经过调整,回测效果提升将近90个百分点。
如果还有改进想法的看官,可以提出建议。另外,小市值策略在近期其实效果很差,与市场整体有关。另外,小市值经常有停牌退市的风险,很有可能在持有阶段停牌,所以风险很高
网友评论