core/main.py
2020-12-21 13:16:26 +00:00

129 lines
3.5 KiB
Python
Executable File

# #!/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.bfxwrapper import Balance
from bfxbot.currency import Symbol
from bfxbot.models import PositionWrapper, SymbolStatus, Event, EventKind
from bfxbot.utils import pw_to_posprop, balance_to_json
from strategy import TrailingStopStrategy
async def bot_loop():
await bot.start()
while True:
await bot.update()
loop = 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)
strategy = TrailingStopStrategy()
bot.set_strategy(Symbol.BTC, strategy)
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_position")
def on_close_position(message: dict):
position_id = message['position_id']
loop.run_until_complete(bot.close_position(position_id))
@socketio.on('connect')
def on_connect():
# sleeping on exception to avoid race condition
ticks, prices, positions, balances = [], [], [], []
while not ticks or not prices:
try:
ticks = bot.symbol_status(Symbol.BTC).all_ticks()
prices = bot.symbol_status(Symbol.BTC).all_prices()
positions = bot.symbol_status(Symbol.BTC).current_positions()
balances = loop.run_until_complete(bot.get_balances())
except KeyError:
sleep(1)
socketio.emit("first_connect",
{
"ticks": ticks,
"prices": prices,
"positions": list(map(pw_to_posprop, positions)),
"balances": list(map(balance_to_json, balances))
})
###################################
# Bot callbacks
###################################
@btc_eh.on_event(EventKind.CLOSE_POSITION)
async def on_close_position(event: Event, _):
print("CLOSING!")
await bot.close_position(event.metadata.position_id)
@btc_eh.on_any_position_state()
async def on_any_state(pw: PositionWrapper, ss: SymbolStatus):
await strategy.update_stop_percentage(pw, ss)
@btc_eh.on_event(EventKind.NEW_TICK)
async def on_new_tick(event: Event, status: SymbolStatus):
tick = event.tick
price = status.prices[event.tick]
balances: List[Balance] = await bot.get_balances()
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(pw_to_posprop, positions)),
"balances": list(map(balance_to_json, balances))})
@btc_eh.on_any_event()
def on_any_event(event: Event, _):
socketio.emit("new_event", {
"tick": event.tick,
"kind": event.kind.name
})
if __name__ == '__main__':
socketio.run(app)