量化投资.docx
《量化投资.docx》由会员分享,可在线阅读,更多相关《量化投资.docx(11页珍藏版)》请在冰豆网上搜索。
![量化投资.docx](https://file1.bdocx.com/fileroot1/2023-1/26/042b8d9a-760a-4343-ad8c-07ac3244c2fa/042b8d9a-760a-4343-ad8c-07ac3244c2fa1.gif)
量化投资
量化投资
【网格交易】,号称全解析~到社区搜了一下,有同学转贴,但还没实现。
冰柠檬同学在钟摆策略中交易方法有用到网格的思想,但没有系统的介绍。
好啦,干货来啦~
1.熊市不用跑,15年6月至今回测收益20%(同期大盘下跌35%)。
2.10年至今6年,年化23%。
3.震荡期的大红包,12年-13年年化30%。
网格交易是啥子
这是一种仓位策略,用于动态调仓。
该大法秉持的原则是"仓位策略比选股策略更重要"。
当然,我们做策略的,选出好的股票池是我们孜孜不倦的追求~~
几个基本概念
∙1.底仓价:
价格的标准线,建仓和调仓的重要依据。
∙2.低吸高抛:
仓位控制贯彻低吸高抛,绝不追涨杀跌。
根据网格设置买卖价位。
下面举个例子
∙
o在底仓价的附近,我们根据网格的大小,比如每跌3%按仓位买入(第一档:
买40%,第二档:
买30%,第三档:
买20%,第四档:
买10%)。
要注意的是,这里买卖不是绝对的定量,而是调仓到对应仓位。
如果第一次跌破3%,而后上涨到5%时,是不操作的,因为下跌时只建了40%的仓,而上涨5%的仓位是60%,不够抛出。
∙3.网格大小:
上图给出了3种网格大小。
特点是买入网格小于卖出网格。
这种不对称编织网格的道理在于网格的目的是网获利润,将利润建立在趋势的必然性中,而不仅仅是靠震荡的偶然性。
先讲特点和局限吧
首先,定理&公理:
没有万能的策略。
∙1.趋势决定策略的成败。
在长期的上涨趋势中策略才能获得满意回报。
∙2.选股集中在波动大、成长性好的中小市值股票。
不断盘整的周期股、大盘股和业绩不佳的垃圾股踩中就麻烦了。
∙3.底仓价格设定在安全边际内。
在估值顶部设立底仓价格风险极大,会造成很大的损失。
∙4.牛市表现不佳。
分散的仓位策略,没有依据价格形态来修改网格,都可能在牛市中跑输大盘。
降低贝塔的代价就是阿尔法也较低。
∙5.买卖规则不灵活,可能使一些重要的突破支持或阻力位置的买卖点被忽略在网格之外。
来看看策略步骤
1.选股
∙重点行业:
I64互联网和相关服务,I65软件和信息技术服务业
∙低估值PE小:
PE<50
∙小市值:
分行业按市值排列选市值小的30只
∙高波动:
分行业在市值最小的30只中选出过去一年波动率最大的5只股票
∙So,我们的股票池有10只股。
每3个月按上述条件更新一次股票池,更新时不在新股票池的股票全部清仓。
2.网格:
[-3%买,5%卖]、[-5%买,10%卖]、[-8%买,15%卖]、[-12%买,20%卖]
∙四种大小的网格都会相应尝试一下看看效果。
3.资金安排:
在仓位控制时,满仓的概念是(总资金/股票池总数*2.5)
∙后面的乘数是为了提高资金利用率,因为3个月的周期内可能不是每只股票都能达到满仓。
好啦,收韭菜的时候到了
回测做了很多组,大致是分市场行情(牛、震荡和熊)各做了一次。
然后在震荡期调整网格大小分别做了4次。
结论
∙1.记住啦:
熊市大网格、震荡小网格、长周期中间网格。
这个比较好理解,网格小意味着操作频繁,震荡周期就是勤能补拙了,多多的交易,熊市的话大网格容忍度高一些。
∙2.【熊市】:
选取2015-6-1至2016-1-26日,大网格-12%买,20%卖。
最好的结果是半年多盈利20%(大盘同期大跌35%),年化40%+
∙【长周期】:
选取2010-1-1至2015-12-31日,中网格-8%买,15%卖。
最好的结果是6年241%(大盘同期4%),年化23%。
∙【震荡期】:
选取2012-1-1至2013-12-31日,小网格-3%买,5%卖。
最好的结果2年68%(大盘同期-0.5%),年化29.6%。
∙3.下面上一个熊市大网格的回测结果,剩下的大家可以自己克隆代码改参数试咯~
补充
1.小市值选股对策略的影响。
这是个讲交易方法的策略,那么高收益是否因为按小市值筛选股票得来的呢?
仔细看代码会发现,这个策略选股的要点是波动率,而非小市值。
下面加一下去掉小市值条件的长周期回测效果(加小市值:
240%,不加小市值232%,并没太大的影响)
2.行业选取对策略的影响
高成长性行业的股票本来就收益可观,那我们看看控制单一变量,去掉网格交易方法,长期持有股票池的股票效果如何。
注意:
这里每3个月股票池轮换还是在做的,大盘止损的条件也不变。
(长期持有:
157%,运用网格交易:
240%,采用网格交易收益更高,回撤也小一些)
最后:
这不是教科书,这不是教科书,这不是教科书。
精要的是思想,细节的东西大家到搬砖贴里自行学习,有问题欢迎交流讨论,欢迎拍砖~
importnumpy
importpandasaspd
frompandasimportSeries
definitialize(context):
g.count=30
g.cash=1000000
g.buy_stock=[]
g.initial_price={}
g.month=context.current_dt.month
run_monthly(select_stock_by_industry,1,'open')
#选股
#重点行业,低估值PE小,优质蓝筹市值大,高波动
defselect_stock_by_industry(context):
#每3个月更新
month=context.current_dt.month
ifmonth%3!
=g.month%3:
return
industry_list=[
#'C27','C39','I63',
'I64','I65'
#'K70',
#'M73','M74'
#,'N77','R86','R87'
]
stocks=[]
forindustry_codeinindustry_list:
stock_set=get_industry_stocks(industry_code)
#选fundamental比较好的前15只,pe_ration<30,market_cap,按market_cap取后20只股票。
q=query(
valuation.code,valuation.market_cap,valuation.pe_ratio
).filter(
valuation.code.in_(stock_set),
valuation.pe_ratio<50
).order_by(
valuation.market_cap.desc()
).limit(
g.count
)
df=get_fundamentals(q)
stock_set=list(df['code'])
#取波动率最高的2只
variance_list=[]
forstockinstock_set:
variance_list.append(variance(stock))
s1=Series(variance_list,index=stock_set).rank()
stocks=list(s1[s1<6].index)
forstockinstocks:
g.buy_stock.append(stock)
g.initial_price[stock]=0
set_universe(g.buy_stock)
reset_position(context)
returnNone
#轮换选股后清除新股票池外的持仓
reset_position(context):
ifcontext.portfolio.positions.keys()!
=[]:
forstockincontext.portfolio.positions.keys():
ifstocknoting.buy_stock:
order_target_value(stock,0)
returnNone
#计算波动率
defvariance(security_code):
hist1=attribute_history(security_code,180,'1d','close',df=False)
narray=numpy.array(hist1['close'])
sum1=narray.sum()
narray2=narray*narray
sum2=narray2.sum()
N=len(hist1['close'])
mean=sum1/N
var=sum2/N-mean**2
returnvar
#计算股票前n日收益率
defsecurity_return(days,security_code):
hist1=attribute_history(security_code,days+1,'1d','close',df=False)
security_returns=(hist1['close'][-1]-hist1['close'][0])/hist1['close'][0]
returnsecurity_returns
#止损,根据前n日收益率
defconduct_nday_stoploss(context,security_code,days,bench):
ifsecurity_return(days,security_code)<=bench:
forstocking.buy_stock:
order_target_value(stock,0)
log.info("Sell%sforstoploss"%stock)
returnTrue
else:
returnFalse
#计算股票累计收益率(从建仓至今)
defsecurity_accumulate_return(context,data,stock):
current_price=data[stock].price
cost=context.portfolio.positions[stock].avg_cost
ifcost!
=0:
return(current_price-cost)/cost
else:
returnNone
#个股止损,根据累计收益
defconduct_accumulate_stoploss(context,data,stock,bench):
ifsecurity_accumulate_return(context,data,stock)!
=None\
andsecurity_accumulate_return(context,data,stock)order_target_value(stock,0)
log.info("Sell%sforstoploss"%stock)
returnTrue
else:
returnFalse
#选股:
连续N日下跌
defis_fall_nday(days,stock):
his=history(days+1,'1d','close',[stock],df=False)
cnt=0
foriinrange(days):
daily_returns=(his[stock][i+1]-his[stock][i])/his[stock][i]
ifdaily_returns<0:
cnt+=1
ifcnt==5:
returnTrue
else:
returnFalse
#比较现价与N日均价
defcompare_current_nmoveavg(data,stock,days,multi):
current_price=data[stock].price
moveavg=data[stock].mavg(days)
ifcurrent_price>multi*moveavg:
returnTrue
else:
returnFalse
#初始底仓选择,判断没有initial_price,则建立基准价
definitial_price(context,data,stock):
ifg.initial_price[stock]==0:
g.initial_price[stock]=data[stock].price
returnNone
#补仓、空仓:
分n买入/卖出
defsetup_position(context,data,stock,bench,status):
bottom_price=g.initial_price[stock]
ifbottom_price==0:
return
cash=context.portfolio.cash
current_price=data[stock].price
amount=context.portfolio.positions[stock].amount
current_value=current_price*amount
unit_value=g.cash/40
returns=(current_price-bottom_price)/bottom_price
#卖出
if(status=='short'):
ifreturns>benchandcurrent_value>6*unit_value:
order_target_value(stock,6*unit_value)
ifreturns>2*benchandcurrent_value>3*unit_value:
order_target_value(stock,3*unit_value)
ifreturns>3*benchandcurrent_value>1*unit_value:
order_target_value(stock,1*unit_value)
ifreturns>4*benchandcurrent_value>0:
order_target_value(stock,0)
#买入
if(status=='long')andcash>0:
ifreturnsorder_target_value(stock,4*unit_value)
ifreturns<2*benchandcurrent_value<7*unit_value:
order_target_value(stock,7*unit_value)
ifreturns<3*benchandcurrent_value<9*unit_value:
order_target_value(stock,9*unit_value)
ifreturns<4*benchandcurrent_value<10*unit_value:
order_target_value(stock,10*unit_value)
returnTrue
#每个单位时间(如果按天回测,则每天调用一次,如果按分钟,则每分钟调用一次)调用一次
defhandle_data(context,data):
#指数止损,前一天跌幅大于3%
ifconduct_nday_stoploss(context,'000001.XSHG',2,-0.03):
return
forstocking.buy_stock:
ifconduct_accumulate_stoploss(context,data,stock,-0.2):
return
#1.连续5日下跌,不操作
ifis_fall_nday(5,stock):
return
#2.大于5日平均或10日平均1.5倍以上,不操作
ifcompare_current_nmoveavg(data,stock,5,1.5)\
orcompare_current_nmoveavg(data,stock,10,1.5):
return
#初始设置底仓
initial_price(context,data,stock)
#补仓步长:
-3%,-5%,-8%,-12%
setup_position(context,data,stock,-0.08,'long')
#空仓步长:
5%,10%,15%,20%
setup_position(context,data,stock,0.15,'short')