From 2a7831287e832616783c3131106a27a78288372e Mon Sep 17 00:00:00 2001 From: Guillaume De Saint Martin Date: Fri, 19 Jul 2024 00:08:52 +0200 Subject: [PATCH 01/20] [WebInterface] improve candlesticks UI --- .../Interfaces/web_interface/models/dashboard.py | 5 ++++- .../static/js/common/candlesticks.js | 15 +++++++++------ .../static/js/components/dashboard.js | 2 ++ .../Interfaces/web_interface/templates/index.html | 2 +- 4 files changed, 16 insertions(+), 8 deletions(-) diff --git a/Services/Interfaces/web_interface/models/dashboard.py b/Services/Interfaces/web_interface/models/dashboard.py index 4258a4757..3a227aa80 100644 --- a/Services/Interfaces/web_interface/models/dashboard.py +++ b/Services/Interfaces/web_interface/models/dashboard.py @@ -71,7 +71,10 @@ def format_trades(dict_trade_history): float(dict_trade[trading_enums.ExchangeConstantsOrderColumns.PRICE.value])) trades[trade_description_key].append( f"{trade_type.name.replace('_', ' ')}: " - f"{dict_trade[trading_enums.ExchangeConstantsOrderColumns.AMOUNT.value]}") + f"{dict_trade[trading_enums.ExchangeConstantsOrderColumns.AMOUNT.value]} " + f"{dict_trade[trading_enums.ExchangeConstantsOrderColumns.QUANTITY_CURRENCY.value]} " + f"at {dict_trade[trading_enums.ExchangeConstantsOrderColumns.PRICE.value]} " + f"{dict_trade[trading_enums.ExchangeConstantsOrderColumns.MARKET.value]}") trades[trade_order_side_key].append(trade_side.value) return trades diff --git a/Services/Interfaces/web_interface/static/js/common/candlesticks.js b/Services/Interfaces/web_interface/static/js/common/candlesticks.js index 38913487d..a66243bbe 100644 --- a/Services/Interfaces/web_interface/static/js/common/candlesticks.js +++ b/Services/Interfaces/web_interface/static/js/common/candlesticks.js @@ -121,6 +121,8 @@ function get_watched_symbol_price_graph(element, callback=undefined, no_data_cal const stop_color = "#FFA500"; const sell_color = "#F65A33"; const buy_color = isDarkTheme() ? '#299a39' : "#009900"; +const candle_sell_color = isDarkTheme() ? "#F65A33" : "#F65A33"; +const candle_buy_color = isDarkTheme() ? '#7DF98D' : "#009900"; function create_candlesticks(candles){ const data_time = candles["time"]; @@ -132,9 +134,9 @@ function create_candlesticks(candles){ return { x: data_time, close: data_close, - decreasing: {line: {color: sell_color}}, + decreasing: {line: {color: candle_sell_color}}, high: data_high, - increasing: {line: {color: buy_color}}, + increasing: {line: {color: candle_buy_color}}, line: {color: 'rgba(31,119,180,1)'}, low: data_low, open: data_open, @@ -187,22 +189,23 @@ function create_trades(trades, trader){ const data_trade_description = trades["trade_description"]; const data_order_side = trades["order_side"]; - const marker_size = trader === "Simulator" ? 14 : 16; - const marker_opacity = trader === "Simulator" ? 0.5 : 0.65; + const marker_size = 15; + const marker_opacity = 0.85; const border_line_color = "#b6b8c3"; const colors = []; $.each(data_order_side, function (index, value) { colors.push(_getOrderColor(trades["trade_description"][index], value)); }); - const line_with = trader === "Simulator" ? 0 : 1; + const line_with = 1; return { x: data_time, y: data_price, mode: 'markers', - name: trader, + name: "", text: data_trade_description, + hovertemplate: `%{text}
%{x}`, marker: { color: colors, size: marker_size, diff --git a/Services/Interfaces/web_interface/static/js/components/dashboard.js b/Services/Interfaces/web_interface/static/js/components/dashboard.js index 194ddb5ac..992246551 100644 --- a/Services/Interfaces/web_interface/static/js/components/dashboard.js +++ b/Services/Interfaces/web_interface/static/js/components/dashboard.js @@ -48,6 +48,8 @@ $(document).ready(function () { const updateProfitabilityDisplay = (bot_real_profitability, bot_real_flat_profitability, bot_simulated_profitability, bot_simulated_flat_profitability) => { + bot_simulated_profitability = 21 + bot_simulated_flat_profitability = 190 if(isDefined(bot_real_profitability)){ displayProfitability(bot_real_profitability, bot_real_flat_profitability); } diff --git a/Services/Interfaces/web_interface/templates/index.html b/Services/Interfaces/web_interface/templates/index.html index 4b0682451..4c848f23e 100644 --- a/Services/Interfaces/web_interface/templates/index.html +++ b/Services/Interfaces/web_interface/templates/index.html @@ -25,7 +25,7 @@
{% endif %} {% if not IS_CLOUD %} {% endif %} From 9a045eb6ec226336c1698a01bd389cb462690af0 Mon Sep 17 00:00:00 2001 From: Guillaume De Saint Martin Date: Fri, 19 Jul 2024 00:16:17 +0200 Subject: [PATCH 02/20] [WebInterface] fix candlesticks resize --- Services/Interfaces/web_interface/static/css/style.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Services/Interfaces/web_interface/static/css/style.css b/Services/Interfaces/web_interface/static/css/style.css index 6cd7a1b75..a4b968a0a 100644 --- a/Services/Interfaces/web_interface/static/css/style.css +++ b/Services/Interfaces/web_interface/static/css/style.css @@ -563,7 +563,7 @@ footer.page-footer { /* Theme */ /* Elegant */ .card-body.candle-graph { - min-height: 30.625rem; + height: 30.625rem; background-color: inherit; } From f5f94ca0cbcede9554f221629534771263ab5697 Mon Sep 17 00:00:00 2001 From: Guillaume De Saint Martin Date: Fri, 19 Jul 2024 00:33:28 +0200 Subject: [PATCH 03/20] [WebInterface] use color palette for candlesticks --- .../web_interface/static/js/common/candlesticks.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Services/Interfaces/web_interface/static/js/common/candlesticks.js b/Services/Interfaces/web_interface/static/js/common/candlesticks.js index a66243bbe..7c604eaaf 100644 --- a/Services/Interfaces/web_interface/static/js/common/candlesticks.js +++ b/Services/Interfaces/web_interface/static/js/common/candlesticks.js @@ -120,9 +120,9 @@ function get_watched_symbol_price_graph(element, callback=undefined, no_data_cal const stop_color = "#FFA500"; const sell_color = "#F65A33"; -const buy_color = isDarkTheme() ? '#299a39' : "#009900"; -const candle_sell_color = isDarkTheme() ? "#F65A33" : "#F65A33"; -const candle_buy_color = isDarkTheme() ? '#7DF98D' : "#009900"; +const buy_color = isDarkTheme() ? '#6cb596' : "#6cb596"; +const candle_sell_color = sell_color; +const candle_buy_color = isDarkTheme() ? '#65e7cf' : "#6cb596"; function create_candlesticks(candles){ const data_time = candles["time"]; @@ -189,15 +189,15 @@ function create_trades(trades, trader){ const data_trade_description = trades["trade_description"]; const data_order_side = trades["order_side"]; - const marker_size = 15; - const marker_opacity = 0.85; - const border_line_color = "#b6b8c3"; + const marker_size = 16; + const marker_opacity = 0.9; + const border_line_color = getTextColor(); const colors = []; $.each(data_order_side, function (index, value) { colors.push(_getOrderColor(trades["trade_description"][index], value)); }); - const line_with = 1; + const line_with = isDarkTheme() ? 1 : 0.2; return { x: data_time, From 93d8bfe2c46c75a656e9fa34b5c8e62eeee98833 Mon Sep 17 00:00:00 2001 From: Guillaume De Saint Martin Date: Fri, 19 Jul 2024 10:48:56 +0200 Subject: [PATCH 04/20] [WebInterface] improve new version notification --- Services/Interfaces/web_interface/controllers/home.py | 3 +++ Services/Interfaces/web_interface/templates/index.html | 10 +++++++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/Services/Interfaces/web_interface/controllers/home.py b/Services/Interfaces/web_interface/controllers/home.py index 2a015ff59..00e0c09a6 100644 --- a/Services/Interfaces/web_interface/controllers/home.py +++ b/Services/Interfaces/web_interface/controllers/home.py @@ -87,6 +87,9 @@ def home(): sandbox_exchanges=sandbox_exchanges, display_ph_launch=display_ph_launch, is_launching=is_launching, + latest_release_url=f"{octobot_commons.constants.GITHUB_BASE_URL}/" + f"{octobot_commons.constants.GITHUB_ORGANISATION}/" + f"{constants.PROJECT_NAME}/releases/latest", ) else: return flask.redirect(flask.url_for("terms")) diff --git a/Services/Interfaces/web_interface/templates/index.html b/Services/Interfaces/web_interface/templates/index.html index 4c848f23e..4931732c6 100644 --- a/Services/Interfaces/web_interface/templates/index.html +++ b/Services/Interfaces/web_interface/templates/index.html @@ -25,7 +25,15 @@
{% endif %} {% if not IS_CLOUD %} {% endif %} From 0e3fe64e497c9de1b089d7ba77c9639b721ec213 Mon Sep 17 00:00:00 2001 From: Guillaume De Saint Martin Date: Fri, 19 Jul 2024 10:12:03 +0200 Subject: [PATCH 05/20] [WebInterface] improve dark UI --- .../web_interface/static/css/style.css | 34 +++++++++++++++---- .../static/js/common/candlesticks.js | 10 +++--- .../components/config/currency_card.html | 4 +-- .../components/config/exchange_card.html | 2 +- .../components/config/service_card.html | 2 +- .../templates/trading_type_selector.html | 2 +- 6 files changed, 38 insertions(+), 16 deletions(-) diff --git a/Services/Interfaces/web_interface/static/css/style.css b/Services/Interfaces/web_interface/static/css/style.css index a4b968a0a..3a1eab767 100644 --- a/Services/Interfaces/web_interface/static/css/style.css +++ b/Services/Interfaces/web_interface/static/css/style.css @@ -21,6 +21,8 @@ :root { --mdb-body-font-family: DM Sans, sans-serif; --local-secondary-bg-text-color: #0f1237; /* same as dark mdb-primary */ + --local-price-chart-sell-color: #F65A33; + --local-price-chart-stop-color: #FFA500; } :root[data-mdb-theme=light] { @@ -72,14 +74,22 @@ --mdb-card-long-border-color: var(--mdb-secondary); --mdb-card-short-border-color: var(--mdb-orange); --mdb-card-very-short-border-color: var(--mdb-red); + --mdb-card-bg: var(--mdb-bg); + --mdb-card-color: var(--mdb-primary); + --mdb-surface-bg: var(--mdb-bg); /* navbar */ --mdb-navbar-bg: var(--mdb-bg); --mdb-navbar-brand-color: var(--mdb-primary); - --mdb-card-bg: var(--mdb-bg); - --mdb-card-color: var(--mdb-primary); - --mdb-surface-bg: var(--mdb-bg); + /* local */ + /* config cards */ + --local-config-card--border-width: 0px; + + /* price charts */ + --local-price-chart-buy-color: #6cb596; + --local-price-chart-candle-sell-color: var(--local-price-chart-sell-color); + --local-price-chart-candle-buy-color: #6cb596; } :root[data-mdb-theme=dark] { @@ -130,14 +140,22 @@ --mdb-card-long-border-color: var(--mdb-secondary); --mdb-card-short-border-color: var(--mdb-orange); --mdb-card-very-short-border-color: var(--mdb-red); + --mdb-card-bg: var(--mdb-secondary); + --mdb-card-color: var(--mdb-primary); + --mdb-surface-bg: var(--mdb-bg-500); /* navbar */ --mdb-navbar-bg: var(--mdb-bg); --mdb-navbar-brand-color: var(--mdb-primary); - --mdb-card-bg: var(--mdb-secondary); - --mdb-card-color: var(--mdb-primary); - --mdb-surface-bg: var(--mdb-bg-500); + /* local */ + /* config cards */ + --local-config-card--border-width: 1px; + + /* price charts */ + --local-price-chart-buy-color: #6cb596; + --local-price-chart-candle-sell-color: var(--local-price-chart-sell-color); + --local-price-chart-candle-buy-color: #65e7cf; } /* Fix incompatibility with bootstrap 4 */ @@ -459,6 +477,10 @@ footer.page-footer { flex-basis: inherit !important; } +.config-card { + border: var(--local-config-card--border-width) solid rgba(var(--mdb-primary-rgb), 0.3); +} + .community-bot-stats-label { font-weight: bold; font-size: x-large; diff --git a/Services/Interfaces/web_interface/static/js/common/candlesticks.js b/Services/Interfaces/web_interface/static/js/common/candlesticks.js index 7c604eaaf..0fe75b880 100644 --- a/Services/Interfaces/web_interface/static/js/common/candlesticks.js +++ b/Services/Interfaces/web_interface/static/js/common/candlesticks.js @@ -118,11 +118,11 @@ function get_watched_symbol_price_graph(element, callback=undefined, no_data_cal }); } -const stop_color = "#FFA500"; -const sell_color = "#F65A33"; -const buy_color = isDarkTheme() ? '#6cb596' : "#6cb596"; -const candle_sell_color = sell_color; -const candle_buy_color = isDarkTheme() ? '#65e7cf' : "#6cb596"; +const stop_color = getComputedStyle(document.body).getPropertyValue('--local-price-chart-stop-color'); +const sell_color = getComputedStyle(document.body).getPropertyValue('--local-price-chart-sell-color'); +const buy_color = getComputedStyle(document.body).getPropertyValue('--local-price-chart-buy-color'); +const candle_sell_color = getComputedStyle(document.body).getPropertyValue('----local-price-chart-candle-sell-color'); +const candle_buy_color = getComputedStyle(document.body).getPropertyValue('--local-price-chart-candle-buy-color'); function create_candlesticks(candles){ const data_time = candles["time"]; diff --git a/Services/Interfaces/web_interface/templates/components/config/currency_card.html b/Services/Interfaces/web_interface/templates/components/config/currency_card.html index ea9be644c..b497bf012 100644 --- a/Services/Interfaces/web_interface/templates/components/config/currency_card.html +++ b/Services/Interfaces/web_interface/templates/components/config/currency_card.html @@ -8,7 +8,7 @@
- {{ crypto_currency }}
-

+

{{ m_editable_config.editable_key( config_symbols, crypto_currency, "crypto-currencies_" + crypto_currency, diff --git a/Services/Interfaces/web_interface/templates/components/config/exchange_card.html b/Services/Interfaces/web_interface/templates/components/config/exchange_card.html index 58a885fb9..20fe60fe5 100644 --- a/Services/Interfaces/web_interface/templates/components/config/exchange_card.html +++ b/Services/Interfaces/web_interface/templates/components/config/exchange_card.html @@ -6,7 +6,7 @@

-
+

{{exchange}} diff --git a/Services/Interfaces/web_interface/templates/components/config/service_card.html b/Services/Interfaces/web_interface/templates/components/config/service_card.html index 01c37edbb..4e7a5b9e5 100644 --- a/Services/Interfaces/web_interface/templates/components/config/service_card.html +++ b/Services/Interfaces/web_interface/templates/components/config/service_card.html @@ -5,7 +5,7 @@
-
+

diff --git a/Services/Interfaces/web_interface/templates/trading_type_selector.html b/Services/Interfaces/web_interface/templates/trading_type_selector.html index 9ef0ef290..65642ffa1 100644 --- a/Services/Interfaces/web_interface/templates/trading_type_selector.html +++ b/Services/Interfaces/web_interface/templates/trading_type_selector.html @@ -65,7 +65,7 @@

Trade using
-
+

{{enabled_exchanges[0]}} From 322d1c708ae63a80274baec444a3ccbdb87eea32 Mon Sep 17 00:00:00 2001 From: Guillaume De Saint Martin Date: Sat, 20 Jul 2024 10:38:26 +0200 Subject: [PATCH 06/20] [WebInterface] remove dashboard temp values --- .../Interfaces/web_interface/static/js/components/dashboard.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/Services/Interfaces/web_interface/static/js/components/dashboard.js b/Services/Interfaces/web_interface/static/js/components/dashboard.js index 992246551..194ddb5ac 100644 --- a/Services/Interfaces/web_interface/static/js/components/dashboard.js +++ b/Services/Interfaces/web_interface/static/js/components/dashboard.js @@ -48,8 +48,6 @@ $(document).ready(function () { const updateProfitabilityDisplay = (bot_real_profitability, bot_real_flat_profitability, bot_simulated_profitability, bot_simulated_flat_profitability) => { - bot_simulated_profitability = 21 - bot_simulated_flat_profitability = 190 if(isDefined(bot_real_profitability)){ displayProfitability(bot_real_profitability, bot_real_flat_profitability); } From 17608c1b8e91bfae838c7bb98f6d4e5237788f68 Mon Sep 17 00:00:00 2001 From: Guillaume De Saint Martin Date: Sat, 20 Jul 2024 10:39:03 +0200 Subject: [PATCH 07/20] [WebInterface] restore update button --- Services/Interfaces/web_interface/templates/index.html | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/Services/Interfaces/web_interface/templates/index.html b/Services/Interfaces/web_interface/templates/index.html index 4931732c6..839ae6c88 100644 --- a/Services/Interfaces/web_interface/templates/index.html +++ b/Services/Interfaces/web_interface/templates/index.html @@ -30,10 +30,9 @@
OctoBot version is available.
- - View latest release - +

{% endif %} From eefdbbb8857e22fd386fc6669fd2f45501968a98 Mon Sep 17 00:00:00 2001 From: Guillaume De Saint Martin Date: Mon, 22 Jul 2024 23:26:24 +0200 Subject: [PATCH 08/20] [IndexTrading] allow intra-day update --- Trading/Mode/index_trading_mode/index_trading.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Trading/Mode/index_trading_mode/index_trading.py b/Trading/Mode/index_trading_mode/index_trading.py index d5deea211..fbf509b76 100644 --- a/Trading/Mode/index_trading_mode/index_trading.py +++ b/Trading/Mode/index_trading_mode/index_trading.py @@ -459,10 +459,10 @@ def init_user_inputs(self, inputs: dict) -> None: Called right before starting the tentacle, should define all the tentacle's user inputs unless those are defined somewhere else. """ - self.refresh_interval_days = int(self.UI.user_input( - IndexTradingModeProducer.REFRESH_INTERVAL, commons_enums.UserInputTypes.INT, + self.refresh_interval_days = float(self.UI.user_input( + IndexTradingModeProducer.REFRESH_INTERVAL, commons_enums.UserInputTypes.FLOAT, self.refresh_interval_days, inputs, - min_val=0, + min_val=0.0006, # min 1 per minute title="Trigger period: Days to wait between each rebalance.", )) self.rebalance_trigger_min_ratio = decimal.Decimal(str(self.UI.user_input( From 124cc064e3e1820acde181d3a4e4c18e98f5f5d3 Mon Sep 17 00:00:00 2001 From: Guillaume De Saint Martin Date: Tue, 23 Jul 2024 10:36:49 +0200 Subject: [PATCH 09/20] [Profiles] add default index profile --- profiles/index_trading/profile.json | 63 +++++++++++++++++++ .../specific_config/IndexTradingMode.json | 6 ++ profiles/index_trading/tentacles_config.json | 7 +++ 3 files changed, 76 insertions(+) create mode 100644 profiles/index_trading/profile.json create mode 100644 profiles/index_trading/specific_config/IndexTradingMode.json create mode 100644 profiles/index_trading/tentacles_config.json diff --git a/profiles/index_trading/profile.json b/profiles/index_trading/profile.json new file mode 100644 index 000000000..202042c4d --- /dev/null +++ b/profiles/index_trading/profile.json @@ -0,0 +1,63 @@ +{ + "config": { + "crypto-currencies": { + "Bitcoin": { + "enabled": true, + "pairs": [ + "BTC/USDT" + ] + }, + "Ethereum": { + "enabled": true, + "pairs": [ + "ETH/USDT" + ] + }, + "Solana": { + "enabled": true, + "pairs": [ + "SOL/USDT" + ] + } + }, + "exchanges": { + "binance": { + "enabled": true, + "exchange-type": "spot" + } + }, + "trader": { + "enabled": false, + "load-trade-history": false + }, + "trader-simulator": { + "enabled": true, + "fees": { + "maker": 0.1, + "taker": 0.1 + }, + "starting-portfolio": { + "USDT": 1000 + } + }, + "trading": { + "reference-market": "USDT", + "risk": 0.5 + } + }, + "profile": { + "auto_update": false, + "avatar": "default_profile.png", + "complexity": 1, + "description": "Index Trading will maintain a custom crypto index using each enabled traded coin.", + "extra_backtesting_time_frames": [], + "id": "index_trading", + "imported": false, + "name": "Index trading", + "origin_url": null, + "read_only": true, + "risk": 1, + "slug": "", + "type": "live" + } +} \ No newline at end of file diff --git a/profiles/index_trading/specific_config/IndexTradingMode.json b/profiles/index_trading/specific_config/IndexTradingMode.json new file mode 100644 index 000000000..9f26d87ab --- /dev/null +++ b/profiles/index_trading/specific_config/IndexTradingMode.json @@ -0,0 +1,6 @@ +{ + "index_content": [], + "rebalance_trigger_min_percent": 5, + "refresh_interval": 1, + "required_strategies": [] +} \ No newline at end of file diff --git a/profiles/index_trading/tentacles_config.json b/profiles/index_trading/tentacles_config.json new file mode 100644 index 000000000..62b585237 --- /dev/null +++ b/profiles/index_trading/tentacles_config.json @@ -0,0 +1,7 @@ +{ + "tentacle_activation": { + "Trading": { + "IndexTradingMode": true + } + } +} \ No newline at end of file From a8964bbdaf3f31dec63ae8d1d66249d9c5441d06 Mon Sep 17 00:00:00 2001 From: Guillaume De Saint Martin Date: Tue, 23 Jul 2024 11:18:57 +0200 Subject: [PATCH 10/20] [IndexTrading] enable real-time price check --- .../Mode/index_trading_mode/index_trading.py | 30 ++++++++++++++++--- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/Trading/Mode/index_trading_mode/index_trading.py b/Trading/Mode/index_trading_mode/index_trading.py index fbf509b76..695ea99df 100644 --- a/Trading/Mode/index_trading_mode/index_trading.py +++ b/Trading/Mode/index_trading_mode/index_trading.py @@ -245,6 +245,13 @@ async def stop(self): async def ohlcv_callback(self, exchange: str, exchange_id: str, cryptocurrency: str, symbol: str, time_frame: str, candle: dict, init_call: bool = False): + await self._check_index_if_necessary() + + async def kline_callback(self, exchange: str, exchange_id: str, cryptocurrency: str, symbol: str, + time_frame, kline: dict): + await self._check_index_if_necessary() + + async def _check_index_if_necessary(self): current_time = self.exchange_manager.exchange.get_exchange_current_time() if ( current_time - self._last_trigger_time @@ -259,7 +266,8 @@ async def ohlcv_callback(self, exchange: str, exchange_id: str, cryptocurrency: else: self._notify_if_missing_too_many_coins() await self.ensure_index() - self.logger.debug(f"Next index check in {self.trading_mode.refresh_interval_days} days") + if not self.trading_mode.is_updating_at_each_price_change(): + self.logger.debug(f"Next index check in {self.trading_mode.refresh_interval_days} days") self._last_trigger_time = current_time async def ensure_index(self): @@ -436,7 +444,17 @@ def _resolve_swaps(self, details: dict): return def get_channels_registration(self): - return [self.TOPIC_TO_CHANNEL_NAME[commons_enums.ActivationTopics.FULL_CANDLES.value]] + # use candles to trigger at each candle interval and when initializing + topics = [ + self.TOPIC_TO_CHANNEL_NAME[commons_enums.ActivationTopics.FULL_CANDLES.value], + ] + if self.trading_mode.is_updating_at_each_price_change(): + # use kline to trigger at each price change + self.logger.info(f"Using price change bound update instead of time-based update.") + topics.append( + self.TOPIC_TO_CHANNEL_NAME[commons_enums.ActivationTopics.IN_CONSTRUCTION_CANDLES.value] + ) + return topics class IndexTradingMode(trading_modes.AbstractTradingMode): @@ -462,8 +480,9 @@ def init_user_inputs(self, inputs: dict) -> None: self.refresh_interval_days = float(self.UI.user_input( IndexTradingModeProducer.REFRESH_INTERVAL, commons_enums.UserInputTypes.FLOAT, self.refresh_interval_days, inputs, - min_val=0.0006, # min 1 per minute - title="Trigger period: Days to wait between each rebalance.", + min_val=0, + title="Trigger period: Days to wait between each rebalance. Can be a fraction of a day. " + "When set to 0, every new price will trigger a rebalance check.", )) self.rebalance_trigger_min_ratio = decimal.Decimal(str(self.UI.user_input( IndexTradingModeProducer.REBALANCE_TRIGGER_MIN_PERCENT, commons_enums.UserInputTypes.FLOAT, @@ -478,6 +497,9 @@ def init_user_inputs(self, inputs: dict) -> None: ) self._update_coins_distribution() + def is_updating_at_each_price_change(self): + return self.refresh_interval_days == 0 + def _update_coins_distribution(self): distribution = self._get_supported_distribution() self.ratio_per_asset = { From 30bd2f1411e49d3e42bda07408010f8bb110d17d Mon Sep 17 00:00:00 2001 From: Guillaume De Saint Martin Date: Thu, 25 Jul 2024 11:37:07 +0200 Subject: [PATCH 11/20] [WebInterface] also send info before login --- .../advanced_templates/advanced_layout.html | 2 +- .../static/js/common/tracking.js | 27 +++++++++++++------ .../web_interface/templates/layout.html | 2 +- 3 files changed, 21 insertions(+), 10 deletions(-) diff --git a/Services/Interfaces/web_interface/advanced_templates/advanced_layout.html b/Services/Interfaces/web_interface/advanced_templates/advanced_layout.html index 4af30475b..a4294c235 100644 --- a/Services/Interfaces/web_interface/advanced_templates/advanced_layout.html +++ b/Services/Interfaces/web_interface/advanced_templates/advanced_layout.html @@ -47,7 +47,7 @@ {% if IS_DEMO or IS_CLOUD or IS_ALLOWING_TRACKING%} {% endif %} diff --git a/Services/Interfaces/web_interface/static/js/common/tracking.js b/Services/Interfaces/web_interface/static/js/common/tracking.js index 91210b00e..6e8419e96 100644 --- a/Services/Interfaces/web_interface/static/js/common/tracking.js +++ b/Services/Interfaces/web_interface/static/js/common/tracking.js @@ -2,17 +2,20 @@ $(document).ready(function() { const getUserEmail = () => { - return getUserDetails().email + return getUserDetails().email || ""; } const getUserDetails = () => { + if (_USER_DETAILS.email === ""){ + // do not erase email if unset + delete _USER_DETAILS.email; + } return _USER_DETAILS } const updateUserDetails = () => { posthog.capture( - getUserEmail(), - event='update_user_details', + 'up_user_details', properties={ '$set': getUserDetails(), } @@ -21,11 +24,19 @@ $(document).ready(function() { const shouldUpdateUserDetails = () => { const currentProperties = posthog.get_property('$stored_person_properties'); - return ( - getUserEmail() !== "" - && isDefined(currentProperties) - && JSON.stringify(currentProperties) !== JSON.stringify(getUserDetails()) - ) + if(currentProperties === undefined){ + return true; + } + if(isDefined(currentProperties)){ + const currentDetails = getUserDetails(); + if(currentDetails.email === undefined){ + // compare without email (otherwise result is always different as no email is currently set) + const localProperties = JSON.parse(JSON.stringify(currentProperties)); + delete localProperties.email + return JSON.stringify(localProperties) !== JSON.stringify(getUserDetails()); + } + } + return JSON.stringify(currentProperties) !== JSON.stringify(getUserDetails()); } const shouldReset = (newEmail) => { diff --git a/Services/Interfaces/web_interface/templates/layout.html b/Services/Interfaces/web_interface/templates/layout.html index 840702896..58816a23e 100644 --- a/Services/Interfaces/web_interface/templates/layout.html +++ b/Services/Interfaces/web_interface/templates/layout.html @@ -61,7 +61,7 @@ {% if IS_DEMO or IS_CLOUD or IS_ALLOWING_TRACKING%} {% endif %} From 432d6919f5d8305c143c0023443ffdeff1f2e713 Mon Sep 17 00:00:00 2001 From: Guillaume De Saint Martin Date: Thu, 25 Jul 2024 11:45:53 +0200 Subject: [PATCH 12/20] [WebInterface] fix exchange accounts check error --- .../web_interface/static/js/common/exchange_accounts.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Services/Interfaces/web_interface/static/js/common/exchange_accounts.js b/Services/Interfaces/web_interface/static/js/common/exchange_accounts.js index 5ac82f499..9554a72bb 100644 --- a/Services/Interfaces/web_interface/static/js/common/exchange_accounts.js +++ b/Services/Interfaces/web_interface/static/js/common/exchange_accounts.js @@ -93,7 +93,7 @@ function register_exchanges_checks(check_existing_accounts){ const check_account = (exchangeCard, source, newValue) => { const exchange = exchangeCard.find(".card-body").attr("name"); - if(exchange !== config_default_value){ + if(exchange !== config_default_value && exchangeCard.find("#exchange_api-key").length > 0){ const apiKey = source.attr("id") === "exchange_api-key" ? newValue : exchangeCard.find("#exchange_api-key").editable('getValue', true).trim(); const apiSecret = source.attr("id") === "exchange_api-secret" ? newValue : exchangeCard.find("#exchange_api-secret").editable('getValue', true).trim(); const apiPassword = source.attr("id") === "exchange_api-password" ? newValue : exchangeCard.find("#exchange_api-password").editable('getValue', true).trim(); From fca9172587be010d030ab09ea68b249073a52e7d Mon Sep 17 00:00:00 2001 From: Guillaume De Saint Martin Date: Mon, 22 Jul 2024 22:56:12 +0200 Subject: [PATCH 13/20] [Kucoin] add websocket feeds limit --- Trading/Exchange/kucoin_websocket_feed/kucoin_websocket.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Trading/Exchange/kucoin_websocket_feed/kucoin_websocket.py b/Trading/Exchange/kucoin_websocket_feed/kucoin_websocket.py index dbe9383f4..8d58142b5 100644 --- a/Trading/Exchange/kucoin_websocket_feed/kucoin_websocket.py +++ b/Trading/Exchange/kucoin_websocket_feed/kucoin_websocket.py @@ -48,6 +48,10 @@ class KucoinCCXTWebsocketConnector(exchanges.CCXTWebsocketConnector): Feeds.TICKER: [Feeds.KLINE] } + # Feeds to create above which not to use websockets + # Kucoin raises "exceed max permits per second" when subscribing to more than 100 feels + MAX_HANDLED_FEEDS = 100 + RECREATE_CLIENT_ON_DISCONNECT = True # when True, a new ccxt websocket client will replace the previous # one when the exchange is disconnected From e2b28f62116787c0a4c3f37851499cf7925a7dbc Mon Sep 17 00:00:00 2001 From: Guillaume De Saint Martin Date: Mon, 22 Jul 2024 23:03:32 +0200 Subject: [PATCH 14/20] [WebInterface] handle overloaded websockets --- Services/Interfaces/web_interface/models/trading.py | 3 ++- Services/Interfaces/web_interface/templates/trading.html | 8 +++++++- .../Exchange/kucoin_websocket_feed/kucoin_websocket.py | 2 +- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/Services/Interfaces/web_interface/models/trading.py b/Services/Interfaces/web_interface/models/trading.py index 63c027455..9bfed793a 100644 --- a/Services/Interfaces/web_interface/models/trading.py +++ b/Services/Interfaces/web_interface/models/trading.py @@ -87,7 +87,8 @@ def get_exchanges_load(): "load": trading_api.get_currently_handled_pair_with_time_frame(exchange_manager), "max_load": trading_api.get_max_handled_pair_with_time_frame(exchange_manager), "overloaded": trading_api.is_overloaded(exchange_manager), - "has_websocket": trading_api.get_has_websocket(exchange_manager) + "has_websocket": trading_api.get_has_websocket(exchange_manager), + "has_reached_websocket_limit": trading_api.get_has_reached_websocket_limit(exchange_manager) } for exchange_manager in interfaces_util.get_exchange_managers() } diff --git a/Services/Interfaces/web_interface/templates/trading.html b/Services/Interfaces/web_interface/templates/trading.html index a738a0d8a..39f93af8f 100644 --- a/Services/Interfaces/web_interface/templates/trading.html +++ b/Services/Interfaces/web_interface/templates/trading.html @@ -8,7 +8,13 @@ {% set vars = {'exchange_overload': False} %} {% macro exchange_overload_warning(exchange, load) -%} - {% if load["overloaded"] %} + {% if load["has_reached_websocket_limit"] %} + + {% elif load["overloaded"] %}