Added dry run capability to funding-fee

This commit is contained in:
Sam Germain 2021-10-22 09:35:50 -06:00
parent 2533d3b420
commit 3eda9455b9
5 changed files with 95 additions and 45 deletions

View File

@ -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():
if market['swap']:
response = self._api.fetch_funding_rate_history( response = self._api.fetch_funding_rate_history(
pair, pair,
limit=1000, limit=1000,
since=start, start=start,
params={ end=end
'endTime': end
}
) )
funding_history[pair] = {}
for fund in response: for fund in response:
funding_history[pair][fund['timestamp']] = fund['funding_rate'] funding_history[fund['timestamp']] = fund['fundingRate']
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

View File

@ -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

View File

@ -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)

View File

@ -269,6 +269,13 @@ 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():
if self.config['dry_run']:
funding_fees = self.exchange.calculate_funding_fees(
trade.pair,
trade.amount,
trade.open_date
)
else:
funding_fees = self.exchange.get_funding_fees_from_exchange( funding_fees = self.exchange.get_funding_fees_from_exchange(
trade.pair, trade.pair,
trade.open_date trade.open_date

View File

@ -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):