Check the max risk relative to the account balance
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
from django.test import TestCase
|
||||
|
||||
from core.exchanges.common import convert_open_trades
|
||||
from core.exchanges import common
|
||||
from core.models import RiskModel, User
|
||||
from core.trading import risk
|
||||
|
||||
@@ -25,8 +25,11 @@ class RiskModelTestCase(TestCase):
|
||||
"side": "BUY",
|
||||
# We already calculated the TP percent loss relative to the account size
|
||||
"take_profit_percent": 9,
|
||||
"take_profit_usd": 9,
|
||||
"stop_loss_percent": 9,
|
||||
"stop_loss_usd": 9,
|
||||
"trailing_stop_loss_percent": 9,
|
||||
"trailing_stop_loss_usd": 9,
|
||||
}
|
||||
|
||||
def test_check_max_loss(self):
|
||||
@@ -65,7 +68,9 @@ class RiskModelTestCase(TestCase):
|
||||
Check that we can open a trade within the max risk limit.
|
||||
"""
|
||||
account_trades = [self.trade]
|
||||
allowed = risk.check_max_risk(self.risk_model, account_trades)
|
||||
allowed = risk.check_max_risk(
|
||||
self.risk_model, self.account_initial_balance, account_trades
|
||||
)
|
||||
self.assertTrue(allowed)
|
||||
|
||||
def test_check_max_risk_multiple_trades(self):
|
||||
@@ -76,8 +81,12 @@ class RiskModelTestCase(TestCase):
|
||||
trade = self.trade.copy()
|
||||
trade["stop_loss_percent"] = 1
|
||||
trade["trailing_stop_loss_percent"] = 1
|
||||
trade["stop_loss_usd"] = 1
|
||||
trade["trailing_stop_loss_usd"] = 1
|
||||
account_trades = [trade] * 9
|
||||
allowed = risk.check_max_risk(self.risk_model, account_trades)
|
||||
allowed = risk.check_max_risk(
|
||||
self.risk_model, self.account_initial_balance, account_trades
|
||||
)
|
||||
self.assertTrue(allowed)
|
||||
|
||||
def test_check_max_risk_fail_exact(self):
|
||||
@@ -87,8 +96,13 @@ class RiskModelTestCase(TestCase):
|
||||
"""
|
||||
trade = self.trade.copy()
|
||||
trade["stop_loss_percent"] = 10
|
||||
trade["trailing_stop_loss_percent"] = 10
|
||||
trade["stop_loss_usd"] = 10
|
||||
trade["trailing_stop_loss_usd"] = 10
|
||||
account_trades = [trade]
|
||||
allowed = risk.check_max_risk(self.risk_model, account_trades)
|
||||
allowed = risk.check_max_risk(
|
||||
self.risk_model, self.account_initial_balance, account_trades
|
||||
)
|
||||
self.assertFalse(allowed)
|
||||
|
||||
def test_check_max_risk_fail_exact_multiple_trades(self):
|
||||
@@ -99,8 +113,12 @@ class RiskModelTestCase(TestCase):
|
||||
trade = self.trade.copy()
|
||||
trade["stop_loss_percent"] = 1
|
||||
trade["trailing_stop_loss_percent"] = 1
|
||||
trade["stop_loss_usd"] = 1
|
||||
trade["trailing_stop_loss_usd"] = 1
|
||||
account_trades = [trade] * 10
|
||||
allowed = risk.check_max_risk(self.risk_model, account_trades)
|
||||
allowed = risk.check_max_risk(
|
||||
self.risk_model, self.account_initial_balance, account_trades
|
||||
)
|
||||
self.assertFalse(allowed)
|
||||
|
||||
def test_check_max_open_trades(self):
|
||||
@@ -191,7 +209,8 @@ class RiskModelTestCase(TestCase):
|
||||
allowed = risk.check_max_open_trades_per_symbol(self.risk_model, account_trades)
|
||||
self.assertFalse(allowed)
|
||||
|
||||
def check_max_risk_market_data(self):
|
||||
# Market data tests, account size: $1000
|
||||
def test_check_max_risk_market_data(self):
|
||||
"""
|
||||
Check that we can open a trade within the max risk limit with market data.
|
||||
"""
|
||||
@@ -206,13 +225,16 @@ class RiskModelTestCase(TestCase):
|
||||
"stopLossOrder": {
|
||||
"price": 0.95, # down by 5%, 5% risk
|
||||
},
|
||||
# Hardcoded prices to avoid calling market API here
|
||||
"stop_loss_usd": 50, # 5% of $1000
|
||||
}
|
||||
converted = convert_open_trades([trade])
|
||||
converted = common.convert_open_trades([trade])
|
||||
self.assertEqual(converted[0]["stop_loss_percent"], 5)
|
||||
max_risk_check = risk.check_max_risk(self.risk_model, converted)
|
||||
self.assertEqual(converted[0]["stop_loss_usd"], 50)
|
||||
max_risk_check = risk.check_max_risk(self.risk_model, 1000, converted)
|
||||
self.assertTrue(max_risk_check) # 5% risk is fine
|
||||
|
||||
def check_max_risk_market_data_multiple(self):
|
||||
def test_check_max_risk_market_data_multiple(self):
|
||||
"""
|
||||
Check that we can open a trade within the max risk limit with market data
|
||||
and multiple trades.
|
||||
@@ -228,12 +250,16 @@ class RiskModelTestCase(TestCase):
|
||||
"stopLossOrder": {
|
||||
"price": 0.96, # down by 4%, 4% risk
|
||||
},
|
||||
# Hardcoded prices to avoid calling market API here
|
||||
"stop_loss_usd": 40, # 4% of $1000
|
||||
}
|
||||
converted = convert_open_trades([trade, trade])
|
||||
max_risk_check = risk.check_max_risk(self.risk_model, converted)
|
||||
converted = common.convert_open_trades([trade, trade])
|
||||
self.assertEqual(converted[0]["stop_loss_percent"], 4)
|
||||
self.assertEqual(converted[0]["stop_loss_usd"], 40)
|
||||
max_risk_check = risk.check_max_risk(self.risk_model, 1000, converted)
|
||||
self.assertTrue(max_risk_check) # 8% risk is fine
|
||||
|
||||
def check_max_risk_market_data_fail(self):
|
||||
def test_check_max_risk_market_data_fail(self):
|
||||
"""
|
||||
Check that we can not open a trade outside the max risk limit with market data.
|
||||
"""
|
||||
@@ -248,13 +274,16 @@ class RiskModelTestCase(TestCase):
|
||||
"stopLossOrder": {
|
||||
"price": 0.9, # down by 10%, 10% risk
|
||||
},
|
||||
# Hardcoded prices to avoid calling market API here
|
||||
"stop_loss_usd": 100, # 10% of $1000
|
||||
}
|
||||
converted = convert_open_trades([trade])
|
||||
converted = common.convert_open_trades([trade])
|
||||
self.assertEqual(converted[0]["stop_loss_percent"], 10)
|
||||
max_risk_check = risk.check_max_risk(self.risk_model, converted)
|
||||
self.assertEqual(converted[0]["stop_loss_usd"], 100)
|
||||
max_risk_check = risk.check_max_risk(self.risk_model, 1000, converted)
|
||||
self.assertFalse(max_risk_check) # 10% risk is too much
|
||||
|
||||
def check_max_risk_market_data_fail_multiple(self):
|
||||
def test_check_max_risk_market_data_fail_multiple(self):
|
||||
"""
|
||||
Check that we can not open a trade outside the max risk limit with market data
|
||||
and multiple trades.
|
||||
@@ -270,12 +299,18 @@ class RiskModelTestCase(TestCase):
|
||||
"stopLossOrder": {
|
||||
"price": 0.95, # down by 5%, 5% risk
|
||||
},
|
||||
# Hardcoded prices to avoid calling market API here
|
||||
"stop_loss_usd": 50, # 5% of $1000
|
||||
}
|
||||
converted = convert_open_trades([trade, trade])
|
||||
max_risk_check = risk.check_max_risk(self.risk_model, converted)
|
||||
converted = common.convert_open_trades([trade, trade])
|
||||
self.assertEqual(converted[0]["stop_loss_percent"], 5)
|
||||
self.assertEqual(converted[0]["stop_loss_usd"], 50)
|
||||
self.assertEqual(converted[1]["stop_loss_percent"], 5)
|
||||
self.assertEqual(converted[1]["stop_loss_usd"], 50)
|
||||
max_risk_check = risk.check_max_risk(self.risk_model, 1000, converted)
|
||||
self.assertFalse(max_risk_check) # 10% risk is too much
|
||||
|
||||
def check_max_risk_market_data_fail_multiple_mixed(self):
|
||||
def test_check_max_risk_market_data_fail_multiple_mixed(self):
|
||||
"""
|
||||
Check that we can not open a trade outside the max risk limit with market data
|
||||
and multiple trades, mixing SL and TSL.
|
||||
@@ -291,16 +326,23 @@ class RiskModelTestCase(TestCase):
|
||||
"stopLossOrder": {
|
||||
"price": 0.95, # down by 5%, 5% risk
|
||||
},
|
||||
# Hardcoded prices to avoid calling market API here
|
||||
"stop_loss_usd": 50, # 5% of $1000
|
||||
"trailing_stop_loss_usd": 50,
|
||||
}
|
||||
trade2 = trade.copy()
|
||||
trade2["trailingStopLossOrder"] = {"price": 0.95}
|
||||
del trade2["stopLossOrder"]
|
||||
|
||||
converted = convert_open_trades([trade, trade2])
|
||||
max_risk_check = risk.check_max_risk(self.risk_model, converted)
|
||||
converted = common.convert_open_trades([trade, trade2])
|
||||
self.assertEqual(converted[0]["stop_loss_percent"], 5)
|
||||
self.assertEqual(converted[0]["stop_loss_usd"], 50)
|
||||
self.assertEqual(converted[1]["trailing_stop_loss_percent"], 5)
|
||||
self.assertEqual(converted[1]["trailing_stop_loss_usd"], 50)
|
||||
max_risk_check = risk.check_max_risk(self.risk_model, 1000, converted)
|
||||
self.assertFalse(max_risk_check) # 10% risk is too much
|
||||
|
||||
def check_max_risk_market_data_fail_multiple_mixed_both(self):
|
||||
def test_check_max_risk_market_data_fail_multiple_mixed_both(self):
|
||||
"""
|
||||
Check that we can not open a trade outside the max risk limit with market data
|
||||
and multiple trades, mixing SL and TSL, where both are set.
|
||||
@@ -316,10 +358,17 @@ class RiskModelTestCase(TestCase):
|
||||
"stopLossOrder": {
|
||||
"price": 0.95, # down by 5%, 5% risk
|
||||
},
|
||||
# Hardcoded prices to avoid calling market API here
|
||||
"stop_loss_usd": 50, # 5% of $1000
|
||||
"trailing_stop_loss_usd": 49,
|
||||
}
|
||||
trade2 = trade.copy()
|
||||
trade2["trailingStopLossOrder"] = {"price": 0.951}
|
||||
|
||||
converted = convert_open_trades([trade, trade2])
|
||||
max_risk_check = risk.check_max_risk(self.risk_model, converted)
|
||||
converted = common.convert_open_trades([trade, trade2])
|
||||
self.assertEqual(converted[0]["stop_loss_percent"], 5)
|
||||
self.assertEqual(converted[0]["stop_loss_usd"], 50)
|
||||
self.assertEqual(float(converted[1]["trailing_stop_loss_percent"]), 4.9)
|
||||
self.assertEqual(converted[1]["trailing_stop_loss_usd"], 49)
|
||||
max_risk_check = risk.check_max_risk(self.risk_model, 1000, converted)
|
||||
self.assertFalse(max_risk_check) # 10% risk is too much
|
||||
|
||||
Reference in New Issue
Block a user