def build(df_dr): #合并 相关变量 group_no_last = 0 #最后的组号 group_master_n_last = 0 #最后的组长 ingroup_n_last = 0 #最后一个在组内的n group_first_n = 0 #最后一个组的第一个n chan_low_pre = None #chan_是指合并后的k的高低 chan_high_pre = None df_dr['updown']= '' #K线是向上up 向下down 平flat df_dr['group']= '' #是否在组内 df_dr['group_no']= '' #组的编号 df_dr['group_high']= '' #组的最高值 df_dr['group_low']= '' #组的最低值 df_dr['group_master']= '' #是否是组长 #分型 相关变量 fx_n_maybe_pre = 0 #前面可能是分型的n,如果有方向则临时记录 fx_direction_pre = "flat" #平均值的方向 fx_high_direction_pre = "flat" #高点的方向 fx_low_direction_pre = "flat" #低点的方向 fx_chan_low_pre = None #chan_是指合并后的k的高低 fx_chan_high_pre = None df_dr['fx']='' #分型的类型,底bottom 顶top #笔 相关变量 fx_n_pre = None node_n_pre = None #node是前面确认的笔的节点 node_type_pre ='' node_high_pre = None node_low_pre = None df_dr['bi']='' #笔的类型,底bottom 顶top bi_count=0 bi_first_n=0 #第一个笔的n bi_second_n=0 #第二个笔的n bi_third_n=0 #第三个笔的n #线段相关变量 dot_n_pre = None #dot是前面确认的线段的节点 dot_bi_count_pre = None #前一个dot是第几个笔 dot_next_bi_n_pre = None #前一个dot的后一笔的n 用于判断新线段反弹 dot_type_pre ='' dot_high_pre = None dot_low_pre = None df_dr['line']='' #线段的类型,底bottom 顶top #中枢相关变量 zs_no=0 #最后一个中枢号 zs_first_n_pre=0 #未结束的中枢的开始n zs_end_n_pre=0 #前面已结束的中枢的结束n zg=0 zd=0 gg=0 dd=0 start_direction='' df_dr['zs_no']=0 df_dr['zg']=0 df_dr['zd']=0 df_dr['gg']=0 df_dr['dd']=0 df_dr['zs_direction']='' df_dr['zs_confirm_time']='' df_dr['zs_confirm_price']='' #逐笔循环 for n, k in df_dr.iterrows(): if n%10000==0: print('开始处理:',n,'/',len(df_dr)) open = k.open close = k.close low = k.low high = k.high ###一、合并 ############################################################################# updown='flat' #升降 is_group=False #是否在组里 is_group_master=False #是否组长,组长是最高的 group_no=0 group_high=0 group_low=0 is_confirm_v_group = False #确定虚拟组(包括单个不成组的K),即前面的K跟这个肯定不同组,那么前面的虚拟组确认 is_confirm_v_group_n = 0 #已确定虚拟组的组长(单个K就是这个K) if(chan_low_pre==None or chan_high_pre==None): chan_low_pre = low chan_high_pre = high else: #上一个原始K k_pre = df_dr.iloc[n-1-1] low_pre = k_pre.low high_pre = k_pre.high is_group_pre = k_pre.group #上升下降 #上升(跟原始K比较平均高度) if high_pre+low_pre < high+low: updown='up' #下降(跟原始K比较平均高度) elif high_pre+low_pre > high+low: updown='down' elif open=low) or (chan_high_pre>=high and chan_low_pre<=low)) and not (n>group_first_n+2 and ingroup_n_last==n-1): #上一个本来在组内,这个合并到原来的组 if ingroup_n_last==n-1: group_no=group_no_last #新组 else: group_no=group_no_last+1 group_first_n=n-1 group_no_last=group_no #组长 if chan_high_pre<=high and chan_low_pre>=low: is_group_master = True group_master_n_last=n elif chan_high_pre>=high and chan_low_pre<=low and ingroup_n_last!=n-1: #新组并且前面的高,需要设置前面的是组长 df_dr.at[n-1,'group_master']= True group_master_n_last=n-1 group_high=max(high, chan_high_pre) group_low=min(low, chan_low_pre) chan_high_pre = group_high chan_low_pre = group_low is_group=True ingroup_n_last=n else: #不包含 chan_low_pre = low chan_high_pre = high is_confirm_v_group = True #这个与前面没有包含关系,则前面的确认 is_confirm_v_group_n = group_master_n_last if is_group_pre else n-1 #写标识值到表中 df_dr.at[n,'updown']= updown df_dr.at[n,'group']= is_group df_dr.at[n,'group_no']= group_no df_dr.at[n,'group_high']= group_high df_dr.at[n,'group_low']= group_low df_dr.at[n,'group_master']= is_group_master if is_group: df_dr.at[n-1,'group']= is_group df_dr.at[n-1,'group_no']= group_no #刷新同组内的group_high and group_low for j in range(group_first_n, n): df_dr.at[j,'group_high']= group_high df_dr.at[j,'group_low']= group_low if is_group_master: df_dr.at[j,'group_master']= False #踢掉原来的组长 ###二、分型 ############################################################################# ## 分型需要出现的k线或者组明确,如果不确认是否被分组或者分组未结束即不确认组长的,需要等确认后再确认分型 is_confirm_fx = False #确定分型,前一个组或者个体是分型,为顶分型 is_confirm_fx_n = 0 #已确定分型的分型顶点 fx_type = '' fx_direction = "flat" #平均值的方向 fx_high_direction = "flat" #高点的方向 fx_low_direction = "flat" #低点的方向 if is_confirm_v_group: last_group_high=df_dr.at[is_confirm_v_group_n,'high'] last_group_low=df_dr.at[is_confirm_v_group_n,'low'] if(fx_chan_low_pre==None or fx_chan_high_pre==None): fx_chan_low_pre=last_group_low fx_chan_high_pre=last_group_high else: #与前面的比较 if fx_chan_high_pre+fx_chan_low_prelast_group_high+last_group_low: fx_direction='down' if last_group_high>fx_chan_high_pre: fx_high_direction='up' elif last_group_highfx_chan_low_pre: fx_low_direction='up' elif last_group_lownode_high_pre)): df_dr.at[node_n_pre,'bi']= '' is_confirm_bi=True is_bi_extend=True #与前节点类型不同,且超过3个差,是新笔 elif node_type_pre!=fx_type and is_confirm_fx_n-node_n_pre>3: if (fx_type=='bottom' and last_fx_lownode_low_pre): #顶底不能高低反 is_confirm_bi=True bi_count+=1 fx_n_pre=is_confirm_fx_n if is_confirm_bi: node_n_pre=is_confirm_fx_n node_type_pre=fx_type node_high_pre=last_fx_high node_low_pre=last_fx_low is_confirm_bi_n=is_confirm_fx_n df_dr.at[is_confirm_bi_n,'bi']= fx_type if bi_count==1: bi_first_n=is_confirm_bi_n elif bi_count==2: bi_second_n=is_confirm_bi_n elif bi_count==3: bi_third_n=is_confirm_bi_n ###三、线段 ############################################################################# ### is_confirm_line=False is_extend_line=False if is_confirm_bi: last_bi_type=df_dr.at[is_confirm_bi_n,'bi'] last_bi_high=df_dr.at[is_confirm_bi_n,'high'] last_bi_low=df_dr.at[is_confirm_bi_n,'low'] #如果上一个笔确认了线段,那么需要记录相邻的下一个笔,用于判断反弹的新线段(是否超越这个笔) if dot_bi_count_pre!=None and dot_bi_count_pre+1==bi_count: dot_next_bi_n_pre=is_confirm_bi_n #找第一个线段,第一个形成走势的三+笔(如果上升,第三+笔的结束点高于第一笔的结束点) if dot_n_pre==None and bi_count>3: bi_first2second_direction='up' if df_dr.at[bi_second_n,'bi']=='top' else 'down' bi_second_high=df_dr.at[bi_second_n,'high'] bi_second_low=df_dr.at[bi_second_n,'low'] bi_third_high=df_dr.at[bi_third_n,'high'] bi_third_low=df_dr.at[bi_third_n,'low'] if last_bi_type=='top' and last_bi_high>bi_second_high and bi_first2second_direction=='up': #上升突破第二个笔节点 df_dr.at[bi_first_n,'line']='bottom' df_dr.at[is_confirm_bi_n,'line']='top' dot_n_pre=is_confirm_bi_n dot_type_pre='top' dot_bi_count_pre=bi_count is_confirm_line=True elif last_bi_type=='bottom' and last_bi_lowbi_third_high and bi_first2second_direction=='down': #上升突破第三个笔节点 df_dr.at[bi_second_n,'line']='bottom' df_dr.at[is_confirm_bi_n,'line']='top' dot_n_pre=is_confirm_bi_n dot_type_pre='top' dot_bi_count_pre=bi_count is_confirm_line=True elif last_bi_type=='bottom' and last_bi_lowdot_high_pre: #看是否突破延申 df_dr.at[dot_n_pre,'line']='' df_dr.at[is_confirm_bi_n,'line']='top' dot_n_pre=is_confirm_bi_n dot_type_pre='top' dot_bi_count_pre=bi_count is_confirm_line=True is_extend_line=True elif last_bi_type=='bottom' and bi_count>dot_bi_count_pre+2 : #没有延申,反弹形成新的线段 df_dr.at[is_confirm_bi_n,'line']='bottom' dot_n_pre=is_confirm_bi_n dot_type_pre='bottom' dot_bi_count_pre=bi_count is_confirm_line=True elif dot_type_pre=='bottom': dot_high_pre=df_dr.at[dot_n_pre,'high'] dot_low_pre=df_dr.at[dot_n_pre,'low'] if last_bi_type=='bottom' and last_bi_lowdot_bi_count_pre+2 : #没有延申,反弹形成新的线段 df_dr.at[is_confirm_bi_n,'line']='top' dot_n_pre=is_confirm_bi_n dot_type_pre='top' dot_bi_count_pre=bi_count is_confirm_line=True #修正线段中间的凹凸漏点,例如上升的线段中有笔的低点低于线段的开始点,需要将这个线段的开始点移到这个更低的点,反之亦然 #有时候突然下来一笔,但是不成线段就会遗漏,此处待验证合理性 if is_confirm_line: df_dr_line=df_dr[df_dr.line!=''] last_line_n = dot_n_pre last2_line_n = df_dr_line.index[-2] last2_line_high = df_dr_line.iloc[-2].high last2_line_low = df_dr_line.iloc[-2].low last2_line_type = df_dr_line.iloc[-2].line df_mod = df_dr.loc[last2_line_n:last_line_n][df_dr.bi!=''] mod_i=0 modified_n_pre=None for mod_n, mod_k in df_mod.iterrows(): mod_high=mod_k.high mod_low=mod_k.low mod_line_type = df_mod.at[mod_n,'line'] if mod_line_type=='': #移动不能使与后面小于三比差,即后面一个如果是线段点,就不处理这个笔点了 if mod_i>len(df_mod)-4: break #移动 if last2_line_type=='top' and mod_high>last2_line_high: df_dr.at[last2_line_n,'line']='' if modified_n_pre!=None: df_dr.at[modified_n_pre,'line']='' df_dr.at[mod_n,'line']='top' modified_n_pre=mod_n elif last2_line_type=='bottom' and mod_lowzs_first_n_pre: dot_last_n=df_dr_line.index[-1] #最后一个线段dot dot_last_type=df_dr_line.at[dot_last_n,'line'] dot_last_high=df_dr_line.at[dot_last_n,'high'] dot_last_low=df_dr_line.at[dot_last_n,'low'] if (dot_last_type=='top' and dot_last_high>zd) or (dot_last_type=='bottom' and dot_last_low=6 and zs_first_n_pre<=zs_end_n_pre: dot1_k_n=df_dr_line.index[-6] #可能的前导头 dot2_k_n=df_dr_line.index[-5] #可能的中枢第一个点 dot3_k_n=df_dr_line.index[-4] dot4_k_n=df_dr_line.index[-3] dot5_k_n=df_dr_line.index[-2] dot6_k_n=df_dr_line.index[-1] #最后一个线段dot dot1_high=df_dr_line.at[dot1_k_n,'high'] dot2_high=df_dr_line.at[dot2_k_n,'high'] dot3_high=df_dr_line.at[dot3_k_n,'high'] dot4_high=df_dr_line.at[dot4_k_n,'high'] dot5_high=df_dr_line.at[dot5_k_n,'high'] dot6_high=df_dr_line.at[dot6_k_n,'high'] dot1_low=df_dr_line.at[dot1_k_n,'low'] dot2_low=df_dr_line.at[dot2_k_n,'low'] dot3_low=df_dr_line.at[dot3_k_n,'low'] dot4_low=df_dr_line.at[dot4_k_n,'low'] dot5_low=df_dr_line.at[dot5_k_n,'low'] dot6_low=df_dr_line.at[dot6_k_n,'low'] if(dot1_k_n>=zs_end_n_pre): #往前找三个点,如果不在中枢里,则判断是否是中枢的头部 start_direction='down' if df_dr_line.at[dot1_k_n,'line']=='top' else 'up' #前导点是top则是下降方向 if start_direction=='down': if min(dot3_high,dot5_high)>max(dot2_low,dot4_low) and dot1_high>max(dot3_high,dot5_high) and dot6_high=zs_first_n_pre) & (df_dr.index<=dot5_k_n) & (df_dr.line!=''),'zs_no']=zs_no df_dr.at[(df_dr.index>=zs_first_n_pre) & (df_dr.index<=dot5_k_n) & (df_dr.line!=''),'zg']=zg df_dr.at[(df_dr.index>=zs_first_n_pre) & (df_dr.index<=dot5_k_n) & (df_dr.line!=''),'zd']=zd #print('新中枢确立',zd,zg,zs_first_n_pre) elif start_direction=='up': if min(dot2_high,dot4_high)>max(dot3_low,dot5_low) and dot1_lowmax(dot3_low,dot5_low): zs_first_n_pre=dot2_k_n #dot1是前导点,这个点是中枢第一个点 zg=min(dot2_high,dot4_high) zd=max(dot3_low,dot5_low) gg=max(dot2_high,dot4_high) dd=min(dot3_low,dot5_low) zs_no+=1 df_dr.at[(df_dr.index>=zs_first_n_pre) & (df_dr.index<=dot5_k_n) & (df_dr.line!=''),'zs_no']=zs_no df_dr.at[(df_dr.index>=zs_first_n_pre) & (df_dr.index<=dot5_k_n) & (df_dr.line!=''),'zg']=zg df_dr.at[(df_dr.index>=zs_first_n_pre) & (df_dr.index<=dot5_k_n) & (df_dr.line!=''),'zd']=zd #print('新中枢确立',zd,zg,zs_first_n_pre) #在中枢里则看是否生长 elif len(df_dr_line)>5 and zs_first_n_pre>zs_end_n_pre: dot_last_n=df_dr_line.index[-1] #最后一个线段dot dot_last_type=df_dr_line.at[dot_last_n,'line'] dot_last_high=df_dr_line.at[dot_last_n,'high'] dot_last_low=df_dr_line.at[dot_last_n,'low'] dot_last3_n=df_dr_line.index[-3] #倒数第三个线段dot dot_last3_type=df_dr_line.at[dot_last3_n,'line'] dot_last3_high=df_dr_line.at[dot_last3_n,'high'] dot_last3_low=df_dr_line.at[dot_last3_n,'low'] #刷新gg dd,只算到倒数第三个,确认中枢时正好为中枢结束点 if dot_last3_type=='top': gg=max(gg,dot_last3_high) elif dot_last3_type=='bottom': dd=min(dd,dot_last3_low) dot_last_trade_time=df_dr_line.at[dot_last_n,'trade_time'] dot_last_close=df_dr_line.at[dot_last_n,'close'] if (dot_last_type=='top' and dot_last_highzg): #中枢完成(这时肯定已经两个点脱离,没有走回去),保存,退出,往后面继续找 # /\ ------------- # / or ------------- # ------------- \ # ------------- \/ #print('中枢完成',zg,zd,df_dr_line.index[-3]) is_confirm_zs=True zs_end_n_pre=df_dr_line.index[-3] #中枢结束点是倒数第三个dot,结束点不是后导点,而开始点是前导点,计算时前后衔接方便 end_direction='down' if dot_last_type=='top' else 'up' #小尾巴是top则是下降方向 df_dr.at[(df_dr.index>=zs_first_n_pre) & (df_dr.index<=zs_end_n_pre) & (df_dr.line!=''),'zs_no']=zs_no df_dr.at[(df_dr.index>=zs_first_n_pre) & (df_dr.index<=zs_end_n_pre) & (df_dr.line!=''),'zg']=zg df_dr.at[(df_dr.index>=zs_first_n_pre) & (df_dr.index<=zs_end_n_pre) & (df_dr.line!=''),'zd']=zd df_dr.at[(df_dr.index>=zs_first_n_pre) & (df_dr.index<=zs_end_n_pre) & (df_dr.line!=''),'gg']=gg df_dr.at[(df_dr.index>=zs_first_n_pre) & (df_dr.index<=zs_end_n_pre) & (df_dr.line!=''),'dd']=dd df_dr.at[(df_dr.index>=zs_first_n_pre) & (df_dr.index<=zs_end_n_pre) & (df_dr.line!=''),'zs_direction']=start_direction+end_direction df_dr.at[(df_dr.index>=zs_first_n_pre) & (df_dr.index<=zs_end_n_pre) & (df_dr.line!=''),'zs_confirm_time']=dot_last_trade_time df_dr.at[(df_dr.index>=zs_first_n_pre) & (df_dr.index<=zs_end_n_pre) & (df_dr.line!=''),'zs_confirm_price']=dot_last_close return df_dr