# #!/usr/bin/env python import asyncio import os import threading from time import sleep from typing import List import dotenv from flask import Flask, render_template from flask_socketio import SocketIO from bfxbot import BfxBot from bfxbot.currency import Symbol from bfxbot.models import PositionWrapper, SymbolStatus, Event, EventKind from strategy import TrailingStopStrategy async def bot_loop(): await bot.start() while True: await bot.update() asyncio.new_event_loop() dotenv.load_dotenv() API_KEY = os.getenv("API_KEY") API_SECRET = os.getenv("API_SECRET") 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()) btc_eh = bot.symbol_event_handler(Symbol.BTC) # initializing and starting bot on other thread threading.Thread(target=lambda: asyncio.run(bot_loop())).start() ################################### # Flask callbacks ################################### @app.route('/') def entry(): return render_template('index.html') ################################### # Socker.IO callbacks ################################### @socketio.on("close") def on_message(message: dict): position_id = message['id'] print("I would close position {}".format(position_id)) @socketio.on('connect') def on_connect(): # sleeping on exception to avoid race condition ticks, prices = [], [] while not ticks or not prices: try: ticks = bot.symbol_status(Symbol.BTC).all_ticks() prices = bot.symbol_status(Symbol.BTC).all_prices() except KeyError: sleep(1) socketio.emit("first_connect", {"ticks": ticks, "prices": prices}) ################################### # Bot callbacks ################################### @btc_eh.on_event(EventKind.NEW_TICK) def on_new_tick(event: Event, status: SymbolStatus): # TODO: finalize JSON structure def pos_to_json(pw: PositionWrapper): return { "id": pw.position.id, "amount": pw.position.amount, "base_price": pw.position.base_price, "state": str(pw.state()), "symbol": pw.position.symbol, "profit_loss": pw.net_profit_loss(), "profit_loss_percentage": pw.net_profit_loss_percentage() } tick = event.tick price = status.prices[event.tick] positions: List[PositionWrapper] = status.positions[event.tick] if event.tick in status.positions else [] socketio.emit("new_tick", {"tick": tick, "price": price, "positions": list(map(pos_to_json, positions))}) if __name__ == '__main__': socketio.run(app, debug=True)