|
|
|
@ -1,5 +1,6 @@
|
|
|
|
|
from django.test import TestCase
|
|
|
|
|
|
|
|
|
|
from core.exchanges.common import convert_open_trades
|
|
|
|
|
from core.models import RiskModel, User
|
|
|
|
|
from core.trading import risk
|
|
|
|
|
|
|
|
|
@ -23,9 +24,9 @@ class RiskModelTestCase(TestCase):
|
|
|
|
|
"symbol": "XXXYYY",
|
|
|
|
|
"side": "BUY",
|
|
|
|
|
# We already calculated the TP percent loss relative to the account size
|
|
|
|
|
"tp_percent": 9,
|
|
|
|
|
"sl_percent": 9,
|
|
|
|
|
"tsl_percent": 9,
|
|
|
|
|
"take_profit_percent": 9,
|
|
|
|
|
"stop_loss_percent": 9,
|
|
|
|
|
"trailing_stop_loss_percent": 9,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
def test_check_max_loss(self):
|
|
|
|
@ -73,8 +74,8 @@ class RiskModelTestCase(TestCase):
|
|
|
|
|
multiple trades.
|
|
|
|
|
"""
|
|
|
|
|
trade = self.trade.copy()
|
|
|
|
|
trade["sl_percent"] = 1
|
|
|
|
|
trade["tsl_percent"] = 1
|
|
|
|
|
trade["stop_loss_percent"] = 1
|
|
|
|
|
trade["trailing_stop_loss_percent"] = 1
|
|
|
|
|
account_trades = [trade] * 9
|
|
|
|
|
allowed = risk.check_max_risk(self.risk_model, account_trades)
|
|
|
|
|
self.assertTrue(allowed)
|
|
|
|
@ -85,7 +86,7 @@ class RiskModelTestCase(TestCase):
|
|
|
|
|
risked is exactly the max risk limit.
|
|
|
|
|
"""
|
|
|
|
|
trade = self.trade.copy()
|
|
|
|
|
trade["sl_percent"] = 10
|
|
|
|
|
trade["stop_loss_percent"] = 10
|
|
|
|
|
account_trades = [trade]
|
|
|
|
|
allowed = risk.check_max_risk(self.risk_model, account_trades)
|
|
|
|
|
self.assertFalse(allowed)
|
|
|
|
@ -96,8 +97,8 @@ class RiskModelTestCase(TestCase):
|
|
|
|
|
risked is exactly the max risk limit with multiple trades.
|
|
|
|
|
"""
|
|
|
|
|
trade = self.trade.copy()
|
|
|
|
|
trade["sl_percent"] = 1
|
|
|
|
|
trade["tsl_percent"] = 1
|
|
|
|
|
trade["stop_loss_percent"] = 1
|
|
|
|
|
trade["trailing_stop_loss_percent"] = 1
|
|
|
|
|
account_trades = [trade] * 10
|
|
|
|
|
allowed = risk.check_max_risk(self.risk_model, account_trades)
|
|
|
|
|
self.assertFalse(allowed)
|
|
|
|
@ -189,3 +190,87 @@ class RiskModelTestCase(TestCase):
|
|
|
|
|
account_trades = [trade1, trade2, trade1, trade2, trade1, trade2]
|
|
|
|
|
allowed = risk.check_max_open_trades_per_symbol(self.risk_model, account_trades)
|
|
|
|
|
self.assertFalse(allowed)
|
|
|
|
|
|
|
|
|
|
def check_max_risk_market_data(self):
|
|
|
|
|
"""
|
|
|
|
|
Check that we can open a trade within the max risk limit with market data.
|
|
|
|
|
"""
|
|
|
|
|
trade = {
|
|
|
|
|
"id": "abd123",
|
|
|
|
|
"symbol": "EUR_USD",
|
|
|
|
|
"currentUnits": 100,
|
|
|
|
|
"side": "long",
|
|
|
|
|
"state": "open",
|
|
|
|
|
"price": 1.0, # initial
|
|
|
|
|
"unrealizedPL": 0, # price == initial
|
|
|
|
|
"stopLossOrder": {
|
|
|
|
|
"price": 0.95, # down by 5%, 5% risk
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
converted = convert_open_trades([trade])
|
|
|
|
|
self.assertEqual(converted[0]["stop_loss_percent"], 5)
|
|
|
|
|
max_risk_check = risk.check_max_risk(self.risk_model, converted)
|
|
|
|
|
self.assertTrue(max_risk_check) # 5% risk is fine
|
|
|
|
|
|
|
|
|
|
def 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.
|
|
|
|
|
"""
|
|
|
|
|
trade = {
|
|
|
|
|
"id": "abd123",
|
|
|
|
|
"symbol": "EUR_USD",
|
|
|
|
|
"currentUnits": 100,
|
|
|
|
|
"side": "long",
|
|
|
|
|
"state": "open",
|
|
|
|
|
"price": 1.0, # initial
|
|
|
|
|
"unrealizedPL": 0, # price == initial
|
|
|
|
|
"stopLossOrder": {
|
|
|
|
|
"price": 0.96, # down by 4%, 4% risk
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
converted = convert_open_trades([trade, trade])
|
|
|
|
|
max_risk_check = risk.check_max_risk(self.risk_model, converted)
|
|
|
|
|
self.assertTrue(max_risk_check) # 8% risk is fine
|
|
|
|
|
|
|
|
|
|
def check_max_risk_market_data_fail(self):
|
|
|
|
|
"""
|
|
|
|
|
Check that we can not open a trade outside the max risk limit with market data.
|
|
|
|
|
"""
|
|
|
|
|
trade = {
|
|
|
|
|
"id": "abd123",
|
|
|
|
|
"symbol": "EUR_USD",
|
|
|
|
|
"currentUnits": 100,
|
|
|
|
|
"side": "long",
|
|
|
|
|
"state": "open",
|
|
|
|
|
"price": 1.0, # initial
|
|
|
|
|
"unrealizedPL": 0, # price == initial
|
|
|
|
|
"stopLossOrder": {
|
|
|
|
|
"price": 0.9, # down by 10%, 10% risk
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
converted = convert_open_trades([trade])
|
|
|
|
|
self.assertEqual(converted[0]["stop_loss_percent"], 10)
|
|
|
|
|
max_risk_check = risk.check_max_risk(self.risk_model, converted)
|
|
|
|
|
self.assertFalse(max_risk_check) # 10% risk is too much
|
|
|
|
|
|
|
|
|
|
def 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.
|
|
|
|
|
"""
|
|
|
|
|
trade = {
|
|
|
|
|
"id": "abd123",
|
|
|
|
|
"symbol": "EUR_USD",
|
|
|
|
|
"currentUnits": 100,
|
|
|
|
|
"side": "long",
|
|
|
|
|
"state": "open",
|
|
|
|
|
"price": 1.0, # initial
|
|
|
|
|
"unrealizedPL": 0, # price == initial
|
|
|
|
|
"stopLossOrder": {
|
|
|
|
|
"price": 0.95, # down by 5%, 5% risk
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
converted = convert_open_trades([trade, trade])
|
|
|
|
|
max_risk_check = risk.check_max_risk(self.risk_model, converted)
|
|
|
|
|
self.assertFalse(max_risk_check) # 10% risk is too much
|
|
|
|
|