Removed backtesting funding-fee code

This commit is contained in:
Sam Germain 2021-09-16 03:36:48 -06:00
parent e827ba1388
commit a8657bb1ce
7 changed files with 2 additions and 195 deletions

View File

@ -1,7 +1,6 @@
""" Binance exchange subclass """ """ Binance exchange subclass """
import logging import logging
from datetime import datetime from typing import Dict, List
from typing import Any, Dict, List, Optional
import arrow import arrow
import ccxt import ccxt
@ -27,13 +26,6 @@ class Binance(Exchange):
"l2_limit_range": [5, 10, 20, 50, 100, 500, 1000], "l2_limit_range": [5, 10, 20, 50, 100, 500, 1000],
} }
funding_fee_times: List[int] = [0, 8, 16] # hours of the day funding_fee_times: List[int] = [0, 8, 16] # hours of the day
_funding_interest_rates: Dict = {} # TODO-lev: delete
def __init__(self, config: Dict[str, Any], validate: bool = True) -> None:
super().__init__(config, validate)
# TODO-lev: Uncomment once lev-exchange merged in
# if self.trading_mode == TradingMode.FUTURES:
# self._funding_interest_rates = self._get_funding_interest_rates()
def stoploss_adjust(self, stop_loss: float, order: Dict) -> bool: def stoploss_adjust(self, stop_loss: float, order: Dict) -> bool:
""" """
@ -101,51 +93,6 @@ class Binance(Exchange):
except ccxt.BaseError as e: except ccxt.BaseError as e:
raise OperationalException(e) from e raise OperationalException(e) from e
def _get_premium_index(self, pair: str, date: datetime) -> float:
raise OperationalException(f'_get_premium_index has not been implemented on {self.name}')
def _get_mark_price(self, pair: str, date: datetime) -> float:
raise OperationalException(f'_get_mark_price has not been implemented on {self.name}')
def _get_funding_interest_rates(self):
rates = self._api.fetch_funding_rates()
interest_rates = {}
for pair, data in rates.items():
interest_rates[pair] = data['interestRate']
return interest_rates
def _calculate_funding_rate(self, pair: str, premium_index: float) -> Optional[float]:
"""
Get's the funding_rate for a pair at a specific date and time in the past
"""
return (
premium_index +
max(min(self._funding_interest_rates[pair] - premium_index, 0.0005), -0.0005)
)
def _get_funding_fee(
self,
pair: str,
contract_size: float,
mark_price: float,
premium_index: Optional[float],
) -> float:
"""
Calculates a single funding fee
:param contract_size: The amount/quanity
:param mark_price: The price of the asset that the contract is based off of
:param funding_rate: the interest rate and the premium
- interest rate: 0.03% daily, BNBUSDT, LINKUSDT, and LTCUSDT are 0%
- premium: varies by price difference between the perpetual contract and mark price
"""
if premium_index is None:
raise OperationalException("Premium index cannot be None for Binance._get_funding_fee")
nominal_value = mark_price * contract_size
funding_rate = self._calculate_funding_rate(pair, premium_index)
if funding_rate is None:
raise OperationalException("Funding rate should never be none on Binance")
return nominal_value * funding_rate
async def _async_get_historic_ohlcv(self, pair: str, timeframe: str, async def _async_get_historic_ohlcv(self, pair: str, timeframe: str,
since_ms: int, is_new_pair: bool since_ms: int, is_new_pair: bool
) -> List: ) -> List:

View File

@ -1529,14 +1529,6 @@ class Exchange:
self._async_get_trade_history(pair=pair, since=since, self._async_get_trade_history(pair=pair, since=since,
until=until, from_id=from_id)) until=until, from_id=from_id))
# https://www.binance.com/en/support/faq/360033525031
def fetch_funding_rate(self, pair):
if not self.exchange_has("fetchFundingHistory"):
raise OperationalException(
f"fetch_funding_history() has not been implemented on ccxt.{self.name}")
return self._api.fetch_funding_rates()
@retrier @retrier
def get_funding_fees_from_exchange(self, pair: str, since: Union[datetime, int]) -> float: def get_funding_fees_from_exchange(self, pair: str, since: Union[datetime, int]) -> float:
""" """
@ -1567,37 +1559,6 @@ class Exchange:
except ccxt.BaseError as e: except ccxt.BaseError as e:
raise OperationalException(e) from e raise OperationalException(e) from e
def _get_premium_index(self, pair: str, date: datetime) -> float:
raise OperationalException(f'_get_premium_index has not been implemented on {self.name}')
def _get_mark_price(self, pair: str, date: datetime) -> float:
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: implement
raise OperationalException(f"get_funding_rate has not been implemented for {self.name}")
def _get_funding_fee(
self,
pair: str,
contract_size: float,
mark_price: float,
premium_index: Optional[float],
# index_price: float,
# interest_rate: float)
) -> float:
"""
Calculates a single funding fee
:param contract_size: The amount/quanity
:param mark_price: The price of the asset that the contract is based off of
:param funding_rate: the interest rate and the premium
- premium: varies by price difference between the perpetual contract and mark price
"""
raise OperationalException(f"Funding fee has not been implemented for {self.name}")
def _get_funding_fee_dates(self, open_date: datetime, close_date: datetime): 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 Get's the date and time of every funding fee that happened between two datetimes
@ -1614,34 +1575,6 @@ class Exchange:
return results 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):
premium_index = self._get_premium_index(pair, date)
mark_price = self._get_mark_price(pair, date)
fees += self._get_funding_fee(
pair=pair,
contract_size=amount,
mark_price=mark_price,
premium_index=premium_index
)
return fees
def is_exchange_known_ccxt(exchange_name: str, ccxt_module: CcxtModuleType = None) -> bool: def is_exchange_known_ccxt(exchange_name: str, ccxt_module: CcxtModuleType = None) -> bool:
return exchange_name in ccxt_exchanges(ccxt_module) return exchange_name in ccxt_exchanges(ccxt_module)

View File

@ -1,7 +1,6 @@
""" FTX exchange subclass """ """ FTX exchange subclass """
import logging import logging
from datetime import datetime from typing import Any, Dict, List
from typing import Any, Dict, List, Optional
import ccxt import ccxt
@ -154,25 +153,3 @@ class Ftx(Exchange):
if order['type'] == 'stop': if order['type'] == 'stop':
return safe_value_fallback2(order, order, 'id_stop', 'id') return safe_value_fallback2(order, order, 'id_stop', 'id')
return order['id'] return order['id']
def _get_funding_rate(self, pair: str, when: datetime) -> Optional[float]:
"""FTX doesn't use this"""
return None
def _get_funding_fee(
self,
pair: str,
contract_size: float,
mark_price: float,
premium_index: 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
: param contract_size: The amount/quanity
: param mark_price: The price of the asset that the contract is based off of
: param funding_rate: Must be None on ftx
"""
return (contract_size * mark_price) / 24

View File

@ -707,7 +707,6 @@ class LocalTrade():
return float(self._calc_base_close(amount, rate, fee) - total_interest) return float(self._calc_base_close(amount, rate, fee) - total_interest)
elif (trading_mode == TradingMode.FUTURES): elif (trading_mode == TradingMode.FUTURES):
self.add_funding_fees()
funding_fees = self.funding_fees or 0.0 funding_fees = self.funding_fees or 0.0
return float(self._calc_base_close(amount, rate, fee)) + funding_fees return float(self._calc_base_close(amount, rate, fee)) + funding_fees
else: else:
@ -786,19 +785,6 @@ class LocalTrade():
else: else:
return None return None
def add_funding_fees(self):
if self.trading_mode == TradingMode.FUTURES:
# TODO-lev: Calculate this correctly and add it
# if self.config['runmode'].value in ('backtest', 'hyperopt'):
# self.funding_fees = getattr(Exchange, self.exchange).calculate_funding_fees(
# self.exchange,
# self.pair,
# self.amount,
# self.open_date_utc,
# self.close_date_utc
# )
return
@staticmethod @staticmethod
def get_trades_proxy(*, pair: str = None, is_open: bool = None, def get_trades_proxy(*, pair: str = None, is_open: bool = None,
open_date: datetime = None, close_date: datetime = None, open_date: datetime = None, close_date: datetime = None,

View File

@ -108,14 +108,6 @@ def test_stoploss_adjust_binance(mocker, default_conf):
assert not exchange.stoploss_adjust(1501, order) assert not exchange.stoploss_adjust(1501, order)
def test_get_funding_rate():
return
def test__get_funding_fee():
return
@pytest.mark.asyncio @pytest.mark.asyncio
async def test__async_get_historic_ohlcv_binance(default_conf, mocker, caplog): async def test__async_get_historic_ohlcv_binance(default_conf, mocker, caplog):
ohlcv = [ ohlcv = [

View File

@ -3044,15 +3044,3 @@ def test_get_funding_fees(default_conf, mocker, exchange_name):
pair="XRP/USDT", pair="XRP/USDT",
since=unix_time since=unix_time
) )
def test_get_mark_price():
return
def test_get_funding_fee_dates():
return
def test_calculate_funding_fees():
return

View File

@ -1,4 +1,3 @@
from datetime import datetime, timedelta
from random import randint from random import randint
from unittest.mock import MagicMock from unittest.mock import MagicMock
@ -192,18 +191,3 @@ def test_get_order_id(mocker, default_conf):
} }
} }
assert exchange.get_order_id_conditional(order) == '1111' assert exchange.get_order_id_conditional(order) == '1111'
@pytest.mark.parametrize("pair,when", [
('XRP/USDT', datetime.utcnow()),
('ADA/BTC', datetime.utcnow()),
('XRP/USDT', datetime.utcnow() - timedelta(hours=30)),
])
def test__get_funding_rate(default_conf, mocker, pair, when):
api_mock = MagicMock()
exchange = get_patched_exchange(mocker, default_conf, api_mock, id="ftx")
assert exchange._get_funding_rate(pair, when) is None
def test__get_funding_fee():
return