Ejemplo n.º 1
0
class SingleMA(strategy.BacktestingStrategy):
    def __init__(self, feed, instrument, n, initialCash=1000000):
        strategy.BacktestingStrategy.__init__(self, feed, initialCash)
        self.__instrument = instrument
        self.getBroker().setFillStrategy(DefaultStrategy(None))
        self.getBroker().setCommission(TradePercentage(0.001))
        self.__position = None
        self.__prices = feed[instrument].getPriceDataSeries()
        self.__malength = int(n)
        self.__ma = ma.SMA(self.__prices, self.__malength)
        self.__pos = SequenceDataSeries()  # record signal

    def getPrice(self):
        return self.__prices

    def getMA(self):
        return self.__ma

    def testCon(self):
        if self.__position is not None:
            self.__pos.append(1)
        elif self.__position is None:
            self.__pos.append(0)

    def getPos(self):
        return self.__pos

    def onEnterCanceled(self, position):
        self.__position = None

    def onEnterOk(self, position):
        execInfo = position.getEntryOrder().getExecutionInfo()
        instrumentInfo = position.getInstrument()
        self.info("BUY %s at $%.2f" % (instrumentInfo, execInfo.getPrice()))

    def onExitOk(self, position):
        execInfo = position.getExitOrder().getExecutionInfo()
        instrumentInfo = position.getInstrument()
        self.info("SELL %s at $%.2f" % (instrumentInfo, execInfo.getPrice()))
        self.__position = None

    def onExitCancelled(self, position):
        self.__position.exitMarket()

    def onBars(self, bars):
        closePrice = bars[self.__instrument].getPrice()

        if self.__ma[-1] is None:
            return

        self.testCon()

        if self.__position is not None:
            if not self.__position.exitActive() and closePrice < self.__ma[-1]:
                self.__position.exitMarket()

        if self.__position is None:
            if closePrice > self.__ma[-1]:
                shares = int(self.getBroker().getEquity() * 0.9 / closePrice)
                self.__position = self.enterLong(self.__instrument, shares)
Ejemplo n.º 2
0
 def __init__(self, feed, instrument, n, initialCash=1000000):
     strategy.BacktestingStrategy.__init__(self, feed, initialCash)
     self.__instrument = instrument
     self.getBroker().setFillStrategy(DefaultStrategy(None))
     self.getBroker().setCommission(TradePercentage(0.001))
     self.__position = None
     self.__prices = feed[instrument].getPriceDataSeries()
     self.__malength = int(n)
     self.__ma = ma.SMA(self.__prices, self.__malength)
     self.__pos = SequenceDataSeries()  # record signal
Ejemplo n.º 3
0
    def __init__(self, feed, instrument, mall, mals, masl, mass):
        strategy.BacktestingStrategy.__init__(self, feed)
        self.getBroker().setFillStrategy(DefaultStrategy(None))
        self.getBroker().setCommission(TradePercentage(0.001))
        self.__instrument = instrument
        self.__close = feed[instrument].getCloseDataSeries()
        self.__longPos = None
        self.__shortPos = None
        self.__mall = ma.SMA(self.__close, int(mall))
        self.__mals = ma.SMA(self.__close, int(mals))
        self.__masl = ma.SMA(self.__close, int(masl))
        self.__mass = ma.SMA(self.__close, int(mass))

        self.__position = SequenceDataSeries()
Ejemplo n.º 4
0
 def __init__(self, feed, instrument, n, initialCash = 1000000):
     strategy.BacktestingStrategy.__init__(self, feed, initialCash)
     self.__instrument = instrument
     self.getBroker().setFillStrategy(DefaultStrategy(None))
     self.getBroker().setCommission(TradePercentage(0.001))
     self.__position = None
     self.__prices = feed[instrument].getPriceDataSeries()
     self.__malength = int(n)
     self.__ma = ma.SMA(self.__prices, self.__malength)
     self.__pos = SequenceDataSeries() # record signal
Ejemplo n.º 5
0
 def __init__(self, feed, instrument, fast, slow, signal, up_cum):
     strategy.BacktestingStrategy.__init__(self, feed)
     self.__instrument = instrument
     self.getBroker().setFillStrategy(DefaultStrategy(None))
     self.getBroker().setCommission(TradePercentage(0.0008))
     self.__longPos = None
     self.__shortPos = None
     self.__prices = feed[instrument].getPriceDataSeries()
     self.__macd=macd.MACD(self.__prices,fast,slow,signal)
     self.__range=0
     self.__circ = int(up_cum)
     self.__position = SequenceDataSeries()
Ejemplo n.º 6
0
 def __init__(self,
              instrument,
              dataSeries,
              fastEMA,
              slowEMA,
              signalEMA,
              maxLen=None):
     assert (fastEMA > 0)
     assert (slowEMA > 0)
     assert (fastEMA < slowEMA)
     assert (signalEMA > 0)
     super(Macd, self).__init__(maxLen)
     self.__instrument = instrument
     self.__skipNum = max(fastEMA, slowEMA, signalEMA)
     self.__fastEMAWindow = EMAEventWindow(fastEMA)
     self.__slowEMAWindow = EMAEventWindow(slowEMA)
     self.__signalEMAWindow = EMAEventWindow(signalEMA)
     self.__signal = SequenceDataSeries(maxLen)  #dea
     self.__histogram = SequenceDataSeries(maxLen)  #macd
     self.__cross = SequenceDataSeries(
         maxLen)  #dead cross signals and gold cross signals
     self.__close_prices = dataSeries.getPriceDataSeries()
     self.top_divergences = list()
     self.double_top_divergences = list()
     self.bottom_divergences = list()
     self.double_bottom_divergences = list()
     self.cross_detect = CrossDetect()
     self.max_limit_detect = MaxLimitDetect
     self.min_limit_detect = MinLimitDetect
     self.top_divergence_detect = TopDivergenceDetect()
     self.bottom_divergence_detect = BottomDivergenceDetect()
     self.__close_prices.getNewValueEvent().subscribe(self.__onNewValue)
Ejemplo n.º 7
0
 def __init__(self, feed, instrument, mall, mals, masl, mass):
     strategy.BacktestingStrategy.__init__(self, feed)
     self.getBroker().setFillStrategy(DefaultStrategy(None))
     self.getBroker().setCommission(TradePercentage(0.001))
     self.__instrument = instrument
     self.__close = feed[instrument].getCloseDataSeries()
     self.__longPos = None
     self.__shortPos = None
     self.__mall = ma.SMA(self.__close, int(mall))
     self.__mals = ma.SMA(self.__close, int(mals))
     self.__masl = ma.SMA(self.__close, int(masl))
     self.__mass = ma.SMA(self.__close, int(mass))
     
     self.__position = SequenceDataSeries()
Ejemplo n.º 8
0
    def __init__(self, feed, instrument, bollingerlength, numStdDev):
        strategy.BacktestingStrategy.__init__(self, feed)
        self.getBroker().setFillStrategy(DefaultStrategy(None))
        self.getBroker().setCommission(TradePercentage(0))
        self.__instrument = instrument
        self.__bollingerlength = int(bollingerlength)
        self.__close = feed[instrument].getPriceDataSeries()
        numStdDev = float(numStdDev) / 10
        self.__longPos = []
        self.__macd=macd.MACD(self.__close,50,150,10)
        self.__bollinger = bollinger.BollingerBands(self.__macd, self.__bollingerlength, int(numStdDev))
        self.__UpperBand = self.__bollinger.getUpperBand()
        self.__LowerBand = self.__bollinger.getLowerBand()

        self.__position = SequenceDataSeries()
        self.__circ=5
Ejemplo n.º 9
0
    def __init__(self, feed, instrument,longline,shortline,bollingerlength, numStdDev):
        strategy.BacktestingStrategy.__init__(self, feed)
        self.getBroker().setFillStrategy(DefaultStrategy(None))
        self.getBroker().setCommission(TradePercentage(0.001))
        self.__instrument = instrument
        self.__bollingerlength = int(bollingerlength)
        self.__close = feed[instrument].getMatchDataSeries()
        numStdDev = float(numStdDev) / 10
        self.__longPos = []
        self.__shortPos = []
        self.__macd=macd.MACD(self.__close,shortline,longline,10)
        self.__bollinger = bollinger.BollingerBands(self.__macd, self.__bollingerlength, int(numStdDev))
        self.__UpperBand = self.__bollinger.getUpperBand()
        self.__LowerBand = self.__bollinger.getLowerBand()

        self.__position = SequenceDataSeries()
        self.__circ=5
        self.__lastLongPos=None
        self.__lastShortPos=None
        self.__barNum=0
        self.__macdMin=[]
        self.__macdMax=[]
Ejemplo n.º 10
0
 def __init__(self, feed, instrument,preclose,prehigh,prelow,p1,p2,p3,p4):
     strategy.BacktestingStrategy.__init__(self, feed)
     self.getBroker().setFillStrategy(DefaultStrategy(None))
     self.getBroker().setCommission(TradePercentage(0.001))
     self.__instrument = instrument
     self.__longPos = []
     self.__shortPos = []
     self.__position = SequenceDataSeries()
     self.__prices= feed[instrument].getPriceDataSeries()
     self.__circ=5
     self.__lastLongPos=None
     self.__lastShortPos=None
     self.__barNum=0
     self.__ssetup=prehigh-p1*(preclose-prelow)
     self.__senter=((1+p2)/2)*(prehigh+preclose)-p2*prelow
     self.__benter=((1+p2)/2)*(prelow+preclose)-p2*prehigh
     self.__bsetup=prelow+p1*(prehigh-preclose)
     self.__bbreak=self.__ssetup+p3*(self.__ssetup-self.__bsetup)
     self.__sbreak=self.__bsetup-p3*(self.__ssetup-self.__bsetup)
     self.__moreSsetup=False
     self.__lessBsetup=False
     self.__couldsbreak=True
     self.__couldbbreak=True
     self.__p4=p4
Ejemplo n.º 11
0
 def __init__(self, feed = None, instrument = '',shortPeriod =  0,longPeriod = 0,money = None,longAllowed=True,shortAllowed=True):
  strategy.BacktestingStrategy.__init__(self, feed)

  self.position_cost = 0  #mid init position value
  
  mid_DEFAULT_MAX_LEN = 10 * DEFAULT_MAX_LEN
  self.__instrument = instrument
  self.__longPosition = None
  self.__shortPosition = None
  
  self.__position_volume = SequenceDataSeries(maxLen = mid_DEFAULT_MAX_LEN)       #mid 当前持有头寸数量
  self.__position_cost = SequenceDataSeries(maxLen = mid_DEFAULT_MAX_LEN)  #mid 当前持有头寸开仓成本
  self.__position_pnl = SequenceDataSeries(maxLen = mid_DEFAULT_MAX_LEN)   #mid 当前持有头寸价值
  self.__portfolio_value = SequenceDataSeries(maxLen = mid_DEFAULT_MAX_LEN)
  self.__buy = SequenceDataSeries(maxLen = mid_DEFAULT_MAX_LEN)
  self.__sell = SequenceDataSeries(maxLen = mid_DEFAULT_MAX_LEN)
  
  
  self.__buySignal = False
  self.__sellSignal = False
  self.money = money
  self.longAllowed = True
  self.shortAllowed = True        
  #mid 计算ma将使用当天的收盘价格计算
  #mid 1)
  dataSeries = feed[instrument]
  dataSeries.setMaxLen(mid_DEFAULT_MAX_LEN)
  closeSeries = dataSeries.getCloseDataSeries()
  #mid 2)
  prices = closeSeries
  prices.setMaxLen(mid_DEFAULT_MAX_LEN)
  #mid 3)
  self.__sma = ma.SMA(prices, shortPeriod,maxLen=mid_DEFAULT_MAX_LEN)
  self.__lma = ma.SMA(prices,longPeriod,maxLen=mid_DEFAULT_MAX_LEN)

  self.i = 0
Ejemplo n.º 12
0
class Bollinger_Bandit(strategy.BacktestingStrategy):
    def __init__(self, feed, instrument, bollingerlength, numStdDev,
                 closelength, ccMAlength, malength, space):
        strategy.BacktestingStrategy.__init__(self, feed)
        self.getBroker().setFillStrategy(DefaultStrategy(None))
        self.getBroker().setCommission(TradePercentage(0.002))
        self.__instrument = instrument
        self.__bollingerlength = int(bollingerlength)
        numStdDev = float(numStdDev) / 10
        self.__closelength = int(closelength)
        self.__ccMAlength = int(ccMAlength)
        self.__malength = int(malength)
        self.__longPos = None
        self.__shortPos = None
        self.__close = feed[instrument].getCloseDataSeries()
        self.__open = feed[instrument].getOpenDataSeries()
        self.__high = feed[instrument].getHighDataSeries()
        self.__low = feed[instrument].getLowDataSeries()
        self.__datetime = feed[instrument].getDateTimes()
        self.__bollinger = bollinger.BollingerBands(self.__close,
                                                    self.__bollingerlength,
                                                    int(numStdDev))
        self.__UpperBand = self.__bollinger.getUpperBand()
        self.__LowerBand = self.__bollinger.getLowerBand()
        self.__MA = SequenceDataSeries()
        self.__space = int(space)
        self.__enter = 0
        self.__enterLong1 = 0
        self.__enterLong2 = 0
        self.__enterShort1 = 0
        self.__enterShort2 = 0
        self.__exitLong1 = 0
        self.__exitLong2 = 0
        self.__exitShort1 = 0
        self.__exitShort1 = 0

        #for test
        #########################################################################
        self.__p = SequenceDataSeries()
        self.__filterCon = SequenceDataSeries()
        self.__ccMACon1 = SequenceDataSeries()
        self.__ccMACon2 = SequenceDataSeries()
        self.__enterCon = SequenceDataSeries()
        self.__enterLongCon1 = SequenceDataSeries()
        self.__enterLongCon2 = SequenceDataSeries()
        self.__enterShortCon1 = SequenceDataSeries()
        self.__enterShortCon2 = SequenceDataSeries()
        self.__exitLongCon1 = SequenceDataSeries()
        self.__exitLongCon2 = SequenceDataSeries()
        self.__exitShortCon1 = SequenceDataSeries()
        self.__exitShortCon2 = SequenceDataSeries()
        ##########################################################################

    def getHigh(self):
        return self.__high

    def getLow(self):
        return self.__low

    def getClose(self):
        return self.__close

    def getBollinger(self):
        return self.__UpperBand, self.__LowerBand

    def getMA(self):
        return self.__MA

    def getDateTime(self):
        return self.__datetime

    def getPosition(self):
        return self.__p

    def getTest(self):
        return self.__filterCon, self.__ccMACon1, self.__ccMACon2, \
        self.__enterCon, self.__enterLongCon1, self.__enterLongCon2, self.__enterShortCon1, \
        self.__enterShortCon2, self.__exitLongCon1, self.__exitLongCon2, \
        self.__exitShortCon1, self.__exitShortCon2

    def onEnterCanceled(self, position):
        if self.__longPos == position:
            self.__longPos = None
        elif self.__shortPos == position:
            self.__shortPos = None
        else:
            assert (False)

    def onExitOk(self, position):
        if self.__longPos == position:
            self.__longPos = None
        elif self.__shortPos == position:
            self.__shortPos = None
        else:
            assert (False)

    def onBars(self, bars):
        # If a position was not opened, check if we should enter a long position.

        bar = bars[self.__instrument]
        if len(self.__high) > 1:
            print self.__close[-1], self.__high[-1], self.__open[
                -1], self.__close[-2]
        if self.__UpperBand is not None:
            print self.__UpperBand[-1]
        # filter datetime
        ###################################################################################
        filterCon = len(self.__close) < max(
            self.__bollingerlength, self.__malength, self.__closelength)
        self.__filterCon.append(filterCon)

        if filterCon:
            return

        # record position
        ####################################################################################
        if self.__longPos is not None and self.__shortPos is None:
            self.__p.append(1)
        elif self.__longPos is None and self.__shortPos is not None:
            self.__p.append(-1)
        else:
            self.__p.append(0)

        # calculate ccMA
        ####################################################################################
        ccMACon1 = self.__longPos is not None or self.__shortPos is not None
        ccMACon2 = self.__malength > self.__ccMAlength

        if ccMACon1 and ccMACon2:
            self.__malength = self.__malength - 1
        elif not ccMACon1:
            self.__malength = 50

        self.__ccMA = np.mean(self.__close[-self.__malength:])
        # print self.__malength, self.__ccMA
        self.__MA.append(self.__ccMA)
        self.__ccMACon1.append(ccMACon1)
        self.__ccMACon2.append(ccMACon2)

        #open and close condition
        ######################################################################################
        self.__enterLong1 = (cross.cross_above(self.__high, self.__UpperBand) >
                             0)
        self.__enterLong2 = (bar.getClose() >= max(
            self.__close[-self.__closelength:]))
        self.__enter = ((self.__UpperBand[-1] - self.__LowerBand[-1]) /
                        bar.getClose() > float(self.__space) / 1000)
        # print (self.__UpperBand[-1] - self.__LowerBand[-1]) / bar.getClose()
        self.__enterShort1 = cross.cross_below(self.__low,
                                               self.__LowerBand) > 0
        self.__enterShort2 = bar.getClose() <= min(
            self.__close[-self.__closelength:])
        self.__exitLong1 = (bar.getClose() < self.__ccMA)
        self.__exitLong2 = (self.__ccMA < self.__UpperBand[-1])
        self.__exitShort1 = (bar.getClose() > self.__ccMA)
        self.__exitShort2 = (self.__ccMA > self.__LowerBand[-1])

        self.__enterCon.append(self.__enter)
        self.__enterLongCon1.append(self.__enterLong1)
        self.__enterLongCon2.append(self.__enterLong2)
        self.__enterShortCon1.append(self.__enterShort1)
        self.__enterShortCon2.append(self.__enterShort2)
        self.__exitLongCon1.append(self.__exitLong1)
        self.__exitLongCon2.append(self.__exitLong2)
        self.__exitShortCon1.append(self.__exitShort1)
        self.__exitShortCon2.append(self.__exitShort2)

        #open and close
        #######################################################################################
        if self.__longPos is not None:
            if self.exitLongSignal():
                self.__longPos.exitMarket()
            if self.__shortPos is not None:
                print 11
                self.info("intend long close")
                print(self.__UpperBand[-1] -
                      self.__LowerBand[-1]) / bar.getClose()

        elif self.__shortPos is not None:
            if self.exitShortSignal():
                self.__shortPos.exitMarket()
                self.info("intend short close")
                print(self.__UpperBand[-1] -
                      self.__LowerBand[-1]) / bar.getClose()

        else:
            if self.enterLongSignal():
                shares = int(self.getBroker().getCash() * 0.2 /
                             bars[self.__instrument].getPrice())
                self.__longPos = self.enterLong(self.__instrument, shares)
                self.info("intend long open")
                print(self.__UpperBand[-1] -
                      self.__LowerBand[-1]) / bar.getClose()

            elif self.enterShortSignal():
                shares = int(self.getBroker().getCash() * 0.2 /
                             bars[self.__instrument].getPrice())
                self.__shortPos = self.enterShort(self.__instrument, shares)
                self.info("intend short open")
                print(self.__UpperBand[-1] -
                      self.__LowerBand[-1]) / bar.getClose()

    def enterLongSignal(self):
        if self.__enterLong1 and self.__enterLong2 and self.__enter:
            return True

    def enterShortSignal(self):
        if self.__enterShort1 and self.__enterShort2 and self.__enter:
            return True

    def exitLongSignal(self):
        if self.__exitLong1 and self.__exitLong2 and not self.__longPos.exitActive(
        ):
            return True

    def exitShortSignal(self):
        if self.__exitShort1 and self.__exitShort2 and not self.__shortPos.exitActive(
        ):
            return True
Ejemplo n.º 13
0
class rbreaker(strategy.BacktestingStrategy):
    def __init__(self, feed, instrument,preclose,prehigh,prelow,p1,p2,p3,p4):
        strategy.BacktestingStrategy.__init__(self, feed)
        self.getBroker().setFillStrategy(DefaultStrategy(None))
        self.getBroker().setCommission(TradePercentage(0.001))
        self.__instrument = instrument
        self.__longPos = []
        self.__shortPos = []
        self.__position = SequenceDataSeries()
        self.__prices= feed[instrument].getPriceDataSeries()
        self.__circ=5
        self.__lastLongPos=None
        self.__lastShortPos=None
        self.__barNum=0
        self.__ssetup=prehigh-p1*(preclose-prelow)
        self.__senter=((1+p2)/2)*(prehigh+preclose)-p2*prelow
        self.__benter=((1+p2)/2)*(prelow+preclose)-p2*prehigh
        self.__bsetup=prelow+p1*(prehigh-preclose)
        self.__bbreak=self.__ssetup+p3*(self.__ssetup-self.__bsetup)
        self.__sbreak=self.__bsetup-p3*(self.__ssetup-self.__bsetup)
        self.__moreSsetup=False
        self.__lessBsetup=False
        self.__couldsbreak=True
        self.__couldbbreak=True
        self.__p4=p4

    def testCon(self):
        # record position
        #######################################################################
        if len(self.__longPos) > 0:
            self.__position.append(len(self.__longPos))
        if len(self.__shortPos)>0 :
            #print(self.__shortPos.getShares())
            self.__position.append(-len(self.__shortPos))
        elif len(self.__longPos)==0 and len(self.__shortPos)==0:
            self.__position.append(0)
            #print(0)


    def getPrice(self):
        return self.__prices

    def getTest(self):
        return self.__position

    def onBars(self, bars):
        bar = bars[self.__instrument]
        if self.__prices[-1]>self.__ssetup:
            self.__moreSsetup=True
        else:
            self.__couldbbreak=True
        if self.__prices[-1]<self.__bsetup:
            self.__lessBsetup=True
        else:
            self.__couldsbreak=True
        dt=bars.getDateTime()
        h=dt.hour
        m=dt.minute
        if(h==14 and m>50):
            if len(self.__longPos)> 0:
                for item in self.__longPos:
                    if item[0]._Position__exitOrder is None:
                        item[0].exitMarket()
            if len(self.__shortPos)>0:
                for item in self.__shortPos:
                    if item[0]._Position__exitOrder is None:
                        item[0].exitMarket()
            return
        self.testCon()
        if len(self.__longPos)> 0:
            if self.exitLongSignal():
               for item in self.__longPos:
                   if item[0]._Position__exitOrder is None:
                        item[0].exitMarket()

        elif len(self.__shortPos)>0:
            if self.exitShortSignal():
                for item in self.__shortPos:
                    if item[0]._Position__exitOrder is None:
                        item[0].exitMarket()

        if self.enterLongSignal():
            for i in range(self.enterLongSignal()):
                shares = int(self.getBroker().getEquity() * 0.2 / bars[self.__instrument].getPrice())
           # self.__longPos.
                pos=self.enterLong(self.__instrument, shares)
                #pos.exitLimit(bars[self.__instrument].getPrice()*0.99)
                self.__longPos.append([pos,0])
            self.__lastLongPos=self.__barNum
            #print('long'+str(shares))

        if self.enterShortSignal():
            for i in range(self.enterShortSignal()):
                shares = int(self.getBroker().getEquity() * 0.2 / bars[self.__instrument].getPrice())
                pos=self.enterShort(self.__instrument, shares)
                #pos.exitLimit(bars[self.__instrument].getPrice()*1.01)
                self.__shortPos.append([pos,0])
            self.__lastShortPos=self.__barNum

    def enterLongSignal (self) :
        if len(self.__longPos)>=2:
            if self.__lessBsetup:
                if self.__prices[-1]<self.__benter:
                    return 1
            if self.__couldbbreak:
                if self.__prices[-1]>self.__bbreak:
                    return 1


    def enterShortSignal(self) :
        if len(self.__shortPos)<=2:
            if self.__moreSsetup:
               if self.__prices[-1]<self.__senter:
                   return 1
            if self.__couldsbreak:
                if self.__prices[-1]<self.__sbreak:
                    return 1

    def exitLongSignal(self) :
        for item in self.__longPos:
            print(item[1])
            if item[0].getReturn()>item[1]:
                item[1]=item[0].getReturn()
            if item[1]-item[0].getReturn()>self.__p4:
                self.__couldbbreak=False
                return 1

    def exitShortSignal(self):
        for item in self.__shortPos:
            if item[0].getReturn()>item[1]:
                item[1]=item[0].getReturn()
            if item[1]-item[0].getReturn()>self.__p4:
                self.__couldsbreak=False
                return 1


    def onEnterCanceled(self, position):
        if len(self.__longPos)>0:
            if self.__longPos[-1] == position:
                del self.__longPos[-1]
                self.__lastLongPos==None
        if len(self.__shortPos)>0:
            if self.__shortPos[-1] == position:
                del self.__shortPos[-1]
                self.__lastShortPos==None

    def onEnterOK(self,position):
        pass

    def onExitOk(self, position):
        if isinstance(position,LongPosition):
            self.__longPos = []
        elif isinstance(position,ShortPosition):
            self.__shortPos = []
        else:
            assert(False)

    def onExitCanceled(self, position):
        position.exitMarket()

    def getParams(self):
        return (self.__bbreak,self.__ssetup,self.__senter,self.__benter,self.__bsetup,self.__sbreak)
Ejemplo n.º 14
0
class thrSMA(strategy.BacktestingStrategy):
    def __init__(self, feed, instrument, fast, slow, signal, up_cum):
        strategy.BacktestingStrategy.__init__(self, feed)
        self.__instrument = instrument
        self.getBroker().setFillStrategy(DefaultStrategy(None))
        self.getBroker().setCommission(TradePercentage(0.0008))
        self.__longPos = None
        self.__shortPos = None
        self.__prices = feed[instrument].getPriceDataSeries()
        self.__macd=macd.MACD(self.__prices,fast,slow,signal)
        self.__range=0
        self.__circ = int(up_cum)
        self.__position = SequenceDataSeries()
    def getPrice(self):
        return self.__prices

    def getMACD(self):
        return self.__macd

    def testCon(self):

        # record position
        #######################################################################
        if self.__longPos is not None:
            self.__position.append(1)
        if self.__shortPos is not None:
            self.__position.append(-1)
        elif self.__longPos is None and self.__shortPos is None:
            self.__position.append(0)


    def getTest(self):
        return self.__position

    def onEnterCanceled(self, position):
        if self.__longPos == position:
            self.__longPos = None
        elif self.__shortPos == position:
            self.__shortPos = None
        else:
            assert(False)

    def onEnterOK(self):
        pass

    def onExitOk(self, position):
        if self.__longPos == position:
            self.__longPos = None
        elif self.__shortPos == position:
            self.__shortPos = None
        else:
            assert(False)

    def onExitCanceled(self, position):
        position.exitMarket()
        
    def buyCon1(self):
        if self.__macd[-1] < -self.__range:
            #print(self.__macd[-1])
            return True
        else:
            return False

    def buyCon2(self):
        if  self.__macd[-1-self.__circ] is None:
            return False
        m1 = 0
        for i in range(self.__circ):
            if self.__macd[-i-1] > self.__macd[-i-2]:
                m1 += 1
        if m1 >= self.__circ:
            return True
        else:
            return False

    def exitLongCon1(self):
        if self.__macd[-1]>0:
            return True
        else:
            return False

    def exitLongCon2(self):
        if  self.__macd[-1-self.__circ] is None:
            return False
        m1 = 0
        for i in range(self.__circ):
            if self.__macd[-i-1] < self.__macd[-i-2]:
                m1 += 1
        if m1 >= self.__circ:
            return True
        else:
            return False

    def exitShortCon1(self):
        if self.__macd[-1]<0:
            return True
        else:
            return False

    def exitShortCon2(self):
        if  self.__macd[-1-self.__circ] is None:
            return False
        m1 = 0
        for i in range(self.__circ):
            if self.__macd[-i-1] > self.__macd[-i-2]:
                m1 += 1
        if m1 >= self.__circ:
            return True
        else:
            return False

    def sellCon1(self):
        if self.__macd[-1] >self.__range:
            return True
        else:
            return False

    def sellCon2(self):
        if  self.__macd[-1-self.__circ] is None:
            return False
        m1 = 0
        for i in range(self.__circ):
            if self.__macd[-i-1] < self.__macd[-i-2]:
                m1 += 1
        if m1 >= self.__circ:
            return True
        else:
            return False

    def onBars(self, bars):
        # If a position was not opened, check if we should enter a long position.
        if self.__macd[-1]is None:
            return
        self.__range=self.__prices[0]*0.004

        self.testCon()
        if self.__longPos is not None:

            if self.exitLongSignal():
                self.__longPos.exitMarket()

        elif self.__shortPos is not None:

            if self.exitShortSignal():
                self.__shortPos.exitMarket()

        elif self.__longPos is None and self.__shortPos is None:
            if self.enterLongSignal():
                shares = int(self.getBroker().getEquity() * 0.2 / bars[self.__instrument].getPrice())
                self.__longPos = self.enterLong(self.__instrument, shares)

            elif self.enterShortSignal():
                shares = int(self.getBroker().getEquity() * 0.2 / bars[self.__instrument].getPrice())
                self.__shortPos = self.enterShort(self.__instrument, shares)


    def enterLongSignal(self) :
        if self.buyCon1() and self.buyCon2():
            return True
        else:
            return False

    def enterShortSignal(self) :
        if self.sellCon1() and self.sellCon2():
            return True
        else:
            return False

    def exitLongSignal(self) :
        if self.exitLongCon1() and self.exitLongCon2() and not self.__longPos.exitActive():
            return True
        else:
            return False

    def exitShortSignal(self):
        if self.exitShortCon1() and self.exitShortCon2() and not self.__shortPos.exitActive():
            return True
        else:
            return False
Ejemplo n.º 15
0
 def __init__(self, feed, instrument, bollingerlength, numStdDev, closelength, ccMAlength, malength, space):
     strategy.BacktestingStrategy.__init__(self, feed)
     self.getBroker().setFillStrategy(DefaultStrategy(None))
     self.getBroker().setCommission(TradePercentage(0.002))
     self.__instrument = instrument
     self.__bollingerlength = int(bollingerlength)
     numStdDev = float(numStdDev) / 10
     self.__closelength = int(closelength)
     self.__ccMAlength = int(ccMAlength)
     self.__malength = int(malength)
     self.__longPos = None
     self.__shortPos = None
     self.__close = feed[instrument].getCloseDataSeries()
     self.__high = feed[instrument].getHighDataSeries()
     self.__low = feed[instrument].getLowDataSeries()
     self.__datetime = feed[instrument].getDateTimes()
     self.__bollinger = bollinger.BollingerBands(self.__close, self.__bollingerlength, int(numStdDev))
     self.__UpperBand = self.__bollinger.getUpperBand()
     self.__LowerBand = self.__bollinger.getLowerBand()
     self.__MA = SequenceDataSeries()
     self.__space = int(space)
     self.__enter = 0
     self.__enterLong1 = 0
     self.__enterLong2 = 0
     self.__enterShort1 = 0
     self.__enterShort2 = 0
     self.__exitLong1 = 0
     self.__exitLong2 = 0
     self.__exitShort1 = 0
     self.__exitShort1 = 0
     
     #for test
     #########################################################################
     self.__p = SequenceDataSeries()
     self.__filterCon = SequenceDataSeries()
     self.__ccMACon1 = SequenceDataSeries()
     self.__ccMACon2 = SequenceDataSeries()
     self.__enterCon = SequenceDataSeries()
     self.__enterLongCon1 = SequenceDataSeries()
     self.__enterLongCon2 = SequenceDataSeries()
     self.__enterShortCon1 = SequenceDataSeries()
     self.__enterShortCon2 = SequenceDataSeries()
     self.__exitLongCon1 = SequenceDataSeries()
     self.__exitLongCon2 = SequenceDataSeries()
     self.__exitShortCon1 = SequenceDataSeries()
     self.__exitShortCon2 = SequenceDataSeries()
Ejemplo n.º 16
0
class Bollinger_Bandit(strategy.BacktestingStrategy):
    def __init__(self, feed, instrument, bollingerlength, numStdDev, closelength, ccMAlength, malength, space):
        strategy.BacktestingStrategy.__init__(self, feed)
        self.getBroker().setFillStrategy(DefaultStrategy(None))
        self.getBroker().setCommission(TradePercentage(0.002))
        self.__instrument = instrument
        self.__bollingerlength = int(bollingerlength)
        numStdDev = float(numStdDev) / 10
        self.__closelength = int(closelength)
        self.__ccMAlength = int(ccMAlength)
        self.__malength = int(malength)
        self.__longPos = None
        self.__shortPos = None
        self.__close = feed[instrument].getCloseDataSeries()
        self.__high = feed[instrument].getHighDataSeries()
        self.__low = feed[instrument].getLowDataSeries()
        self.__datetime = feed[instrument].getDateTimes()
        self.__bollinger = bollinger.BollingerBands(self.__close, self.__bollingerlength, int(numStdDev))
        self.__UpperBand = self.__bollinger.getUpperBand()
        self.__LowerBand = self.__bollinger.getLowerBand()
        self.__MA = SequenceDataSeries()
        self.__space = int(space)
        self.__enter = 0
        self.__enterLong1 = 0
        self.__enterLong2 = 0
        self.__enterShort1 = 0
        self.__enterShort2 = 0
        self.__exitLong1 = 0
        self.__exitLong2 = 0
        self.__exitShort1 = 0
        self.__exitShort1 = 0
        
        #for test
        #########################################################################
        self.__p = SequenceDataSeries()
        self.__filterCon = SequenceDataSeries()
        self.__ccMACon1 = SequenceDataSeries()
        self.__ccMACon2 = SequenceDataSeries()
        self.__enterCon = SequenceDataSeries()
        self.__enterLongCon1 = SequenceDataSeries()
        self.__enterLongCon2 = SequenceDataSeries()
        self.__enterShortCon1 = SequenceDataSeries()
        self.__enterShortCon2 = SequenceDataSeries()
        self.__exitLongCon1 = SequenceDataSeries()
        self.__exitLongCon2 = SequenceDataSeries()
        self.__exitShortCon1 = SequenceDataSeries()
        self.__exitShortCon2 = SequenceDataSeries()
        ##########################################################################
              
    def getHigh(self):
        return self.__high
        
    def getLow(self):
        return self.__low
        
    def getClose(self):
        return self.__close
    
    def getBollinger(self):
        return self.__UpperBand, self.__LowerBand
        
    def getMA(self):
        return self.__MA
        
    def getDateTime(self):
        return self.__datetime
        
    def getPosition(self):
        return self.__p
        
    def getTest(self):
        return self.__filterCon, self.__ccMACon1, self.__ccMACon2, \
        self.__enterCon, self.__enterLongCon1, self.__enterLongCon2, self.__enterShortCon1, \
        self.__enterShortCon2, self.__exitLongCon1, self.__exitLongCon2, \
        self.__exitShortCon1, self.__exitShortCon2
              
    def onEnterCanceled(self, position):
        if self.__longPos == position:
            self.__longPos = None
        elif self.__shortPos == position:
            self.__shortPos = None
        else:
            assert(False)

    def onExitOk(self, position):
        if self.__longPos == position:
            self.__longPos = None
        elif self.__shortPos == position:
            self.__shortPos = None
        else:
            assert(False)

    def onBars(self, bars):
        # If a position was not opened, check if we should enter a long position.
        
        bar = bars[self.__instrument]
        
        # filter datetime    
        ###################################################################################        
        filterCon = len(self.__close) < max(self.__bollingerlength, self.__malength, self.__closelength)
        self.__filterCon.append(filterCon)
        
        if filterCon:
            return
     
        # record position      
        ####################################################################################
        if self.__longPos is not None and self.__shortPos is None:
            self.__p.append(1) 
        elif self.__longPos is None and self.__shortPos is not None:
            self.__p.append(-1)
        else:
            self.__p.append(0)   
  
        # calculate ccMA     
        ####################################################################################           
        ccMACon1 = self.__longPos is not None or self.__shortPos is not None
        ccMACon2 = self.__malength > self.__ccMAlength
        
        if ccMACon1 and ccMACon2: 
            self.__malength = self.__malength - 1
        elif not ccMACon1:
            self.__malength = 50

        self.__ccMA = np.mean(self.__close[-self.__malength:])
#        print self.__malength, self.__ccMA
        self.__MA.append(self.__ccMA)
        self.__ccMACon1.append(ccMACon1)
        self.__ccMACon2.append(ccMACon2)
        
        #open and close condition   
        ######################################################################################   
        self.__enterLong1 = (cross.cross_above(self.__high, self.__UpperBand) > 0)
        self.__enterLong2 = (bar.getClose() >= max(self.__close[-self.__closelength:]))
        self.__enter = ((self.__UpperBand[-1] - self.__LowerBand[-1]) / bar.getClose() > float(self.__space) / 1000)
#        print (self.__UpperBand[-1] - self.__LowerBand[-1]) / bar.getClose()
        self.__enterShort1 = cross.cross_below(self.__low, self.__LowerBand) > 0 
        self.__enterShort2 = bar.getClose() <= min(self.__close[-self.__closelength:])
        self.__exitLong1 = (bar.getClose() < self.__ccMA)
        self.__exitLong2 = (self.__ccMA < self.__UpperBand[-1])
        self.__exitShort1 = (bar.getClose() > self.__ccMA)
        self.__exitShort2 = (self.__ccMA > self.__LowerBand[-1])
        
        self.__enterCon.append(self.__enter)
        self.__enterLongCon1.append(self.__enterLong1)
        self.__enterLongCon2.append(self.__enterLong2)
        self.__enterShortCon1.append(self.__enterShort1)
        self.__enterShortCon2.append(self.__enterShort2)
        self.__exitLongCon1.append(self.__exitLong1)
        self.__exitLongCon2.append(self.__exitLong2)
        self.__exitShortCon1.append(self.__exitShort1)
        self.__exitShortCon2.append(self.__exitShort2)
  
        #open and close  
        #######################################################################################        
        if self.__longPos is not None:         
             if self.exitLongSignal():
                 self.__longPos.exitMarket()
#             if self.__shortPos is not None:
#                 print 11
#                 self.info("intend long close")
#                 print (self.__UpperBand[-1] - self.__LowerBand[-1]) / bar.getClose()
                 
        elif self.__shortPos is not None:
             if self.exitShortSignal():
                  self.__shortPos.exitMarket()
#                  self.info("intend short close")
#                  print (self.__UpperBand[-1] - self.__LowerBand[-1]) / bar.getClose()
                  
        else:
             if self.enterLongSignal():
                 shares = int(self.getBroker().getCash() * 0.2 / bars[self.__instrument].getPrice())
                 self.__longPos = self.enterLong(self.__instrument, shares)
#                 self.info("intend long open")
#                 print (self.__UpperBand[-1] - self.__LowerBand[-1]) / bar.getClose()
              
             elif self.enterShortSignal():
                 shares = int(self.getBroker().getCash() * 0.2 / bars[self.__instrument].getPrice())
                 self.__shortPos = self.enterShort(self.__instrument, shares)
#                 self.info("intend short open")
#                 print (self.__UpperBand[-1] - self.__LowerBand[-1]) / bar.getClose()
                 
    def enterLongSignal(self):
        if self.__enterLong1 and self.__enterLong2 and self.__enter:
            return True
    
    def enterShortSignal(self):
        if self.__enterShort1 and self.__enterShort2 and self.__enter:
            return True
            
    def exitLongSignal(self):
        if self.__exitLong1 and self.__exitLong2 and not self.__longPos.exitActive():
            return True
            
    def exitShortSignal(self):
        if self.__exitShort1 and self.__exitShort2 and not self.__shortPos.exitActive():
            return True 
Ejemplo n.º 17
0
class bollinger_band(strategy.BacktestingStrategy):
    def __init__(self, feed, instrument,longline,shortline,bollingerlength, numStdDev):
        strategy.BacktestingStrategy.__init__(self, feed)
        self.getBroker().setFillStrategy(DefaultStrategy(None))
        self.getBroker().setCommission(TradePercentage(0.001))
        self.__instrument = instrument
        self.__bollingerlength = int(bollingerlength)
        self.__close = feed[instrument].getMatchDataSeries()
        numStdDev = float(numStdDev) / 10
        self.__longPos = []
        self.__shortPos = []
        self.__macd=macd.MACD(self.__close,shortline,longline,10)
        self.__bollinger = bollinger.BollingerBands(self.__macd, self.__bollingerlength, int(numStdDev))
        self.__UpperBand = self.__bollinger.getUpperBand()
        self.__LowerBand = self.__bollinger.getLowerBand()

        self.__position = SequenceDataSeries()
        self.__circ=5
        self.__lastLongPos=None
        self.__lastShortPos=None
        self.__barNum=0
        self.__macdMin=[]
        self.__macdMax=[]
    def getPrice(self):
        return self.__prices

    def getMACD(self):
        return self.__macd

    def getBollingerBands(self):
        return self.__bollinger

    def testCon(self):
        # record position
        #######################################################################
        if len(self.__longPos) > 0:
            self.__position.append(len(self.__longPos))
        if len(self.__shortPos)>0 :
            #print(self.__shortPos.getShares())
            self.__position.append(-len(self.__shortPos))
        elif len(self.__longPos)==0 and len(self.__shortPos)==0:
            self.__position.append(0)
            #print(0)


    def getTest(self):
        return self.__position

    def onBars(self, bars):
        bar = bars[self.__instrument]
        lower = self.__bollinger.getLowerBand()[-1]
        upper = self.__bollinger.getUpperBand()[-1]
        self.__barNum=self.__barNum+1
       # print(self.getActivePositions())

        if self.__macd[-1] is None:
            #print (self.__macd[-1])
            return
        if self.__macd[-1]>self.__macdMax:
            self.__macdMax=self.__macd[-1]
        if self.__macd[-1]<=self.__macdMin:
            self.__macdMin=self.__macd[-1]
        if lower is None or upper is None:
            return
        self.testCon()
        if len(self.__longPos)> 0:

            if self.exitLongSignal():
               for pos in self.__longPos:
                   pos.exitMarket()

        elif len(self.__shortPos)>0:

            if self.exitShortSignal():
                for pos in self.__shortPos:
                   pos.exitMarket()

        if self.enterLongSignal():
            for i in range(self.enterLongSignal()):
                shares = int(self.getBroker().getEquity() * 0.2 / bars[self.__instrument].getMatch())
           # self.__longPos.
                self.__longPos.append(self.enterLong(self.__instrument, shares))
            self.__lastLongPos=self.__barNum
            #print('long'+str(shares))

        elif self.enterShortSignal():
            for i in range(self.enterShortSignal()):
                shares = int(self.getBroker().getEquity() * 0.2 / bars[self.__instrument].getMatch())
                self.__shortPos.append(self.enterShort(self.__instrument, shares))
            self.__lastShortPos=self.__barNum
            #print('short'+str(shares))

    def enterLongSignal (self) :
        if self.__lastLongPos is not None:
            if self.__barNum-self.__lastLongPos<60:
                return 0
        if self.__UpperBand[-1-self.__circ] is None:
            return 0
        m1 = 0
        for i in range(self.__circ):
            if self.__macd[-i-1] <= self.__LowerBand[-i-2]:
                m1 += 1
        if m1 >= self.__circ-1 and cross.cross_above(self.__macd,self.__LowerBand)>0:
            if self.__macd[-1]>0:
                return 0
            else:
                if self.__macdMin==self.__macd[-1] :
                    return 2
                else:
                    return 1
        else:
            return 0

    def enterShortSignal(self) :
        if self.__lastShortPos is not None:
            if self.__barNum-self.__lastShortPos<60:
                return 0
        if self.__UpperBand[-1-self.__circ] is None:
            return 0
        m1 = 0
        for i in range(self.__circ):
            if self.__macd[-i-1] >= self.__UpperBand[-i-2]:
                m1 += 1
        if m1 >= self.__circ-1 and cross.cross_below(self.__macd,self.__UpperBand)>0:
            if self.__macd[-1]<0:
                return 0
            else:
                if self.__macdMax==self.__macd[-1]:
                    return 2
                else:
                    return 1
        else:
            return 0

    def exitLongSignal(self) :
        if self.__UpperBand[-1-self.__circ] is None:
            return False
        m1 = 0
        for i in range(self.__circ):
            if self.__macd[-i-1] >= self.__UpperBand[-i-2]:
                m1 += 1
        if m1 >= self.__circ-1 and cross.cross_below(self.__macd,self.__UpperBand)>0:
            return True
        elif self.__macd[-1]>=self.__UpperBand[-1] and self.__macdMax==self.__macd[-1]:
            return True
        elif self.__macd[-1]*1.001>=self.__UpperBand[-1] and self.__macd[-1]>-0.1:
            return True
        else:
            return False

    def exitShortSignal(self):
        if self.__UpperBand[-1-self.__circ] is None:
            return False
        m1 = 0
        for i in range(self.__circ):
            if self.__macd[-i-1] <= self.__LowerBand[-i-2]:
                m1 += 1
        if m1 >= self.__circ-1 and cross.cross_above(self.__macd,self.__LowerBand)>0:
            return True
        elif self.__macd[-1]<=self.__LowerBand[-1] and self.__macdMin==self.__macd[-1]:
            return True
        elif self.__macd[-1]<=self.__LowerBand[-1]*1.001 and self.__macd[-1]<0.11:
            return True
        else:
            return False


    def onEnterCanceled(self, position):
        if self.__longPos[-1] == position:
            del self.__longPos[-1]
            self.__lastLongPos==None
        elif self.__shortPos[-1] == position:
            del self.__shortPos[-1]
            self.__lastShortPos==None
        else:
            assert(False)

    def onEnterOK(self,position):
        pass

    def onExitOk(self, position):
        if isinstance(position,LongPosition):
            self.__longPos = []
        elif isinstance(position,ShortPosition):
            self.__shortPos = []
        else:
            assert(False)

    def onExitCanceled(self, position):
        position.exitMarket()
Ejemplo n.º 18
0
class fourSMA(strategy.BacktestingStrategy):
    def __init__(self, feed, instrument, mall, mals, masl, mass):
        strategy.BacktestingStrategy.__init__(self, feed)
        self.getBroker().setFillStrategy(DefaultStrategy(None))
        self.getBroker().setCommission(TradePercentage(0.001))
        self.__instrument = instrument
        self.__close = feed[instrument].getCloseDataSeries()
        self.__longPos = None
        self.__shortPos = None
        self.__mall = ma.SMA(self.__close, int(mall))
        self.__mals = ma.SMA(self.__close, int(mals))
        self.__masl = ma.SMA(self.__close, int(masl))
        self.__mass = ma.SMA(self.__close, int(mass))

        self.__position = SequenceDataSeries()

    def getPrice(self):
        return self.__prices

    def getSMA(self):
        return self.__mall, self.__mals, self.__mass, self.__masl

    def testCon(self):

        # record position
        #######################################################################
        if self.__longPos is not None:
            self.__position.append(1)
        if self.__shortPos is not None:
            self.__position.append(-1)
        elif self.__longPos is None and self.__shortPos is None:
            self.__position.append(0)

    def getTest(self):
        return self.__position

    def onEnterCanceled(self, position):
        if self.__longPos == position:
            self.__longPos = None
        elif self.__shortPos == position:
            self.__shortPos = None
        else:
            assert (False)

    def onExitOk(self, position):
        if self.__longPos == position:
            self.__longPos = None
        elif self.__shortPos == position:
            self.__shortPos = None
        else:
            assert (False)

    def onExitCanceled(self, position):
        position.exitMarket()

    def onEnterOk(self, position):
        pass

    def onBars(self, bars):

        bar = bars[self.__instrument]

        if self.__mall[-1] is None:
            return

        self.testCon()

        if self.__longPos is not None:

            if self.exitLongSignal():
                self.__longPos.exitMarket()

        elif self.__shortPos is not None:

            if self.exitShortSignal():
                self.__shortPos.exitMarket()

        elif self.__longPos is None and self.__shortPos is None:
            if self.enterLongSignal():
                shares = int(self.getBroker().getEquity() * 0.2 /
                             bar.getPrice())
                self.__longPos = self.enterLong(self.__instrument, shares)

            elif self.enterShortSignal():
                shares = int(self.getBroker().getEquity() * 0.2 /
                             bar.getPrice())
                self.__shortPos = self.enterShort(self.__instrument, shares)

    def enterLongSignal(self):
        if cross.cross_above(self.__mals, self.__mall) > 0:
            return True

    def enterShortSignal(self):
        if cross.cross_below(self.__mals, self.__mall) > 0:
            return True

    def exitLongSignal(self):
        if cross.cross_below(
                self.__mass,
                self.__masl) > 0 and not self.__longPos.exitActive():
            return True

    def exitShortSignal(self):
        if cross.cross_above(
                self.__mass,
                self.__masl) > 0 and not self.__shortPos.exitActive():
            return True
Ejemplo n.º 19
0
class fourSMA(strategy.BacktestingStrategy):
    def __init__(self, feed, instrument, mall, mals, masl, mass):
        strategy.BacktestingStrategy.__init__(self, feed)
        self.getBroker().setFillStrategy(DefaultStrategy(None))
        self.getBroker().setCommission(TradePercentage(0.001))
        self.__instrument = instrument
        self.__close = feed[instrument].getCloseDataSeries()
        self.__longPos = None
        self.__shortPos = None
        self.__mall = ma.SMA(self.__close, int(mall))
        self.__mals = ma.SMA(self.__close, int(mals))
        self.__masl = ma.SMA(self.__close, int(masl))
        self.__mass = ma.SMA(self.__close, int(mass))

        
        self.__position = SequenceDataSeries()
        
    def getPrice(self):
        return self.__prices

    def getSMA(self):
        return self.__mall,self.__mals,self.__mass,self.__masl

    def testCon(self):
        
        # record position      
        #######################################################################
        if self.__longPos is not None:
            self.__position.append(1)
        if self.__shortPos is not None:
            self.__position.append(-1)
        elif self.__longPos is None and self.__shortPos is None:
            self.__position.append(0)
        
        
    def getTest(self):
        return self.__position
    
    def onEnterCanceled(self, position):
        if self.__longPos == position:
            self.__longPos = None
        elif self.__shortPos == position:
            self.__shortPos = None
        else:
            assert(False)

    def onExitOk(self, position):
        if self.__longPos == position:
            self.__longPos = None
        elif self.__shortPos == position:
            self.__shortPos = None
        else:
            assert(False)

    def onExitCanceled(self, position):
        position.exitMarket()
            
    def onEnterOk(self, position):
        pass

    def onBars(self, bars):

        bar = bars[self.__instrument]
        
        if self.__mall[-1] is None:
            return
            
        self.testCon()            
            
        if self.__longPos is not None:

            if self.exitLongSignal():
                self.__longPos.exitMarket()
           
        elif self.__shortPos is not None:
            
            if self.exitShortSignal():
                self.__shortPos.exitMarket()

        elif self.__longPos is None and self.__shortPos is None:
            if self.enterLongSignal():
                shares = int(self.getBroker().getEquity() * 0.2 / bar.getPrice())
                self.__longPos = self.enterLong(self.__instrument, shares)
                
            elif self.enterShortSignal():
                shares = int(self.getBroker().getEquity() * 0.2 / bar.getPrice())
                self.__shortPos = self.enterShort(self.__instrument, shares)


    def enterLongSignal(self) :
        if cross.cross_above(self.__mals, self.__mall) > 0:
            return True
    
    def enterShortSignal(self) :
        if cross.cross_below(self.__mals, self.__mall) > 0:
            return True
            
    def exitLongSignal(self) :
        if cross.cross_below(self.__mass, self.__masl) > 0 and not self.__longPos.exitActive():
            return True
            
    def exitShortSignal(self):
        if cross.cross_above(self.__mass, self.__masl) > 0 and not self.__shortPos.exitActive():
            return True
Ejemplo n.º 20
0
class midBaseStrategy(strategy.BacktestingStrategy):
    def getFeeds(self,timeFrom=None,timeTo=None):
        import os,sys        
        xpower = os.path.abspath(os.path.join(os.path.dirname(__file__),os.pardir,os.pardir,os.pardir,'midProjects','histdata'))
        sys.path.append(xpower)
        
        import dataCenter as dataCenter            
        self.dataCenter = dataCenter.dataCenter()           
        feeds = self.dataCenter.getFeedsForPAT(dataProvider = self.dataProvider,storageType = self.storageType,instruments = self.instruments,
                                               period=self.period,timeTo = timeTo,timeFrom=timeFrom)        
        return feeds    
    
    def getFeedNew(self,timeFrom=None,timeTo=None):
        '''mid should not be named the same with base class'''
        import os,sys        
        xpower = os.path.abspath(os.path.join(os.path.dirname(__file__),os.pardir,os.pardir,os.pardir,'midProjects','histdata'))
        sys.path.append(xpower)
        
        import dataCenter as dataCenter            
        self.dataCenter = dataCenter.dataCenter()           
        feed = self.dataCenter.getFeedForPAT(dataProvider = self.dataProvider,storageType = self.storageType,instruments = self.instruments,
                                               period=self.period,timeTo = timeTo,timeFrom=timeFrom)        
        return feed      
    
    
    
    def initEa(self,timeFrom=None,timeTo=None):
        self.results = {}
        feed = self.getFeedNew(timeFrom = timeFrom,timeTo = timeTo)
        self.mid_DEFAULT_MAX_LEN = 10 * DEFAULT_MAX_LEN
        mid_DEFAULT_MAX_LEN = self.mid_DEFAULT_MAX_LEN
        
        #mid set init cash
        cash_or_brk = 1000000
        volumeLimit = 0.5       #mid used to calculate available volume for an order: availableVolume = volumeLeft * volumeLimit
        #mid set fillstrategy
        fillStrategy = fillstrategy.DefaultStrategy(volumeLimit = volumeLimit)
        
        broker = backtesting.Broker(cash_or_brk, feed)
        broker.setFillStrategy(fillStrategy)
        #mid init base
        strategy.BacktestingStrategy.__init__(self, feed,broker)
        
        #mid 计算ma将使用当天的收盘价格计算
        #mid 1)
        self.closePrices = {}
        self.longPosition = {}
        self.shortPosition = {}
        self.buySignal = {}
        self.sellSignal = {}        
        self.timeFrom = timeFrom
        self.timeTo = timeTo        
        #mid follow vars will be used only this class
        self.__portfolio_value = SequenceDataSeries(maxLen = mid_DEFAULT_MAX_LEN)
        self.__available_cash  = SequenceDataSeries(maxLen = mid_DEFAULT_MAX_LEN)
        
        self.__exitBar_position_pnl    = {}
        
        self.__curLongPositionCost = {}         #mid init position value
        self.__curShortPositionCost = {}        #mid init position value
        
        self.__position_volume = {}         #mid 当前持有头寸数量
        self.__position_cost = {}           #mid 当前持有头寸开仓成本
        self.__position_pnl = {}            #mid 当前持有头寸价值
        self.__position_cumulativePNL = {}  #mid 当前 symbol 持有头寸cumulative pnl 价值
        self.__buy = {}
        self.__sell = {}    
        
        for instrument in self.instruments:
            dataSeries = feed[instrument]
            
            
            dataSeries.setMaxLen(mid_DEFAULT_MAX_LEN)       
            closeSeries = dataSeries.getCloseDataSeries()
            #mid 2)
            prices = closeSeries
            prices.setMaxLen(mid_DEFAULT_MAX_LEN)        
            
            #mid follow vars will be used in subclass
            self.closePrices[instrument] = prices
            self.longPosition[instrument] = None
            self.shortPosition[instrument] = None
            self.buySignal[instrument] = False
            self.sellSignal[instrument] = False

            #mid follow vars will be used only this class
            self.__curLongPositionCost[instrument] = 0                                                      #mid init position value
            self.__curShortPositionCost[instrument] = 0   
            self.__exitBar_position_pnl[instrument] = None
            #mid init position value
            self.__position_volume[instrument] = SequenceDataSeries(maxLen = mid_DEFAULT_MAX_LEN)       #mid 当前持有头寸数量
            self.__position_cost[instrument] = SequenceDataSeries(maxLen = mid_DEFAULT_MAX_LEN)         #mid 当前持有头寸开仓成本
            self.__position_pnl[instrument] = SequenceDataSeries(maxLen = mid_DEFAULT_MAX_LEN)          #mid 当前持有头寸价值
            self.__position_cumulativePNL[instrument] = SequenceDataSeries(maxLen = mid_DEFAULT_MAX_LEN)
            self.__buy[instrument] = SequenceDataSeries(maxLen = mid_DEFAULT_MAX_LEN)
            self.__sell[instrument] = SequenceDataSeries(maxLen = mid_DEFAULT_MAX_LEN) 
    def getAssetStructure(self):
        #mid --------------------------------
        #mid 当前账户资产结构如下方式获取
        #mid Long 和 Short不会同时存在
        #mid 在开仓前,若有反向持仓,则此过程查询并输出已持有的反向持仓
        broker = self.getBroker()
        portfolio_value = broker.getEquity()
        cash = broker.getCash()
        if self.shortPosition is not None or self.longPosition is not None:
            bars = self.getFeed().getCurrentBars()  

            positions = broker.getPositions()

            positionsOpenValue = {}
            positionsCloseValue = {}
            for key,value in positions.items():
                print "key:"+key+",value:"+str(value)
                bar = bars.getBar(key)
                openPrice = bar.getOpen() 
                closePrice = bar.getClose()
                share = broker.getShares(key)
                positionsOpenValue[key] = openPrice*share
                positionsCloseValue[key] = closePrice*share

            print 
            print 'current bar asset structure'
            print 'open cash %2.f.' % (cash)
            for key,value in positionsOpenValue.items():
                print "key:"+key+",value:"+str(value)
            print 'close cash %2.f.' % (cash)
            for key,value in positionsCloseValue.items():
                print "key:"+key+",value:"+str(value)    
            print 'portfolio:%2.f' % (portfolio_value)

            return portfolio_value,cash,sum(positionsCloseValue.values())
        return portfolio_value,cash,0
    def sampleSub01(self,instrument):
        """mid not called anywhere
        because of open price gap,method below is not right.
        """
        broker = self.getBroker()
        a = broker.getEquity()
        b = self.getResult()
        
        lastOpenPrice  = None
        lastClosePrice = None
        bar = self.getFeed().getLastBar(instrument)
        if bar is not None:
            lastOpenPrice = bar.getOpen()
            lastClosePrice = bar.getClose() 
             #lastPrice = self.getLastPrice(instrument)  
           
            pnl = (lastClosePrice - lastOpenPrice) * share
        else:
            pnl = 0 #mid instrument is dislisted.
        if(len(self.__position_cumulativePNL[instrument])>0):
            lastCumulativePNL = self.__position_cumulativePNL[instrument][-1]
        else:
            lastCumulativePNL = 0        
            
    def recordAccount(self):
        # record position      
        #######################################################################
        broker = self.getBroker()
        curTime = self.getCurrentDateTime()
        currentTime = self.getCurrentDateTime()
        cash = broker.getCash(includeShort=False)
        portfolio_value = broker.getEquity()               #mid 按close价格计算的权益
        
        print 
        self.info("onBars().recordAccount().Current time:%s"%(str(currentTime)))
        self.info("onBars().recordAccount().----portfolio value: %.2f" % (portfolio_value))
        self.info("onBars().recordAccount().----cash in portfolio: %.2f" % (cash))
        
        self.__portfolio_value.appendWithDateTime(currentTime,portfolio_value) 
        self.__available_cash.appendWithDateTime(currentTime,cash) 
        totalCumulativePNL = 0
        
        
        time = self.getCurrentDateTime()
        if(time == dt.datetime(2010,12,21,0,0)):
            a = 8   
          
        for instrument in self.instruments:

            share = broker.getShares(instrument)                #mid position is dict of share
            lastClosePrice = self.getLastPrice(instrument)  

            if(lastClosePrice is None):
                continue
            position_value = lastClosePrice*share
            if(share > 0):
                position_cost = self.__curLongPositionCost[instrument] 
            elif(share < 0):
                position_cost = self.__curShortPositionCost[instrument]
            else:
                position_cost = 0
                
            position_pnl = (position_value - position_cost)
            
         
            

            self.__position_volume[instrument].appendWithDateTime(currentTime,abs(share))  
            self.__position_cost[instrument].appendWithDateTime(currentTime,abs(position_cost))
            self.__position_pnl[instrument].appendWithDateTime(currentTime,position_pnl)
            self.__buy[instrument].appendWithDateTime(currentTime,self.buySignal[instrument])              
            self.__sell[instrument].appendWithDateTime(currentTime,self.sellSignal[instrument])        
            
            if(share != 0):
                if(len(self.__position_pnl[instrument])>2):
                    currentPositionPnl = self.__position_pnl[instrument][-1]
                    lastPositionPnl = self.__position_pnl[instrument][-2]
                    currentBarPnl = currentPositionPnl - lastPositionPnl
                else:
                    currentBarPnl = self.__position_pnl[instrument][-1]
            else:              
                currentBarPnl = 0  
                
            if(self.__exitBar_position_pnl[instrument] is not None):
                """mid
                如果当前bar有某个position在open price被closed掉,则当前bar的position_pnl是0.
                在当前bar的openprice和上一bar的closeprice之间没有gap时,这个算法是合理的,但是,gap往往是存在的,
                所以,据此计算的barPnl在exitbar上会有gap导致的误差
                在此特别处理exitbar                
                """
                currentExitedPositionPnl = self.__exitBar_position_pnl[instrument]
                lastPositionPnl = self.__position_pnl[instrument][-2]
                currentBarExitedPnl = currentExitedPositionPnl - lastPositionPnl                
                self.__exitBar_position_pnl[instrument] = None   
                currentBarPnl = currentBarPnl + currentBarExitedPnl
            if(len(self.__position_cumulativePNL[instrument])>0):
                lastCumulativePNL = self.__position_cumulativePNL[instrument][-1]
                cumulativePNL = lastCumulativePNL + currentBarPnl
            else:
                cumulativePNL = currentBarPnl   

            self.__position_cumulativePNL[instrument].appendWithDateTime(currentTime,cumulativePNL)  

            if(True):
                self.info("onBars().recordAccount().--------mid current bar PNL: %.3f" %(currentBarPnl))
                
                self.info("onBars().recordAccount().--------%s" % (instrument))
                self.info("onBars().recordAccount().--------share:%.3f" % (share))
                self.info("onBars().recordAccount().--------lastClosePrice:%.3f" % (lastClosePrice))
                
                self.info("onBars().recordAccount().--------mid calculated position value: %.3f" %(position_value))
                self.info("onBars().recordAccount().--------mid position cost: %.3f" %(position_cost))
               
                self.info("onBars().recordAccount().--------mid calculated postion pnl: %.3f" %(position_pnl))

                self.info("onBars().recordAccount().--------mid CumulativePNL: %.3f" %(cumulativePNL))
            totalCumulativePNL = totalCumulativePNL + cumulativePNL

        if(abs(1000000 - (portfolio_value - totalCumulativePNL))>0.00000001):
            self.info("onBars().recordAccount().--------mid initCash: %.3f" %(portfolio_value - totalCumulativePNL))
            a = 8            
    def getPortfolioValue(self):
        return self.__portfolio_value
    def getAvailableCash(self):
        return self.__available_cash
    def getCurInstrument(self):
        return self.curInstrument
    def getPositionValue(self,instrument):
        return self.__position_cumulativePNL[instrument]
    def getPositionVolume(self,instrument):
        return self.__position_volume[instrument] 
    def getPositionCost(self,instrument):
        return self.__position_cost[instrument]
    def getPositionPnl(self,instrument):
        return self.__position_pnl[instrument]

    def getBuy(self,instrument):
        return self.__buy[instrument]
    def getSell(self,instrument):
        return self.__sell[instrument]
    def onEnterOk(self, position):
        '''mid
        由于getEquity()返回的是依据当日close价格计算出来的权益
        所以,这个值不能作为持仓成本
        持仓成本需要以onEnterOk时bar的open价格计算
        由于经常有跳开现象,所以依据bar(n-1).close发出的market order,
        在bar(n).open执行时通常会有gap出现,表现在position_cost图上时就是持有成本离计划成本会有跳口,
        '''
        print 
        currentTime = self.getCurrentDateTime()
        execInfo = position.getEntryOrder().getExecutionInfo()   
        self.info("onEnterOK().ExecutionInfo.Current time: %s"%(execInfo.getDateTime()))
        
        
        
        #mid 1)record the position cost
        instrument = position.getInstrument()
        feed = self.getFeed()
        bars = feed.getCurrentBars()
        bar = bars.getBar(instrument)
        openPrice = bar.getOpen()   
        closePrice = self.getLastPrice(instrument) #mid lastPrice == closePrice
        if(False):
            '''mid long+short
            计算获取instrument的净头寸
            long = 10,short = -5
            则position = 5
            '''
            share = self.getBroker().getShares(instrument)
        else:
            '''mid only long or short
            计算当前position代表的头寸
            如果当前为long,则求出long头寸并不考虑short
            long = 10,short = -5
            若position == long
            则此处求出 position=10
             '''
            share = position.getShares()
            
        if isinstance(position, strategy.position.LongPosition):
            self.__curLongPositionCost[instrument] = openPrice*share
            
        if isinstance(position, strategy.position.ShortPosition):
            self.__curShortPositionCost[instrument] = openPrice*share

        #mid 1.1) a example to show price gap
        planedCost = 100000
        if(planedCost - abs(self.__curLongPositionCost[instrument]) > 1000):
            '''mid 
            跳开gap导致的n-1 day计划持仓金额和n day实际持仓金额之间的差额
            以n-1day的close价格为依据计算share to open
            n-1 day close = 10
            n day open = 9.8

            如果是要open 100000元
            则原计划持有数量shares = 100000/10 = 10000
            
            实际持有成本 = 计划持有数量 × 实际open价格
               		= 10000 × 9.8 = 980000'''
            pass
                
        #mid 2)log account info after enterOKed.
        execInfo = position.getEntryOrder().getExecutionInfo()   
        portfolio = self.getResult()
        cash = self.getBroker().getCash()     
        self.info("onEnterOk().symbol:%s" % (instrument))        
        self.info("onEnterOk().current available cash: %.2f,portfolio: %.2f." % (cash,portfolio))
        if isinstance(position, strategy.position.LongPosition):
            print str(self.__curLongPositionCost[instrument])+'='+str(share)+'*'+str(openPrice)
            self.info("onEnterOK().ExecutionInfo: %s,OPEN LONG %.2f at $%.2f" 
                      % (execInfo.getDateTime(),execInfo.getQuantity(),execInfo.getPrice())) 
        elif isinstance(position, strategy.position.ShortPosition):
            print str(self.__curShortPositionCost[instrument])+'='+str(share)+'*'+str(openPrice)
            self.info("onEnterOK().ExecutionInfo: %s,OPEN SHORT %.2f at $%.2f" 
                      % (execInfo.getDateTime(),execInfo.getQuantity(),execInfo.getPrice()))     



    def onEnterCanceled(self, position):
        instrument = position.getInstrument()
        
        self.info("onEnterCanceled().current available cash: %.2f." % (self.getBroker().getCash()))
        if isinstance(position, strategy.position.LongPosition):
            self.longPosition[instrument] = None
            self.info("onEnterCanceled().OPEN LONG cancled.")                                
        elif isinstance(position, strategy.position.ShortPosition):
            self.shortPosition[instrument] = None
            self.info("onEnterCanceled().OPEN SHORT cancled.")
    def onExitOk(self, position):        
        execInfo = position.getExitOrder().getExecutionInfo()     
        portfolio = self.getResult()
        cash = self.getBroker().getCash()
        instrument = position.getInstrument()
        
        print 
        currentTime = self.getCurrentDateTime()
        self.info("onExitOk().ExecutionInfo.Current time: %s"%(execInfo.getDateTime()))
        
        self.info("onExitOk().instrument:%s." % (instrument))        
        self.info("onExitOk().current available cash: %.2f,portfolio: %.2f." % (cash,portfolio))

        
        
        exQuantity  = execInfo.getQuantity()
        exPrice     = execInfo.getPrice()  
        exAmount    = exQuantity * exPrice
        #self.sampleSub01(instrument)
        if isinstance(position, strategy.position.LongPosition):
            positionCost = self.__curLongPositionCost[instrument]
            self.__exitBar_position_pnl[instrument] = exAmount - positionCost
            
            
            
            self.longPosition[instrument] = None
            self.__curLongPositionCost[instrument] = 0
            self.info("onExitOk().ExecutionInfo: %s,CLOSE LONG %.2f at $%.2f" 
                      % (execInfo.getDateTime(),execInfo.getQuantity(),execInfo.getPrice()))                    
        elif isinstance(position, strategy.position.ShortPosition):
            positionCost = self.__curShortPositionCost[instrument]
            self.__exitBar_position_pnl[instrument] = -exAmount - positionCost
            
            self.shortPosition[instrument] = None
            self.__curShortPositionCost[instrument] = 0           
            self.info("onExitOk().ExecutionInfo: %s,CLOSE SHORT %.2f at $%.2f" 
                      % (execInfo.getDateTime(),execInfo.getQuantity(),execInfo.getPrice()))                    
    def onExitCanceled(self, position):
        # If the exit was canceled, re-submit it.
        if isinstance(position, strategy.position.LongPosition):
            self.longPosition[instrument] = None
        elif isinstance(position, strategy.position.ShortPosition):
            self.shortPosition[instrument] = None
    def logInfo(self,bars = None):
        pLong,pShort = 0,0
        if(self.longPosition is not None):
            pLong = self.longPosition.getShares()
        if(self.shortPosition is not None):
            pShort = self.shortPosition.getShares()


        bar = bars[self.instrument]
        pOpen = bar.getOpen()
        pHigh = bar.getHigh()
        pLow = bar.getLow()
        pClose = bar.getClose()
        pPrice = bar.getPrice()

        self.info('logInfo().price:%.3f,open:%.2f,high:%.2f,low:%.2f,close:%.2f'%(pPrice,pOpen,pHigh,pLow,pClose))
        #self.info('long:%.2f#short:%.2f'%(pLong,pShort)) 
    def closePosition(self):        
        for instrument in self.instruments:
            if(self.longPosition[instrument] is not None and self.sellSignal[instrument] == True
               and not self.longPosition[instrument].exitActive()):
                print
                self.info("onBars().closePosition(), instrument:%s"  % (instrument))                                                    
                self.info("onBars().closePosition(), LONG POSITION to close %.2f"  % (self.longPosition[instrument].getShares()))                                    
                self.longPosition[instrument].exitMarket()
            if(self.shortPosition[instrument] is not None and self.buySignal[instrument] == True
               and not self.shortPosition[instrument].exitActive()):
                print
                self.info("onBars().closePosition(), instrument:%s"  % (instrument))                                                                    
                self.info("onBars().closePosition(), SHORT POSITION to close %.2f"  % (self.shortPosition[instrument].getShares()))  
                self.shortPosition[instrument].exitMarket()          
    def openPosition(self):
        '''mid
        此处是onBars,这个和zipline的概念完全不同
        zipline中,需要覆写的是handle_data,这个东西是个tick概念,所以没有OHLC的,只是个price
        PAT中,每次onBars,都会传入一个newbar的OHLC,此时,要如何按这个OHLC决策,全由你
        依据OHLC做完决策后,可以发送交易指令:
        * Order.Type.MARKET
        * Order.Type.LIMIT
        * Order.Type.STOP
        * Order.Type.STOP_LIMIT
        1.市价单,依据下一个bar的openPrice执行命令:
            self.enterLong()
        2.限价单
        3.止损单市价单
        4.止损限价单

        当前似乎没有止盈单

        在均线策略中,应该在每个newbar到来时,按closePrice的均线计算指标值,然后发送市价单
        1.每个newbar按close价格计算指标,并在下一个bar按open成交
        2.每个newbar按open价格计算指标,并在此newbar按open成交
        以上1,2的计算逻辑是一致的。如果当前bar的close和下一个bar的open相差无几时,两种算法的回测结果也应相差无几
        '''         
        # mid 2)open
        if(self.shortAllowed):
            for instrument in self.instruments:
                self.curInstrument = instrument
                if(self.sellSignal[instrument] == True):
                    # Enter a buy market order. The order is good till canceled.
                    bar = self.getFeed().getLastBar(instrument)
                    volume = 0
                    lastClose = 0
                    if bar is not None:
                        volume = bar.getVolume() 
                        lastClose = bar.getClose()
                    shares = self.money.getShares(strat = self)
                    print
                    self.info("onBars().openPosition(), instrument %s" % (instrument))   
                    self.info("onBars().openPosition(), SHORT POSITION to open %.2f" % (shares))   
                    self.info("onBars().openPosition(), lastClose: %.2f,%.2f" % (self.getLastPrice(instrument),lastClose))  
                    self.info("onBars().openPosition(), need amount: %.2f" % (shares*self.getLastPrice(instrument)))  
                    self.info("onBars().openPosition(), available amount: %.2f." % (self.getBroker().getCash() ))                  
                    self.info("onBars().openPosition(), available volume: %.2f." % (volume))                  
                    self.shortPosition[instrument] = self.enterShort(instrument, shares, True)            
            
        if(self.longAllowed):
            for instrument in self.instruments:
                self.curInstrument = instrument
                if(self.buySignal[instrument] == True):
                    shares = self.money.getShares(strat = self)              
                    print
                    self.info("onBars().openPosition(), instrument %s" % (instrument))   
                    self.info("onBars().openPosition(), LONG POSITION to open %.2f" % (shares) )                
                    self.info("onBars().openPosition(), need amount: %.2f." % (shares*self.getLastPrice(instrument)))                  
                    self.info("onBars().openPosition(), available amount: %.2f." % (self.getBroker().getCash() ))                                    
                    self.longPosition[instrument] = self.enterLong(instrument, shares, True)
    def __analiseEachSymbol(self,instrument):
        dataForCandle = self.dataCenter.getCandleData(dataProvider = self.dataProvider,dataStorage = self.storageType,dataPeriod = self.period,
                                                 symbol = instrument,dateStart=self.timeFrom,dateEnd = self.timeTo)     
        self.analyzer.analyseEachSymbol(self.results[instrument],dataForCandle,InKLine = self.InKLine)
        
    def __analiseSummary(self):
        dataProvider = self.benchDataProvider
        instrument = self.benchSymbol
        dataForCandle = self.dataCenter.getCandleData(dataProvider = dataProvider,dataStorage = self.storageType,dataPeriod = self.period,
                                                 symbol = instrument,dateStart=self.timeFrom,dateEnd = self.timeTo)          
        self.analyzer.analyseSummary(self.result,dataForCandle)
    def run(self,timeFrom = None,timeTo = None):
        self.initEa(timeFrom = timeFrom,timeTo = timeTo)
        
        self.initIndicators()
        #self.strat.setUseAdjustedValues(False)
        
        self.initAnalyzer()      
        
        strategy.BacktestingStrategy.run(self)
        
        
        for instrument in self.instruments:
            buy = self.getBuy(instrument)
            sell = self.getSell(instrument)

            position_value = self.getPositionValue(instrument)
            position_volume = self.getPositionVolume(instrument)
            position_cost = self.getPositionCost(instrument)
            position_pnl = self.getPositionPnl(instrument)

            self.results[instrument] = pd.DataFrame({'position_volume':list(position_volume),'position_cost':list(position_cost),
                               'position_pnl':list(position_pnl),
                               'buy':list(buy),'sell':list(sell),'position_value':list(position_value)},
                              columns=['position_volume','position_cost','position_pnl','buy','sell','position_value'],
                              index=position_volume.getDateTimes())
            self.addIndicators(instrument)
            #------------------------------------
    
            if(self.toPlotEachSymbol):
                self.__analiseEachSymbol(instrument)
            
        if(self.toPlotSummary):
            portfolio_value = self.getPortfolioValue()
            available_cash = self.getAvailableCash()
            
            self.result = pd.DataFrame({'available_cash':list(available_cash),'portfolio_value':list(portfolio_value)},
                              columns=['available_cash','portfolio_value'],
                              index=portfolio_value.getDateTimes())
            self.__analiseSummary()
        return self.results            
    #mid from ea
    #----------------------------------------------------------------------
    def summary(self):
        return "from %s to %s:returns:%.2f%%,sharpe:%.2f,MaxDrawdown:%.2f%%,Longest drawdown duration:(%s)" % (str(self.timeFrom),str(self.timeTo),
                                                                                                               self.returnsAnalyzer.getCumulativeReturns()[-1] * 100,
                                                                                                               self.sharpeRatioAnalyzer.getSharpeRatio(0.05),
                                                                                                               self.drawdownAnalyzer.getMaxDrawDown() * 100,
                                                                                                               self.drawdownAnalyzer.getLongestDrawDownDuration())
    def detail(self):
        """"""        
        print "-------------------------------------------------------------------------"
        print "Final portfolio value: $%.2f" % self.getResult()
        print "Cumulative returns: %.2f %%" % (self.returnsAnalyzer.getCumulativeReturns()[-1] * 100)
        print "Sharpe ratio: %.2f" % (self.sharpeRatioAnalyzer.getSharpeRatio(0.05))
        print "Max. drawdown: %.2f %%" % (self.drawdownAnalyzer.getMaxDrawDown() * 100)
        print "Longest drawdown duration: (%s)" % (self.drawdownAnalyzer.getLongestDrawDownDuration())

        print
        print "Total trades: %d" % (self.tradesAnalyzer.getCount())
        if self.tradesAnalyzer.getCount() > 0:
            profits = self.tradesAnalyzer.getAll()
            print "Avg. profit: $%2.f" % (profits.mean())
            print "Profits std. dev.: $%2.f" % (profits.std())
            print "Max. profit: $%2.f" % (profits.max())
            print "Min. profit: $%2.f" % (profits.min())
            returns = self.tradesAnalyzer.getAllReturns()
            print "Avg. return: %2.f %%" % (returns.mean() * 100)
            print "Returns std. dev.: %2.f %%" % (returns.std() * 100)
            print "Max. return: %2.f %%" % (returns.max() * 100)
            print "Min. return: %2.f %%" % (returns.min() * 100)

        print
        print "Profitable trades: %d" % (self.tradesAnalyzer.getProfitableCount())
        if self.tradesAnalyzer.getProfitableCount() > 0:
            profits = self.tradesAnalyzer.getProfits()
            print "Avg. profit: $%2.f" % (profits.mean())
            print "Profits std. dev.: $%2.f" % (profits.std())
            print "Max. profit: $%2.f" % (profits.max())
            print "Min. profit: $%2.f" % (profits.min())
            returns = self.tradesAnalyzer.getPositiveReturns()
            print "Avg. return: %2.f %%" % (returns.mean() * 100)
            print "Returns std. dev.: %2.f %%" % (returns.std() * 100)
            print "Max. return: %2.f %%" % (returns.max() * 100)
            print "Min. return: %2.f %%" % (returns.min() * 100)

        print
        print "Unprofitable trades: %d" % (self.tradesAnalyzer.getUnprofitableCount())
        if self.tradesAnalyzer.getUnprofitableCount() > 0:
            losses = self.tradesAnalyzer.getLosses()
            print "Avg. loss: $%2.f" % (losses.mean())
            print "Losses std. dev.: $%2.f" % (losses.std())
            print "Max. loss: $%2.f" % (losses.min())
            print "Min. loss: $%2.f" % (losses.max())
            returns = self.tradesAnalyzer.getNegativeReturns()
            print "Avg. return: %2.f %%" % (returns.mean() * 100)
            print "Returns std. dev.: %2.f %%" % (returns.std() * 100)
            print "Max. return: %2.f %%" % (returns.max() * 100)
            print "Min. return: %2.f %%" % (returns.min() * 100)    
        print "-------------------------------------------------------------------------"
    def initAnalyzer(self):
        from pyalgotrade.stratanalyzer import sharpe
        from pyalgotrade.stratanalyzer import returns
        from pyalgotrade.stratanalyzer import drawdown
        from pyalgotrade.stratanalyzer import trades        
        # 1.0) 策略结果
        self.returnsAnalyzer = returns.Returns()
        # 1.1) 夏普比率 
        self.sharpeRatioAnalyzer = sharpe.SharpeRatio()
        # 1.2) 
        self.drawdownAnalyzer = drawdown.DrawDown()
        # 1.3)
        self.tradesAnalyzer = trades.Trades()     
        
        self.attachAnalyzer(self.sharpeRatioAnalyzer)
        self.attachAnalyzer(self.returnsAnalyzer)    
        self.attachAnalyzer(self.tradesAnalyzer)   
        self.attachAnalyzer(self.drawdownAnalyzer)    
class midBaseStrategy(strategy.BacktestingStrategy):
    def getFeeds(self, timeFrom=None, timeTo=None):
        import os, sys
        xpower = os.path.abspath(
            os.path.join(os.path.dirname(__file__), os.pardir, os.pardir,
                         os.pardir, 'midProjects', 'histdata'))
        sys.path.append(xpower)

        import dataCenter as dataCenter
        self.dataCenter = dataCenter.dataCenter()
        feeds = self.dataCenter.getFeedsForPAT(dataProvider=self.dataProvider,
                                               storageType=self.storageType,
                                               instruments=self.instruments,
                                               period=self.period,
                                               timeTo=timeTo,
                                               timeFrom=timeFrom)
        return feeds

    def initEa(self, timeFrom=None, timeTo=None):

        feeds = self.getFeeds(timeFrom=timeFrom, timeTo=timeTo)

        instrument = self.instrument

        strategy.BacktestingStrategy.__init__(self, feeds[instrument])
        self.mid_DEFAULT_MAX_LEN = 10 * DEFAULT_MAX_LEN

        mid_DEFAULT_MAX_LEN = self.mid_DEFAULT_MAX_LEN

        #mid 计算ma将使用当天的收盘价格计算
        #mid 1)
        feed = feeds[instrument]
        dataSeries = feed[instrument]
        dataSeries.setMaxLen(mid_DEFAULT_MAX_LEN)
        closeSeries = dataSeries.getCloseDataSeries()
        #mid 2)
        prices = closeSeries
        prices.setMaxLen(mid_DEFAULT_MAX_LEN)
        self.closePrices = prices

        #mid follow vars will be used in subclass
        self.timeFrom = timeFrom
        self.timeTo = timeTo

        self.instrument = instrument
        self.longPosition = None
        self.shortPosition = None
        self.buySignal = False
        self.sellSignal = False

        #mid follow vars will be used only this class
        self.__curPositionCost = 0  #mid init position value
        mid_DEFAULT_MAX_LEN = self.mid_DEFAULT_MAX_LEN
        self.__position_volume = SequenceDataSeries(
            maxLen=mid_DEFAULT_MAX_LEN)  #mid 当前持有头寸数量
        self.__position_cost = SequenceDataSeries(
            maxLen=mid_DEFAULT_MAX_LEN)  #mid 当前持有头寸开仓成本
        self.__position_pnl = SequenceDataSeries(
            maxLen=mid_DEFAULT_MAX_LEN)  #mid 当前持有头寸价值
        self.__portfolio_value = SequenceDataSeries(maxLen=mid_DEFAULT_MAX_LEN)
        self.__buy = SequenceDataSeries(maxLen=mid_DEFAULT_MAX_LEN)
        self.__sell = SequenceDataSeries(maxLen=mid_DEFAULT_MAX_LEN)

    def getAssetStructure(self):
        #mid --------------------------------
        #mid 当前账户资产结构如下方式获取
        #mid Long 和 Short不会同时存在
        #mid 在开仓前,若有反向持仓,则此过程查询并输出已持有的反向持仓
        broker = self.getBroker()
        portfolio_value = broker.getEquity()
        cash = broker.getCash()
        if self.shortPosition is not None or self.longPosition is not None:
            bars = self.getFeed().getCurrentBars()

            positions = broker.getPositions()

            positionsOpenValue = {}
            positionsCloseValue = {}
            for key, value in positions.items():
                print "key:" + key + ",value:" + str(value)
                bar = bars.getBar(key)
                openPrice = bar.getOpen()
                closePrice = bar.getClose()
                share = broker.getShares(key)
                positionsOpenValue[key] = openPrice * share
                positionsCloseValue[key] = closePrice * share

            print
            print 'current bar asset structure'
            print 'open cash %2.f.' % (cash)
            for key, value in positionsOpenValue.items():
                print "key:" + key + ",value:" + str(value)
            print 'close cash %2.f.' % (cash)
            for key, value in positionsCloseValue.items():
                print "key:" + key + ",value:" + str(value)
            print 'portfolio:%2.f' % (portfolio_value)

            return portfolio_value, cash, sum(positionsCloseValue.values())
        return portfolio_value, cash, 0

    def recordPositions(self):
        # record position
        #######################################################################
        broker = self.getBroker()
        position = broker.getPositions()  #mid position is dict of share
        share = broker.getShares(
            self.instrument)  #mid position is dict of share
        lastPrice = self.getLastPrice(self.instrument)
        portfolio_value = broker.getEquity()  #mid 按close价格计算的权益
        cash = broker.getCash()

        position_value = portfolio_value - cash

        position_pnl = position_value - self.__curPositionCost

        print
        print 'cash: %.2f' % (cash)
        print 'position value: %.2f' % (portfolio_value - cash)
        print 'mid calc: %.2f' % (lastPrice * share + cash)
        print 'broker returned: %.2f' % (portfolio_value)

        curTime = self.getCurrentDateTime()
        currentTime = self.getCurrentDateTime()

        self.__position_volume.appendWithDateTime(currentTime, abs(share))

        self.__position_cost.appendWithDateTime(currentTime,
                                                abs(self.__curPositionCost))

        self.__position_pnl.appendWithDateTime(currentTime, position_pnl)

        self.__portfolio_value.appendWithDateTime(currentTime, portfolio_value)
        self.__buy.appendWithDateTime(currentTime, self.buySignal)
        self.__sell.appendWithDateTime(currentTime, self.sellSignal)

    def getInstrument(self):
        return self.instrument

    def getPortfolio(self):
        return self.__portfolio_value

    def getPositionVolume(self):
        return self.__position_volume

    def getPositionCost(self):
        return self.__position_cost

    def getPositionPnl(self):
        return self.__position_pnl

    def getBuy(self):
        return self.__buy

    def getSell(self):
        return self.__sell

    def onEnterOk(self, position):
        execInfo = position.getEntryOrder().getExecutionInfo()
        portfolio = self.getResult()
        cash = self.getBroker().getCash()
        '''mid
  以下两种方法都是为了计算持仓成本
  由于getEquity()返回的是依据当日close价格计算出来的权益
  所以,这个值不能作为持仓成本
  持仓成本需要以onEnterOk时bar的open价格计算
  所以应使用第二种算法
  由于经常有跳开现象,所以依据bar(n-1).close发出的market order,
  在bar(n).open执行时通常会有gap出现,表现在position_cost图上时就是持有成本离计划成本会有跳口,
  '''
        if (False):  #mid two methods to cacl cost.
            portfolio_value = self.getBroker().getEquity()
            self.__curPositionCost = portfolio_value - cash
        else:
            feed = self.getFeed()
            bars = feed.getCurrentBars()
            bar = bars.getBar(self.instrument)
            openPrice = bar.getOpen()
            closePrice = self.getLastPrice(
                self.instrument)  #mid lastPrice == closePrice
            share = self.getBroker().getShares(self.instrument)
            self.__curPositionCost = openPrice * share

        self.info("onEnterOk().current available cash: %.2f,portfolio: %.2f." %
                  (cash, portfolio))
        if isinstance(position, strategy.position.LongPosition):
            self.info("onEnterOK().ExecutionInfo: %s,OPEN LONG %.2f at $%.2f" %
                      (execInfo.getDateTime(), execInfo.getQuantity(),
                       execInfo.getPrice()))
        elif isinstance(position, strategy.position.ShortPosition):
            self.info(
                "onEnterOK().ExecutionInfo: %s,OPEN SHORT %.2f at $%.2f" %
                (execInfo.getDateTime(), execInfo.getQuantity(),
                 execInfo.getPrice()))

    def onEnterCanceled(self, position):
        self.info("onEnterCanceled().current available cash: %.2f." %
                  (self.getBroker().getCash()))
        if isinstance(position, strategy.position.LongPosition):
            self.longPosition = None
            self.info("onEnterCanceled().OPEN LONG cancled.")
        elif isinstance(position, strategy.position.ShortPosition):
            self.shortPosition = None
            self.info("onEnterCanceled().OPEN SHORT cancled.")

    def onExitOk(self, position):
        execInfo = position.getExitOrder().getExecutionInfo()
        portfolio = self.getResult()
        cash = self.getBroker().getCash()
        self.info("onExitOk().current available cash: %.2f,portfolio: %.2f." %
                  (cash, portfolio))

        if isinstance(position, strategy.position.LongPosition):
            self.longPosition = None
            self.info("onExitOk().ExecutionInfo: %s,CLOSE LONG %.2f at $%.2f" %
                      (execInfo.getDateTime(), execInfo.getQuantity(),
                       execInfo.getPrice()))
        elif isinstance(position, strategy.position.ShortPosition):
            self.shortPosition = None
            self.info(
                "onExitOk().ExecutionInfo: %s,CLOSE SHORT %.2f at $%.2f" %
                (execInfo.getDateTime(), execInfo.getQuantity(),
                 execInfo.getPrice()))

    def onExitCanceled(self, position):
        # If the exit was canceled, re-submit it.
        if isinstance(position, strategy.position.LongPosition):
            self.longPosition = None
        elif isinstance(position, strategy.position.ShortPosition):
            self.shortPosition = None

    def logInfo(self, bars=None):
        pLong, pShort = 0, 0
        if (self.longPosition is not None):
            pLong = self.longPosition.getShares()
        if (self.shortPosition is not None):
            pShort = self.shortPosition.getShares()

        bar = bars[self.instrument]
        pOpen = bar.getOpen()
        pHigh = bar.getHigh()
        pLow = bar.getLow()
        pClose = bar.getClose()
        pPrice = bar.getPrice()

        self.info(
            'logInfo().price:%.3f,open:%.2f,high:%.2f,low:%.2f,close:%.2f' %
            (pPrice, pOpen, pHigh, pLow, pClose))
        #self.info('long:%.2f#short:%.2f'%(pLong,pShort))
    def closePosition(self):
        if (self.longPosition is not None and self.sellSignal == True):
            self.info(
                "onBars().Status info,before exitMarket(), LONG POSITION to close %.2f"
                % (self.longPosition.getShares()))
            self.longPosition.exitMarket()
        if (self.shortPosition is not None and self.buySignal == True):
            self.info(
                "onBars().Status info,before exitMarket(), SHORT POSITION to close %.2f"
                % (self.shortPosition.getShares()))
            self.shortPosition.exitMarket()

    def openPosition(self):
        '''mid
        此处是onBars,这个和zipline的概念完全不同
        zipline中,需要覆写的是handle_data,这个东西是个tick概念,所以没有OHLC的,只是个price
        PAT中,每次onBars,都会传入一个newbar的OHLC,此时,要如何按这个OHLC决策,全由你
        依据OHLC做完决策后,可以发送交易指令:
        * Order.Type.MARKET
        * Order.Type.LIMIT
        * Order.Type.STOP
        * Order.Type.STOP_LIMIT
        1.市价单,依据下一个bar的openPrice执行命令:
            self.enterLong()
        2.限价单
        3.止损单市价单
        4.止损限价单

        当前似乎没有止盈单

        在均线策略中,应该在每个newbar到来时,按closePrice的均线计算指标值,然后发送市价单
        1.每个newbar按close价格计算指标,并在下一个bar按open成交
        2.每个newbar按open价格计算指标,并在此newbar按open成交
        以上1,2的计算逻辑是一致的。如果当前bar的close和下一个bar的open相差无几时,两种算法的回测结果也应相差无几
        '''
        # mid 2)open
        if (self.buySignal == True):
            shares = self.money.getShares(strat=self)
            self.info(
                "onBars().Status info,before enterLong(), LONG POSITION to open %.2f,need amount: %.2f,available amount: %.2f."
                % (shares, shares * self.getLastPrice(self.instrument),
                   self.getBroker().getCash()))
            self.longPosition = self.enterLong(self.instrument, shares, True)
        if (self.sellSignal == True):
            # Enter a buy market order. The order is good till canceled.
            shares = self.money.getShares(strat=self)
            self.info(
                "onBars().Status info,before enterShort(), SHORT POSITION to open %.2f,need amount: %.2f,available amount: %.2f."
                % (shares, shares * self.getLastPrice(self.instrument),
                   self.getBroker().getCash()))
            self.shortPosition = self.enterShort(self.instrument, shares, True)

    def __analise(self):
        dataForCandle = self.dataCenter.getCandleData(
            dataProvider=self.dataProvider,
            dataStorage=self.storageType,
            dataPeriod=self.period,
            symbol=self.instrument,
            dateStart=self.timeFrom,
            dateEnd=self.timeTo)
        self.analyzer.analyze(self.result, dataForCandle, InKLine=self.InKLine)

    def run(self, timeFrom=None, timeTo=None):
        self.initEa(timeFrom=timeFrom, timeTo=timeTo)

        self.initIndicators()
        #self.strat.setUseAdjustedValues(False)

        self.initAnalyzer()

        strategy.BacktestingStrategy.run(self)

        buy = self.getBuy()
        sell = self.getSell()

        portfolio_value = self.getPortfolio()
        position_volume = self.getPositionVolume()
        position_cost = self.getPositionCost()
        position_pnl = self.getPositionPnl()

        self.result = pd.DataFrame(
            {
                'position_volume': list(position_volume),
                'position_cost': list(position_cost),
                'position_pnl': list(position_pnl),
                'buy': list(buy),
                'sell': list(sell),
                'portfolio_value': list(portfolio_value)
            },
            columns=[
                'position_volume', 'position_cost', 'position_pnl', 'buy',
                'sell', 'portfolio_value'
            ],
            index=position_volume.getDateTimes())

        self.addIndicators()
        #------------------------------------

        if (self.toPlot):
            self.__analise()

        return self.result

    #mid from ea
    #----------------------------------------------------------------------
    def summary(self):
        return "from %s to %s:returns:%.2f%%,sharpe:%.2f,MaxDrawdown:%.2f%%,Longest drawdown duration:(%s)" % (
            str(self.timeFrom), str(self.timeTo),
            self.returnsAnalyzer.getCumulativeReturns()[-1] * 100,
            self.sharpeRatioAnalyzer.getSharpeRatio(0.05),
            self.drawdownAnalyzer.getMaxDrawDown() * 100,
            self.drawdownAnalyzer.getLongestDrawDownDuration())

    def detail(self):
        """"""
        print "-------------------------------------------------------------------------"
        print "Final portfolio value: $%.2f" % self.getResult()
        print "Cumulative returns: %.2f %%" % (
            self.returnsAnalyzer.getCumulativeReturns()[-1] * 100)
        print "Sharpe ratio: %.2f" % (
            self.sharpeRatioAnalyzer.getSharpeRatio(0.05))
        print "Max. drawdown: %.2f %%" % (
            self.drawdownAnalyzer.getMaxDrawDown() * 100)
        print "Longest drawdown duration: (%s)" % (
            self.drawdownAnalyzer.getLongestDrawDownDuration())

        print
        print "Total trades: %d" % (self.tradesAnalyzer.getCount())
        if self.tradesAnalyzer.getCount() > 0:
            profits = self.tradesAnalyzer.getAll()
            print "Avg. profit: $%2.f" % (profits.mean())
            print "Profits std. dev.: $%2.f" % (profits.std())
            print "Max. profit: $%2.f" % (profits.max())
            print "Min. profit: $%2.f" % (profits.min())
            returns = self.tradesAnalyzer.getAllReturns()
            print "Avg. return: %2.f %%" % (returns.mean() * 100)
            print "Returns std. dev.: %2.f %%" % (returns.std() * 100)
            print "Max. return: %2.f %%" % (returns.max() * 100)
            print "Min. return: %2.f %%" % (returns.min() * 100)

        print
        print "Profitable trades: %d" % (
            self.tradesAnalyzer.getProfitableCount())
        if self.tradesAnalyzer.getProfitableCount() > 0:
            profits = self.tradesAnalyzer.getProfits()
            print "Avg. profit: $%2.f" % (profits.mean())
            print "Profits std. dev.: $%2.f" % (profits.std())
            print "Max. profit: $%2.f" % (profits.max())
            print "Min. profit: $%2.f" % (profits.min())
            returns = self.tradesAnalyzer.getPositiveReturns()
            print "Avg. return: %2.f %%" % (returns.mean() * 100)
            print "Returns std. dev.: %2.f %%" % (returns.std() * 100)
            print "Max. return: %2.f %%" % (returns.max() * 100)
            print "Min. return: %2.f %%" % (returns.min() * 100)

        print
        print "Unprofitable trades: %d" % (
            self.tradesAnalyzer.getUnprofitableCount())
        if self.tradesAnalyzer.getUnprofitableCount() > 0:
            losses = self.tradesAnalyzer.getLosses()
            print "Avg. loss: $%2.f" % (losses.mean())
            print "Losses std. dev.: $%2.f" % (losses.std())
            print "Max. loss: $%2.f" % (losses.min())
            print "Min. loss: $%2.f" % (losses.max())
            returns = self.tradesAnalyzer.getNegativeReturns()
            print "Avg. return: %2.f %%" % (returns.mean() * 100)
            print "Returns std. dev.: %2.f %%" % (returns.std() * 100)
            print "Max. return: %2.f %%" % (returns.max() * 100)
            print "Min. return: %2.f %%" % (returns.min() * 100)
        print "-------------------------------------------------------------------------"

    def initAnalyzer(self):
        from pyalgotrade.stratanalyzer import sharpe
        from pyalgotrade.stratanalyzer import returns
        from pyalgotrade.stratanalyzer import drawdown
        from pyalgotrade.stratanalyzer import trades
        # 1.0) 策略结果
        self.returnsAnalyzer = returns.Returns()
        # 1.1) 夏普比率
        self.sharpeRatioAnalyzer = sharpe.SharpeRatio()
        # 1.2)
        self.drawdownAnalyzer = drawdown.DrawDown()
        # 1.3)
        self.tradesAnalyzer = trades.Trades()

        self.attachAnalyzer(self.sharpeRatioAnalyzer)
        self.attachAnalyzer(self.returnsAnalyzer)
        self.attachAnalyzer(self.tradesAnalyzer)
        self.attachAnalyzer(self.drawdownAnalyzer)
    def initEa(self, timeFrom=None, timeTo=None):

        feeds = self.getFeeds(timeFrom=timeFrom, timeTo=timeTo)

        instrument = self.instrument

        strategy.BacktestingStrategy.__init__(self, feeds[instrument])
        self.mid_DEFAULT_MAX_LEN = 10 * DEFAULT_MAX_LEN

        mid_DEFAULT_MAX_LEN = self.mid_DEFAULT_MAX_LEN

        #mid 计算ma将使用当天的收盘价格计算
        #mid 1)
        feed = feeds[instrument]
        dataSeries = feed[instrument]
        dataSeries.setMaxLen(mid_DEFAULT_MAX_LEN)
        closeSeries = dataSeries.getCloseDataSeries()
        #mid 2)
        prices = closeSeries
        prices.setMaxLen(mid_DEFAULT_MAX_LEN)
        self.closePrices = prices

        #mid follow vars will be used in subclass
        self.timeFrom = timeFrom
        self.timeTo = timeTo

        self.instrument = instrument
        self.longPosition = None
        self.shortPosition = None
        self.buySignal = False
        self.sellSignal = False

        #mid follow vars will be used only this class
        self.__curPositionCost = 0  #mid init position value
        mid_DEFAULT_MAX_LEN = self.mid_DEFAULT_MAX_LEN
        self.__position_volume = SequenceDataSeries(
            maxLen=mid_DEFAULT_MAX_LEN)  #mid 当前持有头寸数量
        self.__position_cost = SequenceDataSeries(
            maxLen=mid_DEFAULT_MAX_LEN)  #mid 当前持有头寸开仓成本
        self.__position_pnl = SequenceDataSeries(
            maxLen=mid_DEFAULT_MAX_LEN)  #mid 当前持有头寸价值
        self.__portfolio_value = SequenceDataSeries(maxLen=mid_DEFAULT_MAX_LEN)
        self.__buy = SequenceDataSeries(maxLen=mid_DEFAULT_MAX_LEN)
        self.__sell = SequenceDataSeries(maxLen=mid_DEFAULT_MAX_LEN)
Ejemplo n.º 23
0
class DMACrossOver(strategy.BacktestingStrategy):
 def __init__(self, feed = None, instrument = '',shortPeriod =  0,longPeriod = 0,money = None,longAllowed=True,shortAllowed=True):
  strategy.BacktestingStrategy.__init__(self, feed)

  self.position_cost = 0  #mid init position value
  
  mid_DEFAULT_MAX_LEN = 10 * DEFAULT_MAX_LEN
  self.__instrument = instrument
  self.__longPosition = None
  self.__shortPosition = None
  
  self.__position_volume = SequenceDataSeries(maxLen = mid_DEFAULT_MAX_LEN)       #mid 当前持有头寸数量
  self.__position_cost = SequenceDataSeries(maxLen = mid_DEFAULT_MAX_LEN)  #mid 当前持有头寸开仓成本
  self.__position_pnl = SequenceDataSeries(maxLen = mid_DEFAULT_MAX_LEN)   #mid 当前持有头寸价值
  self.__portfolio_value = SequenceDataSeries(maxLen = mid_DEFAULT_MAX_LEN)
  self.__buy = SequenceDataSeries(maxLen = mid_DEFAULT_MAX_LEN)
  self.__sell = SequenceDataSeries(maxLen = mid_DEFAULT_MAX_LEN)
  
  
  self.__buySignal = False
  self.__sellSignal = False
  self.money = money
  self.longAllowed = True
  self.shortAllowed = True        
  #mid 计算ma将使用当天的收盘价格计算
  #mid 1)
  dataSeries = feed[instrument]
  dataSeries.setMaxLen(mid_DEFAULT_MAX_LEN)
  closeSeries = dataSeries.getCloseDataSeries()
  #mid 2)
  prices = closeSeries
  prices.setMaxLen(mid_DEFAULT_MAX_LEN)
  #mid 3)
  self.__sma = ma.SMA(prices, shortPeriod,maxLen=mid_DEFAULT_MAX_LEN)
  self.__lma = ma.SMA(prices,longPeriod,maxLen=mid_DEFAULT_MAX_LEN)

  self.i = 0
 def getAssetStructure(self):
  #mid --------------------------------
  #mid 当前账户资产结构如下方式获取
  #mid Long 和 Short不会同时存在
  #mid 在开仓前,若有反向持仓,则此过程查询并输出已持有的反向持仓
  broker = self.getBroker()
  portfolio_value = broker.getEquity()
  cash = broker.getCash()
  if self.__shortPosition is not None or self.__longPosition is not None:
   bars = self.getFeed().getCurrentBars()  
   
   positions = broker.getPositions()
   
   positionsOpenValue = {}
   positionsCloseValue = {}
   for key,value in positions.items():
    print "key:"+key+",value:"+str(value)
    bar = bars.getBar(key)
    openPrice = bar.getOpen() 
    closePrice = bar.getClose()
    share = broker.getShares(key)
    positionsOpenValue[key] = openPrice*share
    positionsCloseValue[key] = closePrice*share
    
   print 
   print 'current bar asset structure'
   print 'open cash %2.f.' % (cash)
   for key,value in positionsOpenValue.items():
    print "key:"+key+",value:"+str(value)
   print 'close cash %2.f.' % (cash)
   for key,value in positionsCloseValue.items():
    print "key:"+key+",value:"+str(value)    
   print 'portfolio:%2.f' % (portfolio_value)
   
   return portfolio_value,cash,sum(positionsCloseValue.values())
  return portfolio_value,cash,0
 def recordPositions(self):
  # record position      
  #######################################################################
  broker = self.getBroker()
  position = broker.getPositions()                   #mid position is dict of share
  share = broker.getShares(self.__instrument)        #mid position is dict of share
  lastPrice = self.getLastPrice(self.__instrument)  
  portfolio_value = broker.getEquity()               #mid 按close价格计算的权益
  cash = broker.getCash()
  
  position_value = portfolio_value - cash
  
  position_pnl = position_value - self.position_cost
  
  print
  print 'cash: %.2f' %(cash)
  print 'position value: %.2f' % (portfolio_value - cash)
  print 'mid calc: %.2f' %(lastPrice*share+cash)
  print 'broker returned: %.2f' %(portfolio_value)
  
  
  curTime = self.getCurrentDateTime()
  if(False):
   yLimit = self.money.getShares()*1.1
   if(self.i==0):
    self.__position.append(yLimit)
    self.i = self.i + 1
   elif(self.i==1):
    self.__position.append(-yLimit)
    self.i = self.i + 1
   else:
    currentTime = self.getCurrentDateTime()
    self.__position.appendWithDateTime(currentTime,abs(share))                
    #self.__position.append(share)

  else:
   currentTime = self.getCurrentDateTime()
   
   self.__position_volume.appendWithDateTime(currentTime,abs(share))  
   
   self.__position_cost.appendWithDateTime(currentTime,abs(self.position_cost))
   
   self.__position_pnl.appendWithDateTime(currentTime,position_pnl)
   
   self.__portfolio_value.appendWithDateTime(currentTime,portfolio_value)  
   self.__buy.appendWithDateTime(currentTime,self.__buySignal)              
   self.__sell.appendWithDateTime(currentTime,self.__sellSignal) 
 def getInstrument(self):
  return self.__instrument
 def getPortfolio(self):
  return self.__portfolio_value
 def getPositionVolume(self):
  return self.__position_volume    
 def getPositionCost(self):
  return self.__position_cost
 def getPositionPnl(self):
  return self.__position_pnl 
 def getSMA(self):
  return self.__sma
 def getLMA(self):
  return self.__lma
 def getBuy(self):
  return self.__buy
 def getSell(self):
  return self.__sell
 def onEnterOk(self, position):
  execInfo = position.getEntryOrder().getExecutionInfo()   
  portfolio = self.getResult()
  cash = self.getBroker().getCash() 

  '''mid
  以下两种方法都是为了计算持仓成本
  由于getEquity()返回的是依据当日close价格计算出来的权益
  所以,这个值不能作为持仓成本
  持仓成本需要以onEnterOk时bar的open价格计算
  所以应使用第二种算法
  由于经常有跳开现象,所以依据bar(n-1).close发出的market order,
  在bar(n).open执行时通常会有gap出现,表现在position_cost图上时就是持有成本离计划成本会有跳口,
  '''
  if(False):#mid two methods to cacl cost.
   portfolio_value = self.getBroker().getEquity()
   self.position_cost = portfolio_value - cash  
  else:
   feed = self.getFeed()
   bars = feed.getCurrentBars()
   bar = bars.getBar(self.__instrument)
   openPrice = bar.getOpen()   
   closePrice = self.getLastPrice(self.__instrument) #mid lastPrice == closePrice
   share = self.getBroker().getShares(self.__instrument)
   self.position_cost = openPrice*share

  self.info("onEnterOk().current available cash: %.2f,portfolio: %.2f." % (cash,portfolio))
  if isinstance(position, strategy.position.LongPosition):
   self.info("onEnterOK().ExecutionInfo: %s,OPEN LONG %.2f at $%.2f" 
             % (execInfo.getDateTime(),execInfo.getQuantity(),execInfo.getPrice())) 
  elif isinstance(position, strategy.position.ShortPosition):
   self.info("onEnterOK().ExecutionInfo: %s,OPEN SHORT %.2f at $%.2f" 
             % (execInfo.getDateTime(),execInfo.getQuantity(),execInfo.getPrice()))     
   
   
   
 def onEnterCanceled(self, position):
  self.info("onEnterCanceled().current available cash: %.2f." % (self.getBroker().getCash()))
  if isinstance(position, strategy.position.LongPosition):
   self.__longPosition = None
   self.info("onEnterCanceled().OPEN LONG cancled.")                                
  elif isinstance(position, strategy.position.ShortPosition):
   self.__shortPosition = None
   self.info("onEnterCanceled().OPEN SHORT cancled.")
 def onExitOk(self, position):        
  execInfo = position.getExitOrder().getExecutionInfo()     
  portfolio = self.getResult()
  cash = self.getBroker().getCash()
  self.info("onExitOk().current available cash: %.2f,portfolio: %.2f." % (cash,portfolio))

  if isinstance(position, strategy.position.LongPosition):
   self.__longPosition = None
   self.info("onExitOk().ExecutionInfo: %s,CLOSE LONG %.2f at $%.2f" 
             % (execInfo.getDateTime(),execInfo.getQuantity(),execInfo.getPrice()))                    
  elif isinstance(position, strategy.position.ShortPosition):
   self.__shortPosition = None
   self.info("onExitOk().ExecutionInfo: %s,CLOSE SHORT %.2f at $%.2f" 
             % (execInfo.getDateTime(),execInfo.getQuantity(),execInfo.getPrice()))                    
 def onExitCanceled(self, position):
  # If the exit was canceled, re-submit it.
  if isinstance(position, strategy.position.LongPosition):
   self.__longPosition = None
  elif isinstance(position, strategy.position.ShortPosition):
   self.__shortPosition = None
 def logInfo(self,bars = None):
  pLong,pShort = 0,0
  if(self.__longPosition is not None):
   pLong = self.__longPosition.getShares()
  if(self.__shortPosition is not None):
   pShort = self.__shortPosition.getShares()


  bar = bars[self.__instrument]
  pOpen = bar.getOpen()
  pHigh = bar.getHigh()
  pLow = bar.getLow()
  pClose = bar.getClose()
  pPrice = bar.getPrice()

  self.info('logInfo().price:%.3f,open:%.2f,high:%.2f,low:%.2f,close:%.2f'%(pPrice,pOpen,pHigh,pLow,pClose))
  #self.info('long:%.2f#short:%.2f'%(pLong,pShort))        
 def run(self):
  strategy.BacktestingStrategy.run(self)

  sma = self.getSMA()
  lma = self.getLMA()
  buy = self.getBuy()
  sell = self.getSell()
  
  portfolio_value = self.getPortfolio()
  
  position_volume = self.getPositionVolume()
  position_cost = self.getPositionCost()
  position_pnl = self.getPositionPnl()
  
  result = pd.DataFrame({'position_volume':list(position_volume),'position_cost':list(position_cost),'position_pnl':list(position_pnl),'short_ema':list(sma),'long_ema':list(lma),
                         'buy':list(buy),'sell':list(sell),'portfolio_value':list(portfolio_value)},
                        columns=['position_volume','position_cost','position_pnl','short_ema','long_ema','buy','sell','portfolio_value'],
                        index=position_volume.getDateTimes())        
  return result
 def onBars(self, bars):
  '''mid
  此处是onBars,这个和zipline的概念完全不同
  zipline中,需要覆写的是handle_data,这个东西是个tick概念,所以没有OHLC的,只是个price
  PAT中,每次onBars,都会传入一个newbar的OHLC,此时,要如何按这个OHLC决策,全由你
  依据OHLC做完决策后,可以发送交易指令:
  * Order.Type.MARKET
  * Order.Type.LIMIT
  * Order.Type.STOP
  * Order.Type.STOP_LIMIT
  1.市价单,依据下一个bar的openPrice执行命令:
      self.enterLong()
  2.限价单
  3.止损单市价单
  4.止损限价单

  当前似乎没有止盈单

  在均线策略中,应该在每个newbar到来时,按closePrice的均线计算指标值,然后发送市价单
  1.每个newbar按close价格计算指标,并在下一个bar按open成交
  2.每个newbar按open价格计算指标,并在此newbar按open成交
  以上1,2的计算逻辑是一致的。如果当前bar的close和下一个bar的open相差无几时,两种算法的回测结果也应相差无几
  '''      
  self.__buySignal,self.__sellSignal = False,False
  # mid 1)close
  if(self.longAllowed):
   if self.__longPosition is not None and not self.__longPosition.exitActive():
    #mid 有多仓,检查是否需要平仓
    if(cross.cross_below(self.__sma, self.__lma) > 0):
     print
     self.info("onBars().Status info,before exitMarket(), LONG POSITION to close %.2f" 
               % (self.__longPosition.getShares()))                                    
     self.__longPosition.exitMarket()
  if(self.shortAllowed):
   if self.__shortPosition is not None and not self.__shortPosition.exitActive():
    if(cross.cross_above(self.__sma, self.__lma) > 0):
     print
     self.info("onBars().Status info,before exitMarket(), SHORT POSITION to close %.2f" 
               % (self.__shortPosition.getShares()))  
     self.__shortPosition.exitMarket()    

  # mid 2)open
  if(self.longAllowed):
   if self.__longPosition is None:
    #mid 无多仓,检查是否需要开多仓
    if cross.cross_above(self.__sma, self.__lma) > 0:
     # Enter a buy market order. The order is good till canceled.
     shares = self.money.getShares(strat = self)                    
     self.info("onBars().Status info,before enterLong(), LONG POSITION to open %.2f,need amount: %.2f,available amount: %.2f." % 
               (shares,shares*self.getLastPrice(self.__instrument),self.getBroker().getCash() ))                                    
     self.__longPosition = self.enterLong(self.__instrument, shares, True)
     self.__buySignal = True   
  if(self.shortAllowed):
   if self.__shortPosition is None:
    if cross.cross_below(self.__sma, self.__lma) > 0:
     # Enter a buy market order. The order is good till canceled.
     shares = self.money.getShares(strat = self)
     self.info("onBars().Status info,before enterShort(), SHORT POSITION to open %.2f,need amount: %.2f,available amount: %.2f." % 
               (shares,shares*self.getLastPrice(self.__instrument),self.getBroker().getCash() ))                                    
     self.__shortPosition = self.enterShort(self.__instrument, shares, True)
     self.__sellSignal = True

  self.recordPositions()            
Ejemplo n.º 24
0
    def __init__(self, feed, instrument, bollingerlength, numStdDev,
                 closelength, ccMAlength, malength, space):
        strategy.BacktestingStrategy.__init__(self, feed)
        self.getBroker().setFillStrategy(DefaultStrategy(None))
        self.getBroker().setCommission(TradePercentage(0.002))
        self.__instrument = instrument
        self.__bollingerlength = int(bollingerlength)
        numStdDev = float(numStdDev) / 10
        self.__closelength = int(closelength)
        self.__ccMAlength = int(ccMAlength)
        self.__malength = int(malength)
        self.__longPos = None
        self.__shortPos = None
        self.__close = feed[instrument].getCloseDataSeries()
        self.__open = feed[instrument].getOpenDataSeries()
        self.__high = feed[instrument].getHighDataSeries()
        self.__low = feed[instrument].getLowDataSeries()
        self.__datetime = feed[instrument].getDateTimes()
        self.__bollinger = bollinger.BollingerBands(self.__close,
                                                    self.__bollingerlength,
                                                    int(numStdDev))
        self.__UpperBand = self.__bollinger.getUpperBand()
        self.__LowerBand = self.__bollinger.getLowerBand()
        self.__MA = SequenceDataSeries()
        self.__space = int(space)
        self.__enter = 0
        self.__enterLong1 = 0
        self.__enterLong2 = 0
        self.__enterShort1 = 0
        self.__enterShort2 = 0
        self.__exitLong1 = 0
        self.__exitLong2 = 0
        self.__exitShort1 = 0
        self.__exitShort1 = 0

        #for test
        #########################################################################
        self.__p = SequenceDataSeries()
        self.__filterCon = SequenceDataSeries()
        self.__ccMACon1 = SequenceDataSeries()
        self.__ccMACon2 = SequenceDataSeries()
        self.__enterCon = SequenceDataSeries()
        self.__enterLongCon1 = SequenceDataSeries()
        self.__enterLongCon2 = SequenceDataSeries()
        self.__enterShortCon1 = SequenceDataSeries()
        self.__enterShortCon2 = SequenceDataSeries()
        self.__exitLongCon1 = SequenceDataSeries()
        self.__exitLongCon2 = SequenceDataSeries()
        self.__exitShortCon1 = SequenceDataSeries()
        self.__exitShortCon2 = SequenceDataSeries()
Ejemplo n.º 25
0
class Macd(SequenceDataSeries):
    def __init__(self,
                 instrument,
                 dataSeries,
                 fastEMA,
                 slowEMA,
                 signalEMA,
                 maxLen=None):
        assert (fastEMA > 0)
        assert (slowEMA > 0)
        assert (fastEMA < slowEMA)
        assert (signalEMA > 0)
        super(Macd, self).__init__(maxLen)
        self.__instrument = instrument
        self.__skipNum = max(fastEMA, slowEMA, signalEMA)
        self.__fastEMAWindow = EMAEventWindow(fastEMA)
        self.__slowEMAWindow = EMAEventWindow(slowEMA)
        self.__signalEMAWindow = EMAEventWindow(signalEMA)
        self.__signal = SequenceDataSeries(maxLen)  #dea
        self.__histogram = SequenceDataSeries(maxLen)  #macd
        self.__cross = SequenceDataSeries(
            maxLen)  #dead cross signals and gold cross signals
        self.__close_prices = dataSeries.getPriceDataSeries()
        self.top_divergences = list()
        self.double_top_divergences = list()
        self.bottom_divergences = list()
        self.double_bottom_divergences = list()
        self.cross_detect = CrossDetect()
        self.max_limit_detect = MaxLimitDetect
        self.min_limit_detect = MinLimitDetect
        self.top_divergence_detect = TopDivergenceDetect()
        self.bottom_divergence_detect = BottomDivergenceDetect()
        self.__close_prices.getNewValueEvent().subscribe(self.__onNewValue)

    def newCross(self, cross_type, cross_date, limit_dif, area, limit_dif_date,
                 macd, macd_date, close, close_date):
        if cross_type == GOLD:
            return GoldCross(cross_date, limit_dif, area, limit_dif_date, macd,
                             macd_date, close, close_date)
        else:
            return DeathCross(cross_date, limit_dif, area, limit_dif_date,
                              macd, macd_date, close, close_date)

    def createNewCross(self, current_date, pre_cross_type, current_cross_type,
                       detect):
        """
        获取三种极值的时间和极值[MACD,CLOSE, DIF]
        :param current_date: 当前bar的date
        :param pre_cross_type: 前一个交叉点的类型
        :param current_cross_type: 当前交叉点的类型
        :param detect: 极值检测类对象
        :return: new class
        """
        pre_cross_signal_date = self.getPreSignalDate(pre_cross_type)
        if pre_cross_signal_date is None:
            return self.newCross(current_cross_type, current_date, None, None,
                                 None, None, None, None, None)
        dif, dif_date = detect.get_limit_info_in(self, pre_cross_signal_date,
                                                 current_date)
        close, close_date = detect.get_close_limit_info_in(
            self.__close_prices, pre_cross_signal_date, current_date)
        macd, macd_date = detect.get_limit_info_in(self.__histogram,
                                                   pre_cross_signal_date,
                                                   current_date)
        area = detect.get_sum_info_in(self.__histogram, pre_cross_signal_date,
                                      current_date)
        return self.newCross(current_cross_type, current_date, dif, area,
                             dif_date, macd, macd_date, close, close_date)

    def getPreSignalDate(self, pre_cross_type):
        """
        获取dif和dea前一个交叉点的时间
        :param pre_cross_type: 前一次交叉的类型[金叉或死叉]
        :return:
        """
        slength = len(self.__cross)
        if slength == 0: return None
        for x in range(slength - 1, -1, -1):
            if self.__cross[x].type == pre_cross_type:
                return self.__cross[x].cdate
        return None

    def getDif(self):
        return self

    def getDea(self):
        """Returns a :class:`pyalgotrade.dataseries.DataSeries` with the EMA over the MACD."""
        return self.__signal

    def getMacd(self):
        """Returns a :class:`pyalgotrade.dataseries.DataSeries` with the histogram (the difference between the MACD and the Signal)."""
        return self.__histogram

    def __onNewValue(self, dataSeries, dateTime, value):
        self.__fastEMAWindow.onNewValue(dateTime, value)
        self.__slowEMAWindow.onNewValue(dateTime, value)
        fastValue = self.__fastEMAWindow.getValue()
        slowValue = self.__slowEMAWindow.getValue()
        if fastValue is None or slowValue is None:
            diffValue = None
        else:
            diffValue = fastValue - slowValue

        self.__signalEMAWindow.onNewValue(dateTime, diffValue)
        deaValue = self.__signalEMAWindow.getValue()
        if diffValue is None or deaValue is None:
            macdValue = None
        else:
            macdValue = 2 * (diffValue - deaValue)

        self.appendWithDateTime(dateTime, diffValue)  #dif
        self.__signal.appendWithDateTime(dateTime, deaValue)  #dea
        self.__histogram.appendWithDateTime(dateTime, macdValue)  #macd
        if len(self) >= self.__skipNum:
            preMacdValue = self.__histogram[-2]
            if self.cross_detect.is_cross(preMacdValue, macdValue, GoldCross):
                cross = self.createNewCross(dateTime, DEATH, GOLD,
                                            self.min_limit_detect)
                log.debug("code:%s 类型:%s, 日期:%s, dif:%s, area:%s, dif date:%s, macd:%s, macd date:%s, close:%s, close date:%s" %\
                (self.__instrument, cross.type, cross.cdate, cross.dif, cross.area, cross.dif_date, cross.macd, cross.macd_date, cross.close, cross.close_date))
                self.__cross.appendWithDateTime(dateTime, cross)
                #self.bottom_divergences = self.bottom_divergence_detect.get_divergences(self.__cross, self, self.__histogram)
                self.double_bottom_divergences = self.bottom_divergence_detect.get_double_divergences(
                    self.__cross, self, self.__histogram)
            elif self.cross_detect.is_cross(preMacdValue, macdValue,
                                            DeathCross):
                cross = self.createNewCross(dateTime, GOLD, DEATH,
                                            self.max_limit_detect)
                log.debug("code:%s 类型:%s, 日期:%s, dif:%s, area:%s, dif date:%s, macd:%s, macd date:%s, close:%s, close date:%s" %\
                (self.__instrument, cross.type, cross.cdate, cross.dif, cross.area, cross.dif_date, cross.macd, cross.macd_date, cross.close, cross.close_date))
                self.__cross.appendWithDateTime(dateTime, cross)
                #self.top_divergences = self.top_divergence_detect.get_divergences(self.__cross, self, self.__histogram)
                self.double_top_divergences = self.top_divergence_detect.get_double_divergences(
                    self.__cross, self, self.__histogram)
            else:
                log.debug("%s 没有信号" % dateTime)
        else:
            log.debug("%s 还需要skip" % dateTime)
Ejemplo n.º 26
0
 def __init_pivot_levels(levels, maxLen=None):
     return {l: SequenceDataSeries(maxLen) for l in levels}
Ejemplo n.º 27
0
    def initEa(self, timeFrom=None, timeTo=None):
        self.results = {}
        feed = self.getFeedNew(timeFrom=timeFrom, timeTo=timeTo)
        self.mid_DEFAULT_MAX_LEN = 10 * DEFAULT_MAX_LEN
        mid_DEFAULT_MAX_LEN = self.mid_DEFAULT_MAX_LEN

        #mid set init cash
        cash_or_brk = 1000000
        volumeLimit = 0.5  #mid used to calculate available volume for an order: availableVolume = volumeLeft * volumeLimit
        #mid set fillstrategy
        fillStrategy = fillstrategy.DefaultStrategy(volumeLimit=volumeLimit)

        broker = backtesting.Broker(cash_or_brk, feed)
        broker.setFillStrategy(fillStrategy)
        #mid init base
        strategy.BacktestingStrategy.__init__(self, feed, broker)

        #mid 计算ma将使用当天的收盘价格计算
        #mid 1)
        self.closePrices = {}
        self.longPosition = {}
        self.shortPosition = {}
        self.buySignal = {}
        self.sellSignal = {}
        self.timeFrom = timeFrom
        self.timeTo = timeTo
        #mid follow vars will be used only this class
        self.__portfolio_value = SequenceDataSeries(
            maxLen=mid_DEFAULT_MAX_LEN)  #mid 记录资产组合(cash + 各个持仓证券的价值和)的合计价值变化
        self.__available_cash = SequenceDataSeries(
            maxLen=mid_DEFAULT_MAX_LEN)  #mid 记录资产组合的现金变化

        self.__long_exitBar_pnl = {}  #mid 多头平仓bar产生的pnl
        self.__long_position_volume = {}  #mid 当前多头数量
        self.__long_position_cost = {}  #mid 当前持有多头开仓成本
        self.__long_position_currentBar_pnl = {}  #mid 当前持有多头当前bar产生的pnl
        self.__long_position_pnl = {}  #mid 当前多头累计产生的pnl

        self.__short_exitBar_pnl = {}
        self.__short_position_volume = {}  #mid 当前持有头寸数量
        self.__short_position_cost = {}  #mid 当前持有头寸开仓成本
        self.__short_position_currentBar_pnl = {}  #mid 当前持有头寸价值
        self.__short_position_pnl = {}

        self.__position_cumulativePNL = {
        }  #mid 当前 symbol 持有头寸cumulative pnl 价值(包括该symbol多头和空头的所有开仓平仓产生的pnl)
        self.__buy = {}
        self.__sell = {}

        for instrument in self.instruments:
            dataSeries = feed[instrument]

            dataSeries.setMaxLen(mid_DEFAULT_MAX_LEN)
            closeSeries = dataSeries.getCloseDataSeries()
            #mid 2)
            prices = closeSeries
            prices.setMaxLen(mid_DEFAULT_MAX_LEN)

            #mid follow vars will be used in subclass
            self.closePrices[instrument] = prices
            self.longPosition[instrument] = None
            self.shortPosition[instrument] = None
            self.buySignal[instrument] = False
            self.sellSignal[instrument] = False

            #mid follow vars will be used only this class
            self.__long_exitBar_pnl[instrument] = None
            self.__short_exitBar_pnl[instrument] = None
            self.__long_position_volume[instrument] = SequenceDataSeries(
                maxLen=mid_DEFAULT_MAX_LEN)  #mid 当前持有头寸数量
            self.__short_position_volume[instrument] = SequenceDataSeries(
                maxLen=mid_DEFAULT_MAX_LEN)  #mid 当前持有头寸数量
            self.__long_position_cost[instrument] = SequenceDataSeries(
                maxLen=mid_DEFAULT_MAX_LEN)  #mid 当前持有头寸开仓成本
            self.__short_position_cost[instrument] = SequenceDataSeries(
                maxLen=mid_DEFAULT_MAX_LEN)  #mid 当前持有头寸开仓成本
            self.__long_position_currentBar_pnl[
                instrument] = SequenceDataSeries(
                    maxLen=mid_DEFAULT_MAX_LEN)  #mid 当前持有头寸价值
            self.__short_position_currentBar_pnl[
                instrument] = SequenceDataSeries(
                    maxLen=mid_DEFAULT_MAX_LEN)  #mid 当前持有头寸价值
            self.__short_position_pnl[instrument] = SequenceDataSeries(
                maxLen=mid_DEFAULT_MAX_LEN)
            self.__long_position_pnl[instrument] = SequenceDataSeries(
                maxLen=mid_DEFAULT_MAX_LEN)
            self.__position_cumulativePNL[instrument] = SequenceDataSeries(
                maxLen=mid_DEFAULT_MAX_LEN)
            self.__buy[instrument] = SequenceDataSeries(
                maxLen=mid_DEFAULT_MAX_LEN)
            self.__sell[instrument] = SequenceDataSeries(
                maxLen=mid_DEFAULT_MAX_LEN)
Ejemplo n.º 28
0
    def __init__(self,
                 feed=None,
                 instrument='',
                 shortPeriod=0,
                 longPeriod=0,
                 money=None,
                 longAllowed=True,
                 shortAllowed=True):
        strategy.BacktestingStrategy.__init__(self, feed)

        self.position_cost = 0  #mid init position value

        mid_DEFAULT_MAX_LEN = 10 * DEFAULT_MAX_LEN
        self.__instrument = instrument
        self.__longPosition = None
        self.__shortPosition = None

        self.__position_volume = SequenceDataSeries(
            maxLen=mid_DEFAULT_MAX_LEN)  #mid 当前持有头寸数量
        self.__position_cost = SequenceDataSeries(
            maxLen=mid_DEFAULT_MAX_LEN)  #mid 当前持有头寸开仓成本
        self.__position_pnl = SequenceDataSeries(
            maxLen=mid_DEFAULT_MAX_LEN)  #mid 当前持有头寸价值
        self.__portfolio_value = SequenceDataSeries(maxLen=mid_DEFAULT_MAX_LEN)
        self.__buy = SequenceDataSeries(maxLen=mid_DEFAULT_MAX_LEN)
        self.__sell = SequenceDataSeries(maxLen=mid_DEFAULT_MAX_LEN)

        self.__buySignal = False
        self.__sellSignal = False
        self.money = money
        self.longAllowed = True
        self.shortAllowed = True
        #mid 计算ma将使用当天的收盘价格计算
        #mid 1)
        dataSeries = feed[instrument]
        dataSeries.setMaxLen(mid_DEFAULT_MAX_LEN)
        closeSeries = dataSeries.getOpenDataSeries()
        #mid 2)
        prices = closeSeries
        prices.setMaxLen(mid_DEFAULT_MAX_LEN)
        #mid 3)
        self.__sma = ma.SMA(prices, shortPeriod, maxLen=mid_DEFAULT_MAX_LEN)
        self.__lma = ma.SMA(prices, longPeriod, maxLen=mid_DEFAULT_MAX_LEN)

        self.i = 0
Ejemplo n.º 29
0
class bollinger_band(strategy.BacktestingStrategy):
    def __init__(self, feed, instrument, bollingerlength, numStdDev):
        strategy.BacktestingStrategy.__init__(self, feed)
        self.getBroker().setFillStrategy(DefaultStrategy(None))
        self.getBroker().setCommission(TradePercentage(0))
        self.__instrument = instrument
        self.__bollingerlength = int(bollingerlength)
        self.__close = feed[instrument].getPriceDataSeries()
        numStdDev = float(numStdDev) / 10
        self.__longPos = []
        self.__macd=macd.MACD(self.__close,50,150,10)
        self.__bollinger = bollinger.BollingerBands(self.__macd, self.__bollingerlength, int(numStdDev))
        self.__UpperBand = self.__bollinger.getUpperBand()
        self.__LowerBand = self.__bollinger.getLowerBand()

        self.__position = SequenceDataSeries()
        self.__circ=5
    def getPrice(self):
        return self.__prices

    def getMACD(self):
        return self.__macd

    def getBollingerBands(self):
        return self.__bollinger

    def testCon(self):
        # record position
        #######################################################################
        if len(self.__longPos) > 0:
            self.__position.append(len(self.__longPos))
        elif len(self.__longPos)==0 :
            self.__position.append(0)
            #print(0)


    def getTest(self):
        return self.__position

    def onBars(self, bars):
        bar = bars[self.__instrument]
        lower = self.__bollinger.getLowerBand()[-1]
        upper = self.__bollinger.getUpperBand()[-1]
       # print(self.getActivePositions())
        if lower is None:
            return
        self.testCon()
        if len(self.__longPos)> 0:
            if self.exitLongSignal():
               for pos in self.__longPos:
                   pos.exitMarket()
        elif len(self.__longPos)<5 :
            if self.enterLongSignal():
                shares =1
               # self.__longPos.
                self.__longPos.append(self.enterLong(self.__instrument, shares))

    def enterLongSignal (self) :
        if self.__UpperBand[-1-self.__circ] is None:
            return False
        m1 = 0
        for i in range(self.__circ):
            if self.__macd[-i-1] <= self.__LowerBand[-i-2]:
                m1 += 1
        if m1 >= self.__circ-1 and cross.cross_above(self.__macd,self.__LowerBand)>0:
            return True
        else:
            return False

    def enterShortSignal(self) :
        if self.__UpperBand[-1-self.__circ] is None:
            return False
        m1 = 0
        for i in range(self.__circ):
            if self.__macd[-i-1] >= self.__UpperBand[-i-2]:
                m1 += 1
        if m1 >= self.__circ-1 and cross.cross_below(self.__macd,self.__UpperBand)>0:
            return True
        else:
            return False

    def exitLongSignal(self) :
        if self.__UpperBand[-1-self.__circ] is None:
            return False
        m1 = 0
        for i in range(self.__circ):
            if self.__macd[-i-1] >= self.__UpperBand[-i-2]:
                m1 += 1
        if m1 >= self.__circ-1 and cross.cross_below(self.__macd,self.__UpperBand)>0:
            return True
        else:
            return False

    def exitShortSignal(self):
        if self.__UpperBand[-1-self.__circ] is None:
            return False
        m1 = 0
        for i in range(self.__circ):
            if self.__macd[-i-1] <= self.__LowerBand[-i-2]:
                m1 += 1
        if m1 >= self.__circ-1 and cross.cross_above(self.__macd,self.__LowerBand)>0:
            return True
        else:
            return False


    def onEnterCanceled(self, position):
        if len(self.__longPos)>0:
            if self.__longPos[-1] == position:
                del self.__longPos[-1]
        #else:
            #assert(False)

    def onEnterOK(self,position):
        pass

    def onExitOk(self, position):
        if isinstance(position,LongPosition):
            self.__longPos = []
        else:
            assert(False)

    def onExitCanceled(self, position):
        position.exitMarket()
Ejemplo n.º 30
0
def metric_goquant_to_backtest(metric_data_series):
    ret = SequenceDataSeries()
    for i, v in metric_data_series.items():
        ret.appendWithDateTime(i, v)
    return ret
Ejemplo n.º 31
0
class SingleMA(strategy.BacktestingStrategy):
    def __init__(self, feed, instrument, n, initialCash = 1000000):
        strategy.BacktestingStrategy.__init__(self, feed, initialCash)
        self.__instrument = instrument
        self.getBroker().setFillStrategy(DefaultStrategy(None))
        self.getBroker().setCommission(TradePercentage(0.001))
        self.__position = None
        self.__prices = feed[instrument].getPriceDataSeries()
        self.__malength = int(n)
        self.__ma = ma.SMA(self.__prices, self.__malength)
        self.__pos = SequenceDataSeries() # record signal

    def getPrice(self):
        return self.__prices

    def getMA(self):
        return self.__ma

    def testCon(self):
        if self.__position is not None:
            self.__pos.append(1)
        elif self.__position is None:
            self.__pos.append(0)

    def getPos(self):
        return self.__pos

    def onEnterCanceled(self, position):
        self.__position = None

    def onEnterOk(self, position):
        execInfo = position.getEntryOrder().getExecutionInfo()
        instrumentInfo = position.getInstrument()
        self.info("BUY %s at $%.2f" % (instrumentInfo, execInfo.getPrice()))

    def onExitOk(self, position):
        execInfo = position.getExitOrder().getExecutionInfo()
        instrumentInfo = position.getInstrument()
        self.info("SELL %s at $%.2f" % (instrumentInfo, execInfo.getPrice()))
        self.__position = None

    def onExitCancelled(self, position):
        self.__position.exitMarket()


    def onBars(self, bars):
        closePrice = bars[self.__instrument].getPrice()

        if self.__ma[-1] is None:
            return

        self.testCon()

        if self.__position is not None:
            if not self.__position.exitActive() and closePrice < self.__ma[-1]:
                self.__position.exitMarket()

        if self.__position is None:
            if closePrice > self.__ma[-1]:
                shares = int(self.getBroker().getEquity() * 0.9 / closePrice)
                self.__position = self.enterLong(self.__instrument, shares)
Ejemplo n.º 32
0
    def initEa(self,timeFrom=None,timeTo=None):
        self.results = {}
        feed = self.getFeedNew(timeFrom = timeFrom,timeTo = timeTo)
        self.mid_DEFAULT_MAX_LEN = 10 * DEFAULT_MAX_LEN
        mid_DEFAULT_MAX_LEN = self.mid_DEFAULT_MAX_LEN
        
        #mid set init cash
        cash_or_brk = 1000000
        volumeLimit = 0.5       #mid used to calculate available volume for an order: availableVolume = volumeLeft * volumeLimit
        #mid set fillstrategy
        fillStrategy = fillstrategy.DefaultStrategy(volumeLimit = volumeLimit)
        
        broker = backtesting.Broker(cash_or_brk, feed)
        broker.setFillStrategy(fillStrategy)
        #mid init base
        strategy.BacktestingStrategy.__init__(self, feed,broker)
        
        #mid 计算ma将使用当天的收盘价格计算
        #mid 1)
        self.closePrices = {}
        self.longPosition = {}
        self.shortPosition = {}
        self.buySignal = {}
        self.sellSignal = {}        
        self.timeFrom = timeFrom
        self.timeTo = timeTo        
        #mid follow vars will be used only this class
        self.__portfolio_value = SequenceDataSeries(maxLen = mid_DEFAULT_MAX_LEN)
        self.__available_cash  = SequenceDataSeries(maxLen = mid_DEFAULT_MAX_LEN)
        
        self.__exitBar_position_pnl    = {}
        
        self.__curLongPositionCost = {}         #mid init position value
        self.__curShortPositionCost = {}        #mid init position value
        
        self.__position_volume = {}         #mid 当前持有头寸数量
        self.__position_cost = {}           #mid 当前持有头寸开仓成本
        self.__position_pnl = {}            #mid 当前持有头寸价值
        self.__position_cumulativePNL = {}  #mid 当前 symbol 持有头寸cumulative pnl 价值
        self.__buy = {}
        self.__sell = {}    
        
        for instrument in self.instruments:
            dataSeries = feed[instrument]
            
            
            dataSeries.setMaxLen(mid_DEFAULT_MAX_LEN)       
            closeSeries = dataSeries.getCloseDataSeries()
            #mid 2)
            prices = closeSeries
            prices.setMaxLen(mid_DEFAULT_MAX_LEN)        
            
            #mid follow vars will be used in subclass
            self.closePrices[instrument] = prices
            self.longPosition[instrument] = None
            self.shortPosition[instrument] = None
            self.buySignal[instrument] = False
            self.sellSignal[instrument] = False

            #mid follow vars will be used only this class
            self.__curLongPositionCost[instrument] = 0                                                      #mid init position value
            self.__curShortPositionCost[instrument] = 0   
            self.__exitBar_position_pnl[instrument] = None
            #mid init position value
            self.__position_volume[instrument] = SequenceDataSeries(maxLen = mid_DEFAULT_MAX_LEN)       #mid 当前持有头寸数量
            self.__position_cost[instrument] = SequenceDataSeries(maxLen = mid_DEFAULT_MAX_LEN)         #mid 当前持有头寸开仓成本
            self.__position_pnl[instrument] = SequenceDataSeries(maxLen = mid_DEFAULT_MAX_LEN)          #mid 当前持有头寸价值
            self.__position_cumulativePNL[instrument] = SequenceDataSeries(maxLen = mid_DEFAULT_MAX_LEN)
            self.__buy[instrument] = SequenceDataSeries(maxLen = mid_DEFAULT_MAX_LEN)
            self.__sell[instrument] = SequenceDataSeries(maxLen = mid_DEFAULT_MAX_LEN) 
Ejemplo n.º 33
0
class midBaseStrategy(strategy.BacktestingStrategy):
    def getFeeds(self, timeFrom=None, timeTo=None):
        import os, sys
        xpower = os.path.abspath(
            os.path.join(os.path.dirname(__file__), os.pardir, os.pardir,
                         os.pardir, 'midProjects', 'histdata'))
        sys.path.append(xpower)

        import dataCenter as dataCenter
        self.dataCenter = dataCenter.dataCenter()
        feeds = self.dataCenter.getFeedsForPAT(dataProvider=self.dataProvider,
                                               storageType=self.storageType,
                                               instruments=self.instruments,
                                               period=self.period,
                                               timeTo=timeTo,
                                               timeFrom=timeFrom)
        return feeds

    def getFeedNew(self, timeFrom=None, timeTo=None):
        '''mid should not be named the same with base class'''
        import os, sys
        xpower = os.path.abspath(
            os.path.join(os.path.dirname(__file__), os.pardir, os.pardir,
                         os.pardir, 'midProjects', 'histdata'))
        sys.path.append(xpower)

        import dataCenter as dataCenter
        self.dataCenter = dataCenter.dataCenter()
        feed = self.dataCenter.getFeedForPAT(dataProvider=self.dataProvider,
                                             storageType=self.storageType,
                                             instruments=self.instruments,
                                             period=self.period,
                                             timeTo=timeTo,
                                             timeFrom=timeFrom)
        return feed

    def initEa(self, timeFrom=None, timeTo=None):
        self.results = {}
        feed = self.getFeedNew(timeFrom=timeFrom, timeTo=timeTo)
        self.mid_DEFAULT_MAX_LEN = 10 * DEFAULT_MAX_LEN
        mid_DEFAULT_MAX_LEN = self.mid_DEFAULT_MAX_LEN

        #mid set init cash
        cash_or_brk = 1000000
        volumeLimit = 0.5  #mid used to calculate available volume for an order: availableVolume = volumeLeft * volumeLimit
        #mid set fillstrategy
        fillStrategy = fillstrategy.DefaultStrategy(volumeLimit=volumeLimit)

        broker = backtesting.Broker(cash_or_brk, feed)
        broker.setFillStrategy(fillStrategy)
        #mid init base
        strategy.BacktestingStrategy.__init__(self, feed, broker)

        #mid 计算ma将使用当天的收盘价格计算
        #mid 1)
        self.closePrices = {}
        self.longPosition = {}
        self.shortPosition = {}
        self.buySignal = {}
        self.sellSignal = {}
        self.timeFrom = timeFrom
        self.timeTo = timeTo
        #mid follow vars will be used only this class
        self.__portfolio_value = SequenceDataSeries(
            maxLen=mid_DEFAULT_MAX_LEN)  #mid 记录资产组合(cash + 各个持仓证券的价值和)的合计价值变化
        self.__available_cash = SequenceDataSeries(
            maxLen=mid_DEFAULT_MAX_LEN)  #mid 记录资产组合的现金变化

        self.__long_exitBar_pnl = {}  #mid 多头平仓bar产生的pnl
        self.__long_position_volume = {}  #mid 当前多头数量
        self.__long_position_cost = {}  #mid 当前持有多头开仓成本
        self.__long_position_currentBar_pnl = {}  #mid 当前持有多头当前bar产生的pnl
        self.__long_position_pnl = {}  #mid 当前多头累计产生的pnl

        self.__short_exitBar_pnl = {}
        self.__short_position_volume = {}  #mid 当前持有头寸数量
        self.__short_position_cost = {}  #mid 当前持有头寸开仓成本
        self.__short_position_currentBar_pnl = {}  #mid 当前持有头寸价值
        self.__short_position_pnl = {}

        self.__position_cumulativePNL = {
        }  #mid 当前 symbol 持有头寸cumulative pnl 价值(包括该symbol多头和空头的所有开仓平仓产生的pnl)
        self.__buy = {}
        self.__sell = {}

        for instrument in self.instruments:
            dataSeries = feed[instrument]

            dataSeries.setMaxLen(mid_DEFAULT_MAX_LEN)
            closeSeries = dataSeries.getCloseDataSeries()
            #mid 2)
            prices = closeSeries
            prices.setMaxLen(mid_DEFAULT_MAX_LEN)

            #mid follow vars will be used in subclass
            self.closePrices[instrument] = prices
            self.longPosition[instrument] = None
            self.shortPosition[instrument] = None
            self.buySignal[instrument] = False
            self.sellSignal[instrument] = False

            #mid follow vars will be used only this class
            self.__long_exitBar_pnl[instrument] = None
            self.__short_exitBar_pnl[instrument] = None
            self.__long_position_volume[instrument] = SequenceDataSeries(
                maxLen=mid_DEFAULT_MAX_LEN)  #mid 当前持有头寸数量
            self.__short_position_volume[instrument] = SequenceDataSeries(
                maxLen=mid_DEFAULT_MAX_LEN)  #mid 当前持有头寸数量
            self.__long_position_cost[instrument] = SequenceDataSeries(
                maxLen=mid_DEFAULT_MAX_LEN)  #mid 当前持有头寸开仓成本
            self.__short_position_cost[instrument] = SequenceDataSeries(
                maxLen=mid_DEFAULT_MAX_LEN)  #mid 当前持有头寸开仓成本
            self.__long_position_currentBar_pnl[
                instrument] = SequenceDataSeries(
                    maxLen=mid_DEFAULT_MAX_LEN)  #mid 当前持有头寸价值
            self.__short_position_currentBar_pnl[
                instrument] = SequenceDataSeries(
                    maxLen=mid_DEFAULT_MAX_LEN)  #mid 当前持有头寸价值
            self.__short_position_pnl[instrument] = SequenceDataSeries(
                maxLen=mid_DEFAULT_MAX_LEN)
            self.__long_position_pnl[instrument] = SequenceDataSeries(
                maxLen=mid_DEFAULT_MAX_LEN)
            self.__position_cumulativePNL[instrument] = SequenceDataSeries(
                maxLen=mid_DEFAULT_MAX_LEN)
            self.__buy[instrument] = SequenceDataSeries(
                maxLen=mid_DEFAULT_MAX_LEN)
            self.__sell[instrument] = SequenceDataSeries(
                maxLen=mid_DEFAULT_MAX_LEN)

    def getAssetStructure(self):
        #mid --------------------------------
        #mid 当前账户资产结构如下方式获取
        #mid Long 和 Short不会同时存在
        #mid 在开仓前,若有反向持仓,则此过程查询并输出已持有的反向持仓
        broker = self.getBroker()
        portfolio_value = broker.getEquity()
        cash = broker.getCash()
        if self.shortPosition is not None or self.longPosition is not None:
            bars = self.getFeed().getCurrentBars()

            positions = broker.getPositions()

            positionsOpenValue = {}
            positionsCloseValue = {}
            for key, value in positions.items():
                print "key:" + key + ",value:" + str(value)
                bar = bars.getBar(key)
                openPrice = bar.getOpen()
                closePrice = bar.getClose()
                share = broker.getShares(key)
                positionsOpenValue[key] = openPrice * share
                positionsCloseValue[key] = closePrice * share

            print
            print 'current bar asset structure'
            print 'open cash %2.f.' % (cash)
            for key, value in positionsOpenValue.items():
                print "key:" + key + ",value:" + str(value)
            print 'close cash %2.f.' % (cash)
            for key, value in positionsCloseValue.items():
                print "key:" + key + ",value:" + str(value)
            print 'portfolio:%2.f' % (portfolio_value)

            return portfolio_value, cash, sum(positionsCloseValue.values())
        return portfolio_value, cash, 0

    def sampleSub01(self, instrument):
        """mid not called anywhere
        because of open price gap,method below is not right.
        """
        broker = self.getBroker()
        a = broker.getEquity()
        b = self.getResult()

        lastOpenPrice = None
        lastClosePrice = None
        bar = self.getFeed().getLastBar(instrument)
        if bar is not None:
            lastOpenPrice = bar.getOpen()
            lastClosePrice = bar.getClose()
            #lastPrice = self.getLastPrice(instrument)

            pnl = (lastClosePrice - lastOpenPrice) * share
        else:
            pnl = 0  #mid instrument is dislisted.
        if (len(self.__position_cumulativePNL[instrument]) > 0):
            lastCumulativePNL = self.__position_cumulativePNL[instrument][-1]
        else:
            lastCumulativePNL = 0

    def recordAccount(self):
        # record position
        #######################################################################
        broker = self.getBroker()
        curTime = self.getCurrentDateTime()
        currentTime = self.getCurrentDateTime()
        cash = broker.getCash(includeShort=False)
        portfolio_value = broker.getEquity()  #mid 按close价格计算的权益

        print
        self.info("onBars().recordAccount().Current time:%s" %
                  (str(currentTime)))
        self.info("onBars().recordAccount().----portfolio value: %.2f" %
                  (portfolio_value))
        self.info("onBars().recordAccount().----cash in portfolio: %.2f" %
                  (cash))

        self.__portfolio_value.appendWithDateTime(currentTime, portfolio_value)
        self.__available_cash.appendWithDateTime(currentTime, cash)
        totalCumulativePNL = 0

        time = self.getCurrentDateTime()
        if (time == dt.datetime(2010, 12, 22, 0, 0)):
            a = 8

        for instrument in self.instruments:
            lastClosePrice = self.getLastPrice(instrument)
            if (lastClosePrice is None):
                continue
            #position_value = lastClosePrice*share
            longPosition = self.longPosition[instrument]
            longQuantity = 0
            longPnl = 0
            longStandingCurBarPnl = 0
            longValue = 0
            longCost = 0

            shortPosition = self.shortPosition[instrument]
            shortQuantity = 0
            shortPnl = 0
            shortStandingCurBarPnl = 0
            shortValue = 0
            shortCost = 0

            if (longPosition):
                entryInfo = longPosition.getEntryOrder()
                execInfo = entryInfo.getExecutionInfo()
                if (execInfo):
                    longPnl = longPosition.getPnL()
                    longStandingCurBarPnl = longPnl - self.__lastLongPnl

                    longQuantity = longPosition.getQuantity()
                    longCostPrice = execInfo.getPrice()
                    longCost = longQuantity * longCostPrice

                    self.__lastLongPnl = longPnl
            if (shortPosition):
                entryInfo = shortPosition.getEntryOrder()
                execInfo = entryInfo.getExecutionInfo()
                if (execInfo):
                    shortPnl = shortPosition.getPnL()
                    shortStandingCurBarPnl = shortPnl - self.__lastShortPnl

                    shortQuantity = shortPosition.getQuantity()
                    shortCostPrice = execInfo.getPrice()
                    shortCost = shortQuantity * shortCostPrice

                    self.__lastShortPnl = shortPnl

            if (self.__long_exitBar_pnl[instrument]):
                self.__long_position_currentBar_pnl[
                    instrument].appendWithDateTime(
                        currentTime, self.__long_exitBar_pnl[instrument])
                self.__long_exitBar_pnl[instrument] = None
            else:
                self.__long_position_currentBar_pnl[
                    instrument].appendWithDateTime(currentTime,
                                                   longStandingCurBarPnl)

            if (self.__short_exitBar_pnl[instrument]):
                self.__short_position_currentBar_pnl[
                    instrument].appendWithDateTime(
                        currentTime, self.__short_exitBar_pnl[instrument])
                self.__short_exitBar_pnl[instrument] = None
            else:
                self.__short_position_currentBar_pnl[
                    instrument].appendWithDateTime(currentTime,
                                                   shortStandingCurBarPnl)

            #self.__short_position_pnl[instrument].appendWithDateTime(currentTime,shortCurBarPnl)

            self.__long_position_pnl[instrument].appendWithDateTime(
                currentTime, longPnl)
            self.__short_position_pnl[instrument].appendWithDateTime(
                currentTime, shortPnl)

            self.__long_position_cost[instrument].appendWithDateTime(
                currentTime, longCost)
            self.__short_position_cost[instrument].appendWithDateTime(
                currentTime, shortCost)

            self.__long_position_volume[instrument].appendWithDateTime(
                currentTime, longQuantity)
            self.__short_position_volume[instrument].appendWithDateTime(
                currentTime, shortQuantity)
            self.__buy[instrument].appendWithDateTime(
                currentTime, self.buySignal[instrument])
            self.__sell[instrument].appendWithDateTime(
                currentTime, self.sellSignal[instrument])

            cumulativePNL = 0
            longCurBarPnl = self.__long_position_currentBar_pnl[instrument][-1]
            shortCurBarPnl = self.__short_position_currentBar_pnl[instrument][
                -1]
            currentBarPnl = longCurBarPnl + shortCurBarPnl

            if (len(self.__position_cumulativePNL[instrument]) > 0):
                lastCumulativePNL = self.__position_cumulativePNL[instrument][
                    -1]
                cumulativePNL = lastCumulativePNL + currentBarPnl
            else:
                cumulativePNL = currentBarPnl

            self.__position_cumulativePNL[instrument].appendWithDateTime(
                currentTime, cumulativePNL)
            """mid
            如果当前bar有某个position在open price被closed掉,则当前bar的position_pnl是0.
            在当前bar的openprice和上一bar的closeprice之间没有gap时,这个算法是合理的,但是,gap往往是存在的,
            所以,据此计算的barPnl在exitbar上会有gap导致的误差
            在此特别处理exitbar                
            """
            """
            if(self.__exitBar_position_pnl[instrument] is not None):

                currentExitedPositionPnl = self.__exitBar_position_pnl[instrument]
                lastPositionPnl = self.__position_pnl[instrument][-2]
                currentBarExitedPnl = currentExitedPositionPnl - lastPositionPnl                
                self.__exitBar_position_pnl[instrument] = None   
                currentBarPnl = currentBarPnl + currentBarExitedPnl
            if(len(self.__position_cumulativePNL[instrument])>0):
                lastCumulativePNL = self.__position_cumulativePNL[instrument][-1]
                cumulativePNL = lastCumulativePNL + currentBarPnl
            else:
                cumulativePNL = currentBarPnl   

            self.__position_cumulativePNL[instrument].appendWithDateTime(currentTime,cumulativePNL)  
        """

            if (True):
                self.info("onBars().recordAccount().--------%s" % (instrument))

                self.info(
                    "onBars().recordAccount().--------mid current bar longPNL: %.3f"
                    % (longCurBarPnl))
                self.info(
                    "onBars().recordAccount().--------mid current bar longQuantity:%.3f"
                    % (longQuantity))
                self.info(
                    "onBars().recordAccount().--------mid current bar longValue: %.3f"
                    % (longValue))
                self.info(
                    "onBars().recordAccount().--------mid current bar longCost: %.3f"
                    % (longCost))

                self.info(
                    "onBars().recordAccount().--------mid current bar shortPNL: %.3f"
                    % (shortPnl))
                self.info(
                    "onBars().recordAccount().--------mid current bar shortQuantity:%.3f"
                    % (shortQuantity))
                self.info(
                    "onBars().recordAccount().--------mid calculated position value: %.3f"
                    % (shortValue))
                self.info(
                    "onBars().recordAccount().--------mid calculated shortPnl: %.3f"
                    % (shortCost))

                self.info(
                    "onBars().recordAccount().--------mid CumulativePNL: %.3f"
                    % (cumulativePNL))
            totalCumulativePNL = totalCumulativePNL + cumulativePNL

        if (abs(1000000 -
                (portfolio_value - totalCumulativePNL)) > 0.00000001):
            self.info("onBars().recordAccount().--------mid initCash: %.3f" %
                      (portfolio_value - totalCumulativePNL))
            a = 8

    def getPortfolioValue(self):
        return self.__portfolio_value

    def getAvailableCash(self):
        return self.__available_cash

    def getCurInstrument(self):
        return self.curInstrument

    def getPositionValue(self, instrument):
        return self.__position_cumulativePNL[instrument]

    def getLongVolume(self, instrument):
        return self.__long_position_volume[instrument]

    def getShortVolume(self, instrument):
        return self.__short_position_volume[instrument]

    def getLongCost(self, instrument):
        return self.__long_position_cost[instrument]

    def getShortCost(self, instrument):
        return self.__short_position_cost[instrument]

    def getLongPnl(self, instrument):
        return self.__long_position_pnl[instrument]

    def getShortPnl(self, instrument):
        return self.__short_position_pnl[instrument]

    def getBuy(self, instrument):
        return self.__buy[instrument]

    def getSell(self, instrument):
        return self.__sell[instrument]

    def onEnterOk(self, position):
        '''mid
        由于getEquity()返回的是依据当日close价格计算出来的权益
        所以,这个值不能作为持仓成本
        持仓成本需要以onEnterOk时bar的open价格计算
        由于经常有跳开现象,所以依据bar(n-1).close发出的market order,
        在bar(n).open执行时通常会有gap出现,表现在position_cost图上时就是持有成本离计划成本会有跳口,
        '''
        print
        currentTime = self.getCurrentDateTime()
        execInfo = position.getEntryOrder().getExecutionInfo()
        self.info("onEnterOK().ExecutionInfo.Current time: %s" %
                  (execInfo.getDateTime()))

        #mid 1)record the position cost
        instrument = position.getInstrument()
        feed = self.getFeed()
        bars = feed.getCurrentBars()
        bar = bars.getBar(instrument)
        openPrice = bar.getOpen()
        closePrice = self.getLastPrice(
            instrument)  #mid lastPrice == closePrice

        #mid 2)log account info after enterOKed.
        execInfo = position.getEntryOrder().getExecutionInfo()
        portfolio = self.getResult()
        cash = self.getBroker().getCash()
        self.info("onEnterOk().symbol:%s" % (instrument))
        self.info("onEnterOk().current available cash: %.2f,portfolio: %.2f." %
                  (cash, portfolio))
        if isinstance(position, strategy.position.LongPosition):
            self.__lastLongPnl = 0
            self.info("onEnterOK().ExecutionInfo: %s,OPEN LONG %.2f at $%.2f" %
                      (execInfo.getDateTime(), execInfo.getQuantity(),
                       execInfo.getPrice()))
        elif isinstance(position, strategy.position.ShortPosition):
            self.__lastShortPnl = 0
            self.info(
                "onEnterOK().ExecutionInfo: %s,OPEN SHORT %.2f at $%.2f" %
                (execInfo.getDateTime(), execInfo.getQuantity(),
                 execInfo.getPrice()))

    def onEnterCanceled(self, position):
        instrument = position.getInstrument()

        self.info("onEnterCanceled().current available cash: %.2f." %
                  (self.getBroker().getCash()))
        if isinstance(position, strategy.position.LongPosition):
            self.longPosition[instrument] = None
            self.info("onEnterCanceled().OPEN LONG cancled.")
        elif isinstance(position, strategy.position.ShortPosition):
            self.shortPosition[instrument] = None
            self.info("onEnterCanceled().OPEN SHORT cancled.")

    def onExitOk(self, position):
        exitInfo = position.getExitOrder().getExecutionInfo()
        entryInfo = position.getEntryOrder().getExecutionInfo()
        instrument = position.getInstrument()

        print
        currentTime = self.getCurrentDateTime()
        self.info("onExitOk().ExecutionInfo.Current time: %s" %
                  (exitInfo.getDateTime()))
        self.info("onExitOk().instrument:%s." % (instrument))

        exitQuantity = exitInfo.getQuantity()
        exitPrice = exitInfo.getPrice()
        exitAmount = exitQuantity * exitPrice

        entryQuantity = entryInfo.getQuantity()
        entryPrice = entryInfo.getPrice()
        entryCost = entryQuantity * entryPrice
        #self.sampleSub01(instrument)
        if isinstance(position, strategy.position.LongPosition):
            positionCost = entryCost

            longPnl = position.getPnL()
            longCurBarPnl = longPnl - self.__lastLongPnl
            #self.__long_position_pnl[instrument].appendWithDateTime(currentTime,longCurBarPnl)
            self.__long_exitBar_pnl[instrument] = longCurBarPnl
            self.longPosition[instrument] = None
            self.info("onExitOk().ExecutionInfo: %s,CLOSE LONG %.2f at $%.2f" %
                      (exitInfo.getDateTime(), exitQuantity, exitPrice))
        elif isinstance(position, strategy.position.ShortPosition):
            positionCost = entryCost

            shortPnl = position.getPnL()
            shortCurBarPnl = shortPnl - self.__lastShortPnl
            #self.__long_position_pnl[instrument].appendWithDateTime(currentTime,longCurBarPnl)
            self.__short_exitBar_pnl[instrument] = shortCurBarPnl
            self.shortPosition[instrument] = None
            self.info("onExitOk().ExecutionInfo: %s,CLOSE LONG %.2f at $%.2f" %
                      (exitInfo.getDateTime(), exitQuantity, exitPrice))

    def onExitCanceled(self, position):
        # If the exit was canceled, re-submit it.
        if isinstance(position, strategy.position.LongPosition):
            self.longPosition[instrument] = None
        elif isinstance(position, strategy.position.ShortPosition):
            self.shortPosition[instrument] = None

    def logInfo(self, bars=None):
        pLong, pShort = 0, 0
        if (self.longPosition is not None):
            pLong = self.longPosition.getShares()
        if (self.shortPosition is not None):
            pShort = self.shortPosition.getShares()

        bar = bars[self.instrument]
        pOpen = bar.getOpen()
        pHigh = bar.getHigh()
        pLow = bar.getLow()
        pClose = bar.getClose()
        pPrice = bar.getPrice()

        self.info(
            'logInfo().price:%.3f,open:%.2f,high:%.2f,low:%.2f,close:%.2f' %
            (pPrice, pOpen, pHigh, pLow, pClose))
        #self.info('long:%.2f#short:%.2f'%(pLong,pShort))
    def closePosition(self):
        for instrument in self.instruments:
            if (self.longPosition[instrument] is not None
                    and self.sellSignal[instrument] == True
                    and not self.longPosition[instrument].exitActive()):
                print
                self.info("onBars().closePosition(), instrument:%s" %
                          (instrument))
                self.info(
                    "onBars().closePosition(), LONG POSITION to close %.2f" %
                    (self.longPosition[instrument].getShares()))
                self.longPosition[instrument].exitMarket()
            if (self.shortPosition[instrument] is not None
                    and self.buySignal[instrument] == True
                    and not self.shortPosition[instrument].exitActive()):
                print
                self.info("onBars().closePosition(), instrument:%s" %
                          (instrument))
                self.info(
                    "onBars().closePosition(), SHORT POSITION to close %.2f" %
                    (self.shortPosition[instrument].getShares()))
                self.shortPosition[instrument].exitMarket()

    def openPosition(self):
        '''mid
        此处是onBars,这个和zipline的概念完全不同
        zipline中,需要覆写的是handle_data,这个东西是个tick概念,所以没有OHLC的,只是个price
        PAT中,每次onBars,都会传入一个newbar的OHLC,此时,要如何按这个OHLC决策,全由你
        依据OHLC做完决策后,可以发送交易指令:
        * Order.Type.MARKET
        * Order.Type.LIMIT
        * Order.Type.STOP
        * Order.Type.STOP_LIMIT
        1.市价单,依据下一个bar的openPrice执行命令:
            self.enterLong()
        2.限价单
        3.止损单市价单
        4.止损限价单

        当前似乎没有止盈单

        在均线策略中,应该在每个newbar到来时,按closePrice的均线计算指标值,然后发送市价单
        1.每个newbar按close价格计算指标,并在下一个bar按open成交
        2.每个newbar按open价格计算指标,并在此newbar按open成交
        以上1,2的计算逻辑是一致的。如果当前bar的close和下一个bar的open相差无几时,两种算法的回测结果也应相差无几
        '''
        # mid 2)open
        if (self.shortAllowed):
            for instrument in self.instruments:
                self.curInstrument = instrument
                if (self.sellSignal[instrument] == True):
                    # Enter a buy market order. The order is good till canceled.
                    bar = self.getFeed().getLastBar(instrument)
                    volume = 0
                    lastClose = 0
                    if bar is not None:
                        volume = bar.getVolume()
                        lastClose = bar.getClose()
                    shares = self.money.getShares(strat=self)
                    print
                    self.info("onBars().openPosition(), instrument %s" %
                              (instrument))
                    self.info(
                        "onBars().openPosition(), SHORT POSITION to open %.2f"
                        % (shares))
                    self.info("onBars().openPosition(), lastClose: %.2f,%.2f" %
                              (self.getLastPrice(instrument), lastClose))
                    self.info("onBars().openPosition(), need amount: %.2f" %
                              (shares * self.getLastPrice(instrument)))
                    self.info(
                        "onBars().openPosition(), available amount: %.2f." %
                        (self.getBroker().getCash()))
                    self.info(
                        "onBars().openPosition(), available volume: %.2f." %
                        (volume))
                    self.shortPosition[instrument] = self.enterShort(
                        instrument, shares, True)

        if (self.longAllowed):
            for instrument in self.instruments:
                self.curInstrument = instrument
                if (self.buySignal[instrument] == True):
                    shares = self.money.getShares(strat=self)
                    print
                    self.info("onBars().openPosition(), instrument %s" %
                              (instrument))
                    self.info(
                        "onBars().openPosition(), LONG POSITION to open %.2f" %
                        (shares))
                    self.info("onBars().openPosition(), need amount: %.2f." %
                              (shares * self.getLastPrice(instrument)))
                    self.info(
                        "onBars().openPosition(), available amount: %.2f." %
                        (self.getBroker().getCash()))
                    self.longPosition[instrument] = self.enterLong(
                        instrument, shares, True)

    def __analiseEachSymbol(self, instrument):
        dataForCandle = self.dataCenter.getCandleData(
            dataProvider=self.dataProvider,
            dataStorage=self.storageType,
            dataPeriod=self.period,
            symbol=instrument,
            dateStart=self.timeFrom,
            dateEnd=self.timeTo)
        self.analyzer.analyseEachSymbol(self.results[instrument],
                                        dataForCandle,
                                        InKLine=self.InKLine)

    def __analiseSummary(self):
        dataProvider = self.benchDataProvider
        instrument = self.benchSymbol
        dataForCandle = self.dataCenter.getCandleData(
            dataProvider=dataProvider,
            dataStorage=self.storageType,
            dataPeriod=self.period,
            symbol=instrument,
            dateStart=self.timeFrom,
            dateEnd=self.timeTo)
        self.analyzer.analyseSummary(self.result, dataForCandle)

    def run(self, timeFrom=None, timeTo=None):
        self.initEa(timeFrom=timeFrom, timeTo=timeTo)

        self.initIndicators()
        #self.strat.setUseAdjustedValues(False)

        self.initAnalyzer()

        strategy.BacktestingStrategy.run(self)

        for instrument in self.instruments:
            buy = self.getBuy(instrument)
            sell = self.getSell(instrument)

            position_value = self.getPositionValue(instrument)
            long_volume = self.getLongVolume(instrument)
            short_volume = self.getShortVolume(instrument)
            long_cost = self.getLongCost(instrument)
            long_pnl = self.getLongPnl(instrument)
            short_cost = self.getShortCost(instrument)
            short_pnl = self.getShortPnl(instrument)

            self.results[instrument] = pd.DataFrame(
                {
                    'long_volume': list(long_volume),
                    'long_cost': list(long_cost),
                    'long_pnl': list(long_pnl),
                    'short_cost': list(short_cost),
                    'short_pnl': list(short_pnl),
                    'buy': list(buy),
                    'sell': list(sell),
                    'position_value': list(position_value)
                },
                columns=[
                    'long_volume', 'long_cost', 'long_pnl', 'short_cost',
                    'short_pnl', 'buy', 'sell', 'position_value'
                ],
                index=long_volume.getDateTimes())
            self.addIndicators(instrument)
            #------------------------------------

            if (self.toPlotEachSymbol):
                self.__analiseEachSymbol(instrument)

        if (self.toPlotSummary):
            portfolio_value = self.getPortfolioValue()
            available_cash = self.getAvailableCash()

            self.result = pd.DataFrame(
                {
                    'available_cash': list(available_cash),
                    'portfolio_value': list(portfolio_value)
                },
                columns=['available_cash', 'portfolio_value'],
                index=portfolio_value.getDateTimes())
            self.__analiseSummary()
        return self.results

    #mid from ea
    #----------------------------------------------------------------------
    def summary(self):
        return "from %s to %s:returns:%.2f%%,sharpe:%.2f,MaxDrawdown:%.2f%%,Longest drawdown duration:(%s)" % (
            str(self.timeFrom), str(self.timeTo),
            self.returnsAnalyzer.getCumulativeReturns()[-1] * 100,
            self.sharpeRatioAnalyzer.getSharpeRatio(0.05),
            self.drawdownAnalyzer.getMaxDrawDown() * 100,
            self.drawdownAnalyzer.getLongestDrawDownDuration())

    def detail(self):
        """"""
        print "-------------------------------------------------------------------------"
        print "Final portfolio value: $%.2f" % self.getResult()
        print "Cumulative returns: %.2f %%" % (
            self.returnsAnalyzer.getCumulativeReturns()[-1] * 100)
        print "Sharpe ratio: %.2f" % (
            self.sharpeRatioAnalyzer.getSharpeRatio(0.05))
        print "Max. drawdown: %.2f %%" % (
            self.drawdownAnalyzer.getMaxDrawDown() * 100)
        print "Longest drawdown duration: (%s)" % (
            self.drawdownAnalyzer.getLongestDrawDownDuration())

        print
        print "Total trades: %d" % (self.tradesAnalyzer.getCount())
        if self.tradesAnalyzer.getCount() > 0:
            profits = self.tradesAnalyzer.getAll()
            print "Avg. profit: $%2.f" % (profits.mean())
            print "Profits std. dev.: $%2.f" % (profits.std())
            print "Max. profit: $%2.f" % (profits.max())
            print "Min. profit: $%2.f" % (profits.min())
            returns = self.tradesAnalyzer.getAllReturns()
            print "Avg. return: %2.f %%" % (returns.mean() * 100)
            print "Returns std. dev.: %2.f %%" % (returns.std() * 100)
            print "Max. return: %2.f %%" % (returns.max() * 100)
            print "Min. return: %2.f %%" % (returns.min() * 100)

        print
        print "Profitable trades: %d" % (
            self.tradesAnalyzer.getProfitableCount())
        if self.tradesAnalyzer.getProfitableCount() > 0:
            profits = self.tradesAnalyzer.getProfits()
            print "Avg. profit: $%2.f" % (profits.mean())
            print "Profits std. dev.: $%2.f" % (profits.std())
            print "Max. profit: $%2.f" % (profits.max())
            print "Min. profit: $%2.f" % (profits.min())
            returns = self.tradesAnalyzer.getPositiveReturns()
            print "Avg. return: %2.f %%" % (returns.mean() * 100)
            print "Returns std. dev.: %2.f %%" % (returns.std() * 100)
            print "Max. return: %2.f %%" % (returns.max() * 100)
            print "Min. return: %2.f %%" % (returns.min() * 100)

        print
        print "Unprofitable trades: %d" % (
            self.tradesAnalyzer.getUnprofitableCount())
        if self.tradesAnalyzer.getUnprofitableCount() > 0:
            losses = self.tradesAnalyzer.getLosses()
            print "Avg. loss: $%2.f" % (losses.mean())
            print "Losses std. dev.: $%2.f" % (losses.std())
            print "Max. loss: $%2.f" % (losses.min())
            print "Min. loss: $%2.f" % (losses.max())
            returns = self.tradesAnalyzer.getNegativeReturns()
            print "Avg. return: %2.f %%" % (returns.mean() * 100)
            print "Returns std. dev.: %2.f %%" % (returns.std() * 100)
            print "Max. return: %2.f %%" % (returns.max() * 100)
            print "Min. return: %2.f %%" % (returns.min() * 100)
        print "-------------------------------------------------------------------------"

    def initAnalyzer(self):
        from pyalgotrade.stratanalyzer import sharpe
        from pyalgotrade.stratanalyzer import returns
        from pyalgotrade.stratanalyzer import drawdown
        from pyalgotrade.stratanalyzer import trades
        # 1.0) 策略结果
        self.returnsAnalyzer = returns.Returns()
        # 1.1) 夏普比率
        self.sharpeRatioAnalyzer = sharpe.SharpeRatio()
        # 1.2)
        self.drawdownAnalyzer = drawdown.DrawDown()
        # 1.3)
        self.tradesAnalyzer = trades.Trades()

        self.attachAnalyzer(self.sharpeRatioAnalyzer)
        self.attachAnalyzer(self.returnsAnalyzer)
        self.attachAnalyzer(self.tradesAnalyzer)
        self.attachAnalyzer(self.drawdownAnalyzer)
Ejemplo n.º 34
0
class DMACrossOver(strategy.BacktestingStrategy):
    def __init__(self,
                 feed=None,
                 instrument='',
                 shortPeriod=0,
                 longPeriod=0,
                 money=None,
                 longAllowed=True,
                 shortAllowed=True):
        strategy.BacktestingStrategy.__init__(self, feed)

        self.position_cost = 0  #mid init position value

        mid_DEFAULT_MAX_LEN = 10 * DEFAULT_MAX_LEN
        self.__instrument = instrument
        self.__longPosition = None
        self.__shortPosition = None

        self.__position_volume = SequenceDataSeries(
            maxLen=mid_DEFAULT_MAX_LEN)  #mid 当前持有头寸数量
        self.__position_cost = SequenceDataSeries(
            maxLen=mid_DEFAULT_MAX_LEN)  #mid 当前持有头寸开仓成本
        self.__position_pnl = SequenceDataSeries(
            maxLen=mid_DEFAULT_MAX_LEN)  #mid 当前持有头寸价值
        self.__portfolio_value = SequenceDataSeries(maxLen=mid_DEFAULT_MAX_LEN)
        self.__buy = SequenceDataSeries(maxLen=mid_DEFAULT_MAX_LEN)
        self.__sell = SequenceDataSeries(maxLen=mid_DEFAULT_MAX_LEN)

        self.__buySignal = False
        self.__sellSignal = False
        self.money = money
        self.longAllowed = True
        self.shortAllowed = True
        #mid 计算ma将使用当天的收盘价格计算
        #mid 1)
        dataSeries = feed[instrument]
        dataSeries.setMaxLen(mid_DEFAULT_MAX_LEN)
        closeSeries = dataSeries.getOpenDataSeries()
        #mid 2)
        prices = closeSeries
        prices.setMaxLen(mid_DEFAULT_MAX_LEN)
        #mid 3)
        self.__sma = ma.SMA(prices, shortPeriod, maxLen=mid_DEFAULT_MAX_LEN)
        self.__lma = ma.SMA(prices, longPeriod, maxLen=mid_DEFAULT_MAX_LEN)

        self.i = 0

    def getAssetStructure(self):
        #mid --------------------------------
        #mid 当前账户资产结构如下方式获取
        #mid Long 和 Short不会同时存在
        #mid 在开仓前,若有反向持仓,则此过程查询并输出已持有的反向持仓
        broker = self.getBroker()
        portfolio_value = broker.getEquity()
        cash = broker.getCash()
        if self.__shortPosition is not None or self.__longPosition is not None:
            bars = self.getFeed().getCurrentBars()

            positions = broker.getPositions()

            positionsOpenValue = {}
            positionsCloseValue = {}
            for key, value in positions.items():
                print "key:" + key + ",value:" + str(value)
                bar = bars.getBar(key)
                openPrice = bar.getOpen()
                closePrice = bar.getClose()
                share = broker.getShares(key)
                positionsOpenValue[key] = openPrice * share
                positionsCloseValue[key] = closePrice * share

            print
            print 'current bar asset structure'
            print 'open cash %2.f.' % (cash)
            for key, value in positionsOpenValue.items():
                print "key:" + key + ",value:" + str(value)
            print 'close cash %2.f.' % (cash)
            for key, value in positionsCloseValue.items():
                print "key:" + key + ",value:" + str(value)
            print 'portfolio:%2.f' % (portfolio_value)

            return portfolio_value, cash, sum(positionsCloseValue.values())
        return portfolio_value, cash, 0

    def recordPositions(self):
        # record position
        #######################################################################
        broker = self.getBroker()
        position = broker.getPositions()  #mid position is dict of share
        share = broker.getShares(
            self.__instrument)  #mid position is dict of share
        lastPrice = self.getLastPrice(self.__instrument)
        portfolio_value = broker.getEquity()  #mid 按close价格计算的权益
        cash = broker.getCash()

        position_value = portfolio_value - cash

        position_pnl = position_value - self.position_cost

        print
        print 'cash: %.2f' % (cash)
        print 'position value: %.2f' % (portfolio_value - cash)
        print 'mid calc: %.2f' % (lastPrice * share + cash)
        print 'broker returned: %.2f' % (portfolio_value)

        curTime = self.getCurrentDateTime()
        if (False):
            yLimit = self.money.getShares() * 1.1
            if (self.i == 0):
                self.__position.append(yLimit)
                self.i = self.i + 1
            elif (self.i == 1):
                self.__position.append(-yLimit)
                self.i = self.i + 1
            else:
                currentTime = self.getCurrentDateTime()
                self.__position.appendWithDateTime(currentTime, abs(share))
                #self.__position.append(share)

        else:
            currentTime = self.getCurrentDateTime()

            self.__position_volume.appendWithDateTime(currentTime, abs(share))

            self.__position_cost.appendWithDateTime(currentTime,
                                                    abs(self.position_cost))

            self.__position_pnl.appendWithDateTime(currentTime, position_pnl)

            self.__portfolio_value.appendWithDateTime(currentTime,
                                                      portfolio_value)
            self.__buy.appendWithDateTime(currentTime, self.__buySignal)
            self.__sell.appendWithDateTime(currentTime, self.__sellSignal)

    def getInstrument(self):
        return self.__instrument

    def getPortfolio(self):
        return self.__portfolio_value

    def getPositionVolume(self):
        return self.__position_volume

    def getPositionCost(self):
        return self.__position_cost

    def getPositionPnl(self):
        return self.__position_pnl

    def getSMA(self):
        return self.__sma

    def getLMA(self):
        return self.__lma

    def getBuy(self):
        return self.__buy

    def getSell(self):
        return self.__sell

    def onEnterOk(self, position):
        execInfo = position.getEntryOrder().getExecutionInfo()
        portfolio = self.getResult()
        cash = self.getBroker().getCash()
        '''mid
  以下两种方法都是为了计算持仓成本
  由于getEquity()返回的是依据当日close价格计算出来的权益
  所以,这个值不能作为持仓成本
  持仓成本需要以onEnterOk时bar的open价格计算
  所以应使用第二种算法
  由于经常有跳开现象,所以依据bar(n-1).close发出的market order,
  在bar(n).open执行时通常会有gap出现,表现在position_cost图上时就是持有成本离计划成本会有跳口,
  '''
        if (False):  #mid two methods to cacl cost.
            portfolio_value = self.getBroker().getEquity()
            self.position_cost = portfolio_value - cash
        else:
            feed = self.getFeed()
            bars = feed.getCurrentBars()
            bar = bars.getBar(self.__instrument)
            openPrice = bar.getOpen()
            closePrice = self.getLastPrice(
                self.__instrument)  #mid lastPrice == closePrice
            share = self.getBroker().getShares(self.__instrument)
            self.position_cost = openPrice * share

        self.info("onEnterOk().current available cash: %.2f,portfolio: %.2f." %
                  (cash, portfolio))
        if isinstance(position, strategy.position.LongPosition):
            self.info("onEnterOK().ExecutionInfo: %s,OPEN LONG %.2f at $%.2f" %
                      (execInfo.getDateTime(), execInfo.getQuantity(),
                       execInfo.getPrice()))
        elif isinstance(position, strategy.position.ShortPosition):
            self.info(
                "onEnterOK().ExecutionInfo: %s,OPEN SHORT %.2f at $%.2f" %
                (execInfo.getDateTime(), execInfo.getQuantity(),
                 execInfo.getPrice()))

    def onEnterCanceled(self, position):
        self.info("onEnterCanceled().current available cash: %.2f." %
                  (self.getBroker().getCash()))
        if isinstance(position, strategy.position.LongPosition):
            self.__longPosition = None
            self.info("onEnterCanceled().OPEN LONG cancled.")
        elif isinstance(position, strategy.position.ShortPosition):
            self.__shortPosition = None
            self.info("onEnterCanceled().OPEN SHORT cancled.")

    def onExitOk(self, position):
        execInfo = position.getExitOrder().getExecutionInfo()
        portfolio = self.getResult()
        cash = self.getBroker().getCash()
        self.info("onExitOk().current available cash: %.2f,portfolio: %.2f." %
                  (cash, portfolio))

        if isinstance(position, strategy.position.LongPosition):
            self.__longPosition = None
            self.info("onExitOk().ExecutionInfo: %s,CLOSE LONG %.2f at $%.2f" %
                      (execInfo.getDateTime(), execInfo.getQuantity(),
                       execInfo.getPrice()))
        elif isinstance(position, strategy.position.ShortPosition):
            self.__shortPosition = None
            self.info(
                "onExitOk().ExecutionInfo: %s,CLOSE SHORT %.2f at $%.2f" %
                (execInfo.getDateTime(), execInfo.getQuantity(),
                 execInfo.getPrice()))

    def onExitCanceled(self, position):
        # If the exit was canceled, re-submit it.
        if isinstance(position, strategy.position.LongPosition):
            self.__longPosition = None
        elif isinstance(position, strategy.position.ShortPosition):
            self.__shortPosition = None

    def logInfo(self, bars=None):
        pLong, pShort = 0, 0
        if (self.__longPosition is not None):
            pLong = self.__longPosition.getShares()
        if (self.__shortPosition is not None):
            pShort = self.__shortPosition.getShares()

        bar = bars[self.__instrument]
        pOpen = bar.getOpen()
        pHigh = bar.getHigh()
        pLow = bar.getLow()
        pClose = bar.getClose()
        pPrice = bar.getPrice()

        self.info(
            'logInfo().price:%.3f,open:%.2f,high:%.2f,low:%.2f,close:%.2f' %
            (pPrice, pOpen, pHigh, pLow, pClose))
        #self.info('long:%.2f#short:%.2f'%(pLong,pShort))
    def run(self):
        strategy.BacktestingStrategy.run(self)

        sma = self.getSMA()
        lma = self.getLMA()
        buy = self.getBuy()
        sell = self.getSell()

        portfolio_value = self.getPortfolio()

        position_volume = self.getPositionVolume()
        position_cost = self.getPositionCost()
        position_pnl = self.getPositionPnl()

        result = pd.DataFrame(
            {
                'position_volume': list(position_volume),
                'position_cost': list(position_cost),
                'position_pnl': list(position_pnl),
                'short_ema': list(sma),
                'long_ema': list(lma),
                'buy': list(buy),
                'sell': list(sell),
                'portfolio_value': list(portfolio_value)
            },
            columns=[
                'position_volume', 'position_cost', 'position_pnl',
                'short_ema', 'long_ema', 'buy', 'sell', 'portfolio_value'
            ],
            index=position_volume.getDateTimes())
        return result

    def onBars(self, bars):
        '''mid
        此处是onBars,这个和zipline的概念完全不同
        zipline中,需要覆写的是handle_data,这个东西是个tick概念,所以没有OHLC的,只是个price
        PAT中,每次onBars,都会传入一个newbar的OHLC,此时,要如何按这个OHLC决策,全由你
        依据OHLC做完决策后,可以发送交易指令:
        * Order.Type.MARKET
        * Order.Type.LIMIT
        * Order.Type.STOP
        * Order.Type.STOP_LIMIT
        1.市价单,依据下一个bar的openPrice执行命令:
            self.enterLong()
        2.限价单
        3.止损单市价单
        4.止损限价单

        当前似乎没有止盈单

        在均线策略中,应该在每个newbar到来时,按closePrice的均线计算指标值,然后发送市价单
        1.每个newbar按close价格计算指标,并在下一个bar按open成交
        2.每个newbar按open价格计算指标,并在此newbar按open成交
        以上1,2的计算逻辑是一致的。如果当前bar的close和下一个bar的open相差无几时,两种算法的回测结果也应相差无几
        '''
        self.__buySignal, self.__sellSignal = False, False
        # mid 1)close
        if (self.longAllowed):
            if self.__longPosition is not None and not self.__longPosition.exitActive(
            ):
                #mid 有多仓,检查是否需要平仓
                if (cross.cross_below(self.__sma, self.__lma) > 0):
                    print
                    self.info(
                        "onBars().Status info,before exitMarket(), LONG POSITION to close %.2f"
                        % (self.__longPosition.getShares()))
                    self.__longPosition.exitMarket()
        if (self.shortAllowed):
            if self.__shortPosition is not None and not self.__shortPosition.exitActive(
            ):
                if (cross.cross_above(self.__sma, self.__lma) > 0):
                    print
                    self.info(
                        "onBars().Status info,before exitMarket(), SHORT POSITION to close %.2f"
                        % (self.__shortPosition.getShares()))
                    self.__shortPosition.exitMarket()

        # mid 2)open
        if (self.longAllowed):
            if self.__longPosition is None:
                #mid 无多仓,检查是否需要开多仓
                if cross.cross_above(self.__sma, self.__lma) > 0:
                    # Enter a buy market order. The order is good till canceled.
                    shares = self.money.getShares(strat=self)
                    self.info(
                        "onBars().Status info,before enterLong(), LONG POSITION to open %.2f,need amount: %.2f,available amount: %.2f."
                        %
                        (shares, shares * self.getLastPrice(self.__instrument),
                         self.getBroker().getCash()))
                    self.__longPosition = self.enterLong(
                        self.__instrument, shares, True)
                    self.__buySignal = True
        if (self.shortAllowed):
            if self.__shortPosition is None:
                if cross.cross_below(self.__sma, self.__lma) > 0:
                    # Enter a buy market order. The order is good till canceled.
                    shares = self.money.getShares(strat=self)
                    self.info(
                        "onBars().Status info,before enterShort(), SHORT POSITION to open %.2f,need amount: %.2f,available amount: %.2f."
                        %
                        (shares, shares * self.getLastPrice(self.__instrument),
                         self.getBroker().getCash()))
                    self.__shortPosition = self.enterShort(
                        self.__instrument, shares, True)
                    self.__sellSignal = True

        self.recordPositions()
Ejemplo n.º 35
0
	def adjustBars(self):

		for key, value in self.__barsDict.iteritems():

			basicbars = []
			bars = value
			bars_in_dtrange = [bar for bar in bars if self.__startdate.replace(tzinfo=None) <= bar.getDateTime() <= self.__enddate.replace(tzinfo=None)]
			bars_in_dtrange.sort(key=lambda bar: bar.getDateTime(), reverse=True)

			k = 0
			splitdataList = []
			dividendList = []

			for bar in bars_in_dtrange:
				splitdata = float(bar.getSplit())
				dividend = float(bar.getDividend())
				if splitdata != 1.0:
					splitdataList.append(bar.getSplit())
				if dividend != 0.0:
					adjFactor = (bar.getClose() + bar.getDividend()) / bar.getClose()
					dividendList.append(adjFactor)
				#### Special case.... end date / analysis date nothing to do..
				if (k==0):
					bar = BasicBar(bar.getDateTime(), 
						bar.getOpen() , bar.getHigh(), bar.getLow(), bar.getClose(), bar.getVolume(), bar.getClose(), Frequency.DAY)
					basicbars.append(bar)
				else:
					#### Adjust OHLC & Volume data for split adjustments and dividend adjustments
					Open = bar.getOpen()
					High = bar.getHigh()
					Low  = bar.getLow()
					Close = bar.getClose()
					Volume = bar.getVolume()
					### adjust data for splits
					for split in splitdataList:
						Open = Open / split
						High = High / split
						Low  = Low / split
						Close = Close /split
						Volume = Volume * split

					### adjust data for dividends
					for adjFactor in dividendList:
						Open = Open / adjFactor
						High = High / adjFactor
						Low  = Low / adjFactor
						Close = Close / adjFactor
						Volume = Volume * adjFactor
					bar = BasicBar(bar.getDateTime(), 
						Open , High, Low, Close, Volume, Close, Frequency.DAY)
					basicbars.append(bar)
				k +=1


			DateTimes = []
			OpenSeries = SequenceDataSeries(4000)
			HighSeries = SequenceDataSeries(4000)
			LowSeries =  SequenceDataSeries(4000)
			CloseSeries = SequenceDataSeries(4000)
			VolumeSeries = SequenceDataSeries(4000)
			TypicalSeries = SequenceDataSeries(4000)
			barSeries = BarDataSeries(4000)
			basicbars.sort(key=lambda bar: bar.getDateTime(), reverse=False)
			

			for bar in basicbars:
				DateTimes.append(bar.getDateTime())
				OpenSeries.appendWithDateTime(bar.getDateTime(), bar.getOpen())
				HighSeries.appendWithDateTime(bar.getDateTime(), bar.getHigh())
				LowSeries.appendWithDateTime(bar.getDateTime(), bar.getLow())
				CloseSeries.appendWithDateTime(bar.getDateTime(), bar.getClose())
				VolumeSeries.appendWithDateTime(bar.getDateTime(), bar.getVolume())
				TypicalSeries.appendWithDateTime(bar.getDateTime(), (bar.getClose()+bar.getHigh()+bar.getLow())/3.0)
				barSeries.appendWithDateTime(bar.getDateTime(), bar)


			self.__DateTimes[key+"_adjusted"] = DateTimes
			self.__OpenDataSeries[key+"_adjusted"] = OpenSeries
			self.__HighDataSeries[key+"_adjusted"] = HighSeries
			self.__LowDataSeries[key+"_adjusted"] =  LowSeries
			self.__CloseDataSeries[key+"_adjusted"] = CloseSeries
			self.__VolumeDataSeries[key+"_adjusted"] = VolumeSeries
			self.__TypicalDataSeries[key+"_adjusted"] = TypicalSeries
			self.__barSeries[key+"_adjusted"] = barSeries