From 3ba16a617337ab06e913db1024b481be9e4a9302 Mon Sep 17 00:00:00 2001 From: cardosofede Date: Thu, 23 Feb 2023 16:20:43 -0300 Subject: [PATCH] (feat) deployment scenarios --- .gitignore | 115 +------------ autostart_hummingbot_compose/README.md | 39 +++++ .../docker-compose.yml | 21 +++ .../conf/strategies/conf_pure_mm_1.yml | 150 +++++++++++++++++ .../hummingbot_files/scripts/format_status.py | 47 ++++++ bash_scripts/README.md | 73 ++++++++ bash_scripts/gateway-copy-certs.sh | 89 ++++++++++ bash_scripts/gateway-create.sh | 157 ++++++++++++++++++ bash_scripts/hummingbot-create.sh | 105 ++++++++++++ bash_scripts/hummingbot-start.sh | 21 +++ bash_scripts/hummingbot-update.sh | 148 +++++++++++++++++ hummingbot_gateway_compose/README.md | 38 +++++ hummingbot_gateway_compose/docker-compose.yml | 30 ++++ multiple_hummingbot_gateway_compose/README.md | 47 ++++++ .../docker-compose.yml | 49 ++++++ simple_hummingbot_compose/README.md | 16 ++ simple_hummingbot_compose/docker-compose.yml | 18 ++ 17 files changed, 1050 insertions(+), 113 deletions(-) create mode 100644 autostart_hummingbot_compose/README.md create mode 100644 autostart_hummingbot_compose/docker-compose.yml create mode 100644 autostart_hummingbot_compose/hummingbot_files/conf/strategies/conf_pure_mm_1.yml create mode 100644 autostart_hummingbot_compose/hummingbot_files/scripts/format_status.py create mode 100644 bash_scripts/README.md create mode 100644 bash_scripts/gateway-copy-certs.sh create mode 100644 bash_scripts/gateway-create.sh create mode 100644 bash_scripts/hummingbot-create.sh create mode 100644 bash_scripts/hummingbot-start.sh create mode 100644 bash_scripts/hummingbot-update.sh create mode 100644 hummingbot_gateway_compose/README.md create mode 100644 hummingbot_gateway_compose/docker-compose.yml create mode 100644 multiple_hummingbot_gateway_compose/README.md create mode 100644 multiple_hummingbot_gateway_compose/docker-compose.yml create mode 100644 simple_hummingbot_compose/README.md create mode 100644 simple_hummingbot_compose/docker-compose.yml diff --git a/.gitignore b/.gitignore index b6e4761..d059872 100644 --- a/.gitignore +++ b/.gitignore @@ -6,102 +6,6 @@ __pycache__/ # C extensions *.so -# Distribution / packaging -.Python -build/ -develop-eggs/ -dist/ -downloads/ -eggs/ -.eggs/ -lib/ -lib64/ -parts/ -sdist/ -var/ -wheels/ -pip-wheel-metadata/ -share/python-wheels/ -*.egg-info/ -.installed.cfg -*.egg -MANIFEST - -# PyInstaller -# Usually these files are written by a python script from a template -# before PyInstaller builds the exe, so as to inject date/other infos into it. -*.manifest -*.spec - -# Installer logs -pip-log.txt -pip-delete-this-directory.txt - -# Unit test / coverage reports -htmlcov/ -.tox/ -.nox/ -.coverage -.coverage.* -.cache -nosetests.xml -coverage.xml -*.cover -*.py,cover -.hypothesis/ -.pytest_cache/ - -# Translations -*.mo -*.pot - -# Django stuff: -*.log -local_settings.py -db.sqlite3 -db.sqlite3-journal - -# Flask stuff: -instance/ -.webassets-cache - -# Scrapy stuff: -.scrapy - -# Sphinx documentation -docs/_build/ - -# PyBuilder -target/ - -# Jupyter Notebook -.ipynb_checkpoints - -# IPython -profile_default/ -ipython_config.py - -# pyenv -.python-version - -# pipenv -# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. -# However, in case of collaboration, if having platform-specific dependencies or dependencies -# having no cross-platform support, pipenv may install dependencies that don't work, or not -# install all needed dependencies. -#Pipfile.lock - -# PEP 582; used by e.g. github.com/David-OConnor/pyflow -__pypackages__/ - -# Celery stuff -celerybeat-schedule -celerybeat.pid - -# SageMath parsed files -*.sage.py - -# Environments .env .venv env/ @@ -110,20 +14,5 @@ ENV/ env.bak/ venv.bak/ -# Spyder project settings -.spyderproject -.spyproject - -# Rope project settings -.ropeproject - -# mkdocs documentation -/site - -# mypy -.mypy_cache/ -.dmypy.json -dmypy.json - -# Pyre type checker -.pyre/ +*.log +*.pem diff --git a/autostart_hummingbot_compose/README.md b/autostart_hummingbot_compose/README.md new file mode 100644 index 0000000..12d8f76 --- /dev/null +++ b/autostart_hummingbot_compose/README.md @@ -0,0 +1,39 @@ +# Deploy and autostart a single Hummingbot instance with docker Compose + +## How to use it + +- Make sure you have docker and docker-compose installed. +- To autostart you will need the config_file of the strategy, and the password already generated. +- **Important:** + - In this example the password generated is `a` and it was done in a Mac, if you are using a different OS + or you want to use a different password, make sure to delete the .password_verification file under the conf folder and follow the + instructions on troubleshooting. + - You can autostart a strategy or a script. In this case on line `13` we are autostarting a script that is inside the scripts folder. +If you want to start a strategy, there is one config file under conf/strategies, you can just change format_status.py for conf_pure_mm_1.yml to test it! +- Make sure that the compose file on lines `12` and `13` have the correct path to the config file and the password. +- Run the following command: + ``` + docker-compose up -d + ``` + +- Attach the terminal: + ``` + docker attach simple_hummingbot_compose-bot-1 + ``` + +- Now you have Hummingbot running and autostarted! Remember that you can detach the terminal without stopping the bot by pressing `Ctrl + P` and `Ctrl + Q`. + + +## Troubleshooting +If you don't have the password you can + - Remove the line `12` and `13` from the compose file + - Start the bot with the following command: + ``` + docker-compose up -d + ``` + - Attach the terminal: + ``` + docker attach autostart_hummingbot_compose-bot-1 + ``` + - Create the password and exit the client + - Add the line `12` and `13` to the compose file and start over! \ No newline at end of file diff --git a/autostart_hummingbot_compose/docker-compose.yml b/autostart_hummingbot_compose/docker-compose.yml new file mode 100644 index 0000000..52d96d8 --- /dev/null +++ b/autostart_hummingbot_compose/docker-compose.yml @@ -0,0 +1,21 @@ +version: "3.9" +services: + bot: + image: hummingbot/hummingbot:latest + volumes: + - "./hummingbot_files/conf:/conf" + - "./hummingbot_files/logs:/logs" + - "./hummingbot_files/data:/data" + - "./hummingbot_files/scripts:/scripts" + - "./hummingbot_files/certs:/certs" + environment: + - CONFIG_PASSWORD=a + - CONFIG_FILE_NAME=format_status.py + logging: + driver: "json-file" + options: + max-size: "10m" + max-file: 5 + tty: true + stdin_open: true + network_mode: host diff --git a/autostart_hummingbot_compose/hummingbot_files/conf/strategies/conf_pure_mm_1.yml b/autostart_hummingbot_compose/hummingbot_files/conf/strategies/conf_pure_mm_1.yml new file mode 100644 index 0000000..fa2f695 --- /dev/null +++ b/autostart_hummingbot_compose/hummingbot_files/conf/strategies/conf_pure_mm_1.yml @@ -0,0 +1,150 @@ +######################################################## +### Pure market making strategy config ### +######################################################## + +template_version: 24 +strategy: pure_market_making + +# Exchange and token parameters. +exchange: binance_paper_trade + +# Token trading pair for the exchange, e.g. BTC-USDT +market: ETH-USDT + +# How far away from mid price to place the bid order. +# Spread of 1 = 1% away from mid price at that time. +# Example if mid price is 100 and bid_spread is 1. +# Your bid is placed at 99. +bid_spread: 1.0 + +# How far away from mid price to place the ask order. +# Spread of 1 = 1% away from mid price at that time. +# Example if mid price is 100 and ask_spread is 1. +# Your bid is placed at 101. +ask_spread: 1.0 + +# Minimum Spread +# How far away from the mid price to cancel active orders +minimum_spread: -100.0 + +# Time in seconds before cancelling and placing new orders. +# If the value is 60, the bot cancels active orders and placing new ones after a minute. +order_refresh_time: 10.0 + +# Time in seconds before replacing existing order with new orders at the same price. +max_order_age: 1800.0 + +# The spread (from mid price) to defer order refresh process to the next cycle. +# (Enter 1 to indicate 1%), value below 0, e.g. -1, is to disable this feature - not recommended. +order_refresh_tolerance_pct: 0.0 + +# Size of your bid and ask order. +order_amount: 0.5 + +# Price band ceiling. +price_ceiling: -1.0 + +# Price band floor. +price_floor: -1.0 + +# enable moving price floor and ceiling. +moving_price_band_enabled: false + +# Price band ceiling pct. +price_ceiling_pct: 1.0 + +# Price band floor pct. +price_floor_pct: -1.0 + +# price_band_refresh_time. +price_band_refresh_time: 86400.0 + +# Whether to alternate between buys and sells (true/false). +ping_pong_enabled: false + +# Whether to enable Inventory skew feature (true/false). +inventory_skew_enabled: false + +# Target base asset inventory percentage target to be maintained (for Inventory skew feature). +inventory_target_base_pct: 50.0 + +# The range around the inventory target base percent to maintain, expressed in multiples of total order size (for +# inventory skew feature). +inventory_range_multiplier: 1.0 + +# Initial price of the base asset. Note: this setting is not affects anything, the price is kept in the database. +inventory_price: 1.0 + +# Number of levels of orders to place on each side of the order book. +order_levels: 1 + +# Increase or decrease size of consecutive orders after the first order (if order_levels > 1). +order_level_amount: 0.0 + +# Order price space between orders (if order_levels > 1). +order_level_spread: 1.0 + +# How long to wait before placing the next order in case your order gets filled. +filled_order_delay: 60.0 + +# Whether to stop cancellations of orders on the other side (of the order book), +# when one side is filled (hanging orders feature) (true/false). +hanging_orders_enabled: false + +# Spread (from mid price, in percentage) hanging orders will be canceled (Enter 1 to indicate 1%) +hanging_orders_cancel_pct: 10.0 + +# Whether to enable order optimization mode (true/false). +order_optimization_enabled: false + +# The depth in base asset amount to be used for finding top ask (for order optimization mode). +ask_order_optimization_depth: 0.0 + +# The depth in base asset amount to be used for finding top bid (for order optimization mode). +bid_order_optimization_depth: 0.0 + +# Whether to enable adding transaction costs to order price calculation (true/false). +add_transaction_costs: false + +# The price source (current_market/external_market/custom_api). +price_source: current_market + +# The price type (mid_price/last_price/last_own_trade_price/best_bid/best_ask/inventory_cost). +price_type: mid_price + +# An external exchange name (for external exchange pricing source). +price_source_exchange: + +# A trading pair for the external exchange, e.g. BTC-USDT (for external exchange pricing source). +price_source_market: + +# An external api that returns price (for custom_api pricing source). +price_source_custom_api: + +# An interval time in second to update the price from custom api (for custom_api pricing source). +custom_api_update_interval: 5.0 + +#Take order if they cross order book when external price source is enabled +take_if_crossed: + +# Use user provided orders to directly override the orders placed by order_amount and order_level_parameter +# This is an advanced feature and user is expected to directly edit this field in config file +# Below is an sample input, the format is a dictionary, the key is user-defined order name, the value is a list which includes buy/sell, order spread, and order amount +# order_override: +# order_1: [buy, 0.5, 100] +# order_2: [buy, 0.75, 200] +# order_3: [sell, 0.1, 500] +# Please make sure there is a space between : and [ +order_override: + +# Simpler override config for separate bid and order level spreads +split_order_levels_enabled: false +bid_order_level_spreads: +ask_order_level_spreads: +bid_order_level_amounts: +ask_order_level_amounts: +# If the strategy should wait to receive cancellations confirmation before creating new orders during refresh time +should_wait_order_cancel_confirmation: true + +# For more detailed information, see: +# https://docs.hummingbot.io/strategies/pure-market-making/#configuration-parameters diff --git a/autostart_hummingbot_compose/hummingbot_files/scripts/format_status.py b/autostart_hummingbot_compose/hummingbot_files/scripts/format_status.py new file mode 100644 index 0000000..7ff9b1f --- /dev/null +++ b/autostart_hummingbot_compose/hummingbot_files/scripts/format_status.py @@ -0,0 +1,47 @@ +from hummingbot.strategy.script_strategy_base import ScriptStrategyBase + + +class FormatStatusExample(ScriptStrategyBase): + """ + This example shows how to add a custom format_status to a strategy and query the order book. + Run the command status --live, once the strategy starts. + """ + markets = { + "binance_paper_trade": {"ETH-USDT"}, + "kucoin_paper_trade": {"ETH-USDT"}, + "gate_io_paper_trade": {"ETH-USDT"}, + } + + def format_status(self) -> str: + """ + Returns status of the current strategy on user balances and current active orders. This function is called + when status command is issued. Override this function to create custom status display output. + """ + if not self.ready_to_trade: + return "Market connectors are not ready." + lines = [] + warning_lines = [] + warning_lines.extend(self.network_warning(self.get_market_trading_pair_tuples())) + + balance_df = self.get_balance_df() + lines.extend(["", " Balances:"] + [" " + line for line in balance_df.to_string(index=False).split("\n")]) + market_status_df = self.get_market_status_df_with_depth() + lines.extend(["", " Market Status Data Frame:"] + [" " + line for line in market_status_df.to_string(index=False).split("\n")]) + + warning_lines.extend(self.balance_warning(self.get_market_trading_pair_tuples())) + if len(warning_lines) > 0: + lines.extend(["", "*** WARNINGS ***"] + warning_lines) + return "\n".join(lines) + + def get_market_status_df_with_depth(self): + market_status_df = self.market_status_data_frame(self.get_market_trading_pair_tuples()) + market_status_df["Exchange"] = market_status_df.apply(lambda x: x["Exchange"].strip("PaperTrade") + "paper_trade", axis=1) + market_status_df["Volume (+1%)"] = market_status_df.apply(lambda x: self.get_volume_for_percentage_from_mid_price(x, 0.01), axis=1) + market_status_df["Volume (-1%)"] = market_status_df.apply(lambda x: self.get_volume_for_percentage_from_mid_price(x, -0.01), axis=1) + return market_status_df + + def get_volume_for_percentage_from_mid_price(self, row, percentage): + price = row["Mid Price"] * (1 + percentage) + is_buy = percentage > 0 + result = self.connectors[row["Exchange"]].get_volume_for_price(row["Market"], is_buy, price) + return result.result_volume diff --git a/bash_scripts/README.md b/bash_scripts/README.md new file mode 100644 index 0000000..8044de6 --- /dev/null +++ b/bash_scripts/README.md @@ -0,0 +1,73 @@ +# Docker commands + +## Setup + +The followings scripts assume that [Docker](https://www.docker.com/) has already been installed. + +They also assume that the user has Docker permissions without requiring `sudo`. If you do not have these permissions: + +1. Enter the following command: + + ``` + sudo usermod -a -G docker $USER + ``` + +2. Run the following command to change the permissions of all files with the ".sh" extension in the current directory, making them executable for all users.: + + ``` + chmod a+x *.sh + ``` + +3. Log out and log back into your console to enable them. + +## Hummingbot Client +### Create an instance of Hummingbot + +The `hummingbot-create.sh` script will create the folders needed to run Hummingbot and then install Hummingbot. + +``` +./create.sh +``` + +### Start up / connect to an instance of Hummingbot + +The `hummingbot-start.sh` script will connect to a running instance of Hummingbot. + +``` +./start.sh +``` + +### Updating Hummingbot version + +The `hummingbot-update.sh` script will update your instance to the latest version of Hummingbot. + +``` +./update.sh +``` + +## Gateway +### Create Gateway Instance + +The `gateway-create.sh` script helps you pull, configure, and run the Gateway Docker image. + +``` +./gateway-create.sh +``` + +### Copy Hummingbot Certs + +If you didn't do this step during `gateway-create.sh`, the `gateway-copy-certs.sh` script helps you copy the SSL certificates generated by Hummingbot into your Gateway files `certs` folder. This lets your Hummingbot instance access Gateway securely. + +``` +./gateway-copy-certs.sh +``` + +### Useful Commands + +These commands assume a Gateway container with the default instance name `gateway`: + +* List all Gateway containers: `docker ps -a --filter ancestor=hummingbot/gateway` +* Start Gateway container and attach to it: `docker start gateway && docker attach gateway` +* Stop Gateway container: `docker stop gateway` +* Update Gateway container to latest version: `docker pull hummingbot/gateway:latest` +* Remove Gateway container: `docker rm gateway` \ No newline at end of file diff --git a/bash_scripts/gateway-copy-certs.sh b/bash_scripts/gateway-copy-certs.sh new file mode 100644 index 0000000..640684d --- /dev/null +++ b/bash_scripts/gateway-copy-certs.sh @@ -0,0 +1,89 @@ +#!/bin/bash +# init +# ============================================= + +echo +echo +echo "=============== COPY CERTS TO GATEWAY FOLDER ===============" +echo +echo "ℹ️ Press [ENTER] for default values:" +echo + +# Ask for Gateway instance name +echo "List of all Gateway containers:" +docker ps -a --filter ancestor=hummingbot/gateway +echo +read -p "Enter Gateway container name (default = \"gateway\") >>> " INSTANCE_NAME +echo +if [ "$INSTANCE_NAME" == "" ] +then + INSTANCE_NAME="gateway" +fi +DEFAULT_FOLDER="${INSTANCE_NAME}_files/certs" +echo +echo "Stopping container: $INSTANCE_NAME" +docker stop $INSTANCE_NAME + +# Ask for path to Hummingbot certs folder +read -p "Enter path to the Hummingbot certs folder >>> " CERTS_FROM_PATH +if [ ! -d "$CERTS_FROM_PATH" ]; then + echo "Error: $CERTS_FROM_PATH does not exist or is not a directory" + exit +fi + +# Ask for path to Gateway files folder +read -p "Enter path to the Gateway certs folder (default = \"./gateway-files/certs/\") >>> " FOLDER +if [ "$FOLDER" == "" ] +then + FOLDER=$PWD/$DEFAULT_FOLDER +elif [[ ${FOLDER::1} != "/" ]]; then + FOLDER=$PWD/$FOLDER +fi +CERTS_TO_PATH="$FOLDER" + +prompt_proceed () { + read -p "Do you want to proceed? [Y/N] >>> " PROCEED + if [ "$PROCEED" == "" ] + then + prompt_proceed + else + if [[ "$PROCEED" != "Y" && "$PROCEED" != "y" ]] + then + PROCEED="N" + fi + fi +} + +copy_certs () { + # Copy all files in the source folder to the destination folder + cp -r $CERTS_FROM_PATH/* $CERTS_TO_PATH/ + + # Confirm that the files were copied + echo + if [ $? -eq 0 ]; then + echo "Files successfully copied from $CERTS_FROM_PATH to $CERTS_TO_PATH" + else + echo "Error copying files from $CERTS_FROM_PATH to $CERTS_TO_PATH" + exit + fi + + echo "Starting container: $INSTANCE_NAME" + docker start $INSTANCE_NAME && docker attach $INSTANCE_NAME + echo +} + +# Ask user to confirm and proceed +echo +echo "ℹ️ Confirm if this is correct:" +echo +printf "%30s %5s\n" "Copy certs FROM:" "$CERTS_FROM_PATH" +printf "%30s %5s\n" "Copy certs TO:" "$CERTS_TO_PATH" +echo +prompt_proceed +if [[ "$PROCEED" == "Y" || "$PROCEED" == "y" ]] +then + copy_certs +else + echo "Exiting..." + exit +fi diff --git a/bash_scripts/gateway-create.sh b/bash_scripts/gateway-create.sh new file mode 100644 index 0000000..a8f3b67 --- /dev/null +++ b/bash_scripts/gateway-create.sh @@ -0,0 +1,157 @@ +#!/bin/bash +# init + +echo +echo +echo "=============== CREATE A NEW GATEWAY INSTANCE ===============" +echo +echo +echo "ℹ️ Press [ENTER] for default values:" +echo + +echo +read -p "Enter Gateway version you want to use [latest/development] (default = \"latest\") >>> " GATEWAY_TAG +if [ "$GATEWAY_TAG" == "" ] +then + GATEWAY_TAG="latest" +fi + +# Ask the user for the name of the new Gateway instance +read -p "Enter a name for your new Gateway instance (default = \"gateway\") >>> " INSTANCE_NAME +if [ "$INSTANCE_NAME" == "" ] +then + INSTANCE_NAME="gateway" + DEFAULT_FOLDER="gateway_files" +else + DEFAULT_FOLDER="${INSTANCE_NAME}_files" +fi + +# Ask the user for the folder location to save files +read -p "Enter the folder name where your Gateway files will be saved (default = \"$DEFAULT_FOLDER\") >>> " FOLDER +if [ "$FOLDER" == "" ] +then + FOLDER=$PWD/$DEFAULT_FOLDER +elif [[ ${FOLDER::1} != "/" ]]; then + FOLDER=$PWD/$FOLDER +fi +CONF_FOLDER="$FOLDER/conf" +LOGS_FOLDER="$FOLDER/logs" +CERTS_FOLDER="$FOLDER/certs" + + +# Ask the user for the hummingbot certs passphrase +prompt_passphrase () { +echo +read -s -p "Enter the passphrase you used to generate certificates in Hummingbot >>> " PASSPHRASE +if [ "$PASSPHRASE" == "" ] +then + echo + echo + echo "!! Error: passphrase cannot be blank" + prompt_passphrase +fi +} +prompt_passphrase + +# Get GMT offset from local system time +GMT_OFFSET=$(date +%z) + +# Check available open port for Gateway +PORT=15888 +LIMIT=$((PORT+1000)) +while [[ $PORT -le LIMIT ]] + do + if [[ $(netstat -nat | grep "$PORT") ]]; then + # check another port + ((PORT = PORT + 1)) + else + break + fi +done + +echo +echo "ℹ️ Confirm below if the instance and its folders are correct:" +echo + +printf "%30s %5s\n" "Gateway instance name:" "$INSTANCE_NAME" +printf "%30s %5s\n" "Version:" "hummingbot/gateway:$GATEWAY_TAG" +echo +printf "%30s %5s\n" "Hummingbot instance ID:" "$HUMMINGBOT_INSTANCE_ID" +printf "%30s %5s\n" "Gateway conf path:" "$CONF_FOLDER" +printf "%30s %5s\n" "Gateway log path:" "$LOGS_FOLDER" +printf "%30s %5s\n" "Gateway certs path:" "$CERTS_FOLDER" +printf "%30s %5s\n" "Gateway port:" "$PORT" +echo + +prompt_existing_certs_path () { + echo + read -p "Enter the path to the folder where Hummingbot certificates are stored >>> " CERTS_PATH_TO_COPY + if [ "$CERTS_PATH_TO_COPY" == "" ] + then + echo + echo "After installation, set certificatePath in $CONF_FOLDER/server.yml and restart Gateway" + else + # Check if source folder exists + if [ ! -d "$CERTS_PATH_TO_COPY" ]; then + echo "Error: $CERTS_PATH_TO_COPY does not exist or is not a directory" + exit 1 + fi + # Copy all files in the source folder to the destination folder + cp -r $CERTS_PATH_TO_COPY/* $CERTS_FOLDER/ + # Confirm that the files were copied + if [ $? -eq 0 ]; then + echo "Files successfully copied from $CERTS_PATH_TO_COPY to $CERTS_FOLDER" + else + echo "Error copying files from $CERTS_PATH_TO_COPY to $CERTS_FOLDER" + exit 1 + fi + fi +} + +prompt_proceed () { + echo + read -p "Do you want to proceed with installation? [Y/N] >>> " PROCEED + if [ "$PROCEED" == "" ] + then + prompt_proceed + else + if [[ "$PROCEED" != "Y" && "$PROCEED" != "y" ]] + then + PROCEED="N" + fi + fi +} + +# Execute docker commands +create_instance () { + echo + echo "Creating Gateway instance ... " + echo + # 1) Create main folder for your new instance + mkdir $FOLDER + # 2) Create subfolders for gateway files + mkdir $CONF_FOLDER + mkdir $LOGS_FOLDER + mkdir $CERTS_FOLDER + # 3) Set required permissions to save gateway passphrase the first time + sudo chmod a+rw $CONF_FOLDER $CERTS_FOLDER + prompt_existing_certs_path + + # Launch a new instance of gateway + docker run \ + --name $INSTANCE_NAME \ + -p $PORT:$PORT \ + -v $CONF_FOLDER:/usr/src/app/conf \ + -v $LOGS_FOLDER:/usr/src/app/logs \ + -v $CERTS_FOLDER:/usr/src/app/certs \ + -e GATEWAY_PASSPHRASE="$PASSPHRASE" \ + hummingbot/gateway:$GATEWAY_TAG +} +prompt_proceed +if [[ "$PROCEED" == "Y" || "$PROCEED" == "y" ]] +then + create_instance +else + echo " Aborted" + echo +fi diff --git a/bash_scripts/hummingbot-create.sh b/bash_scripts/hummingbot-create.sh new file mode 100644 index 0000000..566beb1 --- /dev/null +++ b/bash_scripts/hummingbot-create.sh @@ -0,0 +1,105 @@ +#!/bin/bash +# init + +echo +echo +echo "=============== CREATE A NEW HUMMINGBOT INSTANCE ===============" +echo +echo +echo "ℹ️ Press [ENTER] for default values:" +echo + +# Specify hummingbot version +read -p " Enter Hummingbot version you want to use [latest/development] (default = \"latest\") >>> " TAG +if [ "$TAG" == "" ] +then + TAG="latest" +fi + +# Ask the user for the name of the new instance +read -p " Enter a name for your new Hummingbot instance (default = \"hummingbot\") >>> " INSTANCE_NAME +if [ "$INSTANCE_NAME" == "" ] +then + INSTANCE_NAME="hummingbot" + DEFAULT_FOLDER="hummingbot_files" +else + DEFAULT_FOLDER="${INSTANCE_NAME}_files" +fi + +# Ask the user for the folder location to save files +read -p " Enter a folder name where your Hummingbot files will be saved (default = \"$DEFAULT_FOLDER\") >>> " FOLDER +if [ "$FOLDER" == "" ] +then + FOLDER=$PWD/$DEFAULT_FOLDER +elif [[ ${FOLDER::1} != "/" ]]; then + FOLDER=$PWD/$FOLDER +fi +CONF_FOLDER="$FOLDER/conf" +LOGS_FOLDER="$FOLDER/logs" +DATA_FOLDER="$FOLDER/data" +PMM_SCRIPTS_FOLDER="$FOLDER/pmm-scripts" +SCRIPTS_FOLDER="$FOLDER/scripts" +CERTS_FOLDER="$FOLDER/certs" + +echo +echo "ℹ️ Confirm below if the instance and its folders are correct:" +echo +printf "%30s %5s\n" "Instance name:" "$INSTANCE_NAME" +printf "%30s %5s\n" "Version:" "hummingbot/hummingbot:$TAG" +echo +printf "%30s %5s\n" "Main folder path:" "$FOLDER" +printf "%30s %5s\n" "Config files:" "├── $CONF_FOLDER" +printf "%30s %5s\n" "Log files:" "├── $LOGS_FOLDER" +printf "%30s %5s\n" "Trade and data files:" "├── $DATA_FOLDER" +printf "%30s %5s\n" "PMM scripts files:" "├── $PMM_SCRIPTS_FOLDER" +printf "%30s %5s\n" "Scripts files:" "├── $SCRIPTS_FOLDER" +printf "%30s %5s\n" "Cert files:" "├── $CERTS_FOLDER" +echo + +prompt_proceed () { + read -p " Do you want to proceed? [Y/N] >>> " PROCEED + if [ "$PROCEED" == "" ] + then + PROCEED="Y" + fi +} + +# Execute docker commands +create_instance () { + echo + echo "Creating Hummingbot instance ... Admin password may be required to set the required permissions ..." + echo + # 1) Create main folder for your new instance + mkdir $FOLDER + # 2) Create subfolders for hummingbot files + mkdir $CONF_FOLDER + mkdir $CONF_FOLDER/connectors + mkdir $CONF_FOLDER/strategies + mkdir $LOGS_FOLDER + mkdir $DATA_FOLDER + mkdir $PMM_SCRIPTS_FOLDER + mkdir $CERTS_FOLDER + mkdir $SCRIPTS_FOLDER + # 3) Set required permissions to save hummingbot password the first time + sudo chmod a+rw $CONF_FOLDER $CERTS_FOLDER + # 4) Launch a new instance of hummingbot + docker run -it --log-opt max-size=10m --log-opt max-file=5 \ + --name $INSTANCE_NAME \ + --network host \ + -v $CONF_FOLDER:/conf \ + -v $LOGS_FOLDER:/logs \ + -v $DATA_FOLDER:/data \ + -v $PMM_SCRIPTS_FOLDER:/pmm_scripts \ + -v $SCRIPTS_FOLDER:/scripts \ + -v $CERTS_FOLDER:/certs \ + hummingbot/hummingbot:$TAG +} + +prompt_proceed +if [[ "$PROCEED" == "Y" || "$PROCEED" == "y" ]] +then + create_instance +else + echo " Aborted" + echo +fi \ No newline at end of file diff --git a/bash_scripts/hummingbot-start.sh b/bash_scripts/hummingbot-start.sh new file mode 100644 index 0000000..4506682 --- /dev/null +++ b/bash_scripts/hummingbot-start.sh @@ -0,0 +1,21 @@ +#!/bin/bash +# init +# ============================================= +# SCRIPT COMMANDS +echo +echo "=============== START HUMMINGBOT INSTANCE ===============" +echo +echo "List of all docker instances:" +echo +docker ps -a +echo +echo +read -p " Enter the NAME of the Hummingbot instance to start or connect to (default = \"hummingbot-instance\") >>> " INSTANCE_NAME +if [ "$INSTANCE_NAME" == "" ] +then + INSTANCE_NAME="hummingbot-instance" +fi +echo +# ============================================= +# EXECUTE SCRIPT +docker start $INSTANCE_NAME && docker attach $INSTANCE_NAME \ No newline at end of file diff --git a/bash_scripts/hummingbot-update.sh b/bash_scripts/hummingbot-update.sh new file mode 100644 index 0000000..9f4a992 --- /dev/null +++ b/bash_scripts/hummingbot-update.sh @@ -0,0 +1,148 @@ +#!/bin/bash +# init +# ============================================= + +# Specify hummingbot version +select_version () { + echo + echo + echo "=============== UPDATE HUMMINGBOT INSTANCE ===============" + echo + echo + echo "ℹ️ Press [ENTER] for default values:" + echo + read -p " Enter Hummingbot version to update [latest/development] (default = \"latest\") >>> " TAG + if [ "$TAG" == "" ] + then + TAG="latest" + fi +} + +# List all docker instances using the same image +list_instances () { + echo + echo "List of all docker containers using the \"$TAG\" version:" + echo + docker ps -a --filter ancestor=hummingbot/hummingbot:$TAG + echo + echo "⚠️ WARNING: This will attempt to update all instances. Any containers not in Exited () STATUS will cause the update to fail." + echo + echo "ℹ️ TIP: Connect to a running instance using \"./start.sh\" command and \"exit\" from inside Hummingbot." + echo "ℹ️ TIP: You can also remove unused instances by running \"docker rm [NAME]\" in the terminal." + echo + read -p " Do you want to continue? [Y/N] >>> " CONTINUE + if [ "$CONTINUE" == "" ] + then + CONTINUE="Y" + fi +} + +# List all directories in the current folder +list_dir () { + echo + echo " List of folders in your directory:" + echo + ls -d1 */ 2>&1 | sed 's/^/ 📁 /' + echo +} + +# Ask the user for the folder location of each instance +prompt_folder () { + for instance in "${INSTANCES[@]}" + do + if [ "$instance" == "hummingbot-instance" ] + then + DEFAULT_FOLDER="hummingbot_files" + else + DEFAULT_FOLDER="${instance}_files" + fi + read -p " Enter the destination folder for $instance (default = \"$DEFAULT_FOLDER\") >>> " FOLDER + if [ "$FOLDER" == "" ] + then + FOLDER=$PWD/$DEFAULT_FOLDER + elif [[ ${FOLDER::1} != "/" ]]; then + FOLDER=$PWD/$FOLDER + fi + # Store folder names into an array + FOLDERS+=($FOLDER) + done +} + +# Display instances and destination folders then prompt to proceed +confirm_update () { + echo + echo "ℹ️ Confirm below if the instances and their folders are correct:" + echo + num="0" + printf "%30s %5s %10s\n" "INSTANCE" " " "FOLDER" + for instance in "${INSTANCES[@]}" + do + printf "%30s %5s %10s\n" ${INSTANCES[$num]} " ----------> " ${FOLDERS[$num]} + num=$[$num+1] + done + echo + read -p " Proceed? [Y/N] >>> " PROCEED + if [ "$PROCEED" == "" ] + then + PROCEED="Y" + fi +} + +# Execute docker commands +execute_docker () { + # 1) Delete instance and old hummingbot image + echo + echo "Removing docker containers first ..." + docker rm ${INSTANCES[@]} + echo + # 2) Delete old image + docker image rm hummingbot/hummingbot:$TAG + # 3) Re-create instances with the most recent hummingbot version + echo "Re-creating docker containers with updated image ..." + j="0" + for instance in "${INSTANCES[@]}" + do + docker run -itd --log-opt max-size=10m --log-opt max-file=5 \ + --network host \ + --name ${INSTANCES[$j]} \ + -v $CONF_FOLDER:/conf \ + -v $LOGS_FOLDER:/logs \ + -v $DATA_FOLDER:/data \ + -v $PMM_SCRIPTS_FOLDER:/pmm_scripts \ + -v $SCRIPTS_FOLDER:/scripts \ + -v $CERTS_FOLDER:/certs \ + hummingbot/hummingbot:$TAG + j=$[$j+1] + # Update file ownership + done + echo + echo "Update complete! All running docker instances:" + echo + docker ps + echo + echo "ℹ️ Run command \"./start.sh\" to connect to an instance." + echo +} + +select_version +list_instances +if [ "$CONTINUE" == "Y" ] +then + # Store instance names in an array + declare -a INSTANCES + INSTANCES=( $(docker ps -a --filter ancestor=hummingbot/hummingbot:$TAG --format "{{.Names}}") ) + list_dir + declare -a FOLDERS + prompt_folder + confirm_update + if [ "$PROCEED" == "Y" ] + then + execute_docker + else + echo " Update aborted" + echo + fi +else + echo " Update aborted" + echo +fi \ No newline at end of file diff --git a/hummingbot_gateway_compose/README.md b/hummingbot_gateway_compose/README.md new file mode 100644 index 0000000..69d6e20 --- /dev/null +++ b/hummingbot_gateway_compose/README.md @@ -0,0 +1,38 @@ +# Deploy: Hummingbot + Gateway + +## How to use it +You will need to have the certificates for the gateway and hummingbot under the folder hummingbot_files/certs. +If you don't have it, don't worry, you can generate them with the client by doing the following: +- Make sure you have docker and docker-compose installed. +- Run the following command in the terminal: + ``` + docker-compose up -d + ``` +- You will see that the gateway failed to start because you don't have the certificates +- Attach the instance of the bot by running: + ``` + docker attach hummingbot_gateway_compose-bot-1 + ``` +- Create the password +- Run the following command in the client: + ``` + gateway generate-certs + ``` +- When prompted enter the passphrase that you want. Is important that you change the docker-compose.yml on line 18 to the passphrase that you entered (the current passphrase is `a`). +- Exit the client and run the following command in the terminal: + ``` + docker-compose down + ``` +- You will see that inside the hummingbot_files/certs folder you have the certificates. +- We are ready to deploy the gateway and hummingbot, run the following command in the terminal: + ``` + docker-compose up -d + ``` +- If you attach the terminal of the gateway you will see that it is running. + ``` + docker attach hummingbot_gateway_compose-gateway-1 + ``` +- If you attach the terminal of the bot you will see that it is running and the gateway is ONLINE. + ``` + docker attach hummingbot_gateway_compose-bot-1 + ``` diff --git a/hummingbot_gateway_compose/docker-compose.yml b/hummingbot_gateway_compose/docker-compose.yml new file mode 100644 index 0000000..5672cbd --- /dev/null +++ b/hummingbot_gateway_compose/docker-compose.yml @@ -0,0 +1,30 @@ +version: "3.9" +services: + bot: + image: hummingbot/hummingbot:latest + volumes: + - "./hummingbot_files/conf:/conf" + - "./hummingbot_files/logs:/logs" + - "./hummingbot_files/data:/data" + - "./hummingbot_files/scripts:/scripts" + - "./hummingbot_files/certs:/certs" + logging: + driver: "json-file" + options: + max-size: "10m" + max-file: 5 + tty: true + stdin_open: true + network_mode: host + + gateway: + image: hummingbot/gateway:latest + ports: + - "15888:15888" + - "8080:8080" + volumes: + - "./gateway_files/conf:/usr/src/app/conf" + - "./gateway_files/logs:/usr/src/app/logs" + - "./hummingbot_files/certs:/usr/src/app/certs" + environment: + - GATEWAY_PASSPHRASE=a diff --git a/multiple_hummingbot_gateway_compose/README.md b/multiple_hummingbot_gateway_compose/README.md new file mode 100644 index 0000000..ca6e419 --- /dev/null +++ b/multiple_hummingbot_gateway_compose/README.md @@ -0,0 +1,47 @@ +# Deploy: Hummingbot + Gateway + +## How to use it +You will need to have the certificates for the gateway and hummingbot under the folder hummingbot_files/certs. +If you don't have it, don't worry, you can generate them with the client by doing the following: +- Make sure you have docker and docker-compose installed. +- Run the following command in the terminal: + ``` + docker-compose up -d + ``` +- You will see that the gateway failed to start because you don't have the certificates +- Attach the instance of the bot by running: + ``` + docker attach hummingbot_gateway_compose-bot-1 + ``` +- Create the password +- Run the following command in the client: + ``` + gateway generate-certs + ``` +- When prompted enter the passphrase that you want. Is important that you change the docker-compose.yml on line 18 to the passphrase that you entered (the current passphrase is `a`). +- Exit the client and run the following command in the terminal: + ``` + docker-compose down + ``` +- You will see that inside the hummingbot_files/certs folder you have the certificates. +- We are ready to deploy the gateway and hummingbot, run the following command in the terminal: + ``` + docker-compose up -d + ``` +- If you attach the terminal of the gateway you will see that it is running. + ``` + docker attach hummingbot_gateway_compose-gateway-1 + ``` +- If you attach the terminal of the bot you will see that it is running and the gateway is ONLINE. + ``` + docker attach hummingbot_gateway_compose-bot-1 + ``` +- If you attach the terminal of the bot2 you will see that it is running and the gateway is ONLINE. + ``` + docker attach hummingbot_gateway_compose-bot2-1 + ``` + +## IMPORTANT + +To simplify the example, we are sharing the folder of hummingbot_files between the two bots. You should have one folder for each bot, +but the certs folder that you are sharing between the gateway and the bots should be the same. diff --git a/multiple_hummingbot_gateway_compose/docker-compose.yml b/multiple_hummingbot_gateway_compose/docker-compose.yml new file mode 100644 index 0000000..71a2f07 --- /dev/null +++ b/multiple_hummingbot_gateway_compose/docker-compose.yml @@ -0,0 +1,49 @@ +version: "3.9" +services: + bot: + image: hummingbot/hummingbot:latest + volumes: + - "./hummingbot_files/conf:/conf" + - "./hummingbot_files/logs:/logs" + - "./hummingbot_files/data:/data" + - "./hummingbot_files/scripts:/scripts" + - "./hummingbot_files/certs:/certs" + logging: + driver: "json-file" + options: + max-size: "10m" + max-file: 5 + tty: true + stdin_open: true + network_mode: host + + bot2: + image: hummingbot/hummingbot:latest + volumes: + - "./hummingbot_files/conf:/conf" + - "./hummingbot_files/logs:/logs" + - "./hummingbot_files/data:/data" + - "./hummingbot_files/scripts:/scripts" + - "./hummingbot_files/certs:/certs" + environment: + - CONFIG_PASSWORD=a + logging: + driver: "json-file" + options: + max-size: "10m" + max-file: 5 + tty: true + stdin_open: true + network_mode: host + + gateway: + image: hummingbot/gateway:latest + ports: + - "15888:15888" + - "8080:8080" + volumes: + - "./gateway_files/conf:/usr/src/app/conf" + - "./gateway_files/logs:/usr/src/app/logs" + - "./hummingbot_files/certs:/usr/src/app/certs" + environment: + - GATEWAY_PASSPHRASE=a diff --git a/simple_hummingbot_compose/README.md b/simple_hummingbot_compose/README.md new file mode 100644 index 0000000..04d60c7 --- /dev/null +++ b/simple_hummingbot_compose/README.md @@ -0,0 +1,16 @@ +# Deploy a single Hummingbot instance with docker Compose + +## How to use it + +- Make sure you have docker and docker-compose installed. +- Run the following command: + ``` + docker-compose up -d + ``` + +- Attach the terminal: + ``` + docker attach simple_hummingbot_compose-bot-1 + ``` + +- Now you have Hummingbot running! Remember that you can detach the terminal without stopping the bot by pressing `Ctrl + P` and `Ctrl + Q`. \ No newline at end of file diff --git a/simple_hummingbot_compose/docker-compose.yml b/simple_hummingbot_compose/docker-compose.yml new file mode 100644 index 0000000..a07221d --- /dev/null +++ b/simple_hummingbot_compose/docker-compose.yml @@ -0,0 +1,18 @@ +version: "3.9" +services: + bot: + image: hummingbot/hummingbot:latest + volumes: + - "./hummingbot_files/conf:/conf" + - "./hummingbot_files/logs:/logs" + - "./hummingbot_files/data:/data" + - "./hummingbot_files/scripts:/scripts" + - "./hummingbot_files/certs:/certs" + logging: + driver: "json-file" + options: + max-size: "10m" + max-file: 5 + tty: true + stdin_open: true + network_mode: host