Split tradingmode into tradingmode and collateral, moved functions out of liqformula class

This commit is contained in:
Sam Germain 2021-08-02 20:05:48 -06:00
parent 57ba31c09c
commit dd8cce00a4
5 changed files with 117 additions and 89 deletions

View File

@ -1,5 +1,6 @@
# flake8: noqa: F401 # flake8: noqa: F401
from freqtrade.enums.backteststate import BacktestState from freqtrade.enums.backteststate import BacktestState
from freqtrade.enums.collateral import Collateral
from freqtrade.enums.interestmode import InterestMode from freqtrade.enums.interestmode import InterestMode
from freqtrade.enums.liqformula import LiqFormula from freqtrade.enums.liqformula import LiqFormula
from freqtrade.enums.rpcmessagetype import RPCMessageType from freqtrade.enums.rpcmessagetype import RPCMessageType

View File

@ -0,0 +1,9 @@
from enum import Enum
class Collateral(Enum):
"""
Bot application states
"""
CROSS = "cross"
ISOLATED = "isolated"

View File

@ -1,12 +1,14 @@
# from decimal import Decimal # from decimal import Decimal
from enum import Enum from enum import Enum
# from math import ceil
from typing import Optional
from freqtrade.enums.collateral import Collateral
from freqtrade.enums.tradingmode import TradingMode from freqtrade.enums.tradingmode import TradingMode
from freqtrade.exceptions import OperationalException from freqtrade.exceptions import OperationalException
# from math import ceil
class LiqFormula(Enum): class LiqFormula(Enum):
"""Equations to calculate liquidation price""" """Equations to calculate liquidation price"""
@ -15,72 +17,72 @@ class LiqFormula(Enum):
FTX = "FTX" FTX = "FTX"
NONE = None NONE = None
def _exception(self, trading_mode: TradingMode, freq_specific: Optional[bool] = True):
"""
Raises an exception if exchange used doesn't support desired leverage mode
:param trading_mode: cross, isolated, cross_futures or isolated_futures
:param freq_specific:
False if the exchange does not support this leverage mode
True if only freqtrade doesn't support it
"""
if freq_specific:
raise OperationalException(
f"Freqtrade does not support {trading_mode.value} on {self.name}")
else:
raise OperationalException(f"{self.name} does not support {trading_mode.value} trading")
def _binance(self, trading_mode: TradingMode):
# TODO-lev: Additional arguments, fill in formulas
if trading_mode == TradingMode.CROSS_MARGIN:
# TODO-lev: perform a calculation based on this formula
# https://www.binance.com/en/support/faq/f6b010588e55413aa58b7d63ee0125ed
self._exception(trading_mode)
elif trading_mode == TradingMode.ISOLATED_MARGIN:
self._exception(trading_mode) # Likely won't be implemented
elif trading_mode == TradingMode.CROSS_FUTURES:
# TODO-lev: perform a calculation based on this formula
# https://www.binance.com/en/support/faq/b3c689c1f50a44cabb3a84e663b81d93
self._exception(trading_mode)
elif trading_mode == TradingMode.ISOLATED_FUTURES:
# TODO-lev: perform a calculation based on this formula
# https://www.binance.com/en/support/faq/b3c689c1f50a44cabb3a84e663b81d93
self._exception(trading_mode)
else:
self._exception(trading_mode)
def _kraken(self, trading_mode: TradingMode):
# TODO-lev: Additional arguments, fill in formulas
if trading_mode == TradingMode.CROSS_MARGIN:
self._exception(trading_mode)
# 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.CROSS_FUTURES:
# TODO-lev: implement
self._exception(trading_mode)
elif trading_mode == TradingMode.ISOLATED_MARGIN or \
trading_mode == TradingMode.ISOLATED_FUTURES:
self._exception(trading_mode, True)
else:
self._exception(trading_mode)
def _ftx(self, trading_mode: TradingMode):
# TODO-lev: Additional arguments, fill in formulas
self._exception(trading_mode)
def __call__(self, **k): def __call__(self, **k):
trading_mode: TradingMode = k['trading_mode'] trading_mode: TradingMode = k['trading_mode']
if trading_mode == TradingMode.SPOT or self.name == "NONE": if trading_mode == TradingMode.SPOT or self.name == "NONE":
return None return None
collateral: Collateral = k['collateral']
if self.name == "BINANCE": if self.name == "BINANCE":
return self._binance(trading_mode) return binance(trading_mode, collateral)
elif self.name == "KRAKEN": elif self.name == "KRAKEN":
return self._kraken(trading_mode) return kraken(trading_mode, collateral)
elif self.name == "FTX": elif self.name == "FTX":
return self._ftx(trading_mode) return ftx(trading_mode, collateral)
else: else:
self._exception(trading_mode) 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 trading_mode: cross, isolated, cross_futures or isolated_futures
"""
raise OperationalException(
f"{name} does not support {collateral.value} {trading_mode.value} trading")
def binance(name: str, trading_mode: TradingMode, collateral: Collateral):
# 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):
# 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):
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)

View File

@ -4,10 +4,8 @@ from enum import Enum
class TradingMode(Enum): class TradingMode(Enum):
""" """
Enum to distinguish between Enum to distinguish between
spot, cross margin, isolated margin, futures or any other trading method spot, margin, futures or any other trading method
""" """
SPOT = "spot" SPOT = "spot"
CROSS_MARGIN = "cross margin" MARGIN = "margin"
ISOLATED_MARGIN = "isolated margin" FUTURES = "futures"
CROSS_FUTURES = "cross futures"
ISOLATED_FUTURES = "isolated futures"

View File

@ -1,4 +1,4 @@
from freqtrade.enums import LiqFormula, TradingMode from freqtrade.enums import Collateral, LiqFormula, TradingMode
# from freqtrade.exceptions import OperationalException # from freqtrade.exceptions import OperationalException
@ -7,37 +7,55 @@ from freqtrade.enums import LiqFormula, TradingMode
def test_liquidation_formula(): def test_liquidation_formula():
spot = TradingMode.SPOT spot = TradingMode.SPOT
cross_margin = TradingMode.CROSS_MARGIN margin = TradingMode.MARGIN
isolated_margin = TradingMode.ISOLATED_MARGIN futures = TradingMode.FUTURES
cross_futures = TradingMode.CROSS_FUTURES
isolated_futures = TradingMode.ISOLATED_FUTURES
cross = Collateral.CROSS
isolated = Collateral.ISOLATED
# NONE
assert LiqFormula.NONE(trading_mode=spot) is None assert LiqFormula.NONE(trading_mode=spot) is None
assert LiqFormula.NONE(trading_mode=cross_margin) is None assert LiqFormula.NONE(trading_mode=margin, collateral=cross) is None
assert LiqFormula.NONE(trading_mode=isolated_margin) is None assert LiqFormula.NONE(trading_mode=margin, collateral=isolated) is None
assert LiqFormula.NONE(trading_mode=cross_futures) is None assert LiqFormula.NONE(trading_mode=futures, collateral=cross) is None
assert LiqFormula.NONE(trading_mode=isolated_futures) is None assert LiqFormula.NONE(trading_mode=futures, collateral=isolated) is None
# Binance
assert LiqFormula.BINANCE(trading_mode=spot) is None assert LiqFormula.BINANCE(trading_mode=spot) is None
assert LiqFormula.BINANCE(trading_mode=spot, collateral=cross) is None
assert LiqFormula.BINANCE(trading_mode=spot, collateral=isolated) is None
# TODO-lev: Uncomment these assertions and make them real calculation tests # TODO-lev: Uncomment these assertions and make them real calculation tests
# TODO-lev: Replace 1.0 with real value # TODO-lev: Replace 1.0 with real value
# assert LiqFormula.BINANCE(trading_mode=cross_margin) == 1.0 # assert LiqFormula.BINANCE(trading_mode=margin, collateral=cross) == 1.0
# assert LiqFormula.BINANCE(trading_mode=isolated_margin) == 1.0 # assert LiqFormula.BINANCE(trading_mode=margin, collateral=isolated) == 1.0
# assert LiqFormula.BINANCE(trading_mode=cross_futures) == 1.0 # assert LiqFormula.BINANCE(trading_mode=futures, collateral=cross) == 1.0
# assert LiqFormula.BINANCE(trading_mode=isolated_futures) == 1.0 # Binance supports isolated margin, but freqtrade likely won't for a while on Binance
# assert LiqFormula.BINANCE(trading_mode=margin, collateral=isolated) == 1.0
# Kraken
assert LiqFormula.KRAKEN(trading_mode=spot) is None assert LiqFormula.KRAKEN(trading_mode=spot) is None
assert LiqFormula.KRAKEN(trading_mode=spot, collateral=cross) is None
assert LiqFormula.KRAKEN(trading_mode=spot, collateral=isolated) is None
# TODO-lev: Uncomment these assertions and make them real calculation tests # TODO-lev: Uncomment these assertions and make them real calculation tests
# assert LiqFormula.KRAKEN(trading_mode=cross_margin) == 1.0 # assert LiqFormula.KRAKEN(trading_mode=margin, collateral=cross) == 1.0
# LiqFormula.KRAKEN(trading_mode=isolated_margin) # assert LiqFormula.KRAKEN(trading_mode=margin, collateral=isolated) == 1.0
# asset exception thrown #TODO-lev: Check that exception is thrown
# assert LiqFormula.KRAKEN(trading_mode=cross_futures) == 1.0
# LiqFormula.KRAKEN(trading_mode=isolated_futures)
# asset exception thrown #TODO-lev: Check that exception is thrown
# LiqFormula.KRAKEN(trading_mode=futures, collateral=cross)
# assert exception thrown #TODO-lev: Check that exception is thrown
# LiqFormula.KRAKEN(trading_mode=futures, collateral=isolated)
# assert exception thrown #TODO-lev: Check that exception is thrown
# FTX
assert LiqFormula.FTX(trading_mode=spot) is None assert LiqFormula.FTX(trading_mode=spot) is None
assert LiqFormula.FTX(trading_mode=spot, collateral=cross) is None
assert LiqFormula.FTX(trading_mode=spot, collateral=isolated) is None
# TODO-lev: Uncomment these assertions and make them real calculation tests # TODO-lev: Uncomment these assertions and make them real calculation tests
# assert LiqFormula.FTX(trading_mode=cross_margin) == 1.0 # assert LiqFormula.FTX(trading_mode=margin, collateral=cross) == 1.0
# assert LiqFormula.FTX(trading_mode=isolated_margin) == 1.0 # assert LiqFormula.FTX(trading_mode=margin, collateral=isolated) == 1.0
# assert LiqFormula.FTX(trading_mode=cross_futures) == 1.0
# assert LiqFormula.FTX(trading_mode=isolated_futures) == 1.0 # LiqFormula.KRAKEN(trading_mode=futures, collateral=cross)
# assert exception thrown #TODO-lev: Check that exception is thrown
# LiqFormula.KRAKEN(trading_mode=futures, collateral=isolated)
# assert exception thrown #TODO-lev: Check that exception is thrown