Merge pull request #12059 from freqtrade/feat/bitget

Add bitget base support
This commit is contained in:
Matthias
2025-08-03 09:47:19 +02:00
committed by GitHub
5 changed files with 108 additions and 0 deletions

View File

@@ -328,6 +328,22 @@ It's therefore required to pass the UID as well.
!!! Warning "Necessary Verification" !!! Warning "Necessary Verification"
Bitmart requires Verification Lvl2 to successfully trade on the spot market through the API - even though trading via UI works just fine with just Lvl1 verification. Bitmart requires Verification Lvl2 to successfully trade on the spot market through the API - even though trading via UI works just fine with just Lvl1 verification.
## Bitget
Bitget requires a passphrase for each api key, you will therefore need to add this key into the configuration so your exchange section looks as follows:
```json
"exchange": {
"name": "bitget",
"key": "your_exchange_key",
"secret": "your_exchange_secret",
"password": "your_exchange_api_key_password",
// ...
}
```
Bitget supports [time_in_force](configuration.md#understand-order_time_in_force).
## Hyperliquid ## Hyperliquid
!!! Tip "Stoploss on Exchange" !!! Tip "Stoploss on Exchange"

View File

@@ -6,6 +6,7 @@ from freqtrade.exchange.exchange import Exchange
# isort: on # isort: on
from freqtrade.exchange.binance import Binance from freqtrade.exchange.binance import Binance
from freqtrade.exchange.bingx import Bingx from freqtrade.exchange.bingx import Bingx
from freqtrade.exchange.bitget import Bitget
from freqtrade.exchange.bitmart import Bitmart from freqtrade.exchange.bitmart import Bitmart
from freqtrade.exchange.bitpanda import Bitpanda from freqtrade.exchange.bitpanda import Bitpanda
from freqtrade.exchange.bitvavo import Bitvavo from freqtrade.exchange.bitvavo import Bitvavo

View File

@@ -0,0 +1,52 @@
import logging
from datetime import timedelta
from freqtrade.enums import CandleType
from freqtrade.exchange import Exchange
from freqtrade.exchange.exchange_types import FtHas
from freqtrade.util.datetime_helpers import dt_now, dt_ts
logger = logging.getLogger(__name__)
class Bitget(Exchange):
"""
Bitget exchange class. Contains adjustments needed for Freqtrade to work
with this exchange.
Please note that this exchange is not included in the list of exchanges
officially supported by the Freqtrade development team. So some features
may still not work as expected.
"""
_ft_has: FtHas = {
"ohlcv_candle_limit": 200, # 200 for historical candles, 1000 for recent ones.
"order_time_in_force": ["GTC", "FOK", "IOC", "PO"],
}
_ft_has_futures: FtHas = {
"mark_ohlcv_timeframe": "4h",
}
def ohlcv_candle_limit(
self, timeframe: str, candle_type: CandleType, since_ms: int | None = None
) -> int:
"""
Exchange ohlcv candle limit
bitget has the following behaviour:
* 1000 candles for up-to-date data
* 200 candles for historic data (prior to a certain date)
:param timeframe: Timeframe to check
:param candle_type: Candle-type
:param since_ms: Starting timestamp
:return: Candle limit as integer
"""
timeframe_map = self._api.options["fetchOHLCV"]["maxRecentDaysPerTimeframe"]
days = timeframe_map.get(timeframe, 30)
if candle_type in (CandleType.FUTURES, CandleType.SPOT) and (
not since_ms or dt_ts(dt_now() - timedelta(days=days)) < since_ms
):
return 1000
return super().ohlcv_candle_limit(timeframe, candle_type, since_ms)

View File

@@ -408,6 +408,13 @@ EXCHANGES = {
"candle_count": 200, "candle_count": 200,
"orderbook_max_entries": 50, "orderbook_max_entries": 50,
}, },
"bitget": {
"pair": "BTC/USDT",
"stake_currency": "USDT",
"hasQuoteVolume": True,
"timeframe": "1h",
"candle_count": 1000,
},
"htx": { "htx": {
"pair": "ETH/BTC", "pair": "ETH/BTC",
"stake_currency": "BTC", "stake_currency": "BTC",

View File

@@ -521,3 +521,35 @@ class TestCCXTExchange:
exch, exchangename = exchange exch, exchangename = exchange
for method in EXCHANGES[exchangename].get("private_methods", []): for method in EXCHANGES[exchangename].get("private_methods", []):
assert hasattr(exch._api, method) assert hasattr(exch._api, method)
def test_ccxt_bitget_ohlcv_candle_limit(self, exchange: EXCHANGE_FIXTURE_TYPE):
exch, exchangename = exchange
if exchangename != "bitget":
pytest.skip("This test is only for the Bitget exchange")
timeframes = ("1m", "5m", "1h")
for timeframe in timeframes:
assert exch.ohlcv_candle_limit(timeframe, CandleType.SPOT) == 1000
assert exch.ohlcv_candle_limit(timeframe, CandleType.FUTURES) == 1000
assert exch.ohlcv_candle_limit(timeframe, CandleType.MARK) == 200
assert exch.ohlcv_candle_limit(timeframe, CandleType.FUNDING_RATE) == 200
start_time = dt_ts(dt_now() - timedelta(days=17))
assert exch.ohlcv_candle_limit(timeframe, CandleType.SPOT, start_time) == 1000
assert exch.ohlcv_candle_limit(timeframe, CandleType.FUTURES, start_time) == 1000
assert exch.ohlcv_candle_limit(timeframe, CandleType.MARK, start_time) == 200
assert exch.ohlcv_candle_limit(timeframe, CandleType.FUNDING_RATE, start_time) == 200
start_time = dt_ts(dt_now() - timedelta(days=48))
length = 200 if timeframe in ("1m", "5m") else 1000
assert exch.ohlcv_candle_limit(timeframe, CandleType.SPOT, start_time) == length
assert exch.ohlcv_candle_limit(timeframe, CandleType.FUTURES, start_time) == length
assert exch.ohlcv_candle_limit(timeframe, CandleType.MARK, start_time) == 200
assert exch.ohlcv_candle_limit(timeframe, CandleType.FUNDING_RATE, start_time) == 200
start_time = dt_ts(dt_now() - timedelta(days=61))
length = 200
assert exch.ohlcv_candle_limit(timeframe, CandleType.SPOT, start_time) == length
assert exch.ohlcv_candle_limit(timeframe, CandleType.FUTURES, start_time) == length
assert exch.ohlcv_candle_limit(timeframe, CandleType.MARK, start_time) == 200
assert exch.ohlcv_candle_limit(timeframe, CandleType.FUNDING_RATE, start_time) == 200