You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
249 lines
7.8 KiB
Python
249 lines
7.8 KiB
Python
2 years ago
|
from django.test import TestCase
|
||
|
|
||
2 years ago
|
from core.trading.crossfilter import check_conflicting_position, check_existing_position
|
||
2 years ago
|
|
||
|
|
||
1 year ago
|
class CrossfilterTestCase(TestCase):
|
||
2 years ago
|
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)
|