Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 9 additions & 3 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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

Expand All @@ -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
Expand Down
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
8 changes: 2 additions & 6 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -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 \

Check warning on line 6 in Dockerfile

View workflow job for this annotation

GitHub Actions / ubuntu-latest - Docker - lint

[hadolint] reported by reviewdog 🐶 Delete the apt-get lists after installing something Raw Output: message:"Delete the apt-get lists after installing something" location:{path:"Dockerfile" range:{start:{line:6 column:1}}} severity:INFO source:{name:"hadolint" url:"https://github.com/hadolint/hadolint"} code:{value:"DL3009" url:"https://github.com/hadolint/hadolint/wiki/DL3009"}
&& apt-get install -y --no-install-recommends build-essential git gcc binutils

COPY . .
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion octobot_script/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -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():
Expand Down
2 changes: 1 addition & 1 deletion octobot_script/internal/logging_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down
4 changes: 2 additions & 2 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -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
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -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',
],
)
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,15 @@
# You should have received a copy of the GNU General Public
# License along with OctoBot-Script. If not, see <https://www.gnu.org/licenses/>.

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

Expand All @@ -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:
Expand Down Expand Up @@ -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,
Expand All @@ -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,
Expand Down Expand Up @@ -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,
Expand All @@ -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))
Loading