mirror of
https://github.com/freqtrade/freqtrade.git
synced 2025-11-29 00:23:07 +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"
|
!!! 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"
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
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,
|
"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",
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user