mirror of
https://github.com/aljazceru/hummingbot-dashboard.git
synced 2025-12-30 19:44:25 +01:00
(feat) update readme and bots manager ui
This commit is contained in:
@@ -1,62 +1,43 @@
|
||||
## Requirements
|
||||
|
||||
You will need to install [StreamLit](https://streamlit.io/). For information about Streamlit installation, see the instructions located at https://docs.streamlit.io/library/get-started/installation.
|
||||
|
||||
You will also need to install either [Anaconda](https://www.anaconda.com/) or [Miniconda](https://docs.conda.io/en/latest/miniconda.html) to get Conda:
|
||||
* [Anaconda](https://www.anaconda.com/) is a comprehensive Python distribution that includes a large number of pre-installed data science libraries and packages. It is designed to be an all-in-one solution for data science and machine learning tasks. When you install Anaconda, it comes with a collection of popular Python packages like NumPy, pandas, matplotlib, scikit-learn, and more.
|
||||
* [Miniconda](https://docs.conda.io/en/latest/miniconda.html) is a minimal version of Anaconda. It includes only the essential components, such as Python interpreter and Conda package manager. Unlike Anaconda, Miniconda doesn't come with pre-installed packages, which makes its download size much smaller.
|
||||
|
||||
This repository is maintained by Hummingbot Foundation as a companion for users of [Hummingbot](https://github.com/hummingbot/hummingbot), the open source framework for building high-frequency crypto trading bots.
|
||||
|
||||
Watch this video to understand how it works:
|
||||
https://www.loom.com/share/72d05bcbaf4048a399e3f9247d756a63
|
||||
|
||||
## Requirements
|
||||
|
||||
* 8 GB memory or more (On AWS, this is a `t2.large` instance)
|
||||
* Linux / Debian / MacOS
|
||||
|
||||
## Installation
|
||||
|
||||
1. Install Steamlit and Conda packages utilizing their instructions for your specific environment:
|
||||
* Install [StreamLit](https://docs.streamlit.io/library/get-started/installation)
|
||||
* Install [Anaconda](https://docs.anaconda.com/free/anaconda/install/index.html) or [Miniconda](https://docs.conda.io/en/latest/miniconda.html)
|
||||
1 - Install dependencies:
|
||||
|
||||
2. Clone this repo and navigate to the created directory
|
||||
* [Docker Engine](https://docs.docker.com/engine/install/ubuntu/)
|
||||
* [Miniconda](https://docs.conda.io/en/latest/miniconda.html) or [Anaconda](https://www.anaconda.com/):
|
||||
|
||||
2 - Clone repo and navigate to the created directory
|
||||
```bash
|
||||
git clone https://github.com/hummingbot/dashboard.git
|
||||
cd dashboard
|
||||
```
|
||||
|
||||
3. Run command to create an isolated `conda` environment and install dependencies
|
||||
```
|
||||
3 - Create `conda` environment and install dependencies
|
||||
```bash
|
||||
make env_create
|
||||
```
|
||||
|
||||
4. Activate the isolated 'conda' environment
|
||||
4 - Activate the isolated 'conda' environment
|
||||
```bash
|
||||
conda activate dashboard
|
||||
```
|
||||
|
||||
5. Run the app
|
||||
5 - Start the dashboard
|
||||
```bash
|
||||
streamlit run main.py
|
||||
```
|
||||
|
||||
## Data Feed
|
||||
|
||||
Your `dashboard` environment needs to have access to the database for your Hummingbot environment. This is done by setting up a symbolic link to the 'data' directory of your running Hummingbot instance.
|
||||
|
||||
The data directory differs for Docker versus Source installed Hummingbot. Data directory for each is as follows:
|
||||
* Docker installed: /path/to/hummingbot/hummingbot_files/data
|
||||
* Source installed: /path/to/hummingbot/data
|
||||
|
||||
|
||||
Create a symlink to your Hummingbot `/data` directory
|
||||
```bash
|
||||
# replace `/path/to/hummingbotdata` with the actual path
|
||||
ln -s /path/to/hummingbotdata data
|
||||
|
||||
# if you need to remove the symlink
|
||||
unlink data
|
||||
```
|
||||
|
||||
## Updating Dependencies
|
||||
## Updating
|
||||
|
||||
To update the `dashboard` environment for changes to dependencies defined in `environment.yml`, remove the environment and re-create it:
|
||||
```
|
||||
@@ -69,3 +50,29 @@ To updated the `dashboard` source for latest version, run:
|
||||
cd dashboard
|
||||
git pull
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Docker permissions
|
||||
|
||||
If you get an error like `Permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock`, run this command to enable Docker permissions:
|
||||
```
|
||||
sudo chmod 6666 /var/run/docker.sock
|
||||
```
|
||||
|
||||
### Sym-link data directory
|
||||
|
||||
To use the [Strategy Performance page](https://github.com/hummingbot/dashboard/wiki/%F0%9F%9A%80-Strategy-Performance), you need to establish a symbolic link to the `data` directory of your running Hummingbot instance:
|
||||
|
||||
The `data` directory differs for Docker versus Source installed Hummingbot:
|
||||
* Docker installed: `/path/to/hummingbot/hummingbot_files/data`
|
||||
* Source installed: `/path/to/hummingbot/data`
|
||||
|
||||
Create a symlink to your Hummingbot `/data` directory
|
||||
```bash
|
||||
# replace `/path/to/hummingbotdata` with the actual path
|
||||
ln -s /path/to/hummingbotdata data
|
||||
|
||||
# if you need to remove the symlink
|
||||
unlink data
|
||||
```
|
||||
|
||||
16
README.md
16
README.md
@@ -4,9 +4,9 @@ Hummingbot Dashboard is a community project to build dashboards that help you de
|
||||
|
||||
Here are the current dashboards in the collection:
|
||||
|
||||
* 🚀 **Strategy Performance**: Analyze the performance of a running Hummingbot instance
|
||||
* 🐙 **Bot Orchestration**: Deploy and manage Hummingbot instances
|
||||
* ⚙️ **Backtest Manager**: Deploy and manage backtests of directional strategies
|
||||
* ⚙️ **Backtest Manager**: Backtest strategies against historical data and optimize hyper-parameters
|
||||
* 🚀 **Strategy Performance**: Analyze the performance of a running Hummingbot instance
|
||||
* 🗂 **Candles Downloader**: Download historical exchange data as OHLVC candles. Supports multiple trading pairs and custom time ranges/intervals.
|
||||
* 🔍 **DB Inspector**: Inspect and analyze the orders and trades data contained in a Hummingbot strategy database
|
||||
* 🧙 **Token Spreads**: Identify cross-exchange trading opportunities by analyzing differences in token spreads across venues
|
||||
@@ -18,14 +18,8 @@ This project is built using [StreamLit](https://streamlit.io/) and uses Anaconda
|
||||
|
||||
See [Installation](https://github.com/hummingbot/dashboard/blob/main/INSTALLATION.md) for how to install and update the dashboard.
|
||||
|
||||
### Contributions
|
||||
|
||||
We welcome contributions from the community! See [Contribution](https://github.com/hummingbot/dashboard/blob/main/CONTRIBUTING.md) for more information.
|
||||
|
||||
### Meetings
|
||||
|
||||
We hold bi-weekly livestream Dashboard project meetings. You can participate on our [Discord](https://discord.gg/hummingbot)
|
||||
* Alternating Wenesdays, 3pm GMT / 11am EST / 8am PST / 11pm SIN
|
||||
* Design, Status, Demos, etc
|
||||
### Contributions and feedback
|
||||
|
||||
We welcome contributions from the community! See [Contributing](https://github.com/hummingbot/dashboard/blob/main/CONTRIBUTING.md) for more information.
|
||||
|
||||
To provide feedback, submit a [Github issue](https://github.com/hummingbot/dashboard/issues) or join the #dashboard channel in our [Discord](https://discord.gg/hummingbot).
|
||||
|
||||
@@ -15,7 +15,7 @@ from ui_components.dashboard import Dashboard
|
||||
from ui_components.exited_bot_card import ExitedBotCard
|
||||
from utils.st_utils import initialize_st_page
|
||||
|
||||
initialize_st_page(title="Bot Orchestration", icon="🐙", initial_sidebar_state="expanded")
|
||||
initialize_st_page(title="Bots Manager", icon="🦅", initial_sidebar_state="collapsed")
|
||||
|
||||
if "is_broker_running" not in st.session_state:
|
||||
st.session_state.is_broker_running = False
|
||||
@@ -118,37 +118,43 @@ def get_grid_positions(n_cards: int, cols: int = NUM_CARD_COLS, card_width: int
|
||||
|
||||
|
||||
with elements("create_bot"):
|
||||
with mui.Grid(container=True, spacing=4):
|
||||
with mui.Grid(container=True, spacing=2):
|
||||
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(container=True, spacing=2):
|
||||
with mui.Grid(item=True, xs=12):
|
||||
mui.Typography("🚀 Create Instance", variant="h4")
|
||||
mui.Typography("🚀 Create Instance", variant="h5")
|
||||
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"):
|
||||
with mui.Button(onClick=launch_new_bot,
|
||||
variant="outlined",
|
||||
color="success",
|
||||
sx={"width": "100%", "height": "100%"}):
|
||||
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(container=True, spacing=2):
|
||||
with mui.Grid(item=True, xs=12):
|
||||
mui.Typography("🐙 Manage Broker", variant="h4")
|
||||
mui.Typography("🐙 Manage Broker", variant="h5")
|
||||
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"
|
||||
button_text = "Stop" if st.session_state.is_broker_running else "Start"
|
||||
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"):
|
||||
with mui.Button(onClick=manage_broker_container,
|
||||
color=color,
|
||||
variant="outlined",
|
||||
sx={"width": "100%", "height": "100%"}):
|
||||
icon()
|
||||
mui.Typography(button_text)
|
||||
|
||||
with elements("active_instances_board"):
|
||||
with mui.Paper(style={"padding": "2rem"}, variant="outlined"):
|
||||
mui.Typography("🦅 Active Instances", variant="h4")
|
||||
with mui.Paper(sx={"padding": "2rem"}, variant="outlined"):
|
||||
mui.Typography("🦅 Active Instances", variant="h5")
|
||||
if st.session_state.is_broker_running:
|
||||
quantity_of_active_bots = len(st.session_state.active_bots)
|
||||
if quantity_of_active_bots > 0:
|
||||
@@ -174,7 +180,7 @@ with elements("stopped_instances_board"):
|
||||
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")
|
||||
mui.Typography("💤 Stopped Instances", variant="h5")
|
||||
with exited_instances_board():
|
||||
for bot, card in st.session_state.exited_bots.items():
|
||||
card(bot)
|
||||
|
||||
@@ -40,46 +40,56 @@ class BotPerformanceCard(Dashboard.Item):
|
||||
with mui.Card(key=self._key,
|
||||
sx={"display": "flex", "flexDirection": "column", "borderRadius": 2, "overflow": "auto"},
|
||||
elevation=2):
|
||||
color = "green" if bot_config["is_running"] else "red"
|
||||
subheader_message = "Running " + st.session_state.active_bots[bot_name]["selected_strategy"] if bot_config["is_running"] else "Stopped"
|
||||
color = "green" if bot_config["is_running"] else "grey"
|
||||
subheader_message = "Running " + st.session_state.active_bots[bot_name]["selected_strategy"] if bot_config["is_running"] else "Not running"
|
||||
mui.CardHeader(
|
||||
title=bot_config["bot_name"],
|
||||
subheader=subheader_message,
|
||||
avatar=mui.Avatar("🤖", sx={"bgcolor": color}),
|
||||
action=mui.IconButton(mui.icon.Stop, onClick=lambda: bot_config["broker_client"].stop()) if bot_config[
|
||||
"is_running"] else mui.IconButton(mui.icon.BuildCircle),
|
||||
# action=mui.IconButton(mui.icon.Stop, onClick=lambda: bot_config["broker_client"].stop()) if bot_config[
|
||||
# "is_running"] else mui.IconButton(mui.icon.BuildCircle),
|
||||
className=self._draggable_class,
|
||||
)
|
||||
if bot_config["is_running"]:
|
||||
with mui.CardContent(sx={"flex": 1}):
|
||||
with mui.Paper(elevation=2, sx={"padding": 2, "marginBottom": 2}):
|
||||
mui.Typography("Status", variant="h6")
|
||||
mui.Typography(bot_config["status"])
|
||||
mui.Typography("Status")
|
||||
mui.Typography(bot_config["status"], sx={"fontSize": "0.75rem"})
|
||||
with mui.Accordion(sx={"padding": 2, "marginBottom": 2}):
|
||||
with mui.AccordionSummary(expandIcon="▼"):
|
||||
mui.Typography("Trades" + "(" + str(len(bot_config["trades"])) + ")", variant="h6")
|
||||
mui.Typography("Trades" + "(" + str(len(bot_config["trades"])) + ")")
|
||||
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%"})
|
||||
|
||||
mui.Typography(str(bot_config["trades"]), sx={"fontSize": "0.75rem"})
|
||||
else:
|
||||
with mui.CardContent(sx={"flex": 1}):
|
||||
with mui.Grid(container=True, spacing=2):
|
||||
with mui.Grid(item=True, xs=12):
|
||||
mui.Typography("Select a strategy:")
|
||||
mui.Typography("Select a strategy config file (.yml) or script (.py) to run:")
|
||||
with mui.Grid(item=True, xs=8):
|
||||
with mui.Select(onChange=lazy(lambda x, y: self.set_strategy(x, y, bot_name)),
|
||||
sx={"width": "100%"}):
|
||||
for strategy in strategies:
|
||||
mui.MenuItem(strategy, value=strategy, divider=True, sx={"fontWeight": "bold"})
|
||||
for script in scripts:
|
||||
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"]), variant="contained", color="success"):
|
||||
with mui.Button(onClick=lambda x: self.start_strategy(bot_name, bot_config["broker_client"]),
|
||||
variant="outlined",
|
||||
color="success",
|
||||
sx={"width": "100%", "height": "100%"}):
|
||||
mui.icon.PlayCircle()
|
||||
mui.Typography("Start")
|
||||
with mui.CardActions():
|
||||
with mui.Button(onClick=lambda: DockerManager().stop_container(bot_name), variant="contained", color="error"):
|
||||
mui.icon.DeleteForever()
|
||||
mui.Typography("Stop Instance")
|
||||
with mui.Grid(container=True, spacing=2):
|
||||
with mui.Grid(item=True, xs=6):
|
||||
with mui.Button(onClick=lambda: DockerManager().stop_container(bot_name),
|
||||
variant="outlined",
|
||||
color="error",
|
||||
sx={"width": "100%", "height": "100%"}):
|
||||
mui.icon.DeleteForever()
|
||||
mui.Typography("Stop Instance")
|
||||
with mui.Grid(item=True, xs=6):
|
||||
mui.TextField(disabled=True,
|
||||
label="Attach to bot instance",
|
||||
value="docker attach " + bot_name,
|
||||
sx={"width": "100%"})
|
||||
|
||||
@@ -20,19 +20,28 @@ class ExitedBotCard(Dashboard.Item):
|
||||
|
||||
def __call__(self, bot_name: str):
|
||||
with mui.Card(key=self._key,
|
||||
sx={"display": "flex", "flexDirection": "column", "borderRadius": 3, "overflow": "hidden"},
|
||||
sx={"display": "flex", "flexDirection": "column", "borderRadius": 2, "overflow": "auto"},
|
||||
elevation=2):
|
||||
mui.CardHeader(
|
||||
title=bot_name,
|
||||
subheader="Stopped",
|
||||
avatar=mui.Avatar("💀", sx={"bgcolor": "grey"}),
|
||||
avatar=mui.Avatar("💀", sx={"bgcolor": "black"}),
|
||||
className=self._draggable_class,
|
||||
)
|
||||
|
||||
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), variant="contained", color="error"):
|
||||
mui.icon.DeleteForever()
|
||||
mui.Typography("Delete Container")
|
||||
with mui.Grid(container=True, spacing=2):
|
||||
with mui.Grid(item=True, xs=6):
|
||||
with mui.Button(onClick=lambda: DockerManager().start_container(bot_name),
|
||||
variant="outlined",
|
||||
color="success",
|
||||
sx={"width": "100%"}):
|
||||
mui.icon.PlayCircle()
|
||||
mui.Typography("Start Instance")
|
||||
with mui.Grid(item=True, xs=6):
|
||||
with mui.Button(onClick=lambda: self.remove_container(bot_name),
|
||||
variant="outlined",
|
||||
color="error",
|
||||
sx={"width": "100%"}):
|
||||
mui.icon.DeleteForever()
|
||||
mui.Typography("Delete Instance")
|
||||
|
||||
Reference in New Issue
Block a user