from decimal import Decimal as D from django.test import TestCase from core.exchanges.common import convert_open_trades from core.models import Trade from core.tests.helpers import ElasticMock, LiveBase from core.trading.market import get_precision, get_price, get_sl, get_tp class LiveTradingTestCase(ElasticMock, LiveBase, TestCase): def setUp(self): super(LiveTradingTestCase, self).setUp() self.trade = Trade.objects.create( user=self.user, account=self.account, symbol="EUR_USD", time_in_force="FOK", type="market", amount=10, direction="buy", ) self.commission = 0.025 def test_account_functional(self): """ Test that the account is functional. """ balance = self.account.client.get_balance() # We need some money to place trades self.assertTrue(balance > 1000) def open_trade(self, trade=None): if trade: posted = trade.post() else: posted = self.trade.post() # Check the opened trade self.assertEqual(posted["type"], "MARKET_ORDER") self.assertEqual(posted["symbol"], "EUR_USD") self.assertEqual(posted["units"], "10") self.assertEqual(posted["timeInForce"], "FOK") return posted def close_trade(self, trade=None): if trade: trade.refresh_from_db() closed = self.account.client.close_trade(trade.order_id) else: # refresh the trade to get the trade id self.trade.refresh_from_db() closed = self.account.client.close_trade(self.trade.order_id) # Check the feedback from closing the trade self.assertEqual(closed["type"], "MARKET_ORDER") self.assertEqual(closed["symbol"], "EUR_USD") self.assertEqual(closed["units"], "-10") self.assertEqual(closed["timeInForce"], "FOK") self.assertEqual(closed["reason"], "TRADE_CLOSE") return closed def test_place_close_trade(self): """ Test placing a trade. """ self.open_trade() self.close_trade() def test_get_all_open_trades(self): """ Test getting all open trades. """ self.open_trade() trades = self.account.client.get_all_open_trades() self.trade.refresh_from_db() found = False for trade in trades["itemlist"]: if trade["id"] == self.trade.order_id: self.assertEqual(trade["symbol"], "EUR_USD") self.assertEqual(trade["currentUnits"], "10") self.assertEqual(trade["initialUnits"], "10") self.assertEqual(trade["state"], "OPEN") found = True break self.close_trade() if not found: self.fail("Could not find the trade in the list of open trades") def test_convert_open_trades(self): """ Test converting open trades response to Trade-like format. """ eur_usd_price = get_price(self.account, "buy", "EUR_USD") trade_tp = get_tp("buy", 1, eur_usd_price) trade_sl = get_sl("buy", 2, eur_usd_price) # trade_tsl = get_sl("buy", 1, eur_usd_price, return_var=True) # # TP 1% profit # trade_tp = eur_usd_price * D(1.01) # # SL 2% loss # trade_sl = eur_usd_price * D(0.98) # # TSL 1% loss # trade_tsl = eur_usd_price * D(0.99) trade_precision, display_precision = get_precision(self.account, "EUR_USD") # Round everything to the display precision trade_tp = round(trade_tp, display_precision) trade_sl = round(trade_sl, display_precision) # trade_tsl = round(trade_tsl, display_precision) complex_trade = Trade.objects.create( user=self.user, account=self.account, symbol="EUR_USD", time_in_force="FOK", type="market", amount=10, direction="buy", take_profit=trade_tp, stop_loss=trade_sl, # trailing_stop_loss=trade_tsl, ) self.open_trade(complex_trade) trades = self.account.client.get_all_open_trades() trades_converted = convert_open_trades(trades["itemlist"]) self.assertEqual(len(trades_converted), 1) expected_tp_percent = D(1 - self.commission) expected_sl_percent = D(2 - self.commission) actual_tp_percent = trades_converted[0]["take_profit_percent"] actual_sl_percent = trades_converted[0]["stop_loss_percent"] print("actual_tp_percent", actual_tp_percent) print("actual_sl_percent", actual_sl_percent) tp_percent_difference = abs(expected_tp_percent - actual_tp_percent) sl_percent_difference = abs(expected_sl_percent - actual_sl_percent) max_difference = D(0.08) # depends on market conditions print("TP percent difference: {}".format(tp_percent_difference)) print("SL percent difference: {}".format(sl_percent_difference)) self.assertLess(tp_percent_difference, max_difference) self.assertLess(sl_percent_difference, max_difference) self.close_trade(complex_trade)