Esempio n. 1
0
    def test__get_market_price_with_sell_signal(self):
        """
        Test :meth:`ArbitrageStrategy._get_market_price`

        Assert the returned market price is the ticker ask price.
        """

        arbitrage = ArbitrageStrategy()

        TEST_PRICE = 1.0
        arbitrage.order = {
            'price': TEST_PRICE,
        }

        TEST_PRODUCT = 'USD'
        TEST_BID = 2.0
        TEST_ASK = 3.0
        arbitrage.ticker = {
            TEST_PRODUCT: {
                'bid': TEST_BID,
                'ask': TEST_ASK,
            },
        }

        market_price = arbitrage._get_market_price(CurrencyGraph.SELL_ORDER, TEST_PRODUCT)

        self.assertEqual(market_price, TEST_ASK)
Esempio n. 2
0
    def test__get_market_price_with_invalid_ticker_data(self):
        """
        Test :meth:`ArbitrageStrategy._get_market_price`

        Assert the returned market price is the same as the current order
        price.
        """

        arbitrage = ArbitrageStrategy()

        TEST_PRICE = 1.0
        arbitrage.order = {
            'price': TEST_PRICE,
        }

        TEST_PRODUCT = 'USD'
        TEST_BID = 2.0
        TEST_ASK = 3.0
        arbitrage.ticker = {
            TEST_PRODUCT: {
                'error': 'Invalid ticker data.',
            },
        }

        market_price = arbitrage._get_market_price(CurrencyGraph.BUY_ORDER, TEST_PRODUCT)

        self.assertEqual(market_price, TEST_PRICE)
Esempio n. 3
0
    def test__build_currency_graph_with_missing_ticker_data(self, currency_graph_mock):
        """
        Test :meth:`ArbitrageStrategy._build_currency_graph`

        Assert `None` is returned when invalid ticker data is detected.
        """

        arbitrage = ArbitrageStrategy()

        trader = MagicMock()

        TEST_PRODUCT = 'BTC-USD'
        trader.products = [TEST_PRODUCT]
        arbitrage.trader = trader

        ticker = {
            TEST_PRODUCT: {
                'bid': 1.0,
            },
        }
        arbitrage.ticker = ticker

        currency_graph = arbitrage._build_currency_graph()

        self.assertEqual(currency_graph, None)
Esempio n. 4
0
    def test__track_order__that_has_been_filled(self):
        """
        Test :meth:`ArbitrageStrategy._track_order`

        Assert the current order data is cleared and `False` is returned.
        """

        arbitrage = ArbitrageStrategy()

        test_order = {
            'id': 1,
        }
        arbitrage.order = test_order

        trader = MagicMock()

        test_order_update = {
            'id': 2,
            'status': 'done',
            'settled': True,
        }
        trader.get_order.return_value = test_order_update

        arbitrage.trader = trader

        success = arbitrage._track_order()

        self.assertFalse(success)
        self.assertEqual(arbitrage.order, None)
Esempio n. 5
0
    def test__track_order_success(self):
        """
        Test :meth:`ArbitrageStrategy._track_order`

        Assert the current order data is updated and `True` is returned.
        """

        arbitrage = ArbitrageStrategy()

        test_order = {
            'id': 1,
        }
        arbitrage.order = test_order

        trader = MagicMock()

        test_order_update = {
            'id': 2,
        }
        trader.get_order.return_value = test_order_update

        arbitrage.trader = trader

        success = arbitrage._track_order()

        self.assertTrue(success)
        self.assertEqual(arbitrage.order, test_order_update)
Esempio n. 6
0
    def test__get_market_price_with_no_signal(self):
        """
        Test :meth:`ArbitrageStrategy._get_market_price`

        Assert the returned market price is the same as the current order
        price.
        """

        arbitrage = ArbitrageStrategy()

        TEST_PRICE = 1.0
        arbitrage.order = {
            'price': TEST_PRICE,
        }

        TEST_PRODUCT = 'USD'
        TEST_BID = 2.0
        TEST_ASK = 3.0
        arbitrage.ticker = {
            TEST_PRODUCT: {
                'bid': TEST_BID,
                'ask': TEST_ASK,
            },
        }

        INVALID_SIGNAL = 3
        market_price = arbitrage._get_market_price(INVALID_SIGNAL, TEST_PRODUCT)

        self.assertEqual(market_price, TEST_PRICE)
Esempio n. 7
0
    def test__get_market_price_with_no_order_and_no_signal(self):
        """
        Test :meth:`ArbitrageStrategy._get_market_price`

        Assert the returned market price is `None`.
        """

        arbitrage = ArbitrageStrategy()

        arbitrage.order = None

        TEST_PRODUCT = 'USD'
        TEST_BID = 2.0
        TEST_ASK = 3.0
        arbitrage.ticker = {
            TEST_PRODUCT: {
                'bid': TEST_BID,
                'ask': TEST_ASK,
            },
        }

        INVALID_SIGNAL = 3
        market_price = arbitrage._get_market_price(INVALID_SIGNAL, TEST_PRODUCT)

        self.assertEqual(market_price, None)
Esempio n. 8
0
    def test__get_currency_path_without_currency_graph(self):
        """
        Test :meth:`ArbitrageStrategy._get_currency_path`

        Assert that a :class:`MissingCurrencyGraph` exception is raised.
        """

        arbitrage = ArbitrageStrategy()

        currency_graph = MagicMock()

        currency_graph.find_arbitrage_path.side_effect = AttributeError

        with self.assertRaises(MissingCurrencyGraph):
            path, distance = arbitrage._get_currency_path(currency_graph)
Esempio n. 9
0
    def test__cancel_order_without_order(self):
        """
        Test :meth:`ArbitrageStrategy._cancel_order`

        Assert `False` is returned.
        """

        arbitrage = ArbitrageStrategy()

        arbitrage.order = None

        trader = MagicMock()
        arbitrage.trader = trader

        success = arbitrage._cancel_order()

        self.assertFalse(success)
Esempio n. 10
0
    def test__set_current_node_with_valid_balance(self):
        """
        Test :meth:`ArbitrageStrategy._set_current_node`

        Assert :attr:`ArbitrageStrategy.current_node` is set to the first
        account currency with a positive balance.
        """

        arbitrage = ArbitrageStrategy()

        UNCHANGED_NODE = 'FAKE'
        arbitrage.current_node = UNCHANGED_NODE

        TEST_CURRENCY = 'USD'
        TEST_2ND_CURRENCY = 'BTC'
        TEST_BALANCE = 1.0

        arbitrage.accounts = [
            {
                'currency': TEST_CURRENCY,
                'balance': TEST_BALANCE,
            }, {
                'currency': TEST_2ND_CURRENCY,
                'balance': TEST_BALANCE,
            }
        ]

        arbitrage.ticker = {}

        arbitrage._set_current_node()

        self.assertEqual(arbitrage.current_node, TEST_CURRENCY)
Esempio n. 11
0
    def test__set_current_node_with_empty_balances(self):
        """
        Test :meth:`ArbitrageStrategy._set_current_node`

        Assert :attr:`ArbitrageStrategy.current_node` is unchanged.
        """

        arbitrage = ArbitrageStrategy()

        UNCHANGED_NODE = 'FAKE'
        arbitrage.current_node = UNCHANGED_NODE

        TEST_CURRENCY = 'USD'
        TEST_2ND_CURRENCY = 'BTC'
        TEST_BALANCE = 0.0

        arbitrage.accounts = [
            {
                'currency': TEST_CURRENCY,
                'balance': TEST_BALANCE,
            }, {
                'currency': TEST_2ND_CURRENCY,
                'balance': TEST_BALANCE,
            }
        ]

        arbitrage.ticker = {}

        arbitrage._set_current_node()

        self.assertEqual(arbitrage.current_node, UNCHANGED_NODE)
Esempio n. 12
0
    def test__get_currency_path_with_currency_graph(self):
        """
        Test :meth:`ArbitrageStrategy._get_currency_path`

        Assert the tuple output of :meth:`CurrencyGraph.find_arbitrage_path`
        is returned.
        """

        arbitrage = ArbitrageStrategy()

        currency_graph = MagicMock()

        test_path = ['USD_bid', 'BTC_ask', 'BTC_bid', 'USD_ask']
        TEST_DISTANCE = 1.0
        currency_graph.find_arbitrage_path.return_value = (test_path, TEST_DISTANCE,)

        path, distance = arbitrage._get_currency_path(currency_graph)

        self.assertEqual(path, test_path)
        self.assertEqual(distance, TEST_DISTANCE)
Esempio n. 13
0
    def test__place_order_below_threshold(self):
        """
        Test :meth:`ArbitrageStrategy._place_order`

        Assert that no orders are placed and `False` is returned.
        """

        arbitrage = ArbitrageStrategy()

        TEST_PRICE = 1.0
        arbitrage._get_market_price = MagicMock(return_value=TEST_PRICE)

        arbitrage.get_currency_balance = MagicMock()

        trader = MagicMock()
        arbitrage.trader = trader

        TEST_SIGNAL = CurrencyGraph.BUY_ORDER
        TEST_PRODUCT = 'BTC-USD'
        TEST_DISTANCE = 1.0

        success = arbitrage._place_order(TEST_SIGNAL, TEST_PRODUCT,
                TEST_DISTANCE)

        self.assertEqual(trader.buy.called, 0)
        self.assertEqual(trader.sell.called, 0)
        self.assertFalse(success)
Esempio n. 14
0
    def test__update_pending_order_with_change(self):
        """
        Test :meth:`ArbitrageStrategy._update_pending_order`

        Assert :meth:`ArbitrageStrategy._cancel_order` is called and `True`
        is returned.
        """

        arbitrage = ArbitrageStrategy()

        TEST_PRODUCT = 'BTC-USD'
        TEST_PRICE = 1.0
        arbitrage.order = {
            'product_id': TEST_PRODUCT,
            'price': TEST_PRICE,
        }

        NEW_PRICE = 2.0
        arbitrage._get_market_price = MagicMock(return_value=NEW_PRICE)

        cancel_order = MagicMock()
        arbitrage._cancel_order = cancel_order

        success = arbitrage._update_pending_order(CurrencyGraph.BUY_ORDER,
                TEST_PRODUCT)

        self.assertEqual(cancel_order.called, 1)
        self.assertTrue(success)
Esempio n. 15
0
    def test__place_order_invalid_signal(self):
        """
        Test :meth:`ArbitrageStrategy._place_order`

        Assert that no orders are placed and `False` is returned.
        """

        arbitrage = ArbitrageStrategy()

        TEST_PRICE = 1.0
        arbitrage._get_market_price = MagicMock(return_value=TEST_PRICE)

        arbitrage.get_currency_balance = MagicMock()

        trader = MagicMock()
        arbitrage.trader = trader

        INVALID_SIGNAL = 3
        TEST_PRODUCT = 'BTC-USD'
        TEST_DISTANCE = 2.0

        success = arbitrage._place_order(INVALID_SIGNAL, TEST_PRODUCT,
                TEST_DISTANCE)

        self.assertEqual(trader.buy.called, 0)
        self.assertEqual(trader.sell.called, 0)
        self.assertFalse(success)
Esempio n. 16
0
    def test__place_order_sell_signal(self):
        """
        Test :meth:`ArbitrageStrategy._place_order`

        Assert a sell order is placed and `True` is returned.
        """

        arbitrage = ArbitrageStrategy()

        TEST_PRICE = 1.0
        arbitrage._get_market_price = MagicMock(return_value=TEST_PRICE)

        arbitrage.get_currency_balance = MagicMock()

        trader = MagicMock()
        arbitrage.trader = trader

        TEST_SIGNAL = CurrencyGraph.SELL_ORDER
        TEST_PRODUCT = 'BTC-USD'
        TEST_DISTANCE = 2.0

        success = arbitrage._place_order(TEST_SIGNAL, TEST_PRODUCT,
                TEST_DISTANCE)

        self.assertEqual(trader.buy.called, 0)
        self.assertEqual(trader.sell.called, 1)
        self.assertTrue(success)
Esempio n. 17
0
    def test__cancel_order_with_valid_order(self):
        """
        Test :meth:`ArbitrageStrategy._cancel_order`

        Assert :meth:`GDAXTrader.cancel_order` is called with current order ID
        and `True` is returned.
        """

        arbitrage = ArbitrageStrategy()

        TEST_ID = 1
        arbitrage.order = {
            'order_id': TEST_ID,
        }

        trader = MagicMock()
        arbitrage.trader = trader

        success = arbitrage._cancel_order()

        trader.cancel_order.assert_called_with(TEST_ID)
        self.assertTrue(success)
Esempio n. 18
0
    def test__build_currency_graph_with_valid_ticker_data(self, currency_graph_mock):
        """
        Test :meth:`ArbitrageStrategy._build_currency_graph`

        Assert currency pairs for every product are added to the graph and a
        non-`None` value is returned.
        """

        arbitrage = ArbitrageStrategy()

        trader = MagicMock()

        TEST_PRODUCT = 'BTC-USD'
        trader.products = [TEST_PRODUCT]
        arbitrage.trader = trader

        ticker = {
            TEST_PRODUCT: {
                'bid': 1.0,
                'ask': 1.0,
            },
        }
        arbitrage.ticker = ticker

        currency_graph = arbitrage._build_currency_graph()

        calls = []

        for product in ticker:
            base = CurrencyGraph.get_base(product)
            quote = CurrencyGraph.get_quote(product)
            bid = ticker[product]['bid']
            ask = ticker[product]['ask']
            calls.append(call().add_currency_pair(base, quote, bid, ask))

        currency_graph_mock.assert_has_calls(calls, any_order=True)

        self.assertNotEqual(currency_graph, None)
Esempio n. 19
0
    def test__track_order_with_no_current_order(self):
        """
        Test :meth:`ArbitrageStrategy._track_order`

        Assert `False` is returned.
        """

        arbitrage = ArbitrageStrategy()

        arbitrage.order = None

        trader = MagicMock()

        test_order_update = {
            'id': 2,
        }
        trader.get_order.return_value = test_order_update

        arbitrage.trader = trader

        success = arbitrage._track_order()

        self.assertFalse(success)
        self.assertEqual(arbitrage.order, None)
Esempio n. 20
0
    def test_next_update_pending_order(self):
        """
        Test :meth:`ArbitrageStrategy.next`

        Assert :meth:`ArbitrageStrategy._update_pending_order` is called and
        `True` is returned.
        """

        arbitrage = ArbitrageStrategy()

        trade_signal = (CurrencyGraph.BUY_ORDER, 'BTC-USD', 1.0,)
        arbitrage._get_trade_signal = MagicMock(return_value=trade_signal)

        arbitrage._set_current_node = MagicMock()
        arbitrage._track_order = MagicMock(return_value=True)
        arbitrage._update_pending_order = MagicMock()
        arbitrage._place_order = MagicMock()

        success = arbitrage.next()

        self.assertTrue(success)
        self.assertEqual(arbitrage._update_pending_order.called, 1)
        self.assertEqual(arbitrage._place_order.called, 0)
Esempio n. 21
0
    def test_next_trade_signal_error(self):
        """
        Test :meth:`ArbitrageStrategy.next`

        Assert :meth:`ArbitrageStrategy._update_pending_order` and
        :meth:`ArbitrageStrategy._place_order` are not called and `False` is
        returned.
        """

        arbitrage = ArbitrageStrategy()

        error = MissingCurrencyGraph()
        arbitrage._get_trade_signal = MagicMock(side_effect=error)

        arbitrage._set_current_node = MagicMock()
        arbitrage._track_order = MagicMock(return_value=False)
        arbitrage._update_pending_order = MagicMock()
        arbitrage._place_order = MagicMock()

        success = arbitrage.next()

        self.assertFalse(success)
        self.assertEqual(arbitrage._update_pending_order.called, 0)
        self.assertEqual(arbitrage._place_order.called, 0)
Esempio n. 22
0
    def test__set_current_node_with_invalid_account_data(self):
        """
        Test :meth:`ArbitrageStrategy._set_current_node`

        Assert :attr:`ArbitrageStrategy.current_node` is unchanged.
        """

        arbitrage = ArbitrageStrategy()

        UNCHANGED_NODE = 'FAKE'
        arbitrage.current_node = UNCHANGED_NODE

        TEST_CURRENCY = 'USD'
        TEST_BALANCE = 1.0

        arbitrage.accounts = [
            { 'error': 'Invalid account data.', }
        ]

        arbitrage.ticker = {}

        arbitrage._set_current_node()

        self.assertEqual(arbitrage.current_node, UNCHANGED_NODE)
Esempio n. 23
0
    def test__update_pending_order_without_order(self):
        """
        Test :meth:`ArbitrageStrategy._update_pending_order`

        Assert :meth:`ArbitrageStrategy._cancel_order` is not called and
        `False` is returned.
        """

        arbitrage = ArbitrageStrategy()

        TEST_PRODUCT = 'BTC-USD'
        TEST_PRICE = 1.0
        arbitrage.order = None

        arbitrage._get_market_price = MagicMock(return_value=TEST_PRICE)

        cancel_order = MagicMock()
        arbitrage._cancel_order = cancel_order

        success = arbitrage._update_pending_order(CurrencyGraph.BUY_ORDER,
                TEST_PRODUCT)

        self.assertEqual(cancel_order.called, 0)
        self.assertFalse(success)