Remove error argument in backoff_decorator

Fix backoff_decorator logic to reset number of retries correctly
This commit is contained in:
Ichinga Samuel
2025-07-06 10:22:57 +01:00
parent 8e0a551677
commit 91590496ef
5 changed files with 158 additions and 111 deletions
+8 -1
View File
@@ -1,5 +1,12 @@
# Changelog
## [4.0.14](https://github.com/Ichinga-Samuel/aiomql/releases/tag/v4.0.13) - 2025-03-24
### Added
- Add visualization for `Candles` object.
- Update `Config` class
## [4.0.13](https://github.com/Ichinga-Samuel/aiomql/releases/tag/v4.0.13) - 2025-03-24
### Fixed
@@ -65,5 +72,5 @@
- `add` method for adding dataframes or series objects to the Candles object.
### Fixed
-
- Candles timeframe attribute returns the correct TimeFrame object.
+5 -5
View File
@@ -144,9 +144,9 @@ Use this to run a single strategy on multiple symbols with the same parameters a
<a id='bot.process_pool'></a>
```python
@classmethod
def process_pool(cls, bots: dict[Callable: dict] = None, num_workers: int = None):
def process_pool(cls, processes: dict[Callable: dict] = None, num_workers: int = None):
```
Run multiple functions (scripts, bots) at the same time in parallel with different accounts.
Run multiple processes (scripts, bots) at the same time in parallel with different accounts.
Running multiple functions is useful when you want to run different strategies on different accounts.
The callable can for example be a bot instance that defines its own Config instance within the function scope.
The dictionary should contain the callable as the key and the dictionary of keyword arguments to pass to the callable as
@@ -155,7 +155,7 @@ The num_workers parameter specifies the number of workers to use. If not specifi
number of bots.
#### Parameters
| Name | Type | Description |
|--------------|------------------------|---------------------------------------------------------------------------------|
| `bots` | `dict[Callable: dict]` | A dictionary of callables and their keyword arguments to run as bots |
| Name | Type | Description |
|---------------|------------------------|---------------------------------------------------------------------------------|
| `processes` | `dict[Callable: dict]` | A dictionary of callables and their keyword arguments to run as processes |
| `num_workers` | `int` | The number of workers to use. If not specified, the number of bots will be used |
+1 -1
View File
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
[project]
name = "aiomql"
version = "4.0.13"
version = "4.0.14"
readme = "README.md"
requires-python = ">=3.11"
classifiers = [
+128 -86
View File
@@ -1,118 +1,160 @@
-e git+ssh://git@github.com/VChijioke/aiomql.git@626658d68ac771353b424d50a33e7dd0de6a9054#egg=aiomql
anyio==4.9.0
argon2-cffi==25.1.0
-e git+ssh://git@github.com/Chimezirim-Bassey/aiomql.git@8e0a5516774894505d8d915bbd510bf88c6e3e48#egg=aiomql
anyio==4.3.0
argon2-cffi==23.1.0
argon2-cffi-bindings==21.2.0
arrow==1.3.0
asttokens==3.0.0
async-lru==2.0.5
attrs==25.3.0
babel==2.17.0
beautifulsoup4==4.13.4
bleach==6.2.0
certifi==2025.4.26
cffi==1.17.1
charset-normalizer==3.4.2
asttokens==2.4.1
async-lru==2.0.4
attrs==23.2.0
Babel==2.14.0
beautifulsoup4==4.12.3
black==23.9.1
bleach==6.1.0
build==1.2.2.post1
certifi==2023.7.22
cffi==1.16.0
charset-normalizer==3.3.0
click==8.1.7
colorama==0.4.6
comm==0.2.2
contourpy==1.3.2
contourpy==1.2.1
cycler==0.12.1
debugpy==1.8.14
decorator==5.2.1
databind.core==4.4.1
databind.json==4.4.1
debugpy==1.8.1
decorator==5.1.1
defusedxml==0.7.1
executing==2.2.0
fastjsonschema==2.21.1
fonttools==4.58.2
Deprecated==1.2.14
docspec==2.2.1
docspec-python==2.2.1
docstring-parser==0.11
docutils==0.20.1
docutils-stubs==0.0.22
executing==2.0.1
fastjsonschema==2.19.1
fonttools==4.51.0
fqdn==1.5.1
h11==0.16.0
httpcore==1.0.9
httpx==0.28.1
idna==3.10
iniconfig==2.1.0
ipykernel==6.29.5
ipython==9.3.0
ipython_pygments_lexers==1.1.1
ipywidgets==8.1.7
h11==0.14.0
httpcore==1.0.5
httpx==0.27.0
id==1.5.0
idna==3.4
importlib-metadata==6.8.0
iniconfig==2.0.0
ipykernel==6.29.4
ipython==8.23.0
ipywidgets==8.1.2
isoduration==20.11.0
jedi==0.19.2
Jinja2==3.1.6
json5==0.12.0
jsonpointer==3.0.0
jsonschema==4.24.0
jsonschema-specifications==2025.4.1
jupyter==1.1.1
jaraco.classes==3.3.0
jedi==0.19.1
Jinja2==3.1.2
json5==0.9.24
jsonpointer==2.4
jsonschema==4.21.1
jsonschema-specifications==2023.12.1
jupyter==1.0.0
jupyter-console==6.6.3
jupyter-events==0.12.0
jupyter-events==0.10.0
jupyter-lsp==2.2.5
jupyter_client==8.6.3
jupyter_core==5.8.1
jupyter_server==2.16.0
jupyter_client==8.6.1
jupyter_core==5.7.2
jupyter_server==2.13.0
jupyter_server_terminals==0.5.3
jupyterlab==4.4.3
jupyterlab==4.1.6
jupyterlab_pygments==0.3.0
jupyterlab_server==2.27.3
jupyterlab_widgets==3.0.15
kiwisolver==1.4.8
MarkupSafe==3.0.2
matplotlib==3.10.3
matplotlib-inline==0.1.7
MetaTrader5==5.0.5050
mistune==3.1.3
jupyterlab_server==2.26.0
jupyterlab_widgets==3.0.10
keyring==24.2.0
kiwisolver==1.4.5
markdown-it-py==3.0.0
MarkupSafe==2.1.3
matplotlib==3.8.4
matplotlib-inline==0.1.6
mdurl==0.1.2
MetaTrader5==5.0.4424
mistune==3.0.2
more-itertools==10.1.0
mplfinance==0.12.10b0
nbclient==0.10.2
nbconvert==7.16.6
mypy-extensions==1.0.0
nbclient==0.10.0
nbconvert==7.16.3
nbformat==5.10.4
nest-asyncio==1.6.0
notebook==7.4.3
nh3==0.2.14
notebook==7.1.2
notebook_shim==0.2.4
nr-date==2.1.0
nr-stream==1.1.5
nr.util==0.8.12
numpy==1.26.0
overrides==7.7.0
packaging==25.0
pandas==2.3.0
pandas_ta==0.3.14b0
pandas==2.1.1
pandas-ta==0.3.14b0
pandocfilters==1.5.1
parso==0.8.4
pillow==11.2.1
platformdirs==4.3.8
pluggy==1.6.0
prometheus_client==0.22.1
prompt_toolkit==3.0.51
psutil==7.0.0
pure_eval==0.2.3
pathspec==0.11.2
pillow==10.3.0
pkginfo==1.9.6
platformdirs==3.11.0
pluggy==1.5.0
prometheus_client==0.20.0
prompt-toolkit==3.0.43
psutil==5.9.8
pure-eval==0.2.2
pycparser==2.22
Pygments==2.19.1
pyparsing==3.2.3
pytest==8.4.1
pytest-asyncio==1.0.0
pydoc-markdown==4.8.2
Pygments==2.16.1
pyparsing==3.1.2
pyproject_hooks==1.0.0
pytest==8.3.3
pytest-asyncio==0.24.0
pytest-order==1.3.0
python-dateutil==2.9.0.post0
python-json-logger==3.3.0
pytz==2025.2
pywin32==310
pywinpty==2.0.15
PyYAML==6.0.2
pyzmq==26.4.0
referencing==0.36.2
requests==2.32.3
python-dateutil==2.8.2
python-json-logger==2.0.7
python-telegram-bot==21.0.1
pytz==2023.3.post1
pywin32==306
pywin32-ctypes==0.2.2
pywinpty==2.0.13
PyYAML==6.0.1
pyzmq==25.1.2
qtconsole==5.5.1
QtPy==2.4.1
readme-renderer==42.0
referencing==0.34.0
requests==2.31.0
requests-toolbelt==1.0.0
rfc3339-validator==0.1.4
rfc3986==2.0.0
rfc3986-validator==0.1.1
rpds-py==0.25.1
rich==13.6.0
rpds-py==0.18.0
ruff==0.7.3
Send2Trash==1.8.3
setuptools==80.9.0
six==1.17.0
six==1.16.0
sniffio==1.3.1
soupsieve==2.7
soupsieve==2.5
stack-data==0.6.3
terminado==0.18.1
tinycss2==1.4.0
tornado==6.5.1
traitlets==5.14.3
types-python-dateutil==2.9.0.20250516
typing_extensions==4.14.0
tzdata==2025.2
tinycss2==1.2.1
tomli==2.0.1
tomli_w==1.0.0
tornado==6.4
traitlets==5.14.2
twine==6.1.0
typeapi==2.1.1
types-python-dateutil==2.9.0.20240316
typing_extensions==4.6.3
tzdata==2023.3
uri-template==1.3.0
urllib3==2.4.0
urllib3==2.0.6
watchdog==3.0.0
wcwidth==0.2.13
webcolors==24.11.1
webcolors==1.13
webencodings==0.5.1
websocket-client==1.8.0
widgetsnbextension==4.0.14
websocket-client==1.7.0
widgetsnbextension==4.0.10
wrapt==1.15.0
yapf==0.40.2
zipp==3.17.0
+16 -18
View File
@@ -53,37 +53,35 @@ def dict_to_string(data: dict, multi=False) -> str:
return f"{sep}".join(f"{key}: {value}" for key, value in data.items())
def backoff_decorator(func=None, *, max_retries: int = 2, retries: int = 0, error="") -> callable:
def backoff_decorator(func=None, *, max_retries: int = 3, retries: int = 0) -> callable:
"""A decorator to retry a function a number of times before giving up.
Args:
func (callable, optional): The function to decorate. Defaults to None.
max_retries (int, optional): The maximum number of retries. Defaults to 2.
retries (int, optional): The number of retries. Defaults to 0.
error (Any, optional): The error to raise when the maximum number of retries is reached. Defaults to "".
max_retries (int, optional): The maximum number of retries. The default is 3.
retries (int, optional): The number of retries. The default is 0
"""
if func is None:
return partial(backoff_decorator, max_retries=max_retries, retries=retries, error=error)
return partial(backoff_decorator, max_retries=max_retries, retries=retries)
@wraps(func)
async def wrapper(*args, **kwargs):
nonlocal retries
if max_retries == retries:
retries = 0
await func(*args, **kwargs)
try:
retries += 1
res = await func(*args, **kwargs)
if error != "" and res == error:
raise TypeError("Invalid return type")
else:
retries = 0
return res
retries = 0
return res
except Exception as err:
logger.error("Error in %s: %s", func.__name__, err)
if max_retries == retries:
retries = 0
logger.error("An Error %s: occurred in %s", err, func.__name__)
raise err
retries += 1
if Config().mode != "backtest":
await asyncio.sleep(2**retries + random.uniform(0, max_retries))
await wrapper(*args, **kwargs)
delay = 2 ** retries + random.uniform(0, 1)
logger.warning("An Error %s: occurred in %s, trying again in %f seconds",
err, func.__name__, delay)
await asyncio.sleep(delay)
return await wrapper(*args, **kwargs)
return wrapper