Skip to content

Commit 08171e9

Browse files
authored
Merge pull request #2694 from Drakkar-Software/dev
Dev merge
2 parents 78d15bf + 0ec33a8 commit 08171e9

File tree

13 files changed

+74
-55
lines changed

13 files changed

+74
-55
lines changed

CHANGELOG.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,19 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
66

77
*It is strongly advised to perform an update of your tentacles after updating OctoBot. (start.py tentacles --install --all)*
88

9+
## [2.0.3] - 2024-08-03
10+
### Added
11+
- [IndexTradingMode]: Default profile, intra-day, real time update option and custom content
12+
### Updated
13+
- [Trades] Greatly increase maximum trades in history
14+
- [Updaters] Restore binary updater
15+
- [WebInterface] Improve candlesticks display
16+
- [WebInterface] Improve dark theme UI
17+
### Fixed
18+
- [WebInterface] Ignore archived bots in community tab
19+
- [Kucoin] Websocket issues when using more than 100 feeds
20+
- [Notifications] Now display real trades PNL or no PNL at all
21+
922
## [2.0.2] - 2024-07-17
1023
### Updated
1124
- [WebInterface] Improve light & dark themes display

README.md

Lines changed: 2 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# OctoBot [2.0.2](https://github.com/Drakkar-Software/OctoBot/blob/master/CHANGELOG.md)
1+
# OctoBot [2.0.3](https://github.com/Drakkar-Software/OctoBot/blob/master/CHANGELOG.md)
22
[![PyPI](https://img.shields.io/pypi/v/OctoBot.svg?logo=pypi)](https://pypi.org/project/OctoBot)
33
[![Downloads](https://pepy.tech/badge/octobot/month)](https://pepy.tech/project/octobot)
44
[![Dockerhub](https://img.shields.io/docker/pulls/drakkarsoftware/octobot.svg?logo=docker)](https://hub.docker.com/r/drakkarsoftware/octobot)
@@ -12,15 +12,6 @@
1212
[![Twitter](https://img.shields.io/twitter/follow/DrakkarsOctobot.svg?label=twitter&style=social)](https://x.com/DrakkarsOctoBot)
1313
[![YouTube](https://img.shields.io/youtube/channel/views/UC2YAaBeWY8y_Olqs79b_X8A?label=youtube&style=social)](https://www.youtube.com/@octobot1134)
1414

15-
## 🎉 OctoBot is launching on Product Hunt on July 10th
16-
17-
<p align="center">
18-
<a href="https://www.producthunt.com/posts/octobot-open-source?embed=true&utm_source=badge-featured&utm_medium=badge&utm_souce=badge-octobot&#0045;open&#0045;source" target="_blank"><img src="https://api.producthunt.com/widgets/embed-image/v1/featured.svg?post_id=463219&theme=light" alt="OctoBot&#0032;open&#0032;source - Your&#0032;open&#0032;source&#0032;investment&#0032;strategy&#0032;builder | Product Hunt" style="width: 250px; height: 54px;" width="250" height="54" /></a>
19-
</p>
20-
<p align="center">
21-
👆 Follow the launch to get your exclusive discount!
22-
</p>
23-
2415
<p align="center">
2516
<img src="../assets/illustration.png" alt="Octobot automating trades of its user while the user is relaxing on his couch">
2617
</p>
@@ -67,15 +58,7 @@ To install OctoBot, you can either:
6758
Your OctoBot will be accessible on [http://localhost](http://localhost).
6859
6960
## Exchanges
70-
[![Binance supported exchange partnership](../assets/binance-logo.png)](https://www.octobot.cloud/en/guides/octobot-partner-exchanges/binance?utm_source=github&utm_medium=dk&utm_campaign=regular_open_source_content&utm_content=binance)
71-
[![Okx supported exchange partnership](../assets/okex-logo.png)](https://www.octobot.cloud/en/guides/octobot-partner-exchanges/okx?utm_source=github&utm_medium=dk&utm_campaign=regular_open_source_content&utm_content=okx)
72-
[![Kucoin supported exchange partnership](../assets/kucoin-logo.png)](https://www.octobot.cloud/en/guides/octobot-partner-exchanges/kucoin?utm_source=github&utm_medium=dk&utm_campaign=regular_open_source_content&utm_content=kucoin)
73-
[![Crypto.com supported exchange partnership](../assets/cryptocom-logo.png)](https://www.octobot.cloud/en/guides/octobot-partner-exchanges/crypto-com?utm_source=github&utm_medium=dk&utm_campaign=regular_open_source_content&utm_content=crypto-com)
74-
[![Huobi supported exchange partnership](../assets/huobi-logo.png)](https://www.octobot.cloud/en/guides/octobot-partner-exchanges/huobi?utm_source=github&utm_medium=dk&utm_campaign=regular_open_source_content&utm_content=huobi)
75-
[![Hollaex supported exchange partnership](../assets/hollaex-logo.png)](https://www.octobot.cloud/en/guides/octobot-partner-exchanges/hollaex?utm_source=github&utm_medium=dk&utm_campaign=regular_open_source_content&utm_content=hollaex)
76-
[![Coinbase supported exchange](../assets/coinbasepro-logo.png)](https://www.octobot.cloud/en/guides/octobot-supported-exchanges/coinbase?utm_source=github&utm_medium=dk&utm_campaign=regular_open_source_content&utm_content=coinbase)
77-
[![GateIO supported exchange partnership](../assets/gateio-logo.png)](https://www.octobot.cloud/en/guides/octobot-partner-exchanges/gateio?utm_source=github&utm_medium=dk&utm_campaign=regular_open_source_content&utm_content=gateio)
78-
[![Ascendex supported exchange partnership](../assets/ascendex-logo.png)](https://www.octobot.cloud/en/guides/octobot-partner-exchanges/ascendex?utm_source=github&utm_medium=dk&utm_campaign=regular_open_source_content&utm_content=ascendex)
61+
[![All OctoBot supported exchanges](../assets/exchange_logo.png)](https://www.octobot.cloud/en/guides/exchanges?utm_source=github&utm_medium=dk&utm_campaign=regular_open_source_content&utm_content=binance)
7962
8063
Octobot supports many [exchanges](https://www.octobot.cloud/en/guides/exchanges?utm_source=github&utm_medium=dk&utm_campaign=regular_open_source_content&utm_content=exchanges) thanks to the [ccxt library](https://github.com/ccxt/ccxt).
8164
To activate trading on an exchange, just configure OctoBot with your API keys as described [on the exchange setup guides](https://www.octobot.cloud/en/guides/octobot-configuration/exchanges?utm_source=github&utm_medium=dk&utm_campaign=regular_open_source_content&utm_content=exchanges_setup_guides).

octobot/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,5 +16,5 @@
1616

1717
PROJECT_NAME = "OctoBot"
1818
AUTHOR = "Drakkar-Software"
19-
VERSION = "2.0.2" # major.minor.revision
19+
VERSION = "2.0.3" # major.minor.revision
2020
LONG_VERSION = f"{VERSION}"

octobot/commands.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -127,8 +127,8 @@ async def update_or_repair_tentacles_if_necessary(community_auth, selected_profi
127127

128128
to_install_urls, to_remove_tentacles, force_refresh_tentacles_setup_config = \
129129
community_tentacles_packages.get_to_install_and_remove_tentacles(
130-
community_auth, selected_profile_tentacles_setup_config
131-
)
130+
community_auth, selected_profile_tentacles_setup_config, constants.LONG_VERSION
131+
) if community_auth else ([], [], False)
132132
if to_remove_tentacles:
133133
await community_tentacles_packages.uninstall_tentacles(to_remove_tentacles)
134134
elif force_refresh_tentacles_setup_config:
@@ -167,7 +167,8 @@ async def install_or_update_tentacles(
167167

168168

169169
async def install_all_tentacles(
170-
tentacles_url=None, additional_tentacles_package_urls: typing.Optional[list] = None, only_additional: bool = False
170+
tentacles_url=None, additional_tentacles_package_urls: typing.Optional[list] = None, only_additional: bool = False,
171+
bot_version: str = constants.LONG_VERSION
171172
):
172173
if tentacles_url is None:
173174
tentacles_url = configuration_manager.get_default_tentacles_url()
@@ -185,7 +186,7 @@ async def install_all_tentacles(
185186
if url is None:
186187
continue
187188
hide_url = url in additional_tentacles_package_urls
188-
url = community_tentacles_packages.adapt_url_to_bot_version(url)
189+
url = community_tentacles_packages.adapt_url_to_bot_version(url, bot_version)
189190
await tentacles_manager_api.install_all_tentacles(
190191
url,
191192
aiohttp_session=aiohttp_session,

octobot/community/authentication.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -427,7 +427,7 @@ def _get_self_hosted_bots(self, bots):
427427
return [
428428
bot
429429
for bot in bots
430-
if self.user_account.is_self_hosted(bot)
430+
if self.user_account.is_self_hosted(bot) and not self.user_account.is_archived(bot)
431431
]
432432

433433
async def on_new_bot_select(self):

octobot/community/models/community_user_account.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,11 @@ def is_self_hosted(self, bot):
7474
backend_enums.BotDeploymentKeys.TYPE.value, backend_enums.DeploymentTypes.SELF_HOSTED.value
7575
) == backend_enums.DeploymentTypes.SELF_HOSTED.value
7676

77+
def is_archived(self, bot):
78+
return self._get_bot_deployment(bot).get(
79+
backend_enums.BotDeploymentKeys.STATUS.value
80+
) == backend_enums.BotDeploymentStatus.ARCHIVED.value
81+
7782
def get_selected_bot_deployment_id(self):
7883
return self.get_bot_deployment_value(backend_enums.BotDeploymentKeys.ID)
7984

octobot/community/supabase_backend/enums.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ class BotDeploymentStatus(enum.Enum):
7777
STOPPED = "stopped"
7878
PENDING = "pending"
7979
UNKNOWN = "unknown"
80+
ARCHIVED = "archived"
8081

8182

8283
class ProductSubscriptionDesiredStatus(enum.Enum):

octobot/community/tentacles_packages.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ async def has_tentacles_to_install_and_uninstall_tentacles_if_necessary(communit
2323
community_auth.config.get_tentacles_config_path()
2424
)
2525
to_install, to_remove_tentacles, force_refresh_tentacles_setup_config = get_to_install_and_remove_tentacles(
26-
community_auth, tentacles_setup_config
26+
community_auth, tentacles_setup_config, constants.LONG_VERSION
2727
)
2828
if to_remove_tentacles:
2929
logging.get_logger(__name__).debug(
@@ -36,29 +36,29 @@ async def has_tentacles_to_install_and_uninstall_tentacles_if_necessary(communit
3636
return bool(to_install)
3737

3838

39-
def adapt_url_to_bot_version(package_url: str) -> str:
39+
def adapt_url_to_bot_version(package_url: str, bot_version: str) -> str:
4040
if constants.VERSION_PLACEHOLDER in package_url:
41-
package_url = package_url.replace(constants.VERSION_PLACEHOLDER, constants.LONG_VERSION)
41+
package_url = package_url.replace(constants.VERSION_PLACEHOLDER, bot_version)
4242
return package_url
4343

4444

4545
def get_to_install_and_remove_tentacles(
46-
community_auth, selected_profile_tentacles_setup_config
46+
community_auth, selected_profile_tentacles_setup_config, bot_version: str
4747
):
4848
installed_community_package_urls = [
49-
adapt_url_to_bot_version(package_url)
49+
adapt_url_to_bot_version(package_url, bot_version)
5050
for package_url in tentacles_manager_api.get_all_installed_package_urls(
5151
selected_profile_tentacles_setup_config
5252
)
5353
if is_community_tentacle_url(package_url)
5454
]
5555
additional_tentacles_package_urls = [
56-
adapt_url_to_bot_version(package_url)
56+
adapt_url_to_bot_version(package_url, bot_version)
5757
for package_url in community_auth.get_saved_package_urls()
5858
] if community_auth.is_logged_in() else []
5959
to_keep_tentacles = set(
6060
additional_tentacles_package_urls + [
61-
adapt_url_to_bot_version(package_url)
61+
adapt_url_to_bot_version(package_url, bot_version)
6262
for package_url in get_env_variable_tentacles_urls()
6363
] + get_env_variable_tentacles_urls()
6464
)

octobot/task_manager.py

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@
2626
import octobot.constants as constants
2727

2828

29+
ASYNC_IGNORED_ERROR_MESSAGES = ["'message': 'Unclosed client session'"]
30+
31+
2932
class TaskManager:
3033
"""TaskManager class:
3134
- Create, manage and stop octobot tasks
@@ -136,11 +139,19 @@ def create_pool_executor(self, workers=2):
136139
def _loop_exception_handler(self, loop, context):
137140
loop_str = "bot main async" if loop is self.async_loop else {loop}
138141
message = f"Error in {loop_str} loop: {context}"
142+
function = self.logger.debug if self._should_use_debug_for_message(message) else self.logger.warning
139143
exception = context.get('exception')
140144
if exception is not None:
141145
formatted_traceback = "\n".join(traceback.format_tb(exception.__traceback__))
142146
message = f"{message}:\n{formatted_traceback}"
143-
self.logger.warning(message)
147+
function(message)
148+
149+
@staticmethod
150+
def _should_use_debug_for_message(message: str) -> bool:
151+
for ignored_message in ASYNC_IGNORED_ERROR_MESSAGES:
152+
if ignored_message in message:
153+
return True
154+
return False
144155

145156
def _create_new_asyncio_main_loop(self):
146157
self.async_loop = asyncio.new_event_loop()

octobot/updater/binary_updater.py

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -56,10 +56,6 @@ async def get_latest_version(self):
5656
return self._parse_latest_version(await self._get_latest_release_data())
5757

5858
async def update_impl(self) -> bool:
59-
# TODO fix binary updater to use release endpoint (assents can't be downloaded from gh directly)
60-
self.logger.error(f"Please manually update your OctoBot executable from this page: "
61-
f"{self._get_latest_release_url(False)}")
62-
return False
6359
new_binary_file = await self._download_binary()
6460
if new_binary_file is not None:
6561
self._give_execution_rights(new_binary_file)
@@ -73,10 +69,11 @@ def _get_latest_release_url(self, use_api_url):
7369

7470
async def _get_latest_release_data(self):
7571
try:
76-
async with aiohttp.ClientSession().get(self._get_latest_release_url(True)) as resp:
77-
text = await resp.text()
78-
if resp.status == 200:
79-
return json.loads(text)
72+
async with aiohttp.ClientSession() as session:
73+
async with session.get(self._get_latest_release_url(True)) as resp:
74+
text = await resp.text()
75+
if resp.status == 200:
76+
return json.loads(text)
8077
return None
8178
except Exception as e:
8279
self.logger.debug(f"Error when fetching latest binary data : {e}")
@@ -137,10 +134,11 @@ async def _download_binary(self):
137134
return None
138135
self.logger.info(f"Start downloading OctoBot update at {new_binary_file_url}")
139136
async with aiofiles.open(new_binary_file, 'wb+') as downloaded_file:
140-
await aiohttp_util.download_stream_file(output_file=downloaded_file,
141-
file_url=new_binary_file_url,
142-
aiohttp_session=aiohttp.ClientSession(),
143-
is_aiofiles_output_file=True)
137+
async with aiohttp.ClientSession() as session:
138+
await aiohttp_util.download_stream_file(output_file=downloaded_file,
139+
file_url=new_binary_file_url,
140+
aiohttp_session=session,
141+
is_aiofiles_output_file=True)
144142
self.logger.info(f"OctoBot update downloaded successfully")
145143
return new_binary_file
146144

octobot/updater/python_updater.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,10 +49,11 @@ def _get_latest_pypi_release_url(self):
4949

5050
async def _get_latest_pypi_version_data(self):
5151
try:
52-
async with aiohttp.ClientSession().get(self._get_latest_pypi_release_url()) as resp:
53-
text = await resp.text()
54-
if resp.status == 200:
55-
return json.loads(text)
52+
async with aiohttp.ClientSession() as session:
53+
async with session.get(self._get_latest_pypi_release_url()) as resp:
54+
text = await resp.text()
55+
if resp.status == 200:
56+
return json.loads(text)
5657
return None
5758
except Exception as e:
5859
self.logger.debug(f"Error when fetching latest pypi package data : {e}")

octobot/updater/updater.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,11 +45,13 @@ async def update_impl(self) -> bool:
4545
raise NotImplementedError("update_impl is not implemented")
4646

4747
async def update_tentacles(self):
48+
bot_version = await self.get_latest_version()
4849
authenticator = authentication.Authenticator.instance()
4950
additional_tentacles_package_urls = authenticator.get_saved_package_urls()
5051
await commands.install_all_tentacles(
51-
tentacles_url=configuration_manager.get_default_tentacles_url(version=await self.get_latest_version()),
52-
additional_tentacles_package_urls=additional_tentacles_package_urls
52+
tentacles_url=configuration_manager.get_default_tentacles_url(version=bot_version),
53+
additional_tentacles_package_urls=additional_tentacles_package_urls,
54+
bot_version=bot_version
5355
)
5456

5557
async def post_update(self):

requirements.txt

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
# Drakkar-Software requirements
2-
OctoBot-Commons==1.9.50
3-
OctoBot-Trading==2.4.92
2+
OctoBot-Commons==1.9.51
3+
OctoBot-Trading==2.4.95
44
OctoBot-Evaluators==1.9.5
55
OctoBot-Tentacles-Manager==2.9.15
6-
OctoBot-Services==1.6.15
6+
OctoBot-Services==1.6.16
77
OctoBot-Backtesting==1.9.7
88
Async-Channel==2.2.1
9-
trading-backend==1.2.25
9+
trading-backend==1.2.26
1010

1111
## Others
1212
colorlog==6.8.0
@@ -27,6 +27,10 @@ supafunc==0.2.3 # Supabase functions calls (required by supabase and enforced
2727
postgrest==0.10.8 # Supabase posgres calls (required by supabase and enforced to allow direct import)
2828
realtime==1.0.0 # Supabase realtime lib (required by supabase and enforced to allow direct import)
2929

30+
# async http requests
31+
# avoid v3.10.0 as it is failing CI (<class 'RuntimeError'>: aiodns needs a SelectorEventLoop on Windows. See more: https://github.com/saghul/aiodns/issues/86)
32+
aiohttp==3.9.5
33+
3034
# Experimental to prevent httpx.PoolTimeout
3135
httpcore==0.17.3 # to up to at least 1.0.2 (prevent default version when installing httpx which creates httpx.PoolTimeout)
3236
anyio==4.0.0 #

0 commit comments

Comments
 (0)