diff --git a/strategy.py b/strategy.py index 3d941fb..920dd85 100644 --- a/strategy.py +++ b/strategy.py @@ -1,4 +1,4 @@ -from typing import List +from typing import List, Dict import sympy.abc from bfxapi import Position @@ -47,12 +47,13 @@ class TrailingStopStrategy(Strategy): BREAK_EVEN_PERC = TAKER_FEE MIN_PROFIT_PERC = BREAK_EVEN_PERC + 0.3 GOOD_PROFIT_PERC = MIN_PROFIT_PERC * 2.5 - MAX_LOSS_PERC = -4.5 + MAX_LOSS_PERC = -4.0 TRAILING_STOP = SquaredTrailingStop(Point(MIN_PROFIT_PERC, MIN_PROFIT_PERC / 3 * 2), Point(GOOD_PROFIT_PERC, 0.1)) def __init__(self): - self.stop_percentage: float = None + # position_id : stop percentage + self.stop_percentage: Dict[int, float] = {} def position_on_new_tick(self, current_position: Position, ss: SymbolStatus) -> (PositionState, List[Event]): events = [] @@ -79,8 +80,6 @@ class TrailingStopStrategy(Strategy): if not prev or prev.state() == state: return pw, events - print(f"{prev.state()} vs {state}") - if state == PositionState.PROFIT: events.append(Event(EventKind.REACHED_GOOD_PROFIT, ss.current_tick, event_metadata)) elif state == PositionState.MINIMUM_PROFIT: @@ -97,18 +96,28 @@ class TrailingStopStrategy(Strategy): async def update_stop_percentage(self, pw: PositionWrapper, ss: SymbolStatus): current_pl_perc = pw.net_profit_loss_percentage() + pid = pw.position.id + event_metadata = EventMetadata(position_id=pw.position.id) - # set stop percentage for first time - if not self.stop_percentage: - await ss.add_event(Event(EventKind.TRAILING_STOP_SET, ss.current_tick)) + # if trailing stop not set for this position and state is not profit (we should not set it) + if pid not in self.stop_percentage and pw.state() not in [PositionState.MINIMUM_PROFIT, + PositionState.PROFIT]: + return - self.stop_percentage = current_pl_perc - self.TRAILING_STOP.y(current_pl_perc) + # set stop percentage for first time only if in profit + if pid not in self.stop_percentage: + await ss.add_event(Event(EventKind.TRAILING_STOP_SET, ss.current_tick, event_metadata)) + self.stop_percentage[pid] = current_pl_perc - self.TRAILING_STOP.y(current_pl_perc) return # moving trailing stop - if current_pl_perc - self.TRAILING_STOP.y(pw.net_profit_loss_percentage()) > self.stop_percentage: - await ss.add_event(Event(EventKind.TRAILING_STOP_MOVED, ss.current_tick)) - self.stop_percentage = current_pl_perc - self.TRAILING_STOP.y(current_pl_perc) + if current_pl_perc - self.TRAILING_STOP.y(current_pl_perc) > self.stop_percentage[pid]: + await ss.add_event(Event(EventKind.TRAILING_STOP_MOVED, ss.current_tick, event_metadata)) + self.stop_percentage[pid] = current_pl_perc - self.TRAILING_STOP.y(current_pl_perc) + + # close position if current P/L below stop percentage + if current_pl_perc < self.stop_percentage[pid]: + await ss.add_event(Event(EventKind.CLOSE_POSITION, ss.current_tick, event_metadata)) return