编写一个简单的策略
基本策略:
- 设定好要交易的股票数量stocksnum
- 每天找出市值排名最小的前stocksnum只股票作为要买入的股票
- 若已持有的股票的市值已经不够小而不在要买入的股票中,则卖出这些股票
- 买入要买入的股票,买入金额为当前可用资金的stocksnum分之一。
加强策略:
- 希望能实现通过一个变量period控制操作的周期,即每period天进行一次选股并交易。
def initialize(context):
run_daily(period,time='every_bar')
# 设定好要交易的股票数量stocksnum
g.stocksnum = 7
# 设定交易周期
g.p = 13
# 记录策略进行天数
g.days = 0
def period(context):
if g.days % g.p == 0:#设置13天买一次股票
# 找出市值排名最小的前stocksnum只股票作为要买入的股票
scu= get_index_stocks('000001.XSHG')+get_index_stocks('399106.XSHE')
df=get_fundamentals(query(valuation.code).filter(valuation.code.\
in_(scu)).order_by(valuation.market_cap.asc()).limit(g.stocksnum))
buylist=list(df['code'])
# 若已持有的股票的市值已经不够小而不在要买入的股票中,则卖出这些股票。
for stock in context.portfolio.positions:
if stock not in buylist:
order_target(stock, 0)
# 买入要买入的股票,买入金额为可用资金的stocksnum分之一
for s in buylist:
order_value(s,(context.portfolio.available_cash)/g.stocksnum)
g.days+=g.days
代码中有一个选出所有股票的小技巧:使用获取指数成分股方法可以获取上证指数和深证综指的成分股,两者加起来就是当前全市场股票的股票列表,用加号可以连接两个list。以下是该策略在2016年的回测结果:
继续优化:
- 排除停牌股票、ST股票和涨停股票
- 加入止损条件
def initialize(context):
run_daily(period,time='every_bar')
g.stocksnum = 7
g.p = 13
g.days = 0
def period(context):
if g.days % g.p == 0:
# 找出市值排名最小的前stocksnum只股票作为要买入的股票
scu= get_index_stocks('000001.XSHG')+get_index_stocks('399106.XSHE')
# 排除停牌股票、ST股票和涨停股票
stock_list = []
current_data = get_current_data()#获得universe中股票的信息
for stock in scu:
if not current_data[stock].is_st:
if not current_data[stock].paused:
if current_data[stock].last_price !=current_data[stock].high_limit:
stock_list.append(stock)
df=get_fundamentals(query(valuation.code).filter(valuation.code.\
in_(stock_list)).order_by(valuation.market_cap.asc()).limit(g.stocksnum))
buylist=list(df['code'])
# 若已持有的股票的市值已经不够小而不在要买入的股票中,则卖出,并且止损。
for stock in context.portfolio.positions:
cost = context.portfolio.positions[stock].avg_cost
price = context.portfolio.positions[stock].price
ret = price/cost - 1
if stock not in buylist:
order_target(stock, 0)
else:
if ret < -0.05: #止损
order_target(stock,0)
buylist.remove(stock)
print("触发止损")
if ret > 0.05: #止盈
order_target(stock,0)
buylist.remove(stock)
print("触发止盈")
# 买入要买入的股票,买入金额为可用资金的stocksnum分之一
for s in buylist:
order_value(s,(context.portfolio.available_cash)/g.stocksnum)
g.days+=g.days
get_current_data(security_list=None)函数可以获得数据在一个单位时间(天/分钟)的涨跌停价、是否停牌、当天的开盘价等。如果security_list 是 None,代表使用 universe 中的股票。该函数返回一个 dict 对象,key 是股票代码,value 数据具体如下:
- high_limit : 涨停价
- low_limit : 跌停价
- paused : 是否停止或者暂停交易,当停牌、未上市或退市后返回 True
- is_st : 是否包含 ST,*ST
- day_open : 当天开盘价,分钟回测时可用
- name : 股票现在的名称
- industry_code : 股票现在所属的行业代码
可以看到虽然该策略不如上一个策略表现好,但是更贴近市场真实情况。
参考文献
https://www.joinquant.com/view/community/detail/8ec7aaaa899cf928550f89a104637f22?type=1