Added skeleton functions for maintenance margin

This commit is contained in:
Sam Germain 2021-07-29 16:05:42 -06:00
parent dad98d43be
commit 34ddf7bfa9
8 changed files with 83 additions and 1 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.maintenancemarginformula import MaintenanceMarginFormula
from freqtrade.enums.rpcmessagetype import RPCMessageType from freqtrade.enums.rpcmessagetype import RPCMessageType
from freqtrade.enums.runmode import NON_UTIL_MODES, OPTIMIZE_MODES, TRADING_MODES, RunMode from freqtrade.enums.runmode import NON_UTIL_MODES, OPTIMIZE_MODES, TRADING_MODES, RunMode
from freqtrade.enums.selltype import SellType from freqtrade.enums.selltype import SellType

View File

@ -0,0 +1,26 @@
from enum import Enum
from freqtrade.exceptions import OperationalException
class MaintenanceMarginFormula(Enum):
"""Equations to calculate maintenance margin"""
BINANCE = "BINANCE"
FTX = "FTX"
KRAKEN = "KRAKEN"
# TODO: Add arguments
def __call__(self):
if self.name == "BINANCE":
raise OperationalException("Cross margin not available on this exchange with freqtrade")
# TODO: return This formula
# https://www.binance.com/en/support/faq/f6b010588e55413aa58b7d63ee0125ed
elif self.name == "FTX":
# TODO: Implement
raise OperationalException("Cross margin not available on this exchange with freqtrade")
elif self.name == "KRAKEN":
# TODO: Implement
raise OperationalException("Cross margin not available on this exchange with freqtrade")
# https://support.kraken.com/hc/en-us/articles/203325763-Margin-Call-Level-and-Margin-Liquidation-Level
else:
raise OperationalException("Cross margin not available on this exchange with freqtrade")

View File

@ -3,7 +3,7 @@ import logging
from typing import Dict from typing import Dict
import ccxt import ccxt
from freqtrade.enums import MaintenanceMarginFormula
from freqtrade.exceptions import (DDosProtection, InsufficientFundsError, InvalidOrderException, from freqtrade.exceptions import (DDosProtection, InsufficientFundsError, InvalidOrderException,
OperationalException, TemporaryError) OperationalException, TemporaryError)
from freqtrade.exchange import Exchange from freqtrade.exchange import Exchange
@ -24,6 +24,8 @@ class Binance(Exchange):
"l2_limit_range": [5, 10, 20, 50, 100, 500, 1000], "l2_limit_range": [5, 10, 20, 50, 100, 500, 1000],
} }
maintenance_margin_formula = MaintenanceMarginFormula.BINANCE
def stoploss_adjust(self, stop_loss: float, order: Dict) -> bool: def stoploss_adjust(self, stop_loss: float, order: Dict) -> bool:
""" """
Verify stop_loss against stoploss-order value (limit or price) Verify stop_loss against stoploss-order value (limit or price)

View File

@ -21,6 +21,7 @@ from pandas import DataFrame
from freqtrade.constants import DEFAULT_AMOUNT_RESERVE_PERCENT, ListPairsWithTimeframes from freqtrade.constants import DEFAULT_AMOUNT_RESERVE_PERCENT, ListPairsWithTimeframes
from freqtrade.data.converter import ohlcv_to_dataframe, trades_dict_to_list from freqtrade.data.converter import ohlcv_to_dataframe, trades_dict_to_list
from freqtrade.enums import MaintenanceMarginFormula
from freqtrade.exceptions import (DDosProtection, ExchangeError, InsufficientFundsError, from freqtrade.exceptions import (DDosProtection, ExchangeError, InsufficientFundsError,
InvalidOrderException, OperationalException, PricingError, InvalidOrderException, OperationalException, PricingError,
RetryableOrderError, TemporaryError) RetryableOrderError, TemporaryError)
@ -68,6 +69,7 @@ class Exchange:
"l2_limit_range_required": True, # Allow Empty L2 limit (kucoin) "l2_limit_range_required": True, # Allow Empty L2 limit (kucoin)
} }
_ft_has: Dict = {} _ft_has: Dict = {}
maintenance_margin_formula: MaintenanceMarginFormula
def __init__(self, config: Dict[str, Any], validate: bool = True) -> None: def __init__(self, config: Dict[str, Any], validate: bool = True) -> None:
""" """

View File

@ -4,6 +4,7 @@ from typing import Any, Dict
import ccxt import ccxt
from freqtrade.enums import MaintenanceMarginFormula
from freqtrade.exceptions import (DDosProtection, InsufficientFundsError, InvalidOrderException, from freqtrade.exceptions import (DDosProtection, InsufficientFundsError, InvalidOrderException,
OperationalException, TemporaryError) OperationalException, TemporaryError)
from freqtrade.exchange import Exchange from freqtrade.exchange import Exchange
@ -21,6 +22,8 @@ class Ftx(Exchange):
"ohlcv_candle_limit": 1500, "ohlcv_candle_limit": 1500,
} }
maintenance_margin_formula = MaintenanceMarginFormula.FTX
def market_is_tradable(self, market: Dict[str, Any]) -> bool: def market_is_tradable(self, market: Dict[str, Any]) -> bool:
""" """
Check if the market symbol is tradable by Freqtrade. Check if the market symbol is tradable by Freqtrade.

View File

@ -4,6 +4,7 @@ from typing import Any, Dict
import ccxt import ccxt
from freqtrade.enums import MaintenanceMarginFormula
from freqtrade.exceptions import (DDosProtection, InsufficientFundsError, InvalidOrderException, from freqtrade.exceptions import (DDosProtection, InsufficientFundsError, InvalidOrderException,
OperationalException, TemporaryError) OperationalException, TemporaryError)
from freqtrade.exchange import Exchange from freqtrade.exchange import Exchange
@ -23,6 +24,8 @@ class Kraken(Exchange):
"trades_pagination_arg": "since", "trades_pagination_arg": "since",
} }
maintenance_margin_formula = MaintenanceMarginFormula.KRAKEN
def market_is_tradable(self, market: Dict[str, Any]) -> bool: def market_is_tradable(self, market: Dict[str, Any]) -> bool:
""" """
Check if the market symbol is tradable by Freqtrade. Check if the market symbol is tradable by Freqtrade.

View File

@ -20,6 +20,7 @@ from freqtrade.enums import RPCMessageType, SellType, State
from freqtrade.exceptions import (DependencyException, ExchangeError, InsufficientFundsError, from freqtrade.exceptions import (DependencyException, ExchangeError, InsufficientFundsError,
InvalidOrderException, PricingError) InvalidOrderException, PricingError)
from freqtrade.exchange import timeframe_to_minutes, timeframe_to_seconds from freqtrade.exchange import timeframe_to_minutes, timeframe_to_seconds
from freqtrade.maintenance_margin import MaintenanceMargin
from freqtrade.misc import safe_value_fallback, safe_value_fallback2 from freqtrade.misc import safe_value_fallback, safe_value_fallback2
from freqtrade.mixins import LoggingMixin from freqtrade.mixins import LoggingMixin
from freqtrade.persistence import Order, PairLocks, Trade, cleanup_db, init_db from freqtrade.persistence import Order, PairLocks, Trade, cleanup_db, init_db
@ -102,6 +103,12 @@ class FreqtradeBot(LoggingMixin):
self._sell_lock = Lock() self._sell_lock = Lock()
LoggingMixin.__init__(self, logger, timeframe_to_seconds(self.strategy.timeframe)) LoggingMixin.__init__(self, logger, timeframe_to_seconds(self.strategy.timeframe))
# Start calculating maintenance margin if on cross margin
# TODO: Add margin_mode to freqtrade.configuration?
if self.config.get('margin_mode') == "cross":
self.maintenance_margin = MaintenanceMargin(self.exchange.maintenance_margin_formula)
self.maintenance_margin.run
def notify_status(self, msg: str) -> None: def notify_status(self, msg: str) -> None:
""" """
Public method for users of this class (worker, etc.) to send notifications Public method for users of this class (worker, etc.) to send notifications

View File

@ -0,0 +1,38 @@
from freqtrade.enums import MaintenanceMarginFormula
from freqtrade.persistence import Trade
class MaintenanceMargin:
trades: list[Trade]
formula: MaintenanceMarginFormula
@property
def margin_level(self):
return self.formula() # TODO: Add args to formula
@property
def liq_level(self): # This may be a constant value and may not need a function
return
def __init__(self, formula: MaintenanceMarginFormula):
return
def add_new_trade(self, trade):
return
def remove_trade(self, trade):
return
# ? def update_trade_pric(self):
def sell_all(self):
return
def run(self):
# TODO-mg: implement a thread that constantly updates with every price change,
# TODO-mg: must update at least every second
# while true:
# if self.margin_level <= self.liq_level:
# self.sell_all()
return