def calc(self,sdata,dates,tbegin,evthreshold,**kwargs): buy_func = fcustom(self.buy_func,**kwargs) sell_func = fcustom(self.sell_func,**kwargs) m = Mediator(buy_func,sell_func) name = m.name() trades = m.calc_matched(sdata,dates,begin=tbegin) ev = self.evaluate_func(trades,self.datemap,**kwargs) if(not evthreshold(ev)): ev.matchedtrades,ev.balances = [],[] #相当于先删除。为保证ev的一致性而都赋为[]。否则str(ev)中的zip(...)会出错 #self.ev_result[name] = ev #移入到jduge中,因为可能值不是ev #print 'null list:',get_null_obj_number(list),',null tuple:',get_null_obj_number(tuple) return name,ev
def calc(self, sdata, dates, tbegin, evthreshold, **kwargs): buy_func = fcustom(self.buy_func, **kwargs) sell_func = fcustom(self.sell_func, **kwargs) m = Mediator(buy_func, sell_func) name = m.name() trades = m.calc_matched(sdata, dates, begin=tbegin) ev = self.evaluate_func(trades, self.datemap, **kwargs) if (not evthreshold(ev)): ev.matchedtrades, ev.balances = [], [ ] #相当于先删除。为保证ev的一致性而都赋为[]。否则str(ev)中的zip(...)会出错 #self.ev_result[name] = ev #移入到jduge中,因为可能值不是ev #print 'null list:',get_null_obj_number(list),',null tuple:',get_null_obj_number(tuple) return name, ev
def nmediator_factory(trade_signal_maker=make_trade_signal_advanced, trade_strategy=B1S0, pricer=cl_pricer): return fcustom(NMediator, trade_signal_maker=trade_signal_maker, trade_strategy=trade_strategy, pricer=pricer)
def __init__(self,buy_signal_maker,sell_signal_maker ,taxrate=125 ,trade_signal_maker=make_trade_signal ,matcher = match_trades ,trade_strategy=B1S1 ,pricer = default_pricer,extra_func=atr_extra): self.buy_signal_maker = buy_signal_maker self.sell_signal_maker = sell_signal_maker self.trade_signal_maker = trade_signal_maker self.matcher = matcher self.trade_strategy = trade_strategy self.buy_pricer = pricer[0] self.sell_pricer = pricer[1] self.extra_func = extra_func self.taxrate = taxrate self.make_trades = fcustom(make_trades,taxrate=taxrate,extra_func=extra_func) self.last_trade = fcustom(last_trade,taxrate=taxrate,extra_func=extra_func)
def atr_seller_factory(stop_times=3 * BASE / 2, trace_times=2 * BASE, covered=10, up_sector=HIGH): return fcustom(atr_seller, stop_times=stop_times, trace_times=trace_times, covered=covered, up_sector=up_sector)
def limit_adjust_deprecated( source_signal, limit_signal, trans_signal, covered=10 ): # covered不能大于127否则会溢出, np.sign(bool array)返回的是int8数组 """ 根据停板信号limit_signal和交易日信号trans_signal调整原始信号,使原始信号避开停板到开板日 可能因covered的原因导致连续非停板日中间出现停板日后,信号多发. 但这个可由makke_trade之类的函数处理掉 只有covered=2时,不会出现这个情况 covered=10,最多10个停板,超过则可能导致跌停情况下卖出信号被忽略 """ adjuster = fcustom(_limit_adjuster_deprecated, covered=covered) return smooth(trans_signal, source_signal, limit_signal, sfunc=adjuster)
def limit_adjust_deprecated( source_signal, limit_signal, trans_signal, covered=10): #covered不能大于127否则会溢出, np.sign(bool array)返回的是int8数组 ''' 根据停板信号limit_signal和交易日信号trans_signal调整原始信号,使原始信号避开停板到开板日 可能因covered的原因导致连续非停板日中间出现停板日后,信号多发. 但这个可由makke_trade之类的函数处理掉 只有covered=2时,不会出现这个情况 covered=10,最多10个停板,超过则可能导致跌停情况下卖出信号被忽略 ''' adjuster = fcustom(_limit_adjuster_deprecated, covered=covered) return smooth(trans_signal, source_signal, limit_signal, sfunc=adjuster)
def __init__(self, buy_signal_maker, sell_signal_maker, taxrate=125, trade_signal_maker=make_trade_signal, matcher=match_trades, trade_strategy=B1S1, pricer=default_pricer, extra_func=atr_extra): self.buy_signal_maker = buy_signal_maker self.sell_signal_maker = sell_signal_maker self.trade_signal_maker = trade_signal_maker self.matcher = matcher self.trade_strategy = trade_strategy self.buy_pricer = pricer[0] self.sell_pricer = pricer[1] self.extra_func = extra_func self.taxrate = taxrate self.make_trades = fcustom(make_trades, taxrate=taxrate, extra_func=extra_func) self.last_trade = fcustom(last_trade, taxrate=taxrate, extra_func=extra_func)
def atr_xseller_factory(stop_times=3 * BASE / 2, trace_times=2 * BASE, covered=10, up_sector=HIGH): """ 用于评估的seller_factory 将倒数第二个信号位置位,使得所有开仓合约平仓 """ inner_seller = fcustom( atr_seller, stop_times=stop_times, trace_times=trace_times, covered=covered, up_sector=up_sector ) def seller(stock, buy_signal, **kwargs): ss = inner_seller(stock, buy_signal, *kwargs) twhere = np.where(stock.transaction[VOLUME] > 0)[0] if len(twhere) and twhere[-1] - 1 >= 0: ss[twhere[-1] - 1] = 1 # 最后交易日之前的那一天置位,以便最后卖出平仓。 return ss return seller
def atr_xseller_factory(stop_times=3 * BASE / 2, trace_times=2 * BASE, covered=10, up_sector=HIGH): ''' 用于评估的seller_factory 将倒数第二个信号位置位,使得所有开仓合约平仓 ''' inner_seller = fcustom(atr_seller, stop_times=stop_times, trace_times=trace_times, covered=covered, up_sector=up_sector) def seller(stock, buy_signal, **kwargs): ss = inner_seller(stock, buy_signal, *kwargs) twhere = np.where(stock.transaction[VOLUME] > 0)[0] if len(twhere) and twhere[-1] - 1 >= 0: ss[twhere[-1] - 1] = 1 #最后交易日之前的那一天置位,以便最后卖出平仓。 return ss return seller
''' tsx1 = fpeak(source) sx1 = np.select([tsx1 != 0], [source], 0) if order <= 1: return sx1 icursx = np.nonzero(tsx1)[0] for i in xrange(1, order): sxx = source[icursx] tsxx = fpeak(sxx) icursx = icursx[np.nonzero(tsxx)[0]] osx = np.zeros_like(source) osx[icursx] = source[icursx] return osx zhpeak = fcustom(zpeak, fpeak=fhigh) zlpeak = fcustom(zpeak, fpeak=flow) 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)
index, attr_name_from, attr_name_to=None): if attr_name_from in stock.__dict__: if not attr_name_to: attr_name_to = attr_name_from trade.__dict__[attr_name_to] = int( stock.__dict__[attr_name_from] [index]) #将atr转换为平凡的int类型,而非numpy.int32,以便后续处理 else: logger.warn('append attribute error:%s do not have attribute %s', stock.code, attr_name_from) return trade atr_extra = fcustom(append_attribute_extra, attr_name_from='atr') #atr_extra的一般定义方法 def make_trades(stock, signal, tdate, tpositive, tnegative, begin=0, taxrate=125, trade_strategy=buy_first, extra_func=default_extra): ''' stock为stock ssingal为买卖信号,对于次日买卖的信号,输入前需要将signal roll(1) tpositive,tnegative为信号值为正和负时的选择价格 taxrate为税率,默认为千分之八
def nmediator_factory(trade_signal_maker=make_trade_signal_advanced,trade_strategy=B1S0,pricer = cl_pricer): return fcustom(NMediator,trade_signal_maker = trade_signal_maker,trade_strategy = trade_strategy,pricer=pricer)
order默认为1,小于1当作1 ''' tsx1 = fpeak(source) sx1 = np.select([tsx1!=0],[source],0) if order <= 1: return sx1 icursx = np.nonzero(tsx1)[0] for i in xrange(1,order): sxx = source[icursx] tsxx = fpeak(sxx) icursx = icursx[np.nonzero(tsxx)[0]] osx = np.zeros_like(source) osx[icursx] = source[icursx] return osx zhpeak = fcustom(zpeak,fpeak=fhigh) zlpeak = fcustom(zpeak,fpeak=flow) 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:
#收盘价买入,下限突破价卖出,必须有下限突破线 cl_pricer = (lambda s: s.transaction[CLOSE], lambda s: s.down_limit) #开盘价买入,下限突破价卖出,必须有下限突破线 ol_pricer = (lambda s: s.transaction[OPEN], lambda s: s.down_limit) #开盘价买入,开盘价卖出 oo_pricer = (lambda s: s.transaction[OPEN], lambda s: s.transaction[OPEN]) #收盘价买入,开盘价卖出 co_pricer = (lambda s: s.transaction[CLOSE], lambda s: s.transaction[OPEN]) #可定制自己的pricer,如 #my_pricer = (lambda s : s.buyprice,lambda s : s.sellprice) #定制的Mediator #一次买入一次买出,买入信号次日有效(开盘买入),卖出信号当日起效 Mediator10 = fcustom(Mediator, trade_strategy=B1S0, pricer=ol_pricer) #允许连续买入一次卖出,买入信号次日有效(开盘买入),卖出信号当日起效 CMediator10 = fcustom(Mediator, trade_signal_maker=make_trade_signal_advanced, trade_strategy=B1S0, pricer=ol_pricer) OMediator10 = fcustom(Mediator, trade_signal_maker=make_trade_signal_advanced, trade_strategy=B1S0, pricer=ol_pricer) def mediator_factory(trade_signal_maker=make_trade_signal_advanced, trade_strategy=B1S0, pricer=cl_pricer): return fcustom(Mediator,
return 0 trade.set_volume(wanted_size) tolds.append(trade) return trade.calc() #平均损失函数,返回的是千分比表示的平均损失 def ev_lost(trade): return trade.parent.evaluation.lostavg def atr_lost(trade, times=1000): return trade.atr * times / trade.tprice atr_lost_2000 = fcustom(atr_lost, times=2000) atr_lost_1200 = fcustom(atr_lost, times=1200) def RPR(xt, y): #净值评估函数,xt为日期维x,y为相应净值 '''#根据海龟交易法则 计算方法来自http://www.scipy.org/Cookbook/LinearRegression ''' (ar, br) = np.polyfit(xt, y, 1) #一阶拟合 xr = np.polyval([ar, br], xt) err = sqrt(sum((xr - y)**2) / len(xt)) #标准差 #(a_s,b_s,r,tt,stderr)=stats.linregress(xt,y) #len(xt)必须>2,否则会有问题. 即[begin,end)包含的实际日期数必须大于2 #year_inc_rate = int(a_s * 365 * POS_BASE/b_s) year_inc_rate = int(ar * 365 * POS_BASE / br) #logger.debug('rar:year_inc_rate=%s,a=%s,b=%s,k=a/b=%s,stderr=%s,err=%s',year_inc_rate,a_s,b_s,a_s/b_s,stderr,err) logger.debug('rar:year_inc_rate=%s,a=%s,b=%s,k=a/b=%s,err=%s',
logger.debug('second wanted volume is too small : %s %s',trade.tstock,trade.tdate) trade.set_volume(0) return 0 trade.set_volume(wanted_size) tolds.append(trade) return trade.calc() #平均损失函数,返回的是千分比表示的平均损失 def ev_lost(trade): return trade.parent.evaluation.lostavg def atr_lost(trade,times=1000): return trade.atr * times / trade.tprice atr_lost_2000 = fcustom(atr_lost,times=2000) atr_lost_1200 = fcustom(atr_lost,times=1200) def RPR(xt,y): #净值评估函数,xt为日期维x,y为相应净值 '''#根据海龟交易法则 计算方法来自http://www.scipy.org/Cookbook/LinearRegression ''' (ar,br)=np.polyfit(xt,y,1) #一阶拟合 xr = np.polyval([ar,br],xt) err=sqrt(sum((xr-y)**2)/len(xt)) #标准差 #(a_s,b_s,r,tt,stderr)=stats.linregress(xt,y) #len(xt)必须>2,否则会有问题. 即[begin,end)包含的实际日期数必须大于2 #year_inc_rate = int(a_s * 365 * POS_BASE/b_s) year_inc_rate = int(ar * 365 * POS_BASE/br) #logger.debug('rar:year_inc_rate=%s,a=%s,b=%s,k=a/b=%s,stderr=%s,err=%s',year_inc_rate,a_s,b_s,a_s/b_s,stderr,err) logger.debug('rar:year_inc_rate=%s,a=%s,b=%s,k=a/b=%s,err=%s',year_inc_rate,ar,br,ar/br,err) #logger.debug('rar:ar:%s,br:%s',ar,br)
#收盘价买入,下限突破价卖出,必须有下限突破线 cl_pricer = (lambda s : s.transaction[CLOSE],lambda s : s.down_limit) #开盘价买入,下限突破价卖出,必须有下限突破线 ol_pricer = (lambda s : s.transaction[OPEN],lambda s : s.down_limit) #开盘价买入,开盘价卖出 oo_pricer = (lambda s : s.transaction[OPEN],lambda s : s.transaction[OPEN]) #收盘价买入,开盘价卖出 co_pricer = (lambda s : s.transaction[CLOSE],lambda s : s.transaction[OPEN]) #可定制自己的pricer,如 #my_pricer = (lambda s : s.buyprice,lambda s : s.sellprice) #定制的Mediator #一次买入一次买出,买入信号次日有效(开盘买入),卖出信号当日起效 Mediator10 = fcustom(Mediator,trade_strategy=B1S0,pricer = ol_pricer) #允许连续买入一次卖出,买入信号次日有效(开盘买入),卖出信号当日起效 CMediator10 = fcustom(Mediator,trade_signal_maker=make_trade_signal_advanced ,trade_strategy=B1S0,pricer = ol_pricer) OMediator10 = fcustom(Mediator,trade_signal_maker=make_trade_signal_advanced ,trade_strategy=B1S0,pricer = ol_pricer) def mediator_factory(trade_signal_maker=make_trade_signal_advanced,trade_strategy=B1S0,pricer = cl_pricer): return fcustom(Mediator,trade_signal_maker = trade_signal_maker,trade_strategy = trade_strategy,pricer=pricer) dummy_trades = [Trade(-1,0,0,1),Trade(-1,0,0,-1)] class MM_Mediator(Mediator): ''' 只用于计算mm_ratio的mediator ''' def _calc(self,tmaker,sdata,dates,begin=0,**kwargs): raise NotImplementedError(u'MM_Mediator不能调用_calc')
return trade def atr_extra_custom(trade,stock,index): #将atr值赋给trade,专门定制,已经在后面被一般方法覆盖 trade.atr = int(stock.atr[index]) #将atr转换为平凡的int类型,而非numpy.int32,以便后续处理 return trade def append_attribute_extra(trade,stock,index,attr_name_from,attr_name_to=None): if attr_name_from in stock.__dict__: if not attr_name_to: attr_name_to = attr_name_from trade.__dict__[attr_name_to] = int(stock.__dict__[attr_name_from][index]) #将atr转换为平凡的int类型,而非numpy.int32,以便后续处理 else: logger.warn('append attribute error:%s do not have attribute %s',stock.code,attr_name_from) return trade atr_extra = fcustom(append_attribute_extra,attr_name_from='atr') #atr_extra的一般定义方法 def make_trades(stock,signal,tdate,tpositive,tnegative ,begin=0,taxrate=125,trade_strategy=buy_first,extra_func=default_extra): ''' stock为stock ssingal为买卖信号,对于次日买卖的信号,输入前需要将signal roll(1) tpositive,tnegative为信号值为正和负时的选择价格 taxrate为税率,默认为千分之八 begin为起始交易日 trade_strategy为交易方式,先买后卖,先卖后买,还是均可 以买入开始计算 ''' assert len(tpositive) == len(tnegative) == len(signal) #print signal,'=signal' sis = signal.nonzero()[0] #非0信号的index slen = len(sis)