def test_future_account_order_margin_multiple_instruments( exchange: MagicMock, future_instrument: FutureInstrument, future_instrument2: FutureInstrument) -> None: open_orders: List[FutureLimitOrder] = [] exchange.get_open_orders = MagicMock(return_value=open_orders) exchange.last_price = MagicMock(return_value=10) account = FutureAccount(exchange=exchange, position_cls=FuturePosition, wallet_balance=10000) untraded_order1 = FutureLimitOrder(order_id=random_string(6), account=account, instrument=future_instrument, quantity=100, price=10) untraded_order2 = FutureLimitOrder(order_id=random_string(6), account=account, instrument=future_instrument2, quantity=-90, price=11) untraded_order3 = FutureLimitOrder(order_id=random_string(6), account=account, instrument=future_instrument, quantity=-100, price=9) open_orders.extend([untraded_order3, untraded_order1, untraded_order2]) assert account.order_margin == 66.385
def test_future_account_position_margin( exchange: MagicMock, future_instrument: FutureInstrument, future_instrument2: FutureInstrument) -> None: # test the position margin of the account when the account have two different positions open_orders: List[FutureLimitOrder] = [] exchange.get_open_orders = MagicMock(return_value=open_orders) exchange.last_price = MagicMock(return_value=10) account = FutureAccount(exchange=exchange, position_cls=FuturePosition, wallet_balance=10000) order1 = FutureLimitOrder(order_id=random_string(6), account=account, instrument=future_instrument, quantity=100, price=11) order2 = FutureLimitOrder(order_id=random_string(6), account=account, instrument=future_instrument2, quantity=-200, price=18) trade1 = Trade(order=order1, exec_price=11, exec_quantity=100, trade_id=random_string(6)) trade2 = Trade(order=order2, exec_price=18, exec_quantity=-200, trade_id=random_string(6)) account.deal(trade1) account.deal(trade2) assert account.position_margin == pytest.approx(74.0) position1 = account.positions[future_instrument] position1.set_leverage(4) assert account.position_margin == pytest.approx(271.5)
def test_future_accoutn_order_margin_leverage( exchange: MagicMock, future_instrument: FutureInstrument) -> None: open_orders: List[FutureLimitOrder] = [] exchange.get_open_orders = MagicMock(return_value=open_orders) exchange.last_price = MagicMock(return_value=10) account = FutureAccount(exchange=exchange, position_cls=FuturePosition, wallet_balance=10000) order1 = FutureLimitOrder(order_id=random_string(6), account=account, instrument=future_instrument, quantity=100, price=11) open_orders.append(order1) assert account.order_margin == 60.5 trade1 = Trade(order=order1, exec_price=11, exec_quantity=100, trade_id=random_string(6)) account.deal(trade1) open_orders.remove(order1) position = account.positions[future_instrument] position.set_leverage(5) untraded_order1 = FutureLimitOrder(order_id=random_string(6), account=account, instrument=future_instrument, quantity=100, price=5) untraded_order2 = FutureLimitOrder(order_id=random_string(6), account=account, instrument=future_instrument, quantity=-200, price=20) open_orders.extend([untraded_order1, untraded_order2]) assert account.order_margin == pytest.approx(410)
def test_future_account_order_margin_two_direction( exchange: MagicMock, future_instrument: FutureInstrument) -> None: open_orders: List[FutureLimitOrder] = [] exchange.get_open_orders = MagicMock(return_value=open_orders) exchange.last_price = MagicMock(return_value=10) account = FutureAccount(exchange=exchange, position_cls=FuturePosition, wallet_balance=10000) untraded_order1 = FutureLimitOrder(order_id=random_string(6), account=account, instrument=future_instrument, quantity=100, price=5) untraded_order2 = FutureLimitOrder(order_id=random_string(6), account=account, instrument=future_instrument, quantity=-100, price=20) open_orders.extend([untraded_order1, untraded_order2]) assert account.order_margin == 110.0 untraded_order3 = FutureLimitOrder(order_id=random_string(6), account=account, instrument=future_instrument, quantity=100, price=5) open_orders.append(untraded_order3) assert account.order_margin == 110.0 untraded_order4 = FutureLimitOrder(order_id=random_string(6), account=account, instrument=future_instrument, quantity=100, price=16) open_orders.append(untraded_order4) assert account.order_margin == 143 open_orders.clear()
async def place_limit_order(self, account: FutureAccount, instrument: FutureInstrument, price: float, quantity: float, text: str = '') -> str: if isinstance(instrument, FutureInstrument): order = FutureLimitOrder(account=account, instrument=instrument, price=price, quantity=quantity, order_id=gen_unique_id(), submit_datetime=self.context.now, text=text) else: raise NotImplementedError() self._trade_counter.submit_order(order) return order.order_id
def test_future_account_deal(exchange: MagicMock, future_instrument: FutureInstrument) -> None: open_orders: List[FutureLimitOrder] = [] exchange.get_open_orders = MagicMock(return_value=open_orders) exchange.last_price = MagicMock(return_value=10) account = FutureAccount(exchange=exchange, position_cls=FuturePosition, wallet_balance=10000) assert account.position_margin == 0 assert account.order_margin == 0 assert account.unrealised_pnl == 0 assert account.wallet_balance == 10000 assert account.margin_balance == 10000 assert account.available_balance == 10000 assert account.total_capital == 10000 # open a position order1 = FutureLimitOrder(order_id=random_string(6), account=account, instrument=future_instrument, quantity=100, price=11) open_orders.append(order1) assert account.order_margin == 60.5 trade1 = Trade(order=order1, exec_price=11, exec_quantity=100, trade_id=random_string(6)) account.deal(trade1) open_orders.remove(order1) assert account.wallet_balance == 9997.25 assert account.position_margin == pytest.approx(52.50, 0.0001) assert account.order_margin == 0 assert account.unrealised_pnl == -102.5 assert account.margin_balance == 9894.75 assert account.available_balance == 9842.25 assert account.total_capital == 9894.75 # more on a position order2 = FutureLimitOrder(order_id=random_string(6), account=account, instrument=future_instrument, quantity=200, price=10.5) open_orders.append(order2) assert account.order_margin == 115.5 trade2 = Trade(order=order2, exec_price=10.5, exec_quantity=200, trade_id=random_string(6)) account.deal(trade2) open_orders.remove(order2) assert account.wallet_balance == 9992.0 assert account.position_margin == pytest.approx(157.50, 0.0001) assert account.order_margin == 0 assert account.unrealised_pnl == -207.5 assert account.margin_balance == 9784.5 assert account.available_balance == 9627.0 assert account.total_capital == 9784.5 # close part order3 = FutureLimitOrder(order_id=random_string(6), account=account, instrument=future_instrument, quantity=-100, price=10) open_orders.append(order3) assert account.order_margin == 0 trade3 = Trade(order=order3, exec_price=10, exec_quantity=-100, trade_id=random_string(6)) account.deal(trade3) open_orders.remove(order3) assert account.wallet_balance == pytest.approx(9922.8333, 0.0001) assert account.position_margin == pytest.approx(105, 0.0001) assert account.order_margin == 0 assert account.unrealised_pnl == pytest.approx(-138.3333, 0.0001) assert account.margin_balance == pytest.approx(9784.5000, 0.0001) assert account.available_balance == pytest.approx(9679.5000, 0.0001) assert account.total_capital == pytest.approx(9784.5000, 0.0001) # close and open order4 = FutureLimitOrder(order_id=random_string(6), account=account, instrument=future_instrument, quantity=-300, price=11) open_orders.append(order4) assert account.order_margin == 60.5 trade4 = Trade(order=order4, exec_price=11, exec_quantity=-300, trade_id=random_string(6)) account.deal(trade4) open_orders.remove(order4) assert account.wallet_balance == pytest.approx(9981.2513, 0.0001) assert account.position_margin == pytest.approx(52.5, 0.0001) assert account.order_margin == 0 assert account.unrealised_pnl == pytest.approx(97.5, 0.0001) assert account.margin_balance == pytest.approx(10078.7513, 0.0001) assert account.available_balance == pytest.approx(10026.2513, 0.0001) assert account.total_capital == pytest.approx(10078.7513, 0.0001) # get more order5 = FutureLimitOrder(order_id=random_string(6), account=account, instrument=future_instrument, quantity=-100, price=10.5) open_orders.append(order5) assert account.order_margin == 57.75 trade5 = Trade(order=order5, exec_price=10.5, exec_quantity=-100, trade_id=random_string(6)) account.deal(trade5) open_orders.remove(order5) assert account.wallet_balance == pytest.approx(9978.6263, 0.0001) assert account.position_margin == pytest.approx(105, 0.0001) assert account.order_margin == 0 assert account.unrealised_pnl == pytest.approx(145.0, 0.0001) assert account.margin_balance == pytest.approx(10123.6263, 0.0001) assert account.available_balance == pytest.approx(10018.6263, 0.0001) assert account.total_capital == pytest.approx(10123.6263, 0.0001) # close and open order6 = FutureLimitOrder(order_id=random_string(6), account=account, instrument=future_instrument, quantity=300, price=10.5) open_orders.append(order6) assert account.order_margin == 57.75 trade6 = Trade(order=order6, exec_price=10.5, exec_quantity=300, trade_id=random_string(6)) account.deal(trade6) open_orders.remove(order6) assert account.wallet_balance == pytest.approx(10020.7513, 0.0001) assert account.position_margin == pytest.approx(52.5, 0.0001) assert account.order_margin == 0 assert account.unrealised_pnl == pytest.approx(-52.5, 0.0001) assert account.margin_balance == pytest.approx(9968.2513, 0.0001) assert account.available_balance == pytest.approx(9915.7513, 0.0001) assert account.total_capital == pytest.approx(9968.2513, 0.0001) # close order7 = FutureLimitOrder(order_id=random_string(6), account=account, instrument=future_instrument, quantity=-100, price=9) open_orders.append(order7) assert account.order_margin == 0 trade7 = Trade(order=order7, exec_price=9, exec_quantity=-100, trade_id=random_string(6)) account.deal(trade7) open_orders.remove(order7) assert account.wallet_balance == pytest.approx(9868.5013, 0.0001) assert account.position_margin == 0 assert account.order_margin == 0 assert account.unrealised_pnl == 0 assert account.margin_balance == pytest.approx(9868.5013, 0.0001) assert account.available_balance == pytest.approx(9868.5013, 0.0001) assert account.total_capital == pytest.approx(9868.5013, 0.0001) # close order8 = FutureLimitOrder(order_id=random_string(6), account=account, instrument=future_instrument, quantity=-150, price=11) open_orders.append(order8) assert account.order_margin == 90.75 trade8 = Trade(order=order8, exec_price=11, exec_quantity=-150, trade_id=random_string(6)) account.deal(trade8) open_orders.remove(order8) assert account.wallet_balance == pytest.approx(9864.3763, 0.0001) assert account.position_margin == pytest.approx(78.7500, 0.0001) assert account.order_margin == 0 assert account.unrealised_pnl == pytest.approx(146.25, 0.0001) assert account.margin_balance == pytest.approx(10010.6263, 0.0001) assert account.available_balance == pytest.approx(9931.8763, 0.0001) assert account.total_capital == pytest.approx(10010.6263, 0.0001) order9 = FutureLimitOrder(order_id=random_string(6), account=account, instrument=future_instrument, quantity=150, price=11) open_orders.append(order9) assert account.order_margin == 0 trade9 = Trade(order=order9, exec_price=11, exec_quantity=150, trade_id=random_string(6)) account.deal(trade9) open_orders.remove(order9) assert account.wallet_balance == pytest.approx(9860.2513, 0.0001) assert account.position_margin == 0 assert account.order_margin == 0 assert account.unrealised_pnl == 0 assert account.margin_balance == pytest.approx(9860.2513, 0.0001) assert account.available_balance == pytest.approx(9860.2513, 0.0001) assert account.total_capital == pytest.approx(9860.2513, 0.0001)
def test_future_account_order_margin_short_position( exchange: MagicMock, future_instrument: FutureInstrument) -> None: open_orders: List[FutureLimitOrder] = [] exchange.get_open_orders = MagicMock(return_value=open_orders) exchange.last_price = MagicMock(return_value=10) account = FutureAccount(exchange=exchange, position_cls=FuturePosition, wallet_balance=10000) order1 = FutureLimitOrder(order_id=random_string(6), account=account, instrument=future_instrument, quantity=-100, price=11) open_orders.append(order1) assert account.order_margin == 60.5 trade1 = Trade(order=order1, exec_price=11, exec_quantity=-100, trade_id=random_string(6)) account.deal(trade1) open_orders.remove(order1) untraded_order1 = FutureLimitOrder(order_id=random_string(6), account=account, instrument=future_instrument, quantity=100, price=9) untraded_order2 = FutureLimitOrder(order_id=random_string(6), account=account, instrument=future_instrument, quantity=-90, price=11) open_orders.extend([untraded_order1, untraded_order2]) assert account.order_margin == 54.45 untraded_order3 = FutureLimitOrder(order_id=random_string(6), account=account, instrument=future_instrument, quantity=100, price=12) open_orders.append(untraded_order3) assert account.order_margin == 66.0 untraded_order4 = FutureLimitOrder(order_id=random_string(6), account=account, instrument=future_instrument, quantity=-100, price=10) open_orders.append(untraded_order4) assert account.order_margin == 109.45 untraded_order5 = FutureLimitOrder(order_id=random_string(6), account=account, instrument=future_instrument, quantity=50, price=19) open_orders.append(untraded_order5) assert account.order_margin == 118.25 trade2 = Trade(untraded_order2, exec_price=11, exec_quantity=-30, trade_id=random_string(6)) untraded_order2.deal(trade2) assert account.order_margin == 98.45 untraded_order6 = FutureLimitOrder(order_id=random_string(6), account=account, instrument=future_instrument, quantity=100, price=20) open_orders.append(untraded_order6) assert account.order_margin == 208.45
def test_order_pickle(future_instrument: FutureInstrument, future_account: FutureAccount) -> None: order_id1 = random_string(6) order1 = FutureMarketOrder(order_id=order_id1, account=future_account, instrument=future_instrument, quantity=100, submit_datetime=utc_datetime(2018, 1, 1), text='22') p_order = pickle.dumps(order1) unp_order = pickle.loads(p_order) assert unp_order.quantity == 100 assert unp_order.traded_quantity == 0 assert unp_order.account.exchange.name == 'exchange_test' assert unp_order.order_id == order_id1 assert unp_order.instrument.symbol == future_instrument.symbol assert unp_order.side == SIDE.BUY assert unp_order.remain_quantity == 100 assert isinstance(unp_order, FutureMarketOrder) assert unp_order.direction == DIRECTION.LONG assert unp_order.submit_datetime == utc_datetime(2018, 1, 1) assert unp_order.text == '22' order_id2 = random_string(6) order2 = FutureLimitOrder(order_id=order_id2, account=future_account, instrument=future_instrument, quantity=100, price=11, submit_datetime=utc_datetime(2018, 1, 1), text='random') p_order2 = pickle.dumps(order2) unp_order2 = pickle.loads(p_order2) assert unp_order2.quantity == 100 assert unp_order2.traded_quantity == 0 assert unp_order2.account.exchange.name == 'exchange_test' assert unp_order2.order_id == order_id2 assert unp_order2.instrument.symbol == future_instrument.symbol assert unp_order2.side == SIDE.BUY assert unp_order2.remain_quantity == 100 assert isinstance(unp_order2, FutureLimitOrder) assert unp_order2.direction == DIRECTION.LONG assert unp_order2.submit_datetime == utc_datetime(2018, 1, 1) assert unp_order2.text == 'random' order_id3 = random_string(6) order3 = StopLimitOrder(order_id=order_id3, account=future_account, instrument=future_instrument, quantity=100, stop_price=11, submit_datetime=utc_datetime(2018, 1, 1), text='random2') p_order3 = pickle.dumps(order3) unp_order3 = pickle.loads(p_order3) assert unp_order3.quantity == 100 assert unp_order3.traded_quantity == 0 assert unp_order3.account.exchange.name == 'exchange_test' assert unp_order3.order_id == order_id3 assert unp_order3.instrument.symbol == future_instrument.symbol assert unp_order3.side == SIDE.BUY assert unp_order3.remain_quantity == 100 assert isinstance(unp_order3, StopLimitOrder) assert unp_order3.stop_price == 11 assert unp_order3.submit_datetime == utc_datetime(2018, 1, 1) assert unp_order3.text == 'random2' order_id4 = random_string(6) order4 = StopMarketOrder(order_id=order_id4, account=future_account, instrument=future_instrument, quantity=100, stop_price=11, submit_datetime=utc_datetime(2018, 1, 1), text='random4') p_order4 = pickle.dumps(order4) unp_order4 = pickle.loads(p_order4) assert unp_order4.quantity == 100 assert unp_order4.traded_quantity == 0 assert unp_order4.account.exchange.name == 'exchange_test' assert unp_order4.order_id == order_id4 assert unp_order4.instrument.symbol == future_instrument.symbol assert unp_order4.side == SIDE.BUY assert unp_order4.remain_quantity == 100 assert isinstance(unp_order4, StopMarketOrder) assert unp_order4.stop_price == 11 assert unp_order4.submit_datetime == utc_datetime(2018, 1, 1) assert unp_order4.text == 'random4'
def test_future_limit_order(future_instrument: FutureInstrument, future_account: FutureAccount) -> None: order1 = FutureLimitOrder(order_id=random_string(6), account=future_account, instrument=future_instrument, quantity=100, price=11, submit_datetime=utc_datetime(2018, 1, 1), text='random') assert order1.price == 11 assert order1.quantity == 100 assert order1.traded_quantity == 0 assert order1.side == SIDE.BUY assert order1.order_value == 1100 assert order1.order_status == ORDER_STATUS.NOT_TRADED assert order1.remain_quantity == 100 assert order1.remain_value == 1100 assert order1.direction == DIRECTION.LONG assert order1.text == 'random' trade1 = Trade(order=order1, exec_price=11, exec_quantity=50, trade_id=random_string(6), trade_datetime=utc_datetime(2018, 1, 1, 0, 1)) order1.deal(trade1) assert order1.traded_quantity == 50 assert order1.order_status == ORDER_STATUS.PARTLY_TRADED assert order1.remain_quantity == 50 assert order1.order_value == 1100 assert order1.remain_value == 550 with pytest.raises(AssertionError): order1.deal(trade1) trade2 = Trade(order=order1, exec_price=11, exec_quantity=50, trade_id=random_string(6), trade_datetime=utc_datetime(2018, 1, 1, 0, 1)) order1.deal(trade2) assert order1.traded_quantity == 100 assert order1.remain_quantity == 0 assert order1.order_status == ORDER_STATUS.FULL_TRADED assert order1.remain_value == 0 assert trade1 in order1.trades assert trade2 in order1.trades order2 = FutureLimitOrder(order_id=random_string(6), account=future_account, instrument=future_instrument, quantity=-100, price=13, submit_datetime=utc_datetime(2018, 1, 1), text='random2') assert order2.price == 13 assert order2.quantity == -100 assert order2.traded_quantity == 0 assert order2.side == SIDE.SELL assert order2.order_value == 1300 assert order2.order_status == ORDER_STATUS.NOT_TRADED assert order2.remain_quantity == -100 assert order2.remain_value == 1300 assert order2.direction == DIRECTION.SHORT assert order2.text == 'random2' trade3 = Trade(order=order2, exec_price=13, exec_quantity=-50, trade_id=random_string(6), trade_datetime=utc_datetime(2018, 1, 1, 0, 1)) order2.deal(trade3) assert order2.traded_quantity == -50 assert order2.order_status == ORDER_STATUS.PARTLY_TRADED assert order2.remain_quantity == -50 assert order2.order_value == 1300 assert order2.remain_value == 650 with pytest.raises(AssertionError): order2.deal(trade3) trade4 = Trade(order=order2, exec_price=13, exec_quantity=-50, trade_id=random_string(6), trade_datetime=utc_datetime(2018, 1, 1, 0, 1)) order2.deal(trade4) assert order2.traded_quantity == -100 assert order2.order_status == ORDER_STATUS.FULL_TRADED assert order2.remain_quantity == 0 assert order2.order_value == 1300 assert order2.remain_value == 0