From 9955ddf08e1b9d01f8fce3987d7c004d0e73920b Mon Sep 17 00:00:00 2001 From: Giulio De Pasquale Date: Thu, 10 Dec 2020 16:29:26 +0000 Subject: [PATCH] sending new_ticks event --- bfxbot/bfxbot.py | 45 +++++++++++++++++++++++++++++--------------- bfxbot/models.py | 12 ++++++++++-- main.py | 40 +++++++++++++++++++-------------------- static/js/rustico.js | 10 ++++++++-- templates/index.html | 1 - 5 files changed, 68 insertions(+), 40 deletions(-) diff --git a/bfxbot/bfxbot.py b/bfxbot/bfxbot.py index 13a32f8..a48e277 100644 --- a/bfxbot/bfxbot.py +++ b/bfxbot/bfxbot.py @@ -1,13 +1,12 @@ from time import sleep -from typing import Dict - +from typing import Dict, List from bfxbot.bfxwrapper import BfxWrapper from bfxbot.currency import Symbol -from bfxbot.models import SymbolStatus, Ticker, EventHandler, Strategy +from bfxbot.models import SymbolStatus, Ticker, EventHandler, Strategy, Event, EventKind class BfxBot: - def __init__(self, api_key: str, api_secret: str, tick_duration: int = 1): + def __init__(self, api_key: str, api_secret: str, symbols: List[Symbol], tick_duration: int = 1, ): if api_key is None: print("API_KEY is not set!") raise ValueError @@ -20,25 +19,41 @@ class BfxBot: self.status: Dict[Symbol, SymbolStatus] = {} self.ticker: Ticker = Ticker(tick_duration) + if isinstance(symbols, Symbol): + symbols = [symbols] + + self.symbols: List[Symbol] = symbols + + # init symbol statuses + for s in self.symbols: + self.status[s] = SymbolStatus(s) + async def __update_status__(self): active_positions = await self.bfx.get_active_position() - for p in active_positions: - symbol = Symbol.from_str(p.symbol) + for symbol in self.status: + # updating tick + self.status[symbol].current_tick = self.ticker.current_tick - if symbol not in self.status: - self.status[symbol] = SymbolStatus(symbol) + # updating last price + last_price = await self.bfx.get_current_prices(symbol) + last_price = last_price[0] - await self.status[symbol].add_position(p) + self.status[symbol].set_price(self.ticker.current_tick, last_price) - for symbol in self.status.keys(): - active_orders = await self.bfx.get_active_orders(symbol) + # updating positions + for p in [x for x in active_positions if x.symbol == symbol]: + await self.status[p.symbol].add_position(p) - for o in active_orders: - if symbol not in self.status: - self.status[symbol] = SymbolStatus(symbol) + # # updating orders + # active_orders = await self.bfx.get_active_orders(symbol) + # + # for o in active_orders: + # self.status[symbol].add_order(o) + + # emitting event + await self.status[symbol].__add_event__(Event(EventKind.NEW_TICK, 0, self.ticker.current_tick)) - self.status[symbol].add_order(o) def event_handler(self, symbol) -> EventHandler: if symbol not in self.status: diff --git a/bfxbot/models.py b/bfxbot/models.py index eac4aa5..2db3d66 100644 --- a/bfxbot/models.py +++ b/bfxbot/models.py @@ -44,6 +44,7 @@ class EventKind(Enum): TRAILING_STOP_SET = 9, TRAILING_STOP_MOVED = 10, ORDER_SUBMITTED = 11, + NEW_TICK = 12 class Ticker: @@ -93,6 +94,7 @@ class SymbolStatus: def __init__(self, symbol: Symbol, strategy=None): self.symbol = symbol self.eh = EventHandler() + self.prices: Dict[int, float] = {} self.events: List[Event] = [] self.orders: Dict[int, List[Order]] = {} self.positions: Dict[int, List[PositionWrapper]] = {} @@ -143,6 +145,8 @@ class SymbolStatus: pw.set_state(state) await self.eh.call_state(self, pw) + def set_price(self, tick, price): + self.prices[tick] = price class Strategy: """ @@ -167,8 +171,10 @@ class EventHandler: self.any_events = [] self.any_state = [] - async def call_event(self, event: Event, status: SymbolStatus): + async def call_event(self, status: SymbolStatus, event: Event): value = event.kind.value + + # print("CALLING EVENT: {}".format(event)) if value in self.event_handlers: for h in self.event_handlers[value]: if inspect.iscoroutinefunction(h): @@ -182,7 +188,9 @@ class EventHandler: else: h(event, status) - async def call_state(self, state: PositionState, status: SymbolStatus): + async def call_state(self, status: SymbolStatus, pw: PositionWrapper): + state = pw.state + if state in self.state_handlers: for h in self.state_handlers[state]: if inspect.iscoroutinefunction(h): diff --git a/main.py b/main.py index 0b48b0c..10fa225 100755 --- a/main.py +++ b/main.py @@ -492,20 +492,18 @@ import dotenv from bfxbot import BfxBot from bfxbot.currency import Symbol -from bfxbot.models import EventHandler, PositionState, SymbolStatus, Event +from bfxbot.models import EventHandler, PositionState, SymbolStatus, Event, EventKind from strategy import TrailingStopStrategy from flask import Flask, render_template from flask_socketio import SocketIO app = Flask(__name__) -socketio = SocketIO(app) +socketio = SocketIO(app, async_mode="threading") dotenv.load_dotenv() loop = asyncio.new_event_loop() -bot: BfxBot = None -eh: EventHandler = None - +bot = None @app.route('/') def entry(): @@ -531,6 +529,7 @@ def entry(): # while True: # await bot.update() +from flask import request @socketio.on("close") def on_message(message: dict): @@ -540,29 +539,30 @@ def on_message(message: dict): @socketio.on('connect') def start_bot(): - asyncio.set_event_loop(loop) - global bot - global eh + + asyncio.set_event_loop(loop) API_KEY = os.getenv("API_KEY") API_SECRET = os.getenv("API_SECRET") - bot = BfxBot(api_key=API_KEY, api_secret=API_SECRET) - strategy = TrailingStopStrategy() - bot.set_strategy(Symbol.BTC, strategy) - eh = bot.event_handler(Symbol.BTC) - - @eh.on_any_event() - def on_any_event(event: Event, status: SymbolStatus): - print("EMITTING") - socketio.emit("event", {"kind": "a"}) - - threading.Thread(target=lambda: asyncio.run(bot_loop())).start() - print("Bot started.") + if not bot: + bot = BfxBot(api_key=API_KEY, api_secret=API_SECRET, symbols=[Symbol.BTC], tick_duration=20) + strategy = TrailingStopStrategy() + bot.set_strategy(Symbol.BTC, strategy) + threading.Thread(target=lambda: asyncio.run(bot_loop())).start() + print("Bot started.") async def bot_loop(): + global bot + + eh = bot.event_handler(Symbol.BTC) + + @eh.on_event(EventKind.NEW_TICK) + def on_new_tick(event: Event, status: SymbolStatus): + socketio.emit("new_tick", {"tick": event.tick, "price": status.prices[event.tick]}) + await bot.start() while True: diff --git a/static/js/rustico.js b/static/js/rustico.js index 6632c5b..bbc18db 100644 --- a/static/js/rustico.js +++ b/static/js/rustico.js @@ -27,6 +27,12 @@ $(document).ready(function () { }) }) - socket.on("event", () => { - }) + socket.on("connect", function(socket) { + console.log("Connected"); + }); + + socket.on("new_tick", function(data) { + console.log("Tick " + data['tick'] + "| Price: " + data['price']); + }); + }); \ No newline at end of file diff --git a/templates/index.html b/templates/index.html index 1b08b8c..415e60f 100644 --- a/templates/index.html +++ b/templates/index.html @@ -9,7 +9,6 @@ -