From b882ba15d0e1ce031bd344f562f94c2d6cdd2aef Mon Sep 17 00:00:00 2001 From: Mark Veidemanis Date: Mon, 12 Dec 2022 19:53:32 +0000 Subject: [PATCH] Write tests for crossfilter sub-functions --- core/tests/lib/__init__.py | 0 core/tests/lib/test_market.py | 248 ++++++++++++++++++++++++++++++++++ 2 files changed, 248 insertions(+) create mode 100644 core/tests/lib/__init__.py create mode 100644 core/tests/lib/test_market.py diff --git a/core/tests/lib/__init__.py b/core/tests/lib/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/core/tests/lib/test_market.py b/core/tests/lib/test_market.py new file mode 100644 index 0000000..4b5efd3 --- /dev/null +++ b/core/tests/lib/test_market.py @@ -0,0 +1,248 @@ +from django.test import TestCase + +from core.lib.market import check_conflicting_position, check_existing_position + + +class MarketTestCase(TestCase): + def test_conflict_position(self): + position = { + "symbol": "EUR_USD", + "base": "EUR", + "quote": "USD", + "side": "long", + "units": "1", + } + trade_cast = { + "symbol": "GBP_EUR", + "base": "GBP", + "quote": "EUR", + "side": "long", + "units": "1", + } + opposite = "short" + + check = check_conflicting_position( + func="entry", + position=position, + open_base=position["base"], + open_quote=position["quote"], + open_side=position["side"], + open_symbol=position["symbol"], + open_units=position["units"], + new_base=trade_cast["base"], + new_quote=trade_cast["quote"], + new_side=trade_cast["side"], + new_symbol=trade_cast["symbol"], + trade_side_opposite=opposite, + ) + self.assertEqual(check["action"], "rejected") + + def test_conflict_position_quote(self): + position = { + "symbol": "EUR_USD", + "base": "EUR", + "quote": "USD", + "side": "long", + "units": "1", + } + trade_cast = { + "symbol": "USD_JPY", + "base": "USD", + "quote": "JPY", + "side": "long", + "units": "1", + } + opposite = "short" + + check = check_conflicting_position( + func="entry", + position=position, + open_base=position["base"], + open_quote=position["quote"], + open_side=position["side"], + open_symbol=position["symbol"], + open_units=position["units"], + new_base=trade_cast["base"], + new_quote=trade_cast["quote"], + new_side=trade_cast["side"], + new_symbol=trade_cast["symbol"], + trade_side_opposite=opposite, + ) + self.assertEqual(check["action"], "rejected") + + def test_conflict_position_invert_allowed(self): + position = { + "symbol": "EUR_USD", + "base": "EUR", + "quote": "USD", + "side": "long", + "units": "1", + } + trade_cast = { + "symbol": "GBP_EUR", + "base": "GBP", + "quote": "EUR", + "side": "short", + "units": "1", + } + opposite = "long" + + check = check_conflicting_position( + func="entry", + position=position, + open_base=position["base"], + open_quote=position["quote"], + open_side=position["side"], + open_symbol=position["symbol"], + open_units=position["units"], + new_base=trade_cast["base"], + new_quote=trade_cast["quote"], + new_side=trade_cast["side"], + new_symbol=trade_cast["symbol"], + trade_side_opposite=opposite, + ) + self.assertFalse(check) + + def test_conflict_position_quote_invert_allowed(self): + position = { + "symbol": "EUR_USD", + "base": "EUR", + "quote": "USD", + "side": "short", + "units": "1", + } + trade_cast = { + "symbol": "USD_JPY", + "base": "USD", + "quote": "JPY", + "side": "long", + "units": "1", + } + opposite = "short" + + check = check_conflicting_position( + func="entry", + position=position, + open_base=position["base"], + open_quote=position["quote"], + open_side=position["side"], + open_symbol=position["symbol"], + open_units=position["units"], + new_base=trade_cast["base"], + new_quote=trade_cast["quote"], + new_side=trade_cast["side"], + new_symbol=trade_cast["symbol"], + trade_side_opposite=opposite, + ) + self.assertFalse(check) + + def test_conflict_position_identical_allowed(self): + position = { + "symbol": "EUR_USD", + "base": "EUR", + "quote": "USD", + "side": "long", + "units": "1", + } + trade_cast = { + "symbol": "EUR_USD", + "base": "EUR", + "quote": "USD", + "side": "long", + "units": "1", + } + opposite = "short" + + check = check_conflicting_position( + func="entry", + position=position, + open_base=position["base"], + open_quote=position["quote"], + open_side=position["side"], + open_symbol=position["symbol"], + open_units=position["units"], + new_base=trade_cast["base"], + new_quote=trade_cast["quote"], + new_side=trade_cast["side"], + new_symbol=trade_cast["symbol"], + trade_side_opposite=opposite, + ) + self.assertFalse(check) + + def test_existing_position_fail(self): + """ + Check we cannot enter a short if we already have a long. + """ + position = {"symbol": "EUR_USD", "side": "long", "units": "1"} + trade_cast = {"symbol": "EUR_USD", "side": "short", "units": "1"} + opposite = "long" + + check = check_existing_position( + func="entry", + position=position, + open_side=position["side"], + open_symbol=position["symbol"], + open_units=position["units"], + new_side=trade_cast["side"], + new_symbol=trade_cast["symbol"], + trade_side_opposite=opposite, + ) + self.assertEqual(check["action"], "rejected") + + def test_existing_position_flip_fail(self): + """ + Check we cannot enter a long if we already have a short. + """ + position = {"symbol": "EUR_USD", "side": "short", "units": "1"} + trade_cast = {"symbol": "EUR_USD", "side": "long", "units": "1"} + opposite = "short" + + check = check_existing_position( + func="entry", + position=position, + open_side=position["side"], + open_symbol=position["symbol"], + open_units=position["units"], + new_side=trade_cast["side"], + new_symbol=trade_cast["symbol"], + trade_side_opposite=opposite, + ) + self.assertEqual(check["action"], "rejected") + + def test_existing_position_exit(self): + position = {"symbol": "EUR_USD", "side": "long", "units": "1"} + trade_cast = {"symbol": "EUR_USD", "side": "short", "units": "1"} + opposite = "long" + + check = check_existing_position( + func="exit", + position=position, + open_side=position["side"], + open_symbol=position["symbol"], + open_units=position["units"], + new_side=trade_cast["side"], + new_symbol=trade_cast["symbol"], + trade_side_opposite=opposite, + ) + + self.assertEqual(check["action"], "close") + self.assertEqual(check["positions"], position) + self.assertEqual(check["side"], opposite) + + def test_existing_position_exit_no_units(self): + position = {"symbol": "EUR_USD", "side": "long", "units": "0"} + trade_cast = {"symbol": "EUR_USD", "side": "short", "units": "1"} + opposite = "long" + + check = check_existing_position( + func="exit", + position=position, + open_side=position["side"], + open_symbol=position["symbol"], + open_units=position["units"], + new_side=trade_cast["side"], + new_symbol=trade_cast["symbol"], + trade_side_opposite=opposite, + ) + + self.assertFalse(check)