propalgos 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.
- propalgos-0.1.0/.gitignore +222 -0
- propalgos-0.1.0/LICENSE +29 -0
- propalgos-0.1.0/PKG-INFO +437 -0
- propalgos-0.1.0/README.md +392 -0
- propalgos-0.1.0/examples/quickstart.py +24 -0
- propalgos-0.1.0/pyproject.toml +73 -0
- propalgos-0.1.0/src/propalgos/__init__.py +70 -0
- propalgos-0.1.0/src/propalgos/_version.py +1 -0
- propalgos-0.1.0/src/propalgos/account/__init__.py +10 -0
- propalgos-0.1.0/src/propalgos/api/__init__.py +11 -0
- propalgos-0.1.0/src/propalgos/auth/__init__.py +11 -0
- propalgos-0.1.0/src/propalgos/backtest/__init__.py +22 -0
- propalgos-0.1.0/src/propalgos/backtest/costs.py +43 -0
- propalgos-0.1.0/src/propalgos/backtest/engine.py +263 -0
- propalgos-0.1.0/src/propalgos/backtest/metrics.py +77 -0
- propalgos-0.1.0/src/propalgos/backtest/results.py +132 -0
- propalgos-0.1.0/src/propalgos/cli/__init__.py +5 -0
- propalgos-0.1.0/src/propalgos/cli/main.py +84 -0
- propalgos-0.1.0/src/propalgos/config.py +59 -0
- propalgos-0.1.0/src/propalgos/data/__init__.py +37 -0
- propalgos-0.1.0/src/propalgos/data/cache.py +145 -0
- propalgos-0.1.0/src/propalgos/data/crypto.py +353 -0
- propalgos-0.1.0/src/propalgos/data/loader.py +166 -0
- propalgos-0.1.0/src/propalgos/data/prices.py +312 -0
- propalgos-0.1.0/src/propalgos/data/registry.py +186 -0
- propalgos-0.1.0/src/propalgos/data/returns.py +134 -0
- propalgos-0.1.0/src/propalgos/data/schemas.py +45 -0
- propalgos-0.1.0/src/propalgos/data/staging.py +42 -0
- propalgos-0.1.0/src/propalgos/env/__init__.py +131 -0
- propalgos-0.1.0/src/propalgos/env/gpu.py +296 -0
- propalgos-0.1.0/src/propalgos/env/runtime.py +83 -0
- propalgos-0.1.0/src/propalgos/exceptions.py +75 -0
- propalgos-0.1.0/src/propalgos/factors/__init__.py +56 -0
- propalgos-0.1.0/src/propalgos/factors/performance.py +155 -0
- propalgos-0.1.0/src/propalgos/factors/risk.py +163 -0
- propalgos-0.1.0/src/propalgos/notebook/__init__.py +10 -0
- propalgos-0.1.0/src/propalgos/py.typed +0 -0
- propalgos-0.1.0/src/propalgos/signals/__init__.py +38 -0
- propalgos-0.1.0/src/propalgos/signals/compose.py +93 -0
- propalgos-0.1.0/src/propalgos/signals/mean_reversion.py +107 -0
- propalgos-0.1.0/src/propalgos/signals/momentum.py +131 -0
- propalgos-0.1.0/src/propalgos/signals/scan.py +139 -0
- propalgos-0.1.0/src/propalgos/signals/trend.py +137 -0
- propalgos-0.1.0/src/propalgos/storage/__init__.py +11 -0
- propalgos-0.1.0/src/propalgos/submit/__init__.py +10 -0
- propalgos-0.1.0/src/propalgos/viz/__init__.py +63 -0
- propalgos-0.1.0/src/propalgos/viz/_compat.py +41 -0
- propalgos-0.1.0/src/propalgos/viz/candles.py +266 -0
- propalgos-0.1.0/src/propalgos/viz/heatmaps.py +216 -0
- propalgos-0.1.0/src/propalgos/viz/strip.py +139 -0
- propalgos-0.1.0/src/propalgos/viz/tearsheet.py +359 -0
- propalgos-0.1.0/src/propalgos/viz/theme.py +186 -0
- propalgos-0.1.0/tests/__init__.py +0 -0
- propalgos-0.1.0/tests/conftest.py +42 -0
- propalgos-0.1.0/tests/test_backtest.py +114 -0
- propalgos-0.1.0/tests/test_data.py +453 -0
- propalgos-0.1.0/tests/test_factors.py +124 -0
- propalgos-0.1.0/tests/test_import.py +134 -0
- propalgos-0.1.0/tests/test_signals.py +265 -0
- propalgos-0.1.0/tests/test_viz.py +284 -0
- propalgos-0.1.0/uv.lock +3097 -0
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
# Environment variables
|
|
2
|
+
.env
|
|
3
|
+
.env.local
|
|
4
|
+
.env.development.local
|
|
5
|
+
.env.test.local
|
|
6
|
+
.env.production.local
|
|
7
|
+
frontend/.env
|
|
8
|
+
backend/.env
|
|
9
|
+
backend/.env.bak
|
|
10
|
+
backend/.env.backup
|
|
11
|
+
backend/.env.vault
|
|
12
|
+
cloud_api_testing/config/.env
|
|
13
|
+
temp/
|
|
14
|
+
temp/*
|
|
15
|
+
|
|
16
|
+
# Cloud credentials
|
|
17
|
+
cloud_creds/
|
|
18
|
+
cloud_creds/*
|
|
19
|
+
|
|
20
|
+
# Vault init keys (NEVER commit)
|
|
21
|
+
.vault-init-keys.json
|
|
22
|
+
|
|
23
|
+
# Dependencies
|
|
24
|
+
node_modules/
|
|
25
|
+
*/node_modules/
|
|
26
|
+
|
|
27
|
+
# Build outputs (frontend only)
|
|
28
|
+
frontend/build/
|
|
29
|
+
frontend/dist/
|
|
30
|
+
|
|
31
|
+
# Runtime data
|
|
32
|
+
pids
|
|
33
|
+
*.pid
|
|
34
|
+
*.seed
|
|
35
|
+
*.pid.lock
|
|
36
|
+
|
|
37
|
+
# Coverage directory used by tools like istanbul
|
|
38
|
+
coverage/
|
|
39
|
+
*.lcov
|
|
40
|
+
|
|
41
|
+
# Python coverage files
|
|
42
|
+
backend/htmlcov/
|
|
43
|
+
backend/.coverage
|
|
44
|
+
backend/coverage.xml
|
|
45
|
+
backend/*.coverage.*
|
|
46
|
+
# Keep the baseline coverage json
|
|
47
|
+
!backend/coverage.json
|
|
48
|
+
!backend/test_coverage_baseline.json
|
|
49
|
+
|
|
50
|
+
# nyc test coverage
|
|
51
|
+
.nyc_output
|
|
52
|
+
|
|
53
|
+
# ESLint cache
|
|
54
|
+
.eslintcache
|
|
55
|
+
|
|
56
|
+
# Optional npm cache directory
|
|
57
|
+
.npm
|
|
58
|
+
|
|
59
|
+
# Optional REPL history
|
|
60
|
+
.node_repl_history
|
|
61
|
+
|
|
62
|
+
# Output of 'npm pack'
|
|
63
|
+
*.tgz
|
|
64
|
+
|
|
65
|
+
# Yarn Integrity file
|
|
66
|
+
.yarn-integrity
|
|
67
|
+
|
|
68
|
+
# parcel-bundler cache (https://parceljs.org/)
|
|
69
|
+
.cache
|
|
70
|
+
.parcel-cache
|
|
71
|
+
|
|
72
|
+
# next.js build output
|
|
73
|
+
.next
|
|
74
|
+
|
|
75
|
+
# nuxt.js build output
|
|
76
|
+
.nuxt
|
|
77
|
+
|
|
78
|
+
# vuepress build output
|
|
79
|
+
.vuepress/dist
|
|
80
|
+
|
|
81
|
+
# Serverless directories
|
|
82
|
+
.serverless
|
|
83
|
+
|
|
84
|
+
# FuseBox cache
|
|
85
|
+
.fusebox/
|
|
86
|
+
|
|
87
|
+
# DynamoDB Local files
|
|
88
|
+
.dynamodb/
|
|
89
|
+
|
|
90
|
+
# TernJS port file
|
|
91
|
+
.tern-port
|
|
92
|
+
|
|
93
|
+
# IDE files
|
|
94
|
+
.vscode/
|
|
95
|
+
.idea/
|
|
96
|
+
*.swp
|
|
97
|
+
*.swo
|
|
98
|
+
*~
|
|
99
|
+
|
|
100
|
+
# OS generated files
|
|
101
|
+
.DS_Store
|
|
102
|
+
.DS_Store?
|
|
103
|
+
._*
|
|
104
|
+
.Spotlight-V100
|
|
105
|
+
.Trashes
|
|
106
|
+
ehthumbs.db
|
|
107
|
+
Thumbs.db
|
|
108
|
+
|
|
109
|
+
# Logs
|
|
110
|
+
logs
|
|
111
|
+
*.log
|
|
112
|
+
npm-debug.log*
|
|
113
|
+
yarn-debug.log*
|
|
114
|
+
yarn-error.log*
|
|
115
|
+
lerna-debug.log*
|
|
116
|
+
|
|
117
|
+
# Python
|
|
118
|
+
__pycache__/
|
|
119
|
+
*.py[cod]
|
|
120
|
+
*$py.class
|
|
121
|
+
*.so
|
|
122
|
+
.Python
|
|
123
|
+
/env/
|
|
124
|
+
venv/
|
|
125
|
+
/ENV/
|
|
126
|
+
env.bak/
|
|
127
|
+
venv.bak/
|
|
128
|
+
backend/waitlist-env/
|
|
129
|
+
backend/*-env/
|
|
130
|
+
|
|
131
|
+
# uv specific
|
|
132
|
+
.venv/
|
|
133
|
+
backend/.venv/
|
|
134
|
+
uv.lock.*
|
|
135
|
+
.uv/
|
|
136
|
+
backend/.uv/
|
|
137
|
+
|
|
138
|
+
# Jupyter Notebook
|
|
139
|
+
.ipynb_checkpoints
|
|
140
|
+
|
|
141
|
+
# pyenv
|
|
142
|
+
.python-version
|
|
143
|
+
|
|
144
|
+
# AWS
|
|
145
|
+
.aws/
|
|
146
|
+
docker/aws/credentials
|
|
147
|
+
docker/aws/credentials.backup
|
|
148
|
+
|
|
149
|
+
# Terraform
|
|
150
|
+
*.tfstate
|
|
151
|
+
*.tfstate.*
|
|
152
|
+
.terraform/
|
|
153
|
+
.terraform.lock.hcl
|
|
154
|
+
|
|
155
|
+
# Docker
|
|
156
|
+
#.dockerignore
|
|
157
|
+
|
|
158
|
+
# Miscellaneous
|
|
159
|
+
archive/
|
|
160
|
+
archive/*
|
|
161
|
+
CURRENT_TODO/
|
|
162
|
+
backend/.env_COPY
|
|
163
|
+
|
|
164
|
+
# Vault credentials (local development only)
|
|
165
|
+
.vault-credentials
|
|
166
|
+
**/.vault-credentials
|
|
167
|
+
vault-backup.json.gpg
|
|
168
|
+
|
|
169
|
+
# Vault backups (contain sensitive data)
|
|
170
|
+
vault-complete-backup*.json
|
|
171
|
+
vault-backup*.json
|
|
172
|
+
*.vault-backup.json
|
|
173
|
+
|
|
174
|
+
# Packer build artifacts (3.8GB on 2025-10-12!)
|
|
175
|
+
backend/packer_build_logs/*.log
|
|
176
|
+
backend/packer_build_logs/*.json
|
|
177
|
+
backend/packer_build_logs/
|
|
178
|
+
infrastructure/packer/templates/manifest.json
|
|
179
|
+
infrastructure/packer/scripts/userdata/
|
|
180
|
+
|
|
181
|
+
# Image scanner reports
|
|
182
|
+
backend/services/image_scanners/
|
|
183
|
+
infrastructure/ssm_documents/
|
|
184
|
+
|
|
185
|
+
# Memory/context files (not committed)
|
|
186
|
+
docs/memory/
|
|
187
|
+
|
|
188
|
+
# Temporary test files
|
|
189
|
+
backend/test_*.py
|
|
190
|
+
!backend/tests/
|
|
191
|
+
infrastructure/test_*.py
|
|
192
|
+
infrastructure/tests/
|
|
193
|
+
backend/tmp*.json
|
|
194
|
+
backend/*.tmp
|
|
195
|
+
|
|
196
|
+
# Cloud API testing cache
|
|
197
|
+
cloud_api_testing/scripts/gcp_gpu_api.py
|
|
198
|
+
docker/aws/cli/cache/
|
|
199
|
+
|
|
200
|
+
# Integration test artifacts
|
|
201
|
+
frontend/*_TESTS.md
|
|
202
|
+
frontend/**/*.integration.md
|
|
203
|
+
|
|
204
|
+
# Backup files
|
|
205
|
+
**/*.bak
|
|
206
|
+
**/*.bak2
|
|
207
|
+
backups/
|
|
208
|
+
|
|
209
|
+
# Test result artifacts
|
|
210
|
+
**/*_test_results.json
|
|
211
|
+
**/*_FINDINGS.md
|
|
212
|
+
backend/test_gpu.db
|
|
213
|
+
backend/test_gpu_performance.db
|
|
214
|
+
|
|
215
|
+
# Azure setup files (planning docs)
|
|
216
|
+
AZURE_SETUP_FILES/
|
|
217
|
+
|
|
218
|
+
# Crypto data cache (bootstrap/refresh artifacts)
|
|
219
|
+
infrastructure/scripts/crypto_cache/
|
|
220
|
+
|
|
221
|
+
# Database dumps
|
|
222
|
+
propalgos_backup.dump
|
propalgos-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
Copyright (c) 2026 PropAlgos, Inc. All rights reserved.
|
|
2
|
+
|
|
3
|
+
PROPRIETARY SOFTWARE LICENSE
|
|
4
|
+
|
|
5
|
+
This software and associated documentation files (the "Software") are the
|
|
6
|
+
proprietary property of PropAlgos, Inc. ("PropAlgos").
|
|
7
|
+
|
|
8
|
+
Permission is hereby granted to any person who has obtained a copy of this
|
|
9
|
+
Software through an authorized distribution channel (PyPI, PropAlgos platform,
|
|
10
|
+
or direct download from PropAlgos) to use the Software for personal and
|
|
11
|
+
commercial purposes, subject to the following conditions:
|
|
12
|
+
|
|
13
|
+
1. You may NOT redistribute, sublicense, sell, or otherwise transfer copies
|
|
14
|
+
of the Software to third parties without prior written permission from
|
|
15
|
+
PropAlgos.
|
|
16
|
+
|
|
17
|
+
2. You may NOT modify, reverse engineer, decompile, or disassemble the
|
|
18
|
+
Software except to the extent that such activity is expressly permitted
|
|
19
|
+
by applicable law.
|
|
20
|
+
|
|
21
|
+
3. You may NOT remove or alter any proprietary notices, labels, or marks
|
|
22
|
+
on the Software.
|
|
23
|
+
|
|
24
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
25
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
26
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
27
|
+
PROPALGOS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
|
28
|
+
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
29
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
propalgos-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,437 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: propalgos
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Quant research SDK for PropAlgos — data, signals, backtesting, and visualization
|
|
5
|
+
Project-URL: Homepage, https://propalgos.ai
|
|
6
|
+
Project-URL: Documentation, https://propalgos.ai/docs
|
|
7
|
+
Author-email: PropAlgos <eng@propalgos.ai>
|
|
8
|
+
License: Proprietary
|
|
9
|
+
License-File: LICENSE
|
|
10
|
+
Classifier: Development Status :: 3 - Alpha
|
|
11
|
+
Classifier: Intended Audience :: Financial and Insurance Industry
|
|
12
|
+
Classifier: Intended Audience :: Science/Research
|
|
13
|
+
Classifier: License :: Other/Proprietary License
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
19
|
+
Classifier: Topic :: Office/Business :: Financial :: Investment
|
|
20
|
+
Classifier: Typing :: Typed
|
|
21
|
+
Requires-Python: >=3.10
|
|
22
|
+
Requires-Dist: httpx>=0.28
|
|
23
|
+
Requires-Dist: numpy>=1.26
|
|
24
|
+
Requires-Dist: pandas>=2.2
|
|
25
|
+
Requires-Dist: pydantic>=2.8
|
|
26
|
+
Requires-Dist: typer[all]>=0.15
|
|
27
|
+
Requires-Dist: yfinance>=0.2.40
|
|
28
|
+
Provides-Extra: dev
|
|
29
|
+
Requires-Dist: build>=1.2; extra == 'dev'
|
|
30
|
+
Requires-Dist: ipywidgets>=8.1; extra == 'dev'
|
|
31
|
+
Requires-Dist: mypy>=1.15; extra == 'dev'
|
|
32
|
+
Requires-Dist: plotly>=6.0; extra == 'dev'
|
|
33
|
+
Requires-Dist: pyarrow>=18.0; extra == 'dev'
|
|
34
|
+
Requires-Dist: pytest>=8.3; extra == 'dev'
|
|
35
|
+
Requires-Dist: ruff>=0.11; extra == 'dev'
|
|
36
|
+
Provides-Extra: keyring
|
|
37
|
+
Requires-Dist: keyring>=25.0; extra == 'keyring'
|
|
38
|
+
Provides-Extra: notebook
|
|
39
|
+
Requires-Dist: ipykernel>=6.29; extra == 'notebook'
|
|
40
|
+
Requires-Dist: jupyterlab>=4.2; extra == 'notebook'
|
|
41
|
+
Provides-Extra: viz
|
|
42
|
+
Requires-Dist: ipywidgets>=8.1; extra == 'viz'
|
|
43
|
+
Requires-Dist: plotly>=6.0; extra == 'viz'
|
|
44
|
+
Description-Content-Type: text/markdown
|
|
45
|
+
|
|
46
|
+
# propalgos
|
|
47
|
+
|
|
48
|
+
Quant research SDK for [PropAlgos](https://propalgos.ai) — data, signals, backtesting, and visualization on GPU cloud instances.
|
|
49
|
+
|
|
50
|
+
## Install
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
pip install propalgos
|
|
54
|
+
|
|
55
|
+
# with visualization (plotly)
|
|
56
|
+
pip install 'propalgos[viz]'
|
|
57
|
+
|
|
58
|
+
# with notebook support (jupyterlab)
|
|
59
|
+
pip install 'propalgos[notebook]'
|
|
60
|
+
|
|
61
|
+
# all optional deps
|
|
62
|
+
pip install 'propalgos[viz,notebook,keyring]'
|
|
63
|
+
|
|
64
|
+
# development
|
|
65
|
+
pip install -e ".[dev,viz]"
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Or with uv:
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
uv add propalgos
|
|
72
|
+
uv add 'propalgos[viz]'
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## Quickstart
|
|
76
|
+
|
|
77
|
+
```python
|
|
78
|
+
import propalgos as pa
|
|
79
|
+
|
|
80
|
+
prices = pa.data.prices("SPY", start="2020-01-01")
|
|
81
|
+
signal = pa.signals.sma_cross(prices, fast=20, slow=100)
|
|
82
|
+
bt = pa.backtest.run(prices, signal, initial_cash=100_000, fee_bps=1)
|
|
83
|
+
bt.summary()
|
|
84
|
+
pa.viz.tearsheet(bt)
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## CLI
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
propalgos version # print SDK version
|
|
91
|
+
propalgos doctor # check deps and connectivity
|
|
92
|
+
propalgos env # print runtime environment summary (GPU, frameworks, cloud)
|
|
93
|
+
propalgos --help # all commands
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
The `pa` alias works too: `pa version`, `pa doctor`, `pa env`.
|
|
97
|
+
|
|
98
|
+
---
|
|
99
|
+
|
|
100
|
+
## Module Reference
|
|
101
|
+
|
|
102
|
+
### `pa.data` — Market Data
|
|
103
|
+
|
|
104
|
+
```python
|
|
105
|
+
# fetch OHLCV data (yfinance backend, disk-cached)
|
|
106
|
+
prices = pa.data.prices("SPY", start="2020-01-01", end="2024-12-31", interval="1d")
|
|
107
|
+
|
|
108
|
+
# multiple symbols → MultiIndex columns
|
|
109
|
+
prices = pa.data.prices(["SPY", "QQQ"], start="2023-01-01")
|
|
110
|
+
|
|
111
|
+
# returns
|
|
112
|
+
daily = pa.data.returns(prices) # simple returns
|
|
113
|
+
log_r = pa.data.returns(prices, method="log") # log returns
|
|
114
|
+
cum = pa.data.cumulative_returns(daily) # cumulative
|
|
115
|
+
|
|
116
|
+
# load from file
|
|
117
|
+
prices = pa.data.from_csv("my_data.csv")
|
|
118
|
+
|
|
119
|
+
# bulk dataset loading (on-platform or with local parquets)
|
|
120
|
+
df = pa.data.load("crypto-kraken", interval="1h") # stacked multi-symbol DataFrame
|
|
121
|
+
datasets = pa.data.list_datasets() # discover available datasets
|
|
122
|
+
symbols = pa.data.list_symbols("crypto-kraken", interval="1d") # symbols in a dataset
|
|
123
|
+
|
|
124
|
+
# swap data backend
|
|
125
|
+
from propalgos.data.prices import DataProvider
|
|
126
|
+
pa.data.configure(my_custom_provider) # must implement DataProvider protocol
|
|
127
|
+
pa.data.clear_cache() # purge disk cache
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
| Function | Parameters | Returns |
|
|
131
|
+
|----------|-----------|---------|
|
|
132
|
+
| `prices` | `symbols`, `start=None`, `end=None`, `interval="1d"`, `cache=True` | `pd.DataFrame` |
|
|
133
|
+
| `returns` | `prices_df`, `method="simple"` | `pd.DataFrame` |
|
|
134
|
+
| `cumulative_returns` | `returns_df` | `pd.DataFrame` |
|
|
135
|
+
| `from_csv` | `path` | `pd.DataFrame` |
|
|
136
|
+
| `load` | `dataset_id`, `interval="1d"` | `pd.DataFrame` |
|
|
137
|
+
| `list_datasets` | — | `list[dict]` |
|
|
138
|
+
| `list_symbols` | `dataset_id`, `interval="1d"` | `list[str]` |
|
|
139
|
+
| `configure` | `provider: DataProvider` | `None` |
|
|
140
|
+
| `clear_cache` | — | `int` (files removed) |
|
|
141
|
+
|
|
142
|
+
**DataProvider protocol** — implement `name: str` property and `fetch_prices(symbols, start, end, interval) -> pd.DataFrame`.
|
|
143
|
+
|
|
144
|
+
---
|
|
145
|
+
|
|
146
|
+
### `pa.signals` — Signal Generators
|
|
147
|
+
|
|
148
|
+
All signal functions accept a `pd.DataFrame` with a `close` column and return a `pd.Series` of `{-1, 0, 1}` (sell, flat, buy). Warmup periods output `0`.
|
|
149
|
+
|
|
150
|
+
```python
|
|
151
|
+
sig = pa.signals.sma_cross(prices, fast=20, slow=100)
|
|
152
|
+
sig = pa.signals.rsi_reversion(prices, period=14, overbought=70, oversold=30)
|
|
153
|
+
sig = pa.signals.combine([sig_a, sig_b], method="and")
|
|
154
|
+
|
|
155
|
+
# raw RSI values (0-100 float, not a signal)
|
|
156
|
+
rsi_values = pa.signals.rsi(prices, period=14)
|
|
157
|
+
|
|
158
|
+
# multi-symbol operations (stacked DataFrames)
|
|
159
|
+
df = pa.signals.rsi_stacked(stacked_df, period=14, symbol_col="symbol") # adds 'rsi' column
|
|
160
|
+
df = pa.signals.scan(stacked_df, pa.signals.sma_cross, symbol_col="symbol") # adds 'signal' column
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
| Function | Parameters | Strategy |
|
|
164
|
+
|----------|-----------|----------|
|
|
165
|
+
| `sma_cross` | `fast=20`, `slow=100` | SMA crossover — long when fast > slow |
|
|
166
|
+
| `ema_cross` | `fast=12`, `slow=26` | EMA crossover |
|
|
167
|
+
| `trend_filter` | `period=50` | Trend following — long above SMA, short below |
|
|
168
|
+
| `rsi_reversion` | `period=14`, `overbought=70`, `oversold=30` | RSI mean reversion |
|
|
169
|
+
| `rsi` | `period=14` | Raw RSI values (0–100 float, not a signal) |
|
|
170
|
+
| `macd` | *(default MACD params)* | MACD histogram sign |
|
|
171
|
+
| `bollinger_bands` | `period=20`, `num_std=2.0` | Band extremes — long at lower, short at upper |
|
|
172
|
+
| `zscore_reversion` | `period=20`, `entry_z=2.0`, `exit_z=0.5` | Z-score extremes |
|
|
173
|
+
| `combine` | `signals: list`, `method="and"\|"or"\|"majority"` | Combine multiple signals |
|
|
174
|
+
| `rsi_stacked` | `df`, `period=14`, `symbol_col="symbol"` | Vectorized RSI across stacked multi-symbol DataFrames |
|
|
175
|
+
| `scan` | `df`, `signal_fn`, `symbol_col="symbol"` | Generic groupby applicator — apply any signal function across symbols |
|
|
176
|
+
|
|
177
|
+
---
|
|
178
|
+
|
|
179
|
+
### `pa.factors` — Performance Metrics & Risk Analytics
|
|
180
|
+
|
|
181
|
+
All functions accept a `pd.Series` of daily simple returns.
|
|
182
|
+
|
|
183
|
+
```python
|
|
184
|
+
pa.factors.sharpe(returns) # 1.42
|
|
185
|
+
pa.factors.max_drawdown(returns) # 0.187
|
|
186
|
+
pa.factors.var(returns, 0.95) # 0.023
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
**Performance** (annualized where applicable):
|
|
190
|
+
|
|
191
|
+
| Function | Parameters | Returns |
|
|
192
|
+
|----------|-----------|---------|
|
|
193
|
+
| `sharpe` | `rf=0.0` | `float` |
|
|
194
|
+
| `sortino` | `rf=0.0` | `float` |
|
|
195
|
+
| `calmar` | — | `float` |
|
|
196
|
+
| `total_return` | — | `float` |
|
|
197
|
+
| `annualized_return` | — | `float` |
|
|
198
|
+
| `annualized_volatility` | — | `float` |
|
|
199
|
+
| `win_rate` | — | `float` |
|
|
200
|
+
| `profit_factor` | — | `float` |
|
|
201
|
+
|
|
202
|
+
**Risk:**
|
|
203
|
+
|
|
204
|
+
| Function | Parameters | Returns |
|
|
205
|
+
|----------|-----------|---------|
|
|
206
|
+
| `var` | `confidence=0.95` | `float` |
|
|
207
|
+
| `cvar` | `confidence=0.95` | `float` |
|
|
208
|
+
| `max_drawdown` | — | `float` |
|
|
209
|
+
| `drawdown_series` | — | `pd.Series` |
|
|
210
|
+
| `beta` | `strategy_returns, benchmark_returns` | `float` |
|
|
211
|
+
| `rolling_volatility` | `window=20` | `pd.Series` |
|
|
212
|
+
|
|
213
|
+
**Constant:** `pa.factors.TRADING_DAYS = 252`
|
|
214
|
+
|
|
215
|
+
---
|
|
216
|
+
|
|
217
|
+
### `pa.backtest` — Vectorized Backtesting
|
|
218
|
+
|
|
219
|
+
```python
|
|
220
|
+
result = pa.backtest.run(
|
|
221
|
+
prices, # DataFrame with 'close' column
|
|
222
|
+
signal, # Series of {-1, 0, 1}
|
|
223
|
+
initial_cash=100_000, # starting capital
|
|
224
|
+
fee_bps=5, # 0.05% per trade
|
|
225
|
+
slippage_bps=2, # 0.02% slippage
|
|
226
|
+
benchmark="SPY", # optional benchmark (str or DataFrame)
|
|
227
|
+
)
|
|
228
|
+
|
|
229
|
+
result.summary() # formatted text output
|
|
230
|
+
result.to_dict() # serializable dict
|
|
231
|
+
result.to_json() # JSON string
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
**BacktestResult attributes:**
|
|
235
|
+
|
|
236
|
+
| Attribute | Type | Description |
|
|
237
|
+
|-----------|------|-------------|
|
|
238
|
+
| `equity_curve` | `pd.Series` | Dollar equity by date |
|
|
239
|
+
| `returns` | `pd.Series` | Daily simple returns |
|
|
240
|
+
| `positions` | `pd.Series` | Position at each bar (-1, 0, 1) |
|
|
241
|
+
| `trades` | `pd.DataFrame` | One row per position change |
|
|
242
|
+
| `drawdowns` | `pd.Series` | Peak-to-trough drawdown series |
|
|
243
|
+
| `benchmark_equity` | `pd.Series \| None` | Benchmark equity curve |
|
|
244
|
+
| `benchmark_returns` | `pd.Series \| None` | Benchmark daily returns |
|
|
245
|
+
| `metrics` | `dict[str, float]` | Sharpe, Sortino, max DD, CAGR, etc. |
|
|
246
|
+
| `initial_cash` | `float` | Starting capital |
|
|
247
|
+
| `cost_model` | `CostModel` | Fee + slippage config |
|
|
248
|
+
|
|
249
|
+
**CostModel:** `CostModel(fee_bps=0, slippage_bps=0)` — immutable cost config.
|
|
250
|
+
|
|
251
|
+
---
|
|
252
|
+
|
|
253
|
+
### `pa.viz` — Visualization
|
|
254
|
+
|
|
255
|
+
Requires `plotly` — install with `pip install 'propalgos[viz]'`.
|
|
256
|
+
|
|
257
|
+
```python
|
|
258
|
+
pa.viz.tearsheet(result) # multi-panel backtest tearsheet
|
|
259
|
+
pa.viz.candles(prices, indicators=["sma20", "bb20"], signals=signal)
|
|
260
|
+
pa.viz.monthly_returns(result) # years x months heatmap
|
|
261
|
+
pa.viz.heatmap(matrix, colorscale="rsi", fmt=".0f", zrange=(0, 100))
|
|
262
|
+
pa.viz.strip(data, x="timeframe", y="rsi", color="symbol",
|
|
263
|
+
thresholds={"Oversold": (0, 30), "Overbought": (70, 100)})
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
| Function | Description |
|
|
267
|
+
|----------|-------------|
|
|
268
|
+
| `tearsheet(result)` | Equity curve + drawdown + monthly returns + metrics panel. Auto-shows in notebooks. |
|
|
269
|
+
| `candles(prices, indicators=None, signals=None, title=None)` | Candlestick chart with optional SMA/EMA/BB overlays and buy/sell markers. |
|
|
270
|
+
| `monthly_returns(result_or_returns)` | Monthly returns heatmap (years x months). Accepts BacktestResult or raw Series. |
|
|
271
|
+
| `heatmap(z, colorscale="diverging", fmt=".1%", title="", zrange=None)` | General-purpose heatmap for any DataFrame matrix. |
|
|
272
|
+
| `strip(data, x, y, color, thresholds=None, title="", y_range=None)` | Strip/jitter plot with optional threshold bands for signal distribution. |
|
|
273
|
+
|
|
274
|
+
**Indicator specs** for `candles()`: `sma{n}`, `ema{n}`, `bb{n}` (e.g. `"sma20"`, `"ema50"`, `"bb20"`).
|
|
275
|
+
|
|
276
|
+
**Colorscale presets**: `"diverging"` (red → green), `"sequential"` (green → red), `"rsi"` (green → red, 5-stop). Or pass a raw Plotly colorscale list.
|
|
277
|
+
|
|
278
|
+
#### Dark/Light Mode
|
|
279
|
+
|
|
280
|
+
```python
|
|
281
|
+
pa.viz.set_mode("light") # switch to light theme
|
|
282
|
+
pa.viz.tearsheet(result) # now renders with light palette
|
|
283
|
+
|
|
284
|
+
pa.viz.set_mode("dark") # back to default dark theme
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
All chart functions read from the active palette automatically. `COLORS` dict and `COLORSCALES` dict update in place when mode changes.
|
|
288
|
+
|
|
289
|
+
| Function/Object | Description |
|
|
290
|
+
|-----------------|-------------|
|
|
291
|
+
| `set_mode("dark" \| "light")` | Set global theme mode |
|
|
292
|
+
| `colors()` | Returns active color palette dict |
|
|
293
|
+
| `colorscales()` | Returns active colorscale presets dict |
|
|
294
|
+
| `COLORS` | Active palette dict (mutates with `set_mode`) |
|
|
295
|
+
| `COLORSCALES` | Active colorscale presets (mutates with `set_mode`) |
|
|
296
|
+
| `apply_theme(fig)` | Apply PropAlgos theme to any Plotly figure |
|
|
297
|
+
|
|
298
|
+
---
|
|
299
|
+
|
|
300
|
+
### `pa.env` — Environment Detection
|
|
301
|
+
|
|
302
|
+
```python
|
|
303
|
+
pa.env.summary()
|
|
304
|
+
# PropAlgos Environment
|
|
305
|
+
# ─────────────────────
|
|
306
|
+
# Runtime: PropAlgos Cloud (AWS us-east-1, g4dn.xlarge)
|
|
307
|
+
# Python: 3.11.9
|
|
308
|
+
# GPU: NVIDIA T4 (16 GB) — CUDA 12.4
|
|
309
|
+
# Frameworks: PyTorch 2.3.0 (GPU), RAPIDS cuDF 24.10 (GPU)
|
|
310
|
+
|
|
311
|
+
gpu = pa.env.gpu() # GPUInfo(available=True, name="NVIDIA T4", ...)
|
|
312
|
+
fws = pa.env.frameworks() # [FrameworkInfo(name="torch", version="2.3.0", gpu_enabled=True), ...]
|
|
313
|
+
rt = pa.env.detect_runtime() # RuntimeInfo(on_propalgos=True, cloud_provider="aws", ...)
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
| Function | Returns | Description |
|
|
317
|
+
|----------|---------|-------------|
|
|
318
|
+
| `summary()` | `None` | Print formatted environment info to stdout |
|
|
319
|
+
| `gpu()` | `GPUInfo` | GPU hardware detection (nvidia-smi → torch → tensorflow fallback) |
|
|
320
|
+
| `in_propalgos()` | `bool` | True if running on a PropAlgos-managed instance |
|
|
321
|
+
| `frameworks()` | `list[FrameworkInfo]` | Detected ML frameworks (torch, tensorflow, jax, RAPIDS) |
|
|
322
|
+
| `detect_runtime()` | `RuntimeInfo` | Cloud provider, region, instance type, Python version |
|
|
323
|
+
|
|
324
|
+
**GPUInfo fields**: `available`, `name`, `memory_mb`, `driver_version`, `cuda_version`, `count`
|
|
325
|
+
|
|
326
|
+
**RuntimeInfo fields**: `on_propalgos`, `cloud_provider`, `region`, `instance_type`, `instance_id`, `python_version`, `platform`
|
|
327
|
+
|
|
328
|
+
---
|
|
329
|
+
|
|
330
|
+
### `pa.config` — Configuration
|
|
331
|
+
|
|
332
|
+
```python
|
|
333
|
+
from propalgos.config import get_config
|
|
334
|
+
|
|
335
|
+
cfg = get_config()
|
|
336
|
+
cfg.api_url # "https://api.propalgos.ai"
|
|
337
|
+
cfg.token # from PROPALGOS_TOKEN env
|
|
338
|
+
cfg.is_on_platform # True if PROPALGOS_INSTANCE_ID is set
|
|
339
|
+
cfg.cache_dir # ~/.cache/propalgos
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
**Environment variables:**
|
|
343
|
+
|
|
344
|
+
| Variable | Default | Description |
|
|
345
|
+
|----------|---------|-------------|
|
|
346
|
+
| `PROPALGOS_API_URL` | `https://api.propalgos.ai` | Backend API URL |
|
|
347
|
+
| `PROPALGOS_TOKEN` | `None` | Auth token |
|
|
348
|
+
| `PROPALGOS_ENV` | `production` | Environment name |
|
|
349
|
+
| `PROPALGOS_CACHE_DIR` | `~/.cache/propalgos` | Disk cache directory |
|
|
350
|
+
| `PROPALGOS_INSTANCE_ID` | `None` | Set automatically on PropAlgos instances |
|
|
351
|
+
| `PROPALGOS_CUDF_AUTO` | `1` | Set to `0` to disable auto GPU acceleration on-platform |
|
|
352
|
+
|
|
353
|
+
---
|
|
354
|
+
|
|
355
|
+
### `pa.exceptions` — Error Hierarchy
|
|
356
|
+
|
|
357
|
+
All exceptions inherit from `PropAlgosError(message, code)`.
|
|
358
|
+
|
|
359
|
+
| Exception | Code | Description |
|
|
360
|
+
|-----------|------|-------------|
|
|
361
|
+
| `PropAlgosError` | varies | Base exception with machine-readable `code` |
|
|
362
|
+
| `AuthenticationError` | `auth_error` | Invalid or expired token |
|
|
363
|
+
| `APIError` | `api_error` | Backend API call failed (`status_code`, `response_body`) |
|
|
364
|
+
| `InsufficientCreditsError` | `insufficient_credits` | Balance too low (`balance`, `required`) |
|
|
365
|
+
| `DataError` | `data_error` | Market data fetch failed |
|
|
366
|
+
| `BacktestError` | `backtest_error` | Unrecoverable backtest issue |
|
|
367
|
+
| `ConfigError` | `config_error` | Missing or invalid configuration |
|
|
368
|
+
|
|
369
|
+
---
|
|
370
|
+
|
|
371
|
+
## GPU Acceleration
|
|
372
|
+
|
|
373
|
+
On PropAlgos GPU instances with RAPIDS installed, `import propalgos` automatically activates `cudf.pandas` — all pandas operations across the SDK and your own code run on the GPU with zero code changes:
|
|
374
|
+
|
|
375
|
+
```python
|
|
376
|
+
import propalgos as pa
|
|
377
|
+
import pandas as pd
|
|
378
|
+
|
|
379
|
+
# both use GPU transparently — no %load_ext or manual setup needed
|
|
380
|
+
prices = pa.data.prices("SPY", start="2020-01-01")
|
|
381
|
+
df = pd.read_parquet("my_data.parquet") # also GPU-accelerated
|
|
382
|
+
```
|
|
383
|
+
|
|
384
|
+
Auto-activation requires `PROPALGOS_INSTANCE_ID` (set automatically on PropAlgos instances) and a RAPIDS kernel. It's a no-op when either condition isn't met.
|
|
385
|
+
|
|
386
|
+
**Opt out** (for benchmarking or debugging):
|
|
387
|
+
|
|
388
|
+
```bash
|
|
389
|
+
export PROPALGOS_CUDF_AUTO=0
|
|
390
|
+
```
|
|
391
|
+
|
|
392
|
+
**Off-platform** (local dev, Colab, etc.) — activate manually before importing propalgos:
|
|
393
|
+
|
|
394
|
+
```python
|
|
395
|
+
%load_ext cudf.pandas # or: import cudf.pandas; cudf.pandas.install()
|
|
396
|
+
|
|
397
|
+
import propalgos as pa
|
|
398
|
+
```
|
|
399
|
+
|
|
400
|
+
---
|
|
401
|
+
|
|
402
|
+
## Development
|
|
403
|
+
|
|
404
|
+
```bash
|
|
405
|
+
cd sdk/python
|
|
406
|
+
|
|
407
|
+
# install with dev + viz extras
|
|
408
|
+
pip install -e ".[dev,viz]"
|
|
409
|
+
# or with uv
|
|
410
|
+
uv sync --extra dev
|
|
411
|
+
|
|
412
|
+
# run tests (130 tests)
|
|
413
|
+
uv run -- python -m pytest tests/ -v
|
|
414
|
+
|
|
415
|
+
# lint
|
|
416
|
+
uv run -- ruff check src tests
|
|
417
|
+
|
|
418
|
+
# typecheck
|
|
419
|
+
uv run -- mypy src
|
|
420
|
+
```
|
|
421
|
+
|
|
422
|
+
### Test files
|
|
423
|
+
|
|
424
|
+
| File | Coverage |
|
|
425
|
+
|------|----------|
|
|
426
|
+
| `test_import.py` | Package structure, namespaces, exports |
|
|
427
|
+
| `test_signals.py` | All 8 signal functions + combine, raw RSI, `rsi_stacked`, `scan` |
|
|
428
|
+
| `test_factors.py` | Performance and risk metrics |
|
|
429
|
+
| `test_backtest.py` | Engine, results, costs, edge cases |
|
|
430
|
+
| `test_viz.py` | Heatmap, strip, theme modes, colorscales, monthly returns |
|
|
431
|
+
| `test_data.py` | Crypto providers, dataset registry, `load()`, `list_datasets()`, `list_symbols()` |
|
|
432
|
+
|
|
433
|
+
---
|
|
434
|
+
|
|
435
|
+
## License
|
|
436
|
+
|
|
437
|
+
Proprietary — PropAlgos, Inc. See [LICENSE](./LICENSE).
|