added trailing stop

This commit is contained in:
Giulio De Pasquale 2020-12-16 13:36:20 +00:00
parent 912c4db2e2
commit c19530badb
4 changed files with 45 additions and 12 deletions

View File

@ -65,7 +65,7 @@ class BfxBot:
# emitting new tick event
## TODO: handle _on_new_tick() from Strategy
await self.__status[symbol].__add_event__(Event(EventKind.NEW_TICK, self.__ticker.current_tick))
await self.__status[symbol].add_event(Event(EventKind.NEW_TICK, self.__ticker.current_tick))
async def best_position_closing_price(self, position_id: int) -> Optional[float]:
pw: Optional[PositionWrapper] = self.__position_wrapper_from_id(position_id)

View File

@ -120,6 +120,10 @@ class SymbolStatus:
self.current_tick: int = 1
self.strategy: Strategy = strategy
async def add_event(self, event: Event):
self.events.append(event)
await self.eh.call_event(self, event)
def add_order(self, order: Order):
if self.strategy:
self.strategy.order_on_new_tick(order, self)
@ -162,10 +166,6 @@ class SymbolStatus:
def set_tick_price(self, tick, price):
self.prices[tick] = price
async def __add_event__(self, event: Event):
self.events.append(event)
await self.eh.call_event(self, event)
async def __apply_strategy_to_position__(self, position: Position):
if not self.strategy:
return
@ -185,7 +185,7 @@ class SymbolStatus:
for e in events:
if not isinstance(e, Event):
raise ValueError
await self.__add_event__(e)
await self.add_event__(e)
return pw
@ -239,15 +239,15 @@ class EventHandler:
if state in self.state_handlers:
for h in self.state_handlers[state]:
if inspect.iscoroutinefunction(h):
await h(status)
await h(pw, status)
else:
h(status)
h(pw, status)
for h in self.any_state:
if inspect.iscoroutinefunction(h):
await h(status)
await h(pw, status)
else:
h(status)
h(pw, status)
def on_event(self, kind: EventKind):
value = kind.value

16
main.py
View File

@ -12,7 +12,7 @@ from flask_socketio import SocketIO
from bfxbot import BfxBot
from bfxbot.currency import Symbol
from bfxbot.models import PositionWrapper, SymbolStatus, Event, EventKind
from bfxbot.models import PositionWrapper, SymbolStatus, Event, EventKind, PositionState
from bfxbot.utils import pos_to_json
from strategy import TrailingStopStrategy
@ -35,7 +35,8 @@ app = Flask(__name__)
socketio = SocketIO(app, async_mode="threading")
bot = BfxBot(api_key=API_KEY, api_secret=API_SECRET,
symbols=[Symbol.BTC], tick_duration=20)
bot.set_strategy(Symbol.BTC, TrailingStopStrategy())
strategy = TrailingStopStrategy()
bot.set_strategy(Symbol.BTC, strategy)
btc_eh = bot.symbol_event_handler(Symbol.BTC)
# initializing and starting bot on other thread
@ -92,6 +93,16 @@ def on_close_position(event: Event, _):
loop.run_until_complete(bot.close_position(event.metadata.position_id))
@btc_eh.on_position_state(PositionState.PROFIT)
async def on_state_min_profit(pw: PositionWrapper, ss: SymbolStatus):
await strategy.update_stop_percentage(pw, ss)
@btc_eh.on_position_state(PositionState.MINIMUM_PROFIT)
async def on_state_min_profit(pw: PositionWrapper, ss: SymbolStatus):
await strategy.update_stop_percentage(pw, ss)
@btc_eh.on_event(EventKind.NEW_TICK)
def on_new_tick(event: Event, status: SymbolStatus):
tick = event.tick
@ -106,6 +117,7 @@ def on_new_tick(event: Event, status: SymbolStatus):
@btc_eh.on_any_event()
def on_any_event(event: Event, _):
await strategy
socketio.emit("new_event", {
"tick": event.tick,
"kind": event.kind.name

View File

@ -51,6 +51,9 @@ class TrailingStopStrategy(Strategy):
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
def position_on_new_tick(self, position: Position, ss: SymbolStatus) -> (PositionState, List[Event]):
events = []
@ -88,3 +91,21 @@ class TrailingStopStrategy(Strategy):
events.append(Event(EventKind.CLOSE_POSITION, ss.current_tick, event_metadata))
return pw, events
async def update_stop_percentage(self, pw: PositionWrapper, ss: SymbolStatus):
current_pl_perc = pw.net_profit_loss_percentage()
# set stop percentage for first time
if not self.stop_percentage:
await ss.add_event(Event(EventKind.TRAILING_STOP_SET, ss.current_tick))
self.stop_percentage = 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)
return