def setUp(self): # Fixture Setup clock = TestClock() logger = TestLogger(clock) self.order_factory = OrderFactory( trader_id=TraderId("TESTER", "000"), strategy_id=StrategyId("S", "001"), clock=TestClock(), ) state = AccountState( account_id=AccountId("BINANCE", "1513111"), balances=[Money("10.00000000", BTC)], balances_free=[Money("0.00000000", BTC)], balances_locked=[Money("0.00000000", BTC)], info={}, event_id=uuid4(), event_timestamp=UNIX_EPOCH, ) self.data_cache = DataCache(logger) self.account = Account(state) self.portfolio = Portfolio(clock, logger) self.portfolio.register_account(self.account) self.portfolio.register_cache(self.data_cache) self.data_cache.add_instrument(AUDUSD_SIM) self.data_cache.add_instrument(GBPUSD_SIM) self.data_cache.add_instrument(BTCUSDT_BINANCE) self.data_cache.add_instrument(BTCUSD_BITMEX) self.data_cache.add_instrument(ETHUSD_BITMEX)
def setup(self): # Fixture Setup self.clock = LiveClock() self.uuid_factory = UUIDFactory() self.logger = Logger(self.clock) self.trader_id = TraderId("TESTER", "000") self.account_id = TestStubs.account_id() self.order_factory = OrderFactory( trader_id=self.trader_id, strategy_id=StrategyId("S", "001"), clock=self.clock, ) self.random_order_factory = OrderFactory( trader_id=TraderId("RANDOM", "042"), strategy_id=StrategyId("S", "042"), clock=self.clock, ) self.portfolio = Portfolio( clock=self.clock, logger=self.logger, ) self.portfolio.register_cache(DataCache(self.logger)) self.analyzer = PerformanceAnalyzer() # Fresh isolated loop testing pattern self.loop = asyncio.new_event_loop() asyncio.set_event_loop(self.loop) self.database = BypassExecutionDatabase(trader_id=self.trader_id, logger=self.logger) self.engine = LiveExecutionEngine( loop=self.loop, database=self.database, portfolio=self.portfolio, clock=self.clock, logger=self.logger, ) self.instrument_provider = InstrumentProvider() self.instrument_provider.add(AUDUSD_SIM) self.instrument_provider.add(GBPUSD_SIM) self.client = MockLiveExecutionClient( name=SIM.value, account_id=self.account_id, engine=self.engine, instrument_provider=self.instrument_provider, clock=self.clock, logger=self.logger, ) self.engine.register_client(self.client)
def setUp(self): # Fixture Setup self.clock = TestClock() self.uuid_factory = UUIDFactory() self.logger = TestLogger(self.clock) self.trader_id = TraderId("TESTER", "000") self.account_id = AccountId("BINANCE", "000") self.portfolio = Portfolio( clock=self.clock, logger=self.logger, ) self.portfolio.register_cache(DataCache(self.logger)) self.analyzer = PerformanceAnalyzer() database = BypassExecutionDatabase( trader_id=self.trader_id, logger=self.logger, ) self.exec_engine = ExecutionEngine( database=database, portfolio=self.portfolio, clock=self.clock, logger=self.logger, ) self.exchange = SimulatedExchange( venue=Venue("BINANCE"), oms_type=OMSType.NETTING, generate_position_ids=True, is_frozen_account=False, starting_balances=[Money(1_000_000, USD)], instruments=[ETHUSDT_BINANCE], modules=[], exec_cache=self.exec_engine.cache, fill_model=FillModel(), clock=self.clock, logger=self.logger, ) self.exec_client = BacktestExecClient( exchange=self.exchange, account_id=self.account_id, engine=self.exec_engine, clock=self.clock, logger=self.logger, ) self.order_factory = OrderFactory( trader_id=self.trader_id, strategy_id=StrategyId("SCALPER", "000"), clock=self.clock, )
def setUp(self): # Fixture Setup self.clock = TestClock() logger = TestLogger(self.clock) self.order_factory = OrderFactory( trader_id=TraderId("TESTER", "000"), strategy_id=StrategyId("S", "001"), clock=TestClock(), ) self.portfolio = Portfolio(self.clock, logger) self.portfolio.register_cache(DataCache(logger))
def setUp(self): # Fixture Setup self.clock = LiveClock() self.uuid_factory = UUIDFactory() self.logger = TestLogger(self.clock, bypass_logging=True) self.trader_id = TraderId("TESTER", "000") self.account_id = AccountId("BINANCE", "001") self.portfolio = Portfolio( clock=self.clock, logger=self.logger, ) self.portfolio.register_cache(DataCache(self.logger)) self.analyzer = PerformanceAnalyzer() # Fresh isolated loop testing pattern self.loop = asyncio.new_event_loop() asyncio.set_event_loop(self.loop) database = BypassExecutionDatabase(trader_id=self.trader_id, logger=self.logger) self.exec_engine = LiveExecutionEngine( loop=self.loop, database=database, portfolio=self.portfolio, clock=self.clock, logger=self.logger, ) exec_client = MockExecutionClient( venue=Venue("BINANCE"), account_id=self.account_id, exec_engine=self.exec_engine, clock=self.clock, logger=self.logger, ) self.exec_engine.register_client(exec_client) self.exec_engine.process(TestStubs.event_account_state( self.account_id)) self.strategy = TradingStrategy(order_id_tag="001") self.strategy.register_trader( TraderId("TESTER", "000"), self.clock, self.logger, ) self.exec_engine.register_strategy(self.strategy)
def setUp(self): # Fixture Setup # Fresh isolated loop testing pattern self.loop = asyncio.new_event_loop() asyncio.set_event_loop(self.loop) self.clock = LiveClock() self.uuid_factory = UUIDFactory() self.logger = TestLogger(self.clock) self.trader_id = TraderId("TESTER", "000") self.account_id = TestStubs.account_id() self.order_factory = OrderFactory( trader_id=self.trader_id, strategy_id=StrategyId("S", "001"), clock=self.clock, ) self.portfolio = Portfolio( clock=self.clock, logger=self.logger, ) self.portfolio.register_cache(DataCache(self.logger)) self.analyzer = PerformanceAnalyzer() # Fresh isolated loop testing pattern self.loop = asyncio.new_event_loop() asyncio.set_event_loop(self.loop) database = BypassExecutionDatabase(trader_id=self.trader_id, logger=self.logger) self.engine = LiveExecutionEngine( loop=self.loop, database=database, portfolio=self.portfolio, clock=self.clock, logger=self.logger, ) instrument_provider = InstrumentProvider(venue=SIM, load_all=False) self.client = LiveExecutionClient( venue=SIM, account_id=self.account_id, engine=self.engine, instrument_provider=instrument_provider, clock=self.clock, logger=self.logger, )
def setUp(self): # Fixture Setup self.clock = TestClock() self.uuid_factory = UUIDFactory() self.logger = TestLogger(self.clock) self.trader_id = TraderId("TESTER", "000") self.account_id = TestStubs.account_id() self.order_factory = OrderFactory( trader_id=self.trader_id, strategy_id=StrategyId("S", "001"), clock=TestClock(), ) self.portfolio = Portfolio( clock=self.clock, logger=self.logger, ) self.portfolio.register_cache(DataCache(self.logger)) self.analyzer = PerformanceAnalyzer() database = BypassExecutionDatabase(trader_id=self.trader_id, logger=self.logger) self.exec_engine = ExecutionEngine( database=database, portfolio=self.portfolio, clock=self.clock, logger=self.logger, ) self.cache = self.exec_engine.cache self.exec_engine.process(TestStubs.event_account_state()) self.venue = Venue("SIM") self.exec_client = MockExecutionClient( self.venue, self.account_id, self.exec_engine, self.clock, self.logger, ) self.exec_engine.register_client(self.exec_client)
def setup(self): # Fixture Setup self.clock = TestClock() self.uuid_factory = UUIDFactory() self.logger = Logger(self.clock) self.trader_id = TraderId("TESTER", "000") self.account_id = TestStubs.account_id() self.venue = Venue("SIM") self.portfolio = Portfolio( clock=self.clock, logger=self.logger, ) self.portfolio.register_cache(DataCache(self.logger)) self.database = MockExecutionDatabase(trader_id=self.trader_id, logger=self.logger) self.exec_engine = ExecutionEngine( database=self.database, portfolio=self.portfolio, clock=self.clock, logger=self.logger, ) self.exec_client = MockExecutionClient( ClientId(self.venue.value), self.account_id, self.exec_engine, self.clock, self.logger, ) self.risk_engine = RiskEngine( exec_engine=self.exec_engine, portfolio=self.portfolio, clock=self.clock, logger=self.logger, config={}, ) self.exec_engine.register_client(self.exec_client) self.exec_engine.register_risk_engine(self.risk_engine)
def setUp(self): # Fixture Setup self.clock = TestClock() self.uuid_factory = UUIDFactory() self.logger = TestLogger(self.clock) self.trader_id = TraderId("TESTER", "000") self.account_id = TestStubs.account_id() portfolio = Portfolio( clock=self.clock, logger=self.logger, ) portfolio.register_cache(DataCache(self.logger)) database = BypassExecutionDatabase(trader_id=self.trader_id, logger=self.logger) self.exec_engine = ExecutionEngine( database=database, portfolio=portfolio, clock=self.clock, logger=self.logger, ) self.venue = Venue("SIM") self.client = ExecutionClient( venue=self.venue, account_id=self.account_id, engine=self.exec_engine, clock=self.clock, logger=self.logger, ) self.order_factory = OrderFactory( trader_id=TraderId("TESTER", "000"), strategy_id=StrategyId("S", "001"), clock=TestClock(), )
def setup(self): # Fixture Setup self.clock = LiveClock() self.uuid_factory = UUIDFactory() self.logger = Logger(self.clock) self.trader_id = TraderId("TESTER", "000") self.account_id = TestStubs.account_id() self.order_factory = OrderFactory( trader_id=self.trader_id, strategy_id=StrategyId("S", "001"), clock=self.clock, ) self.random_order_factory = OrderFactory( trader_id=TraderId("RANDOM", "042"), strategy_id=StrategyId("S", "042"), clock=self.clock, ) self.portfolio = Portfolio( clock=self.clock, logger=self.logger, ) self.portfolio.register_cache(DataCache(self.logger)) self.analyzer = PerformanceAnalyzer() # Fresh isolated loop testing pattern self.loop = asyncio.new_event_loop() asyncio.set_event_loop(self.loop) self.database = BypassExecutionDatabase(trader_id=self.trader_id, logger=self.logger) self.exec_engine = LiveExecutionEngine( loop=self.loop, database=self.database, portfolio=self.portfolio, clock=self.clock, logger=self.logger, ) self.venue = Venue("SIM") self.exec_client = MockExecutionClient( self.venue.value, self.account_id, self.exec_engine, self.clock, self.logger, ) self.risk_engine = LiveRiskEngine( loop=self.loop, exec_engine=self.exec_engine, portfolio=self.portfolio, clock=self.clock, logger=self.logger, config={}, ) self.exec_engine.register_client(self.exec_client) self.exec_engine.register_risk_engine(self.risk_engine)
def setUp(self): # Fixture Setup self.cache = DataCache(logger=TestLogger(TestClock()))
class DataCacheTests(unittest.TestCase): def setUp(self): # Fixture Setup self.cache = DataCache(logger=TestLogger(TestClock())) def test_reset_an_empty_cache(self): # Arrange # Act self.cache.reset() # Assert self.assertEqual([], self.cache.instruments()) self.assertEqual([], self.cache.quote_ticks(AUDUSD_SIM.id)) self.assertEqual([], self.cache.trade_ticks(AUDUSD_SIM.id)) self.assertEqual([], self.cache.bars(TestStubs.bartype_gbpusd_1sec_mid())) def test_instrument_ids_when_no_instruments_returns_empty_list(self): # Arrange # Act # Assert self.assertEqual([], self.cache.instrument_ids()) def test_instruments_when_no_instruments_returns_empty_list(self): # Arrange # Act # Assert self.assertEqual([], self.cache.instruments()) def test_quote_ticks_for_unknown_instrument_returns_empty_list(self): # Arrange # Act # Assert self.assertEqual([], self.cache.quote_ticks(AUDUSD_SIM.id)) def test_trade_ticks_for_unknown_instrument_returns_empty_list(self): # Arrange # Act # Assert self.assertEqual([], self.cache.trade_ticks(AUDUSD_SIM.id)) def test_bars_for_unknown_bar_type_returns_empty_list(self): # Arrange # Act # Assert self.assertEqual([], self.cache.bars(TestStubs.bartype_gbpusd_1sec_mid())) def test_instrument_when_no_instruments_returns_none(self): # Arrange # Act # Assert self.assertIsNone(self.cache.instrument(AUDUSD_SIM.id)) def test_order_book_for_unknown_instrument_returns_none(self): # Arrange # Act # Assert self.assertIsNone(self.cache.order_book(AUDUSD_SIM.id)) def test_quote_tick_when_no_ticks_returns_none(self): # Arrange # Act # Assert self.assertIsNone(self.cache.quote_tick(AUDUSD_SIM.id)) def test_trade_tick_when_no_ticks_returns_none(self): # Arrange # Act # Assert self.assertIsNone(self.cache.trade_tick(AUDUSD_SIM.id)) def test_bar_when_no_bars_returns_none(self): # Arrange # Act # Assert self.assertIsNone(self.cache.bar(TestStubs.bartype_gbpusd_1sec_mid())) def test_quote_tick_count_for_unknown_instrument_returns_zero(self): # Arrange # Act # Assert self.assertEqual(0, self.cache.quote_tick_count(AUDUSD_SIM.id)) def test_trade_tick_count_for_unknown_instrument_returns_zero(self): # Arrange # Act # Assert self.assertEqual(0, self.cache.trade_tick_count(AUDUSD_SIM.id)) def test_has_order_book_for_unknown_instrument_returns_false(self): # Arrange # Act # Assert self.assertFalse(self.cache.has_order_book(AUDUSD_SIM.id)) def test_has_quote_ticks_for_unknown_instrument_returns_false(self): # Arrange # Act # Assert self.assertFalse(self.cache.has_quote_ticks(AUDUSD_SIM.id)) def test_has_trade_ticks_for_unknown_instrument_returns_false(self): # Arrange # Act # Assert self.assertFalse(self.cache.has_trade_ticks(AUDUSD_SIM.id)) def test_has_bars_for_unknown_bar_type_returns_false(self): # Arrange # Act # Assert self.assertFalse(self.cache.has_bars(TestStubs.bartype_gbpusd_1sec_mid())) def test_instrument_ids_when_one_instrument_returns_expected_list(self): # Arrange instrument = TestInstrumentProvider.ethusdt_binance() self.cache.add_instrument(instrument) # Act result = self.cache.instrument_ids() # Assert self.assertEqual([instrument.id], result) def test_instruments_when_one_instrument_returns_expected_list(self): # Arrange instrument = TestInstrumentProvider.ethusdt_binance() self.cache.add_instrument(instrument) # Act result = self.cache.instruments() # Assert self.assertEqual([instrument], result) def test_quote_ticks_when_one_tick_returns_expected_list(self): # Arrange tick = QuoteTick( AUDUSD_SIM.id, Price("1.00000"), Price("1.00001"), Quantity(1), Quantity(1), UNIX_EPOCH, ) self.cache.add_quote_ticks([tick]) # Act result = self.cache.quote_ticks(tick.instrument_id) # Assert self.assertEqual([tick], result) def test_add_quote_ticks_when_already_ticks_does_not_add(self): # Arrange tick = QuoteTick( AUDUSD_SIM.id, Price("1.00000"), Price("1.00001"), Quantity(1), Quantity(1), UNIX_EPOCH, ) self.cache.add_quote_tick(tick) # Act self.cache.add_quote_ticks([tick]) result = self.cache.quote_ticks(tick.instrument_id) # Assert self.assertEqual([tick], result) def test_trade_ticks_when_one_tick_returns_expected_list(self): # Arrange tick = TradeTick( AUDUSD_SIM.id, Price("1.00000"), Quantity(10000), OrderSide.BUY, TradeMatchId("123456789"), UNIX_EPOCH, ) self.cache.add_trade_ticks([tick]) # Act result = self.cache.trade_ticks(tick.instrument_id) # Assert self.assertEqual([tick], result) def test_add_trade_ticks_when_already_ticks_does_not_add(self): # Arrange tick = TradeTick( AUDUSD_SIM.id, Price("1.00000"), Quantity(10000), OrderSide.BUY, TradeMatchId("123456789"), UNIX_EPOCH, ) self.cache.add_trade_tick(tick) # Act self.cache.add_trade_ticks([tick]) result = self.cache.trade_ticks(tick.instrument_id) # Assert self.assertEqual([tick], result) def test_bars_when_one_bar_returns_expected_list(self): # Arrange bar_type = TestStubs.bartype_gbpusd_1sec_mid() bar = Bar( Price("1.00001"), Price("1.00004"), Price("1.00002"), Price("1.00003"), Quantity(100000), UNIX_EPOCH, ) self.cache.add_bars(bar_type, [bar]) # Act result = self.cache.bars(bar_type) # Assert self.assertTrue([bar], result) def test_add_bars_when_already_bars_does_not_add(self): # Arrange bar_type = TestStubs.bartype_gbpusd_1sec_mid() bar = Bar( Price("1.00001"), Price("1.00004"), Price("1.00002"), Price("1.00003"), Quantity(100000), UNIX_EPOCH, ) self.cache.add_bar(bar_type, bar) # Act self.cache.add_bars(bar_type, [bar]) result = self.cache.bars(bar_type) # Assert self.assertTrue([bar], result) def test_instrument_when_no_instrument_returns_none(self): # Arrange # Act result = self.cache.instrument(AUDUSD_SIM.id) # Assert self.assertIsNone(result) def test_instrument_when_instrument_exists_returns_expected(self): # Arrange self.cache.add_instrument(AUDUSD_SIM) # Act result = self.cache.instrument(AUDUSD_SIM.id) # Assert self.assertEqual(AUDUSD_SIM, result) def test_order_book_when_order_book_exists_returns_expected(self): # Arrange order_book = OrderBook( instrument_id=ETHUSDT_BINANCE.id, level=2, depth=25, price_precision=2, size_precision=2, bids=[[1550.15, 0.51], [1580.00, 1.20]], asks=[[1552.15, 1.51], [1582.00, 2.20]], update_id=1, timestamp=0, ) self.cache.add_order_book(order_book) # Act result = self.cache.order_book(ETHUSDT_BINANCE.id) # Assert self.assertEqual(order_book, result) def test_price_when_no_ticks_returns_none(self): # Act result = self.cache.price(AUDUSD_SIM.id, PriceType.LAST) # Assert self.assertIsNone(result) def test_price_given_last_when_no_trade_ticks_returns_none(self): # Act tick = QuoteTick( AUDUSD_SIM.id, Price("1.00000"), Price("1.00001"), Quantity(1), Quantity(1), UNIX_EPOCH, ) self.cache.add_quote_tick(tick) result = self.cache.price(AUDUSD_SIM.id, PriceType.LAST) # Assert self.assertIsNone(result) def test_price_given_quote_price_type_when_no_quote_ticks_returns_none(self): # Arrange tick = TradeTick( AUDUSD_SIM.id, Price("1.00000"), Quantity(10000), OrderSide.BUY, TradeMatchId("123456789"), UNIX_EPOCH, ) self.cache.add_trade_tick(tick) # Act result = self.cache.price(AUDUSD_SIM.id, PriceType.MID) # Assert self.assertIsNone(result) def test_price_given_last_when_trade_tick_returns_expected_price(self): # Arrange tick = TradeTick( AUDUSD_SIM.id, Price("1.00000"), Quantity(10000), OrderSide.BUY, TradeMatchId("123456789"), UNIX_EPOCH, ) self.cache.add_trade_tick(tick) # Act result = self.cache.price(AUDUSD_SIM.id, PriceType.LAST) # Assert self.assertEqual(Price("1.00000"), result) @parameterized.expand([ [PriceType.BID, Price("1.00000")], [PriceType.ASK, Price("1.00001")], [PriceType.MID, Price("1.000005")], ]) def test_price_given_various_quote_price_types_when_quote_tick_returns_expected_price(self, price_type, expected): # Arrange tick = QuoteTick( AUDUSD_SIM.id, Price("1.00000"), Price("1.00001"), Quantity(1), Quantity(1), UNIX_EPOCH, ) self.cache.add_quote_tick(tick) # Act result = self.cache.price(AUDUSD_SIM.id, price_type) # Assert self.assertEqual(expected, result) def test_quote_tick_when_index_out_of_range_returns_none(self): # Arrange tick = QuoteTick( AUDUSD_SIM.id, Price("1.00000"), Price("1.00001"), Quantity(1), Quantity(1), UNIX_EPOCH, ) self.cache.add_quote_tick(tick) # Act result = self.cache.quote_tick(AUDUSD_SIM.id, index=1) # Assert self.assertEqual(1, self.cache.quote_tick_count(AUDUSD_SIM.id)) self.assertIsNone(result) def test_quote_tick_with_two_ticks_returns_expected_tick(self): # Arrange tick1 = QuoteTick( AUDUSD_SIM.id, Price("1.00000"), Price("1.00001"), Quantity(1), Quantity(1), UNIX_EPOCH, ) tick2 = QuoteTick( AUDUSD_SIM.id, Price("1.00001"), Price("1.00003"), Quantity(1), Quantity(1), UNIX_EPOCH, ) self.cache.add_quote_tick(tick1) self.cache.add_quote_tick(tick2) # Act result = self.cache.quote_tick(AUDUSD_SIM.id, index=0) # Assert self.assertEqual(2, self.cache.quote_tick_count(AUDUSD_SIM.id)) self.assertEqual(tick2, result) def test_trade_tick_when_index_out_of_range_returns_none(self): # Arrange tick = TradeTick( AUDUSD_SIM.id, Price("1.00000"), Quantity(10000), OrderSide.BUY, TradeMatchId("123456789"), UNIX_EPOCH, ) self.cache.add_trade_tick(tick) # Act result = self.cache.trade_tick(AUDUSD_SIM.id, index=1) # Assert self.assertEqual(1, self.cache.trade_tick_count(AUDUSD_SIM.id)) self.assertIsNone(result) def test_trade_tick_with_one_tick_returns_expected_tick(self): # Arrange tick1 = TradeTick( AUDUSD_SIM.id, Price("1.00000"), Quantity(10000), OrderSide.BUY, TradeMatchId("123456789"), UNIX_EPOCH, ) tick2 = TradeTick( AUDUSD_SIM.id, Price("1.00001"), Quantity(20000), OrderSide.SELL, TradeMatchId("123456789"), UNIX_EPOCH, ) self.cache.add_trade_tick(tick1) self.cache.add_trade_tick(tick2) # Act result = self.cache.trade_tick(AUDUSD_SIM.id, index=0) # Assert self.assertEqual(2, self.cache.trade_tick_count(AUDUSD_SIM.id)) self.assertEqual(tick2, result) def test_bar_index_out_of_range_returns_expected_bar(self): # Arrange bar_type = TestStubs.bartype_gbpusd_1sec_mid() bar = Bar( Price("1.00001"), Price("1.00004"), Price("1.00002"), Price("1.00003"), Quantity(100000), UNIX_EPOCH, ) self.cache.add_bar(bar_type, bar) # Act result = self.cache.bar(bar_type, index=1) # Assert self.assertEqual(1, self.cache.bar_count(bar_type)) self.assertIsNone(result) def test_bar_with_two_bars_returns_expected_bar(self): # Arrange bar_type = TestStubs.bartype_gbpusd_1sec_mid() bar1 = Bar( Price("1.00001"), Price("1.00004"), Price("1.00002"), Price("1.00003"), Quantity(100000), UNIX_EPOCH, ) bar2 = Bar( Price("1.00002"), Price("1.00003"), Price("1.00004"), Price("1.00005"), Quantity(200000), UNIX_EPOCH, ) self.cache.add_bar(bar_type, bar1) self.cache.add_bar(bar_type, bar2) # Act result = self.cache.bar(bar_type, index=0) # Assert self.assertEqual(2, self.cache.bar_count(bar_type)) self.assertEqual(bar2, result) def test_get_xrate_returns_correct_rate(self): # Arrange self.cache.add_instrument(USDJPY_SIM) tick = QuoteTick( USDJPY_SIM.id, Price("110.80000"), Price("110.80010"), Quantity(1), Quantity(1), UNIX_EPOCH, ) self.cache.add_quote_tick(tick) # Act result = self.cache.get_xrate(SIM, JPY, USD) # Assert self.assertEqual(Decimal("0.009025266685348968705339031887"), result) def test_get_xrate_with_no_conversion_returns_one(self): # Arrange # Act result = self.cache.get_xrate(SIM, AUD, AUD) # Assert self.assertEqual(Decimal("1"), result) def test_get_xrate_with_conversion(self): # Arrange self.cache.add_instrument(AUDUSD_SIM) tick = QuoteTick( AUDUSD_SIM.id, Price("0.80000"), Price("0.80010"), Quantity(1), Quantity(1), UNIX_EPOCH, ) self.cache.add_quote_tick(tick) # Act result = self.cache.get_xrate(SIM, AUD, USD) # Assert self.assertEqual(Decimal("0.80005"), result)
class PortfolioTests(unittest.TestCase): def setUp(self): # Fixture Setup clock = TestClock() logger = TestLogger(clock) self.order_factory = OrderFactory( trader_id=TraderId("TESTER", "000"), strategy_id=StrategyId("S", "001"), clock=TestClock(), ) state = AccountState( account_id=AccountId("BINANCE", "1513111"), balances=[Money("10.00000000", BTC)], balances_free=[Money("0.00000000", BTC)], balances_locked=[Money("0.00000000", BTC)], info={}, event_id=uuid4(), event_timestamp=UNIX_EPOCH, ) self.data_cache = DataCache(logger) self.account = Account(state) self.portfolio = Portfolio(clock, logger) self.portfolio.register_account(self.account) self.portfolio.register_cache(self.data_cache) self.data_cache.add_instrument(AUDUSD_SIM) self.data_cache.add_instrument(GBPUSD_SIM) self.data_cache.add_instrument(BTCUSDT_BINANCE) self.data_cache.add_instrument(BTCUSD_BITMEX) self.data_cache.add_instrument(ETHUSD_BITMEX) def test_account_when_no_account_returns_none(self): # Arrange # Act # Assert self.assertIsNone(self.portfolio.account(SIM)) def test_account_when_account_returns_the_account_facade(self): # Arrange # Act result = self.portfolio.account(BINANCE) # Assert self.assertEqual(self.account, result) def test_net_position_when_no_positions_returns_zero(self): # Arrange # Act # Assert self.assertEqual(Decimal(0), self.portfolio.net_position(AUDUSD_SIM.symbol)) def test_is_net_long_when_no_positions_returns_false(self): # Arrange # Act # Assert self.assertEqual(False, self.portfolio.is_net_long(AUDUSD_SIM.symbol)) def test_is_net_short_when_no_positions_returns_false(self): # Arrange # Act # Assert self.assertEqual(False, self.portfolio.is_net_short(AUDUSD_SIM.symbol)) def test_is_flat_when_no_positions_returns_true(self): # Arrange # Act # Assert self.assertEqual(True, self.portfolio.is_flat(AUDUSD_SIM.symbol)) def test_is_completely_flat_when_no_positions_returns_true(self): # Arrange # Act # Assert self.assertEqual(True, self.portfolio.is_flat(AUDUSD_SIM.symbol)) def test_unrealized_pnl_for_symbol_when_no_instrument_returns_none(self): # Arrange # Act # Assert self.assertIsNone(self.portfolio.unrealized_pnl(USDJPY_SIM.symbol)) def test_unrealized_pnl_for_venue_when_no_account_returns_empty_dict(self): # Arrange # Act # Assert self.assertEqual({}, self.portfolio.unrealized_pnls(SIM)) def test_initial_margins_when_no_account_returns_none(self): # Arrange # Act # Assert self.assertEqual(None, self.portfolio.initial_margins(SIM)) def test_maint_margins_when_no_account_returns_none(self): # Arrange # Act # Assert self.assertEqual(None, self.portfolio.maint_margins(SIM)) def test_open_value_when_no_account_returns_none(self): # Arrange # Act # Assert self.assertEqual(None, self.portfolio.market_values(SIM)) def test_update_tick(self): # Arrange tick = TestStubs.quote_tick_5decimal(GBPUSD_SIM.symbol) # Act self.portfolio.update_tick(tick) # Assert self.assertIsNone(self.portfolio.unrealized_pnl(GBPUSD_SIM.symbol)) def test_update_orders_working(self): # Arrange self.portfolio.register_account(self.account) # Create two working orders order1 = self.order_factory.stop_market( BTCUSDT_BINANCE.symbol, OrderSide.BUY, Quantity("10.5"), Price("25000.00"), ) order2 = self.order_factory.stop_market( BTCUSDT_BINANCE.symbol, OrderSide.BUY, Quantity("10.5"), Price("25000.00"), ) # Push state to FILLED order1.apply(TestStubs.event_order_submitted(order1)) order1.apply(TestStubs.event_order_accepted(order1)) filled1 = TestStubs.event_order_filled( order1, instrument=BTCUSDT_BINANCE, position_id=PositionId("P-1"), strategy_id=StrategyId("S", "1"), fill_price=Price("25000.00"), ) order1.apply(filled1) # Push state to ACCEPTED order2.apply(TestStubs.event_order_submitted(order2)) order2.apply(TestStubs.event_order_accepted(order2)) # Update the last quote last = QuoteTick( BTCUSDT_BINANCE.symbol, Price("25001.00"), Price("25002.00"), Quantity(1), Quantity(1), UNIX_EPOCH, ) # Act self.portfolio.update_tick(last) self.portfolio.initialize_orders({order1, order2}) # Assert self.assertEqual({}, self.portfolio.initial_margins(BINANCE)) def test_update_positions(self): # Arrange self.portfolio.register_account(self.account) # Create a closed position order1 = self.order_factory.market( BTCUSDT_BINANCE.symbol, OrderSide.BUY, Quantity("10.50000000"), ) order2 = self.order_factory.market( BTCUSDT_BINANCE.symbol, OrderSide.SELL, Quantity("10.50000000"), ) filled1 = TestStubs.event_order_filled( order1, instrument=BTCUSDT_BINANCE, position_id=PositionId("P-1"), strategy_id=StrategyId("S", "1"), fill_price=Price("25000.00"), ) filled2 = TestStubs.event_order_filled( order2, instrument=BTCUSDT_BINANCE, position_id=PositionId("P-1"), strategy_id=StrategyId("S", "1"), fill_price=Price("25000.00"), ) position1 = Position(filled1) position1.apply(filled2) order3 = self.order_factory.market( BTCUSDT_BINANCE.symbol, OrderSide.BUY, Quantity("10.00000000"), ) filled3 = TestStubs.event_order_filled( order3, instrument=BTCUSDT_BINANCE, strategy_id=StrategyId("S", "1"), fill_price=Price("25000.00"), ) position2 = Position(filled3) # Update the last quote last = QuoteTick( BTCUSDT_BINANCE.symbol, Price("25001.00"), Price("25002.00"), Quantity(1), Quantity(1), UNIX_EPOCH, ) # Act self.portfolio.initialize_positions({position1, position2}) self.portfolio.update_tick(last) # Assert self.assertTrue(self.portfolio.is_net_long(BTCUSDT_BINANCE.symbol)) def test_opening_one_long_position_updates_portfolio(self): # Arrange order = self.order_factory.market( BTCUSDT_BINANCE.symbol, OrderSide.BUY, Quantity("10.000000"), ) fill = TestStubs.event_order_filled( order=order, instrument=BTCUSDT_BINANCE, position_id=PositionId("P-123456"), strategy_id=StrategyId("S", "001"), fill_price=Price("10500.00"), ) last = QuoteTick( BTCUSDT_BINANCE.symbol, Price("10510.00"), Price("10511.00"), Quantity("1.000000"), Quantity("1.000000"), UNIX_EPOCH, ) self.data_cache.add_quote_tick(last) self.portfolio.update_tick(last) position = Position(fill) # Act self.portfolio.update_position( TestStubs.event_position_opened(position)) # Assert self.assertEqual({USDT: Money("105100.00000000", USDT)}, self.portfolio.market_values(BINANCE)) self.assertEqual({USDT: Money("100.00000000", USDT)}, self.portfolio.unrealized_pnls(BINANCE)) self.assertEqual({}, self.portfolio.maint_margins(BINANCE)) self.assertEqual(Money("105100.00000000", USDT), self.portfolio.market_value(BTCUSDT_BINANCE.symbol)) self.assertEqual(Money("100.00000000", USDT), self.portfolio.unrealized_pnl(BTCUSDT_BINANCE.symbol)) self.assertEqual(Decimal("10.00000000"), self.portfolio.net_position(order.symbol)) self.assertTrue(self.portfolio.is_net_long(order.symbol)) self.assertFalse(self.portfolio.is_net_short(order.symbol)) self.assertFalse(self.portfolio.is_flat(order.symbol)) self.assertFalse(self.portfolio.is_completely_flat()) def test_opening_one_short_position_updates_portfolio(self): # Arrange order = self.order_factory.market( BTCUSDT_BINANCE.symbol, OrderSide.SELL, Quantity("0.515"), ) fill = TestStubs.event_order_filled(order=order, instrument=BTCUSDT_BINANCE, position_id=PositionId("P-123456"), strategy_id=StrategyId("S", "001"), fill_price=Price("15000.00")) last = QuoteTick( BTCUSDT_BINANCE.symbol, Price("15510.15"), Price("15510.25"), Quantity("12.62"), Quantity("3.1"), UNIX_EPOCH, ) self.data_cache.add_quote_tick(last) self.portfolio.update_tick(last) position = Position(fill) # Act self.portfolio.update_position( TestStubs.event_position_opened(position)) # Assert self.assertEqual({USDT: Money("7987.77875000", USDT)}, self.portfolio.market_values(BINANCE)) self.assertEqual({USDT: Money("-262.77875000", USDT)}, self.portfolio.unrealized_pnls(BINANCE)) self.assertEqual({}, self.portfolio.maint_margins(BINANCE)) self.assertEqual(Money("7987.77875000", USDT), self.portfolio.market_value(BTCUSDT_BINANCE.symbol)) self.assertEqual(Money("-262.77875000", USDT), self.portfolio.unrealized_pnl(BTCUSDT_BINANCE.symbol)) self.assertEqual(Decimal("-0.515"), self.portfolio.net_position(order.symbol)) self.assertFalse(self.portfolio.is_net_long(order.symbol)) self.assertTrue(self.portfolio.is_net_short(order.symbol)) self.assertFalse(self.portfolio.is_flat(order.symbol)) self.assertFalse(self.portfolio.is_completely_flat()) def test_opening_positions_with_multi_asset_account(self): # Arrange state = AccountState( account_id=AccountId("BITMEX", "01234"), balances=[Money("10.00000000", BTC), Money("10.00000000", ETH)], balances_free=[ Money("0.00000000", BTC), Money("10.00000000", ETH) ], balances_locked=[ Money("0.00000000", BTC), Money("0.00000000", ETH) ], info={}, event_id=uuid4(), event_timestamp=UNIX_EPOCH, ) account = Account(state) self.portfolio.register_account(account) last_ethusd = QuoteTick( ETHUSD_BITMEX.symbol, Price("376.05"), Price("377.10"), Quantity("16"), Quantity("25"), UNIX_EPOCH, ) last_btcusd = QuoteTick( BTCUSD_BITMEX.symbol, Price("10500.05"), Price("10501.51"), Quantity("2.54"), Quantity("0.91"), UNIX_EPOCH, ) self.data_cache.add_quote_tick(last_ethusd) self.data_cache.add_quote_tick(last_btcusd) self.portfolio.update_tick(last_ethusd) self.portfolio.update_tick(last_btcusd) order = self.order_factory.market( ETHUSD_BITMEX.symbol, OrderSide.BUY, Quantity(10000), ) fill = TestStubs.event_order_filled( order=order, instrument=ETHUSD_BITMEX, position_id=PositionId("P-123456"), strategy_id=StrategyId("S", "001"), fill_price=Price("376.05"), ) position = Position(fill) # Act self.portfolio.update_position( TestStubs.event_position_opened(position)) # Assert self.assertEqual({ETH: Money("2.65922085", ETH)}, self.portfolio.market_values(BITMEX)) self.assertEqual({ETH: Money("0.03855870", ETH)}, self.portfolio.maint_margins(BITMEX)) self.assertEqual(Money("2.65922085", ETH), self.portfolio.market_value(ETHUSD_BITMEX.symbol)) self.assertEqual(Money("0.00000000", ETH), self.portfolio.unrealized_pnl(ETHUSD_BITMEX.symbol)) def test_unrealized_pnl_when_insufficient_data_for_xrate_returns_none( self): # Arrange state = AccountState( account_id=AccountId("BITMEX", "01234"), balances=[Money("10.00000000", BTC), Money("10.00000000", ETH)], balances_free=[ Money("10.00000000", BTC), Money("10.00000000", ETH) ], balances_locked=[ Money("0.00000000", BTC), Money("0.00000000", ETH) ], info={}, event_id=uuid4(), event_timestamp=UNIX_EPOCH, ) account = Account(state) self.portfolio.register_account(account) order = self.order_factory.market( ETHUSD_BITMEX.symbol, OrderSide.BUY, Quantity(100), ) fill = TestStubs.event_order_filled( order=order, instrument=ETHUSD_BITMEX, position_id=PositionId("P-123456"), strategy_id=StrategyId("S", "001"), fill_price=Price("376.05"), ) position = Position(fill) self.portfolio.update_position( TestStubs.event_position_opened(position)) # Act result = self.portfolio.unrealized_pnls(BITMEX) # # Assert self.assertIsNone(result) def test_market_value_when_insufficient_data_for_xrate_returns_none(self): # Arrange state = AccountState( account_id=AccountId("BITMEX", "01234"), balances=[Money("10.00000000", BTC), Money("10.00000000", ETH)], balances_free=[ Money("10.00000000", BTC), Money("10.00000000", ETH) ], balances_locked=[ Money("0.00000000", BTC), Money("0.00000000", ETH) ], info={}, event_id=uuid4(), event_timestamp=UNIX_EPOCH, ) account = Account(state) self.portfolio.register_account(account) order = self.order_factory.market( ETHUSD_BITMEX.symbol, OrderSide.BUY, Quantity(100), ) fill = TestStubs.event_order_filled( order=order, instrument=ETHUSD_BITMEX, position_id=PositionId("P-123456"), strategy_id=StrategyId("S", "001"), fill_price=Price("376.05"), ) last_ethusd = QuoteTick( ETHUSD_BITMEX.symbol, Price("376.05"), Price("377.10"), Quantity("16"), Quantity("25"), UNIX_EPOCH, ) position = Position(fill) self.portfolio.update_position( TestStubs.event_position_opened(position)) self.data_cache.add_quote_tick(last_ethusd) self.portfolio.update_tick(last_ethusd) # Act result = self.portfolio.market_values(BITMEX) # Assert # TODO: Currently no Quanto thus no xrate required self.assertEqual({ETH: Money('0.02659221', ETH)}, result) def test_opening_several_positions_updates_portfolio(self): # Arrange state = AccountState( AccountId("SIM", "01234"), balances=[Money(1_000_000.00, USD)], balances_free=[Money(1_000_000.00, USD)], balances_locked=[Money(0.00, USD)], info={"default_currency": "USD"}, event_id=uuid4(), event_timestamp=UNIX_EPOCH, ) account = Account(state) self.portfolio.register_account(account) last_audusd = QuoteTick( AUDUSD_SIM.symbol, Price("0.80501"), Price("0.80505"), Quantity(1), Quantity(1), UNIX_EPOCH, ) last_gbpusd = QuoteTick( GBPUSD_SIM.symbol, Price("1.30315"), Price("1.30317"), Quantity(1), Quantity(1), UNIX_EPOCH, ) self.data_cache.add_quote_tick(last_audusd) self.data_cache.add_quote_tick(last_gbpusd) self.portfolio.update_tick(last_audusd) self.portfolio.update_tick(last_gbpusd) order1 = self.order_factory.market( AUDUSD_SIM.symbol, OrderSide.BUY, Quantity(100000), ) order2 = self.order_factory.market( GBPUSD_SIM.symbol, OrderSide.BUY, Quantity(100000), ) order1_filled = TestStubs.event_order_filled( order1, instrument=AUDUSD_SIM, position_id=PositionId("P-1"), strategy_id=StrategyId("S", "1"), fill_price=Price("1.00000"), ) order2_filled = TestStubs.event_order_filled( order2, instrument=AUDUSD_SIM, position_id=PositionId("P-2"), strategy_id=StrategyId("S", "1"), fill_price=Price("1.00000"), ) position1 = Position(order1_filled) position2 = Position(order2_filled) position_opened1 = TestStubs.event_position_opened(position1) position_opened2 = TestStubs.event_position_opened(position2) # Act self.portfolio.update_position(position_opened1) self.portfolio.update_position(position_opened2) # Assert self.assertEqual({USD: Money("4216.32", USD)}, self.portfolio.market_values(SIM)) self.assertEqual({USD: Money("10816.00", USD)}, self.portfolio.unrealized_pnls(SIM)) self.assertEqual({USD: Money("130.71", USD)}, self.portfolio.maint_margins(SIM)) self.assertEqual(Money("1610.02", USD), self.portfolio.market_value(AUDUSD_SIM.symbol)) self.assertEqual(Money("2606.30", USD), self.portfolio.market_value(GBPUSD_SIM.symbol)) self.assertEqual(Money("-19499.00", USD), self.portfolio.unrealized_pnl(AUDUSD_SIM.symbol)) self.assertEqual(Money("30315.00", USD), self.portfolio.unrealized_pnl(GBPUSD_SIM.symbol)) self.assertEqual(Decimal(100000), self.portfolio.net_position(AUDUSD_SIM.symbol)) self.assertEqual(Decimal(100000), self.portfolio.net_position(GBPUSD_SIM.symbol)) self.assertTrue(self.portfolio.is_net_long(AUDUSD_SIM.symbol)) self.assertFalse(self.portfolio.is_net_short(AUDUSD_SIM.symbol)) self.assertFalse(self.portfolio.is_flat(AUDUSD_SIM.symbol)) self.assertFalse(self.portfolio.is_completely_flat()) def test_modifying_position_updates_portfolio(self): # Arrange state = AccountState( AccountId("SIM", "01234"), balances=[Money(1_000_000.00, USD)], balances_free=[Money(1_000_000.00, USD)], balances_locked=[Money(0.00, USD)], info={"default_currency": "USD"}, event_id=uuid4(), event_timestamp=UNIX_EPOCH, ) account = Account(state) self.portfolio.register_account(account) last_audusd = QuoteTick( AUDUSD_SIM.symbol, Price("0.80501"), Price("0.80505"), Quantity(1), Quantity(1), UNIX_EPOCH, ) self.data_cache.add_quote_tick(last_audusd) self.portfolio.update_tick(last_audusd) order1 = self.order_factory.market( AUDUSD_SIM.symbol, OrderSide.BUY, Quantity(100000), ) order1_filled = TestStubs.event_order_filled( order1, instrument=AUDUSD_SIM, position_id=PositionId("P-123456"), strategy_id=StrategyId("S", "1"), fill_price=Price("1.00000"), ) position = Position(order1_filled) self.portfolio.update_position( TestStubs.event_position_opened(position)) order2 = self.order_factory.market( AUDUSD_SIM.symbol, OrderSide.SELL, Quantity(50000), ) order2_filled = TestStubs.event_order_filled( order2, instrument=AUDUSD_SIM, position_id=PositionId("P-123456"), strategy_id=StrategyId("S", "1"), fill_price=Price("1.00000"), ) position.apply(order2_filled) # Act self.portfolio.update_position( TestStubs.event_position_changed(position)) # Assert self.assertEqual({USD: Money("805.01", USD)}, self.portfolio.market_values(SIM)) self.assertEqual({USD: Money("-9749.50", USD)}, self.portfolio.unrealized_pnls(SIM)) self.assertEqual({USD: Money("24.96", USD)}, self.portfolio.maint_margins(SIM)) self.assertEqual(Money("805.01", USD), self.portfolio.market_value(AUDUSD_SIM.symbol)) self.assertEqual(Money("-9749.50", USD), self.portfolio.unrealized_pnl(AUDUSD_SIM.symbol)) self.assertEqual(Decimal(50000), self.portfolio.net_position(AUDUSD_SIM.symbol)) self.assertTrue(self.portfolio.is_net_long(AUDUSD_SIM.symbol)) self.assertFalse(self.portfolio.is_net_short(AUDUSD_SIM.symbol)) self.assertFalse(self.portfolio.is_flat(AUDUSD_SIM.symbol)) self.assertFalse(self.portfolio.is_completely_flat()) self.assertEqual({}, self.portfolio.unrealized_pnls(BINANCE)) self.assertEqual({}, self.portfolio.market_values(BINANCE)) def test_closing_position_updates_portfolio(self): # Arrange state = AccountState( AccountId("SIM", "01234"), balances=[Money(1_000_000.00, USD)], balances_free=[Money(1_000_000.00, USD)], balances_locked=[Money(0.00, USD)], info={"default_currency": "USD"}, event_id=uuid4(), event_timestamp=UNIX_EPOCH, ) account = Account(state) self.portfolio.register_account(account) order1 = self.order_factory.market( AUDUSD_SIM.symbol, OrderSide.BUY, Quantity(100000), ) order1_filled = TestStubs.event_order_filled( order1, instrument=AUDUSD_SIM, position_id=PositionId("P-123456"), strategy_id=StrategyId("S", "1"), fill_price=Price("1.00000"), ) position = Position(order1_filled) self.portfolio.update_position( TestStubs.event_position_opened(position)) order2 = self.order_factory.market( AUDUSD_SIM.symbol, OrderSide.SELL, Quantity(100000), ) order2_filled = TestStubs.event_order_filled( order2, instrument=AUDUSD_SIM, position_id=PositionId("P-123456"), strategy_id=StrategyId("S", "1"), fill_price=Price("1.00010"), ) position.apply(order2_filled) # Act self.portfolio.update_position( TestStubs.event_position_closed(position)) # Assert self.assertEqual({}, self.portfolio.market_values(SIM)) self.assertEqual({}, self.portfolio.unrealized_pnls(SIM)) self.assertEqual({}, self.portfolio.maint_margins(SIM)) self.assertEqual(Money("0", USD), self.portfolio.market_value(AUDUSD_SIM.symbol)) self.assertEqual(Money("0", USD), self.portfolio.unrealized_pnl(AUDUSD_SIM.symbol)) self.assertEqual(Decimal(0), self.portfolio.net_position(AUDUSD_SIM.symbol)) self.assertFalse(self.portfolio.is_net_long(AUDUSD_SIM.symbol)) self.assertFalse(self.portfolio.is_net_short(AUDUSD_SIM.symbol)) self.assertTrue(self.portfolio.is_flat(AUDUSD_SIM.symbol)) self.assertTrue(self.portfolio.is_completely_flat()) def test_several_positions_with_different_symbols_updates_portfolio(self): # Arrange state = AccountState( AccountId("SIM", "01234"), balances=[Money(1_000_000.00, USD)], balances_free=[Money(1_000_000.00, USD)], balances_locked=[Money(0.00, USD)], info={"default_currency": "USD"}, event_id=uuid4(), event_timestamp=UNIX_EPOCH, ) account = Account(state) self.portfolio.register_account(account) order1 = self.order_factory.market( AUDUSD_SIM.symbol, OrderSide.BUY, Quantity(100000), ) order2 = self.order_factory.market( AUDUSD_SIM.symbol, OrderSide.BUY, Quantity(100000), ) order3 = self.order_factory.market( GBPUSD_SIM.symbol, OrderSide.BUY, Quantity(100000), ) order4 = self.order_factory.market( GBPUSD_SIM.symbol, OrderSide.SELL, Quantity(100000), ) order1_filled = TestStubs.event_order_filled( order1, instrument=GBPUSD_SIM, position_id=PositionId("P-1"), strategy_id=StrategyId("S", "1"), fill_price=Price("1.00000"), ) order2_filled = TestStubs.event_order_filled( order2, instrument=GBPUSD_SIM, position_id=PositionId("P-2"), strategy_id=StrategyId("S", "1"), fill_price=Price("1.00000"), ) order3_filled = TestStubs.event_order_filled( order3, instrument=GBPUSD_SIM, position_id=PositionId("P-3"), strategy_id=StrategyId("S", "1"), fill_price=Price("1.00000"), ) order4_filled = TestStubs.event_order_filled( order4, instrument=GBPUSD_SIM, position_id=PositionId("P-3"), strategy_id=StrategyId("S", "1"), fill_price=Price("1.00100"), ) position1 = Position(order1_filled) position2 = Position(order2_filled) position3 = Position(order3_filled) last_audusd = QuoteTick( AUDUSD_SIM.symbol, Price("0.80501"), Price("0.80505"), Quantity(1), Quantity(1), UNIX_EPOCH, ) last_gbpusd = QuoteTick( GBPUSD_SIM.symbol, Price("1.30315"), Price("1.30317"), Quantity(1), Quantity(1), UNIX_EPOCH, ) self.data_cache.add_quote_tick(last_audusd) self.data_cache.add_quote_tick(last_gbpusd) self.portfolio.update_tick(last_audusd) self.portfolio.update_tick(last_gbpusd) # Act self.portfolio.update_position( TestStubs.event_position_opened(position1)) self.portfolio.update_position( TestStubs.event_position_opened(position2)) self.portfolio.update_position( TestStubs.event_position_opened(position3)) position3.apply(order4_filled) self.portfolio.update_position( TestStubs.event_position_closed(position3)) # Assert self.assertEqual({USD: Money("-38998.00", USD)}, self.portfolio.unrealized_pnls(SIM)) self.assertEqual({USD: Money("3220.04", USD)}, self.portfolio.market_values(SIM)) self.assertEqual({USD: Money("99.82", USD)}, self.portfolio.maint_margins(SIM)) self.assertEqual(Money("3220.04", USD), self.portfolio.market_value(AUDUSD_SIM.symbol)) self.assertEqual(Money("-38998.00", USD), self.portfolio.unrealized_pnl(AUDUSD_SIM.symbol)) self.assertEqual(Money("0", USD), self.portfolio.unrealized_pnl(GBPUSD_SIM.symbol)) self.assertEqual(Decimal(200000), self.portfolio.net_position(AUDUSD_SIM.symbol)) self.assertEqual(Decimal(0), self.portfolio.net_position(GBPUSD_SIM.symbol)) self.assertTrue(self.portfolio.is_net_long(AUDUSD_SIM.symbol)) self.assertTrue(self.portfolio.is_flat(GBPUSD_SIM.symbol)) self.assertFalse(self.portfolio.is_completely_flat())