def setUp(self): """ Set up the Portfolio object that will store the collection of Position objects, supplying it with $500,000.00 USD in initial cash. """ ph = PriceHandlerMock() cash = PriceParser.parse(500000.00) self.portfolio = Portfolio(ph, cash)
def setUp(self): """ Set up the Portfolio object that will store the collection of Position objects, supplying it with $500,000.00 USD in initial cash. """ ph = PriceHandlerMock() cash = Decimal("500000.00") self.portfolio = Portfolio(ph, cash)
class TestLiquidateRebalancePositionSizer(unittest.TestCase): def setUp(self): price_handler_mock = PriceHandlerMock() ticker_weights = {"AAA": 0.3, "BBB": 0.7} self.position_sizer = LiquidateRebalancePositionSizer(ticker_weights) self.portfolio = Portfolio(price_handler_mock, PriceParser.parse(10000.00)) def test_will_add_positions(self): """ Tests that the position sizer will open up new positions with the correct weights. """ order_a = SuggestedOrder("AAA", "BOT", 0) order_b = SuggestedOrder("BBB", "BOT", 0) sized_a = self.position_sizer.size_order(self.portfolio, order_a) sized_b = self.position_sizer.size_order(self.portfolio, order_b) self.assertEqual(sized_a.action, "BOT") self.assertEqual(sized_b.action, "BOT") self.assertEqual(sized_a.quantity, 60) self.assertEqual(sized_b.quantity, 70) def test_will_liquidate_positions(self): """ Ensure positions will be liquidated completely when asked. Include a long & a short. """ self.portfolio._add_position("BOT", "AAA", 100, PriceParser.parse(60.00), 0.0) self.portfolio._add_position("BOT", "BBB", -100, PriceParser.parse(60.00), 0.0) exit_a = SuggestedOrder("AAA", "EXIT", 0) exit_b = SuggestedOrder("BBB", "EXIT", 0) sized_a = self.position_sizer.size_order(self.portfolio, exit_a) sized_b = self.position_sizer.size_order(self.portfolio, exit_b) self.assertEqual(sized_a.action, "SLD") self.assertEqual(sized_b.action, "BOT") self.assertEqual(sized_a.quantity, 100) self.assertEqual(sized_a.quantity, 100)
def test_calculating_statistics(self): """ Purchase/sell multiple lots of AMZN, GOOG at various prices/commissions to ensure the arithmetic in calculating equity, drawdowns and sharpe ratio is correct. """ # Create Statistics object price_handler = PriceHandlerMock() self.portfolio = Portfolio(price_handler, PriceParser.parse(500000.00)) portfolio_handler = PortfolioHandlerMock(self.portfolio) statistics = SimpleStatistics(self.config, portfolio_handler) # Check initialization was correct self.assertEqual(PriceParser.display(statistics.equity[0]), 500000.00) self.assertEqual(PriceParser.display(statistics.drawdowns[0]), 00) self.assertEqual(statistics.equity_returns[0], 0.0) # Perform transaction and test statistics at this tick self.portfolio.transact_position( "BOT", "AMZN", 100, PriceParser.parse(566.56), PriceParser.parse(1.00) ) t = "2000-01-01 00:00:00" statistics.update(t, portfolio_handler) self.assertEqual(PriceParser.display(statistics.equity[1]), 499807.00) self.assertEqual(PriceParser.display(statistics.drawdowns[1]), 193.00) self.assertEqual(statistics.equity_returns[1], -0.0386) # Perform transaction and test statistics at this tick self.portfolio.transact_position( "BOT", "AMZN", 200, PriceParser.parse(566.395), PriceParser.parse(1.00) ) t = "2000-01-02 00:00:00" statistics.update(t, portfolio_handler) self.assertEqual(PriceParser.display(statistics.equity[2]), 499455.00) self.assertEqual(PriceParser.display(statistics.drawdowns[2]), 545.00) self.assertEqual(statistics.equity_returns[2], -0.0705) # Perform transaction and test statistics at this tick self.portfolio.transact_position( "BOT", "GOOG", 200, PriceParser.parse(707.50), PriceParser.parse(1.00) ) t = "2000-01-03 00:00:00" statistics.update(t, portfolio_handler) self.assertEqual(PriceParser.display(statistics.equity[3]), 499046.00) self.assertEqual(PriceParser.display(statistics.drawdowns[3]), 954.00) self.assertEqual(statistics.equity_returns[3], -0.0820) # Perform transaction and test statistics at this tick self.portfolio.transact_position( "SLD", "AMZN", 100, PriceParser.parse(565.83), PriceParser.parse(1.00) ) t = "2000-01-04 00:00:00" statistics.update(t, portfolio_handler) self.assertEqual(PriceParser.display(statistics.equity[4]), 499164.00) self.assertEqual(PriceParser.display(statistics.drawdowns[4]), 836.00) self.assertEqual(statistics.equity_returns[4], 0.0236) # Perform transaction and test statistics at this tick self.portfolio.transact_position( "BOT", "GOOG", 200, PriceParser.parse(705.545), PriceParser.parse(1.00) ) t = "2000-01-05 00:00:00" statistics.update(t, portfolio_handler) self.assertEqual(PriceParser.display(statistics.equity[5]), 499146.00) self.assertEqual(PriceParser.display(statistics.drawdowns[5]), 854.00) self.assertEqual(statistics.equity_returns[5], -0.0036) # Perform transaction and test statistics at this tick self.portfolio.transact_position( "SLD", "AMZN", 200, PriceParser.parse(565.59), PriceParser.parse(1.00) ) t = "2000-01-06 00:00:00" statistics.update(t, portfolio_handler) self.assertEqual(PriceParser.display(statistics.equity[6]), 499335.00) self.assertEqual(PriceParser.display(statistics.drawdowns[6]), 665.00) self.assertEqual(statistics.equity_returns[6], 0.0379) # Perform transaction and test statistics at this tick self.portfolio.transact_position( "SLD", "GOOG", 100, PriceParser.parse(707.92), PriceParser.parse(1.00) ) t = "2000-01-07 00:00:00" statistics.update(t, portfolio_handler) self.assertEqual(PriceParser.display(statistics.equity[7]), 499580.00) self.assertEqual(PriceParser.display(statistics.drawdowns[7]), 420.00) self.assertEqual(statistics.equity_returns[7], 0.0490) # Perform transaction and test statistics at this tick self.portfolio.transact_position( "SLD", "GOOG", 100, PriceParser.parse(707.90), PriceParser.parse(0.00) ) t = "2000-01-08 00:00:00" statistics.update(t, portfolio_handler) self.assertEqual(PriceParser.display(statistics.equity[8]), 499824.00) self.assertEqual(PriceParser.display(statistics.drawdowns[8]), 176.00) self.assertEqual(statistics.equity_returns[8], 0.0488) # Perform transaction and test statistics at this tick self.portfolio.transact_position( "SLD", "GOOG", 100, PriceParser.parse(707.92), PriceParser.parse(0.50) ) t = "2000-01-09 00:00:00" statistics.update(t, portfolio_handler) self.assertEqual(PriceParser.display(statistics.equity[9]), 500069.50) self.assertEqual(PriceParser.display(statistics.drawdowns[9]), 00.00) self.assertEqual(statistics.equity_returns[9], 0.0491) # Perform transaction and test statistics at this tick self.portfolio.transact_position( "SLD", "GOOG", 100, PriceParser.parse(707.78), PriceParser.parse(1.00) ) t = "2000-01-10 00:00:00" statistics.update(t, portfolio_handler) self.assertEqual(PriceParser.display(statistics.equity[10]), 500300.50) self.assertEqual(PriceParser.display(statistics.drawdowns[10]), 00.00) self.assertEqual(statistics.equity_returns[10], 0.0462) # Test that results are calculated correctly. results = statistics.get_results() self.assertEqual(results["max_drawdown"], 954.00) self.assertEqual(results["max_drawdown_pct"], 0.1908) self.assertAlmostEqual(float(results["sharpe"]), 1.7575)
def test_calculating_statistics(self): """ Purchase/sell multiple lots of AMZN, GOOG at various prices/commissions to ensure the arithmetic in calculating equity, drawdowns and sharpe ratio is correct. """ # Create Statistics object price_handler = PriceHandlerMock() self.portfolio = Portfolio(price_handler, Decimal("500000.00")) portfolio_handler = PortfolioHandlerMock(self.portfolio) statistics = SimpleStatistics(portfolio_handler) # Perform transaction and test statistics at this tick self.portfolio.transact_position( "BOT", "AMZN", 100, Decimal("566.56"), Decimal("1.00") ) t = "2000-01-01 00:00:00" statistics.update(t) self.assertEqual(statistics.equity[t], Decimal("499807.00")) self.assertEqual(statistics.drawdowns[t], Decimal("193.00")) self.assertEqual(statistics.equity_returns[t], Decimal("-0.0386")) # Perform transaction and test statistics at this tick self.portfolio.transact_position( "BOT", "AMZN", 200, Decimal ("566.395"), Decimal("1.00") ) t = "2000-01-02 00:00:00" statistics.update(t) self.assertEqual(statistics.equity[t], Decimal("499455.00")) self.assertEqual(statistics.drawdowns[t], Decimal("545.00")) self.assertEqual(statistics.equity_returns[t], Decimal("-0.0705")) # Perform transaction and test statistics at this tick self.portfolio.transact_position( "BOT", "GOOG", 200, Decimal("707.50"), Decimal("1.00") ) t = "2000-01-03 00:00:00" statistics.update(t) self.assertEqual(statistics.equity[t], Decimal("499046.00")) self.assertEqual(statistics.drawdowns[t], Decimal("954.00")) self.assertEqual(statistics.equity_returns[t], Decimal("-0.0820")) # Perform transaction and test statistics at this tick self.portfolio.transact_position( "SLD", "AMZN", 100, Decimal("565.83"), Decimal("1.00") ) t = "2000-01-04 00:00:00" statistics.update(t) self.assertEqual(statistics.equity[t], Decimal("499164.00")) self.assertEqual(statistics.drawdowns[t], Decimal("836.00")) self.assertEqual(statistics.equity_returns[t], Decimal("0.0236")) # Perform transaction and test statistics at this tick self.portfolio.transact_position( "BOT", "GOOG", 200, Decimal("705.545"), Decimal("1.00") ) t = "2000-01-05 00:00:00" statistics.update(t) self.assertEqual(statistics.equity[t], Decimal("499146.00")) self.assertEqual(statistics.drawdowns[t], Decimal("854.00")) self.assertEqual(statistics.equity_returns[t], Decimal("-0.0036")) # Perform transaction and test statistics at this tick self.portfolio.transact_position( "SLD", "AMZN", 200, Decimal("565.59"), Decimal("1.00") ) t = "2000-01-06 00:00:00" statistics.update(t) self.assertEqual(statistics.equity[t], Decimal("499335.00")) self.assertEqual(statistics.drawdowns[t], Decimal("665.00")) self.assertEqual(statistics.equity_returns[t], Decimal("0.0379")) # Perform transaction and test statistics at this tick self.portfolio.transact_position( "SLD", "GOOG", 100, Decimal("707.92"), Decimal("1.00") ) t = "2000-01-07 00:00:00" statistics.update(t) self.assertEqual(statistics.equity[t], Decimal("499580.00")) self.assertEqual(statistics.drawdowns[t], Decimal("420.00")) self.assertEqual(statistics.equity_returns[t], Decimal("0.0490")) # Perform transaction and test statistics at this tick self.portfolio.transact_position( "SLD", "GOOG", 100, Decimal("707.90"), Decimal("0.00") ) t = "2000-01-08 00:00:00" statistics.update(t) self.assertEqual(statistics.equity[t], Decimal("499824.00")) self.assertEqual(statistics.drawdowns[t], Decimal("176.00")) self.assertEqual(statistics.equity_returns[t], Decimal("0.0488")) # Perform transaction and test statistics at this tick self.portfolio.transact_position( "SLD", "GOOG", 100, Decimal("707.92"), Decimal("0.50") ) t = "2000-01-09 00:00:00" statistics.update(t) self.assertEqual(statistics.equity[t], Decimal("500069.50")) self.assertEqual(statistics.drawdowns[t], Decimal("00.00")) self.assertEqual(statistics.equity_returns[t], Decimal("0.0491")) # Perform transaction and test statistics at this tick self.portfolio.transact_position( "SLD", "GOOG", 100, Decimal("707.78"), Decimal("1.00") ) t = "2000-01-10 00:00:00" statistics.update(t) self.assertEqual(statistics.equity[t], Decimal("500300.50")) self.assertEqual(statistics.drawdowns[t], Decimal("00.00")) self.assertEqual(statistics.equity_returns[t], Decimal("0.0462")) # Test that results are calculated correctly. results = statistics.get_results() self.assertEqual(results["max_drawdown"], Decimal("954.00")) self.assertEqual(results["max_drawdown_pct"], Decimal("0.1908")) self.assertAlmostEqual(float(results["sharpe"]), 1.8353)
def test_calculating_statistics(self): """ Purchase/sell multiple lots of AMZN, GOOG at various prices/commissions to ensure the arithmetic in calculating equity, drawdowns and sharpe ratio is correct. """ # Create Statistics object price_handler = PriceHandlerMock() self.portfolio = Portfolio(price_handler, PriceParser.parse(500000.00)) portfolio_handler = PortfolioHandlerMock(self.portfolio) statistics = SimpleStatistics(self.config, portfolio_handler) # Check initialization was correct self.assertEqual(PriceParser.display(statistics.equity[0]), 500000.00) self.assertEqual(PriceParser.display(statistics.drawdowns[0]), 00) self.assertEqual(statistics.equity_returns[0], 0.0) # Perform transaction and test statistics at this tick self.portfolio.transact_position("BOT", "AMZN", 100, PriceParser.parse(566.56), PriceParser.parse(1.00)) t = "2000-01-01 00:00:00" statistics.update(t, portfolio_handler) self.assertEqual(PriceParser.display(statistics.equity[1]), 499807.00) self.assertEqual(PriceParser.display(statistics.drawdowns[1]), 193.00) self.assertEqual(statistics.equity_returns[1], -0.0386) # Perform transaction and test statistics at this tick self.portfolio.transact_position("BOT", "AMZN", 200, PriceParser.parse(566.395), PriceParser.parse(1.00)) t = "2000-01-02 00:00:00" statistics.update(t, portfolio_handler) self.assertEqual(PriceParser.display(statistics.equity[2]), 499455.00) self.assertEqual(PriceParser.display(statistics.drawdowns[2]), 545.00) self.assertEqual(statistics.equity_returns[2], -0.0705) # Perform transaction and test statistics at this tick self.portfolio.transact_position("BOT", "GOOG", 200, PriceParser.parse(707.50), PriceParser.parse(1.00)) t = "2000-01-03 00:00:00" statistics.update(t, portfolio_handler) self.assertEqual(PriceParser.display(statistics.equity[3]), 499046.00) self.assertEqual(PriceParser.display(statistics.drawdowns[3]), 954.00) self.assertEqual(statistics.equity_returns[3], -0.0820) # Perform transaction and test statistics at this tick self.portfolio.transact_position("SLD", "AMZN", 100, PriceParser.parse(565.83), PriceParser.parse(1.00)) t = "2000-01-04 00:00:00" statistics.update(t, portfolio_handler) self.assertEqual(PriceParser.display(statistics.equity[4]), 499164.00) self.assertEqual(PriceParser.display(statistics.drawdowns[4]), 836.00) self.assertEqual(statistics.equity_returns[4], 0.0236) # Perform transaction and test statistics at this tick self.portfolio.transact_position("BOT", "GOOG", 200, PriceParser.parse(705.545), PriceParser.parse(1.00)) t = "2000-01-05 00:00:00" statistics.update(t, portfolio_handler) self.assertEqual(PriceParser.display(statistics.equity[5]), 499146.00) self.assertEqual(PriceParser.display(statistics.drawdowns[5]), 854.00) self.assertEqual(statistics.equity_returns[5], -0.0036) # Perform transaction and test statistics at this tick self.portfolio.transact_position("SLD", "AMZN", 200, PriceParser.parse(565.59), PriceParser.parse(1.00)) t = "2000-01-06 00:00:00" statistics.update(t, portfolio_handler) self.assertEqual(PriceParser.display(statistics.equity[6]), 499335.00) self.assertEqual(PriceParser.display(statistics.drawdowns[6]), 665.00) self.assertEqual(statistics.equity_returns[6], 0.0379) # Perform transaction and test statistics at this tick self.portfolio.transact_position("SLD", "GOOG", 100, PriceParser.parse(707.92), PriceParser.parse(1.00)) t = "2000-01-07 00:00:00" statistics.update(t, portfolio_handler) self.assertEqual(PriceParser.display(statistics.equity[7]), 499580.00) self.assertEqual(PriceParser.display(statistics.drawdowns[7]), 420.00) self.assertEqual(statistics.equity_returns[7], 0.0490) # Perform transaction and test statistics at this tick self.portfolio.transact_position("SLD", "GOOG", 100, PriceParser.parse(707.90), PriceParser.parse(0.00)) t = "2000-01-08 00:00:00" statistics.update(t, portfolio_handler) self.assertEqual(PriceParser.display(statistics.equity[8]), 499824.00) self.assertEqual(PriceParser.display(statistics.drawdowns[8]), 176.00) self.assertEqual(statistics.equity_returns[8], 0.0488) # Perform transaction and test statistics at this tick self.portfolio.transact_position("SLD", "GOOG", 100, PriceParser.parse(707.92), PriceParser.parse(0.50)) t = "2000-01-09 00:00:00" statistics.update(t, portfolio_handler) self.assertEqual(PriceParser.display(statistics.equity[9]), 500069.50) self.assertEqual(PriceParser.display(statistics.drawdowns[9]), 00.00) self.assertEqual(statistics.equity_returns[9], 0.0491) # Perform transaction and test statistics at this tick self.portfolio.transact_position("SLD", "GOOG", 100, PriceParser.parse(707.78), PriceParser.parse(1.00)) t = "2000-01-10 00:00:00" statistics.update(t, portfolio_handler) self.assertEqual(PriceParser.display(statistics.equity[10]), 500300.50) self.assertEqual(PriceParser.display(statistics.drawdowns[10]), 00.00) self.assertEqual(statistics.equity_returns[10], 0.0462) # Test that results are calculated correctly. results = statistics.get_results() self.assertEqual(results["max_drawdown"], 954.00) self.assertEqual(results["max_drawdown_pct"], 0.1908) self.assertAlmostEqual(float(results["sharpe"]), 1.7575)
class TestAmazonGooglePortfolio(unittest.TestCase): """ Test a portfolio consisting of Amazon and Google/Alphabet with various orders to create round-trips for both. These orders were carried out in the Interactive Brokers demo account and checked for cash, equity and PnL equality. """ def setUp(self): """ Set up the Portfolio object that will store the collection of Position objects, supplying it with $500,000.00 USD in initial cash. """ ph = PriceHandlerMock() cash = Decimal("500000.00") self.portfolio = Portfolio(ph, cash) def test_calculate_round_trip(self): """ Purchase/sell multiple lots of AMZN and GOOG at various prices/commissions to check the arithmetic and cost handling. """ # Buy 300 of AMZN over two transactions self.portfolio.transact_position( "BOT", "AMZN", 100, Decimal("566.56"), Decimal("1.00") ) self.portfolio.transact_position( "BOT", "AMZN", 200, Decimal("566.395"), Decimal("1.00") ) # Buy 200 GOOG over one transaction self.portfolio.transact_position( "BOT", "GOOG", 200, Decimal("707.50"), Decimal("1.00") ) # Add to the AMZN position by 100 shares self.portfolio.transact_position( "SLD", "AMZN", 100, Decimal("565.83"), Decimal("1.00") ) # Add to the GOOG position by 200 shares self.portfolio.transact_position( "BOT", "GOOG", 200, Decimal("705.545"), Decimal("1.00") ) # Sell 200 of the AMZN shares self.portfolio.transact_position( "SLD", "AMZN", 200, Decimal("565.59"), Decimal("1.00") ) # Multiple transactions bundled into one (in IB) # Sell 300 GOOG from the portfolio self.portfolio.transact_position( "SLD", "GOOG", 100, Decimal("704.92"), Decimal("1.00") ) self.portfolio.transact_position( "SLD", "GOOG", 100, Decimal("704.90"), Decimal("0.00") ) self.portfolio.transact_position( "SLD", "GOOG", 100, Decimal("704.92"), Decimal("0.50") ) # Finally, sell the remaining GOOG 100 shares self.portfolio.transact_position( "SLD", "GOOG", 100, Decimal("704.78"), Decimal("1.00") ) # The figures below are derived from Interactive Brokers # demo account using the above trades with prices provided # by their demo feed. self.assertEqual(self.portfolio.cur_cash, Decimal("499100.50")) self.assertEqual(self.portfolio.equity, Decimal("499100.50")) self.assertEqual(self.portfolio.unrealised_pnl, Decimal("0.00")) self.assertEqual(self.portfolio.realised_pnl, Decimal("-899.50"))
class TestAmazonGooglePortfolio(unittest.TestCase): """ Test a portfolio consisting of Amazon and Google/Alphabet with various orders to create round-trips for both. These orders were carried out in the Interactive Brokers demo account and checked for cash, equity and PnL equality. """ def setUp(self): """ Set up the Portfolio object that will store the collection of Position objects, supplying it with $500,000.00 USD in initial cash. """ ph = PriceHandlerMock() cash = PriceParser.parse(500000.00) self.portfolio = Portfolio(ph, cash) def test_calculate_round_trip(self): """ Purchase/sell multiple lots of AMZN and GOOG at various prices/commissions to check the arithmetic and cost handling. """ # Buy 300 of AMZN over two transactions self.portfolio.transact_position( "BOT", "AMZN", 100, PriceParser.parse(566.56), PriceParser.parse(1.00) ) self.portfolio.transact_position( "BOT", "AMZN", 200, PriceParser.parse(566.395), PriceParser.parse(1.00) ) # Buy 200 GOOG over one transaction self.portfolio.transact_position( "BOT", "GOOG", 200, PriceParser.parse(707.50), PriceParser.parse(1.00) ) # Add to the AMZN position by 100 shares self.portfolio.transact_position( "SLD", "AMZN", 100, PriceParser.parse(565.83), PriceParser.parse(1.00) ) # Add to the GOOG position by 200 shares self.portfolio.transact_position( "BOT", "GOOG", 200, PriceParser.parse(705.545), PriceParser.parse(1.00) ) # Sell 200 of the AMZN shares self.portfolio.transact_position( "SLD", "AMZN", 200, PriceParser.parse(565.59), PriceParser.parse(1.00) ) # Multiple transactions bundled into one (in IB) # Sell 300 GOOG from the portfolio self.portfolio.transact_position( "SLD", "GOOG", 100, PriceParser.parse(704.92), PriceParser.parse(1.00) ) self.portfolio.transact_position( "SLD", "GOOG", 100, PriceParser.parse(704.90), PriceParser.parse(0.00) ) self.portfolio.transact_position( "SLD", "GOOG", 100, PriceParser.parse(704.92), PriceParser.parse(0.50) ) # Finally, sell the remaining GOOG 100 shares self.portfolio.transact_position( "SLD", "GOOG", 100, PriceParser.parse(704.78), PriceParser.parse(1.00) ) # The figures below are derived from Interactive Brokers # demo account using the above trades with prices provided # by their demo feed. self.assertEqual(len(self.portfolio.positions), 0) self.assertEqual(len(self.portfolio.closed_positions), 2) self.assertEqual(PriceParser.display(self.portfolio.cur_cash), 499100.50) self.assertEqual(PriceParser.display(self.portfolio.equity), 499100.50) self.assertEqual(PriceParser.display(self.portfolio.unrealised_pnl), 0.00) self.assertEqual(PriceParser.display(self.portfolio.realised_pnl), -899.50)
def setUp(self): price_handler_mock = PriceHandlerMock() ticker_weights = {"AAA": 0.3, "BBB": 0.7} self.position_sizer = LiquidateRebalancePositionSizer(ticker_weights) self.portfolio = Portfolio(price_handler_mock, PriceParser.parse(10000.00))