mirror of
https://github.com/freqtrade/freqtrade.git
synced 2025-11-29 16:43:06 +00:00
Merge pull request #12059 from freqtrade/feat/bitget
Add bitget base support
This commit is contained in:
@@ -328,6 +328,22 @@ It's therefore required to pass the UID as well.
|
||||
!!! 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.
|
||||
|
||||
## 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
|
||||
|
||||
!!! Tip "Stoploss on Exchange"
|
||||
|
||||
@@ -6,6 +6,7 @@ from freqtrade.exchange.exchange import Exchange
|
||||
# isort: on
|
||||
from freqtrade.exchange.binance import Binance
|
||||
from freqtrade.exchange.bingx import Bingx
|
||||
from freqtrade.exchange.bitget import Bitget
|
||||
from freqtrade.exchange.bitmart import Bitmart
|
||||
from freqtrade.exchange.bitpanda import Bitpanda
|
||||
from freqtrade.exchange.bitvavo import Bitvavo
|
||||
|
||||
52
freqtrade/exchange/bitget.py
Normal file
52
freqtrade/exchange/bitget.py
Normal 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)
|
||||
@@ -408,6 +408,13 @@ EXCHANGES = {
|
||||
"candle_count": 200,
|
||||
"orderbook_max_entries": 50,
|
||||
},
|
||||
"bitget": {
|
||||
"pair": "BTC/USDT",
|
||||
"stake_currency": "USDT",
|
||||
"hasQuoteVolume": True,
|
||||
"timeframe": "1h",
|
||||
"candle_count": 1000,
|
||||
},
|
||||
"htx": {
|
||||
"pair": "ETH/BTC",
|
||||
"stake_currency": "BTC",
|
||||
|
||||
@@ -521,3 +521,35 @@ class TestCCXTExchange:
|
||||
exch, exchangename = exchange
|
||||
for method in EXCHANGES[exchangename].get("private_methods", []):
|
||||
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
|
||||
|
||||
Reference in New Issue
Block a user