一般K线数据,主要是记录HLOC(High,Low,Open,Close)四个值,再加上Volume交易量。在做基于K线分析时候,变动百分比也是一个经常考虑数值。这里说下增加变动百分比的属性。


其实还是很简单,如果不考虑跳空的话,就是(Close - Open)* 100.0 / Open; 考虑到跳空的话,就是当前K线结束值前取上个K线结束值,再处于上个K线结束值即可。


如果有个close的值队列的,示例代码如下

closelist=[100,99,101,103,105,109]defgetPrecentlist(inputlist):precentlist=[]foriinrange(1,len(inputlist)):precent=(inputlist[i]-inputlist[i-1])*100.0/inputlist[i-1]precentlist.append(precent)returnprecentlistgetPrecentlist(closelist)

返回就是如下百分比队列。

[-1.0,2.0202020202020203,1.9801980198019802,1.941747572815534,3.8095238095238093]


同理, 在VNPY的K线序列管理工具ArrayManager,可以加入下面代码。按照属性返回百分比序列

@propertydefpercent(self):"""获取百分比序列"""arrayold=self.closeArray[0:self.size-1]arraynew=self.closeArray[1:self.size]returnmap(lambda(closenew,closeold):(closenew-closeold)*100.0/closeold,zip(arraynew,arrayold))

这里稍微有点玄机,就是利用了lambda把原来function简化,同时用zip生成一个当前close和前一个close的元祖,来调来计算。


下面使用之前做的DataFrame anaylzer做的一些分析。对于豆粕m1905,从2018年09月1日到现在,10分钟K的变动百分比。

首先不出所料,precent以0为中轴的高斯分布。


比较出乎意料的是,对于最大和最小的百分之一到百分之五的K线,之后的2,4,6个K线结束时候,过半数是反转掉头的。我原来以为如果有个大的K线向上,之后回顺着向上,但是看起来,反转更能多出现。


Precent 大于 0.4312038575295748, 99时候,k线数量为 54,第二根K线结束价格上涨概率为 31.48148148148148%;
Precent 小于于 -0.4345589035350628, 1时候,k线数量为 54, 第二根K线结束价格下跌概率为 38.888888888888886%
Precent 大于 0.4312038575295748, 99时候,第四根K线结束价格上涨概率为 33.333333333333336%
Precent 小于于 -0.4345589035350628, 1时候,第四根K线结束价格下跌概率为 48.148148148148145%
Precent 大于 0.4312038575295748, 99时候,第六根K线结束价格上涨概率为 35.18518518518518%
Precent 小于于 -0.4345589035350628, 1时候,第六根K线结束价格下跌概率为 46.2962962962963%
Precent 大于 0.31567899447202463, 98时候,k线数量为 107,第二根K线结束价格上涨概率为 38.3177570093458%;
Precent 小于于 -0.3369829012686155, 2时候,k线数量为 107, 第二根K线结束价格下跌概率为 36.44859813084112%
Precent 大于 0.31567899447202463, 98时候,第四根K线结束价格上涨概率为 37.38317757009346%
Precent 小于于 -0.3369829012686155, 2时候,第四根K线结束价格下跌概率为 41.12149532710281%
Precent 大于 0.31567899447202463, 98时候,第六根K线结束价格上涨概率为 33.64485981308411%
Precent 小于于 -0.3369829012686155, 2时候,第六根K线结束价格下跌概率为 40.18691588785047%
Precent 大于 0.27096928404930803, 97时候,k线数量为 160,第二根K线结束价格上涨概率为 39.375%;
Precent 小于于 -0.2776041810690485, 3时候,k线数量为 160, 第二根K线结束价格下跌概率为 36.25%
Precent 大于 0.27096928404930803, 97时候,第四根K线结束价格上涨概率为 40.625%
Precent 小于于 -0.2776041810690485, 3时候,第四根K线结束价格下跌概率为 41.875%
Precent 大于 0.27096928404930803, 97时候,第六根K线结束价格上涨概率为 40.0%
Precent 小于于 -0.2776041810690485, 3时候,第六根K线结束价格下跌概率为 42.5%
Precent 大于 0.23543815932988155, 96时候,k线数量为 213,第二根K线结束价格上涨概率为 37.55868544600939%;
Precent 小于于 -0.24673951357067325, 4时候,k线数量为 214, 第二根K线结束价格下跌概率为 38.78504672897196%
Precent 大于 0.23543815932988155, 96时候,第四根K线结束价格上涨概率为 40.375586854460096%
Precent 小于于 -0.24673951357067325, 4时候,第四根K线结束价格下跌概率为 43.925233644859816%
Precent 大于 0.23543815932988155, 96时候,第六根K线结束价格上涨概率为 39.436619718309856%
Precent 小于于 -0.24673951357067325, 4时候,第六根K线结束价格下跌概率为 43.925233644859816%


但是,我尝试用这个规律做继续分析收益的时候,发现虽然继续向上或者向下次数不多,但是往往是巨量的,这样如果下一个反转的单子意味着巨亏。这个就是虽然小于50%出现,但是来一次都是高风险呀。


DataFrame 分析代码如下:

#encoding:UTF-8frompymongoimportMongoClient,ASCENDINGimportpandasaspdimportnumpyasnpfromdatetimeimportdatetimeimporttalibimportmatplotlib.pyplotaspltimportscipy.statsasscsclassDataAnalyzer(object):def__init__(self,exportpath="C:\Project\\",datformat=['datetime','high','low','open','close','volume']):self.mongohost=Noneself.mongoport=Noneself.db=Noneself.collection=Noneself.df=pd.DataFrame()self.exportpath=exportpathself.datformat=datformatdefdb2df(self,db,collection,start,end,mongohost="localhost",mongoport=27017,export2csv=False):"""读取MongoDB数据库行情记录,输出到Dataframe中"""self.mongohost=mongohostself.mongoport=mongoportself.db=dbself.collection=collectiondbClient=MongoClient(self.mongohost,self.mongoport,connectTimeoutMS=500)db=dbClient[self.db]cursor=db[self.collection].find({'datetime':{'$gte':start,'$lt':end}}).sort("datetime",ASCENDING)self.df=pd.DataFrame(list(cursor))self.df=self.df[self.datformat]self.df=self.df.reset_index(drop=True)path=self.exportpath+self.collection+".csv"ifexport2csv==True:self.df.to_csv(path,index=True,header=True)returnself.dfdefcsv2df(self,csvpath,dataname="csv_data",export2csv=False):"""读取csv行情数据,输入到Dataframe中"""csv_df=pd.read_csv(csvpath)self.df=csv_df[self.datformat]self.df["datetime"]=pd.to_datetime(self.df['datetime'])self.df=self.df.reset_index(drop=True)path=self.exportpath+dataname+".csv"ifexport2csv==True:self.df.to_csv(path,index=True,header=True)returnself.dfdefdf2Barmin(self,inputdf,barmins,crossmin=1,export2csv=False):"""输入分钟k线dataframe数据,合并多多种数据,例如三分钟/5分钟等,如果开始时间是9点1分,crossmin=0;如果是9点0分,crossmin为1"""dfbarmin=pd.DataFrame()highBarMin=0lowBarMin=0openBarMin=0volumeBarmin=0datetime=0foriinrange(0,len(inputdf)-1):bar=inputdf.iloc[i,:].to_dict()ifopenBarMin==0:openBarmin=bar["open"]ifhighBarMin==0:highBarMin=bar["high"]else:highBarMin=max(bar["high"],highBarMin)iflowBarMin==0:lowBarMin=bar["low"]else:lowBarMin=min(bar["low"],lowBarMin)closeBarMin=bar["close"]datetime=bar["datetime"]volumeBarmin+=int(bar["volume"])#X分钟已经走完ifnot(bar["datetime"].minute+crossmin)%barmins:#可以用X整除#生成上一X分钟K线的时间戳barMin={'datetime':datetime,'high':highBarMin,'low':lowBarMin,'open':openBarmin,'close':closeBarMin,'volume':volumeBarmin}dfbarmin=dfbarmin.append(barMin,ignore_index=True)highBarMin=0lowBarMin=0openBarMin=0volumeBarmin=0ifexport2csv==True:dfbarmin.to_csv(self.exportpath+"bar"+str(barmins)+str(self.collection)+".csv",index=True,header=True)returndfbarmin#--------------------------------------------------------------defPercentage(self,inputdf,export2csv=True):"""计算Percentage"""dfPercentage=inputdfforiinrange(1,len(inputdf)):ifdfPercentage.loc[i-1,"close"]==0.0:percentage=0else:percentage=((dfPercentage.loc[i,"close"]-dfPercentage.loc[i-1,"close"])/dfPercentage.loc[i-1,"close"])*100.0dfPercentage.loc[i,"Perentage"]=percentagedfPercentage=dfPercentage.fillna(0)dfPercentage=dfPercentage.replace(np.inf,0)ifexport2csv==True:dfPercentage.to_csv(self.exportpath+"Percentage_"+str(self.collection)+".csv",index=True,header=True)returndfPercentagedefresultValuate(self,inputdf,nextBar,export2csv=True):summayKey=["Percentage","TestValues"]dft=pd.DataFrame(columns=summayKey)defaddResultBar(self,inputdf,export2csv=False):dfaddResultBar=inputdf######cci在(100-200),(200-300)后的第2根,第4根,第6根的价格走势######################dfaddResultBar["next2BarClose"]=NonedfaddResultBar["next4BarClose"]=NonedfaddResultBar["next6BarClose"]=NonedfaddResultBar["next5BarCloseMakrup"]=Noneforiinrange(1,len(dfaddResultBar)-6):dfaddResultBar.loc[i,"next2BarPercentage"]=dfaddResultBar.loc[i+2,"close"]-dfaddResultBar.loc[i,"close"]dfaddResultBar.loc[i,"next4BarPercentage"]=dfaddResultBar.loc[i+4,"close"]-dfaddResultBar.loc[i,"close"]dfaddResultBar.loc[i,"next6BarPercentage"]=dfaddResultBar.loc[i+6,"close"]-dfaddResultBar.loc[i,"close"]ifdfaddResultBar.loc[i,"close"]>dfaddResultBar.loc[i+2,"close"]:dfaddResultBar.loc[i,"next2BarClose"]=-1elifdfaddResultBar.loc[i,"close"]<dfaddResultBar.loc[i+2,"close"]:dfaddResultBar.loc[i,"next2BarClose"]=1ifdfaddResultBar.loc[i,"close"]>dfaddResultBar.loc[i+4,"close"]:dfaddResultBar.loc[i,"next4BarClose"]=-1elifdfaddResultBar.loc[i,"close"]<dfaddResultBar.loc[i+4,"close"]:dfaddResultBar.loc[i,"next4BarClose"]=1ifdfaddResultBar.loc[i,"close"]>dfaddResultBar.loc[i+6,"close"]:dfaddResultBar.loc[i,"next6BarClose"]=-1elifdfaddResultBar.loc[i,"close"]<dfaddResultBar.loc[i+6,"close"]:dfaddResultBar.loc[i,"next6BarClose"]=1dfaddResultBar=dfaddResultBar.fillna(0)ifexport2csv==True:dfaddResultBar.to_csv(self.exportpath+"addResultBar"+str(self.collection)+".csv",index=True,header=True)returndfaddResultBardefPrecentAnalysis(inputdf):dfPercentage=inputdf#######################################分析分布########################################plt.figure(figsize=(10,3))plt.hist(dfPercentage['Perentage'],bins=300,histtype='bar',align='mid',orientation='vertical',color='r')plt.show()forPerentagekeyinrange(1,5):lpHigh=np.percentile(dfPercentage['Perentage'],100-Perentagekey)lpLow=np.percentile(dfPercentage['Perentage'],Perentagekey)de_anaylsisH=dfPercentage.loc[(dfPercentage["Perentage"]>=lpHigh)]HCount=de_anaylsisH['Perentage'].count()de_anaylsisL=dfPercentage.loc[(dfPercentage["Perentage"]<=lpLow)]LCount=de_anaylsisL['Perentage'].count()percebtage=de_anaylsisH[de_anaylsisH["next2BarClose"]>0]["next2BarClose"].count()*100.000/HCountde_anaylsisHsum=de_anaylsisH["next2BarPercentage"].sum()de_anaylsisLsum=de_anaylsisL["next2BarPercentage"].sum()print('Precent大于%s,%s时候,k线数量为%s,第二根K线结束价格上涨概率为%s%%;'%(lpHigh,100-Perentagekey,HCount,percebtage))print('和值%s'%(de_anaylsisHsum))de_anaylsisL=dfPercentage.loc[(dfPercentage["Perentage"]<=lpLow)]percebtage=de_anaylsisL[de_anaylsisL["next2BarClose"]<0]["next2BarClose"].count()*100.000/LCountprint('Precent小于于%s,%s时候,k线数量为%s,第二根K线结束价格下跌概率为%s%%'%(lpLow,Perentagekey,LCount,percebtage))print('和值%s'%(de_anaylsisLsum))de_anaylsisHsum=de_anaylsisH["next4BarPercentage"].sum()de_anaylsisLsum=de_anaylsisL["next4BarPercentage"].sum()percebtage=de_anaylsisH[de_anaylsisH["next4BarClose"]>0]["next2BarClose"].count()*100.000/HCountprint('Precent大于%s,%s时候,第四根K线结束价格上涨概率为%s%%'%(lpHigh,100-Perentagekey,percebtage))#print('和值%s'%(de_anaylsisHsum))percebtage=de_anaylsisL[de_anaylsisL["next4BarClose"]<0]["next2BarClose"].count()*100.000/LCountprint('Precent小于于%s,%s时候,第四根K线结束价格下跌概率为%s%%'%(lpLow,Perentagekey,percebtage))print('和值%s'%(de_anaylsisLsum))de_anaylsisHsum=de_anaylsisH["next6BarPercentage"].sum()de_anaylsisLsum=de_anaylsisL["next6BarPercentage"].sum()percebtage=de_anaylsisH[de_anaylsisH["next6BarClose"]>0]["next2BarClose"].count()*100.000/HCountprint('Precent大于%s,%s时候,第六根K线结束价格上涨概率为%s%%'%(lpHigh,100-Perentagekey,percebtage))print('和值%s'%(de_anaylsisHsum))percebtage=de_anaylsisL[de_anaylsisL["next6BarClose"]<0]["next2BarClose"].count()*100.000/LCountprint('Precent小于于%s,%s时候,第六根K线结束价格下跌概率为%s%%'%(lpLow,Perentagekey,percebtage))print('和值%s'%(de_anaylsisLsum))if__name__=='__main__':DA=DataAnalyzer()#数据库导入start=datetime.strptime("20180901",'%Y%m%d')end=datetime.today()df=DA.db2df(db="VnTrader_1Min_Db",collection="m1905",start=start,end=end)#csv导入#df=DA.csv2df("rb1905.csv")df10min=DA.df2Barmin(df,10)dfPercentage=DA.Percentage(df10min)dfPercentage=DA.addResultBar(dfPercentage)PrecentAnalysis(dfPercentage)