这是indexloc提供的服务,不要输入任何密码
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions main.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
import streamlit as st
from st_pages import Page, show_pages
from st_pages import Page, Section, show_pages, add_page_title

from utils.st_utils import initialize_st_page


initialize_st_page(title="Hummingbot Dashboard", icon="📊")

show_pages(
[
Page("main.py", "Hummingbot Dashboard", "📊"),
Page("pages/strategy_performance/app.py", "Strategy Performance", "🚀"),
Section("Foundation Pages", "🏠"),
Page("pages/bot_orchestration/app.py", "Bot Orchestration", "🐙"),
Page("pages/file_manager/app.py", "File Manager", "🗂"),
Section("Community Pages", "👨‍👩‍👧‍👦"),
Page("pages/strategy_performance/app.py", "Strategy Performance", "🚀"),
Page("pages/backtest_manager/app.py", "Backtest Manager", "⚙️"),
Page("pages/candles_downloader/app.py", "Candles Downloader", "🗂"),
Page("pages/db_inspector/app.py", "DB Inspector", "🔍"),
Expand Down
169 changes: 66 additions & 103 deletions pages/bot_orchestration/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,10 @@

from ui_components.bot_performance_card import BotPerformanceCard
from ui_components.dashboard import Dashboard
from ui_components.editor import Editor
from ui_components.exited_bot_card import ExitedBotCard
from ui_components.file_explorer import FileExplorer
from utils.st_utils import initialize_st_page

initialize_st_page(title="Bot Orchestration", icon="🐙", initial_sidebar_state="collapsed")
initialize_st_page(title="Bot Orchestration", icon="🐙", initial_sidebar_state="expanded")

if "is_broker_running" not in st.session_state:
st.session_state.is_broker_running = False
Expand All @@ -35,21 +33,14 @@
if "selected_strategy" not in st.session_state:
st.session_state.selected_strategy = None

if "selected_file" not in st.session_state:
st.session_state.selected_file = ""

if "editor_tabs" not in st.session_state:
st.session_state.editor_tabs = {}


def manage_broker_container():
if st.session_state.is_broker_running:
docker_manager.stop_container("hummingbot-broker")
with st.spinner('Stopping hummingbot broker... You are not going to be able to manage bots anymore.'):
with st.spinner('Stopping Hummingbot Broker... you will not going to be able to manage bots anymore.'):
time.sleep(5)
else:
docker_manager.create_broker()
with st.spinner('Starting hummingbot broker... This process may take a few seconds'):
with st.spinner('Starting Hummingbot Broker... This process may take a few seconds'):
time.sleep(20)


Expand Down Expand Up @@ -106,109 +97,81 @@ def update_containers_info(docker_manager):


docker_manager = DockerManager()
CARD_WIDTH = 4
CARD_WIDTH = 6
CARD_HEIGHT = 3
NUM_CARD_COLS = 2

if not docker_manager.is_docker_running():
st.warning("Docker is not running. Please start Docker and refresh the page.")
st.stop()
orchestrate, manage = st.tabs(["Orchestrate", "Manage Files"])
update_containers_info(docker_manager)
exited_containers = [container for container in docker_manager.get_exited_containers() if "broker" not in container]


def get_grid_positions(n_cards: int, cols: int = 3, card_width: int = 4, card_height: int = 3):
def get_grid_positions(n_cards: int, cols: int = NUM_CARD_COLS, card_width: int = CARD_HEIGHT, card_height: int = CARD_WIDTH):
rows = n_cards // cols + 1
x_y = [(x * card_width, y * card_height) for x in range(cols) for y in range(rows)]
return sorted(x_y, key=lambda x: (x[1], x[0]))


with orchestrate:
with elements("create_bot"):
with mui.Grid(container=True, spacing=4):
with mui.Grid(item=True, xs=6):
with mui.Paper(elevation=3, style={"padding": "2rem"}, spacing=[2, 2], container=True):
with mui.Grid(container=True, spacing=4):
with mui.Grid(item=True, xs=12):
mui.Typography("🚀 Create Bot", variant="h4")
with mui.Grid(item=True, xs=8):
mui.TextField(label="Bot Name", variant="outlined", onChange=lazy(sync("new_bot_name")),
sx={"width": "100%"})
with mui.Grid(item=True, xs=4):
with mui.Button(onClick=launch_new_bot):
mui.icon.AddCircleOutline()
mui.Typography("Create")
with mui.Grid(item=True, xs=6):
with mui.Paper(elevation=3, style={"padding": "2rem"}, spacing=[2, 2], container=True):
with mui.Grid(container=True, spacing=4):
with mui.Grid(item=True, xs=12):
mui.Typography("🐙 Manage Broker", variant="h4")
with mui.Grid(item=True, xs=8):
mui.Typography("To control and monitor your bots you need to launch Hummingbot Broker."
"This component enables two-way communication with bots.")
with mui.Grid(item=True, xs=4):
button_text = "Stop Broker" if st.session_state.is_broker_running else "Start Broker"
color = "error" if st.session_state.is_broker_running else "success"
icon = mui.icon.Stop if st.session_state.is_broker_running else mui.icon.PlayCircle
with mui.Button(onClick=manage_broker_container, color=color):
icon()
mui.Typography(button_text)

with elements("active_instances_board"):
with mui.Paper(elevation=3, style={"padding": "2rem"}, spacing=[2, 2], container=True):
mui.Typography("🦅 Active Bots", variant="h4")
if st.session_state.is_broker_running:
quantity_of_active_bots = len(st.session_state.active_bots)
if quantity_of_active_bots > 0:
# TODO: Make layout configurable
grid_positions = get_grid_positions(n_cards=quantity_of_active_bots, cols=3,
card_width=CARD_WIDTH, card_height=CARD_HEIGHT)
active_instances_board = Dashboard()
for (bot, config), (x, y) in zip(st.session_state.active_bots.items(), grid_positions):
st.session_state.active_bots[bot]["bot_performance_card"] = BotPerformanceCard(active_instances_board,
x, y,
CARD_WIDTH, CARD_HEIGHT)
with active_instances_board():
for bot, config in st.session_state.active_bots.items():
st.session_state.active_bots[bot]["bot_performance_card"](config)
else:
mui.Alert("No active bots found. Please create a new bot.", severity="info", sx={"margin": "1rem"})
with elements("create_bot"):
with mui.Grid(container=True, spacing=4):
with mui.Grid(item=True, xs=6):
with mui.Paper(style={"padding": "2rem"}, variant="outlined"):
with mui.Grid(container=True, spacing=4):
with mui.Grid(item=True, xs=12):
mui.Typography("🚀 Create Instance", variant="h4")
with mui.Grid(item=True, xs=8):
mui.TextField(label="Bot Name", variant="outlined", onChange=lazy(sync("new_bot_name")),
sx={"width": "100%"})
with mui.Grid(item=True, xs=4):
with mui.Button(onClick=launch_new_bot, variant="contained", color="success"):
mui.icon.AddCircleOutline()
mui.Typography("Create")
with mui.Grid(item=True, xs=6):
with mui.Paper(style={"padding": "2rem"}, variant="outlined"):
with mui.Grid(container=True, spacing=4):
with mui.Grid(item=True, xs=12):
mui.Typography("🐙 Manage Broker", variant="h4")
with mui.Grid(item=True, xs=8):
mui.Typography("Hummingbot Broker helps you control and monitor your bot instances.")
with mui.Grid(item=True, xs=4):
button_text = "Stop Broker" if st.session_state.is_broker_running else "Start Broker"
color = "error" if st.session_state.is_broker_running else "success"
icon = mui.icon.Stop if st.session_state.is_broker_running else mui.icon.PlayCircle
with mui.Button(onClick=manage_broker_container, color=color, variant="contained"):
icon()
mui.Typography(button_text)

with elements("active_instances_board"):
with mui.Paper(style={"padding": "2rem"}, variant="outlined"):
mui.Typography("🦅 Active Instances", variant="h4")
if st.session_state.is_broker_running:
quantity_of_active_bots = len(st.session_state.active_bots)
if quantity_of_active_bots > 0:
# TODO: Make layout configurable
grid_positions = get_grid_positions(n_cards=quantity_of_active_bots, cols=NUM_CARD_COLS,
card_width=CARD_WIDTH, card_height=CARD_HEIGHT)
active_instances_board = Dashboard()
for (bot, config), (x, y) in zip(st.session_state.active_bots.items(), grid_positions):
st.session_state.active_bots[bot]["bot_performance_card"] = BotPerformanceCard(active_instances_board,
x, y,
CARD_WIDTH, CARD_HEIGHT)
with active_instances_board():
for bot, config in st.session_state.active_bots.items():
st.session_state.active_bots[bot]["bot_performance_card"](config)
else:
mui.Alert("Please start the Hummingbot Broker to control your bots.", severity="warning", sx={"margin": "1rem"})
with elements("stopped_instances_board"):
grid_positions = get_grid_positions(n_cards=len(exited_containers), cols=3, card_width=4, card_height=3)
exited_instances_board = Dashboard()
for exited_instance, (x, y) in zip(exited_containers, grid_positions):
st.session_state.exited_bots[exited_instance] = ExitedBotCard(exited_instances_board, x, y,
CARD_WIDTH, 1)
with mui.Paper(elevation=3, style={"padding": "2rem"}, spacing=[2, 2], container=True):
mui.Typography("💤 Stopped Bots", variant="h4")
with exited_instances_board():
for bot, card in st.session_state.exited_bots.items():
card(bot)


with manage:
if "w" not in st.session_state:
board = Dashboard()
w = SimpleNamespace(
dashboard=board,
file_explorer=FileExplorer(board, 0, 0, 3, 7),
editor=Editor(board, 4, 0, 9, 7),
)
st.session_state.w = w

else:
w = st.session_state.w

for tab_name, content in st.session_state.editor_tabs.items():
if tab_name not in w.editor._tabs:
w.editor.add_tab(tab_name, content["content"], content["language"], content["file_path"])

with elements("bot_config"):
with mui.Paper(elevation=3, style={"padding": "2rem"}, spacing=[2, 2], container=True):
mui.Typography("🗂Files Management", variant="h3", sx={"margin-bottom": "2rem"})
event.Hotkey("ctrl+s", sync(), bindInputs=True, overrideDefault=True)
with w.dashboard():
w.file_explorer()
w.editor()
mui.Alert("No active bots found. Please create a new bot.", severity="info", sx={"margin": "1rem"})
else:
mui.Alert("Please start Hummingbot Broker to control your bots.", severity="warning", sx={"margin": "1rem"})
with elements("stopped_instances_board"):
grid_positions = get_grid_positions(n_cards=len(exited_containers), cols=NUM_CARD_COLS, card_width=CARD_WIDTH, card_height=CARD_HEIGHT)
exited_instances_board = Dashboard()
for exited_instance, (x, y) in zip(exited_containers, grid_positions):
st.session_state.exited_bots[exited_instance] = ExitedBotCard(exited_instances_board, x, y,
CARD_WIDTH, 1)
with mui.Paper(style={"padding": "2rem"}, variant="outlined"):
mui.Typography("💤 Inactive Instances", variant="h4")
with exited_instances_board():
for bot, card in st.session_state.exited_bots.items():
card(bot)
13 changes: 13 additions & 0 deletions pages/file_manager/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
### Description

This page helps you manage and edit script files to run with Hummingbot instances:

- Selecting files
- Editing and saving files

### Maintainers

This page is maintained by Hummingbot Foundation:

* [cardosfede](https://github.com/cardosfede)
* [fengtality](https://github.com/fengtality)
44 changes: 44 additions & 0 deletions pages/file_manager/app.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import streamlit as st
from streamlit_elements import elements, mui, lazy, sync, event

from types import SimpleNamespace

import streamlit as st
from streamlit_elements import elements, mui, lazy, sync, event

from ui_components.dashboard import Dashboard
from ui_components.file_explorer import FileExplorer
from ui_components.editor import Editor
from utils.st_utils import initialize_st_page

initialize_st_page(title="File Manager", icon="🗂️", initial_sidebar_state="expanded")

if "editor_tabs" not in st.session_state:
st.session_state.editor_tabs = {}

# TODO: Use this to save the current file selected
if "selected_file" not in st.session_state:
st.session_state.selected_file = ""

if "w" not in st.session_state:
board = Dashboard()
w = SimpleNamespace(
dashboard=board,
file_explorer=FileExplorer(board, 0, 0, 3, 7),
editor=Editor(board, 4, 0, 9, 7),
)
st.session_state.w = w
else:
w = st.session_state.w

for tab_name, content in st.session_state.editor_tabs.items():
if tab_name not in w.editor._tabs:
w.editor.add_tab(tab_name, content["content"], content["language"], content["file_path"])

with elements("bot_config"):
with mui.Paper(style={"padding": "2rem"}, variant="outlined"):
mui.Typography("Select a file and click ✏️ to edit it or 🗑️ to delete it. Click 💾 to save your changes.", variant="body1", sx={"margin-bottom": "2rem"})
event.Hotkey("ctrl+s", sync(), bindInputs=True, overrideDefault=True)
with w.dashboard():
w.file_explorer()
w.editor()
29 changes: 17 additions & 12 deletions ui_components/bot_performance_card.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,10 @@ def __call__(self, bot_config: dict):
st.session_state.active_bots[bot_name]["selected_strategy"] = strategies[0]

with mui.Card(key=self._key,
sx={"display": "flex", "flexDirection": "column", "borderRadius": 3, "overflow": "hidden"},
sx={"display": "flex", "flexDirection": "column", "borderRadius": 2, "overflow": "hidden"},
elevation=2):
color = "green" if bot_config["is_running"] else "red"
subheader_message = "Running" if bot_config["is_running"] else "Stopped"
subheader_message = "Running " + st.session_state.active_bots[bot_name]["selected_strategy"] if bot_config["is_running"] else "Stopped"
mui.CardHeader(
title=bot_config["bot_name"],
subheader=subheader_message,
Expand All @@ -52,10 +52,16 @@ def __call__(self, bot_config: dict):
)
if bot_config["is_running"]:
with mui.CardContent(sx={"flex": 1}):
mui.Typography("Status:")
mui.Typography(bot_config["status"])
mui.Typography("Trades:")
mui.Typography(str(bot_config["trades"]))
with mui.Paper(elevation=2, sx={"padding": 2, "marginBottom": 2}):
mui.Typography("Status", variant="h6")
mui.Typography(bot_config["status"])
with mui.Accordion(sx={"padding": 2, "marginBottom": 2}):
with mui.AccordionSummary(expandIcon="▼"):
mui.Typography("Trades" + "(" + str(len(bot_config["trades"])) + ")", variant="h6")
with mui.AccordionDetails():
mui.Typography(str(bot_config["trades"]))
mui.Typography("Run the following command in Bash/Terminal to attach to the bot instance:")
mui.TextField(disabled=True, value="docker attach " + bot_name, sx={"width": "100%"})

else:
with mui.CardContent(sx={"flex": 1}):
Expand All @@ -69,12 +75,11 @@ def __call__(self, bot_config: dict):
mui.MenuItem(script, value=script)
for strategy in strategies:
mui.MenuItem(strategy, value=strategy)

with mui.Grid(item=True, xs=4):
with mui.Button(onClick=lambda x: self.start_strategy(bot_name, bot_config["broker_client"])):
with mui.Button(onClick=lambda x: self.start_strategy(bot_name, bot_config["broker_client"]), variant="contained", color="success"):
mui.icon.PlayCircle()
mui.Typography("Start")
with mui.CardActions(disableSpacing=True):
with mui.Button(onClick=lambda: DockerManager().stop_container(bot_name)):
mui.icon.DeleteForever()
mui.Typography("Stop Container")
with mui.CardActions():
with mui.Button(onClick=lambda: DockerManager().stop_container(bot_name), variant="contained", color="error"):
mui.icon.DeleteForever()
mui.Typography("Stop Instance")
6 changes: 3 additions & 3 deletions ui_components/exited_bot_card.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,10 @@ def __call__(self, bot_name: str):
className=self._draggable_class,
)

with mui.CardActions(disableSpacing=True):
with mui.Button(onClick=lambda: DockerManager().start_container(bot_name), color="success"):
with mui.CardActions():
with mui.Button(onClick=lambda: DockerManager().start_container(bot_name), variant="contained", color="success", sx={"pr": "2"}):
mui.icon.PlayCircle()
mui.Typography("Start Container")
with mui.Button(onClick=lambda: self.remove_container(bot_name), color="error"):
with mui.Button(onClick=lambda: self.remove_container(bot_name), variant="contained", color="error"):
mui.icon.DeleteForever()
mui.Typography("Delete Container")
2 changes: 1 addition & 1 deletion ui_components/file_explorer.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ def __call__(self):
with mui.Grid(container=True, spacing=4, sx={"display": "flex", "alignItems": "center"}):
with mui.Grid(item=True, xs=6, sx={"display": "flex", "alignItems": "center"}):
mui.icon.Folder()
mui.Typography("File Explorer")
mui.Typography("/bot_configs/")
with mui.Grid(item=True, xs=6, sx={"display": "flex", "justifyContent": "flex-end"}):
mui.IconButton(mui.icon.Delete, onClick=self.delete_file, sx={"mx": 1})
mui.IconButton(mui.icon.Edit, onClick=self.edit_file, sx={"mx": 1})
Expand Down
Loading