tailwind #9
@ -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:
|
||||
|
@ -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):
|
||||
|
40
main.py
40
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:
|
||||
|
@ -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']);
|
||||
});
|
||||
|
||||
});
|
@ -9,7 +9,6 @@
|
||||
<script src="{{ url_for('static', filename='js/jquery-3.5.1.min.js') }}"></script>
|
||||
<script src="{{ url_for('static', filename='js/plotly-latest.min.js') }}"></script>
|
||||
<script src="{{ url_for('static', filename='js/socket.io.min.js') }}"></script>
|
||||
<script src="{{ url_for('static', filename='js/toast.js') }}"></script>
|
||||
<script src="{{ url_for('static', filename='js/rustico.js') }}"></script>
|
||||
</head>
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user