Updated tests to new persistence
This commit is contained in:
@@ -49,9 +49,6 @@ def migrate_trades_table(decl_base, inspector, engine, table_back_name: str, col
|
||||
strategy = get_column_def(cols, 'strategy', 'null')
|
||||
|
||||
leverage = get_column_def(cols, 'leverage', 'null')
|
||||
borrowed = get_column_def(cols, 'borrowed', '0.0')
|
||||
borrowed_currency = get_column_def(cols, 'borrowed_currency', 'null')
|
||||
collateral_currency = get_column_def(cols, 'collateral_currency', 'null')
|
||||
interest_rate = get_column_def(cols, 'interest_rate', '0.0')
|
||||
liquidation_price = get_column_def(cols, 'liquidation_price', 'null')
|
||||
is_short = get_column_def(cols, 'is_short', 'False')
|
||||
@@ -91,8 +88,7 @@ def migrate_trades_table(decl_base, inspector, engine, table_back_name: str, col
|
||||
stoploss_order_id, stoploss_last_update,
|
||||
max_rate, min_rate, sell_reason, sell_order_status, strategy,
|
||||
timeframe, open_trade_value, close_profit_abs,
|
||||
leverage, borrowed, borrowed_currency, collateral_currency, interest_rate,
|
||||
liquidation_price, is_short
|
||||
leverage, interest_rate, liquidation_price, is_short
|
||||
)
|
||||
select id, lower(exchange),
|
||||
case
|
||||
@@ -116,14 +112,11 @@ def migrate_trades_table(decl_base, inspector, engine, table_back_name: str, col
|
||||
{sell_order_status} sell_order_status,
|
||||
{strategy} strategy, {timeframe} timeframe,
|
||||
{open_trade_value} open_trade_value, {close_profit_abs} close_profit_abs,
|
||||
{leverage} leverage, {borrowed} borrowed, {borrowed_currency} borrowed_currency,
|
||||
{collateral_currency} collateral_currency, {interest_rate} interest_rate,
|
||||
{leverage} leverage, {interest_rate} interest_rate,
|
||||
{liquidation_price} liquidation_price, {is_short} is_short
|
||||
from {table_back_name}
|
||||
"""))
|
||||
|
||||
# TODO: Does leverage go in here?
|
||||
|
||||
|
||||
def migrate_open_orders_to_trades(engine):
|
||||
with engine.begin() as connection:
|
||||
|
@@ -132,7 +132,11 @@ class Order(_DECL_BASE):
|
||||
order_filled_date = Column(DateTime, nullable=True)
|
||||
order_update_date = Column(DateTime, nullable=True)
|
||||
|
||||
leverage = Column(Float, nullable=True, default=None)
|
||||
is_short = Column(Boolean, nullable=True, default=False)
|
||||
|
||||
def __repr__(self):
|
||||
|
||||
return (f'Order(id={self.id}, order_id={self.order_id}, trade_id={self.ft_trade_id}, '
|
||||
f'side={self.side}, order_type={self.order_type}, status={self.status})')
|
||||
|
||||
@@ -226,7 +230,6 @@ class LocalTrade():
|
||||
fee_close_currency: str = ''
|
||||
open_rate: float = 0.0
|
||||
open_rate_requested: Optional[float] = None
|
||||
|
||||
# open_trade_value - calculated via _calc_open_trade_value
|
||||
open_trade_value: float = 0.0
|
||||
close_rate: Optional[float] = None
|
||||
@@ -261,61 +264,23 @@ class LocalTrade():
|
||||
timeframe: Optional[int] = None
|
||||
|
||||
# Margin trading properties
|
||||
borrowed_currency: str = None
|
||||
collateral_currency: str = None
|
||||
interest_rate: float = 0.0
|
||||
liquidation_price: float = None
|
||||
is_short: bool = False
|
||||
borrowed: float = 0.0
|
||||
leverage: float = None
|
||||
|
||||
# @property
|
||||
# def base_currency(self) -> str:
|
||||
# if not self.pair:
|
||||
# raise OperationalException('LocalTrade.pair must be assigned')
|
||||
# return self.pair.split("/")[1]
|
||||
@property
|
||||
def has_no_leverage(self) -> bool:
|
||||
return (self.leverage == 1.0 and not self.is_short) or self.leverage is None
|
||||
|
||||
# TODO: @samgermain: Amount should be persisted "as is".
|
||||
# I've partially reverted this (this killed most of your tests)
|
||||
# but leave this here as i'm not sure where you intended to use this.
|
||||
# @property
|
||||
# def amount(self) -> float:
|
||||
# if self._leverage is not None:
|
||||
# return self._amount * self.leverage
|
||||
# else:
|
||||
# return self._amount
|
||||
|
||||
# @amount.setter
|
||||
# def amount(self, value):
|
||||
# self._amount = value
|
||||
|
||||
# @property
|
||||
# def borrowed(self) -> float:
|
||||
# if self._leverage is not None:
|
||||
# if self.is_short:
|
||||
# # If shorting the full amount must be borrowed
|
||||
# return self._amount * self._leverage
|
||||
# else:
|
||||
# # If not shorting, then the trader already owns a bit
|
||||
# return self._amount * (self._leverage-1)
|
||||
# else:
|
||||
# return self._borrowed
|
||||
|
||||
# @borrowed.setter
|
||||
# def borrowed(self, value):
|
||||
# self._borrowed = value
|
||||
# self._leverage = None
|
||||
|
||||
# @property
|
||||
# def leverage(self) -> float:
|
||||
# return self._leverage
|
||||
|
||||
# @leverage.setter
|
||||
# def leverage(self, value):
|
||||
# self._leverage = value
|
||||
# self._borrowed = None
|
||||
|
||||
# End of margin trading properties
|
||||
@property
|
||||
def borrowed(self) -> float:
|
||||
if self.has_no_leverage:
|
||||
return 0.0
|
||||
elif not self.is_short:
|
||||
return self.stake_amount * (self.leverage-1)
|
||||
else:
|
||||
return self.amount
|
||||
|
||||
@property
|
||||
def open_date_utc(self):
|
||||
@@ -326,13 +291,8 @@ class LocalTrade():
|
||||
return self.close_date.replace(tzinfo=timezone.utc)
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
if kwargs.get('leverage') and kwargs.get('borrowed'):
|
||||
# TODO-mg: should I raise an error?
|
||||
raise OperationalException('Cannot pass both borrowed and leverage to Trade')
|
||||
for key in kwargs:
|
||||
setattr(self, key, kwargs[key])
|
||||
if not self.is_short:
|
||||
self.is_short = False
|
||||
self.recalc_open_trade_value()
|
||||
|
||||
def __repr__(self):
|
||||
@@ -404,9 +364,6 @@ class LocalTrade():
|
||||
'max_rate': self.max_rate,
|
||||
|
||||
'leverage': self.leverage,
|
||||
'borrowed': self.borrowed,
|
||||
'borrowed_currency': self.borrowed_currency,
|
||||
'collateral_currency': self.collateral_currency,
|
||||
'interest_rate': self.interest_rate,
|
||||
'liquidation_price': self.liquidation_price,
|
||||
'is_short': self.is_short,
|
||||
@@ -473,7 +430,7 @@ class LocalTrade():
|
||||
|
||||
# evaluate if the stop loss needs to be updated
|
||||
else:
|
||||
# stop losses only walk up, never down!, #TODO: But adding more to a margin account would create a lower liquidation price, decreasing the minimum stoploss
|
||||
# stop losses only walk up, never down!, #But adding more to a margin account would create a lower liquidation price, decreasing the minimum stoploss
|
||||
if (new_loss > self.stop_loss and not self.is_short) or (new_loss < self.stop_loss and self.is_short):
|
||||
logger.debug(f"{self.pair} - Adjusting stoploss...")
|
||||
self._set_new_stoploss(new_loss, stoploss)
|
||||
@@ -510,13 +467,8 @@ class LocalTrade():
|
||||
"""
|
||||
order_type = order['type']
|
||||
|
||||
if ('leverage' in order and 'borrowed' in order):
|
||||
raise OperationalException(
|
||||
'Pass only one of Leverage or Borrowed to the order in update trade')
|
||||
|
||||
if 'is_short' in order and order['side'] == 'sell':
|
||||
# Only set's is_short on opening trades, ignores non-shorts
|
||||
# TODO-mg: I don't like this, but it might be the only way
|
||||
self.is_short = order['is_short']
|
||||
|
||||
# Ignore open and cancelled orders
|
||||
@@ -527,15 +479,10 @@ class LocalTrade():
|
||||
|
||||
if order_type in ('market', 'limit') and self.is_opening_trade(order['side']):
|
||||
# Update open rate and actual amount
|
||||
|
||||
self.open_rate = float(safe_value_fallback(order, 'average', 'price'))
|
||||
self.amount = float(safe_value_fallback(order, 'filled', 'amount'))
|
||||
|
||||
if 'borrowed' in order:
|
||||
self.borrowed = order['borrowed']
|
||||
elif 'leverage' in order:
|
||||
if 'leverage' in order:
|
||||
self.leverage = order['leverage']
|
||||
|
||||
self.recalc_open_trade_value()
|
||||
if self.is_open:
|
||||
payment = "SELL" if self.is_short else "BUY"
|
||||
@@ -544,7 +491,8 @@ class LocalTrade():
|
||||
elif order_type in ('market', 'limit') and self.is_closing_trade(order['side']):
|
||||
if self.is_open:
|
||||
payment = "BUY" if self.is_short else "SELL"
|
||||
# TODO: On Shorts technically your buying a little bit more than the amount because it's the ammount plus the interest
|
||||
# TODO-mg: On Shorts technically your buying a little bit more than the amount because it's the ammount plus the interest
|
||||
# But this wll only print the original
|
||||
logger.info(f'{order_type.upper()}_{payment} has been fulfilled for {self}.')
|
||||
self.close(safe_value_fallback(order, 'average', 'price')) # TODO: Double check this
|
||||
elif order_type in ('stop_loss_limit', 'stop-loss', 'stop-loss-limit', 'stop'):
|
||||
@@ -632,17 +580,16 @@ class LocalTrade():
|
||||
: param interest_rate: interest_charge for borrowing this coin(optional).
|
||||
If interest_rate is not set self.interest_rate will be used
|
||||
"""
|
||||
# TODO-mg: Need to set other conditions because sometimes self.open_date is not defined, but why would it ever not be set
|
||||
|
||||
zero = Decimal(0.0)
|
||||
if not (self.borrowed):
|
||||
# If nothing was borrowed
|
||||
if (self.leverage == 1.0 and not self.is_short) or not self.leverage:
|
||||
return zero
|
||||
|
||||
open_date = self.open_date.replace(tzinfo=None)
|
||||
now = datetime.utcnow()
|
||||
# sec_per_day = Decimal(86400)
|
||||
now = (self.close_date or datetime.utcnow()).replace(tzinfo=None)
|
||||
sec_per_hour = Decimal(3600)
|
||||
total_seconds = Decimal((now - open_date).total_seconds())
|
||||
# days = total_seconds/sec_per_day or zero
|
||||
hours = total_seconds/sec_per_hour or zero
|
||||
|
||||
rate = Decimal(interest_rate or self.interest_rate)
|
||||
@@ -654,7 +601,7 @@ class LocalTrade():
|
||||
if self.exchange == 'binance':
|
||||
# Rate is per day but accrued hourly or something
|
||||
# binance: https://www.binance.com/en-AU/support/faq/360030157812
|
||||
return borrowed * rate * max(hours, one)/twenty_four # TODO-mg: Is hours rounded?
|
||||
return borrowed * rate * max(hours, one)/twenty_four
|
||||
elif self.exchange == 'kraken':
|
||||
# https://support.kraken.com/hc/en-us/articles/206161568-What-are-the-fees-for-margin-trading-
|
||||
opening_fee = borrowed * rate
|
||||
@@ -746,16 +693,15 @@ class LocalTrade():
|
||||
if (self.is_short and close_trade_value == 0.0) or (not self.is_short and self.open_trade_value == 0.0):
|
||||
return 0.0
|
||||
else:
|
||||
if self.borrowed: # TODO: This is only needed so that previous tests that included dummy stake_amounts don't fail. Undate those tests and get rid of this else
|
||||
if self.has_no_leverage:
|
||||
# TODO: This is only needed so that previous tests that included dummy stake_amounts don't fail. Undate those tests and get rid of this else
|
||||
profit_ratio = (close_trade_value/self.open_trade_value) - 1
|
||||
else:
|
||||
if self.is_short:
|
||||
profit_ratio = ((self.open_trade_value - close_trade_value) / self.stake_amount)
|
||||
else:
|
||||
profit_ratio = ((close_trade_value - self.open_trade_value) / self.stake_amount)
|
||||
else: # TODO: This is only needed so that previous tests that included dummy stake_amounts don't fail. Undate those tests and get rid of this else
|
||||
if self.is_short:
|
||||
profit_ratio = 1 - (close_trade_value/self.open_trade_value)
|
||||
else:
|
||||
profit_ratio = (close_trade_value/self.open_trade_value) - 1
|
||||
|
||||
return float(f"{profit_ratio:.8f}")
|
||||
|
||||
def select_order(self, order_side: str, is_open: Optional[bool]) -> Optional[Order]:
|
||||
@@ -907,14 +853,10 @@ class Trade(_DECL_BASE, LocalTrade):
|
||||
timeframe = Column(Integer, nullable=True)
|
||||
|
||||
# Margin trading properties
|
||||
leverage = Column(Float, nullable=True) # TODO: can this be nullable, or should it default to 1? (must also be changed in migrations eventually)
|
||||
borrowed = Column(Float, nullable=False, default=0.0)
|
||||
leverage = Column(Float, nullable=True)
|
||||
interest_rate = Column(Float, nullable=False, default=0.0)
|
||||
liquidation_price = Column(Float, nullable=True)
|
||||
is_short = Column(Boolean, nullable=False, default=False)
|
||||
# TODO: Bottom 2 might not be needed
|
||||
borrowed_currency = Column(Float, nullable=True)
|
||||
collateral_currency = Column(String(25), nullable=True)
|
||||
# End of margin trading properties
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
|
Reference in New Issue
Block a user