gateio, ftx and binance all use same funding fee formula

This commit is contained in:
Sam Germain 2021-10-09 12:49:00 -06:00
parent badc0fa445
commit ef8b617eb2
6 changed files with 14 additions and 90 deletions

View File

@ -1,9 +1,8 @@
""" Binance exchange subclass """ """ Binance exchange subclass """
import json import json
import logging import logging
from datetime import datetime
from pathlib import Path from pathlib import Path
from typing import Any, Dict, List, Optional, Tuple from typing import Dict, List, Optional, Tuple
import arrow import arrow
import ccxt import ccxt
@ -30,13 +29,7 @@ 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 # but the schedule won't check within this timeframe
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()
_supported_trading_mode_collateral_pairs: List[Tuple[TradingMode, Collateral]] = [ _supported_trading_mode_collateral_pairs: List[Tuple[TradingMode, Collateral]] = [
# TradingMode.SPOT always supported and not required in this list # TradingMode.SPOT always supported and not required in this list
@ -218,38 +211,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_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, premium_index: float) -> Optional[float]:
"""
Get's the funding_rate for a pair at a specific date and time in the past
"""
raise OperationalException(f'_get_mark_price has not been implemented on {self.name}')
def _get_funding_fee(
self,
pair: str,
contract_size: float,
mark_price: float,
funding_rate: 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 mark_price is None:
raise OperationalException("Mark price cannot be None for Binance._get_funding_fee")
nominal_value = mark_price * contract_size
if funding_rate is None:
raise OperationalException(
"Funding rate should never be none on Binance._get_funding_fee")
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

@ -1649,17 +1649,19 @@ class Exchange:
self, self,
pair: str, pair: str,
contract_size: float, contract_size: float,
funding_rate: float,
mark_price: float, mark_price: float,
funding_rate: Optional[float]
) -> float: ) -> float:
""" """
Calculates a single funding fee Calculates a single funding fee
:param contract_size: The amount/quanity :param contract_size: The amount/quanity
:param mark_price: The price of the asset that the contract is based off of :param mark_price: The price of the asset that the contract is based off of
:param funding_rate: the interest rate and the premium :param funding_rate: the interest rate and the premium
- interest rate:
- premium: varies by price difference between the perpetual contract and mark price - premium: varies by price difference between the perpetual contract and mark price
""" """
raise OperationalException(f"Funding fee has not been implemented for {self.name}") nominal_value = mark_price * contract_size
return nominal_value * funding_rate
@retrier @retrier
def _set_leverage( def _set_leverage(

View File

@ -1,6 +1,5 @@
""" FTX exchange subclass """ """ FTX exchange subclass """
import logging import logging
from datetime import datetime
from typing import Any, Dict, List, Optional, Tuple from typing import Any, Dict, List, Optional, Tuple
import ccxt import ccxt
@ -184,25 +183,3 @@ 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_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

@ -342,14 +342,6 @@ def test__set_leverage_binance(mocker, default_conf):
) )
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

@ -3292,3 +3292,11 @@ def test_get_funding_fee_dates():
def test_calculate_funding_fees(): def test_calculate_funding_fees():
return return
def test__get_funding_rate(default_conf, mocker):
return
def test__get_funding_fee():
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
@ -268,18 +267,3 @@ def test_fill_leverage_brackets_ftx(default_conf, mocker):
exchange = get_patched_exchange(mocker, default_conf, id="ftx") exchange = get_patched_exchange(mocker, default_conf, id="ftx")
exchange.fill_leverage_brackets() exchange.fill_leverage_brackets()
assert exchange._leverage_brackets == {} assert exchange._leverage_brackets == {}
@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