Compare commits
1 Commits
develop
...
feat/cross
Author | SHA1 | Date | |
---|---|---|---|
|
2b9775ae22 |
@ -17,12 +17,13 @@ from freqtrade.constants import BuySell, LongShort
|
|||||||
from freqtrade.data.converter import order_book_to_dataframe
|
from freqtrade.data.converter import order_book_to_dataframe
|
||||||
from freqtrade.data.dataprovider import DataProvider
|
from freqtrade.data.dataprovider import DataProvider
|
||||||
from freqtrade.edge import Edge
|
from freqtrade.edge import Edge
|
||||||
from freqtrade.enums import (ExitCheckTuple, ExitType, RPCMessageType, RunMode, SignalDirection,
|
from freqtrade.enums import (ExitCheckTuple, ExitType, MarginMode, RPCMessageType, RunMode,
|
||||||
State, TradingMode)
|
SignalDirection, State, TradingMode)
|
||||||
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.exchange.exchange import timeframe_to_next_date
|
from freqtrade.exchange.exchange import timeframe_to_next_date
|
||||||
|
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
|
||||||
@ -104,7 +105,11 @@ class FreqtradeBot(LoggingMixin):
|
|||||||
LoggingMixin.__init__(self, logger, timeframe_to_seconds(self.strategy.timeframe))
|
LoggingMixin.__init__(self, logger, timeframe_to_seconds(self.strategy.timeframe))
|
||||||
|
|
||||||
self.trading_mode: TradingMode = self.config.get('trading_mode', TradingMode.SPOT)
|
self.trading_mode: TradingMode = self.config.get('trading_mode', TradingMode.SPOT)
|
||||||
|
self.margin_mode: MarginMode = (
|
||||||
|
MarginMode(config.get('margin_mode'))
|
||||||
|
if config.get('margin_mode')
|
||||||
|
else MarginMode.NONE
|
||||||
|
)
|
||||||
self._schedule = Scheduler()
|
self._schedule = Scheduler()
|
||||||
|
|
||||||
if self.trading_mode == TradingMode.FUTURES:
|
if self.trading_mode == TradingMode.FUTURES:
|
||||||
@ -125,6 +130,16 @@ class FreqtradeBot(LoggingMixin):
|
|||||||
# Initialize protections AFTER bot start - otherwise parameters are not loaded.
|
# Initialize protections AFTER bot start - otherwise parameters are not loaded.
|
||||||
self.protections = ProtectionManager(self.config, self.strategy.protections)
|
self.protections = ProtectionManager(self.config, self.strategy.protections)
|
||||||
|
|
||||||
|
# Start calculating maintenance margin if on cross margin
|
||||||
|
# TODO-lev: finish the below...
|
||||||
|
if self.margin_mode == MarginMode.CROSS:
|
||||||
|
|
||||||
|
self.maintenance_margin = MaintenanceMargin(
|
||||||
|
exchange_name=self.exchange.name,
|
||||||
|
trading_mode=self.trading_mode)
|
||||||
|
|
||||||
|
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
|
||||||
@ -721,6 +736,10 @@ class FreqtradeBot(LoggingMixin):
|
|||||||
|
|
||||||
trade.orders.append(order_obj)
|
trade.orders.append(order_obj)
|
||||||
trade.recalc_trade_from_orders()
|
trade.recalc_trade_from_orders()
|
||||||
|
|
||||||
|
if self.margin_mode == MarginMode.CROSS:
|
||||||
|
self.maintenance_margin.add_new_trade(trade)
|
||||||
|
|
||||||
Trade.query.session.add(trade)
|
Trade.query.session.add(trade)
|
||||||
Trade.commit()
|
Trade.commit()
|
||||||
|
|
||||||
@ -1501,10 +1520,21 @@ class FreqtradeBot(LoggingMixin):
|
|||||||
# In case of market sell orders the order can be closed immediately
|
# In case of market sell orders the order can be closed immediately
|
||||||
if order.get('status', 'unknown') in ('closed', 'expired'):
|
if order.get('status', 'unknown') in ('closed', 'expired'):
|
||||||
self.update_trade_state(trade, trade.open_order_id, order)
|
self.update_trade_state(trade, trade.open_order_id, order)
|
||||||
|
|
||||||
Trade.commit()
|
Trade.commit()
|
||||||
|
|
||||||
|
self._remove_maintenance_trade(trade)
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
def _remove_maintenance_trade(self, trade: Trade):
|
||||||
|
"""
|
||||||
|
Removes a trade from the maintenance margin object
|
||||||
|
:param trade: The trade to remove from the maintenance margin
|
||||||
|
"""
|
||||||
|
if self.margin_mode == MarginMode.CROSS:
|
||||||
|
self.maintenance_margin.remove_trade(trade)
|
||||||
|
|
||||||
def _notify_exit(self, trade: Trade, order_type: str, fill: bool = False) -> None:
|
def _notify_exit(self, trade: Trade, order_type: str, fill: bool = False) -> None:
|
||||||
"""
|
"""
|
||||||
Sends rpc notification when a sell occurred.
|
Sends rpc notification when a sell occurred.
|
||||||
|
52
freqtrade/maintenance_margin.py
Normal file
52
freqtrade/maintenance_margin.py
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
from typing import List
|
||||||
|
|
||||||
|
from freqtrade.enums import TradingMode
|
||||||
|
from freqtrade.leverage import liquidation_price
|
||||||
|
from freqtrade.persistence import Trade
|
||||||
|
|
||||||
|
|
||||||
|
class MaintenanceMargin:
|
||||||
|
|
||||||
|
trades: List[Trade]
|
||||||
|
exchange_name: str
|
||||||
|
trading_mode: TradingMode
|
||||||
|
|
||||||
|
@property
|
||||||
|
def margin_level(self):
|
||||||
|
# This is the current value of all assets,
|
||||||
|
# and if you pass below liq_level, you are liquidated
|
||||||
|
# TODO-lev: Add args to formula
|
||||||
|
return liquidation_price(
|
||||||
|
trading_mode=self.trading_mode,
|
||||||
|
exchange_name=self.exchange_name
|
||||||
|
)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def liq_level(self): # This may be a constant value and may not need a function
|
||||||
|
# TODO-lev: The is the value that you are liquidated at
|
||||||
|
return # If constant, would need to be recalculated after each new trade
|
||||||
|
|
||||||
|
def __init__(self, exchange_name: str, trading_mode: TradingMode):
|
||||||
|
self.exchange_name = exchange_name
|
||||||
|
self.trading_mode = trading_mode
|
||||||
|
return
|
||||||
|
|
||||||
|
def add_new_trade(self, trade):
|
||||||
|
self.trades.append(trade)
|
||||||
|
|
||||||
|
def remove_trade(self, trade):
|
||||||
|
self.trades.remove(trade)
|
||||||
|
|
||||||
|
# ? def update_trade_pric(self):
|
||||||
|
|
||||||
|
def sell_all(self):
|
||||||
|
# TODO-lev
|
||||||
|
return
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
# TODO-lev: implement a thread that constantly updates with every price change,
|
||||||
|
# TODO-lev: must update at least every few seconds or so
|
||||||
|
# while true:
|
||||||
|
# if self.margin_level <= self.liq_level:
|
||||||
|
# self.sell_all()
|
||||||
|
return
|
Loading…
Reference in New Issue
Block a user