diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index d9a0168..aa63c00 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -12,6 +12,7 @@ jobs: uses: Drakkar-Software/.github/.github/workflows/python3_lint_workflow.yml@master with: project_main_package: octobot_script + python_version: 3.13.x tests: name: ${{ matrix.os }} - Python - ${{ matrix.type }} - tests @@ -23,10 +24,10 @@ jobs: steps: - uses: actions/checkout@v5 - - name: Set up Python 3.10 + - name: Set up Python uses: actions/setup-python@v5 with: - python-version: 3.10.x + python-version: 3.13.x architecture: x64 - uses: actions/setup-node@v6 @@ -39,6 +40,11 @@ jobs: - name: Install tentacles from cli run: python start.py install_tentacles + - name: Build report templates + run: | + npm install + npm run build + - name: Pytests run: pytest --cov=. --cov-config=.coveragerc --durations=0 -rw tests @@ -61,7 +67,7 @@ jobs: - name: Set up Python uses: actions/setup-python@v5 with: - python-version: 3.10.x + python-version: 3.13.x architecture: x64 - name: Install dependencies diff --git a/CHANGELOG.md b/CHANGELOG.md index 28334cd..a427741 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,11 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.1.1] - 2026-03-22 +### Updated +- OctoBot to 2.1.0 +- Added python 3.13 support + ## [0.1.0] - 2026-02-27 ### Added - Support for services tentacles diff --git a/Dockerfile b/Dockerfile index f69a8dc..8614ad1 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,13 +1,9 @@ -FROM python:3.10-slim-buster AS base +FROM python:3.13-slim-buster AS base WORKDIR /app # requires git to install requirements with git+https -# Update to debian archive from https://gist.github.com/ishad0w/6ce1eb569c734880200c47923577426a -RUN echo "deb http://archive.debian.org/debian buster main contrib non-free" > /etc/apt/sources.list \ - && echo "deb http://archive.debian.org/debian-security buster/updates main contrib non-free" >> /etc/apt/sources.list \ - && echo "deb http://archive.debian.org/debian buster-backports main contrib non-free" >> /etc/apt/sources.list \ - && apt-get update \ +RUN apt-get update \ && apt-get install -y --no-install-recommends build-essential git gcc binutils COPY . . diff --git a/README.md b/README.md index 93de86d..092fb4f 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ Documentation available at [octobot.cloud/en/guides/octobot-script](https://www. ## Install OctoBot Script from pip -> OctoBot Script requires **Python 3.10** +> OctoBot Script requires **Python 3.13** ``` {.sourceCode .bash} python3 -m pip install OctoBot wheel appdirs==1.4.4 diff --git a/octobot_script/__init__.py b/octobot_script/__init__.py index 34c8136..853a551 100644 --- a/octobot_script/__init__.py +++ b/octobot_script/__init__.py @@ -16,7 +16,7 @@ PROJECT_NAME = "OctoBot-Script" AUTHOR = "Drakkar-Software" -VERSION = "0.1.0" # major.minor.revision => don't forget to also update the setup.py version +VERSION = "0.1.1" # major.minor.revision => don't forget to also update the setup.py version def _use_module_local_tentacles(): diff --git a/octobot_script/internal/logging_util.py b/octobot_script/internal/logging_util.py index 5e153db..c81e0a2 100644 --- a/octobot_script/internal/logging_util.py +++ b/octobot_script/internal/logging_util.py @@ -31,7 +31,7 @@ def load_logging_config(config_file="logging_config.ini"): os.mkdir(logs_folder) try: config.fileConfig(config_file) - except KeyError: + except (KeyError, FileNotFoundError): logging_config = os.path.join(octobot_mocks.get_module_install_path(), "config", config_file) config.fileConfig(logging_config) octobot.logger.init_bot_channel_logger() diff --git a/requirements.txt b/requirements.txt index aee6720..ee16b96 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,11 +1,11 @@ # Drakkar-Software requirements -OctoBot[full]==2.0.16 +OctoBot[full]==2.1.0 # manage tentacles install path appdirs==1.4.4 # CLI -click==8.1.3 +click==8.3.1 # versions managed by OctoBot's dependencies jinja2 diff --git a/setup.py b/setup.py index 1462d38..25b893e 100644 --- a/setup.py +++ b/setup.py @@ -114,6 +114,6 @@ def run(self): 'Operating System :: MacOS :: MacOS X', 'Operating System :: Microsoft :: Windows', 'Operating System :: POSIX', - 'Programming Language :: Python :: 3.10', + 'Programming Language :: Python :: 3.13', ], ) diff --git a/tests/functionnal/example_scripts/test_precomputed_vs_iteration_rsi.py b/tests/functionnal/example_scripts/test_precomputed_vs_iteration_rsi.py index ac493c0..8a08ffd 100644 --- a/tests/functionnal/example_scripts/test_precomputed_vs_iteration_rsi.py +++ b/tests/functionnal/example_scripts/test_precomputed_vs_iteration_rsi.py @@ -14,11 +14,15 @@ # You should have received a copy of the GNU General Public # License along with OctoBot-Script. If not, see . +import mock import pytest -import os +import shutil import tulipy +import os import octobot_script as obs +import octobot_script.resources as resources +import octobot_script.model.backtest_plot as backtest_plot from octobot_script.api.ploting import generate_and_show_report from tests.functionnal import one_day_btc_usdt_data @@ -27,7 +31,17 @@ pytestmark = pytest.mark.asyncio -async def test_precomputed_vs_iteration_rsi(one_day_btc_usdt_data): +@pytest.fixture +def mock_backtest_report_server_serve(): + with mock.patch.object( + backtest_plot.BacktestReportServer, "serve", mock.Mock() + ) as serve_mock: + yield serve_mock + + +async def test_precomputed_vs_iteration_rsi( + one_day_btc_usdt_data, mock_backtest_report_server_serve +): # 1. pre-compute entries at first iteration only async def _pre_compute_update(ctx): if run_data["entries"] is None: @@ -79,7 +93,9 @@ async def _pre_compute_update(ctx): assert res.duration < 10 assert res.candles_count == 1947 await _check_report(res) + mock_backtest_report_server_serve.assert_called_once() + await _reload_backtest_data(one_day_btc_usdt_data) # ensure second run gives the same result run_data = { "entries": None, @@ -101,6 +117,7 @@ async def _pre_compute_update(ctx): != res_2.report["bot_report"]["starting_portfolio"]["binance"] ) + await _reload_backtest_data(one_day_btc_usdt_data) # try with different config run_data = { "entries": None, @@ -146,6 +163,7 @@ async def _iterations_update(ctx): take_profit_offset="25%", ) + await _reload_backtest_data(one_day_btc_usdt_data) res_iteration = await obs.run( one_day_btc_usdt_data, config, @@ -160,23 +178,17 @@ async def _iterations_update(ctx): ) +async def _reload_backtest_data(backtesting_data): + """Recreate importers after a run; OctoBot closes DB handles when the run ends.""" + await backtesting_data.initialize() + backtesting_data.preloaded_candle_managers = {} + + async def _check_report(res): description = res.describe() assert str(res.strategy_config) in description - report = "report.html" - import os - import octobot_script.resources as resources - dist_index = resources.get_report_resource_path("dist/index.html") - if not os.path.exists(dist_index): - return - await generate_and_show_report(res) - with open(report) as rep: - report_content = rep.read() - for key, val in res.strategy_config.items(): - assert str(key) in report_content - assert str(val) in report_content - assert "BTC/USDT" in report_content - assert "1d" in report_content - assert "Binance" in report_content - os.remove(report) + assert os.path.isfile(dist_index) + report_result = await generate_and_show_report(res) + assert os.path.isfile(report_result.report_file) + shutil.rmtree(os.path.dirname(report_result.report_file))