Added dry run capability to funding-fee
This commit is contained in:
parent
2533d3b420
commit
3eda9455b9
@ -1636,23 +1636,8 @@ class Exchange:
|
|||||||
except ccxt.BaseError as e:
|
except ccxt.BaseError as e:
|
||||||
raise OperationalException(e) from e
|
raise OperationalException(e) from e
|
||||||
|
|
||||||
def _get_mark_price(self, pair: str, date: datetime) -> float:
|
|
||||||
"""
|
|
||||||
Get's the mark price for a pair at a specific date and time in the past
|
|
||||||
"""
|
|
||||||
# TODO-lev: Can maybe use self._api.fetchFundingRate, or get the most recent candlestick
|
|
||||||
raise OperationalException(f'_get_mark_price has not been implemented on {self.name}')
|
|
||||||
|
|
||||||
def _get_funding_rate(self, pair: str, when: datetime):
|
|
||||||
"""
|
|
||||||
Get's the funding_rate for a pair at a specific date and time in the past
|
|
||||||
"""
|
|
||||||
# TODO-lev: Maybe use self._api.fetchFundingRate or fetchFundingRateHistory with length 1
|
|
||||||
raise OperationalException(f"get_funding_rate has not been implemented for {self.name}")
|
|
||||||
|
|
||||||
def _get_funding_fee(
|
def _get_funding_fee(
|
||||||
self,
|
self,
|
||||||
pair: str,
|
|
||||||
contract_size: float,
|
contract_size: float,
|
||||||
funding_rate: float,
|
funding_rate: float,
|
||||||
mark_price: float,
|
mark_price: float,
|
||||||
@ -1726,12 +1711,39 @@ class Exchange:
|
|||||||
except ccxt.BaseError as e:
|
except ccxt.BaseError as e:
|
||||||
raise OperationalException(e) from e
|
raise OperationalException(e) from e
|
||||||
|
|
||||||
|
def _get_mark_price_history(
|
||||||
|
self,
|
||||||
|
pair: str,
|
||||||
|
start: int,
|
||||||
|
end: Optional[int]
|
||||||
|
) -> Dict:
|
||||||
|
"""
|
||||||
|
Get's the mark price history for a pair
|
||||||
|
"""
|
||||||
|
if end:
|
||||||
|
params = {
|
||||||
|
'endTime': end
|
||||||
|
}
|
||||||
|
else:
|
||||||
|
params = {}
|
||||||
|
|
||||||
|
candles = self._api.fetch_mark_ohlcv(
|
||||||
|
pair,
|
||||||
|
timeframe="1h",
|
||||||
|
since=start,
|
||||||
|
params=params
|
||||||
|
)
|
||||||
|
history = {}
|
||||||
|
for candle in candles:
|
||||||
|
history[candle[0]] = candle[1]
|
||||||
|
return history
|
||||||
|
|
||||||
def calculate_funding_fees(
|
def calculate_funding_fees(
|
||||||
self,
|
self,
|
||||||
pair: str,
|
pair: str,
|
||||||
amount: float,
|
amount: float,
|
||||||
open_date: datetime,
|
open_date: datetime,
|
||||||
close_date: datetime
|
close_date: Optional[datetime]
|
||||||
) -> float:
|
) -> float:
|
||||||
"""
|
"""
|
||||||
calculates the sum of all funding fees that occurred for a pair during a futures trade
|
calculates the sum of all funding fees that occurred for a pair during a futures trade
|
||||||
@ -1742,11 +1754,22 @@ class Exchange:
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
fees: float = 0
|
fees: float = 0
|
||||||
|
if close_date:
|
||||||
|
close_date_timestamp: Optional[int] = int(close_date.timestamp())
|
||||||
|
funding_rate_history = self.get_funding_rate_history(
|
||||||
|
pair,
|
||||||
|
int(open_date.timestamp()),
|
||||||
|
close_date_timestamp
|
||||||
|
)
|
||||||
|
mark_price_history = self._get_mark_price_history(
|
||||||
|
pair,
|
||||||
|
int(open_date.timestamp()),
|
||||||
|
close_date_timestamp
|
||||||
|
)
|
||||||
for date in self._get_funding_fee_dates(open_date, close_date):
|
for date in self._get_funding_fee_dates(open_date, close_date):
|
||||||
funding_rate = self._get_funding_rate(pair, date)
|
funding_rate = funding_rate_history[date.timestamp]
|
||||||
mark_price = self._get_mark_price(pair, date)
|
mark_price = mark_price_history[date.timestamp]
|
||||||
fees += self._get_funding_fee(
|
fees += self._get_funding_fee(
|
||||||
pair=pair,
|
|
||||||
contract_size=amount,
|
contract_size=amount,
|
||||||
mark_price=mark_price,
|
mark_price=mark_price,
|
||||||
funding_rate=funding_rate
|
funding_rate=funding_rate
|
||||||
@ -1756,10 +1779,12 @@ class Exchange:
|
|||||||
|
|
||||||
def get_funding_rate_history(
|
def get_funding_rate_history(
|
||||||
self,
|
self,
|
||||||
|
pair: str,
|
||||||
start: int,
|
start: int,
|
||||||
end: int
|
end: Optional[int] = None
|
||||||
) -> Dict:
|
) -> Dict:
|
||||||
'''
|
'''
|
||||||
|
:param pair: quote/base currency pair
|
||||||
:param start: timestamp in ms of the beginning time
|
:param start: timestamp in ms of the beginning time
|
||||||
:param end: timestamp in ms of the end time
|
:param end: timestamp in ms of the end time
|
||||||
'''
|
'''
|
||||||
@ -1771,19 +1796,14 @@ class Exchange:
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
funding_history: Dict = {}
|
funding_history: Dict = {}
|
||||||
for pair, market in self.markets.items():
|
response = self._api.fetch_funding_rate_history(
|
||||||
if market['swap']:
|
pair,
|
||||||
response = self._api.fetch_funding_rate_history(
|
limit=1000,
|
||||||
pair,
|
start=start,
|
||||||
limit=1000,
|
end=end
|
||||||
since=start,
|
)
|
||||||
params={
|
for fund in response:
|
||||||
'endTime': end
|
funding_history[fund['timestamp']] = fund['fundingRate']
|
||||||
}
|
|
||||||
)
|
|
||||||
funding_history[pair] = {}
|
|
||||||
for fund in response:
|
|
||||||
funding_history[pair][fund['timestamp']] = fund['funding_rate']
|
|
||||||
return funding_history
|
return funding_history
|
||||||
except ccxt.DDoSProtection as e:
|
except ccxt.DDoSProtection as e:
|
||||||
raise DDosProtection(e) from e
|
raise DDosProtection(e) from e
|
||||||
|
@ -183,3 +183,30 @@ class Ftx(Exchange):
|
|||||||
:nominal_value: Here for super method, not used on FTX
|
:nominal_value: Here for super method, not used on FTX
|
||||||
"""
|
"""
|
||||||
return 20.0
|
return 20.0
|
||||||
|
|
||||||
|
def _get_mark_price_history(
|
||||||
|
self,
|
||||||
|
pair: str,
|
||||||
|
start: int,
|
||||||
|
end: Optional[int]
|
||||||
|
) -> Dict:
|
||||||
|
"""
|
||||||
|
Get's the mark price history for a pair
|
||||||
|
"""
|
||||||
|
if end:
|
||||||
|
params = {
|
||||||
|
'endTime': end
|
||||||
|
}
|
||||||
|
else:
|
||||||
|
params = {}
|
||||||
|
|
||||||
|
candles = self._api.fetch_index_ohlcv(
|
||||||
|
pair,
|
||||||
|
timeframe="1h",
|
||||||
|
since=start,
|
||||||
|
params=params
|
||||||
|
)
|
||||||
|
history = {}
|
||||||
|
for candle in candles:
|
||||||
|
history[candle[0]] = candle[1]
|
||||||
|
return history
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
""" Gate.io exchange subclass """
|
""" Gate.io exchange subclass """
|
||||||
import logging
|
import logging
|
||||||
from typing import Dict, List
|
from typing import Dict, List, Optional
|
||||||
|
|
||||||
from freqtrade.exceptions import OperationalException
|
from freqtrade.exceptions import OperationalException
|
||||||
from freqtrade.exchange import Exchange
|
from freqtrade.exchange import Exchange
|
||||||
@ -36,12 +36,13 @@ class Gateio(Exchange):
|
|||||||
|
|
||||||
def get_funding_rate_history(
|
def get_funding_rate_history(
|
||||||
self,
|
self,
|
||||||
|
pair: str,
|
||||||
start: int,
|
start: int,
|
||||||
end: int
|
end: Optional[int] = None
|
||||||
) -> Dict:
|
) -> Dict:
|
||||||
'''
|
'''
|
||||||
:param start: timestamp in ms of the beginning time
|
:param start: timestamp in ms of the beginning time
|
||||||
:param end: timestamp in ms of the end time
|
:param end: timestamp in ms of the end time
|
||||||
'''
|
'''
|
||||||
# TODO-lev: Has a max limit into the past of 333 days
|
# TODO-lev: Has a max limit into the past of 333 days
|
||||||
return super().get_funding_rate_history(start, end)
|
return super().get_funding_rate_history(pair, start, end)
|
||||||
|
@ -269,10 +269,17 @@ class FreqtradeBot(LoggingMixin):
|
|||||||
def update_funding_fees(self):
|
def update_funding_fees(self):
|
||||||
if self.trading_mode == TradingMode.FUTURES:
|
if self.trading_mode == TradingMode.FUTURES:
|
||||||
for trade in Trade.get_open_trades():
|
for trade in Trade.get_open_trades():
|
||||||
funding_fees = self.exchange.get_funding_fees_from_exchange(
|
if self.config['dry_run']:
|
||||||
trade.pair,
|
funding_fees = self.exchange.calculate_funding_fees(
|
||||||
trade.open_date
|
trade.pair,
|
||||||
)
|
trade.amount,
|
||||||
|
trade.open_date
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
funding_fees = self.exchange.get_funding_fees_from_exchange(
|
||||||
|
trade.pair,
|
||||||
|
trade.open_date
|
||||||
|
)
|
||||||
trade.funding_fees = funding_fees
|
trade.funding_fees = funding_fees
|
||||||
|
|
||||||
def startup_update_open_orders(self):
|
def startup_update_open_orders(self):
|
||||||
|
@ -3,7 +3,6 @@
|
|||||||
"""
|
"""
|
||||||
This module contains the backtesting logic
|
This module contains the backtesting logic
|
||||||
"""
|
"""
|
||||||
import ccxt
|
|
||||||
import logging
|
import logging
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
from copy import deepcopy
|
from copy import deepcopy
|
||||||
@ -127,10 +126,6 @@ class Backtesting:
|
|||||||
self.progress = BTProgress()
|
self.progress = BTProgress()
|
||||||
self.abort = False
|
self.abort = False
|
||||||
|
|
||||||
self.funding_rate_history = getattr(ccxt, self._exchange_name).load_funding_rate_history(
|
|
||||||
self.timerange.startts,
|
|
||||||
self.timerange.stopts
|
|
||||||
)
|
|
||||||
self.init_backtest()
|
self.init_backtest()
|
||||||
|
|
||||||
def __del__(self):
|
def __del__(self):
|
||||||
|
Loading…
Reference in New Issue
Block a user