-
-
Notifications
You must be signed in to change notification settings - Fork 8k
Funding Fee #5364
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Closed
Closed
Funding Fee #5364
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,11 @@ | ||
# flake8: noqa: F401 | ||
from freqtrade.enums.backteststate import BacktestState | ||
from freqtrade.enums.collateral import Collateral | ||
from freqtrade.enums.interestmode import InterestMode | ||
from freqtrade.enums.liqformula import LiqFormula | ||
from freqtrade.enums.rpcmessagetype import RPCMessageType | ||
from freqtrade.enums.runmode import NON_UTIL_MODES, OPTIMIZE_MODES, TRADING_MODES, RunMode | ||
from freqtrade.enums.selltype import SellType | ||
from freqtrade.enums.signaltype import SignalTagType, SignalType | ||
from freqtrade.enums.state import State | ||
from freqtrade.enums.tradingmode import TradingMode |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
from enum import Enum | ||
|
||
|
||
class Collateral(Enum): | ||
""" | ||
Enum to distinguish between | ||
cross margin/futures collateral and | ||
isolated margin/futures collateral | ||
""" | ||
CROSS = "cross" | ||
ISOLATED = "isolated" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
# from decimal import Decimal | ||
from enum import Enum | ||
|
||
from freqtrade.enums.collateral import Collateral | ||
from freqtrade.enums.tradingmode import TradingMode | ||
from freqtrade.exceptions import OperationalException | ||
|
||
|
||
# from math import ceil | ||
|
||
|
||
class LiqFormula(Enum): | ||
"""Equations to calculate liquidation price""" | ||
|
||
BINANCE = "Binance" | ||
KRAKEN = "Kraken" | ||
FTX = "FTX" | ||
NONE = None | ||
|
||
def __call__(self, **k): | ||
|
||
trading_mode: TradingMode = k['trading_mode'] | ||
if trading_mode == TradingMode.SPOT or self.name == "NONE": | ||
return None | ||
|
||
collateral: Collateral = k['collateral'] | ||
|
||
if self.name == "BINANCE": | ||
return binance(trading_mode, collateral) | ||
elif self.name == "KRAKEN": | ||
return kraken(trading_mode, collateral) | ||
elif self.name == "FTX": | ||
return ftx(trading_mode, collateral) | ||
else: | ||
exception(self.name, trading_mode, collateral) | ||
|
||
|
||
def exception(name: str, trading_mode: TradingMode, collateral: Collateral): | ||
""" | ||
Raises an exception if exchange used doesn't support desired leverage mode | ||
:param name: Name of the exchange | ||
:param trading_mode: spot, margin, futures | ||
:param collateral: cross, isolated | ||
""" | ||
raise OperationalException( | ||
f"{name} does not support {collateral.value} {trading_mode.value} trading") | ||
|
||
|
||
def binance(name: str, trading_mode: TradingMode, collateral: Collateral): | ||
""" | ||
Calculates the liquidation price on Binance | ||
:param name: Name of the exchange | ||
:param trading_mode: spot, margin, futures | ||
:param collateral: cross, isolated | ||
""" | ||
# TODO-lev: Additional arguments, fill in formulas | ||
|
||
if trading_mode == TradingMode.MARGIN and collateral == Collateral.CROSS: | ||
# TODO-lev: perform a calculation based on this formula | ||
# https://www.binance.com/en/support/faq/f6b010588e55413aa58b7d63ee0125ed | ||
exception(name, trading_mode, collateral) | ||
elif trading_mode == TradingMode.FUTURES and collateral == Collateral.CROSS: | ||
# TODO-lev: perform a calculation based on this formula | ||
# https://www.binance.com/en/support/faq/b3c689c1f50a44cabb3a84e663b81d93 | ||
exception(name, trading_mode, collateral) | ||
elif trading_mode == TradingMode.FUTURES and collateral == Collateral.ISOLATED: | ||
# TODO-lev: perform a calculation based on this formula | ||
# https://www.binance.com/en/support/faq/b3c689c1f50a44cabb3a84e663b81d93 | ||
exception(name, trading_mode, collateral) | ||
|
||
# If nothing was returned | ||
exception(name, trading_mode, collateral) | ||
|
||
|
||
def kraken(name: str, trading_mode: TradingMode, collateral: Collateral): | ||
""" | ||
Calculates the liquidation price on Kraken | ||
:param name: Name of the exchange | ||
:param trading_mode: spot, margin, futures | ||
:param collateral: cross, isolated | ||
""" | ||
# TODO-lev: Additional arguments, fill in formulas | ||
|
||
if collateral == Collateral.CROSS: | ||
if trading_mode == TradingMode.MARGIN: | ||
exception(name, trading_mode, collateral) | ||
# TODO-lev: perform a calculation based on this formula | ||
# https://support.kraken.com/hc/en-us/articles/203325763-Margin-Call-Level-and-Margin-Liquidation-Level | ||
elif trading_mode == TradingMode.FUTURES: | ||
exception(name, trading_mode, collateral) | ||
|
||
# If nothing was returned | ||
exception(name, trading_mode, collateral) | ||
|
||
|
||
def ftx(name: str, trading_mode: TradingMode, collateral: Collateral): | ||
""" | ||
Calculates the liquidation price on FTX | ||
:param name: Name of the exchange | ||
:param trading_mode: spot, margin, futures | ||
:param collateral: cross, isolated | ||
""" | ||
if collateral == Collateral.CROSS: | ||
# TODO-lev: Additional arguments, fill in formulas | ||
exception(name, trading_mode, collateral) | ||
|
||
# If nothing was returned | ||
exception(name, trading_mode, collateral) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
from enum import Enum | ||
|
||
|
||
class TradingMode(Enum): | ||
""" | ||
Enum to distinguish between | ||
spot, margin, futures or any other trading method | ||
""" | ||
SPOT = "spot" | ||
MARGIN = "margin" | ||
FUTURES = "futures" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
# flake8: noqa: F401 | ||
from freqtrade.leverage.funding_fee import FundingFee |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
from datetime import datetime, timedelta | ||
from typing import List | ||
|
||
import schedule | ||
|
||
from freqtrade.persistence import Trade | ||
|
||
|
||
class FundingFee: | ||
|
||
trades: List[Trade] | ||
begin_times = [ | ||
# TODO-lev: Make these UTC time | ||
"23:59:45", | ||
"07:59:45", | ||
"15:59:45", | ||
] | ||
|
||
def _is_time_between(self, begin_time, end_time): | ||
# If check time is not given, default to current UTC time | ||
check_time = datetime.utcnow().time() | ||
if begin_time < end_time: | ||
return check_time >= begin_time and check_time <= end_time | ||
else: # crosses midnight | ||
return check_time >= begin_time or check_time <= end_time | ||
|
||
def _apply_funding_fees(self, num_of: int = 1): | ||
if num_of == 0: | ||
return | ||
for trade in self.trades: | ||
trade.adjust_funding_fee(self._calculate(trade.amount) * num_of) | ||
|
||
def _calculate(self, amount): | ||
# TODO-futures: implement | ||
# TODO-futures: Check how other exchages do it and adjust accordingly | ||
# https://www.binance.com/en/support/faq/360033525031 | ||
# mark_price = | ||
# contract_size = maybe trade.amount | ||
# funding_rate = # https://www.binance.com/en/futures/funding-history/0 | ||
# nominal_value = mark_price * contract_size | ||
# adjustment = nominal_value * funding_rate | ||
# return adjustment | ||
return | ||
|
||
def initial_funding_fee(self, amount) -> float: | ||
# A funding fee interval is applied immediately if within 30s of an iterval | ||
for begin_string in self.begin_times: | ||
begin_time = datetime.strptime(begin_string, "%H:%M:%S") | ||
end_time = (begin_time + timedelta(seconds=30)) | ||
if self._is_time_between(begin_time.time(), end_time.time()): | ||
return self._calculate(amount) | ||
return 0.0 | ||
|
||
def start(self): | ||
for interval in self.begin_times: | ||
schedule.every().day.at(interval).do(self._apply_funding_fees()) | ||
|
||
# https://stackoverflow.com/a/30393162/6331353 | ||
# TODO-futures: Put schedule.run_pending() somewhere in the bot_loop | ||
|
||
def reboot(self): | ||
# TODO-futures Find out how many begin_times have passed since last funding_fee added | ||
amount_missed = 0 | ||
self.apply_funding_fees(num_of=amount_missed) | ||
self.start() | ||
|
||
def add_new_trade(self, trade): | ||
self.trades.append(trade) | ||
|
||
def remove_trade(self, trade): | ||
self.trades.remove(trade) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.