diff --git a/README.md b/README.md index c6e54b112..d7ab7c05c 100644 --- a/README.md +++ b/README.md @@ -29,6 +29,7 @@ Please read the [exchange specific notes](docs/exchanges.md) to learn about even - [X] [Binance](https://www.binance.com/) - [X] [Bitmart](https://bitmart.com/) +- [X] [BingX](https://bingx.com/invite/0EM9RX) - [X] [Gate.io](https://www.gate.io/ref/6266643) - [X] [HTX](https://www.htx.com/) (Former Huobi) - [X] [Kraken](https://kraken.com/) diff --git a/docs/exchanges.md b/docs/exchanges.md index d4437cfff..f3550e97e 100644 --- a/docs/exchanges.md +++ b/docs/exchanges.md @@ -127,6 +127,13 @@ These settings will be checked on startup, and freqtrade will show an error if t Freqtrade will not attempt to change these settings. +## Bingx + +BingX supports [time_in_force](configuration.md#understand-order_time_in_force) with settings "GTC" (good till cancelled), "IOC" (immediate-or-cancel) and "PO" (Post only) settings. + +!!! Tip "Stoploss on Exchange" + Bingx supports `stoploss_on_exchange` and can use both stop-limit and stop-market orders. It provides great advantages, so we recommend to benefit from it by enabling stoploss on exchange. + ## Kraken Kraken supports [time_in_force](configuration.md#understand-order_time_in_force) with settings "GTC" (good till cancelled), "IOC" (immediate-or-cancel) and "PO" (Post only) settings. diff --git a/docs/index.md b/docs/index.md index 26debe993..55835f555 100644 --- a/docs/index.md +++ b/docs/index.md @@ -41,6 +41,7 @@ Please read the [exchange specific notes](exchanges.md) to learn about eventual, - [X] [Binance](https://www.binance.com/) - [X] [Bitmart](https://bitmart.com/) +- [X] [BingX](https://bingx.com/invite/0EM9RX) - [X] [Gate.io](https://www.gate.io/ref/6266643) - [X] [HTX](https://www.htx.com/) (Former Huobi) - [X] [Kraken](https://kraken.com/) diff --git a/docs/stoploss.md b/docs/stoploss.md index a1095b465..e0353d4da 100644 --- a/docs/stoploss.md +++ b/docs/stoploss.md @@ -30,6 +30,7 @@ The Order-type will be ignored if only one mode is available. |----------|-------------| | Binance | limit | | Binance Futures | market, limit | +| Bingx | market, limit | | HTX (former Huobi) | limit | | kraken | market, limit | | Gate | limit | diff --git a/freqtrade/commands/build_config_commands.py b/freqtrade/commands/build_config_commands.py index 76f3bb2af..1e771a372 100644 --- a/freqtrade/commands/build_config_commands.py +++ b/freqtrade/commands/build_config_commands.py @@ -113,6 +113,7 @@ def ask_user_config() -> Dict[str, Any]: "choices": [ "binance", "binanceus", + "bingx", "gate", "htx", "kraken", @@ -128,7 +129,7 @@ def ask_user_config() -> Dict[str, Any]: "message": "Do you want to trade Perpetual Swaps (perpetual futures)?", "default": False, "filter": lambda val: "futures" if val else "spot", - "when": lambda x: x["exchange_name"] in ["binance", "gate", "okx"], + "when": lambda x: x["exchange_name"] in ["binance", "gate", "okx", "bybit"], }, { "type": "autocomplete", diff --git a/freqtrade/exchange/bingx.py b/freqtrade/exchange/bingx.py index 4efd621e8..2d81643a1 100644 --- a/freqtrade/exchange/bingx.py +++ b/freqtrade/exchange/bingx.py @@ -17,6 +17,7 @@ class Bingx(Exchange): _ft_has: Dict = { "ohlcv_candle_limit": 1000, - "stoploss_on_exchange": False, + "stoploss_on_exchange": True, "stoploss_order_types": {"limit": "limit", "market": "market"}, + "order_time_in_force": ["GTC", "IOC", "PO"], } diff --git a/freqtrade/exchange/common.py b/freqtrade/exchange/common.py index 5035d0dd8..99f891836 100644 --- a/freqtrade/exchange/common.py +++ b/freqtrade/exchange/common.py @@ -53,6 +53,7 @@ MAP_EXCHANGE_CHILDCLASS = { SUPPORTED_EXCHANGES = [ "binance", + "bingx", "bitmart", "gate", "htx", diff --git a/requirements.txt b/requirements.txt index 12c02b0b4..399b51337 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,7 +2,7 @@ numpy==1.26.4 pandas==2.2.2 pandas-ta==0.3.14b -ccxt==4.3.27 +ccxt==4.3.30 cryptography==42.0.7 aiohttp==3.9.5 SQLAlchemy==2.0.30 diff --git a/tests/exchange_online/conftest.py b/tests/exchange_online/conftest.py index ee1e8a741..8820ce3e7 100644 --- a/tests/exchange_online/conftest.py +++ b/tests/exchange_online/conftest.py @@ -45,7 +45,25 @@ EXCHANGES = { "workingTime": 1674493798550, "fills": [], "selfTradePreventionMode": "NONE", - } + }, + { + "symbol": "SOLUSDT", + "orderId": 3551312894, + "orderListId": -1, + "clientOrderId": "x-R4DD3S8297c73a11ccb9dc8f2811ba", + "transactTime": 1674493798550, + "price": "15.50000000", + "origQty": "1.10000000", + "executedQty": "1.10000000", + "cummulativeQuoteQty": "17.05", + "status": "FILLED", + "timeInForce": "GTC", + "type": "LIMIT", + "side": "BUY", + "workingTime": 1674493798550, + "fills": [], + "selfTradePreventionMode": "NONE", + }, ], }, "binanceus": { @@ -288,6 +306,36 @@ EXCHANGES = { "hasQuoteVolume": True, "timeframe": "1h", "futures": False, + "sample_order": [ + { + "symbol": "SOL-USDT", + "orderId": "1762393630149869568", + "transactTime": "1674493798550", + "price": "15.5", + "stopPrice": "0", + "origQty": "1.1", + "executedQty": "1.1", + "cummulativeQuoteQty": "17.05", + "status": "FILLED", + "type": "LIMIT", + "side": "BUY", + "clientOrderID": "", + }, + { + "symbol": "SOL-USDT", + "orderId": "1762393630149869568", + "transactTime": "1674493798550", + "price": "15.5", + "stopPrice": "0", + "origQty": "1.1", + "executedQty": "1.1", + "cummulativeQuoteQty": "17.05", + "status": "FILLED", + "type": "MARKET", + "side": "BUY", + "clientOrderID": "", + }, + ], }, } diff --git a/tests/exchange_online/test_ccxt_compat.py b/tests/exchange_online/test_ccxt_compat.py index 6eb9f0023..49fbfc60d 100644 --- a/tests/exchange_online/test_ccxt_compat.py +++ b/tests/exchange_online/test_ccxt_compat.py @@ -76,7 +76,8 @@ class TestCCXTExchange: assert isinstance(po["timestamp"], int) assert isinstance(po["price"], float) assert po["price"] == 15.5 - if po["average"] is not None: + if po["status"] == "closed": + # Filled orders should have average assigned. assert isinstance(po["average"], float) assert po["average"] == 15.5 assert po["symbol"] == pair