Repository: Drakkar-Software/trading-backend (language: python)

Issue:
[OKEx] Add get_orders_parameters



Discussion / hints:

Fix patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index d1d9156..43faab5 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,6 +4,11 @@ All notable changes to this project will be documented in this file.
 The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
 and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
 
+## [1.0.6] - 2021-08-02
+### Added
+- FTX ids
+- OKEx ids
+
 ## [1.0.5] - 2021-08-02
 ### Added
 - Referral id
diff --git a/README.md b/README.md
index bf6882e..50b2fb3 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-# trading-backend [1.0.5](https://github.com/Drakkar-Software/trading-backend/tree/master/CHANGELOG.md)
+# trading-backend [1.0.6](https://github.com/Drakkar-Software/trading-backend/tree/master/CHANGELOG.md)
 [![PyPI](https://img.shields.io/pypi/v/trading-backend.svg)](https://pypi.python.org/pypi/trading-backend/)
 [![Downloads](https://pepy.tech/badge/trading-backend/month)](https://pepy.tech/project/trading-backend)
 [![Github-Action-CI](https://github.com/Drakkar-Software/trading-backend/workflows/trading-backend-CI/badge.svg)](https://github.com/Drakkar-Software/trading-backend/actions)
diff --git a/trading_backend/__init__.py b/trading_backend/__init__.py
index 646f576..eb9464c 100644
--- a/trading_backend/__init__.py
+++ b/trading_backend/__init__.py
@@ -13,7 +13,7 @@
 #
 #  You should have received a copy of the GNU Lesser General Public
 #  License along with this library.
-VERSION = "1.0.5"
+VERSION = "1.0.6"
 PROJECT_NAME = "trading-backend"
 
 from trading_backend import exchange_factory
diff --git a/trading_backend/exchanges/__init__.py b/trading_backend/exchanges/__init__.py
index 95a06a2..229ce51 100644
--- a/trading_backend/exchanges/__init__.py
+++ b/trading_backend/exchanges/__init__.py
@@ -28,8 +28,14 @@
     OKEx
 )
 
+from trading_backend.exchanges import ftx
+from trading_backend.exchanges.ftx import (
+    FTX
+)
+
 __all__ = [
     "Exchange",
     "Binance",
     "OKEx",
+    "FTX",
 ]
diff --git a/trading_backend/exchanges/ftx.py b/trading_backend/exchanges/ftx.py
new file mode 100644
index 0000000..074b33c
--- /dev/null
+++ b/trading_backend/exchanges/ftx.py
@@ -0,0 +1,48 @@
+#  Drakkar-Software trading-backend
+#  Copyright (c) Drakkar-Software, All rights reserved.
+#
+#  This library is free software; you can redistribute it and/or
+#  modify it under the terms of the GNU Lesser General Public
+#  License as published by the Free Software Foundation; either
+#  version 3.0 of the License, or (at your option) any later version.
+#
+#  This library is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+#  Lesser General Public License for more details.
+#
+#  You should have received a copy of the GNU Lesser General Public
+#  License along with this library.
+import trading_backend.exchanges as exchanges
+
+
+class FTX(exchanges.Exchange):
+    SPOT_ID = "Octobot"
+    MARGIN_ID = "Octobot"
+    FUTURE_ID = "Octobot"
+    REF_ID = "33613187"
+    IS_SPONSORING = True
+
+    @classmethod
+    def get_name(cls):
+        return 'ftx'
+
+    def get_orders_parameters(self, params=None) -> dict:
+        params = super().get_orders_parameters(params)
+        params.update({'externalReferralProgram': self._get_id()})
+        return params
+
+    async def _inner_is_valid_account(self) -> (bool, str):
+        """
+        Response doc from https://help.ftx.com/hc/en-us/articles/360044373831-External-Referral-Programs
+        {
+        'enabled': True,
+        'externalReferralProgram': 'TradeX100',
+        'readOnly': False,
+        'requireWhitelistedIp': False,
+        'subaccountNickname': None,
+        'withdrawalEnabled': False
+        }
+        """
+        # Seems to be unnecessary because the program name is overwritten in `get_orders_parameters`
+        return True, None


Test patch:
diff --git a/tests/__init__.py b/tests/__init__.py
index 34cd9d6..79bd484 100644
--- a/tests/__init__.py
+++ b/tests/__init__.py
@@ -27,6 +27,11 @@ def okex_exchange():
     return ExchangeWrapper(ccxt.async_support.okex())
 
 
+@pytest.fixture
+def ftx_exchange():
+    return ExchangeWrapper(ccxt.async_support.ftx())
+
+
 @pytest.fixture
 def bybit_exchange():
     return ExchangeWrapper(ccxt.async_support.bybit())
diff --git a/tests/exchanges/test_ftx.py b/tests/exchanges/test_ftx.py
new file mode 100644
index 0000000..e636efb
--- /dev/null
+++ b/tests/exchanges/test_ftx.py
@@ -0,0 +1,33 @@
+#  Drakkar-Software trading-backend
+#  Copyright (c) Drakkar-Software, All rights reserved.
+#
+#  This library is free software; you can redistribute it and/or
+#  modify it under the terms of the GNU Lesser General Public
+#  License as published by the Free Software Foundation; either
+#  version 3.0 of the License, or (at your option) any later version.
+#
+#  This library is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+#  Lesser General Public License for more details.
+#
+#  You should have received a copy of the GNU Lesser General Public
+#  License along with this library.
+import pytest
+import ccxt.async_support
+import trading_backend.exchanges as exchanges
+import tests.util.create_order_tests as create_order_tests
+from tests import ftx_exchange
+
+
+def test_get_name(ftx_exchange):
+    assert exchanges.FTX(ftx_exchange).get_name() == ccxt.async_support.ftx().name.lower()
+
+
+@pytest.mark.asyncio
+async def test_get_orders_parameters(ftx_exchange):
+    exchange = exchanges.FTX(ftx_exchange)
+    await create_order_tests.create_order_mocked_test(exchange,
+                                                      exchange_private_post_order_method_name="privatePostOrders",
+                                                      exchange_request_referral_key="externalReferralProgram",
+                                                      should_contains=False)
diff --git a/tests/exchanges/test_okex.py b/tests/exchanges/test_okex.py
index 162bd98..ea56a55 100644
--- a/tests/exchanges/test_okex.py
+++ b/tests/exchanges/test_okex.py
@@ -14,10 +14,9 @@
 #  You should have received a copy of the GNU Lesser General Public
 #  License along with this library.
 import pytest
-import mock
 import ccxt.async_support
 import trading_backend.exchanges as exchanges
-import trading_backend
+import tests.util.create_order_tests as create_order_tests
 from tests import okex_exchange
 
 
@@ -28,15 +27,7 @@ def test_get_name(okex_exchange):
 @pytest.mark.asyncio
 async def test_get_orders_parameters(okex_exchange):
     exchange = exchanges.OKEx(okex_exchange)
-    with mock.patch.object(exchange._exchange.connector.client,
-                           "privatePostTradeOrder",
-                           mock.AsyncMock(return_value={})) as privatePostTradeOrder_mock:
-
-        # without broker id patch
-        await exchange._exchange.connector.client.create_limit_buy_order("BTC/USDT", 1, 1)
-        assert exchange._get_id() not in privatePostTradeOrder_mock.call_args[0][0].get("clOrdId", "")
-
-        # with broker id patch
-        exchange.get_orders_parameters()
-        await exchange._exchange.connector.client.create_limit_buy_order("BTC/USDT", 1, 1)
-        assert exchange._get_id() in privatePostTradeOrder_mock.call_args[0][0].get("clOrdId", "")
+    await create_order_tests.create_order_mocked_test(exchange,
+                                                      exchange_private_post_order_method_name="privatePostTradeOrder",
+                                                      exchange_request_referral_key="clOrdId",
+                                                      should_contains=True)
diff --git a/tests/test_exchanges_factory.py b/tests/test_exchanges_factory.py
index a03419b..566069f 100644
--- a/tests/test_exchanges_factory.py
+++ b/tests/test_exchanges_factory.py
@@ -59,5 +59,5 @@ def test_get_exchanges():
         exchange.get_name(): exchange
         for exchange in trading_backend.exchanges.Exchange.__subclasses__()
     })
-    assert len(exchanges_by_name) == 3
+    assert len(exchanges_by_name) == 4
     assert trading_backend.exchange_factory._get_exchanges() == exchanges_by_name
diff --git a/tests/util/__init__.py b/tests/util/__init__.py
new file mode 100644
index 0000000..6f1ea0b
--- /dev/null
+++ b/tests/util/__init__.py
@@ -0,0 +1,15 @@
+#  Drakkar-Software trading-backend
+#  Copyright (c) Drakkar-Software, All rights reserved.
+#
+#  This library is free software; you can redistribute it and/or
+#  modify it under the terms of the GNU Lesser General Public
+#  License as published by the Free Software Foundation; either
+#  version 3.0 of the License, or (at your option) any later version.
+#
+#  This library is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+#  Lesser General Public License for more details.
+#
+#  You should have received a copy of the GNU Lesser General Public
+#  License along with this library.
diff --git a/tests/util/create_order_tests.py b/tests/util/create_order_tests.py
new file mode 100644
index 0000000..e4f8d6e
--- /dev/null
+++ b/tests/util/create_order_tests.py
@@ -0,0 +1,43 @@
+#  Drakkar-Software trading-backend
+#  Copyright (c) Drakkar-Software, All rights reserved.
+#
+#  This library is free software; you can redistribute it and/or
+#  modify it under the terms of the GNU Lesser General Public
+#  License as published by the Free Software Foundation; either
+#  version 3.0 of the License, or (at your option) any later version.
+#
+#  This library is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+#  Lesser General Public License for more details.
+#
+#  You should have received a copy of the GNU Lesser General Public
+#  License along with this library.
+import mock
+import trading_backend.exchanges as exchanges
+
+
+async def create_order_mocked_test(exchange: exchanges.Exchange,
+                                   exchange_private_post_order_method_name: str,
+                                   exchange_request_referral_key: str,
+                                   should_contains: bool = True,
+                                   symbol: str = "BTC/USDT",
+                                   amount: int = 1,
+                                   price: int = 1):
+    with mock.patch.object(exchange._exchange.connector.client,
+                           exchange_private_post_order_method_name,
+                           mock.AsyncMock(return_value={})) as post_order_mock:
+        # without referral patch
+        await exchange._exchange.connector.client.create_limit_buy_order(symbol, amount, price)
+        if should_contains:
+            assert exchange._get_id() not in post_order_mock.call_args[0][0].get(exchange_request_referral_key, "")
+        else:
+            assert exchange._get_id() != post_order_mock.call_args[0][0].get(exchange_request_referral_key, "")
+
+        # with referral patch
+        await exchange._exchange.connector.client.create_limit_buy_order(symbol, amount, price,
+                                                                         params=exchange.get_orders_parameters())
+        if should_contains:
+            assert exchange._get_id() in post_order_mock.call_args[0][0].get(exchange_request_referral_key, "")
+        else:
+            assert exchange._get_id() == post_order_mock.call_args[0][0].get(exchange_request_referral_key, "")