From 85ea845e3e9f080dc4480204131f4fe0f6ecdd6c Mon Sep 17 00:00:00 2001 From: cardosofede Date: Wed, 11 Oct 2023 11:37:49 -0300 Subject: [PATCH 1/7] (feat) change to generic email --- credentials.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/credentials.yml b/credentials.yml index 64a24000..eabdf258 100644 --- a/credentials.yml +++ b/credentials.yml @@ -10,4 +10,4 @@ credentials: password: abc # To be replaced with hashed password: hashed_passwords = stauth.Hasher(['abc', 'def']).generate() preauthorized: # the preferred way to add users since there is no need for manual hashing of passwords emails: - - operations@hummingbot.org + - admin@admin.com From bb1d5ceea0815006f2b68e23c0e9eeac8b7a7e15 Mon Sep 17 00:00:00 2001 From: cardosofede Date: Wed, 11 Oct 2023 11:38:14 -0300 Subject: [PATCH 2/7] (feat) add mount for scripts --- hummingbot_files/compose_files/data-downloader-compose.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/hummingbot_files/compose_files/data-downloader-compose.yml b/hummingbot_files/compose_files/data-downloader-compose.yml index ea8accec..468220bc 100644 --- a/hummingbot_files/compose_files/data-downloader-compose.yml +++ b/hummingbot_files/compose_files/data-downloader-compose.yml @@ -7,6 +7,7 @@ services: - "../../data/candles:/home/hummingbot/data" - "../bots/data_downloader/conf:/home/hummingbot/conf" - "../bots/data_downloader/conf/connectors:/home/hummingbot/conf/connectors" + - "../bots/data_downloader/scripts:/home/hummingbot/scripts" environment: - CONFIG_PASSWORD=a - CONFIG_FILE_NAME=download_candles.py From a3b19a992dcb8ecea38b58cd58ab7dca69475894 Mon Sep 17 00:00:00 2001 From: cardosofede Date: Wed, 11 Oct 2023 11:42:40 -0300 Subject: [PATCH 3/7] (feat) add download candles --- .../scripts/download_candles.py | 61 +++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 hummingbot_files/bots/data_downloader/scripts/download_candles.py diff --git a/hummingbot_files/bots/data_downloader/scripts/download_candles.py b/hummingbot_files/bots/data_downloader/scripts/download_candles.py new file mode 100644 index 00000000..46d737c6 --- /dev/null +++ b/hummingbot_files/bots/data_downloader/scripts/download_candles.py @@ -0,0 +1,61 @@ +import os +from typing import Dict + +from hummingbot import data_path +from hummingbot.client.hummingbot_application import HummingbotApplication +from hummingbot.connector.connector_base import ConnectorBase +from hummingbot.data_feed.candles_feed.candles_factory import CandlesConfig, CandlesFactory +from hummingbot.strategy.script_strategy_base import ScriptStrategyBase + + +class DownloadCandles(ScriptStrategyBase): + """ + This script provides an example of how to use the Candles Feed to download and store historical data. + It downloads 3-minute candles for 3 Binance trading pairs ["APE-USDT", "BTC-USDT", "BNB-USDT"] and stores them in + CSV files in the /data directory. The script stops after it has downloaded 50,000 max_records records for each pair. + Is important to notice that the component will fail if all the candles are not available since the idea of it is to + use it in production based on candles needed to compute technical indicators. + """ + exchange = os.getenv("EXCHANGE", "binance_perpetual") + trading_pairs = os.getenv("TRADING_PAIRS", "DODO-BUSD,LTC-USDT").split(",") + intervals = os.getenv("INTERVALS", "1m,3m,5m,1h").split(",") + days_to_download = int(os.getenv("DAYS_TO_DOWNLOAD", "3")) + # we can initialize any trading pair since we only need the candles + markets = {"binance_paper_trade": {"BTC-USDT"}} + + @staticmethod + def get_max_records(days_to_download: int, interval: str) -> int: + conversion = {"s": 1 / 60, "m": 1, "h": 60, "d": 1440} + unit = interval[-1] + quantity = int(interval[:-1]) + return int(days_to_download * 24 * 60 / (quantity * conversion[unit])) + + def __init__(self, connectors: Dict[str, ConnectorBase]): + super().__init__(connectors) + combinations = [(trading_pair, interval) for trading_pair in self.trading_pairs for interval in self.intervals] + + self.candles = {f"{combinations[0]}_{combinations[1]}": {} for combinations in combinations} + # we need to initialize the candles for each trading pair + for combination in combinations: + + candle = CandlesFactory.get_candle(CandlesConfig(connector=self.exchange, trading_pair=combination[0], interval=combination[1], max_records=self.get_max_records(self.days_to_download, combination[1]))) + candle.start() + # we are storing the candles object and the csv path to save the candles + self.candles[f"{combination[0]}_{combination[1]}"]["candles"] = candle + self.candles[f"{combination[0]}_{combination[1]}"][ + "csv_path"] = data_path() + f"/candles_{self.exchange}_{combination[0]}_{combination[1]}.csv" + + def on_tick(self): + for trading_pair, candles_info in self.candles.items(): + if not candles_info["candles"].is_ready: + self.logger().info(f"Candles not ready yet for {trading_pair}! Missing {candles_info['candles']._candles.maxlen - len(candles_info['candles']._candles)}") + pass + else: + df = candles_info["candles"].candles_df + df.to_csv(candles_info["csv_path"], index=False) + if all(candles_info["candles"].is_ready for candles_info in self.candles.values()): + HummingbotApplication.main_application().stop() + + def on_stop(self): + for candles_info in self.candles.values(): + candles_info["candles"].stop() From 3e5d4cb80889d603c5b1ae9a0e7f7289f68d66e9 Mon Sep 17 00:00:00 2001 From: cardosofede Date: Wed, 11 Oct 2023 11:43:28 -0300 Subject: [PATCH 4/7] (feat) add changes for config files --- .../bots/data_downloader/conf/conf_client.yml | 2 +- .../conf/conf_fee_overrides.yml | 36 +++++++++++++++++++ .../master_bot_conf/conf/conf_client.yml | 2 +- .../conf/conf_fee_overrides.yml | 24 +++++++++++++ ui_components/editor.py | 2 -- 5 files changed, 62 insertions(+), 4 deletions(-) diff --git a/hummingbot_files/bots/data_downloader/conf/conf_client.yml b/hummingbot_files/bots/data_downloader/conf/conf_client.yml index f6ec3421..ab2880cc 100644 --- a/hummingbot_files/bots/data_downloader/conf/conf_client.yml +++ b/hummingbot_files/bots/data_downloader/conf/conf_client.yml @@ -133,7 +133,7 @@ command_shortcuts: - config bid_spread $1 - config ask_spread $2 -# A source for rate oracle, currently ascend_ex, binance, coin_gecko, kucoin, gate_io +# A source for rate oracle, currently ascend_ex, binance, coin_gecko, coin_cap, kucoin, gate_io rate_oracle_source: name: binance diff --git a/hummingbot_files/bots/data_downloader/conf/conf_fee_overrides.yml b/hummingbot_files/bots/data_downloader/conf/conf_fee_overrides.yml index 76512b13..f2956509 100644 --- a/hummingbot_files/bots/data_downloader/conf/conf_fee_overrides.yml +++ b/hummingbot_files/bots/data_downloader/conf/conf_fee_overrides.yml @@ -302,3 +302,39 @@ polkadex_taker_percent_fee: polkadex_buy_percent_fee_deducted_from_returns: polkadex_maker_fixed_fees: polkadex_taker_fixed_fees: +woo_x_percent_fee_token: +woo_x_maker_percent_fee: +woo_x_taker_percent_fee: +woo_x_buy_percent_fee_deducted_from_returns: +woo_x_maker_fixed_fees: +woo_x_taker_fixed_fees: +woo_x_testnet_percent_fee_token: +woo_x_testnet_maker_percent_fee: +woo_x_testnet_taker_percent_fee: +woo_x_testnet_buy_percent_fee_deducted_from_returns: +woo_x_testnet_maker_fixed_fees: +woo_x_testnet_taker_fixed_fees: +vertex_percent_fee_token: +vertex_maker_percent_fee: +vertex_taker_percent_fee: +vertex_buy_percent_fee_deducted_from_returns: +vertex_maker_fixed_fees: +vertex_taker_fixed_fees: +vertex_testnet_percent_fee_token: +vertex_testnet_maker_percent_fee: +vertex_testnet_taker_percent_fee: +vertex_testnet_buy_percent_fee_deducted_from_returns: +vertex_testnet_maker_fixed_fees: +vertex_testnet_taker_fixed_fees: +injective_v2_percent_fee_token: +injective_v2_maker_percent_fee: +injective_v2_taker_percent_fee: +injective_v2_buy_percent_fee_deducted_from_returns: +injective_v2_maker_fixed_fees: +injective_v2_taker_fixed_fees: +injective_v2_perpetual_percent_fee_token: +injective_v2_perpetual_maker_percent_fee: +injective_v2_perpetual_taker_percent_fee: +injective_v2_perpetual_buy_percent_fee_deducted_from_returns: +injective_v2_perpetual_maker_fixed_fees: +injective_v2_perpetual_taker_fixed_fees: diff --git a/hummingbot_files/templates/master_bot_conf/conf/conf_client.yml b/hummingbot_files/templates/master_bot_conf/conf/conf_client.yml index c50c793d..9e2b6e16 100644 --- a/hummingbot_files/templates/master_bot_conf/conf/conf_client.yml +++ b/hummingbot_files/templates/master_bot_conf/conf/conf_client.yml @@ -133,7 +133,7 @@ command_shortcuts: - config bid_spread $1 - config ask_spread $2 -# A source for rate oracle, currently ascend_ex, binance, coin_gecko, kucoin, gate_io +# A source for rate oracle, currently ascend_ex, binance, coin_gecko, coin_cap, kucoin, gate_io rate_oracle_source: name: binance diff --git a/hummingbot_files/templates/master_bot_conf/conf/conf_fee_overrides.yml b/hummingbot_files/templates/master_bot_conf/conf/conf_fee_overrides.yml index 3345de57..8648bb54 100644 --- a/hummingbot_files/templates/master_bot_conf/conf/conf_fee_overrides.yml +++ b/hummingbot_files/templates/master_bot_conf/conf/conf_fee_overrides.yml @@ -314,3 +314,27 @@ vertex_testnet_taker_percent_fee: vertex_testnet_buy_percent_fee_deducted_from_returns: vertex_testnet_maker_fixed_fees: vertex_testnet_taker_fixed_fees: +woo_x_percent_fee_token: +woo_x_maker_percent_fee: +woo_x_taker_percent_fee: +woo_x_buy_percent_fee_deducted_from_returns: +woo_x_maker_fixed_fees: +woo_x_taker_fixed_fees: +woo_x_testnet_percent_fee_token: +woo_x_testnet_maker_percent_fee: +woo_x_testnet_taker_percent_fee: +woo_x_testnet_buy_percent_fee_deducted_from_returns: +woo_x_testnet_maker_fixed_fees: +woo_x_testnet_taker_fixed_fees: +injective_v2_percent_fee_token: +injective_v2_maker_percent_fee: +injective_v2_taker_percent_fee: +injective_v2_buy_percent_fee_deducted_from_returns: +injective_v2_maker_fixed_fees: +injective_v2_taker_fixed_fees: +injective_v2_perpetual_percent_fee_token: +injective_v2_perpetual_maker_percent_fee: +injective_v2_perpetual_taker_percent_fee: +injective_v2_perpetual_buy_percent_fee_deducted_from_returns: +injective_v2_perpetual_maker_fixed_fees: +injective_v2_perpetual_taker_fixed_fees: diff --git a/ui_components/editor.py b/ui_components/editor.py index 538560ae..66b04f79 100644 --- a/ui_components/editor.py +++ b/ui_components/editor.py @@ -68,8 +68,6 @@ def __call__(self): with mui.Grid(item=True, xs=2, sx={"display": "flex", "justifyContent": "flex-end"}): mui.IconButton(mui.icon.Save, onClick=self.save_file, sx={"mx": 1}) - - for index, (label, tab) in enumerate(self._tabs.items()): with mui.Box(sx=self._editor_box_style, hidden=(index != self._index)): editor.Monaco( From 3d3c8e489a2796dba928a74eb601bda9191e8c20 Mon Sep 17 00:00:00 2001 From: cardosofede Date: Wed, 11 Oct 2023 12:07:33 -0300 Subject: [PATCH 5/7] (feat) move apply to top --- ui_components/editor.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/ui_components/editor.py b/ui_components/editor.py index 66b04f79..a99963f6 100644 --- a/ui_components/editor.py +++ b/ui_components/editor.py @@ -66,6 +66,7 @@ def __call__(self): for label in self._tabs.keys(): mui.Tab(label=label) with mui.Grid(item=True, xs=2, sx={"display": "flex", "justifyContent": "flex-end"}): + mui.Button("Apply", variant="contained", onClick=sync()) mui.IconButton(mui.icon.Save, onClick=self.save_file, sx={"mx": 1}) for index, (label, tab) in enumerate(self._tabs.items()): @@ -84,6 +85,4 @@ def __call__(self): ) with mui.Stack(direction="row", spacing=2, alignItems="center", sx={"padding": "10px"}): - mui.Button("Apply", variant="contained", onClick=sync()) event.Hotkey("ctrl+s", sync(), bindInputs=True, overrideDefault=True) - mui.Typography("Or press ctrl+s", sx={"flex": 1}) From 27884030dad3e78a1eec5b4c2a1e2af0bea339e9 Mon Sep 17 00:00:00 2001 From: cardosofede Date: Wed, 11 Oct 2023 15:28:50 -0300 Subject: [PATCH 6/7] (feat) change button of save --- ui_components/editor.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui_components/editor.py b/ui_components/editor.py index a99963f6..f2bb5fef 100644 --- a/ui_components/editor.py +++ b/ui_components/editor.py @@ -67,7 +67,7 @@ def __call__(self): mui.Tab(label=label) with mui.Grid(item=True, xs=2, sx={"display": "flex", "justifyContent": "flex-end"}): mui.Button("Apply", variant="contained", onClick=sync()) - mui.IconButton(mui.icon.Save, onClick=self.save_file, sx={"mx": 1}) + mui.Button("Save to File", variant="contained", onClick=self.save_file, sx={"mx": 1}) for index, (label, tab) in enumerate(self._tabs.items()): with mui.Box(sx=self._editor_box_style, hidden=(index != self._index)): From f24e001b8cb6e3afc572ef39b4fa97019e39bbb4 Mon Sep 17 00:00:00 2001 From: cardosofede Date: Thu, 12 Oct 2023 13:12:45 -0300 Subject: [PATCH 7/7] (feat) adapt labels to Mike's suggestion --- ui_components/editor.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ui_components/editor.py b/ui_components/editor.py index f2bb5fef..df65be63 100644 --- a/ui_components/editor.py +++ b/ui_components/editor.py @@ -66,8 +66,8 @@ def __call__(self): for label in self._tabs.keys(): mui.Tab(label=label) with mui.Grid(item=True, xs=2, sx={"display": "flex", "justifyContent": "flex-end"}): - mui.Button("Apply", variant="contained", onClick=sync()) - mui.Button("Save to File", variant="contained", onClick=self.save_file, sx={"mx": 1}) + mui.Button("Apply Changes", variant="contained", onClick=sync()) + mui.Button("Save Changes", variant="contained", onClick=self.save_file, sx={"mx": 1}) for index, (label, tab) in enumerate(self._tabs.items()): with mui.Box(sx=self._editor_box_style, hidden=(index != self._index)):