roboquant 2.2.0__tar.gz → 2.3.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {roboquant-2.2.0 → roboquant-2.3.1}/PKG-INFO +17 -17
- {roboquant-2.2.0 → roboquant-2.3.1}/pyproject.toml +7 -7
- {roboquant-2.2.0 → roboquant-2.3.1}/roboquant/__init__.py +0 -7
- roboquant-2.2.0/.github/workflows/verify.yml +0 -46
- roboquant-2.2.0/.gitignore +0 -15
- roboquant-2.2.0/.vscode/settings.json +0 -39
- roboquant-2.2.0/.zed/settings.json +0 -21
- roboquant-2.2.0/.zed/tasks.json +0 -30
- roboquant-2.2.0/bin/local_install.sh +0 -19
- roboquant-2.2.0/bin/publish.sh +0 -24
- roboquant-2.2.0/bin/verify.sh +0 -13
- roboquant-2.2.0/docs/DESIGN.md +0 -85
- roboquant-2.2.0/docs/roboquant_header.png +0 -0
- roboquant-2.2.0/tests/__init__.py +0 -0
- roboquant-2.2.0/tests/common.py +0 -84
- roboquant-2.2.0/tests/data/stooq/5_min/ibm.us.txt +0 -2731
- roboquant-2.2.0/tests/data/stooq/daily/ibm.us.txt +0 -15626
- roboquant-2.2.0/tests/data/yahoo/AAPL.csv +0 -1219
- roboquant-2.2.0/tests/data/yahoo/AMZN.csv +0 -527
- roboquant-2.2.0/tests/data/yahoo/META.csv +0 -535
- roboquant-2.2.0/tests/data/yahoo/TSLA.csv +0 -6
- roboquant-2.2.0/tests/integration/__init__.py +0 -0
- roboquant-2.2.0/tests/integration/test_alpaca.py +0 -89
- roboquant-2.2.0/tests/integration/test_ccxt.py +0 -31
- roboquant-2.2.0/tests/integration/test_ibkr.py +0 -112
- roboquant-2.2.0/tests/integration/test_yahoo.py +0 -33
- roboquant-2.2.0/tests/performance/__init__.py +0 -0
- roboquant-2.2.0/tests/performance/test_bigfeed.py +0 -60
- roboquant-2.2.0/tests/performance/test_delay.py +0 -73
- roboquant-2.2.0/tests/performance/test_profiling.py +0 -43
- roboquant-2.2.0/tests/samples/__init__.py +0 -0
- roboquant-2.2.0/tests/samples/alpaca_forwardtest_bars.py +0 -30
- roboquant-2.2.0/tests/samples/alpaca_forwardtest_trades.py +0 -33
- roboquant-2.2.0/tests/samples/alpaca_live_feed.py +0 -25
- roboquant-2.2.0/tests/samples/alpaca_papertrade.py +0 -38
- roboquant-2.2.0/tests/samples/alpaca_record.py +0 -48
- roboquant-2.2.0/tests/samples/charts.py +0 -61
- roboquant-2.2.0/tests/samples/chronos_prediction.py +0 -87
- roboquant-2.2.0/tests/samples/crypto_backtest.py +0 -29
- roboquant-2.2.0/tests/samples/extra_logging.py +0 -18
- roboquant-2.2.0/tests/samples/ibkr_close_positions.py +0 -29
- roboquant-2.2.0/tests/samples/monetary.py +0 -53
- roboquant-2.2.0/tests/samples/pandas_dataframe.py +0 -21
- roboquant-2.2.0/tests/samples/parquet_csv.py +0 -24
- roboquant-2.2.0/tests/samples/parquet_csv_large.py +0 -17
- roboquant-2.2.0/tests/samples/parquet_yahoo.py +0 -11
- roboquant-2.2.0/tests/samples/sb3_strategy.py +0 -39
- roboquant-2.2.0/tests/samples/sb3_strategy_quotes.py +0 -45
- roboquant-2.2.0/tests/samples/talib_feature.py +0 -28
- roboquant-2.2.0/tests/samples/talib_strategy.py +0 -42
- roboquant-2.2.0/tests/samples/tensorboard_metrics.py +0 -21
- roboquant-2.2.0/tests/samples/torch_lstm.py +0 -73
- roboquant-2.2.0/tests/samples/torch_transformer.py +0 -105
- roboquant-2.2.0/tests/samples/yahoo_backtest.py +0 -17
- roboquant-2.2.0/tests/samples/yahoo_walkforward.py +0 -16
- roboquant-2.2.0/tests/samples/yahoo_walkforward_multiprocess.py +0 -50
- roboquant-2.2.0/tests/unit/__init__.py +0 -0
- roboquant-2.2.0/tests/unit/test_account.py +0 -42
- roboquant-2.2.0/tests/unit/test_asset.py +0 -74
- roboquant-2.2.0/tests/unit/test_buffer.py +0 -31
- roboquant-2.2.0/tests/unit/test_csvfeed.py +0 -43
- roboquant-2.2.0/tests/unit/test_features.py +0 -91
- roboquant-2.2.0/tests/unit/test_feedutil.py +0 -23
- roboquant-2.2.0/tests/unit/test_journal.py +0 -32
- roboquant-2.2.0/tests/unit/test_monetary.py +0 -92
- roboquant-2.2.0/tests/unit/test_order.py +0 -49
- roboquant-2.2.0/tests/unit/test_parquetfeed.py +0 -42
- roboquant-2.2.0/tests/unit/test_randomwalk.py +0 -23
- roboquant-2.2.0/tests/unit/test_rnn.py +0 -76
- roboquant-2.2.0/tests/unit/test_run.py +0 -37
- roboquant-2.2.0/tests/unit/test_signal.py +0 -30
- roboquant-2.2.0/tests/unit/test_simbroker.py +0 -69
- roboquant-2.2.0/tests/unit/test_sqlfeed.py +0 -31
- roboquant-2.2.0/tests/unit/test_strategy.py +0 -33
- roboquant-2.2.0/tests/unit/test_tastrategy.py +0 -30
- roboquant-2.2.0/tests/unit/test_tensorboard.py +0 -27
- roboquant-2.2.0/tests/unit/test_timeframe.py +0 -62
- roboquant-2.2.0/uv.lock +0 -3114
- {roboquant-2.2.0 → roboquant-2.3.1}/LICENSE +0 -0
- {roboquant-2.2.0 → roboquant-2.3.1}/README.md +0 -0
- {roboquant-2.2.0 → roboquant-2.3.1}/roboquant/account.py +0 -0
- {roboquant-2.2.0 → roboquant-2.3.1}/roboquant/ai/__init__.py +0 -0
- {roboquant-2.2.0 → roboquant-2.3.1}/roboquant/ai/features.py +0 -0
- {roboquant-2.2.0 → roboquant-2.3.1}/roboquant/ai/rl.py +0 -0
- {roboquant-2.2.0 → roboquant-2.3.1}/roboquant/ai/strategies.py +0 -0
- {roboquant-2.2.0 → roboquant-2.3.1}/roboquant/alpaca/__init__.py +0 -0
- {roboquant-2.2.0 → roboquant-2.3.1}/roboquant/alpaca/broker.py +0 -0
- {roboquant-2.2.0 → roboquant-2.3.1}/roboquant/alpaca/feed.py +0 -0
- {roboquant-2.2.0 → roboquant-2.3.1}/roboquant/asset.py +0 -0
- {roboquant-2.2.0 → roboquant-2.3.1}/roboquant/brokers/__init__.py +0 -0
- {roboquant-2.2.0 → roboquant-2.3.1}/roboquant/brokers/broker.py +0 -0
- {roboquant-2.2.0 → roboquant-2.3.1}/roboquant/brokers/simbroker.py +0 -0
- {roboquant-2.2.0 → roboquant-2.3.1}/roboquant/crypto/__init__.py +0 -0
- {roboquant-2.2.0 → roboquant-2.3.1}/roboquant/crypto/cryptobroker.py +0 -0
- {roboquant-2.2.0 → roboquant-2.3.1}/roboquant/crypto/cryptofeed.py +0 -0
- {roboquant-2.2.0 → roboquant-2.3.1}/roboquant/event.py +0 -0
- {roboquant-2.2.0 → roboquant-2.3.1}/roboquant/feeds/__init__.py +0 -0
- {roboquant-2.2.0 → roboquant-2.3.1}/roboquant/feeds/csvfeed.py +0 -0
- {roboquant-2.2.0 → roboquant-2.3.1}/roboquant/feeds/feed.py +0 -0
- {roboquant-2.2.0 → roboquant-2.3.1}/roboquant/feeds/historic.py +0 -0
- {roboquant-2.2.0 → roboquant-2.3.1}/roboquant/feeds/live.py +0 -0
- {roboquant-2.2.0 → roboquant-2.3.1}/roboquant/feeds/parquet.py +0 -0
- {roboquant-2.2.0 → roboquant-2.3.1}/roboquant/feeds/randomwalk.py +0 -0
- {roboquant-2.2.0 → roboquant-2.3.1}/roboquant/feeds/resources/us10.parquet +0 -0
- {roboquant-2.2.0 → roboquant-2.3.1}/roboquant/feeds/sql.py +0 -0
- {roboquant-2.2.0 → roboquant-2.3.1}/roboquant/feeds/util.py +0 -0
- {roboquant-2.2.0 → roboquant-2.3.1}/roboquant/feeds/yahoo.py +0 -0
- {roboquant-2.2.0 → roboquant-2.3.1}/roboquant/ibkr/__init__.py +0 -0
- {roboquant-2.2.0 → roboquant-2.3.1}/roboquant/ibkr/broker.py +0 -0
- {roboquant-2.2.0 → roboquant-2.3.1}/roboquant/ibkr/types.py +0 -0
- {roboquant-2.2.0 → roboquant-2.3.1}/roboquant/journals/__init__.py +0 -0
- {roboquant-2.2.0 → roboquant-2.3.1}/roboquant/journals/alphabeta.py +0 -0
- {roboquant-2.2.0 → roboquant-2.3.1}/roboquant/journals/basicjournal.py +0 -0
- {roboquant-2.2.0 → roboquant-2.3.1}/roboquant/journals/feedmetric.py +0 -0
- {roboquant-2.2.0 → roboquant-2.3.1}/roboquant/journals/journal.py +0 -0
- {roboquant-2.2.0 → roboquant-2.3.1}/roboquant/journals/marketmetric.py +0 -0
- {roboquant-2.2.0 → roboquant-2.3.1}/roboquant/journals/metric.py +0 -0
- {roboquant-2.2.0 → roboquant-2.3.1}/roboquant/journals/metricsjournal.py +0 -0
- {roboquant-2.2.0 → roboquant-2.3.1}/roboquant/journals/pnlmetric.py +0 -0
- {roboquant-2.2.0 → roboquant-2.3.1}/roboquant/journals/pricemetric.py +0 -0
- {roboquant-2.2.0 → roboquant-2.3.1}/roboquant/journals/runmetric.py +0 -0
- {roboquant-2.2.0 → roboquant-2.3.1}/roboquant/journals/scorecard.py +0 -0
- {roboquant-2.2.0 → roboquant-2.3.1}/roboquant/journals/tensorboard.py +0 -0
- {roboquant-2.2.0 → roboquant-2.3.1}/roboquant/monetary.py +0 -0
- {roboquant-2.2.0 → roboquant-2.3.1}/roboquant/order.py +0 -0
- {roboquant-2.2.0 → roboquant-2.3.1}/roboquant/run.py +0 -0
- {roboquant-2.2.0 → roboquant-2.3.1}/roboquant/signal.py +0 -0
- {roboquant-2.2.0 → roboquant-2.3.1}/roboquant/strategies/__init__.py +0 -0
- {roboquant-2.2.0 → roboquant-2.3.1}/roboquant/strategies/buffer.py +0 -0
- {roboquant-2.2.0 → roboquant-2.3.1}/roboquant/strategies/cachedstrategy.py +0 -0
- {roboquant-2.2.0 → roboquant-2.3.1}/roboquant/strategies/emacrossover.py +0 -0
- {roboquant-2.2.0 → roboquant-2.3.1}/roboquant/strategies/ibsstrategy.py +0 -0
- {roboquant-2.2.0 → roboquant-2.3.1}/roboquant/strategies/multistrategy.py +0 -0
- {roboquant-2.2.0 → roboquant-2.3.1}/roboquant/strategies/strategy.py +0 -0
- {roboquant-2.2.0 → roboquant-2.3.1}/roboquant/strategies/tastrategy.py +0 -0
- {roboquant-2.2.0 → roboquant-2.3.1}/roboquant/ta/__init__.py +0 -0
- {roboquant-2.2.0 → roboquant-2.3.1}/roboquant/timeframe.py +0 -0
- {roboquant-2.2.0 → roboquant-2.3.1}/roboquant/traders/__init__.py +0 -0
- {roboquant-2.2.0 → roboquant-2.3.1}/roboquant/traders/flextrader.py +0 -0
- {roboquant-2.2.0 → roboquant-2.3.1}/roboquant/traders/trader.py +0 -0
|
@@ -1,43 +1,43 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: roboquant
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.3.1
|
|
4
4
|
Summary: A fast algorithmic trading platform with support for AI based strategies
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
Project-URL: Issues, https://github.com/neurallayer/roboquant.py/issues
|
|
5
|
+
Keywords: algorithmic,trading,machine learning,AI,investment,finance,crypto,stocks,exchange,forex
|
|
6
|
+
Author: roboquant team
|
|
8
7
|
Author-email: roboquant team <info@roboquant.org>
|
|
9
8
|
License-Expression: Apache-2.0
|
|
10
9
|
License-File: LICENSE
|
|
11
|
-
Keywords: AI,algorithmic,crypto,exchange,finance,forex,investment,machine learning,stocks,trading
|
|
12
10
|
Classifier: Development Status :: 4 - Beta
|
|
13
11
|
Classifier: Intended Audience :: Developers
|
|
14
|
-
Classifier: License :: OSI Approved :: Apache Software License
|
|
15
|
-
Classifier: Operating System :: OS Independent
|
|
16
12
|
Classifier: Programming Language :: Python
|
|
17
13
|
Classifier: Programming Language :: Python :: 3
|
|
18
14
|
Classifier: Programming Language :: Python :: 3 :: Only
|
|
19
15
|
Classifier: Programming Language :: Python :: 3.12
|
|
20
16
|
Classifier: Programming Language :: Python :: 3.13
|
|
21
17
|
Classifier: Programming Language :: Python :: 3.14
|
|
18
|
+
Classifier: Operating System :: OS Independent
|
|
22
19
|
Classifier: Topic :: Office/Business :: Financial
|
|
23
20
|
Classifier: Topic :: Office/Business :: Financial :: Investment
|
|
24
|
-
Requires-Python: <3.15,>=3.12
|
|
25
21
|
Requires-Dist: numpy>2.0.0
|
|
26
|
-
Requires-Dist: pyarrow>24.0.0
|
|
27
22
|
Requires-Dist: requests>2.30.0
|
|
28
|
-
Requires-Dist: ta-lib==0.6.5
|
|
29
23
|
Requires-Dist: yfinance>1.5.0
|
|
24
|
+
Requires-Dist: pyarrow>24.0.0
|
|
25
|
+
Requires-Dist: ta-lib==0.6.5
|
|
26
|
+
Requires-Dist: torch>=2.9.0 ; extra == 'ai'
|
|
27
|
+
Requires-Dist: tensorboard>=2.21.0 ; extra == 'ai'
|
|
28
|
+
Requires-Dist: stable-baselines3>=2.9.0 ; extra == 'ai'
|
|
29
|
+
Requires-Dist: sb3-contrib>=2.9.0 ; extra == 'ai'
|
|
30
|
+
Requires-Dist: alpaca-py>=0.43.5 ; extra == 'alpaca'
|
|
31
|
+
Requires-Dist: ccxt>=4.5.65 ; extra == 'crypto'
|
|
32
|
+
Requires-Dist: ibind[oauth]>=0.1.22 ; extra == 'ibkr'
|
|
33
|
+
Requires-Python: >=3.12, <3.15
|
|
34
|
+
Project-URL: Homepage, https://roboquant.org
|
|
35
|
+
Project-URL: Repository, https://github.com/neurallayer/roboquant.py.git
|
|
36
|
+
Project-URL: Issues, https://github.com/neurallayer/roboquant.py/issues
|
|
30
37
|
Provides-Extra: ai
|
|
31
|
-
Requires-Dist: sb3-contrib>=2.9.0; extra == 'ai'
|
|
32
|
-
Requires-Dist: stable-baselines3>=2.9.0; extra == 'ai'
|
|
33
|
-
Requires-Dist: tensorboard>=2.21.0; extra == 'ai'
|
|
34
|
-
Requires-Dist: torch>=2.9.0; extra == 'ai'
|
|
35
38
|
Provides-Extra: alpaca
|
|
36
|
-
Requires-Dist: alpaca-py>=0.43.5; extra == 'alpaca'
|
|
37
39
|
Provides-Extra: crypto
|
|
38
|
-
Requires-Dist: ccxt>=4.5.65; extra == 'crypto'
|
|
39
40
|
Provides-Extra: ibkr
|
|
40
|
-
Requires-Dist: ibind[oauth]>=0.1.22; extra == 'ibkr'
|
|
41
41
|
Description-Content-Type: text/markdown
|
|
42
42
|
|
|
43
43
|
|
|
@@ -2,11 +2,8 @@
|
|
|
2
2
|
line-length = 127
|
|
3
3
|
|
|
4
4
|
[build-system]
|
|
5
|
-
requires = ["
|
|
6
|
-
build-backend = "
|
|
7
|
-
|
|
8
|
-
[tool.hatch.version]
|
|
9
|
-
path = "roboquant/__init__.py"
|
|
5
|
+
requires = ["uv_build>=0.11.28,<0.12"]
|
|
6
|
+
build-backend = "uv_build"
|
|
10
7
|
|
|
11
8
|
[tool.ruff.lint]
|
|
12
9
|
select = ["E", "F", "W"]
|
|
@@ -16,9 +13,13 @@ typeCheckingMode = "standard"
|
|
|
16
13
|
reportPrivateImportUsage = "none"
|
|
17
14
|
# typeCheckingMode = "strict"
|
|
18
15
|
|
|
16
|
+
[tool.uv.build-backend]
|
|
17
|
+
module-root = ""
|
|
18
|
+
module-name = "roboquant"
|
|
19
|
+
|
|
19
20
|
[project]
|
|
20
21
|
name = "roboquant"
|
|
21
|
-
|
|
22
|
+
version = "2.3.1"
|
|
22
23
|
authors = [{ name = "roboquant team", email = "info@roboquant.org" }]
|
|
23
24
|
description = "A fast algorithmic trading platform with support for AI based strategies"
|
|
24
25
|
readme = "README.md"
|
|
@@ -34,7 +35,6 @@ classifiers = [
|
|
|
34
35
|
"Programming Language :: Python :: 3.12",
|
|
35
36
|
"Programming Language :: Python :: 3.13",
|
|
36
37
|
"Programming Language :: Python :: 3.14",
|
|
37
|
-
"License :: OSI Approved :: Apache Software License",
|
|
38
38
|
"Operating System :: OS Independent",
|
|
39
39
|
"Topic :: Office/Business :: Financial",
|
|
40
40
|
"Topic :: Office/Business :: Financial :: Investment",
|
|
@@ -3,10 +3,6 @@ The `roboquant` package contains the `run` method and a number of shared classes
|
|
|
3
3
|
like `Account`, `Asset` and `Event`.
|
|
4
4
|
"""
|
|
5
5
|
|
|
6
|
-
__version__ = "2.2.0"
|
|
7
|
-
|
|
8
|
-
import logging
|
|
9
|
-
|
|
10
6
|
from roboquant import brokers
|
|
11
7
|
from roboquant import feeds
|
|
12
8
|
from roboquant import journals
|
|
@@ -22,9 +18,6 @@ from .asset import Asset, Stock, Crypto, Forex, Option
|
|
|
22
18
|
from .run import run
|
|
23
19
|
from .timeframe import Timeframe, utcnow
|
|
24
20
|
|
|
25
|
-
logger = logging.getLogger(__name__)
|
|
26
|
-
logger.info("roboquant version=%s", __version__)
|
|
27
|
-
|
|
28
21
|
__all__ = [
|
|
29
22
|
"brokers",
|
|
30
23
|
"feeds",
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
# This workflow will install Python dependencies, run tests and lint with a variety of Python versions
|
|
2
|
-
|
|
3
|
-
name: Verify roboquant
|
|
4
|
-
|
|
5
|
-
on:
|
|
6
|
-
push:
|
|
7
|
-
branches: [ "main" ]
|
|
8
|
-
pull_request:
|
|
9
|
-
branches: [ "main" ]
|
|
10
|
-
|
|
11
|
-
env:
|
|
12
|
-
PYRIGHT_PYTHON_FORCE_VERSION: latest
|
|
13
|
-
|
|
14
|
-
jobs:
|
|
15
|
-
verify:
|
|
16
|
-
|
|
17
|
-
runs-on: ${{ matrix.os }}
|
|
18
|
-
strategy:
|
|
19
|
-
fail-fast: false
|
|
20
|
-
matrix:
|
|
21
|
-
os: [ubuntu-24.04, windows-latest, macos-latest]
|
|
22
|
-
python-version: ["3.12", "3.13"]
|
|
23
|
-
|
|
24
|
-
steps:
|
|
25
|
-
- name: Checkout
|
|
26
|
-
uses: actions/checkout@v7
|
|
27
|
-
|
|
28
|
-
- name: Install uv
|
|
29
|
-
uses: astral-sh/setup-uv@v7
|
|
30
|
-
with:
|
|
31
|
-
ignore-nothing-to-cache: true
|
|
32
|
-
python-version: ${{ matrix.python-version }}
|
|
33
|
-
|
|
34
|
-
- name: Install the project
|
|
35
|
-
run: uv sync --all-extras --no-dev
|
|
36
|
-
|
|
37
|
-
- name: Run ruff checking
|
|
38
|
-
run: uvx ruff check
|
|
39
|
-
|
|
40
|
-
- name: Run pyright
|
|
41
|
-
run: uv run pyright tests roboquant
|
|
42
|
-
|
|
43
|
-
- name: Run unit tests
|
|
44
|
-
run: uv run --no-dev python -m unittest discover -s tests/unit
|
|
45
|
-
|
|
46
|
-
|
roboquant-2.2.0/.gitignore
DELETED
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"cSpell.words": [
|
|
3
|
-
"annualize",
|
|
4
|
-
"dataframe",
|
|
5
|
-
"dtype",
|
|
6
|
-
"hstack",
|
|
7
|
-
"ibkr",
|
|
8
|
-
"ohlcv",
|
|
9
|
-
"optim",
|
|
10
|
-
"pnlmetric",
|
|
11
|
-
"prettytable",
|
|
12
|
-
"roboquant",
|
|
13
|
-
"stooq",
|
|
14
|
-
"Tensorboard",
|
|
15
|
-
"Tiingo",
|
|
16
|
-
"timeframes"
|
|
17
|
-
],
|
|
18
|
-
"python.testing.unittestArgs": [
|
|
19
|
-
"-v",
|
|
20
|
-
"-p",
|
|
21
|
-
"test_*.py"
|
|
22
|
-
],
|
|
23
|
-
"__python.testing.unittestArgs": [
|
|
24
|
-
"-v",
|
|
25
|
-
"-s",
|
|
26
|
-
"./tests/unit",
|
|
27
|
-
"-p",
|
|
28
|
-
"test_*.py"
|
|
29
|
-
],
|
|
30
|
-
"__python.testing.pytestArgs": [
|
|
31
|
-
"--ignore=tests/integration",
|
|
32
|
-
"--ignore=tests/performance"
|
|
33
|
-
],
|
|
34
|
-
"python.testing.pytestEnabled": false,
|
|
35
|
-
"python.testing.unittestEnabled": true,
|
|
36
|
-
"[python]": {
|
|
37
|
-
"editor.defaultFormatter": "charliermarsh.ruff"
|
|
38
|
-
}
|
|
39
|
-
}
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"languages": {
|
|
3
|
-
"Python": {
|
|
4
|
-
"language_servers": ["pyright"],
|
|
5
|
-
"tasks": {
|
|
6
|
-
"variables": {
|
|
7
|
-
"TEST_RUNNER": "unittest",
|
|
8
|
-
},
|
|
9
|
-
},
|
|
10
|
-
},
|
|
11
|
-
},
|
|
12
|
-
"lsp": {
|
|
13
|
-
"pyright": {
|
|
14
|
-
"settings": {
|
|
15
|
-
"python": {
|
|
16
|
-
"pythonPath": ".venv/bin/python",
|
|
17
|
-
},
|
|
18
|
-
},
|
|
19
|
-
},
|
|
20
|
-
},
|
|
21
|
-
}
|
roboquant-2.2.0/.zed/tasks.json
DELETED
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
// Project tasks configuration. See https://zed.dev/docs/tasks for documentation.
|
|
2
|
-
//
|
|
3
|
-
// Example:
|
|
4
|
-
[
|
|
5
|
-
{
|
|
6
|
-
"label": "run unit test",
|
|
7
|
-
"command": "uv run python -m unittest discover -s tests/unit",
|
|
8
|
-
"show_command": false,
|
|
9
|
-
},
|
|
10
|
-
{
|
|
11
|
-
"label": "run pyright",
|
|
12
|
-
"command": "uv run pyright tests roboquant",
|
|
13
|
-
"show_command": false,
|
|
14
|
-
},
|
|
15
|
-
{
|
|
16
|
-
"label": "uv sync",
|
|
17
|
-
"command": "uv sync --all-extras --dev",
|
|
18
|
-
"show_command": false,
|
|
19
|
-
},
|
|
20
|
-
{
|
|
21
|
-
"label": "uv ruff",
|
|
22
|
-
"command": "uvx ruff check",
|
|
23
|
-
"show_command": false,
|
|
24
|
-
},
|
|
25
|
-
{
|
|
26
|
-
"label": "run pyright",
|
|
27
|
-
"command": "uv run pyright tests roboquant",
|
|
28
|
-
"show_command": false,
|
|
29
|
-
},
|
|
30
|
-
]
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
[[ ! -f "LICENSE" ]] && echo "run the script from the project root directory like this: ./bin/local_install.sh" && exit 1
|
|
3
|
-
export PYRIGHT_PYTHON_FORCE_VERSION="latest"
|
|
4
|
-
|
|
5
|
-
rm -rf ./runs
|
|
6
|
-
|
|
7
|
-
uv sync --all-extras --dev
|
|
8
|
-
|
|
9
|
-
# QA
|
|
10
|
-
uvx ruff check || exit 1
|
|
11
|
-
uv run python -m unittest discover -s tests/unit || exit 1
|
|
12
|
-
|
|
13
|
-
# Build the package
|
|
14
|
-
rm -rf dist
|
|
15
|
-
uv build || exit 1
|
|
16
|
-
|
|
17
|
-
# Install the just build package
|
|
18
|
-
uv pip install dist/*.whl
|
|
19
|
-
|
roboquant-2.2.0/bin/publish.sh
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
[[ ! -f "LICENSE" ]] && echo "run the script from the project root directory like this: ./bin/publish.sh" && exit 1
|
|
3
|
-
export PYRIGHT_PYTHON_FORCE_VERSION="latest"
|
|
4
|
-
|
|
5
|
-
rm -rf ./runs
|
|
6
|
-
|
|
7
|
-
uv sync --all-extras --dev
|
|
8
|
-
|
|
9
|
-
# QA
|
|
10
|
-
uvx ruff check
|
|
11
|
-
uv run pyright tests roboquant || exit 1
|
|
12
|
-
uv run python -m unittest discover -s tests/unit || exit 1
|
|
13
|
-
|
|
14
|
-
# Build
|
|
15
|
-
rm -rf dist
|
|
16
|
-
uv build || exit 1
|
|
17
|
-
|
|
18
|
-
# Publish
|
|
19
|
-
read -p "Publish (y/n)? " ANSWER
|
|
20
|
-
if [ "$ANSWER" = "y" ]; then
|
|
21
|
-
uv publish; exit 0
|
|
22
|
-
else
|
|
23
|
-
echo "Not published"; exit 1
|
|
24
|
-
fi
|
roboquant-2.2.0/bin/verify.sh
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
[[ ! -f "LICENSE" ]] && echo "run the script from the project root directory like this: ./bin/verify.sh" && exit 1
|
|
2
|
-
export PYRIGHT_PYTHON_FORCE_VERSION="latest"
|
|
3
|
-
|
|
4
|
-
uv sync --all-extras --dev
|
|
5
|
-
|
|
6
|
-
# QA
|
|
7
|
-
echo "Running ruff"
|
|
8
|
-
uvx ruff check || exit 1
|
|
9
|
-
uv run pyright tests roboquant || exit 1
|
|
10
|
-
echo "Running unittest"
|
|
11
|
-
uv run python -m unittest discover -s tests/unit || exit 1
|
|
12
|
-
|
|
13
|
-
echo "All tests passed"
|
roboquant-2.2.0/docs/DESIGN.md
DELETED
|
@@ -1,85 +0,0 @@
|
|
|
1
|
-
# Design Principles
|
|
2
|
-
|
|
3
|
-
## Modular Pipeline Architecture
|
|
4
|
-
|
|
5
|
-
The library is built around a clean separation of five orthogonal concerns:
|
|
6
|
-
|
|
7
|
-
| Component | Responsibility | Has access to Account? |
|
|
8
|
-
|-----------|---------------|----------------------|
|
|
9
|
-
| **Feed** | Provides market data events | No |
|
|
10
|
-
| **Strategy** | Generates trading signals from events | No |
|
|
11
|
-
| **Trader** | Converts signals into orders (risk/sizing) | Yes |
|
|
12
|
-
| **Broker** | Executes orders, maintains account state | Yes (owns Account) |
|
|
13
|
-
| **Journal** | Logs/tracks every step (read-only) | Read-only snapshot |
|
|
14
|
-
|
|
15
|
-
Each component is an abstract base class with pluggable implementations, making every part of the pipeline independently swappable.
|
|
16
|
-
|
|
17
|
-
## The Run Loop
|
|
18
|
-
|
|
19
|
-
The core of the system is the `roboquant.run()` function, which connects all components in a streaming event loop:
|
|
20
|
-
|
|
21
|
-
```
|
|
22
|
-
for each event in feed.play(timeframe):
|
|
23
|
-
1. broker.sync(event) — update account, execute fills
|
|
24
|
-
2. strategy.create_signals(event) — generate signals from market data
|
|
25
|
-
3. trader.create_orders(signals, ...) — apply risk rules, produce orders
|
|
26
|
-
4. broker.place_orders(orders) — submit orders to the broker
|
|
27
|
-
5. journal.track(event, account, ...) — record metrics (optional)
|
|
28
|
-
```
|
|
29
|
-
|
|
30
|
-
### Step-by-step
|
|
31
|
-
|
|
32
|
-
1. **`broker.sync(event)`** — Updates the account with the latest market data. Open orders from previous steps are tested against prices and executed if conditions are met. No look-ahead bias: orders placed at time `t` only execute at time `t+1`.
|
|
33
|
-
|
|
34
|
-
2. **`strategy.create_signals(event)`** — The strategy examines the event's price data and returns a list of `Signal` objects. Each signal has an asset, a rating (typically -1.0 to 1.0), and a type (`ENTRY`, `EXIT`, or `ENTRY_EXIT`). Strategies are **pure decision-makers** — they know nothing about cash, positions, or risk.
|
|
35
|
-
|
|
36
|
-
3. **`trader.create_orders(signals, event, account)`** — The trader applies risk management rules (position sizing, shorting constraints, order limits) and converts signals into concrete `Order` objects. Unlike strategies, traders **have full access to the Account** (cash, positions, buying power).
|
|
37
|
-
|
|
38
|
-
4. **`broker.place_orders(orders)`** — New orders are submitted to the broker. In `SimBroker`, they are stored and evaluated for execution when the next event arrives.
|
|
39
|
-
|
|
40
|
-
5. **`journal.track(...)`** — Optional logging and metrics collection. Journals are passive observers that never modify state.
|
|
41
|
-
|
|
42
|
-
## Minimal Backtest
|
|
43
|
-
|
|
44
|
-
```python
|
|
45
|
-
import roboquant as rq
|
|
46
|
-
|
|
47
|
-
feed = rq.feeds.YahooFeed("JPM", "IBM", start_date="2015-01-01")
|
|
48
|
-
account = rq.run(feed, rq.strategies.EMACrossover())
|
|
49
|
-
print(account)
|
|
50
|
-
```
|
|
51
|
-
|
|
52
|
-
This works because `run()` provides sensible defaults: `SimBroker` (USD 1M deposit, 0% slippage) and `FlexTrader` (conservative position sizing).
|
|
53
|
-
|
|
54
|
-
## Custom Backtest
|
|
55
|
-
|
|
56
|
-
```python
|
|
57
|
-
feed = rq.feeds.YahooFeed("AAPL", "MSFT", start_date="2020-01-01")
|
|
58
|
-
strategy = rq.strategies.EMACrossover()
|
|
59
|
-
trader = rq.traders.FlexTrader(max_order_perc=0.1, shorting=True)
|
|
60
|
-
broker = rq.brokers.SimBroker(deposit=500_000)
|
|
61
|
-
journal = rq.journals.MetricsJournal()
|
|
62
|
-
|
|
63
|
-
account = rq.run(feed, strategy, trader=trader, broker=broker, journal=journal)
|
|
64
|
-
print(account)
|
|
65
|
-
print(journal.metrics())
|
|
66
|
-
```
|
|
67
|
-
|
|
68
|
-
## Strategy/Trader Separation
|
|
69
|
-
|
|
70
|
-
This is the most important design choice in the library:
|
|
71
|
-
|
|
72
|
-
- **Strategies** produce signals from market data only. They implement `create_signals(event) -> list[Signal]` and have no access to account state. This keeps them pure, testable, and reusable across any trader configuration.
|
|
73
|
-
- **Traders** implement `create_orders(signals, event, account) -> list[Order]` and are responsible for risk management, position sizing, and order construction. They know nothing about indicators or market data beyond what is in the signal.
|
|
74
|
-
|
|
75
|
-
Example: The same `EMACrossover` strategy can be used with a conservative trader (2% max order) in backtesting and a different trader (20% max order, shorting enabled) in live trading — without changing a line of strategy code.
|
|
76
|
-
|
|
77
|
-
## Key Principles
|
|
78
|
-
|
|
79
|
-
- **Event-driven streaming** — Everything is built around `Event` objects produced lazily by feeds, supporting both backtesting and live trading with the same pipeline.
|
|
80
|
-
- **Broker owns the Account** — The Account is never modified directly by user code; it is always the broker's canonical view returned by `sync()`.
|
|
81
|
-
- **Default-everywhere** — `roboquant.run(feed, strategy)` works out of the box with sensible defaults, making the simplest case a one-liner.
|
|
82
|
-
- **Immutable core types** — `Asset`, `Signal`, and `Event` are immutable; `Order` uses `cancel()`/`modify()` returning new objects.
|
|
83
|
-
- **Strategy composition** — `MultiStrategy` combines multiple strategies with configurable conflict resolution (`first`, `last`, `mean`, `none`).
|
|
84
|
-
- **Pluggable pricing** — Price type strings (`"OPEN"`, `"CLOSE"`, `"HIGH"`, `"LOW"`, `"DEFAULT"`) allow strategies and traders to choose which price to use for evaluation.
|
|
85
|
-
- **Multi-currency** — Built-in support via `Amount`, `Wallet`, and pluggable `CurrencyConverter` (ECB, static, one-to-one).
|
|
Binary file
|
|
File without changes
|
roboquant-2.2.0/tests/common.py
DELETED
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
import math
|
|
2
|
-
import pathlib
|
|
3
|
-
from datetime import date, datetime, timedelta
|
|
4
|
-
from typing import Iterable
|
|
5
|
-
from unittest import TestCase
|
|
6
|
-
|
|
7
|
-
from roboquant import PriceItem, Bar, Quote, TradePrice, Timeframe
|
|
8
|
-
from roboquant.asset import Asset
|
|
9
|
-
from roboquant.feeds import CSVFeed
|
|
10
|
-
from roboquant.feeds.feed import Feed
|
|
11
|
-
from roboquant.signal import Signal
|
|
12
|
-
from roboquant.strategies.strategy import Strategy
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
def get_feed() -> CSVFeed:
|
|
16
|
-
"""Return a CSV feed based on some stock data in Yahoo format"""
|
|
17
|
-
root = pathlib.Path(__file__).parent.resolve().joinpath("data", "yahoo")
|
|
18
|
-
return CSVFeed.yahoo(str(root))
|
|
19
|
-
|
|
20
|
-
def get_recent_start_date(days: int = 10):
|
|
21
|
-
"""Get a recent (in the past) date"""
|
|
22
|
-
start = date.today() - timedelta(days=days)
|
|
23
|
-
return start.strftime("%Y-%m-%d")
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
def run_price_item_feed(
|
|
27
|
-
feed: Feed, assets: Iterable[Asset], test_case: TestCase, timeframe: Timeframe | None = None, min_items: int = 1
|
|
28
|
-
):
|
|
29
|
-
"""Common test for all feeds that produce price-items. It validates the data and the order of the items"""
|
|
30
|
-
|
|
31
|
-
last = datetime.fromisoformat("1900-01-01T00:00:00+00:00")
|
|
32
|
-
n_items = 0
|
|
33
|
-
for event in feed.play():
|
|
34
|
-
test_case.assertIsInstance(event.time, datetime)
|
|
35
|
-
test_case.assertEqual("UTC", event.time.tzname())
|
|
36
|
-
test_case.assertGreaterEqual(event.time, last, f"{event} < {last}, items={event.items}")
|
|
37
|
-
last = event.time
|
|
38
|
-
|
|
39
|
-
n_items += len(event.items)
|
|
40
|
-
|
|
41
|
-
for item in event.items:
|
|
42
|
-
test_case.assertIsInstance(item, PriceItem)
|
|
43
|
-
test_case.assertIsInstance(item.asset, Asset)
|
|
44
|
-
test_case.assertIn(item.asset, assets)
|
|
45
|
-
|
|
46
|
-
match item:
|
|
47
|
-
case Bar():
|
|
48
|
-
ohlcv = item.ohlcv
|
|
49
|
-
v = ohlcv[4]
|
|
50
|
-
test_case.assertTrue(math.isnan(v) or v >= 0.0)
|
|
51
|
-
for i in range(0, 4):
|
|
52
|
-
test_case.assertGreaterEqual(ohlcv[1], ohlcv[i]) # High >= OHLC
|
|
53
|
-
test_case.assertGreaterEqual(ohlcv[i], ohlcv[2])
|
|
54
|
-
test_case.assertGreaterEqual(ohlcv[i], 0.0)
|
|
55
|
-
case TradePrice():
|
|
56
|
-
test_case.assertTrue(math.isfinite(item.trade_price))
|
|
57
|
-
test_case.assertTrue(math.isfinite(item.trade_volume))
|
|
58
|
-
case Quote():
|
|
59
|
-
for f in item.data:
|
|
60
|
-
test_case.assertTrue(math.isfinite(f))
|
|
61
|
-
test_case.assertGreaterEqual(item.data[0], item.data[2]) # ask >= bid
|
|
62
|
-
case _:
|
|
63
|
-
pass
|
|
64
|
-
|
|
65
|
-
test_case.assertGreaterEqual(n_items, min_items)
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
def run_strategy(strategy: Strategy, test_case: TestCase):
|
|
69
|
-
"""Run and test a strategy on the default feed"""
|
|
70
|
-
feed = get_feed()
|
|
71
|
-
all_assets = feed.assets()
|
|
72
|
-
total_signals = 0
|
|
73
|
-
for event in feed.play():
|
|
74
|
-
signals = strategy.create_signals(event)
|
|
75
|
-
for signal in signals:
|
|
76
|
-
asset = signal.asset
|
|
77
|
-
test_case.assertEqual(type(signal), Signal)
|
|
78
|
-
test_case.assertEqual(asset.symbol, asset.symbol.upper())
|
|
79
|
-
test_case.assertIn(asset, all_assets)
|
|
80
|
-
test_case.assertGreaterEqual(signal.rating, -1)
|
|
81
|
-
test_case.assertLessEqual(signal.rating, 1)
|
|
82
|
-
total_signals += len(signals)
|
|
83
|
-
|
|
84
|
-
test_case.assertGreater(total_signals, 0)
|