def test_merge_direct(self): bc = Bar(self.sym, self.data[0]) b1 = Bar(self.sym, self.data[0]) b2 = Bar(self.sym, self.data[1]) b1.merge(b2.cl, b2.hi, b2.lo) self.assertTrue(b1.date == bc.date) self.assertTrue(b1.op == bc.op) self.assertTrue(b1.hi == b2.hi) self.assertTrue(b1.lo == b2.lo) self.assertTrue(b1.cl == b2.cl) b1 = Bar(self.sym, self.data[0]) b1.merge(b2.cl, b2.hi) self.assertTrue(b1.date == bc.date) self.assertTrue(b1.op == bc.op) self.assertTrue(b1.hi == b2.hi) self.assertTrue(b1.lo == bc.lo) self.assertTrue(b1.cl == b2.cl) b1 = Bar(self.sym, self.data[0]) b1.merge(b2.cl) self.assertTrue(b1.date == bc.date) self.assertTrue(b1.op == bc.op) self.assertTrue(b1.hi == bc.hi) self.assertTrue(b1.lo == bc.lo) self.assertTrue(b1.cl == b2.cl)
def testSellStop(self): b1 = Bar(self.sym, "20010102-230000,EURUSD,0.9507,0.9509,0.9505,0.9506") b2 = Bar(self.sym, "20010102-230000,EURUSD,0.9507,0.9509,0.9499,0.9506") o1 = Order(self.sym, dir=Order.SELL, type=Order.STOP, level=0.9499, size=-10000) self.bt.book.add(o1) self.bt.next_bar(self.sym, b1) self.aEq(len(self.bt.poslist.open), 0) self.bt.next_bar(self.sym, b2) self.aEq(len(self.bt.poslist.open), 1)
def test_merge_bar(self): bc = Bar(self.sym, self.data[0]) b1 = Bar(self.sym, self.data[0]) b2 = Bar(self.sym, self.data[1]) #base case b2 should replace all of b1 except open and date b1.merge(b2) self.assertTrue(b1.date == bc.date) self.assertTrue(b1.op == bc.op) self.assertTrue(b1.hi == b2.hi) self.assertTrue(b1.lo == b2.lo) self.assertTrue(b1.cl == b2.cl)
def testBuyLimit(self): b1 = Bar(self.sym, "20010102-230000,EURUSD,0.9507,0.9509,0.9505,0.9506") b2 = Bar(self.sym, "20010102-230000,EURUSD,0.9507,0.9509,0.9500,0.9506") o1 = Order(self.sym, dir=Order.BUY, type=Order.LIMIT, level=0.9501, size=10000) self.bt.book.add(o1) self.bt.next_bar(self.sym, b1) #should be no fill for b1 self.aEq(len(self.bt.poslist.open), 0) self.bt.next_bar(self.sym, b2) self.aEq(len(self.bt.poslist.open), 1)
def testRewind(self): #in this case we have a sl/tp, and get a bar which triggers them both #when this happens, we cancel both the orders and unwind the original position #as if it never happened. If this is happening a lot you need lower time frame data #stop loss/take profit b1 = Bar(self.sym, "20010102-230000,EURUSD,0.9507,0.9509,0.9505,0.9506") b2 = Bar(self.sym, "20010102-230000,EURUSD,0.9507,0.9510,0.9499,0.9506") #buy order at 9505 o1 = Order(self.sym, dir=Order.BUY, type=Order.MARKET, level=0.9505, size=10000) #stop loss at 9499 sl = Order(self.sym, dir=Order.SELL, type=Order.STOP, level=0.9499, size=-10000) #take profit at 9510 tp = Order(self.sym, dir=Order.SELL, type=Order.LIMIT, level=0.9510, size=-10000) #stop loss hit cancels tp and vice versa Order.OCO(sl, tp) #when the order is filled it activates sl/tp o1.trigger(sl, tp) self.bt.book.add(o1, sl, tp) self.bt.next_bar(self.sym, b1) #the order should be filled self.aEq(len(self.bt.poslist.open), 1) self.aItEq([sl.id, tp.id], self.bt.book.active) self.bt.next_bar(self.sym, b2) self.aEq(len(self.bt.poslist.open), 0) self.aEq(len(self.bt.poslist.closed), 0) self.aEq(len(self.bt.poslist.rewinded), 1) self.aEq(len(self.bt.book.active), 0) self.aEq(self.bt.equity, 100000)
def testMark(self): o1 = Order(self.sym, dir=Order.BUY, type=Order.MARKET, level=1.0000, size=10000) o2 = Order("NOPE", dir=Order.BUY, type=Order.MARKET, level=1.0000, size=10000) p1 = self.pl.add(o1, datetime.now()) p2 = self.pl.add(o1, datetime.now()) p3 = self.pl.add(o2, datetime.now()) b1 = Bar(self.sym, "20010102-230000,EURUSD,0.9507,0.9509,0.9505,0.9506") self.pl.mark(b1) #mark should update p1 & p2 but not p3 self.aEq(p1.mark, b1.cl) self.aEq(p2.mark, b1.cl) self.aEq(p3.mark, o2.level)
def testGetFills(self): o1 = Order(self.sym, dir=Order.BUY, type=Order.LIMIT, level=0.9551, size=1) o2 = Order(symbol="NOPE", dir=Order.BUY, type=Order.LIMIT, level=0.9551, size=1) b1 = Bar(self.sym, "20010102-230000,EURUSD,0.9507,0.9509,0.9505,0.9506") b2 = Bar(self.sym, "20010102-230000,EURUSD,0.9507,0.9560,0.9505,0.9506") self.ob.add(o1) self.ob.add(o2) self.aEq([], self.ob.get_fills(b1)) self.aEq([o1], self.ob.get_fills(b2)) #market orders always get filled the next bar #the "fill price" is really just the level set on the order ... o3 = Order(self.sym, dir=Order.BUY, type=Order.MARKET, level=0.9551, size=1) self.ob.add(o3) self.aEq([o3], self.ob.get_fills(b1))
def testSL(self): #stop loss/take profit b1 = Bar(self.sym, "20010102-230000,EURUSD,0.9507,0.9509,0.9505,0.9506") b2 = Bar(self.sym, "20010102-230000,EURUSD,0.9507,0.9509,0.9499,0.9506") #buy order at 9505 o1 = Order(self.sym, dir=Order.BUY, type=Order.MARKET, level=0.9505, size=10000) #stop loss at 9499 sl = Order(self.sym, dir=Order.SELL, type=Order.STOP, level=0.9499, size=-10000) #take profit at 9510 tp = Order(self.sym, dir=Order.SELL, type=Order.LIMIT, level=0.9510, size=-10000) #stop loss hit cancels tp and vice versa Order.OCO(sl, tp) #when the order is filled it activates sl/tp o1.trigger(sl, tp) self.bt.book.add(o1, sl, tp) self.bt.next_bar(self.sym, b1) #the order should be filled self.aEq(len(self.bt.poslist.open), 1) self.aItEq([sl.id, tp.id], self.bt.book.active) self.bt.next_bar(self.sym, b2) self.aEq(len(self.bt.poslist.open), 0) self.aEq(len(self.bt.poslist.closed), 1) self.aEq(len(self.bt.book.active), 0) self.aEq(self.bt.equity, 99994)
def testBuyMarket(self): b1 = Bar(self.sym, "20010102-230000,EURUSD,0.9507,0.9509,0.9505,0.9506") o1 = Order(self.sym, dir=Order.BUY, type=Order.MARKET, level=0.9508, size=10000) self.bt.book.add(o1) #self.bt.bar_close = self.bar_close self.bt.next_bar(self.sym, b1) #should have an open position self.aEq(len(self.bt.poslist.open), 1) p = self.bt.poslist.open[0] self.aEq(p.order_id, o1.id) self.aEq(p.mark, b1.cl) self.aEq(p.entry, o1.level)
def test_init(self): b = Bar(self.sym, self.data[0])