From ae42d9b2230d4afcdd0d0a63f18b49bdfe56e090 Mon Sep 17 00:00:00 2001 From: Mark Veidemanis Date: Fri, 6 Jan 2023 08:52:15 +0000 Subject: [PATCH] Fix profit/loss calculation --- core/exchanges/common.py | 39 +++++++++++++++++++++-------- core/tests/exchanges/test_common.py | 10 ++++---- core/tests/trading/test_live.py | 4 --- core/trading/risk.py | 5 ++++ 4 files changed, 39 insertions(+), 19 deletions(-) diff --git a/core/exchanges/common.py b/core/exchanges/common.py index 4ad221f..a25bf95 100644 --- a/core/exchanges/common.py +++ b/core/exchanges/common.py @@ -1,6 +1,7 @@ from decimal import Decimal as D from core.lib.elastic import store_msg +from core.trading.market import to_currency def get_balance_hook(user_id, user_name, account_id, account_name, balance): @@ -34,9 +35,22 @@ def tp_price_to_percent(tp_price, side, current_price, current_units, unrealised # Get the percent change of the TP price from the initial price. change_percent = ((initial_price - D(tp_price)) / initial_price) * 100 - # If the trade is long, the TP price will be lower than the initial price. if side == "long": - change_percent *= -1 + if D(tp_price) < initial_price: + loss = True + else: + loss = False + else: + if D(tp_price) > initial_price: + loss = True + else: + loss = False + + # if we are in loss on the short side, we want to show a negative + if loss: + change_percent = 0 - abs(change_percent) + else: + change_percent = abs(change_percent) return round(change_percent, 5) @@ -65,23 +79,22 @@ def sl_price_to_percent(sl_price, side, current_price, current_units, unrealised # change_percent *= -1 if side == "long": - if D(current_price) > initial_price: + if D(sl_price) > initial_price: profit = True else: profit = False else: - if D(current_price) < initial_price: + if D(sl_price) < initial_price: profit = True else: profit = False - # if we are in profit on the short side, we want to show a negative loss - if profit and side == "short": - # change_percent *= -1 + print("CHANGE PERCENT: ", change_percent) + print("PROFIT", profit) + + if profit: change_percent = 0 - abs(change_percent) - # if we are in loss on the long side, we want to show a positive loss - if not profit and side == "long": - # change_percent *= -1 + else: change_percent = abs(change_percent) return round(change_percent, 5) @@ -143,3 +156,9 @@ def convert_open_trades(open_trades): trades.append(cast) return trades + + +def convert_trades_to_usd(account, trades): + """ + Convert a list of trades to USD. + """ diff --git a/core/tests/exchanges/test_common.py b/core/tests/exchanges/test_common.py index 8ce583e..52e9134 100644 --- a/core/tests/exchanges/test_common.py +++ b/core/tests/exchanges/test_common.py @@ -163,7 +163,7 @@ class CommonTestCase(TestCase): """ Test that the SL price to percent conversion works for long trades. """ - sl_price = 1.1 # 10% + sl_price = 0.9 # 10% current_price = 1.0 current_units = 1 unrealised_pl = 0 @@ -176,7 +176,7 @@ class CommonTestCase(TestCase): """ Test that the SL price to percent conversion works for short trades. """ - sl_price = 0.9 # 10% + sl_price = 1.1 # 10% current_price = 1.0 current_units = 1 unrealised_pl = 0 @@ -219,7 +219,7 @@ class CommonTestCase(TestCase): Test that the SL price to percent conversion works for long trades with multiple units. """ - sl_price = 1.1 # -10% + sl_price = 0.9 # -10% current_price = 1.0 current_units = 10 unrealised_pl = 0 @@ -233,14 +233,14 @@ class CommonTestCase(TestCase): Test that the SL price to percent conversion works for short trades with multiple units. """ - sl_price = 0.9 # -10% + sl_price = 1.2 # -20% current_price = 1.0 current_units = 10 unrealised_pl = 0 percent = sl_price_to_percent( sl_price, "short", current_price, current_units, unrealised_pl ) - self.assertEqual(percent, 10) + self.assertEqual(percent, 20) def test_sl_price_to_percent_change_long_multi_profit(self): """ diff --git a/core/tests/trading/test_live.py b/core/tests/trading/test_live.py index b9ffabf..714b67d 100644 --- a/core/tests/trading/test_live.py +++ b/core/tests/trading/test_live.py @@ -134,14 +134,10 @@ class LiveTradingTestCase(ElasticMock, LiveBase, TestCase): 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) diff --git a/core/trading/risk.py b/core/trading/risk.py index 15bdff2..16c81d2 100644 --- a/core/trading/risk.py +++ b/core/trading/risk.py @@ -1,3 +1,6 @@ +from core.trading.market import to_currency + + def check_max_loss(risk_model, initial_balance, account_balance): """ Check that the account balance is within the max loss limit. @@ -15,6 +18,8 @@ def check_max_risk(risk_model, account_trades): total_risk = 0 for trade in account_trades: max_tmp = [] + # Need to calculate the max risk in base account currency + # Percentages relate to the price movement, without accounting the size of the trade if "stop_loss_percent" in trade: max_tmp.append(trade["stop_loss_percent"]) if "trailing_stop_loss_percent" in trade: