From ed63085e108e9d57b4fa67074e09fa2ee6cb674c Mon Sep 17 00:00:00 2001 From: Mark Veidemanis Date: Wed, 22 Feb 2023 07:20:37 +0000 Subject: [PATCH] Implement updating protection --- core/exchanges/oanda.py | 15 ++++++----- core/lib/schemas/oanda_s.py | 19 ++++++++++++++ core/tests/trading/test_live.py | 43 ++++++++++++++++--------------- core/trading/active_management.py | 11 ++++---- 4 files changed, 55 insertions(+), 33 deletions(-) diff --git a/core/exchanges/oanda.py b/core/exchanges/oanda.py index a27b6d8..b6823ba 100644 --- a/core/exchanges/oanda.py +++ b/core/exchanges/oanda.py @@ -145,13 +145,14 @@ class OANDAExchange(BaseExchange): r = trades.TradeDetails(accountID=self.account_id, tradeID=trade_id) return self.call(r) - def update_trade(self, trade): - raise NotImplementedError - # r = orders.OrderReplace( - # accountID=self.account_id, orderID=trade.order_id, data=data - # ) - # self.client.request(r) - # return r.response + def update_trade(self, trade_id, take_profit_price, stop_loss_price): + data = {} + if take_profit_price: + data["takeProfit"] = {"price": str(take_profit_price)} + if stop_loss_price: + data["stopLoss"] = {"price": str(stop_loss_price)} + r = trades.TradeCRCDO(accountID=self.account_id, tradeID=trade_id, data=data) + return self.call(r) def cancel_trade(self, trade_id): raise NotImplementedError diff --git a/core/lib/schemas/oanda_s.py b/core/lib/schemas/oanda_s.py index ffb3259..c978e6d 100644 --- a/core/lib/schemas/oanda_s.py +++ b/core/lib/schemas/oanda_s.py @@ -730,3 +730,22 @@ TradeCloseSchema = { "longPositionCloseout": "orderCreateTransaction.longPositionCloseout", "longOrderFillTransaction": "orderCreateTransaction.longOrderFillTransaction", } + + +class TradeCRCDO(BaseModel): + takeProfitOrderCancelTransaction: OrderTransaction + takeProfitOrderTransaction: OrderTransaction + stopLossOrderCancelTransaction: OrderTransaction + stopLossOrderTransaction: OrderTransaction + relatedTransactionIDs: list[str] + lastTransactionID: str + + +TradeCRCDOSchema = { + "takeProfitOrderCancelTransaction": "takeProfitOrderCancelTransaction", + "takeProfitOrderTransaction": "takeProfitOrderTransaction", + "stopLossOrderCancelTransaction": "stopLossOrderCancelTransaction", + "stopLossOrderTransaction": "stopLossOrderTransaction", + "relatedTransactionIDs": "relatedTransactionIDs", + "lastTransactionID": "lastTransactionID", +} diff --git a/core/tests/trading/test_live.py b/core/tests/trading/test_live.py index 61e534f..b036572 100644 --- a/core/tests/trading/test_live.py +++ b/core/tests/trading/test_live.py @@ -182,8 +182,6 @@ class ActiveManagementMixinTestCase(StrategyMixin): "buy", self.account, self.strategy, self.account.client.get_balance(), "EUR" ) trade_size = round(trade_size, 0) - print("TRADE SIZE", trade_size) - print("TYPE", type(trade_size)) complex_trade = self.create_complex_trade("buy", trade_size, "EUR_USD", 5, 5) self.open_trade(complex_trade) @@ -192,16 +190,20 @@ class ActiveManagementMixinTestCase(StrategyMixin): expected = { "close": [ { - "id": complex_trade.id, + "id": complex_trade.order_id, "check": "protection", - } ] } - del self.ams.checks["close"][0]["extra"] + del self.ams.actions["close"][0]["extra"] + + self.assertEqual(self.ams.actions, expected) - self.assertEqual(self.ams.checks, expected) + self.ams.execute_actions() + + trades = self.account.client.get_all_open_trades() + self.assertEqual(len(trades), 0) def test_ams_protection_violated_adjust(self): # Don't violate position size check @@ -209,25 +211,24 @@ class ActiveManagementMixinTestCase(StrategyMixin): "buy", self.account, self.strategy, self.account.client.get_balance(), "EUR" ) trade_size = round(trade_size, 0) - print("TRADE SIZE", trade_size) - print("TYPE", type(trade_size)) complex_trade = self.create_complex_trade("buy", trade_size, "EUR_USD", 5, 5) self.open_trade(complex_trade) self.ams.run_checks() - expected = { - "adjust": [ - { - "id": "21381", - "check": "protection", - "extra": { - "stop_loss_price": D("1.05812"), - "take_profit_price": D("1.08484"), - }, - } - ] - } - print("CHECKS", self.ams.actions) + + self.assertEqual(len(self.ams.actions["adjust"]), 1) + expected_tp = self.ams.actions["adjust"][0]["extra"]["take_profit_price"] + expected_sl = self.ams.actions["adjust"][0]["extra"]["stop_loss_price"] + self.assertEqual(len(self.ams.actions["adjust"]), 1) + + self.ams.execute_actions() + + trades = self.account.client.get_all_open_trades() + self.assertEqual(len(trades), 1) + self.assertEqual(D(trades[0]["takeProfitOrder"]["price"]), expected_tp) + self.assertEqual(D(trades[0]["stopLossOrder"]["price"]), expected_sl) + + self.close_trade(complex_trade) def test_ams_asset_groups_violated(self): pass diff --git a/core/trading/active_management.py b/core/trading/active_management.py index da9ca2d..2916c40 100644 --- a/core/trading/active_management.py +++ b/core/trading/active_management.py @@ -86,10 +86,11 @@ class ActiveManagement(object): for action_cast in action_cast_list: msg += f"ACTION: '{action}' on trade ID '{action_cast['id']}'\n" msg += f"VIOLATION: '{action_cast['check']}'\n" - if action_cast["extra"]: - extra = action_cast["extra"] - extra = ", ".join([f"{k}: {v}" for k, v in extra.items()]) - msg += f"EXTRA: {extra}\n" + if "extra" in action_cast: + if action_cast["extra"]: + extra = action_cast["extra"] + extra = ", ".join([f"{k}: {v}" for k, v in extra.items()]) + msg += f"EXTRA: {extra}\n" msg += "=========\n" sendmsg(self.strategy.user, msg, title=f"AMS: {action}") @@ -114,7 +115,7 @@ class ActiveManagement(object): self.strategy.account.client.close_trade(trade_id, difference, symbol) def adjust_protection(self, trade_id, new_protection): - pass # TODO + self.strategy.account.client.update_trade(trade_id, **new_protection) def bulk_adjust(self, action_cast_list): for item in action_cast_list: