Esempio n. 1
0
    def create_order(self, order: 'Order') -> 'Order':

        wallet_instrument = self.side.instrument(self.exchange_pair.pair)

        exchange = order.exchange_pair.exchange
        wallet = order.portfolio.get_wallet(exchange.id,
                                            instrument=wallet_instrument)
        quantity = wallet.locked.get(order.path_id, None)

        if not quantity or quantity.size == 0:
            return None

        return Order(step=exchange.clock.step,
                     side=self.side,
                     trade_type=self.type,
                     exchange_pair=self.exchange_pair,
                     quantity=quantity,
                     portfolio=order.portfolio,
                     price=self.exchange_pair.price,
                     criteria=self.criteria,
                     end=order.end,
                     path_id=order.path_id)
Esempio n. 2
0
def test_init(mock_portfolio_class):

    portfolio = mock_portfolio_class.return_value

    order = Order(step=0,
                  side=TradeSide.BUY,
                  trade_type=TradeType.MARKET,
                  pair=USD / BTC,
                  quantity=5000 * USD,
                  price=7000,
                  portfolio=portfolio)

    assert order
    assert order.id
    assert order.path_id
    assert order.step == 0
    assert order.quantity.instrument == USD
    assert order.filled_size == 0
    assert order.remaining_size == order.quantity
    assert isinstance(order.pair, TradingPair)
    assert order.pair.base == USD
    assert order.pair.quote == BTC
Esempio n. 3
0
def test_properties(mock_portfolio_class):

    portfolio = mock_portfolio_class.return_value

    order = Order(side=TradeSide.BUY,
                  trade_type=TradeType.LIMIT,
                  pair=USD / BTC,
                  quantity=5000.00 * USD,
                  portfolio=portfolio,
                  price=7000.00)

    assert order
    assert order.base_instrument == USD
    assert order.quote_instrument == BTC
    assert order.size == 5000.00 * USD
    assert order.price == 7000.00
    assert order.trades == []
    assert order.is_buy
    assert not order.is_sell
    assert not order.is_market_order
    assert order.is_limit_order
    assert order.created_at == 0
Esempio n. 4
0
def hidden_limit_order(step: int,
                       side: 'TradeSide',
                       pair: 'TradingPair',
                       price: float,
                       size: float,
                       portfolio: 'Portfolio',
                       ttl_in_seconds: int = None,
                       ttl_in_steps: int = None):
    instrument = side.instrument(pair)
    order = Order(step=step,
                  side=side,
                  trade_type=TradeType.MARKET,
                  pair=pair,
                  price=price,
                  quantity=(size * instrument),
                  ttl_in_seconds=ttl_in_seconds,
                  ttl_in_steps=ttl_in_steps,
                  portfolio=portfolio,
                  criteria=Limit(limit_price=price)
                  )

    return order
Esempio n. 5
0
def test_detach(mock_portfolio_class, mock_order_listener_class):
    portfolio = mock_portfolio_class.return_value
    order = Order(side=TradeSide.BUY,
                  trade_type=TradeType.MARKET,
                  pair=USD / BTC,
                  quantity=5000.00 * USD,
                  portfolio=portfolio,
                  price=7000.00)

    listener = mock_order_listener_class.return_value
    order.attach(listener)
    assert len(order._listeners) == 1
    assert listener in order._listeners

    order.detach(listener)
    assert len(order._listeners) == 0
    assert listener not in order._listeners
Esempio n. 6
0
def test_fill(mock_order_listener_class,
              mock_trade_class,
              mock_exchange_class):

    exchange = mock_exchange_class.return_value
    exchange.id = "fake_exchange_id"

    wallets = [Wallet(exchange, 10000 * USD), Wallet(exchange, 0 * BTC)]
    portfolio = Portfolio(USD, wallets)

    order = Order(step=0,
                  exchange_name="coinbase",
                  side=TradeSide.BUY,
                  trade_type=TradeType.MARKET,
                  pair=USD / BTC,
                  quantity=5200.00 * USD,
                  portfolio=portfolio,
                  price=7000.00)

    listener = mock_order_listener_class.return_value
    listener.on_fill = mock.Mock(return_value=None)
    order.attach(listener)

    order.execute(exchange)

    trade = mock_trade_class.return_value
    trade.size = 3997.00
    trade.commission = 3.00 * USD

    assert order.status == OrderStatus.OPEN
    order.fill(exchange, trade)
    assert order.status == OrderStatus.PARTIALLY_FILLED

    assert order.remaining_size == 1200.00

    listener.on_fill.assert_called_once_with(order, exchange, trade)
Esempio n. 7
0
def test_on_fill(mock_trade_class, mock_exchange_class):

    exchange = mock_exchange_class.return_value
    exchange.id = "fake_exchange_id"

    broker = Broker(exchange)

    wallets = [Wallet(exchange, 10000 * USD), Wallet(exchange, 0 * BTC)]
    portfolio = Portfolio(USD, wallets)

    order = Order(step=0,
                  side=TradeSide.BUY,
                  trade_type=TradeType.MARKET,
                  pair=USD / BTC,
                  quantity=5200.00 * USD,
                  portfolio=portfolio,
                  price=7000.00)

    order.attach(broker)

    order.execute(exchange)

    broker._executed[order.id] = order

    trade = mock_trade_class.return_value
    trade.size = 5197.00
    trade.commission = 3.00 * USD
    trade.order_id = order.id

    assert order.status == OrderStatus.OPEN
    order.fill(exchange, trade)
    assert order.status == OrderStatus.FILLED

    assert order.remaining_size == 0

    assert trade in broker.trades[order.id]
Esempio n. 8
0
def test_update_on_single_exchange_with_multiple_orders(mock_exchange_class):

    exchange = mock_exchange_class.return_value
    exchange.id = "fake_exchange_id"

    wallets = [Wallet(exchange, 10000 * USD), Wallet(exchange, 0 * BTC)]
    portfolio = Portfolio(USD, wallets)

    broker = Broker(exchange)

    # Submit order 1
    o1 = Order(step=0,
               side=TradeSide.BUY,
               trade_type=TradeType.MARKET,
               pair=USD / BTC,
               quantity=5200.00 * USD,
               portfolio=portfolio,
               price=7000.00)
    o1.is_executable_on = mock.MagicMock(side_effect=[False, True])
    broker.submit(o1)

    # Submit order 2
    o2 = Order(step=0,
               side=TradeSide.BUY,
               trade_type=TradeType.MARKET,
               pair=USD / BTC,
               quantity=230.00 * USD,
               portfolio=portfolio,
               price=7300.00)
    o2.is_executable_on = mock.MagicMock(side_effect=[True, False])
    broker.submit(o2)

    # No updates have been made yet
    assert o1 in broker.unexecuted and o1 not in broker.executed
    assert o2 in broker.unexecuted and o2 not in broker.executed

    # First update
    broker.update()
    assert o1 in broker.unexecuted and o1.id not in broker.executed
    assert o2 not in broker.unexecuted and o2.id in broker.executed

    # Second update
    broker.update()
    assert o1 not in broker.unexecuted and o1.id in broker.executed
    assert o2 not in broker.unexecuted and o2.id in broker.executed
Esempio n. 9
0
def test_order_runs_through_broker():
    wallets = [Wallet(exchange, 10000 * USD), Wallet(exchange, 0 * BTC)]
    portfolio = Portfolio(base_instrument=USD, wallets=wallets)
    exchange.reset()
    portfolio.reset()
    broker.reset()

    base_wallet = portfolio.get_wallet(exchange.id, USD)

    quantity = (1 / 10) * base_wallet.balance
    order = Order(side=TradeSide.BUY,
                  trade_type=TradeType.MARKET,
                  pair=USD / BTC,
                  quantity=quantity,
                  portfolio=portfolio)

    base_wallet -= quantity.size * order.pair.base
    base_wallet += order.quantity

    broker.submit(order)

    broker.update()
    portfolio.update()
Esempio n. 10
0
def risk_managed_order(step: int, side: 'TradeSide', trade_type: 'TradeType',
                       pair: 'TradingPair', price: float, size: float,
                       down_percent: float, up_percent: float,
                       portfolio: 'Portfolio'):

    order = Order(step=step,
                  side=side,
                  trade_type=trade_type,
                  pair=pair,
                  price=price,
                  quantity=(size * pair.base),
                  portfolio=portfolio)

    risk_criteria = Stop("down", down_percent) ^ Stop("up", up_percent)

    risk_management = OrderSpec(
        side=TradeSide.SELL if side == TradeSide.BUY else TradeSide.BUY,
        trade_type=TradeType.MARKET,
        pair=pair,
        criteria=risk_criteria)

    order += risk_management

    return order
Esempio n. 11
0
    def get_order(self, action: int, exchange: 'Exchange',
                  portfolio: 'Portfolio') -> Order:
        if action == 0:
            return None

        (pair, stop_loss, take_profit, size) = self._actions[action]

        base_instrument = pair.base if self._trade_side == TradeSide.BUY else pair.quote
        base_wallet = portfolio.get_wallet(exchange.id,
                                           instrument=base_instrument)

        price = exchange.quote_price(pair)
        size = min(base_wallet.balance.size, (base_wallet.balance.size * size))

        if size < 10**-base_instrument.precision:
            return None

        buy_quantity = size * base_instrument

        order = Order(side=self._trade_side,
                      trade_type=self._trade_type,
                      pair=pair,
                      price=price,
                      quantity=buy_quantity,
                      portfolio=portfolio)

        risk_criteria = StopLoss(direction='either',
                                 up_percent=take_profit,
                                 down_percent=stop_loss)

        risk_management = Recipe(side=TradeSide.SELL if self._trade_side
                                 == TradeSide.BUY else TradeSide.BUY,
                                 trade_type=TradeType.MARKET,
                                 pair=pair,
                                 criteria=risk_criteria)

        order.add_recipe(risk_management)

        if self._order_listener is not None:
            order.attach(self._order_listener)

        return order
def test_on_execute(mock_exchange_class,
                    execute_listener):
    exchange = mock_exchange_class.return_value
    exchange.id = "fake_id"

    wallets = [Wallet(exchange, 10000 * USD), Wallet(exchange, 0 * BTC)]
    portfolio = Portfolio(USD, wallets)

    order = Order(side=TradeSide.BUY,
                  trade_type=TradeType.MARKET,
                  pair=USD / BTC,
                  quantity=5200.00 * USD,
                  portfolio=portfolio,
                  price=7000.00)

    order.attach(execute_listener)

    assert not execute_listener.listened
    order.execute(exchange)
    assert execute_listener.listened
Esempio n. 13
0
def test_on_cancel(mock_exchange_class, cancel_listener):

    exchange = mock_exchange_class.return_value
    exchange.id = "fake_exchange_id"
    exchange.name = "coinbase"

    wallets = [Wallet(exchange, 10000 * USD), Wallet(exchange, 0 * BTC)]
    portfolio = Portfolio(USD, wallets)

    order = Order(step=0,
                  exchange_name="coinbase",
                  side=TradeSide.BUY,
                  trade_type=TradeType.MARKET,
                  pair=USD / BTC,
                  quantity=5200.00 * USD,
                  portfolio=portfolio,
                  price=7000.00)

    order.attach(cancel_listener)

    assert not cancel_listener.listened
    order.cancel()
    assert cancel_listener.listened
Esempio n. 14
0
def test_execute(mock_order_listener_class, mock_exchange_class):

    exchange = mock_exchange_class.return_value
    exchange.options = ExchangeOptions()
    exchange.id = "fake_exchange_id"
    exchange.name = "coinbase"
    exchange.clock = mock.Mock()
    exchange.clock.step = 0

    wallets = [Wallet(exchange, 10000 * USD), Wallet(exchange, 0 * BTC)]
    portfolio = Portfolio(USD, wallets)

    order = Order(step=0,
                  exchange_pair=ExchangePair(exchange, USD / BTC),
                  side=TradeSide.BUY,
                  trade_type=TradeType.MARKET,
                  quantity=5200.00 * USD,
                  portfolio=portfolio,
                  price=Decimal(7000.00))

    listener = mock_order_listener_class.return_value
    listener.on_execute = mock.Mock(return_value=None)
    order.attach(listener)

    assert order.status == OrderStatus.PENDING
    order.execute()
    assert order.status == OrderStatus.OPEN

    wallet_usd = portfolio.get_wallet(exchange.id, USD)
    wallet_btc = portfolio.get_wallet(exchange.id, BTC)

    assert wallet_usd.balance == 4800 * USD
    assert wallet_usd.locked_balance == 5200 * USD
    assert order.path_id in wallet_usd.locked.keys()
    assert wallet_btc.balance == 0 * BTC

    listener.on_execute.assert_called_once_with(order)
Esempio n. 15
0
def test_is_executable_on(mock_exchange_class):

    exchange = mock_exchange_class.return_value
    exchange.options = ExchangeOptions()
    exchange.id = "fake_exchange_id"
    exchange.name = "coinbase"
    exchange.clock = mock.Mock()
    exchange.clock.step = 0

    # Market order
    wallets = [Wallet(exchange, 10000 * USD), Wallet(exchange, 0 * BTC)]
    portfolio = Portfolio(USD, wallets)
    order = Order(step=0,
                  exchange_pair=ExchangePair(exchange, USD / BTC),
                  side=TradeSide.BUY,
                  trade_type=TradeType.MARKET,
                  quantity=5000.00 * USD,
                  portfolio=portfolio,
                  price=Decimal(7000.00))

    exchange.quote_price = mock.Mock(return_value=Decimal(6800.00))
    assert order.is_executable()

    exchange.quote_price = mock.Mock(return_value=Decimal(7200.00))
    assert order.is_executable()

    # Limit order
    wallets = [Wallet(exchange, 10000 * USD), Wallet(exchange, 0 * BTC)]
    portfolio = Portfolio(USD, wallets)
    order = Order(step=0,
                  exchange_pair=ExchangePair(exchange, USD / BTC),
                  side=TradeSide.BUY,
                  trade_type=TradeType.LIMIT,
                  quantity=5000.00 * USD,
                  portfolio=portfolio,
                  price=Decimal(7000.00))

    exchange.quote_price = mock.Mock(return_value=Decimal(6800.00))
    assert order.is_executable()

    exchange.quote_price = mock.Mock(return_value=Decimal(7200.00))
    assert order.is_executable()

    # Stop Order
    wallets = [Wallet(exchange, 0 * USD), Wallet(exchange, 2 * BTC)]
    portfolio = Portfolio(USD, wallets)
    order = Order(step=0,
                  exchange_pair=ExchangePair(exchange, USD / BTC),
                  side=TradeSide.SELL,
                  trade_type=TradeType.LIMIT,
                  quantity=1 * BTC,
                  portfolio=portfolio,
                  price=Decimal(7000.00),
                  criteria=Stop("down", 0.03))

    exchange.quote_price = mock.Mock(return_value=Decimal(1 - 0.031) *
                                     order.price)
    assert order.is_executable()

    exchange.quote_price = mock.Mock(return_value=Decimal(1 - 0.02) *
                                     order.price)
    assert not order.is_executable()
Esempio n. 16
0
def test_cancel(mock_order_listener_class, mock_trade_class,
                mock_exchange_class):

    exchange = mock_exchange_class.return_value
    exchange.options = ExchangeOptions()
    exchange.id = "fake_exchange_id"
    exchange.name = "coinbase"
    exchange.clock = mock.Mock()
    exchange.clock.step = 0
    exchange.quote_price = mock.Mock(return_value=Decimal(7000.00))

    wallets = [Wallet(exchange, 10000 * USD), Wallet(exchange, 0 * BTC)]
    portfolio = Portfolio(USD, wallets)

    order = Order(step=0,
                  exchange_pair=ExchangePair(exchange, USD / BTC),
                  side=TradeSide.BUY,
                  trade_type=TradeType.MARKET,
                  quantity=5200.00 * USD,
                  portfolio=portfolio,
                  price=Decimal(7000.00))

    listener = mock_order_listener_class.return_value
    listener.on_cancel = mock.Mock(return_value=None)
    order.attach(listener)

    order.execute()

    # Execute fake trade
    price = Decimal(7010.00)
    scale = order.price / price
    commission = 3.00 * USD

    trade = mock_trade_class.return_value
    trade.size = Decimal(scale * order.size - commission.size)
    trade.quantity = trade.size * USD
    trade.price = price
    trade.commission = commission

    base_wallet = portfolio.get_wallet(exchange.id, USD)
    quote_wallet = portfolio.get_wallet(exchange.id, BTC)

    base_size = trade.size + commission.size
    quote_size = (order.price / trade.price) * (trade.size / trade.price)

    base_wallet.withdraw(quantity=Quantity(USD,
                                           size=base_size,
                                           path_id=order.path_id),
                         reason="test")
    quote_wallet.deposit(quantity=Quantity(BTC,
                                           size=quote_size,
                                           path_id=order.path_id),
                         reason="test")

    order.fill(trade)

    assert order.status == OrderStatus.PARTIALLY_FILLED
    assert base_wallet.balance == 4800.00 * USD
    assert float(round(base_wallet.locked[order.path_id].size, 2)) == 7.42
    assert quote_wallet.balance == 0 * BTC
    assert float(round(quote_wallet.locked[order.path_id].size,
                       8)) == 0.73925519
    order.cancel()

    listener.on_cancel.assert_called_once_with(order)
    assert float(round(base_wallet.balance.size, 2)) == 4807.42
    assert order.path_id not in base_wallet.locked
    assert float(round(quote_wallet.balance.size, 8)) == 0.73925519
    assert order.path_id not in quote_wallet.locked
Esempio n. 17
0
def test_complete_complex_order(mock_trade_class, mock_exchange_class):
    exchange = mock_exchange_class.return_value
    exchange.options = ExchangeOptions()
    exchange.id = "fake_exchange_id"
    exchange.name = "coinbase"
    exchange.clock = mock.Mock()
    exchange.clock.step = 0
    exchange.quote_price = mock.Mock(return_value=Decimal(7000.00))

    wallets = [Wallet(exchange, 10000 * USD), Wallet(exchange, 0 * BTC)]
    portfolio = Portfolio(USD, wallets)

    side = TradeSide.BUY

    order = Order(step=0,
                  exchange_pair=ExchangePair(exchange, USD / BTC),
                  side=TradeSide.BUY,
                  trade_type=TradeType.MARKET,
                  quantity=5200.00 * USD,
                  portfolio=portfolio,
                  price=Decimal(7000.00))

    risk_criteria = Stop("down", 0.03) ^ Stop("up", 0.02)

    risk_management = OrderSpec(
        side=TradeSide.SELL if side == TradeSide.BUY else TradeSide.BUY,
        trade_type=TradeType.MARKET,
        exchange_pair=ExchangePair(exchange, USD / BTC),
        criteria=risk_criteria)

    order += risk_management

    order.execute()

    # Execute fake trade
    price = Decimal(7010.00)
    scale = order.price / price
    commission = 3.00 * USD

    base_size = scale * order.size - commission.size

    trade = mock_trade_class.return_value
    trade.size = Decimal(base_size)
    trade.quantity = base_size * USD
    trade.price = price
    trade.commission = commission

    base_wallet = portfolio.get_wallet(exchange.id, USD)
    quote_wallet = portfolio.get_wallet(exchange.id, BTC)

    base_size = trade.size + trade.commission.size
    quote_size = (order.price / trade.price) * (trade.size / trade.price)

    base_wallet.withdraw(quantity=Quantity(USD,
                                           size=base_size,
                                           path_id=order.path_id),
                         reason="test")
    quote_wallet.deposit(quantity=Quantity(BTC,
                                           size=quote_size,
                                           path_id=order.path_id),
                         reason="test")

    # Fill fake trade
    order.fill(trade)

    assert order.path_id in portfolio.get_wallet(exchange.id, USD).locked

    assert order.status == OrderStatus.PARTIALLY_FILLED
    next_order = order.complete()
    assert order.status == OrderStatus.FILLED

    assert next_order
    assert next_order.path_id == order.path_id
    assert next_order.size
    assert next_order.status == OrderStatus.PENDING
    assert next_order.side == TradeSide.SELL
    assert next_order.exchange_pair == ExchangePair(exchange, USD / BTC)
Esempio n. 18
0
def test_on_fill_with_complex_order(mock_trade_class, mock_exchange_class):

    exchange = mock_exchange_class.return_value
    exchange.options.max_trade_size = 1e6
    exchange.id = "fake_exchange_id"
    exchange.name = "coinbase"
    exchange.quote_price = lambda pair: Decimal(7000.00)

    broker = Broker()
    broker.exchanges = [exchange]

    wallets = [Wallet(exchange, 10000 * USD), Wallet(exchange, 0 * BTC)]
    portfolio = Portfolio(USD, wallets)

    side = TradeSide.BUY

    order = Order(step=0,
                  exchange_pair=ExchangePair(exchange, USD / BTC),
                  side=TradeSide.BUY,
                  trade_type=TradeType.MARKET,
                  quantity=5200.00 * USD,
                  portfolio=portfolio,
                  price=Decimal(7000.00))

    risk_criteria = Stop("down", 0.03) ^ Stop("up", 0.02)

    risk_management = OrderSpec(
        side=TradeSide.SELL if side == TradeSide.BUY else TradeSide.BUY,
        trade_type=TradeType.MARKET,
        exchange_pair=ExchangePair(exchange, USD / BTC),
        criteria=risk_criteria)

    order += risk_management

    order.attach(broker)
    order.execute()

    broker._executed[order.id] = order

    # Execute fake trade
    price = Decimal(7000.00)
    scale = order.price / price
    commission = 3.00 * USD

    base_size = scale * order.size - commission.size

    trade = mock_trade_class.return_value
    trade.order_id = order.id
    trade.size = base_size
    trade.quantity = base_size * USD
    trade.price = price
    trade.commission = commission

    base_wallet = portfolio.get_wallet(exchange.id, USD)
    quote_wallet = portfolio.get_wallet(exchange.id, BTC)

    base_size = trade.size + trade.commission.size
    quote_size = (order.price / trade.price) * (trade.size / trade.price)

    base_wallet.withdraw(quantity=Quantity(USD,
                                           size=base_size,
                                           path_id=order.path_id),
                         reason="test")
    quote_wallet.deposit(quantity=Quantity(BTC,
                                           size=quote_size,
                                           path_id=order.path_id),
                         reason="test")

    assert trade.order_id in broker.executed.keys()
    assert trade not in broker.trades
    assert broker.unexecuted == []

    order.fill(trade)

    assert order.remaining == 0
    assert trade in broker.trades[order.id]
    assert broker.unexecuted != []
Esempio n. 19
0
def test_is_executable_on(mock_portfolio_class, mock_exchange_class):

    exchange = mock_exchange_class.return_value
    portfolio = mock_portfolio_class.return_value

    # Market order
    order = Order(step=0,
                  side=TradeSide.BUY,
                  trade_type=TradeType.MARKET,
                  pair=USD/BTC,
                  quantity=5000.00 * USD,
                  portfolio=portfolio,
                  price=7000.00)

    exchange.quote_price = mock.Mock(return_value=6800.00)
    assert order.is_executable_on(exchange)

    exchange.quote_price = mock.Mock(return_value=7200.00)
    assert order.is_executable_on(exchange)

    # Limit order
    order = Order(step=0,
                  side=TradeSide.BUY,
                  trade_type=TradeType.LIMIT,
                  pair=USD/BTC,
                  quantity=5000.00 * USD,
                  portfolio=portfolio,
                  price=7000.00)

    exchange.quote_price = mock.Mock(return_value=6800.00)
    assert order.is_executable_on(exchange)

    exchange.quote_price = mock.Mock(return_value=7200.00)
    assert order.is_executable_on(exchange)

    # Stop Order
    order = Order(step=0,
                  side=TradeSide.SELL,
                  trade_type=TradeType.LIMIT,
                  pair=USD/BTC,
                  quantity=5000.00 * USD,
                  portfolio=portfolio,
                  price=7000.00,
                  criteria=Stop("down", 0.03))

    exchange.quote_price = mock.Mock(return_value=(1 - 0.031)*order.price)
    assert order.is_executable_on(exchange)

    exchange.quote_price = mock.Mock(return_value=(1 - 0.02) * order.price)
    assert not order.is_executable_on(exchange)
Esempio n. 20
0
def test_complete_complex_order(mock_trade_class,
                                mock_exchange_class):

    exchange = mock_exchange_class.return_value
    exchange.id = "fake_exchange_id"

    wallets = [Wallet(exchange, 10000 * USD), Wallet(exchange, 0 * BTC)]
    portfolio = Portfolio(USD, wallets)

    side = TradeSide.BUY

    order = Order(step=0,
                  side=TradeSide.BUY,
                  trade_type=TradeType.MARKET,
                  pair=USD / BTC,
                  quantity=5200.00 * USD,
                  portfolio=portfolio,
                  price=7000.00)

    risk_criteria = Stop("down", 0.03) ^ Stop("up", 0.02)

    risk_management = OrderSpec(side=TradeSide.SELL if side == TradeSide.BUY else TradeSide.BUY,
                                trade_type=TradeType.MARKET,
                                pair=USD / BTC,
                                criteria=risk_criteria)

    order += risk_management

    order.execute(exchange)

    # Execute fake trade
    price = 7010.00
    scale = order.price / price
    commission = 3.00 * USD

    base_size = scale * order.size - commission.size

    trade = mock_trade_class.return_value
    trade.size = base_size
    trade.price = price
    trade.commission = commission

    base_wallet = portfolio.get_wallet(exchange.id, USD)
    quote_wallet = portfolio.get_wallet(exchange.id, BTC)

    base_size = trade.size + trade.commission.size
    quote_size = (order.price / trade.price) * (trade.size / trade.price)

    base_wallet -= Quantity(USD, size=base_size, path_id=order.path_id)
    quote_wallet += Quantity(BTC, size=quote_size, path_id=order.path_id)

    # Fill fake trade
    order.fill(exchange, trade)

    assert order.path_id in portfolio.get_wallet(exchange.id, USD).locked

    assert order.status == OrderStatus.PARTIALLY_FILLED
    next_order = order.complete(exchange)
    assert order.status == OrderStatus.FILLED

    assert next_order
    assert next_order.path_id == order.path_id
    assert next_order.size
    assert next_order.status == OrderStatus.PENDING
    assert next_order.side == TradeSide.SELL
    assert next_order.pair == USD/BTC
Esempio n. 21
0
def assert_execute_order(
    current_price,
    base_balance,
    quote_balance,
    order_side,
    order_quantity,
    order_price,
):
    mock_clock = mock.Mock()
    clock = mock_clock.return_value
    clock.step = 3

    base = base_balance.instrument
    quote = quote_balance.instrument

    current_price = Decimal(current_price).quantize(
        Decimal(10)**-base.precision)
    order_price = Decimal(order_price).quantize(Decimal(10)**-base.precision)

    options = ExchangeOptions()
    mock_exchange = mock.Mock()
    exchange = mock_exchange.return_value
    exchange.name = "coinbase"
    exchange.options = options
    exchange.quote_price = lambda pair: current_price

    base_wallet = Wallet(exchange, base_balance)
    quote_wallet = Wallet(exchange, quote_balance)

    portfolio = Portfolio(USD, [base_wallet, quote_wallet])

    order = Order(step=1,
                  side=order_side,
                  trade_type=TradeType.MARKET,
                  exchange_pair=ExchangePair(exchange, base / quote),
                  quantity=order_quantity,
                  portfolio=portfolio,
                  price=order_price,
                  path_id="fake_id")
    order.status = OrderStatus.OPEN

    if order_side == TradeSide.BUY:

        trade = execute_buy_order(
            order,
            base_wallet,
            quote_wallet,
            current_price=current_price,
            options=options,
            clock=clock,
        )

        base_balance = base_wallet.locked['fake_id'].size
        quote_balance = quote_wallet.locked['fake_id'].size

        expected_base_balance = order_quantity.size - (trade.size +
                                                       trade.commission.size)
        expected_quote_balance = trade.size / current_price

        expected_base_balance = expected_base_balance.quantize(
            Decimal(10)**-base.precision)
        expected_quote_balance = expected_quote_balance.quantize(
            Decimal(10)**-quote.precision)

        assert base_balance == expected_base_balance
        assert quote_balance == expected_quote_balance

    else:
        trade = execute_sell_order(
            order,
            base_wallet,
            quote_wallet,
            current_price=current_price,
            options=options,
            clock=clock,
        )

        base_balance = base_wallet.locked['fake_id'].size
        quote_balance = quote_wallet.locked['fake_id'].size

        expected_base_balance = trade.size * current_price
        expected_base_balance = expected_base_balance.quantize(
            Decimal(10)**-base.precision)

        assert base_balance == expected_base_balance
        assert quote_balance == 0
Esempio n. 22
0
def test_on_fill_with_complex_order(mock_trade_class, mock_exchange_class):

    exchange = mock_exchange_class.return_value
    exchange.id = "fake_exchange_id"

    broker = Broker(exchange)

    wallets = [Wallet(exchange, 10000 * USD), Wallet(exchange, 0 * BTC)]
    portfolio = Portfolio(USD, wallets)

    side = TradeSide.BUY

    order = Order(step=0,
                  side=TradeSide.BUY,
                  trade_type=TradeType.MARKET,
                  pair=USD / BTC,
                  quantity=5200.00 * USD,
                  portfolio=portfolio,
                  price=7000.00)

    risk_criteria = Stop("down", 0.03) ^ Stop("up", 0.02)

    risk_management = OrderSpec(
        side=TradeSide.SELL if side == TradeSide.BUY else TradeSide.BUY,
        trade_type=TradeType.MARKET,
        pair=USD / BTC,
        criteria=risk_criteria)

    order += risk_management

    order.attach(broker)
    order.execute(exchange)

    broker._executed[order.id] = order

    # Execute fake trade
    price = 7000.00
    scale = order.price / price
    commission = 3.00 * USD

    base_size = scale * order.size - commission.size

    trade = mock_trade_class.return_value
    trade.order_id = order.id
    trade.size = base_size
    trade.price = price
    trade.commission = commission

    base_wallet = portfolio.get_wallet(exchange.id, USD)
    quote_wallet = portfolio.get_wallet(exchange.id, BTC)

    base_size = trade.size + trade.commission.size
    quote_size = (order.price / trade.price) * (trade.size / trade.price)

    base_wallet -= Quantity(USD, size=base_size, path_id=order.path_id)
    quote_wallet += Quantity(BTC, size=quote_size, path_id=order.path_id)

    assert trade.order_id in broker.executed.keys()
    assert trade not in broker.trades
    assert broker.unexecuted == []

    order.fill(exchange, trade)

    assert order.remaining_size == 0
    assert trade in broker.trades[order.id]
    assert broker.unexecuted != []