def __init__(self, initial_cash, events_queue, price_handler, position_sizer, risk_manager): """ The PortfolioHandler is designed to interact with the backtesting or live trading overall event-driven architecture. It exposes two methods, on_signal and on_fill, which handle how SignalEvent and FillEvent objects are dealt with. Each PortfolioHandler contains a Portfolio object, which stores the actual Position objects. The PortfolioHandler takes a handle to a PositionSizer object which determines a mechanism, based on the current Portfolio, as to how to size a new Order. The PortfolioHandler also takes a handle to the RiskManager, which is used to modify any generated Orders to remain in line with risk parameters. """ self.initial_cash = initial_cash self.events_queue = events_queue self.price_handler = price_handler self.position_sizer = position_sizer self.risk_manager = risk_manager self.portfolio = Portfolio(price_handler, initial_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)
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.assertEqual(results["sharpe"], Decimal("1.8353"))
class PriceHandlerMock(object): def __init__(self): pass def get_best_bid_ask(self, ticker): prices = { "GOOG": (Decimal("762.15"), Decimal("762.15")), "AMZN": (Decimal("660.51"), Decimal("660.51")), } return prices[ticker] ph = PriceHandlerMock() cash = Decimal("500000.00") port = Portfolio(ph, cash) port.add_position("BOT", "GOOG", 100, Decimal("761.75"), Decimal("1.00")) port.add_position("BOT", "AMZN", 100, Decimal("660.86"), Decimal("1.00")) port.modify_position("BOT", "AMZN", 100, Decimal("660.14"), Decimal("1.00")) port.modify_position("BOT", "AMZN", 150, Decimal("660.20"), Decimal("1.00")) port.modify_position("SLD", "AMZN", 300, Decimal("659.713"), Decimal("1.50")) print("CASH:", port.cur_cash) print("EQUITY:", port.equity) print("UPnL:", port.unrealised_pnl) print("PnL:", port.realised_pnl) pprint.pprint(port.positions) print("") for p in port.positions: