def kfactor(source, signal=None): ''' 计算source中相邻信号的k因子 k因子指值差除以距离 返回的是浮点数 这里不设置interval参数,是因为如果interval>1,则有kfactor的交叠问题 如1-->3,2-->4,则1-->2用13的斜率,而2-4用24斜率,直觉无意义 ''' if len(source) == 0: return np.array([]) if signal == None: #对于数值正好为0的情况,需要signal signal = source else: assert len(source) == len(signal) rev = np.zeros(len(source), np.float) si = np.nonzero(signal)[0] if len(si) == 0: return rev ss = source[si] drev = nsubd(ss) * 1.0 / nsubd(si) rev[rollx(si)] = drev rev = extend2next(rev) #rev[si] = rev[si-1] #起点/转折点斜率为0 rev = np.select([signal != 0], [rollx(rev)], rev) return rev
def zpeaki(source,order=1,fpeak=fhigh): ''' 寻找n阶高/低点 返回值为高点数据序列,以及该高点最大跨度的坐标(即计算该高/低点所需用到的最远的未来数据的坐标) order默认为1,小于1当作1 返回值中第一个是高/低点非0,其余为0的序列 sh 第二个是该高低点的最远未来数据的坐标序列 si 其中 sh[np.nonzero(sh)]为高点序列, si[np.nonzero(sh)]为坐标序列,sif.time[si[np.nonzero(sh)]]为坐标的影响时间序列 ''' tsx1 = fpeak(source) sx1 = np.select([tsx1!=0],[source],0) icovered = rollx(np.arange(len(source)),-1) if order <= 1: return sx1,np.select([tsx1],[icovered],0) icursx = np.nonzero(tsx1)[0] for i in xrange(1,order): #必然进入循环 sxx = source[icursx] tsxx = fpeak(sxx) icovered[icursx] = rollx(icovered[icursx],-1) #当前高/低点的计算范围,即之前顶点的范围左转一位(排除掉不是顶点的) icursx = icursx[np.nonzero(tsxx)[0]] osx = np.zeros_like(source) osx[icursx] = source[icursx] iz = np.zeros_like(source) iz[icursx] = icovered[icursx] #去掉icovered之中不必要的那些数字 return osx,iz
def zpeaki(source, order=1, fpeak=fhigh): ''' 寻找n阶高/低点 返回值为高点数据序列,以及该高点最大跨度的坐标(即计算该高/低点所需用到的最远的未来数据的坐标) order默认为1,小于1当作1 返回值中第一个是高/低点非0,其余为0的序列 sh 第二个是该高低点的最远未来数据的坐标序列 si 其中 sh[np.nonzero(sh)]为高点序列, si[np.nonzero(sh)]为坐标序列,sif.time[si[np.nonzero(sh)]]为坐标的影响时间序列 ''' tsx1 = fpeak(source) sx1 = np.select([tsx1 != 0], [source], 0) icovered = rollx(np.arange(len(source)), -1) if order <= 1: return sx1, np.select([tsx1], [icovered], 0) icursx = np.nonzero(tsx1)[0] for i in xrange(1, order): #必然进入循环 sxx = source[icursx] tsxx = fpeak(sxx) icovered[icursx] = rollx(icovered[icursx], -1) #当前高/低点的计算范围,即之前顶点的范围左转一位(排除掉不是顶点的) icursx = icursx[np.nonzero(tsxx)[0]] osx = np.zeros_like(source) osx[icursx] = source[icursx] iz = np.zeros_like(source) iz[icursx] = icovered[icursx] #去掉icovered之中不必要的那些数字 return osx, iz
def kfactor(source,signal=None): ''' 计算source中相邻信号的k因子 k因子指值差除以距离 返回的是浮点数 这里不设置interval参数,是因为如果interval>1,则有kfactor的交叠问题 如1-->3,2-->4,则1-->2用13的斜率,而2-4用24斜率,直觉无意义 ''' if len(source)==0: return np.array([]) if signal == None: #对于数值正好为0的情况,需要signal signal = source else: assert len(source) == len(signal) rev = np.zeros(len(source),np.float) si = np.nonzero(signal)[0] if len(si) == 0: return rev ss = source[si] drev = nsubd(ss) * 1.0 / nsubd(si) rev[rollx(si)] = drev rev = extend2next(rev) #rev[si] = rev[si-1] #起点/转折点斜率为0 rev = np.select([signal!=0],[rollx(rev)],rev) return rev
def utr(sopen,sclose,shigh,slow): ''' 上升波幅 根据最高价-sopen和最高价-rollx(sclose)的大者 ''' sho = shigh - sopen shc = shigh - rollx(sclose) return gmax(sho,shc) #必然>=0
def supdown2(sopen, sclose, shigh, slow): ''' 计算每日的上升行程和下降行程 以距离开盘价距离近的方向为运行方向 则若最低近,运行轨迹为 开盘-->最低-->最高-->收盘 若最高近,运行轨迹为 开盘-->最高-->最低-->收盘 平开往低走 另,如果开盘大于昨日收盘,则上升段 + 开盘-昨收盘 小于昨日收盘,则下降段 + 昨收盘 - 开盘 ''' if len(sopen) == 0: return np.array([], int), np.array([], int) sc1 = rollx(sclose) sc1[0] = sopen[0] #前一日收盘价视同首日开盘价 u_hlc = shigh - sopen + sclose - slow u_lhc = shigh - slow d_hlc = shigh - slow d_lhc = sopen - slow + shigh - sclose ou = np.where(sopen > sc1) od = np.where(sopen < sc1) doc = sopen - sc1 u_hlc[ou] = u_hlc[ou] + doc[ou] u_lhc[ou] = u_lhc[ou] + doc[ou] d_hlc[od] = d_hlc[od] - doc[od] #doc[od]<0 d_lhc[od] = d_lhc[od] - doc[od] #doc[od]<0 is_up = shigh - sopen < sopen - slow #True为向上,False为向下 u = np.select([is_up], [u_hlc], default=u_lhc) d = np.select([is_up], [d_hlc], default=d_lhc) return u, d
def supdownc(sopen,sclose,shigh,slow): ''' 计算每日的上升力比例和下降力比例,考虑前一日的情况 基本上升力: high-open+close-low 基本下降力: open-low+high-close 基本单位: high - low 若open>=close(-1): 上升力 = 基本上升力 + open - close(-1) else: 下降力 = 基本下降力 - open + close(-1) 若low>close(-1): 单位 = 基本单位 + low - close(-1) 若high<close(-1): 单位 = 基本单位 + close(-1) - high ''' if len(sopen) == 0: return np.array([],int),np.array([],int) sc1 = rollx(sclose) sc1[0] = sopen[0] #哨兵,便于处理 ob = shigh - slow su,sd = xupdownc(sopen,sclose,shigh,slow) sb1 = np.where(slow>sc1,ob+slow-sc1,ob) sb = np.where(shigh<sc1,sb1+sc1-shigh,sb1) return su*BASE/sb,sd*BASE/sb
def supdown2(sopen,sclose,shigh,slow): ''' 计算每日的上升行程和下降行程 以距离开盘价距离近的方向为运行方向 则若最低近,运行轨迹为 开盘-->最低-->最高-->收盘 若最高近,运行轨迹为 开盘-->最高-->最低-->收盘 平开往低走 另,如果开盘大于昨日收盘,则上升段 + 开盘-昨收盘 小于昨日收盘,则下降段 + 昨收盘 - 开盘 ''' if len(sopen) == 0: return np.array([],int),np.array([],int) sc1 = rollx(sclose) sc1[0] = sopen[0] #前一日收盘价视同首日开盘价 u_hlc = shigh-sopen+sclose-slow u_lhc = shigh - slow d_hlc = shigh - slow d_lhc = sopen-slow+shigh-sclose ou = np.where(sopen > sc1) od = np.where(sopen < sc1) doc = sopen-sc1 u_hlc[ou] = u_hlc[ou] + doc[ou] u_lhc[ou] = u_lhc[ou] + doc[ou] d_hlc[od] = d_hlc[od] - doc[od] #doc[od]<0 d_lhc[od] = d_lhc[od] - doc[od] #doc[od]<0 is_up = shigh-sopen < sopen-slow #True为向上,False为向下 u = np.select([is_up],[u_hlc],default=u_lhc) d = np.select([is_up],[d_hlc],default=d_lhc) return u,d
def supdownc(sopen, sclose, shigh, slow): ''' 计算每日的上升力比例和下降力比例,考虑前一日的情况 基本上升力: high-open+close-low 基本下降力: open-low+high-close 基本单位: high - low 若open>=close(-1): 上升力 = 基本上升力 + open - close(-1) else: 下降力 = 基本下降力 - open + close(-1) 若low>close(-1): 单位 = 基本单位 + low - close(-1) 若high<close(-1): 单位 = 基本单位 + close(-1) - high ''' if len(sopen) == 0: return np.array([], int), np.array([], int) sc1 = rollx(sclose) sc1[0] = sopen[0] #哨兵,便于处理 ob = shigh - slow su, sd = xupdownc(sopen, sclose, shigh, slow) sb1 = np.where(slow > sc1, ob + slow - sc1, ob) sb = np.where(shigh < sc1, sb1 + sc1 - shigh, sb1) return su * BASE / sb, sd * BASE / sb
def utr(sopen, sclose, shigh, slow): ''' 上升波幅 根据最高价-sopen和最高价-rollx(sclose)的大者 ''' sho = shigh - sopen shc = shigh - rollx(sclose) return gmax(sho, shc) #必然>=0
def tr(sclose,shigh,slow): ''' 真实波幅 ''' sclose = rollx(sclose) shl = np.abs(shigh - slow) shc = np.abs(shigh - sclose) slc = np.abs(slow - sclose) return gmax(shl,shc,slc)
def dtr(sopen,sclose,shigh,slow): ''' 下跌波幅 根据sopen-最低价和rollx(sclose)-最低价的大者 ''' slo = sopen - slow slc = rollx(sclose) - slow return gmax(slo,slc) #必然>=0
def dtr(sopen, sclose, shigh, slow): ''' 下跌波幅 根据sopen-最低价和rollx(sclose)-最低价的大者 ''' slo = sopen - slow slc = rollx(sclose) - slow return gmax(slo, slc) #必然>=0
def tr(sclose, shigh, slow): ''' 真实波幅 ''' sclose = rollx(sclose) shl = np.abs(shigh - slow) shc = np.abs(shigh - sclose) slc = np.abs(slow - sclose) return gmax(shl, shc, slc)
def sroc(source,interval=1): ''' roc的np版本 ''' assert interval > 0 rc = rollx(source,interval) rev = (source - rc)*BASE*BASE / rc rev[:interval] = 0 return rev
def sroc(source, interval=1): ''' roc的np版本 ''' assert interval > 0 rc = rollx(source, interval) rev = (source - rc) * BASE * BASE / rc rev[:interval] = 0 return rev
def mfi(source, vol, length=13): ''' mfi指标 source = (close+high+low)/3 TYP := (HIGH + LOW + CLOSE)/3; V1=SUM(IF(TYP>REF(TYP,1),TYP*VOL,0),N)/SUM(IF(TYP<REF(TYP,1),TYP*VOL,0),N); MFI:100-(100/(1+V1)) 设定 PV = SUM(IF(TYP>REF(TYP,1),TYP*VOL,0),N) NV = SUM(IF(TYP<REF(TYP,1),TYP*VOL,0),N); 则MFI = 100PV/(PV+NV) ''' pvol = np.select([source > rollx(source)], [vol]) nvol = np.select([source < rollx(source)], [vol]) spv = msum(pvol, length) snv = msum(nvol, length) result = (BASE * spv + (spv + snv) / 2) / (spv + snv) #四舍五入 return result
def mm_ratio(sclose,shigh,slow,satr,covered=1): ''' 计算标准化的最大有利变动(MFE)/最大不利变动(MAE) 即以当日为基准,计算covered内AMFE=(最大值-当日值)/atr和(当日值-最小值)/atr 用于优势率e_ratio的计算: 所有信号的CMFE之和/所有信号的CMAE之和 (信号次数被约掉) 应当用这种方式,而不是单独计算CMFE/CMAE然后求平均 比如一次是2/1,另一次是1/2,如果单独求比例然后平均,则e_ratio=(2+0.5)/2=1.25 而先求平均再除,则是 (2+1)/(1+2) = 1 显然后者是正常情形 这是一个future函数, 正因为有左移的原因,所以最后covered的数据是失准的,需要处理掉,失灭为准 ''' m_max = rollx(tmax(sclose,covered),-covered) #未来数据左移 m_min = rollx(tmin(sclose,covered),-covered) #未来数据左移 #print m_min,tmin(sclose,covered) amfe = (m_max - sclose) * BASE / satr #可能出现m_max[i] < sclose[i]的情况,如当日之后的covered内sclose一直下行 amae = (sclose - m_min) * BASE / satr #可能出现m_min[i] > sclose[i]的情况,如当日之后的covered内sclose一直上行 amfe[-covered:] = amae[-covered:] = 0 #print amfe.tolist(),amae.tolist() return amfe,amae
def mfi(source,vol,length=13): ''' mfi指标 source = (close+high+low)/3 TYP := (HIGH + LOW + CLOSE)/3; V1=SUM(IF(TYP>REF(TYP,1),TYP*VOL,0),N)/SUM(IF(TYP<REF(TYP,1),TYP*VOL,0),N); MFI:100-(100/(1+V1)) 设定 PV = SUM(IF(TYP>REF(TYP,1),TYP*VOL,0),N) NV = SUM(IF(TYP<REF(TYP,1),TYP*VOL,0),N); 则MFI = 100PV/(PV+NV) ''' pvol = np.select([source>rollx(source)],[vol]) nvol = np.select([source<rollx(source)],[vol]) spv = msum(pvol,length) snv = msum(nvol,length) result = (BASE*spv+(spv+snv)/2)/(spv+snv) #四舍五入 return result
def xmaxmin_points(source,extends,functor,gfunctor,limit): ''' 计算最高或最低点,extends为作用范围. 返回值中前extends和后extends位都置0 ''' covered = extends * 2 + 1 #最大点必然大于之前的extends个元素和之后的extends个元素 if(len(source) < covered): return np.zeros_like(source) peak_values = tmaxmin(source,covered,functor,gfunctor,limit) xpeak_values = rollx(peak_values,-extends) cores = equals(source,xpeak_values) ncores = derepeatc(cores) ncores[:extends] = ncores[-extends:] = 0 return ncores
def xmaxmin_points(source, extends, functor, gfunctor, limit): ''' 计算最高或最低点,extends为作用范围. 返回值中前extends和后extends位都置0 ''' covered = extends * 2 + 1 #最大点必然大于之前的extends个元素和之后的extends个元素 if (len(source) < covered): return np.zeros_like(source) peak_values = tmaxmin(source, covered, functor, gfunctor, limit) xpeak_values = rollx(peak_values, -extends) cores = equals(source, xpeak_values) ncores = derepeatc(cores) ncores[:extends] = ncores[-extends:] = 0 return ncores
def temv(shigh, slow, sweight, length=14, BASE=100): #国内常用的emv方式 ''' BASE设定为100是考虑到mid的精度问题,同时又不至于溢出 VOLUME:=MA(VOL,N)/VOL; MID:=100*(HIGH+LOW-REF(HIGH+LOW,1))/(HIGH+LOW); EMV:MA(MID*VOLUME*(HIGH-LOW)/MA(HIGH-LOW,N),N); MAEMV:MA(EMV,M); ''' mvol = ma(sweight, length) * BASE / sweight ahl = shigh + slow jhl = shigh - slow mid = (ahl - rollx(ahl)) * BASE * BASE / ahl rev = ma(mid * mvol * jhl / ma(jhl, length), length) return rev
def rollx2(source,shift): #每行数据右移,移动部分补第一列. 二维版本(兼容一维) if source.ndim == 1: return d1.rollx(source,shift) assert source.ndim == 2 if len(source[0]) == 0: return source.copy() rev = np.roll(source,shift,axis=1) if shift > 0: rev[:,:shift] = source[:,0][:,np.newaxis] #化行为列,source[:,0]返回的是行,[:,np.newaxis]后变为二维 elif shift < 0: rlen = source.shape[1] begin = rlen + shift if rlen + shift >=0 else 0 rev[:,begin:] = source[:,-1][:,np.newaxis] #化行为列 return rev
def rsi2(source,length): ''' np方式的rsi算法 国内通用方式 ''' rev = np.zeros_like(source) ds = source - rollx(source) pds = np.select([ds>0],[ds],0) mpds = sma(pds,length,1) ms = sma(np.abs(ds),length,1) return mpds * BASE / ms
def rsi2(source, length): ''' np方式的rsi算法 国内通用方式 ''' rev = np.zeros_like(source) ds = source - rollx(source) pds = np.select([ds > 0], [ds], 0) mpds = sma(pds, length, 1) ms = sma(np.abs(ds), length, 1) return mpds * BASE / ms
def mm_ratio(sclose, shigh, slow, satr, covered=1): ''' 计算标准化的最大有利变动(MFE)/最大不利变动(MAE) 即以当日为基准,计算covered内AMFE=(最大值-当日值)/atr和(当日值-最小值)/atr 用于优势率e_ratio的计算: 所有信号的CMFE之和/所有信号的CMAE之和 (信号次数被约掉) 应当用这种方式,而不是单独计算CMFE/CMAE然后求平均 比如一次是2/1,另一次是1/2,如果单独求比例然后平均,则e_ratio=(2+0.5)/2=1.25 而先求平均再除,则是 (2+1)/(1+2) = 1 显然后者是正常情形 这是一个future函数, 正因为有左移的原因,所以最后covered的数据是失准的,需要处理掉,失灭为准 ''' m_max = rollx(tmax(sclose, covered), -covered) #未来数据左移 m_min = rollx(tmin(sclose, covered), -covered) #未来数据左移 #print m_min,tmin(sclose,covered) amfe = ( m_max - sclose ) * BASE / satr #可能出现m_max[i] < sclose[i]的情况,如当日之后的covered内sclose一直下行 amae = ( sclose - m_min ) * BASE / satr #可能出现m_min[i] > sclose[i]的情况,如当日之后的covered内sclose一直上行 amfe[-covered:] = amae[-covered:] = 0 #print amfe.tolist(),amae.tolist() return amfe, amae
def temv(shigh,slow,sweight,length=14,BASE=100):#国内常用的emv方式 ''' BASE设定为100是考虑到mid的精度问题,同时又不至于溢出 VOLUME:=MA(VOL,N)/VOL; MID:=100*(HIGH+LOW-REF(HIGH+LOW,1))/(HIGH+LOW); EMV:MA(MID*VOLUME*(HIGH-LOW)/MA(HIGH-LOW,N),N); MAEMV:MA(EMV,M); ''' mvol = ma(sweight,length) * BASE / sweight ahl = shigh + slow jhl = shigh - slow mid = (ahl-rollx(ahl))*BASE*BASE/ahl rev = ma(mid*mvol*jhl/ma(jhl,length),length) return rev
def devi(shigh, sdiff, regr=96): ''' 背离,是指shigh新高头部形成时,sdiff没有创相应周期的新高 shigh:高点序列 sdiff:macd的diff序列 regr:回撤比例 ''' xhigh = tmax(shigh, 7) xhighl = xhigh * regr / 100 xhighA = gand(shigh < xhighl, rollx(shigh, 6) < xhigh) xhigh60 = tmax(shigh, 60) xdiff7 = tmax(sdiff, 7) xdiff60 = tmax(sdiff, 60) xdev = gand(xhighA, xhigh == xhigh60, xdiff7 < xdiff60) return xdev
def devi(shigh,sdiff,regr=96): ''' 背离,是指shigh新高头部形成时,sdiff没有创相应周期的新高 shigh:高点序列 sdiff:macd的diff序列 regr:回撤比例 ''' xhigh = tmax(shigh,7) xhighl = xhigh * regr/100 xhighA = gand(shigh < xhighl,rollx(shigh,6)<xhigh) xhigh60 =tmax(shigh,60) xdiff7 = tmax(sdiff,7) xdiff60 = tmax(sdiff,60) xdev = gand(xhighA,xhigh == xhigh60,xdiff7<xdiff60) return xdev
def xupdowns(sopen,sclose,shigh,slow): ''' 计算每日的上升力和下降力,简版,不考虑前一日情况 物理含义: 能确定的必然经历的上升段,是从开盘到高点,以及从最低到收盘 下降段,是从开盘到低点,和从最高到收盘 上升力: high-open+close-low 下降力: open-low+high-close 单位: high - low ''' if len(sopen) == 0: return np.array([],int),np.array([],int) sc1 = rollx(sclose) su = shigh - sopen + sclose - slow sd = sopen - slow + shigh - sclose return su,sd
def xupdowns(sopen, sclose, shigh, slow): ''' 计算每日的上升力和下降力,简版,不考虑前一日情况 物理含义: 能确定的必然经历的上升段,是从开盘到高点,以及从最低到收盘 下降段,是从开盘到低点,和从最高到收盘 上升力: high-open+close-low 下降力: open-low+high-close 单位: high - low ''' if len(sopen) == 0: return np.array([], int), np.array([], int) sc1 = rollx(sclose) su = shigh - sopen + sclose - slow sd = sopen - slow + shigh - sclose return su, sd
def rollx2(source, shift): #每行数据右移,移动部分补第一列. 二维版本(兼容一维) if source.ndim == 1: return d1.rollx(source, shift) assert source.ndim == 2 if len(source[0]) == 0: return source.copy() rev = np.roll(source, shift, axis=1) if shift > 0: rev[:, : shift] = source[:, 0][:, np. newaxis] #化行为列,source[:,0]返回的是行,[:,np.newaxis]后变为二维 elif shift < 0: rlen = source.shape[1] begin = rlen + shift if rlen + shift >= 0 else 0 rev[:, begin:] = source[:, -1][:, np.newaxis] #化行为列 return rev
def xupdownc(sopen,sclose,shigh,slow): ''' 计算每日的上升力和下降力,考虑前一日的情况 基本上升力: high-open+close-low 基本下降力: open-low+high-close 若open>=close(-1): 上升力 = 基本上升力 + open - close(-1) else: 下降力 = 基本下降力 - open + close(-1) ''' if len(sopen) == 0: return np.array([],int),np.array([],int) sc1 = rollx(sclose) sc1[0] = sopen[0] #哨兵,便于处理 ou = shigh - sopen + sclose - slow od = sopen - slow + shigh - sclose ob = shigh - slow su = np.where(sopen>=sc1,ou+sopen-sc1,ou) sd = np.where(sopen<sc1,od-sopen+sc1,od) return su,sd
def xupdownc(sopen, sclose, shigh, slow): ''' 计算每日的上升力和下降力,考虑前一日的情况 基本上升力: high-open+close-low 基本下降力: open-low+high-close 若open>=close(-1): 上升力 = 基本上升力 + open - close(-1) else: 下降力 = 基本下降力 - open + close(-1) ''' if len(sopen) == 0: return np.array([], int), np.array([], int) sc1 = rollx(sclose) sc1[0] = sopen[0] #哨兵,便于处理 ou = shigh - sopen + sclose - slow od = sopen - slow + shigh - sclose ob = shigh - slow su = np.where(sopen >= sc1, ou + sopen - sc1, ou) sd = np.where(sopen < sc1, od - sopen + sc1, od) return su, sd
def supdown(sopen, sclose, shigh, slow): ''' 计算每日的上升行程和下降行程 以前一日收盘和今日开盘指向的方向为运行方向 则若指向下方,运行轨迹为 开盘-->最低-->最高-->收盘 若指向上方,运行轨迹为 开盘-->最高-->最低-->收盘 平开,则顺着昨天的指向收盘的方向,亦即昨日的开盘方向(每日收盘方向等于开盘方向) 但这个方式有个问题,按理说 跳高开盘高走,应当是买力强劲,而低开高走则相对弱势 但在本方式的Volume的分配上,反而是后者的比例高。 ''' if len(sopen) == 0: return np.array([], int), np.array([], int) sc1 = rollx(sclose) sc1[0] = sopen[0] #前一日收盘价视同首日开盘价 u_hlc = shigh - sc1 + sclose - slow u_lhc = shigh - slow d_hlc = shigh - slow d_lhc = sc1 - slow + shigh - sclose direct = np.sign(sopen - sc1) #1为向上,-1为向下,0为平 direct[0] = 1 direct = extend2next(direct) #把0都给填充掉,即用昨日指向收盘的方向作为今日的方向 u = np.select([direct > 0, direct < 0], [u_hlc, u_lhc]) d = np.select([direct > 0, direct < 0], [d_hlc, d_lhc]) return u, d
def gtrend1(shigh, slow): ''' 江恩1周期趋势线 #返回trend线,top,bottom线 返回trend线,使用时可用strend2来判断当前趋势,当up时当前点为高点,down时为低点 如果要找到高点之前的地点,可以用strend2作为选择,找到这些点,然后extend2next 如: t1=strend2(gtrend) thigh = np.select([t1>0],[gtrend]) thigh = extend2next(thigh) 如此就取到了高点序列,同理可得到低点序列 一日摆动由江恩定义. 1日转向图. 上升日(Up down:UD): 高点高,低点高 下降日(Down day:DD): 高点低,低点低 外延日(Outside day,OD):高点高,低点低 内移日(Inside day:ID):高点低,低点高 上升日则趋势线移动到高点,下降日则趋势线移动到低点 上升趋势中的外延日,如果先高后低,则移动到低点,否则移动到高点,#这里简单起见,都算延续趋势 下降趋势中的外延日,如果先低后高,则移动到高点,否则移动到高点,#这里简单起见,都算延续趋势 忽略内移日 top:上行中的高点,或转为下行前的上一个高点 bottom: 下行中的低点,或转为上行前的上一个低点 ''' dup = gand(shigh > rollx(shigh), slow > rollx(slow)) ddown = gand(shigh < rollx(shigh), slow < rollx(slow)) dexpand = gand(shigh > rollx(shigh), slow < rollx(slow)) #dinside = gand(shigh<rollx(shigh),slow>rollx(slow)) #忽略 #先不计扩张日,得到原始趋势 st = np.select([dup, ddown], [shigh, slow], 0) st = extend2next(st) t1 = strend2(st) st2 = np.select( [dup, gand(dexpand, t1 > 0), ddown, gand(dexpand, t1 < 0)], [shigh, shigh, slow, slow]) #st_top = np.select([dup,gand(dexpand,t1>0)],[shigh,shigh]) #st_bottom = np.select([ddown,gand(dexpand,t1<0)],[slow,slow]) st2 = extend2next(st2) #st_top = extend2next(st_top) #st_bottom = extend2next(st_bottom) return st2 #,st_top,st_bottom
def supdown(sopen,sclose,shigh,slow): ''' 计算每日的上升行程和下降行程 以前一日收盘和今日开盘指向的方向为运行方向 则若指向下方,运行轨迹为 开盘-->最低-->最高-->收盘 若指向上方,运行轨迹为 开盘-->最高-->最低-->收盘 平开,则顺着昨天的指向收盘的方向,亦即昨日的开盘方向(每日收盘方向等于开盘方向) 但这个方式有个问题,按理说 跳高开盘高走,应当是买力强劲,而低开高走则相对弱势 但在本方式的Volume的分配上,反而是后者的比例高。 ''' if len(sopen) == 0: return np.array([],int),np.array([],int) sc1 = rollx(sclose) sc1[0] = sopen[0] #前一日收盘价视同首日开盘价 u_hlc = shigh-sc1+sclose-slow u_lhc = shigh - slow d_hlc = shigh - slow d_lhc = sc1-slow+shigh-sclose direct = np.sign(sopen-sc1) #1为向上,-1为向下,0为平 direct[0] = 1 direct = extend2next(direct) #把0都给填充掉,即用昨日指向收盘的方向作为今日的方向 u = np.select([direct>0,direct<0],[u_hlc,u_lhc]) d = np.select([direct>0,direct<0],[d_hlc,d_lhc]) return u,d
def gtrend1(shigh,slow): ''' 江恩1周期趋势线 #返回trend线,top,bottom线 返回trend线,使用时可用strend2来判断当前趋势,当up时当前点为高点,down时为低点 如果要找到高点之前的地点,可以用strend2作为选择,找到这些点,然后extend2next 如: t1=strend2(gtrend) thigh = np.select([t1>0],[gtrend]) thigh = extend2next(thigh) 如此就取到了高点序列,同理可得到低点序列 一日摆动由江恩定义. 1日转向图. 上升日(Up down:UD): 高点高,低点高 下降日(Down day:DD): 高点低,低点低 外延日(Outside day,OD):高点高,低点低 内移日(Inside day:ID):高点低,低点高 上升日则趋势线移动到高点,下降日则趋势线移动到低点 上升趋势中的外延日,如果先高后低,则移动到低点,否则移动到高点,#这里简单起见,都算延续趋势 下降趋势中的外延日,如果先低后高,则移动到高点,否则移动到高点,#这里简单起见,都算延续趋势 忽略内移日 top:上行中的高点,或转为下行前的上一个高点 bottom: 下行中的低点,或转为上行前的上一个低点 ''' dup = gand(shigh>rollx(shigh),slow>rollx(slow)) ddown = gand(shigh<rollx(shigh),slow<rollx(slow)) dexpand = gand(shigh>rollx(shigh),slow<rollx(slow)) #dinside = gand(shigh<rollx(shigh),slow>rollx(slow)) #忽略 #先不计扩张日,得到原始趋势 st = np.select([dup,ddown],[shigh,slow],0) st = extend2next(st) t1 = strend2(st) st2 = np.select([dup,gand(dexpand,t1>0),ddown,gand(dexpand,t1<0)],[shigh,shigh,slow,slow]) #st_top = np.select([dup,gand(dexpand,t1>0)],[shigh,shigh]) #st_bottom = np.select([ddown,gand(dexpand,t1<0)],[slow,slow]) st2 = extend2next(st2) #st_top = extend2next(st_top) #st_bottom = extend2next(st_bottom) return st2 #,st_top,st_bottom
def limitup2(high, low, limit=990): #一字涨停,以万分之表示,不再依赖limit,认为上涨一线就是停 #return band(high-low==0,limitup1(high,limit)) pre = rollx(high, 1) return band(high - low == 0, pre < high)
def limitdown1(source, limit=-990): #跌停板,以万分之表示 pre = rollx(source, 1) return np.sign(source * LIMIT_BASE / pre <= limit + LIMIT_BASE)
def limitdown2(high,low,limit=-990): #一字跌停,以万分之表示 pre = rollx(high,1) return band(high-low==0,pre>high)
def limitdown2(high, low, limit=-990): #一字跌停,以万分之表示 pre = rollx(high, 1) return band(high - low == 0, pre > high)
def opendayofweek(weekdays): #周开盘日 #特定情形下会不正确,如某周一交易日后,下一个交易日正好是下周二,则该周二不会被识别为周开盘日. 好在错误对称。 #另,第一个交易日也被识别为周开盘日 return greater(lesser_equals(weekdays-rollx(weekdays)) + equals(weekdays,1))
def svap2_ma(svolume, sprice, malength, weight=5): ''' 依赖svolume为整数序列,否则导致ma之后0值有非零的base,直接导致后续所有计算出错 weight为权数,unit单位ma再除以weight. unit的粒度越细,一致性越好 ''' return svap2(svolume, sprice, rollx(ma(svolume, malength) / weight))
def score2(sprice, svolume): si = subd(sprice) * BASE / rollx(sprice) fprice = np.select([si > 5, si < -5], [1, -1], default=0) fvolume = np.choose(subd(svolume) > 0, [1, 2]) return fprice * fvolume
def psy(source,length=12): ''' 心理线PSY:COUNT(CLOSE>REF(CLOSE,1),N)/N*100 ''' s = greater(source,rollx(source)) rev = (msum(s,length) * BASE + length/2)/ length return rev
def opendayofweek(weekdays): #周开盘日 #特定情形下会不正确,如某周一交易日后,下一个交易日正好是下周二,则该周二不会被识别为周开盘日. 好在错误对称。 #另,第一个交易日也被识别为周开盘日 return greater( lesser_equals(weekdays - rollx(weekdays)) + equals(weekdays, 1))
for i in xrange(1, len(source)): cur_v = source[i] if cur_v > pre_v: cur = cur + 1 if cur > 0 else 1 elif cur_v < pre_v: cur = cur - 1 if cur < 0 else -1 else: #curv == pre_v cur = cur + 1 if cur >= 0 else cur - 1 #最初为0时,也算上升 rev[i] = cur pre_v = cur_v return rev #趋势的翻转次数 rturn = lambda sx: sum( gor(gand(rollx(sx) > 0, sx < 0), gand(rollx(sx) < 0, sx > 0))) def cross(target, follow): ''' 交叉计算: target: 参照系,follow: 追击者 状态: 1 Follow上叉Target 0 无交叉状态 -1 Follow下叉 粘合一次后按趋势发散仍然算叉,即追击--追平--超越也算,但追击--追平--平--....--超越不算 这里不保证Target在上叉(下叉)时的趋势是向上(向下)的 ''' assert len(target) == len(follow) if (len(target) == 0): return target.copy() s = np.sign(follow - target)
def limitup1(source, limit=990): #涨停板,以万分之表示 pre = rollx(source, 1) return np.sign(source * LIMIT_BASE / pre >= limit + LIMIT_BASE)
def score2(sprice,svolume): si = subd(sprice) * BASE / rollx(sprice) fprice = np.select([si>5,si<-5],[1,-1],default=0) fvolume = np.choose(subd(svolume) > 0,[1,2]) return fprice * fvolume
pre_v = source[0] cur = 0 for i in xrange(1,len(source)): cur_v = source[i] if cur_v > pre_v: cur = cur + 1 if cur > 0 else 1 elif cur_v < pre_v: cur = cur - 1 if cur < 0 else -1 else: #curv == pre_v cur = cur + 1 if cur >= 0 else cur-1 #最初为0时,也算上升 rev[i] = cur pre_v = cur_v return rev #趋势的翻转次数 rturn = lambda sx:sum(gor(gand(rollx(sx)>0,sx<0),gand(rollx(sx)<0,sx>0))) def cross(target,follow): ''' 交叉计算: target: 参照系,follow: 追击者 状态: 1 Follow上叉Target 0 无交叉状态 -1 Follow下叉 粘合一次后按趋势发散仍然算叉,即追击--追平--超越也算,但追击--追平--平--....--超越不算 这里不保证Target在上叉(下叉)时的趋势是向上(向下)的 ''' assert len(target) == len(follow) if(len(target) == 0): return target.copy() s = np.sign(follow - target)
def limitup1(source,limit=990): #涨停板,以万分之表示 pre = rollx(source,1) return np.sign(source * LIMIT_BASE / pre >= limit + LIMIT_BASE)
def closedayofweek(weekdays): #周收盘日 #特别特殊的情形下会不正确,如某周一交易日后,下一个交易日正好是下周二,则该周一不会被识别为周收盘日 #另,最后一个交易日也被识别为周收盘日 return greater(greater_equals(weekdays-rollx(weekdays,-1)) + equals(weekdays,5))
def limitdown1(source,limit=-990): #跌停板,以万分之表示 pre = rollx(source,1) return np.sign(source * LIMIT_BASE / pre <= limit+LIMIT_BASE)
def psy(source, length=12): ''' 心理线PSY:COUNT(CLOSE>REF(CLOSE,1),N)/N*100 ''' s = greater(source, rollx(source)) rev = (msum(s, length) * BASE + length / 2) / length return rev
def limitup2(high,low,limit=990): #一字涨停,以万分之表示,不再依赖limit,认为上涨一线就是停 #return band(high-low==0,limitup1(high,limit)) pre = rollx(high,1) return band(high-low==0,pre<high)
def closedayofweek(weekdays): #周收盘日 #特别特殊的情形下会不正确,如某周一交易日后,下一个交易日正好是下周二,则该周一不会被识别为周收盘日 #另,最后一个交易日也被识别为周收盘日 return greater( greater_equals(weekdays - rollx(weekdays, -1)) + equals(weekdays, 5))
def svap2_ma(svolume,sprice,malength,weight=5): ''' 依赖svolume为整数序列,否则导致ma之后0值有非零的base,直接导致后续所有计算出错 weight为权数,unit单位ma再除以weight. unit的粒度越细,一致性越好 ''' return svap2(svolume,sprice,rollx(ma(svolume,malength)/weight))