quantcore-lite 0.1.0__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.
- quantcore_lite-0.1.0/LICENSE +21 -0
- quantcore_lite-0.1.0/PKG-INFO +172 -0
- quantcore_lite-0.1.0/README.md +137 -0
- quantcore_lite-0.1.0/pyproject.toml +60 -0
- quantcore_lite-0.1.0/setup.cfg +4 -0
- quantcore_lite-0.1.0/src/quantcore/__init__.py +15 -0
- quantcore_lite-0.1.0/src/quantcore/cli.py +208 -0
- quantcore_lite-0.1.0/src/quantcore/engine.py +142 -0
- quantcore_lite-0.1.0/src/quantcore/metrics.py +75 -0
- quantcore_lite-0.1.0/src/quantcore/pro/__init__.py +6 -0
- quantcore_lite-0.1.0/src/quantcore/pro/license.py +67 -0
- quantcore_lite-0.1.0/src/quantcore/pro/monte_carlo.py +67 -0
- quantcore_lite-0.1.0/src/quantcore/pro/optimizer.py +66 -0
- quantcore_lite-0.1.0/src/quantcore/pro/strategies.py +270 -0
- quantcore_lite-0.1.0/src/quantcore/pro/tearsheet.py +131 -0
- quantcore_lite-0.1.0/src/quantcore/strategies/__init__.py +18 -0
- quantcore_lite-0.1.0/src/quantcore/strategies/base.py +33 -0
- quantcore_lite-0.1.0/src/quantcore/strategies/mean_reversion.py +38 -0
- quantcore_lite-0.1.0/src/quantcore/strategies/momentum.py +32 -0
- quantcore_lite-0.1.0/src/quantcore/strategies/moving_average.py +37 -0
- quantcore_lite-0.1.0/src/quantcore_lite.egg-info/PKG-INFO +172 -0
- quantcore_lite-0.1.0/src/quantcore_lite.egg-info/SOURCES.txt +24 -0
- quantcore_lite-0.1.0/src/quantcore_lite.egg-info/dependency_links.txt +1 -0
- quantcore_lite-0.1.0/src/quantcore_lite.egg-info/entry_points.txt +2 -0
- quantcore_lite-0.1.0/src/quantcore_lite.egg-info/requires.txt +9 -0
- quantcore_lite-0.1.0/src/quantcore_lite.egg-info/top_level.txt +1 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 QuantCore Team
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: quantcore-lite
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Open-core backtesting framework for quantitative trading strategies
|
|
5
|
+
Author: QuantCore Team
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/Septal083/quantcore
|
|
8
|
+
Project-URL: Repository, https://github.com/Septal083/quantcore
|
|
9
|
+
Project-URL: Issues, https://github.com/Septal083/quantcore/issues
|
|
10
|
+
Project-URL: Changelog, https://github.com/Septal083/quantcore/blob/main/CHANGELOG.md
|
|
11
|
+
Keywords: backtesting,trading,quantitative-finance,strategies
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Intended Audience :: Financial and Insurance Industry
|
|
14
|
+
Classifier: Intended Audience :: Science/Research
|
|
15
|
+
Classifier: Operating System :: OS Independent
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
21
|
+
Classifier: Topic :: Office/Business :: Financial :: Investment
|
|
22
|
+
Classifier: Topic :: Scientific/Engineering :: Information Analysis
|
|
23
|
+
Requires-Python: >=3.9
|
|
24
|
+
Description-Content-Type: text/markdown
|
|
25
|
+
License-File: LICENSE
|
|
26
|
+
Requires-Dist: pandas>=1.5.0
|
|
27
|
+
Requires-Dist: numpy>=1.23.0
|
|
28
|
+
Requires-Dist: matplotlib>=3.6.0
|
|
29
|
+
Requires-Dist: reportlab>=4.0.0
|
|
30
|
+
Provides-Extra: dev
|
|
31
|
+
Requires-Dist: pytest>=7.0; extra == "dev"
|
|
32
|
+
Requires-Dist: pytest-cov>=4.0; extra == "dev"
|
|
33
|
+
Requires-Dist: ruff>=0.1.0; extra == "dev"
|
|
34
|
+
Dynamic: license-file
|
|
35
|
+
|
|
36
|
+
[](https://pypi.org/project/quantcore-lite/)
|
|
37
|
+
[](https://github.com/Septal083/quantcore/stargazers)
|
|
38
|
+
[](https://opensource.org/licenses/MIT)
|
|
39
|
+
|
|
40
|
+
# QuantCore
|
|
41
|
+
|
|
42
|
+
**Open-core backtesting framework for quantitative trading strategies.**
|
|
43
|
+
|
|
44
|
+
QuantCore lets you backtest trading strategies against historical OHLCV data with a clean Python API and CLI. The free tier includes three battle-tested strategies and essential performance metrics. Upgrade to Pro for advanced strategies, Monte Carlo simulation, tearsheet PDF reports, and parameter optimization.
|
|
45
|
+
|
|
46
|
+
## Installation
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
pip install quantcore-lite
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## Quick Start
|
|
53
|
+
|
|
54
|
+
### Python API
|
|
55
|
+
|
|
56
|
+
```python
|
|
57
|
+
import pandas as pd
|
|
58
|
+
from quantcore import Backtest, MomentumStrategy
|
|
59
|
+
|
|
60
|
+
# Load your OHLCV data
|
|
61
|
+
data = pd.read_csv("market_data.csv", index_col=0, parse_dates=True)
|
|
62
|
+
|
|
63
|
+
# Run a backtest with the Momentum strategy
|
|
64
|
+
bt = Backtest(data, MomentumStrategy(lookback=20))
|
|
65
|
+
bt.run()
|
|
66
|
+
|
|
67
|
+
print(bt.summary())
|
|
68
|
+
bt.export_csv("results.csv")
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### CLI
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
quantcore backtest --data market_data.csv --strategy momentum
|
|
75
|
+
quantcore backtest --data market_data.csv --strategy mean_reversion --output results.csv
|
|
76
|
+
quantcore strategies
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## Strategies
|
|
80
|
+
|
|
81
|
+
### Momentum
|
|
82
|
+
|
|
83
|
+
Buy when the rate of change over a lookback period is positive, sell when negative.
|
|
84
|
+
|
|
85
|
+
```python
|
|
86
|
+
from quantcore import Backtest, MomentumStrategy
|
|
87
|
+
|
|
88
|
+
strategy = MomentumStrategy(lookback=20)
|
|
89
|
+
bt = Backtest(data, strategy)
|
|
90
|
+
bt.run()
|
|
91
|
+
print(bt.summary())
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### Mean Reversion
|
|
95
|
+
|
|
96
|
+
Buy when price falls below its rolling mean by a threshold, sell when it reverts above.
|
|
97
|
+
|
|
98
|
+
```python
|
|
99
|
+
from quantcore import Backtest, MeanReversion
|
|
100
|
+
|
|
101
|
+
strategy = MeanReversion(window=20, threshold=1.5)
|
|
102
|
+
bt = Backtest(data, strategy)
|
|
103
|
+
bt.run()
|
|
104
|
+
print(bt.summary())
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### Moving Average Crossover
|
|
108
|
+
|
|
109
|
+
Buy on golden cross (short MA crosses above long MA), sell on death cross.
|
|
110
|
+
|
|
111
|
+
```python
|
|
112
|
+
from quantcore import Backtest, MovingAverageCrossover
|
|
113
|
+
|
|
114
|
+
strategy = MovingAverageCrossover(short_window=20, long_window=50)
|
|
115
|
+
bt = Backtest(data, strategy)
|
|
116
|
+
bt.run()
|
|
117
|
+
print(bt.summary())
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
## Performance Metrics
|
|
121
|
+
|
|
122
|
+
Every backtest reports:
|
|
123
|
+
|
|
124
|
+
| Metric | Description |
|
|
125
|
+
|--------|-------------|
|
|
126
|
+
| **Sharpe Ratio** | Risk-adjusted return (annualized) |
|
|
127
|
+
| **Max Drawdown** | Largest peak-to-trough decline |
|
|
128
|
+
| **CAGR** | Compound annual growth rate |
|
|
129
|
+
| **Win Rate** | Percentage of profitable trades |
|
|
130
|
+
| **Total Return** | Overall portfolio return |
|
|
131
|
+
|
|
132
|
+
## Free vs Pro Comparison
|
|
133
|
+
|
|
134
|
+
| Feature | Free | Pro |
|
|
135
|
+
|---------|:----:|:---:|
|
|
136
|
+
| Momentum strategy | ✅ | ✅ |
|
|
137
|
+
| Mean Reversion strategy | ✅ | ✅ |
|
|
138
|
+
| Moving Average Crossover strategy | ✅ | ✅ |
|
|
139
|
+
| Performance metrics (Sharpe, CAGR, drawdown, win rate) | ✅ | ✅ |
|
|
140
|
+
| CSV export | ✅ | ✅ |
|
|
141
|
+
| CLI interface | ✅ | ✅ |
|
|
142
|
+
| RSI, Bollinger Bands, MACD strategies | ❌ | ✅ |
|
|
143
|
+
| Pairs Trading, Volatility Breakout, Turtle Trading | ❌ | ✅ |
|
|
144
|
+
| Mean Reversion Z-Score, Kalman Filter, Dual Momentum, Sector Rotation | ❌ | ✅ |
|
|
145
|
+
| Monte Carlo simulation (1000 runs, confidence intervals) | ❌ | ✅ |
|
|
146
|
+
| Tearsheet PDF generator | ❌ | ✅ |
|
|
147
|
+
| Parameter grid search optimizer | ❌ | ✅ |
|
|
148
|
+
|
|
149
|
+
## ⭐ Pro Version
|
|
150
|
+
|
|
151
|
+
Unlock 10 additional strategies, Monte Carlo simulation, tearsheet PDF reports, and parameter optimization.
|
|
152
|
+
|
|
153
|
+
**[Get QuantCore Pro →](https://buy.polar.sh/polar_cl_rA97pLblKd1pRhwXezgssGgCp1NaKlDV0CeG74fP4q4)**
|
|
154
|
+
|
|
155
|
+
Set your license key:
|
|
156
|
+
|
|
157
|
+
```bash
|
|
158
|
+
export QUANTCORE_LICENSE_KEY="your-license-key"
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
Then use Pro features:
|
|
162
|
+
|
|
163
|
+
```bash
|
|
164
|
+
quantcore backtest --data market_data.csv --strategy rsi --tearsheet report.pdf --monte-carlo
|
|
165
|
+
quantcore optimize --data market_data.csv --strategy bollinger_bands
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
Pro features are validated via [Polar.sh](https://polar.sh) license keys.
|
|
169
|
+
|
|
170
|
+
## License
|
|
171
|
+
|
|
172
|
+
MIT — see [LICENSE](LICENSE) for details.
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
[](https://pypi.org/project/quantcore-lite/)
|
|
2
|
+
[](https://github.com/Septal083/quantcore/stargazers)
|
|
3
|
+
[](https://opensource.org/licenses/MIT)
|
|
4
|
+
|
|
5
|
+
# QuantCore
|
|
6
|
+
|
|
7
|
+
**Open-core backtesting framework for quantitative trading strategies.**
|
|
8
|
+
|
|
9
|
+
QuantCore lets you backtest trading strategies against historical OHLCV data with a clean Python API and CLI. The free tier includes three battle-tested strategies and essential performance metrics. Upgrade to Pro for advanced strategies, Monte Carlo simulation, tearsheet PDF reports, and parameter optimization.
|
|
10
|
+
|
|
11
|
+
## Installation
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
pip install quantcore-lite
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Quick Start
|
|
18
|
+
|
|
19
|
+
### Python API
|
|
20
|
+
|
|
21
|
+
```python
|
|
22
|
+
import pandas as pd
|
|
23
|
+
from quantcore import Backtest, MomentumStrategy
|
|
24
|
+
|
|
25
|
+
# Load your OHLCV data
|
|
26
|
+
data = pd.read_csv("market_data.csv", index_col=0, parse_dates=True)
|
|
27
|
+
|
|
28
|
+
# Run a backtest with the Momentum strategy
|
|
29
|
+
bt = Backtest(data, MomentumStrategy(lookback=20))
|
|
30
|
+
bt.run()
|
|
31
|
+
|
|
32
|
+
print(bt.summary())
|
|
33
|
+
bt.export_csv("results.csv")
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
### CLI
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
quantcore backtest --data market_data.csv --strategy momentum
|
|
40
|
+
quantcore backtest --data market_data.csv --strategy mean_reversion --output results.csv
|
|
41
|
+
quantcore strategies
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## Strategies
|
|
45
|
+
|
|
46
|
+
### Momentum
|
|
47
|
+
|
|
48
|
+
Buy when the rate of change over a lookback period is positive, sell when negative.
|
|
49
|
+
|
|
50
|
+
```python
|
|
51
|
+
from quantcore import Backtest, MomentumStrategy
|
|
52
|
+
|
|
53
|
+
strategy = MomentumStrategy(lookback=20)
|
|
54
|
+
bt = Backtest(data, strategy)
|
|
55
|
+
bt.run()
|
|
56
|
+
print(bt.summary())
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### Mean Reversion
|
|
60
|
+
|
|
61
|
+
Buy when price falls below its rolling mean by a threshold, sell when it reverts above.
|
|
62
|
+
|
|
63
|
+
```python
|
|
64
|
+
from quantcore import Backtest, MeanReversion
|
|
65
|
+
|
|
66
|
+
strategy = MeanReversion(window=20, threshold=1.5)
|
|
67
|
+
bt = Backtest(data, strategy)
|
|
68
|
+
bt.run()
|
|
69
|
+
print(bt.summary())
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### Moving Average Crossover
|
|
73
|
+
|
|
74
|
+
Buy on golden cross (short MA crosses above long MA), sell on death cross.
|
|
75
|
+
|
|
76
|
+
```python
|
|
77
|
+
from quantcore import Backtest, MovingAverageCrossover
|
|
78
|
+
|
|
79
|
+
strategy = MovingAverageCrossover(short_window=20, long_window=50)
|
|
80
|
+
bt = Backtest(data, strategy)
|
|
81
|
+
bt.run()
|
|
82
|
+
print(bt.summary())
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## Performance Metrics
|
|
86
|
+
|
|
87
|
+
Every backtest reports:
|
|
88
|
+
|
|
89
|
+
| Metric | Description |
|
|
90
|
+
|--------|-------------|
|
|
91
|
+
| **Sharpe Ratio** | Risk-adjusted return (annualized) |
|
|
92
|
+
| **Max Drawdown** | Largest peak-to-trough decline |
|
|
93
|
+
| **CAGR** | Compound annual growth rate |
|
|
94
|
+
| **Win Rate** | Percentage of profitable trades |
|
|
95
|
+
| **Total Return** | Overall portfolio return |
|
|
96
|
+
|
|
97
|
+
## Free vs Pro Comparison
|
|
98
|
+
|
|
99
|
+
| Feature | Free | Pro |
|
|
100
|
+
|---------|:----:|:---:|
|
|
101
|
+
| Momentum strategy | ✅ | ✅ |
|
|
102
|
+
| Mean Reversion strategy | ✅ | ✅ |
|
|
103
|
+
| Moving Average Crossover strategy | ✅ | ✅ |
|
|
104
|
+
| Performance metrics (Sharpe, CAGR, drawdown, win rate) | ✅ | ✅ |
|
|
105
|
+
| CSV export | ✅ | ✅ |
|
|
106
|
+
| CLI interface | ✅ | ✅ |
|
|
107
|
+
| RSI, Bollinger Bands, MACD strategies | ❌ | ✅ |
|
|
108
|
+
| Pairs Trading, Volatility Breakout, Turtle Trading | ❌ | ✅ |
|
|
109
|
+
| Mean Reversion Z-Score, Kalman Filter, Dual Momentum, Sector Rotation | ❌ | ✅ |
|
|
110
|
+
| Monte Carlo simulation (1000 runs, confidence intervals) | ❌ | ✅ |
|
|
111
|
+
| Tearsheet PDF generator | ❌ | ✅ |
|
|
112
|
+
| Parameter grid search optimizer | ❌ | ✅ |
|
|
113
|
+
|
|
114
|
+
## ⭐ Pro Version
|
|
115
|
+
|
|
116
|
+
Unlock 10 additional strategies, Monte Carlo simulation, tearsheet PDF reports, and parameter optimization.
|
|
117
|
+
|
|
118
|
+
**[Get QuantCore Pro →](https://buy.polar.sh/polar_cl_rA97pLblKd1pRhwXezgssGgCp1NaKlDV0CeG74fP4q4)**
|
|
119
|
+
|
|
120
|
+
Set your license key:
|
|
121
|
+
|
|
122
|
+
```bash
|
|
123
|
+
export QUANTCORE_LICENSE_KEY="your-license-key"
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
Then use Pro features:
|
|
127
|
+
|
|
128
|
+
```bash
|
|
129
|
+
quantcore backtest --data market_data.csv --strategy rsi --tearsheet report.pdf --monte-carlo
|
|
130
|
+
quantcore optimize --data market_data.csv --strategy bollinger_bands
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
Pro features are validated via [Polar.sh](https://polar.sh) license keys.
|
|
134
|
+
|
|
135
|
+
## License
|
|
136
|
+
|
|
137
|
+
MIT — see [LICENSE](LICENSE) for details.
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=68.0", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "quantcore-lite"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Open-core backtesting framework for quantitative trading strategies"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = "MIT"
|
|
11
|
+
requires-python = ">=3.9"
|
|
12
|
+
authors = [
|
|
13
|
+
{name = "QuantCore Team"},
|
|
14
|
+
]
|
|
15
|
+
keywords = ["backtesting", "trading", "quantitative-finance", "strategies"]
|
|
16
|
+
classifiers = [
|
|
17
|
+
"Development Status :: 4 - Beta",
|
|
18
|
+
"Intended Audience :: Financial and Insurance Industry",
|
|
19
|
+
"Intended Audience :: Science/Research",
|
|
20
|
+
"Operating System :: OS Independent",
|
|
21
|
+
"Programming Language :: Python :: 3",
|
|
22
|
+
"Programming Language :: Python :: 3.9",
|
|
23
|
+
"Programming Language :: Python :: 3.10",
|
|
24
|
+
"Programming Language :: Python :: 3.11",
|
|
25
|
+
"Programming Language :: Python :: 3.12",
|
|
26
|
+
"Topic :: Office/Business :: Financial :: Investment",
|
|
27
|
+
"Topic :: Scientific/Engineering :: Information Analysis",
|
|
28
|
+
]
|
|
29
|
+
dependencies = [
|
|
30
|
+
"pandas>=1.5.0",
|
|
31
|
+
"numpy>=1.23.0",
|
|
32
|
+
"matplotlib>=3.6.0",
|
|
33
|
+
"reportlab>=4.0.0",
|
|
34
|
+
]
|
|
35
|
+
|
|
36
|
+
[project.optional-dependencies]
|
|
37
|
+
dev = [
|
|
38
|
+
"pytest>=7.0",
|
|
39
|
+
"pytest-cov>=4.0",
|
|
40
|
+
"ruff>=0.1.0",
|
|
41
|
+
]
|
|
42
|
+
|
|
43
|
+
[project.urls]
|
|
44
|
+
Homepage = "https://github.com/Septal083/quantcore"
|
|
45
|
+
Repository = "https://github.com/Septal083/quantcore"
|
|
46
|
+
Issues = "https://github.com/Septal083/quantcore/issues"
|
|
47
|
+
Changelog = "https://github.com/Septal083/quantcore/blob/main/CHANGELOG.md"
|
|
48
|
+
|
|
49
|
+
[project.scripts]
|
|
50
|
+
quantcore = "quantcore.cli:main"
|
|
51
|
+
|
|
52
|
+
[tool.setuptools.packages.find]
|
|
53
|
+
where = ["src"]
|
|
54
|
+
|
|
55
|
+
[tool.ruff]
|
|
56
|
+
line-length = 100
|
|
57
|
+
target-version = "py39"
|
|
58
|
+
|
|
59
|
+
[tool.ruff.lint]
|
|
60
|
+
select = ["E", "F", "I", "W"]
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"""QuantCore — open-core backtesting framework for quantitative trading strategies."""
|
|
2
|
+
|
|
3
|
+
__version__ = "0.1.0"
|
|
4
|
+
|
|
5
|
+
from quantcore.engine import Backtest
|
|
6
|
+
from quantcore.metrics import compute_metrics
|
|
7
|
+
from quantcore.strategies import MeanReversion, MomentumStrategy, MovingAverageCrossover
|
|
8
|
+
|
|
9
|
+
__all__ = [
|
|
10
|
+
"Backtest",
|
|
11
|
+
"compute_metrics",
|
|
12
|
+
"MomentumStrategy",
|
|
13
|
+
"MeanReversion",
|
|
14
|
+
"MovingAverageCrossover",
|
|
15
|
+
]
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
"""Command-line interface for QuantCore."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import argparse
|
|
6
|
+
import sys
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
|
|
9
|
+
import pandas as pd
|
|
10
|
+
|
|
11
|
+
from quantcore.engine import Backtest
|
|
12
|
+
from quantcore.strategies import FREE_STRATEGIES
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def _get_all_strategies() -> dict:
|
|
16
|
+
"""Return combined dict of free + pro strategies (pro only if licensed)."""
|
|
17
|
+
all_strats = dict(FREE_STRATEGIES)
|
|
18
|
+
try:
|
|
19
|
+
from quantcore.pro.license import validate_license
|
|
20
|
+
|
|
21
|
+
if validate_license():
|
|
22
|
+
from quantcore.pro.strategies import PRO_STRATEGIES
|
|
23
|
+
|
|
24
|
+
all_strats.update(PRO_STRATEGIES)
|
|
25
|
+
except Exception:
|
|
26
|
+
pass
|
|
27
|
+
return all_strats
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def cmd_backtest(args: argparse.Namespace) -> None:
|
|
31
|
+
"""Run a backtest from the CLI."""
|
|
32
|
+
data_path = Path(args.data)
|
|
33
|
+
if not data_path.exists():
|
|
34
|
+
print(f"Error: Data file not found: {data_path}")
|
|
35
|
+
sys.exit(1)
|
|
36
|
+
|
|
37
|
+
data = pd.read_csv(data_path, parse_dates=True, index_col=0)
|
|
38
|
+
|
|
39
|
+
all_strategies = _get_all_strategies()
|
|
40
|
+
strategy_key = args.strategy.lower().replace("-", "_").replace(" ", "_")
|
|
41
|
+
|
|
42
|
+
if strategy_key not in all_strategies:
|
|
43
|
+
# Check if it's a pro strategy that requires license
|
|
44
|
+
from quantcore.pro.strategies import PRO_STRATEGIES
|
|
45
|
+
|
|
46
|
+
if strategy_key in PRO_STRATEGIES:
|
|
47
|
+
from quantcore.pro.license import require_pro
|
|
48
|
+
|
|
49
|
+
if not require_pro():
|
|
50
|
+
sys.exit(0)
|
|
51
|
+
all_strategies.update(PRO_STRATEGIES)
|
|
52
|
+
else:
|
|
53
|
+
available = ", ".join(sorted(all_strategies.keys()))
|
|
54
|
+
print(f"Error: Unknown strategy '{args.strategy}'. Available: {available}")
|
|
55
|
+
sys.exit(1)
|
|
56
|
+
|
|
57
|
+
strategy_cls = all_strategies[strategy_key]
|
|
58
|
+
strategy = strategy_cls()
|
|
59
|
+
|
|
60
|
+
bt = Backtest(
|
|
61
|
+
data,
|
|
62
|
+
strategy,
|
|
63
|
+
initial_capital=args.capital,
|
|
64
|
+
commission=args.commission,
|
|
65
|
+
)
|
|
66
|
+
bt.run()
|
|
67
|
+
|
|
68
|
+
print(bt.summary())
|
|
69
|
+
print()
|
|
70
|
+
|
|
71
|
+
if args.output:
|
|
72
|
+
out_path = bt.export_csv(args.output)
|
|
73
|
+
print(f"Results exported to: {out_path}")
|
|
74
|
+
|
|
75
|
+
if args.tearsheet:
|
|
76
|
+
from quantcore.pro.license import require_pro
|
|
77
|
+
|
|
78
|
+
if require_pro():
|
|
79
|
+
from quantcore.pro.monte_carlo import monte_carlo_simulation
|
|
80
|
+
from quantcore.pro.tearsheet import generate_tearsheet
|
|
81
|
+
|
|
82
|
+
mc = monte_carlo_simulation(bt.results, initial_capital=args.capital)
|
|
83
|
+
pdf_path = generate_tearsheet(
|
|
84
|
+
bt.results, bt.metrics, mc, strategy.name, args.tearsheet
|
|
85
|
+
)
|
|
86
|
+
print(f"Tearsheet saved to: {pdf_path}")
|
|
87
|
+
|
|
88
|
+
if args.monte_carlo:
|
|
89
|
+
from quantcore.pro.license import require_pro
|
|
90
|
+
|
|
91
|
+
if require_pro():
|
|
92
|
+
from quantcore.pro.monte_carlo import monte_carlo_simulation
|
|
93
|
+
|
|
94
|
+
mc = monte_carlo_simulation(
|
|
95
|
+
bt.results, n_simulations=args.mc_runs, initial_capital=args.capital
|
|
96
|
+
)
|
|
97
|
+
ci = mc["confidence_intervals"]
|
|
98
|
+
print(f"\nMonte Carlo ({mc['n_simulations']} simulations):")
|
|
99
|
+
print(f" Median final value: ${mc['median_final']:,.2f}")
|
|
100
|
+
print(f" Mean final value: ${mc['mean_final']:,.2f}")
|
|
101
|
+
for pct, val in ci.items():
|
|
102
|
+
print(f" {pct} percentile: ${val:,.2f}")
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
def cmd_strategies(args: argparse.Namespace) -> None:
|
|
106
|
+
"""List available strategies."""
|
|
107
|
+
print("Free strategies:")
|
|
108
|
+
for name in sorted(FREE_STRATEGIES.keys()):
|
|
109
|
+
print(f" - {name}")
|
|
110
|
+
|
|
111
|
+
print("\nPro strategies (requires license):")
|
|
112
|
+
from quantcore.pro.strategies import PRO_STRATEGIES
|
|
113
|
+
|
|
114
|
+
for name in sorted(PRO_STRATEGIES.keys()):
|
|
115
|
+
print(f" - {name}")
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
def cmd_optimize(args: argparse.Namespace) -> None:
|
|
119
|
+
"""Run parameter grid search optimization."""
|
|
120
|
+
from quantcore.pro.license import require_pro
|
|
121
|
+
|
|
122
|
+
if not require_pro():
|
|
123
|
+
sys.exit(0)
|
|
124
|
+
|
|
125
|
+
from quantcore.pro.optimizer import grid_search
|
|
126
|
+
|
|
127
|
+
data = pd.read_csv(args.data, parse_dates=True, index_col=0)
|
|
128
|
+
|
|
129
|
+
all_strategies = dict(FREE_STRATEGIES)
|
|
130
|
+
from quantcore.pro.strategies import PRO_STRATEGIES
|
|
131
|
+
|
|
132
|
+
all_strategies.update(PRO_STRATEGIES)
|
|
133
|
+
|
|
134
|
+
strategy_key = args.strategy.lower().replace("-", "_").replace(" ", "_")
|
|
135
|
+
if strategy_key not in all_strategies:
|
|
136
|
+
print(f"Error: Unknown strategy '{args.strategy}'")
|
|
137
|
+
sys.exit(1)
|
|
138
|
+
|
|
139
|
+
# Default param grids per strategy
|
|
140
|
+
default_grids = {
|
|
141
|
+
"momentum": {"lookback": [10, 20, 30, 50]},
|
|
142
|
+
"mean_reversion": {"window": [10, 20, 30], "threshold": [1.0, 1.5, 2.0]},
|
|
143
|
+
"moving_average": {"short_window": [10, 20], "long_window": [30, 50, 100]},
|
|
144
|
+
"rsi": {"period": [7, 14, 21], "oversold": [20, 30], "overbought": [70, 80]},
|
|
145
|
+
"bollinger_bands": {"window": [10, 20, 30], "num_std": [1.5, 2.0, 2.5]},
|
|
146
|
+
"macd": {"fast": [8, 12], "slow": [21, 26], "signal": [7, 9]},
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
param_grid = default_grids.get(strategy_key, {"lookback": [10, 20, 30]})
|
|
150
|
+
results = grid_search(data, all_strategies[strategy_key], param_grid, metric=args.metric)
|
|
151
|
+
|
|
152
|
+
print(f"\nGrid search results for {strategy_key} (optimizing {args.metric}):\n")
|
|
153
|
+
for i, r in enumerate(results[:10]):
|
|
154
|
+
print(f" #{i + 1}: {r['params']} -> {args.metric}={r['score']:.4f}")
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
def build_parser() -> argparse.ArgumentParser:
|
|
158
|
+
"""Build the CLI argument parser."""
|
|
159
|
+
parser = argparse.ArgumentParser(
|
|
160
|
+
prog="quantcore",
|
|
161
|
+
description="QuantCore — backtesting framework for quantitative trading strategies",
|
|
162
|
+
)
|
|
163
|
+
subparsers = parser.add_subparsers(dest="command", help="Available commands")
|
|
164
|
+
|
|
165
|
+
# backtest
|
|
166
|
+
bt_parser = subparsers.add_parser("backtest", help="Run a backtest")
|
|
167
|
+
bt_parser.add_argument("--data", "-d", required=True, help="Path to OHLCV CSV file")
|
|
168
|
+
bt_parser.add_argument(
|
|
169
|
+
"--strategy", "-s", required=True, help="Strategy name (e.g. momentum, mean_reversion)"
|
|
170
|
+
)
|
|
171
|
+
bt_parser.add_argument("--capital", "-c", type=float, default=100_000, help="Initial capital")
|
|
172
|
+
bt_parser.add_argument("--commission", type=float, default=0.001, help="Commission rate")
|
|
173
|
+
bt_parser.add_argument("--output", "-o", help="Output CSV path for results")
|
|
174
|
+
bt_parser.add_argument("--tearsheet", help="Output PDF path for tearsheet (Pro)")
|
|
175
|
+
bt_parser.add_argument("--monte-carlo", action="store_true", help="Run Monte Carlo sim (Pro)")
|
|
176
|
+
bt_parser.add_argument("--mc-runs", type=int, default=1000, help="Number of MC simulations")
|
|
177
|
+
|
|
178
|
+
# strategies
|
|
179
|
+
subparsers.add_parser("strategies", help="List available strategies")
|
|
180
|
+
|
|
181
|
+
# optimize
|
|
182
|
+
opt_parser = subparsers.add_parser("optimize", help="Grid search optimization (Pro)")
|
|
183
|
+
opt_parser.add_argument("--data", "-d", required=True, help="Path to OHLCV CSV file")
|
|
184
|
+
opt_parser.add_argument("--strategy", "-s", required=True, help="Strategy to optimize")
|
|
185
|
+
opt_parser.add_argument("--metric", "-m", default="sharpe_ratio", help="Metric to optimize")
|
|
186
|
+
|
|
187
|
+
return parser
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
def main(argv: list[str] | None = None) -> None:
|
|
191
|
+
"""Entry point for the quantcore CLI."""
|
|
192
|
+
parser = build_parser()
|
|
193
|
+
args = parser.parse_args(argv)
|
|
194
|
+
|
|
195
|
+
if args.command is None:
|
|
196
|
+
parser.print_help()
|
|
197
|
+
sys.exit(0)
|
|
198
|
+
|
|
199
|
+
commands = {
|
|
200
|
+
"backtest": cmd_backtest,
|
|
201
|
+
"strategies": cmd_strategies,
|
|
202
|
+
"optimize": cmd_optimize,
|
|
203
|
+
}
|
|
204
|
+
commands[args.command](args)
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
if __name__ == "__main__":
|
|
208
|
+
main()
|