Added funding_fee method headers to exchange, and implemented some of the methods

This commit is contained in:
Sam Germain
2021-09-09 01:19:24 -06:00
parent d559b6d6c6
commit d54117990b
8 changed files with 78 additions and 25 deletions

View File

@@ -3,12 +3,12 @@ import logging
from typing import Dict, List, Optional
import ccxt
from datetime import time
from freqtrade.exceptions import (DDosProtection, InsufficientFundsError, InvalidOrderException,
OperationalException, TemporaryError)
from freqtrade.exchange import Exchange
from freqtrade.exchange.common import retrier
from freqtrade.utils import hours_to_time
logger = logging.getLogger(__name__)
@@ -23,7 +23,7 @@ class Binance(Exchange):
"trades_pagination_arg": "fromId",
"l2_limit_range": [5, 10, 20, 50, 100, 500, 1000],
}
funding_fee_times: List[time] = hours_to_time([0, 8, 16])
funding_fee_times: List[int] = [0, 8, 16] # hours of the day
def stoploss_adjust(self, stop_loss: float, order: Dict) -> bool:
"""

View File

@@ -7,7 +7,7 @@ import http
import inspect
import logging
from copy import deepcopy
from datetime import datetime, time, timezone
from datetime import datetime, timedelta, timezone
from math import ceil
from typing import Any, Dict, List, Optional, Tuple, Union
@@ -69,7 +69,7 @@ class Exchange:
"l2_limit_range_required": True, # Allow Empty L2 limit (kucoin)
}
_ft_has: Dict = {}
funding_fee_times: List[time] = []
funding_fee_times: List[int] = [] # hours of the day
def __init__(self, config: Dict[str, Any], validate: bool = True) -> None:
"""
@@ -1555,6 +1555,21 @@ class Exchange:
except ccxt.BaseError as e:
raise OperationalException(e) from e
def get_mark_price(self, pair: str, when: datetime):
"""
Get's the value of the underlying asset for a futures contract
at a specific date and time in the past
"""
# TODO-lev: implement
raise OperationalException(f"get_mark_price has not been implemented for {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: implement
raise OperationalException(f"get_funding_rate has not been implemented for {self.name}")
def _get_funding_fee(
self,
contract_size: float,
@@ -1572,6 +1587,45 @@ class Exchange:
"""
raise OperationalException(f"Funding fee has not been implemented for {self.name}")
def get_funding_fee_dates(self, open_date: datetime, close_date: datetime):
"""
Get's the date and time of every funding fee that happened between two datetimes
"""
open_date = datetime(open_date.year, open_date.month, open_date.day, open_date.hour)
close_date = datetime(close_date.year, close_date.month, close_date.day, close_date.hour)
results = []
date_iterator = open_date
while date_iterator < close_date:
date_iterator += timedelta(hours=1)
if date_iterator.hour in self.funding_fee_times:
results.append(date_iterator)
return results
def calculate_funding_fees(
self,
pair: str,
amount: float,
open_date: datetime,
close_date: datetime
) -> float:
"""
calculates the sum of all funding fees that occurred for a pair during a futures trade
:param pair: The quote/base pair of the trade
:param amount: The quantity of the trade
:param open_date: The date and time that the trade started
:param close_date: The date and time that the trade ended
"""
fees: float = 0
for date in self.get_funding_fee_dates(open_date, close_date):
funding_rate = self.get_funding_rate(pair, date)
mark_price = self.get_mark_price(pair, date)
fees += self._get_funding_fee(amount, mark_price, funding_rate)
return fees
def is_exchange_known_ccxt(exchange_name: str, ccxt_module: CcxtModuleType = None) -> bool:
return exchange_name in ccxt_exchanges(ccxt_module)

View File

@@ -3,13 +3,13 @@ import logging
from typing import Any, Dict, List, Optional
import ccxt
from datetime import time
from freqtrade.exceptions import (DDosProtection, InsufficientFundsError, InvalidOrderException,
OperationalException, TemporaryError)
from freqtrade.exchange import Exchange
from freqtrade.exchange.common import API_FETCH_ORDER_RETRY_COUNT, retrier
from freqtrade.misc import safe_value_fallback2
from freqtrade.utils import hours_to_time
logger = logging.getLogger(__name__)
@@ -20,7 +20,7 @@ class Ftx(Exchange):
"stoploss_on_exchange": True,
"ohlcv_candle_limit": 1500,
}
funding_fee_times: List[time] = hours_to_time(list(range(0, 23)))
funding_fee_times: List[int] = list(range(0, 23))
def market_is_tradable(self, market: Dict[str, Any]) -> bool:
"""
@@ -159,9 +159,7 @@ class Ftx(Exchange):
contract_size: float,
mark_price: float,
funding_rate: Optional[float],
# index_price: float,
# interest_rate: float)
):
) -> float:
"""
Calculates a single funding fee
Always paid in USD on FTX # TODO: How do we account for this
@@ -169,5 +167,4 @@ class Ftx(Exchange):
:param mark_price: The price of the asset that the contract is based off of
:param funding_rate: Must be None on ftx
"""
(contract_size * mark_price) / 24
return
return (contract_size * mark_price) / 24

View File

@@ -3,12 +3,12 @@ import logging
from typing import Any, Dict, List
import ccxt
from datetime import time
from freqtrade.exceptions import (DDosProtection, InsufficientFundsError, InvalidOrderException,
OperationalException, TemporaryError)
from freqtrade.exchange import Exchange
from freqtrade.exchange.common import retrier
from freqtrade.utils import hours_to_time
logger = logging.getLogger(__name__)
@@ -22,7 +22,7 @@ class Kraken(Exchange):
"trades_pagination": "id",
"trades_pagination_arg": "since",
}
funding_fee_times: List[time] = hours_to_time([0, 4, 8, 12, 16, 20])
funding_fee_times: List[int] = [0, 4, 8, 12, 16, 20] # hours of the day
def market_is_tradable(self, market: Dict[str, Any]) -> bool:
"""