Example #1
0
 def test_match_trades_empty(self):
     #空的输入
     self.assertEquals([], match_trades([]))
     #有输入,但无匹配
     trade1 = Trade(1, 20050101, 1000, 1)
     trade2 = Trade(2, 20050101, 1100, 1)
     trades = [trade1, trade2]
     mts = match_trades(trades)
     self.assertEquals(0, len(mts))
Example #2
0
 def test_evaluate_all(self):    #Ö»²âÊÔͨ·
     trade1 = Trade(1,20050101,1000,1)
     trade2 = Trade(1,20050101,1100,-1)
     pman = AdvancedPositionManager()
     dm = DateManager(20050101,20050401)        
     rev,srev = evaluate_all([[trade1,trade2]],pman,dm)
     self.assertTrue(rev)
     self.assertTrue(srev)
     self.assertTrue(rev.pre_ev)
     self.assertTrue(rev.g_ev)
Example #3
0
 def test_match_trades_successive_neg(self):  #连续建空仓
     trade1 = Trade(1, 20050101, 1000, -1)
     trade2 = Trade(1, 20050101, 1100, -1)
     trade3 = Trade(1, 20050101, 800, 1)
     trade4 = Trade(1, 20050101, 1200, 1)
     trades = [trade1, trade2, trade3, trade4]
     mts = match_trades(trades)
     self.assertEquals(1, len(mts))
     self.assertEquals([trade1, trade2, trade3], mts[0])
     self.assertEquals(trade1.tvolume + trade2.tvolume, -trade3.tvolume)
Example #4
0
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)
    if slen == 0:
        return []
    tbegin = tdate.searchsorted(begin)
    ibegin = sis.searchsorted(tbegin)  #tbegin在非0索引中的插入位置
    #print tbegin,ibegin
    if ibegin >= slen:  #空信号
        return []
    should_skip = trade_strategy(signal[sis[ibegin]])
    ibegin += should_skip
    if ibegin >= slen:  #仍然是空信号
        return []
    #print signal[tbegin:].tolist(),sis,ibegin,tbegin
    tbegin = sis[ibegin]
    trades = []
    #print sis
    #print tnegative
    for i in xrange(ibegin, slen):
        ci = sis[i]
        cs = signal[ci]  #通常是1/-1,只有正/负有意义,数值本身无意义
        price = tpositive[ci] if cs > 0 else tnegative[ci]
        #print ci,cs,price,tdate[ci],tnegative[ci]
        ctrade = Trade(
            stock.code, int(tdate[ci]), int(price),
            int(cs) * VOLUME_BASE, taxrate
        )  #int强制转换,避免把numpy.int32传入trade.因为ndarray索引得到的值是numpy.intxx的,而非普通int
        ctrade.stock = stock
        ctrade.idate = ci
        trades.append(extra_func(ctrade, stock, ci))
    #if sum(signal[tbegin:]) != 0: #最后一个未平仓,不计算。 这一点已经在match_trades中保证
    #print sum(signal[tbegin:]),signal[tbegin:].tolist()
    #    trades.pop()
    #print trades[-1].tdate,trades[-1].tvolume,trades[-1].tprice
    return trades
Example #5
0
 def test_save_last(self):
     from wolfox.fengine.base.common import Trade
     trades1 = [Trade('test', 1, 1, 1), Trade('test2', 2, 2, 2)]
     trades2 = [Trade('test3', 1, 1, 1), Trade('test4', 2, 2, 2)]
     import os
     save_last('test_save_last.txt', {}, 20010101, 20050101, 20041220)
     save_last('test_save_last.txt', {
         't1': trades1,
         't2': trades2
     }, 20010101, 20050101, 20041220)
     os.remove('test_save_last.txt')
Example #6
0
 def test_match_trades_left(self):  #包含未闭合交易
     trade1 = Trade(1, 20050101, 1000, 1)
     trade2 = Trade(1, 20050101, 1100, 1)
     trade3 = Trade(1, 20050101, 800, -1)
     trade4 = Trade(1, 20050101, 1200, -1)
     trade5 = Trade(1, 20050101, 1200, 1)
     trades = [trade1, trade2, trade3, trade4, trade5]
     mts = match_trades(trades)
     #print mts
     self.assertEquals(2, len(mts))
     self.assertEquals([[trade1, trade2, trade3], [trade4, trade5]], mts)
     self.assertEquals(trade1.tvolume + trade2.tvolume, -trade3.tvolume)
Example #7
0
 def organize_trades(self, named_trades):
     trades = PositionManager.organize_trades(self, named_trades)
     #for trade in trades:
     #    print trade
     if len(trades) == 0:
         return trades
     new_trades = []
     ti = 0
     tcur = trades[ti]
     dlen = len(trades[0].stock.transaction[CLOSE])
     holding = {}
     for i in xrange(dlen):
         for hold in holding.values():  #i=0是没有持仓,所以不需要判断i>1
             tlimit = (hold[0].transaction[CLOSE][i - 1] +
                       hold[0].transaction[HIGH][i - 1]) / 2
             base = hold[-1]
             #print tlimit,hold[1]+hold[2]
             if (tlimit > hold[1] + hold[2] and tlimit <
                     base.tprice + hold[2] * 5):  #当不超过3ATR时,添加一个trade
                 #print base.tstock,self.dates[i],tlimit,hold[1],hold[2],base.tprice
                 tvolume = base.tvolume / 2 or 1
                 trade = Trade(base.tstock, int(self.dates[i]),
                               int(hold[0].transaction[OPEN][i]), tvolume,
                               base.taxrate)
                 trade.stock = base.stock
                 trade.atr = int(base.stock.atr2[i])
                 trade.type = 'append'
                 new_trades.append(trade)
                 holding[hold[0]][1] = hold[1] + hold[2]  #更改起始价格
         while tcur.idate == i:
             if tcur.tvolume > 0:
                 holding[tcur.stock] = [
                     tcur.stock, tcur.tprice,
                     int(tcur.stock.atr2[i]), tcur
                 ]
             elif tcur.tvolume < 0 and tcur.stock in holding:
                 #print 'del:',tcur.tdate
                 del holding[tcur.stock]
             ti += 1
             if ti >= len(trades):
                 break
             tcur = trades[ti]
         if ti >= len(trades):
             break
     trades[0:0] = new_trades  #插入到前面,以便如果B/S同时出现,B排序在前面
     trades.sort(cmp=lambda x, y: x.tdate - y.tdate)
     #for trade in trades:print trade
     return trades
Example #8
0
 def test_gevaluate(self):
     trade1 = Trade(1,20050101,1000,1)
     trade2 = Trade(1,20050101,1100,-1)
     trade3 = Trade(2,20050501,1000,1)
     trade4 = Trade(2,20050501,1100,-1)
     #trade5 = Trade(3,20050501,1100,1)        
     datemap = {20050101:0,20050501:1}
     nt1 = BaseObject(name='test1',evaluation=Evaluation([],datemap),trades=[[trade1,trade2]])
     nt2 = BaseObject(name='test1',evaluation=Evaluation([],datemap),trades=[[trade3,trade4]])
     #nt3 = BaseObject(name='test1',evaluation=Evaluation([]),trades=[trade5])
     ev = gevaluate([nt1,nt2],datemap)
     self.assertEquals([[trade1,trade2],[trade3,trade4]],ev.matchedtrades)
     self.assertEquals(nt1,trade1.parent)
     self.assertEquals(nt1,trade2.parent)
     self.assertEquals(nt2,trade3.parent)
     self.assertEquals(nt2,trade4.parent)
Example #9
0
def last_trade(stock,
               signal,
               tdate,
               tpositive,
               tnegative,
               begin=0,
               taxrate=125,
               trade_strategy=buy_first,
               extra_func=default_extra):  #trade_strategy虽然没用,也给写上
    ''' 返回值为[x]形式(无时为[])
    '''
    assert len(tpositive) == len(tnegative) == len(signal)
    #for t,s in zip(tdate,signal):print t,s
    sis = signal.nonzero()[0]  #非0信号的index
    tbegin = tdate.searchsorted(begin)
    ibegin = sis.searchsorted(tbegin)  #tbegin在非0索引中的插入位置
    slen = len(sis)
    #print tbegin,ibegin,slen
    #if slen == 0 or sum(signal[tbegin:]) == 0 or tdate[sis[-1]] < begin: #空信号序列(实际上也是sum(signal)==0)或都已经匹配,无悬挂之买入/卖出
    #    return []
    if slen == 0 or tdate[sis[-1]] < begin:  #空信号序列,匹配的卖出也要显示
        return []
    #print signal
    last_index = sis[-1]
    cs = signal[last_index]
    price = tpositive[last_index] if cs > 0 else tnegative[last_index]
    ltrade = Trade(stock.code, int(tdate[last_index]), int(price),
                   int(cs) * VOLUME_BASE, taxrate)
    trades = [extra_func(ltrade, stock, last_index)]
    return trades
Example #10
0
 def test_atr_extra(self):
     stock = BaseObject(code='test', atr=np.array([1, 2, 3]))
     trade = Trade(stock.code, 20010101, 10000, 1)
     atr_extra(trade, stock, 0)
     self.assertEquals(1, trade.atr)
     self.assertEquals(type(1), type(trade.atr))
     atr_extra(trade, stock, 2)
     self.assertEquals(3, trade.atr)
Example #11
0
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)    
    if slen == 0:
        return []
    tbegin = tdate.searchsorted(begin)
    ibegin = sis.searchsorted(tbegin)   #tbegin在非0索引中的插入位置
    #print tbegin,ibegin
    if ibegin >= slen: #空信号
        return []
    should_skip = trade_strategy(signal[sis[ibegin]])
    ibegin += should_skip
    if ibegin >= slen: #仍然是空信号
        return []
    #print signal[tbegin:].tolist(),sis,ibegin,tbegin
    tbegin = sis[ibegin]
    trades = []
    #print sis
    #print tnegative
    for i in xrange(ibegin,slen):
        ci = sis[i]
        cs = signal[ci]     #通常是1/-1,只有正/负有意义,数值本身无意义
        price = tpositive[ci] if cs>0 else tnegative[ci]
        #print ci,cs,price,tdate[ci],tnegative[ci]
        ctrade = Trade(stock.code,int(tdate[ci]),int(price),int(cs)*VOLUME_BASE,taxrate) #int强制转换,避免把numpy.int32传入trade.因为ndarray索引得到的值是numpy.intxx的,而非普通int
        ctrade.stock = stock
        ctrade.idate = ci
        trades.append(extra_func(ctrade,stock,ci))
    #if sum(signal[tbegin:]) != 0: #最后一个未平仓,不计算。 这一点已经在match_trades中保证
        #print sum(signal[tbegin:]),signal[tbegin:].tolist()
    #    trades.pop()
    #print trades[-1].tdate,trades[-1].tvolume,trades[-1].tprice
    return trades
Example #12
0
 def organize_trades(self,named_trades):
     trades = PositionManager.organize_trades(self,named_trades)
     #for trade in trades:
     #    print trade
     if len(trades) == 0:
         return trades
     new_trades = []
     ti = 0
     tcur = trades[ti]
     dlen = len(trades[0].stock.transaction[CLOSE])
     holding = {}
     for i in xrange(dlen):
         for hold in holding.values():   #i=0是没有持仓,所以不需要判断i>1
             tlimit = (hold[0].transaction[CLOSE][i-1] + hold[0].transaction[HIGH][i-1])/2
             base = hold[-1]
             #print tlimit,hold[1]+hold[2]
             if(tlimit > hold[1] + hold[2] and tlimit <  base.tprice + hold[2]*5):#当不超过3ATR时,添加一个trade
                 #print base.tstock,self.dates[i],tlimit,hold[1],hold[2],base.tprice
                 tvolume = base.tvolume/2 or 1
                 trade = Trade(base.tstock,int(self.dates[i]),int(hold[0].transaction[OPEN][i]),tvolume,base.taxrate)
                 trade.stock = base.stock
                 trade.atr = int(base.stock.atr2[i])
                 trade.type = 'append'
                 new_trades.append(trade)
                 holding[hold[0]][1] = hold[1] + hold[2] #更改起始价格
         while tcur.idate == i:
             if tcur.tvolume>0:
                 holding[tcur.stock] = [tcur.stock,tcur.tprice,int(tcur.stock.atr2[i]),tcur]
             elif tcur.tvolume<0 and tcur.stock in holding:
                 #print 'del:',tcur.tdate
                 del holding[tcur.stock]
             ti += 1
             if ti >= len(trades):
                 break
             tcur = trades[ti]
         if ti>=len(trades):
             break
     trades[0:0]= new_trades #插入到前面,以便如果B/S同时出现,B排序在前面
     trades.sort(cmp=lambda x,y:x.tdate-y.tdate)
     #for trade in trades:print trade
     return trades
Example #13
0
 def test_append_attribute_extra(self):
     stock = BaseObject(code='test', atr=np.array([1, 2, 3]))
     trade = Trade(stock.code, 20010101, 10000, 1)
     append_attribute_extra(trade, stock, 0, 'atr')
     self.assertEquals(1, trade.atr)
     append_attribute_extra(trade, stock, 2, 'atr')
     self.assertEquals(3, trade.atr)
     append_attribute_extra(trade, stock, 0, 'atr', 'vtr')  #指定不同的目的名字
     self.assertEquals(1, trade.vtr)
     #属性不存在测试
     append_attribute_extra(trade, stock, 2, 'xtr')
     self.assertRaises(AttributeError, lambda: trade.xtr)
Example #14
0
 def test_match_trades_multi(self):  #包含未闭合交易
     trade1 = Trade(1, 20050101, 1000, 1)
     trade2 = Trade(2, 20050101, 1100, 1)
     trade3 = Trade(1, 20050101, 800, -1)
     trade4 = Trade(2, 20050101, 1200, -1)
     trade5 = Trade(1, 20050101, 1200, 1)
     trade6 = Trade(2, 20050101, 1300, -1)
     trades = [trade1, trade2, trade3, trade4, trade5, trade6]
     mts = match_trades(trades)
     self.assertEquals(2, len(mts))
     self.assertEquals([trade1, trade3], mts[0])
     self.assertEquals([trade2, trade4], mts[1])
Example #15
0
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')

    def calc_matched(self, sdata, dates, begin=0, **kwargs):
        trades = []
        for s in sdata.values():
            try:  #捕捉某些异常,如未划入任何板块的股票在计算板块相关信号时会出错
                self.prepare(s, **kwargs)
                sbuy = self.buy_signal_maker(s)
                #for i in range(np.sum(sbuy)):   #假Trade数据
Example #16
0
import numpy as np
from math import sqrt
#from scipy import stats

from wolfox.fengine.base.common import Trade
from wolfox.fengine.core.base import BaseObject, CLOSE, HIGH, OPEN
from wolfox.fengine.core.d1 import greater
from wolfox.fengine.core.utils import fcustom
from wolfox.fengine.core.d1ex import extend2next
from wolfox.fengine.core.future import decline_ranges, decline_periods, decline

logger = logging.getLogger('wolfox.fengine.core.postion_manager')

POS_BASE = 1000

NULL_TRADE = Trade(0, 0, 0, 0)  #用于占位的空TRADE


class Position(object
               ):  #只能用于管理单边头寸(即卖出都是pop,买入都是push或相反),否则需要调用者判断某个买卖动作是push还是pop
    def __init__(self):
        self.holdings = {}  #现有仓位: code ==> [trade,....]    各trade都是同向操作
        self.history = []  #元素为一次封闭交易[trade_buy,trade_buy,...trade_sell]的列表

    def clear(self):
        self.holdings = {}  #比clear快
        self.history = []

    def push(self, trade, lostavg, risk, size_limit):
        ''' trade为标准交易
            返回根据lostavg,risk计算的实际的交易额,但不能超过size_limit