def testBuyAndSellBreakEvenWithCommision(self): posTracker = returns.PositionTracker(broker.IntegerTraits()) posTracker.buy(1, 10, 0.5) self.assertEqual(posTracker.getCostPerShare(), 10) posTracker.sell(1, 11, 0.5) self.assertEqual(posTracker.getNetProfit(includeCommissions=False), 1) self.assertEqual(posTracker.getNetProfit(), 0) self.assertEqual(posTracker.getReturn(includeCommissions=False), 0.1) self.assertEqual(posTracker.getReturn(), 0)
def testBuyAndSellWin(self): posTracker = returns.PositionTracker() posTracker.buy(1, 10) posTracker.sell(1, 11) self.assertTrue(posTracker.getCost() == 10) self.assertTrue( posTracker.getNetProfit(PosTrackerTestCase.invalid_price) == 1) self.assertTrue( posTracker.getReturn(PosTrackerTestCase.invalid_price) == 0.1)
def testSellAndBuyWin(self): posTracker = returns.PositionTracker() posTracker.sell(1, 11) posTracker.buy(1, 10) self.assertTrue(posTracker.getCost() == 11) self.assertTrue( posTracker.getNetProfit(PosTrackerTestCase.invalid_price) == 1) self.assertTrue( round(posTracker.getReturn(PosTrackerTestCase.invalid_price), 4) == round(0.090909091, 4))
def testSellAndBuyWin(self): posTracker = returns.PositionTracker(broker.IntegerTraits()) posTracker.sell(1, 13) self.assertEqual(posTracker.getAvgPrice(), 13) self.assertEqual(posTracker.getPnL(), 0) self.assertEqual(posTracker.getPnL(price=10), 3) posTracker.buy(1, 10) self.assertEqual(posTracker.getAvgPrice(), 0) self.assertEqual(posTracker.getPnL(), 3) self.assertEqual(round(posTracker.getReturn(), 9), round(0.23076923076923, 9))
def testLongShortEqualAmount(self): posTrackerXYZ = returns.PositionTracker() posTrackerXYZ.buy(11, 10) posTrackerXYZ.sell(11, 30) self.assertTrue(posTrackerXYZ.getCost() == 11*10) self.assertTrue(posTrackerXYZ.getNetProfit(PosTrackerTestCase.invalid_price) == 20*11) self.assertTrue(posTrackerXYZ.getReturn(PosTrackerTestCase.invalid_price) == 2) posTrackerABC = returns.PositionTracker() posTrackerABC.sell(100, 1.1) posTrackerABC.buy(100, 1) self.assertTrue(posTrackerABC.getCost() == 100*1.1) self.assertTrue(round(posTrackerABC.getNetProfit(PosTrackerTestCase.invalid_price), 2) == 100*0.1) self.assertEqual(round(posTrackerABC.getReturn(PosTrackerTestCase.invalid_price), 2), 0.09) combinedCost = posTrackerXYZ.getCost() + posTrackerABC.getCost() combinedPL = posTrackerXYZ.getNetProfit(PosTrackerTestCase.invalid_price) + posTrackerABC.getNetProfit(PosTrackerTestCase.invalid_price) combinedReturn = combinedPL / float(combinedCost) self.assertTrue(round(combinedReturn, 9) == 1.045454545)
def testSellAndBuyWin(self): posTracker = returns.PositionTracker(INSTRUMENT, DefaultInstrumentTraits()) posTracker.sell(1, 13) self.assertEqual(posTracker.getAvgPrice(), 13) self.assertEqual(posTracker.getPnL(), 0) self.assertEqual(posTracker.getPnL(price=10), 3) posTracker.buy(1, 10) self.assertEqual(posTracker.getAvgPrice(), 0) self.assertEqual(posTracker.getPnL(), 3) self.assertEqual(round(posTracker.getReturn(), 9), round(0.23076923076923, 9))
def testBuyAndSellBreakEvenWithCommision(self): posTracker = returns.PositionTracker() posTracker.buy(1, 10, 0.5) posTracker.sell(1, 11, 0.5) self.assertTrue(posTracker.getCost() == 10) self.assertTrue(posTracker.getNetProfit(PosTrackerTestCase.invalid_price, False) == 1) self.assertTrue(posTracker.getReturn(PosTrackerTestCase.invalid_price, False) == 0.1) self.assertTrue(posTracker.getNetProfit(PosTrackerTestCase.invalid_price, True) == 0) self.assertTrue(posTracker.getReturn(PosTrackerTestCase.invalid_price, True) == 0)
def __getPosTracker(self): ret = returns.PositionTracker() entryExecInfo = self.getEntryOrder().getExecutionInfo() ret.sell(entryExecInfo.getQuantity(), entryExecInfo.getPrice(), entryExecInfo.getCommission()) if self.exitFilled(): exitExecInfo = self.getExitOrder().getExecutionInfo() ret.buy(exitExecInfo.getQuantity(), exitExecInfo.getPrice(), exitExecInfo.getCommission()) return ret
def testBuyAndSellInTwoTrades(self): posTracker = returns.PositionTracker(broker.IntegerTraits()) posTracker.buy(2, 10) self.assertEqual(posTracker.getAvgPrice(), 10) posTracker.sell(1, 11) self.assertEqual(posTracker.getAvgPrice(), 10) self.assertEqual(posTracker.getPnL(), 1) self.assertEqual(posTracker.getReturn(), 0.05) posTracker.sell(1, 12) self.assertEqual(posTracker.getPnL(), 3) self.assertEqual(posTracker.getReturn(), 3 / 20.0)
def testBuyAndSellInTwoTrades(self): posTracker = returns.PositionTracker(INSTRUMENT, DefaultInstrumentTraits()) posTracker.buy(2, 10) self.assertEqual(posTracker.getAvgPrice(), 10) posTracker.sell(1, 11) self.assertEqual(posTracker.getAvgPrice(), 10) self.assertEqual(posTracker.getPnL(), 1) self.assertEqual(posTracker.getReturn(), 0.05) posTracker.sell(1, 12) self.assertEqual(posTracker.getPnL(), 3) self.assertEqual(posTracker.getReturn(), 3/20.0)
def testSellAndBuyWin(self): posTracker = returns.PositionTracker(broker.IntegerTraits()) posTracker.sell(1, 13) self.assertEqual(posTracker.getCostPerShare(), 13) self.assertEqual(posTracker.getNetProfit(), 0) self.assertEqual(posTracker.getNetProfit(10), 3) posTracker.buy(1, 10) self.assertEqual(posTracker.getCostPerShare(), 0) self.assertEqual(posTracker.getNetProfit(), 3) self.assertEqual(round(posTracker.getReturn(), 9), round(0.23076923076923, 9))
def testBuySellBuy(self): posTracker = returns.PositionTracker() posTracker.buy(1, 10) self.assertTrue(posTracker.getCost() == 10) posTracker.sell(2, 13) # Short selling 1 @ $13 self.assertTrue(posTracker.getCost() == 10 + 13) posTracker.buy(1, 10) self.assertTrue(posTracker.getCost() == 10 + 13) self.assertTrue(posTracker.getNetProfit(PosTrackerTestCase.invalid_price) == 6) self.assertTrue(round(posTracker.getReturn(PosTrackerTestCase.invalid_price), 4) == round(0.260869565, 4))
def testBuyAndSellBreakEvenWithCommission(self): posTracker = returns.PositionTracker() posTracker.buy(1, 10, 0.01) posTracker.sell(1, 10.02, 0.01) self.assertTrue(posTracker.getCost() == 10) # We need to round here or else the testcase fails since the value returned is not exactly 0.< # The same issue can be reproduced with this piece of code: # a = 10.02 - 10 # b = 0.02 # print a - b # print a - b == 0 self.assertTrue(round(posTracker.getNetProfit(PosTrackerTestCase.invalid_price), 2) == 0.0) self.assertTrue(round(posTracker.getReturn(PosTrackerTestCase.invalid_price), 2) == 0.0)
def testSeparateAndCombined(self): posA = returns.PositionTracker(broker.IntegerTraits()) posA.buy(11, 10) posA.sell(11, 30) self.assertEqual(posA.getPnL(), 20 * 11) self.assertEqual(posA.getReturn(), 2) posB = returns.PositionTracker(broker.IntegerTraits()) posB.sell(100, 1.1) posB.buy(100, 1) self.assertEqual(round(posB.getPnL(), 2), 100 * 0.1) self.assertEqual(round(posB.getReturn(), 2), 0.09) combinedPos = returns.PositionTracker(broker.IntegerTraits()) combinedPos.buy(11, 10) combinedPos.sell(11, 30) combinedPos.sell(100, 1.1) combinedPos.buy(100, 1) self.assertEqual(round(combinedPos.getReturn(), 6), 2.090909) # The return of the combined position is less than the two returns combined # because when the second position gets opened the amount of cash not invested is greater # than that of posB alone. self.assertLess(round(combinedPos.getReturn(), 6), ((1 + posA.getReturn()) * (1 + posB.getReturn()) - 1))
def testBuyAndUpdate(self): posTracker = returns.PositionTracker() posTracker.buy(1, 10) self.assertTrue(posTracker.getCost() == 10) self.assertTrue(posTracker.getNetProfit(20) == 10) self.assertTrue(posTracker.getReturn(20) == 1) posTracker.update(15) self.assertTrue(posTracker.getCost() == 15) self.assertTrue(posTracker.getNetProfit(15) == 0) self.assertTrue(posTracker.getReturn(15) == 0) self.assertTrue(posTracker.getNetProfit(20) == 5) self.assertTrue(round(posTracker.getReturn(20), 2) == 0.33)
def testSellAndBuyMultipleEvals(self): posTracker = returns.PositionTracker() posTracker.sell(2, 11) self.assertTrue(posTracker.getCost() == 22) self.assertTrue(posTracker.getNetProfit(11) == 0) self.assertTrue(posTracker.getReturn(11) == 0) posTracker.buy(1, 10) self.assertTrue(posTracker.getCost() == 22) self.assertTrue(posTracker.getNetProfit(11) == 1) self.assertTrue(round(posTracker.getReturn(11), 4) == round(0.045454545, 4)) posTracker.buy(1, 10) self.assertTrue(posTracker.getCost() == 22) self.assertTrue(posTracker.getNetProfit(PosTrackerTestCase.invalid_price) == 2) self.assertTrue(round(posTracker.getReturn(PosTrackerTestCase.invalid_price), 4) == round(0.090909091, 4))
def testBuyAndSellBreakEvenWithCommission(self): posTracker = returns.PositionTracker(INSTRUMENT, DefaultInstrumentTraits()) posTracker.buy(1, 10, 0.01) self.assertEqual(posTracker.getPosition(), 1) self.assertEqual(posTracker.getAvgPrice(), 10) posTracker.sell(1, 10.02, 0.01) self.assertEqual(posTracker.getPosition(), 0) self.assertEqual(posTracker.getAvgPrice(), 0) # We need to round to avoid floating point errors. # The same issue can be reproduced with this piece of code: # a = 10.02 - 10 # b = 0.02 # print a - b # print a - b == 0 self.assertEqual(posTracker.getPosition(), 0) self.assertEqual(round(posTracker.getPnL(), 2), 0) self.assertEqual(round(posTracker.getReturn(), 2), 0)
def testBuyAndSellBreakEvenWithCommission(self): posTracker = returns.PositionTracker(broker.IntegerTraits()) self.assertEqual(posTracker.getCash(), 0) posTracker.buy(1, 10, 0.01) self.assertEqual(posTracker.getCash(), -10.01) self.assertEqual(posTracker.getCostPerShare(), 10) posTracker.sell(1, 10.02, 0.01) self.assertEqual(round(posTracker.getCash(), 2), 0) self.assertEqual(posTracker.getCostPerShare(), 0) # We need to round to avoid floating point errors. # The same issue can be reproduced with this piece of code: # a = 10.02 - 10 # b = 0.02 # print a - b # print a - b == 0 self.assertEqual(posTracker.getShares(), 0) self.assertEqual(round(posTracker.getNetProfit(), 2), 0) self.assertEqual(round(posTracker.getReturn(), 2), 0)
def testBuyUpdateAndSell(self): posTracker = returns.PositionTracker() posTracker.buy(1, 10) self.assertTrue(posTracker.getCost() == 10) self.assertTrue(posTracker.getNetProfit(15) == 5) self.assertTrue(posTracker.getReturn(15) == 0.5) posTracker.update(15) self.assertTrue(posTracker.getCost() == 15) posTracker.sell(1, 20) self.assertTrue(posTracker.getCost() == 15) self.assertTrue(posTracker.getNetProfit(PosTrackerTestCase.invalid_price) == 5) self.assertTrue(round(posTracker.getReturn(PosTrackerTestCase.invalid_price), 2) == 0.33) posTracker.update(100) self.assertTrue(posTracker.getCost() == 0) self.assertTrue(posTracker.getNetProfit(PosTrackerTestCase.invalid_price) == 0) self.assertTrue(posTracker.getReturn(PosTrackerTestCase.invalid_price) == 0)
def __init__(self, strategy, entryOrder, goodTillCanceled, allOrNone): # The order must be created but not submitted. assert (entryOrder.isInitial()) self.__state = None self.__activeOrders = {} self.__shares = 0 self.__strategy = strategy self.__entryOrder = None self.__exitOrder = None self.__posTracker = returns.PositionTracker() self.__allOrNone = allOrNone self.switchState(WaitingEntryState()) entryOrder.setGoodTillCanceled(goodTillCanceled) entryOrder.setAllOrNone(allOrNone) self.__placeAndRegisterOrder(entryOrder) self.__entryOrder = entryOrder
def testSellAndBuyMultipleEvals(self): posTracker = returns.PositionTracker(broker.IntegerTraits()) posTracker.sell(2, 11) self.assertEqual(posTracker.getAvgPrice(), 11) self.assertEqual(posTracker.getPnL(price=10), 2) self.assertEqual(posTracker.getPnL(price=11), 0) self.assertEqual(posTracker.getPnL(price=12), -2) self.assertEqual(posTracker.getReturn(11), 0) posTracker.buy(1, 10) self.assertEqual(posTracker.getAvgPrice(), 11) self.assertEqual(posTracker.getPnL(price=11), 1) self.assertEqual(round(posTracker.getReturn(11), 9), round(0.045454545, 9)) posTracker.buy(1, 10) self.assertEqual(posTracker.getAvgPrice(), 0) self.assertEqual(posTracker.getPnL(), 2) self.assertEqual(posTracker.getPnL(price=100), 2) self.assertEqual(round(posTracker.getReturn(), 9), round(0.090909091, 9))
def __init__(self, strategy, entryOrder, goodTillCanceled): # The order must be created but not submitted. assert (entryOrder.isInitial()) if not entryOrder.getAllOrNone(): raise Exception( "Only all-or-none orders are supported with the position interface" ) self.__state = WaitingEntryState() self.__activeOrders = {} self.__shares = 0 self.__strategy = strategy self.__entryOrder = None self.__exitOrder = None self.__posTracker = returns.PositionTracker() entryOrder.setGoodTillCanceled(goodTillCanceled) self.__placeAndRegisterOrder(entryOrder) self.__entryOrder = entryOrder
def testSellBuySell(self): posTracker = returns.PositionTracker(broker.IntegerTraits()) posTracker.sell(1, 10) self.assertEqual(posTracker.getAvgPrice(), 10) self.assertEqual(posTracker.getPnL(), 0) self.assertEqual(posTracker.getReturn(), 0) self.assertEqual(posTracker.getPnL(price=13), -3) self.assertEqual(posTracker.getReturn(13), -0.3) # Closing the short position and going long 1 @ $13. # The cost basis for the new position is $13. posTracker.buy(2, 13) self.assertEqual(posTracker.getAvgPrice(), 13) self.assertEqual(posTracker.getPnL(), -3) self.assertEqual(round(posTracker.getReturn(), 9), round(-0.23076923076923, 9)) posTracker.sell(1, 10) self.assertEqual(posTracker.getAvgPrice(), 0) self.assertEqual(posTracker.getPnL(), -6) self.assertEqual(round(posTracker.getReturn(), 9), round(-0.46153846153846, 9))
def testSellAndBuyMultipleEvals(self): posTracker = returns.PositionTracker(broker.IntegerTraits()) posTracker.sell(2, 11) self.assertEqual(posTracker.getCostPerShare(), 11) self.assertEqual(posTracker.getNetProfit(10), 2) self.assertEqual(posTracker.getNetProfit(11), 0) self.assertEqual(posTracker.getNetProfit(12), -2) self.assertEqual(posTracker.getReturn(11), 0) posTracker.buy(1, 10) self.assertEqual(posTracker.getCostPerShare(), 11) self.assertEqual(posTracker.getNetProfit(11), 1) self.assertEqual(round(posTracker.getReturn(11), 9), round(0.045454545, 9)) posTracker.buy(1, 10) self.assertEqual(posTracker.getCostPerShare(), 0) self.assertEqual(posTracker.getNetProfit(), 2) self.assertEqual(posTracker.getNetProfit(100), 2) self.assertEqual(round(posTracker.getReturn(), 9), round(0.090909091, 9))
def testBuySellBuy(self): posTracker = returns.PositionTracker(broker.IntegerTraits()) posTracker.buy(1, 10) self.assertEqual(posTracker.getAvgPrice(), 10) self.assertEqual(posTracker.getPnL(price=9), -1) self.assertEqual(posTracker.getPnL(), 0) self.assertEqual(posTracker.getPnL(price=10), 0) self.assertEqual(posTracker.getPnL(price=11), 1) self.assertEqual(posTracker.getReturn(), 0) self.assertEqual(posTracker.getReturn(13), 0.3) # Closing the long position and short selling 1 @ $13. # The cost basis for the new position is $13. posTracker.sell(2, 13) self.assertEqual(posTracker.getAvgPrice(), 13) self.assertEqual(posTracker.getPnL(), 3) self.assertEqual(round(posTracker.getReturn(), 8), 0.23076923) posTracker.buy(1, 10) self.assertEqual(posTracker.getAvgPrice(), 0) self.assertEqual(posTracker.getPnL(), 6) self.assertEqual(round(posTracker.getReturn(), 9), round(0.46153846153846, 9))
def testBuyAndSellMultipleEvals(self): posTracker = returns.PositionTracker() posTracker.buy(2, 10) self.assertTrue(posTracker.getCost() == 20) self.assertTrue(posTracker.getNetProfit(10) == 0) self.assertTrue(posTracker.getReturn(10) == 0) self.assertTrue(posTracker.getNetProfit(11) == 2) self.assertTrue(posTracker.getReturn(11) == 0.1) self.assertTrue(posTracker.getNetProfit(20) == 20) self.assertTrue(posTracker.getReturn(20) == 1) posTracker.sell(1, 11) self.assertTrue(posTracker.getCost() == 20) self.assertTrue(posTracker.getNetProfit(11) == 2) self.assertTrue(posTracker.getReturn(11) == 0.1) posTracker.sell(1, 10) self.assertTrue(posTracker.getCost() == 20) self.assertTrue(posTracker.getNetProfit(PosTrackerTestCase.invalid_price) == 1) self.assertTrue(posTracker.getReturn(11) == 0.05)
def __onOrderEvent(self, broker_, orderEvent): # Only interested in filled or partially filled orders. if orderEvent.getEventType() not in ( broker.OrderEvent.Type.PARTIALLY_FILLED, broker.OrderEvent.Type.FILLED): return order = orderEvent.getOrder() # Get or create the tracker for this instrument. try: posTracker = self.__posTrackers[order.getInstrument()] except KeyError: posTracker = returns.PositionTracker(order.getInstrumentTraits()) self.__posTrackers[order.getInstrument()] = posTracker # Update the tracker for this order. execInfo = orderEvent.getEventInfo() price = execInfo.getPrice() commission = execInfo.getCommission() action = order.getAction() if action in [ broker.Order.Action.BUY, broker.Order.Action.BUY_TO_COVER ]: quantity = execInfo.getQuantity() elif action in [ broker.Order.Action.SELL, broker.Order.Action.SELL_SHORT ]: quantity = execInfo.getQuantity() * -1 else: # Unknown action assert (False) self.__updatePosTracker(posTracker, price, commission, quantity) self.all_trade.loc[len(self.all_trade), :] = [ order.getSubmitDateTime(), order.getInstrument(), self.action[str(order.getAction())], order.getAvgFillPrice(), order.getQuantity() ]
def testProfitReturnsAndCost(self): posTracker = returns.PositionTracker(INSTRUMENT, DefaultInstrumentTraits()) posTracker.buy(10, 1) self.assertEqual(posTracker.getPnL(), 0) self.assertEqual(posTracker.getAvgPrice(), 1) self.assertEqual(posTracker.getCommissions(), 0) self.assertEqual(posTracker.getPosition(), 10) posTracker.buy(20, 1, 10) self.assertEqual(posTracker.getPnL(), -10) self.assertEqual(posTracker.getAvgPrice(), 1) self.assertEqual(posTracker.getCommissions(), 10) self.assertEqual(posTracker.getPosition(), 30) posTracker.sell(30, 1) self.assertEqual(posTracker.getAvgPrice(), 0) self.assertEqual(posTracker.getPnL(), -10) self.assertEqual(posTracker.getPosition(), 0) self.assertEqual(posTracker.getCommissions(), 10) self.assertEqual(posTracker.getReturn(), -10/30.0) posTracker.buy(10, 1) self.assertEqual(posTracker.getPnL(), -10) self.assertEqual(posTracker.getAvgPrice(), 1)
def testProfitReturnsAndCost(self): posTracker = returns.PositionTracker(broker.IntegerTraits()) posTracker.buy(10, 1) self.assertEqual(posTracker.getPnL(), 0) self.assertEqual(posTracker.getAvgPrice(), 1) self.assertEqual(posTracker.getCommissions(), 0) # self.assertEqual(posTracker.getCash(), -10) posTracker.buy(20, 1, 10) self.assertEqual(posTracker.getPnL(), -10) self.assertEqual(posTracker.getAvgPrice(), 1) self.assertEqual(posTracker.getCommissions(), 10) # self.assertEqual(posTracker.getCash(), -40) posTracker.sell(30, 1) self.assertEqual(posTracker.getAvgPrice(), 0) self.assertEqual(posTracker.getPnL(), -10) # self.assertEqual(posTracker.getCash(), -10) self.assertEqual(posTracker.getCommissions(), 10) self.assertEqual(posTracker.getReturn(), -10 / 30.0) posTracker.buy(10, 1) self.assertEqual(posTracker.getPnL(), -10) self.assertEqual(posTracker.getAvgPrice(), 1)
def __onOrderUpdate(self, broker_, order): # Only interested in filled orders. if not order.isFilled(): return # Get or create the tracker for this instrument. try: posTracker = self.__posTrackers[order.getInstrument()] except KeyError: posTracker = returns.PositionTracker() self.__posTrackers[order.getInstrument()] = posTracker # Update the tracker for this order. price = order.getExecutionInfo().getPrice() commission = order.getExecutionInfo().getCommission() action = order.getAction() if action in [broker.Order.Action.BUY, broker.Order.Action.BUY_TO_COVER]: quantity = order.getExecutionInfo().getQuantity() elif action in [broker.Order.Action.SELL, broker.Order.Action.SELL_SHORT]: quantity = order.getExecutionInfo().getQuantity() * -1 else: # Unknown action assert(False) self.__updatePosTracker(posTracker, price, commission, quantity)