Removed backtesting funding-fee code
This commit is contained in:
parent
e827ba1388
commit
a8657bb1ce
@ -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:
|
||||||
|
@ -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)
|
||||||
|
@ -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
|
|
||||||
|
@ -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,
|
||||||
|
@ -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 = [
|
||||||
|
@ -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
|
|
||||||
|
@ -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
|
|
||||||
|
Loading…
Reference in New Issue
Block a user