diff --git a/freqtrade/persistence.py b/freqtrade/persistence.py index 20a7db4bb..76a499eed 100644 --- a/freqtrade/persistence.py +++ b/freqtrade/persistence.py @@ -151,6 +151,12 @@ class Trade(_DECL_BASE): open_date = Column(DateTime, nullable=False, default=datetime.utcnow) close_date = Column(DateTime) open_order_id = Column(String) + # absolute value of the stop loss + stop_loss = Column(Float, nullable=True, default=0.0) + # absolute value of the initial stop loss + initial_stop_loss = Column(Float, nullable=True, default=0.0) + # absolute value of the highest reached price + max_rate = Column(Float, nullable=True, default=0.0) def __repr__(self): return 'Trade(id={}, pair={}, amount={:.8f}, open_rate={:.8f}, open_since={})'.format( @@ -161,6 +167,49 @@ class Trade(_DECL_BASE): arrow.get(self.open_date).humanize() if self.is_open else 'closed' ) + def adjust_stop_loss(self, current_price, stoploss): + """ + this adjusts the stop loss to it's most recently observed + setting + :param current_price: + :param stoploss: + :return: + """ + + new_loss = Decimal(current_price * (1 - abs(stoploss))) + + # keeping track of the highest observed rate for this trade + if self.max_rate is None: + self.max_rate = current_price + else: + if current_price > self.max_rate: + self.max_rate = current_price + + # no stop loss assigned yet + if self.stop_loss is None or self.stop_loss == 0: + logger.debug("assigning new stop loss") + self.stop_loss = new_loss + self.initial_stop_loss = new_loss + + # evaluate if the stop loss needs to be updated + else: + if new_loss > self.stop_loss: # stop losses only walk up, never down! + self.stop_loss = new_loss + logger.debug("adjusted stop loss") + else: + logger.debug("keeping current stop loss") + + logger.debug( + "{} - current price {:.8f}, bought at {:.8f} and calculated " + "stop loss is at: {:.8f} initial stop at {:.8f}. trailing stop loss saved us: {:.8f} " + "and max observed rate was {:.8f}".format( + self.pair, current_price, self.open_rate, + self.initial_stop_loss, + self.stop_loss, float(self.stop_loss) - float(self.initial_stop_loss), + self.max_rate + + )) + def update(self, order: Dict) -> None: """ Updates this entity with amount and actual open/close rates.