Merge branch 'feat/short' into lev-freqtradebot
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
""" Bibox exchange subclass """
|
||||
import logging
|
||||
from typing import Dict
|
||||
from typing import Dict, List
|
||||
|
||||
from freqtrade.exchange import Exchange
|
||||
|
||||
@@ -24,3 +24,5 @@ class Bibox(Exchange):
|
||||
def _ccxt_config(self) -> Dict:
|
||||
# Parameters to add directly to ccxt sync/async initialization.
|
||||
return {"has": {"fetchCurrencies": False}}
|
||||
|
||||
funding_fee_times: List[int] = [0, 8, 16] # hours of the day
|
||||
|
@@ -28,6 +28,8 @@ class Binance(Exchange):
|
||||
"trades_pagination_arg": "fromId",
|
||||
"l2_limit_range": [5, 10, 20, 50, 100, 500, 1000],
|
||||
}
|
||||
funding_fee_times: List[int] = [0, 8, 16] # hours of the day
|
||||
# but the schedule won't check within this timeframe
|
||||
|
||||
_supported_trading_mode_collateral_pairs: List[Tuple[TradingMode, Collateral]] = [
|
||||
# TradingMode.SPOT always supported and not required in this list
|
||||
|
@@ -1,7 +1,8 @@
|
||||
""" Bybit exchange subclass """
|
||||
import logging
|
||||
from typing import Dict
|
||||
from typing import Dict, List, Tuple
|
||||
|
||||
from freqtrade.enums import Collateral, TradingMode
|
||||
from freqtrade.exchange import Exchange
|
||||
|
||||
|
||||
@@ -21,3 +22,11 @@ class Bybit(Exchange):
|
||||
_ft_has: Dict = {
|
||||
"ohlcv_candle_limit": 200,
|
||||
}
|
||||
|
||||
funding_fee_times: List[int] = [0, 8, 16] # hours of the day
|
||||
|
||||
_supported_trading_mode_collateral_pairs: List[Tuple[TradingMode, Collateral]] = [
|
||||
# TradingMode.SPOT always supported and not required in this list
|
||||
# (TradingMode.FUTURES, Collateral.CROSS), # TODO-lev: Uncomment once supported
|
||||
# (TradingMode.FUTURES, Collateral.ISOLATED) # TODO-lev: Uncomment once supported
|
||||
]
|
||||
|
@@ -9,7 +9,7 @@ import logging
|
||||
from copy import deepcopy
|
||||
from datetime import datetime, timezone
|
||||
from math import ceil
|
||||
from typing import Any, Dict, List, Optional, Tuple
|
||||
from typing import Any, Dict, List, Optional, Tuple, Union
|
||||
|
||||
import arrow
|
||||
import ccxt
|
||||
@@ -72,6 +72,10 @@ class Exchange:
|
||||
}
|
||||
_ft_has: Dict = {}
|
||||
|
||||
# funding_fee_times is currently unused, but should ideally be used to properly
|
||||
# schedule refresh times
|
||||
funding_fee_times: List[int] = [] # hours of the day
|
||||
|
||||
_supported_trading_mode_collateral_pairs: List[Tuple[TradingMode, Collateral]] = [
|
||||
# TradingMode.SPOT always supported and not required in this list
|
||||
]
|
||||
@@ -503,7 +507,7 @@ class Exchange:
|
||||
if startup_candles + 5 > candle_limit:
|
||||
raise OperationalException(
|
||||
f"This strategy requires {startup_candles} candles to start. "
|
||||
f"{self.name} only provides {candle_limit} for {timeframe}.")
|
||||
f"{self.name} only provides {candle_limit - 5} for {timeframe}.")
|
||||
|
||||
def validate_trading_mode_and_collateral(
|
||||
self,
|
||||
@@ -565,7 +569,7 @@ class Exchange:
|
||||
precision = self.markets[pair]['precision']['price']
|
||||
missing = price % precision
|
||||
if missing != 0:
|
||||
price = price - missing + precision
|
||||
price = round(price - missing + precision, 10)
|
||||
else:
|
||||
symbol_prec = self.markets[pair]['precision']['price']
|
||||
big_price = price * pow(10, symbol_prec)
|
||||
@@ -1130,7 +1134,7 @@ class Exchange:
|
||||
ticker_rate = ticker[conf_strategy['price_side']]
|
||||
if ticker['last'] and ticker_rate:
|
||||
if side == 'buy' and ticker_rate > ticker['last']:
|
||||
balance = conf_strategy['ask_last_balance']
|
||||
balance = conf_strategy.get('ask_last_balance', 0.0)
|
||||
ticker_rate = ticker_rate + balance * (ticker['last'] - ticker_rate)
|
||||
elif side == 'sell' and ticker_rate < ticker['last']:
|
||||
balance = conf_strategy.get('bid_last_balance', 0.0)
|
||||
@@ -1600,6 +1604,37 @@ class Exchange:
|
||||
self._async_get_trade_history(pair=pair, since=since,
|
||||
until=until, from_id=from_id))
|
||||
|
||||
@retrier
|
||||
def get_funding_fees_from_exchange(self, pair: str, since: Union[datetime, int]) -> float:
|
||||
"""
|
||||
Returns the sum of all funding fees that were exchanged for a pair within a timeframe
|
||||
:param pair: (e.g. ADA/USDT)
|
||||
:param since: The earliest time of consideration for calculating funding fees,
|
||||
in unix time or as a datetime
|
||||
"""
|
||||
# TODO-lev: Add dry-run handling for this.
|
||||
|
||||
if not self.exchange_has("fetchFundingHistory"):
|
||||
raise OperationalException(
|
||||
f"fetch_funding_history() has not been implemented on ccxt.{self.name}")
|
||||
|
||||
if type(since) is datetime:
|
||||
since = int(since.timestamp()) * 1000 # * 1000 for ms
|
||||
|
||||
try:
|
||||
funding_history = self._api.fetch_funding_history(
|
||||
pair=pair,
|
||||
since=since
|
||||
)
|
||||
return sum(fee['amount'] for fee in funding_history)
|
||||
except ccxt.DDoSProtection as e:
|
||||
raise DDosProtection(e) from e
|
||||
except (ccxt.NetworkError, ccxt.ExchangeError) as e:
|
||||
raise TemporaryError(
|
||||
f'Could not get funding fees due to {e.__class__.__name__}. Message: {e}') from e
|
||||
except ccxt.BaseError as e:
|
||||
raise OperationalException(e) from e
|
||||
|
||||
def fill_leverage_brackets(self):
|
||||
"""
|
||||
# TODO-lev: Should maybe be renamed, leverage_brackets might not be accurate for kraken
|
||||
|
@@ -21,6 +21,7 @@ class Ftx(Exchange):
|
||||
"stoploss_on_exchange": True,
|
||||
"ohlcv_candle_limit": 1500,
|
||||
}
|
||||
funding_fee_times: List[int] = list(range(0, 24))
|
||||
|
||||
_supported_trading_mode_collateral_pairs: List[Tuple[TradingMode, Collateral]] = [
|
||||
# TradingMode.SPOT always supported and not required in this list
|
||||
|
@@ -1,7 +1,8 @@
|
||||
""" Gate.io exchange subclass """
|
||||
import logging
|
||||
from typing import Dict
|
||||
from typing import Dict, List
|
||||
|
||||
from freqtrade.exceptions import OperationalException
|
||||
from freqtrade.exchange import Exchange
|
||||
|
||||
|
||||
@@ -23,3 +24,12 @@ class Gateio(Exchange):
|
||||
}
|
||||
|
||||
_headers = {'X-Gate-Channel-Id': 'freqtrade'}
|
||||
|
||||
funding_fee_times: List[int] = [0, 8, 16] # hours of the day
|
||||
|
||||
def validate_ordertypes(self, order_types: Dict) -> None:
|
||||
super().validate_ordertypes(order_types)
|
||||
|
||||
if any(v == 'market' for k, v in order_types.items()):
|
||||
raise OperationalException(
|
||||
f'Exchange {self.name} does not support market orders.')
|
||||
|
@@ -1,5 +1,5 @@
|
||||
import logging
|
||||
from typing import Dict
|
||||
from typing import Dict, List
|
||||
|
||||
from freqtrade.exchange import Exchange
|
||||
|
||||
@@ -21,3 +21,5 @@ class Hitbtc(Exchange):
|
||||
"ohlcv_candle_limit": 1000,
|
||||
"ohlcv_params": {"sort": "DESC"}
|
||||
}
|
||||
|
||||
funding_fee_times: List[int] = [0, 8, 16] # hours of the day
|
||||
|
@@ -23,6 +23,7 @@ class Kraken(Exchange):
|
||||
"trades_pagination": "id",
|
||||
"trades_pagination_arg": "since",
|
||||
}
|
||||
funding_fee_times: List[int] = [0, 4, 8, 12, 16, 20] # hours of the day
|
||||
|
||||
_supported_trading_mode_collateral_pairs: List[Tuple[TradingMode, Collateral]] = [
|
||||
# TradingMode.SPOT always supported and not required in this list
|
||||
|
@@ -1,6 +1,6 @@
|
||||
""" Kucoin exchange subclass """
|
||||
import logging
|
||||
from typing import Dict
|
||||
from typing import Dict, List
|
||||
|
||||
from freqtrade.exchange import Exchange
|
||||
|
||||
@@ -24,3 +24,5 @@ class Kucoin(Exchange):
|
||||
"order_time_in_force": ['gtc', 'fok', 'ioc'],
|
||||
"time_in_force_parameter": "timeInForce",
|
||||
}
|
||||
|
||||
funding_fee_times: List[int] = [4, 12, 20] # hours of the day
|
||||
|
Reference in New Issue
Block a user