stacksats 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.
Files changed (79) hide show
  1. stacksats-0.1.0/LICENSE +21 -0
  2. stacksats-0.1.0/PKG-INFO +318 -0
  3. stacksats-0.1.0/README.md +269 -0
  4. stacksats-0.1.0/pyproject.toml +74 -0
  5. stacksats-0.1.0/setup.cfg +4 -0
  6. stacksats-0.1.0/stacksats/__init__.py +21 -0
  7. stacksats-0.1.0/stacksats/api.py +373 -0
  8. stacksats-0.1.0/stacksats/backtest.py +430 -0
  9. stacksats-0.1.0/stacksats/btc_api/__init__.py +1 -0
  10. stacksats-0.1.0/stacksats/btc_api/bitstamp_btc_usd.py +10 -0
  11. stacksats-0.1.0/stacksats/btc_api/coinbase_btc_usd.py +10 -0
  12. stacksats-0.1.0/stacksats/btc_api/coingecko_btc_usd.py +10 -0
  13. stacksats-0.1.0/stacksats/btc_api/coinmetrics_btc_csv.py +128 -0
  14. stacksats-0.1.0/stacksats/btc_api/kraken_xbt_usd.py +12 -0
  15. stacksats-0.1.0/stacksats/btc_price_fetcher.py +484 -0
  16. stacksats-0.1.0/stacksats/export_weights.py +748 -0
  17. stacksats-0.1.0/stacksats/loader.py +60 -0
  18. stacksats-0.1.0/stacksats/matplotlib_setup.py +54 -0
  19. stacksats-0.1.0/stacksats/modal_app.py +529 -0
  20. stacksats-0.1.0/stacksats/model_development.py +822 -0
  21. stacksats-0.1.0/stacksats/plot_mvrv.py +376 -0
  22. stacksats-0.1.0/stacksats/plot_weights.py +502 -0
  23. stacksats-0.1.0/stacksats/prelude.py +561 -0
  24. stacksats-0.1.0/stacksats/py.typed +1 -0
  25. stacksats-0.1.0/stacksats/strategies/__init__.py +14 -0
  26. stacksats-0.1.0/stacksats/strategies/base.py +37 -0
  27. stacksats-0.1.0/stacksats/strategies/examples.py +73 -0
  28. stacksats-0.1.0/stacksats/strategies/mvrv.py +20 -0
  29. stacksats-0.1.0/stacksats.egg-info/PKG-INFO +318 -0
  30. stacksats-0.1.0/stacksats.egg-info/SOURCES.txt +77 -0
  31. stacksats-0.1.0/stacksats.egg-info/dependency_links.txt +1 -0
  32. stacksats-0.1.0/stacksats.egg-info/entry_points.txt +6 -0
  33. stacksats-0.1.0/stacksats.egg-info/requires.txt +27 -0
  34. stacksats-0.1.0/stacksats.egg-info/top_level.txt +1 -0
  35. stacksats-0.1.0/tests/test_api_enhancements.py +226 -0
  36. stacksats-0.1.0/tests/test_backtest_errors.py +200 -0
  37. stacksats-0.1.0/tests/test_backtest_export_parity.py +690 -0
  38. stacksats-0.1.0/tests/test_backtest_performance.py +296 -0
  39. stacksats-0.1.0/tests/test_bdd_backtest.py +13 -0
  40. stacksats-0.1.0/tests/test_bdd_consistency.py +13 -0
  41. stacksats-0.1.0/tests/test_bdd_data_integrity.py +13 -0
  42. stacksats-0.1.0/tests/test_bdd_database_operations.py +13 -0
  43. stacksats-0.1.0/tests/test_bdd_date_ranges.py +13 -0
  44. stacksats-0.1.0/tests/test_bdd_edge_cases.py +13 -0
  45. stacksats-0.1.0/tests/test_bdd_export_weights.py +13 -0
  46. stacksats-0.1.0/tests/test_bdd_forward_looking.py +13 -0
  47. stacksats-0.1.0/tests/test_bdd_golden_snapshots.py +13 -0
  48. stacksats-0.1.0/tests/test_bdd_model_development.py +13 -0
  49. stacksats-0.1.0/tests/test_bdd_weight_computation.py +13 -0
  50. stacksats-0.1.0/tests/test_bdd_weight_constraints.py +13 -0
  51. stacksats-0.1.0/tests/test_bdd_weight_stability.py +14 -0
  52. stacksats-0.1.0/tests/test_btc_price_fetcher.py +688 -0
  53. stacksats-0.1.0/tests/test_btc_price_fetcher_historical.py +219 -0
  54. stacksats-0.1.0/tests/test_coinmetrics_btc_csv.py +155 -0
  55. stacksats-0.1.0/tests/test_cross_validation.py +565 -0
  56. stacksats-0.1.0/tests/test_debug_multiplier.py +212 -0
  57. stacksats-0.1.0/tests/test_debug_weights.py +164 -0
  58. stacksats-0.1.0/tests/test_export_weights_database.py +145 -0
  59. stacksats-0.1.0/tests/test_export_weights_detailed.py +183 -0
  60. stacksats-0.1.0/tests/test_helpers.py +24 -0
  61. stacksats-0.1.0/tests/test_main.py +407 -0
  62. stacksats-0.1.0/tests/test_market_regimes.py +701 -0
  63. stacksats-0.1.0/tests/test_modal_app.py +112 -0
  64. stacksats-0.1.0/tests/test_model_development_helpers.py +86 -0
  65. stacksats-0.1.0/tests/test_model_edge_cases.py +129 -0
  66. stacksats-0.1.0/tests/test_monte_carlo.py +647 -0
  67. stacksats-0.1.0/tests/test_package_api.py +68 -0
  68. stacksats-0.1.0/tests/test_performance_benchmarks.py +478 -0
  69. stacksats-0.1.0/tests/test_plotting.py +71 -0
  70. stacksats-0.1.0/tests/test_prelude_cache.py +72 -0
  71. stacksats-0.1.0/tests/test_prelude_gap_filling.py +102 -0
  72. stacksats-0.1.0/tests/test_prelude_mvrv_fallback.py +412 -0
  73. stacksats-0.1.0/tests/test_price_validation.py +44 -0
  74. stacksats-0.1.0/tests/test_property_based.py +339 -0
  75. stacksats-0.1.0/tests/test_sensitivity_analysis.py +396 -0
  76. stacksats-0.1.0/tests/test_simulation.py +748 -0
  77. stacksats-0.1.0/tests/test_statistical_validation.py +484 -0
  78. stacksats-0.1.0/tests/test_visualization.py +337 -0
  79. stacksats-0.1.0/tests/test_weight_stability.py +415 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Hypertrial
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,318 @@
1
+ Metadata-Version: 2.4
2
+ Name: stacksats
3
+ Version: 0.1.0
4
+ Summary: Bitcoin DCA model development, backtesting, and Modal deployment toolkit
5
+ Author: StackSats Contributors
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/stacksats/stacksats
8
+ Project-URL: Repository, https://github.com/stacksats/stacksats
9
+ Project-URL: Documentation, https://github.com/stacksats/stacksats/tree/main/docs
10
+ Keywords: bitcoin,dca,backtesting,quant,crypto
11
+ Classifier: Development Status :: 3 - Alpha
12
+ Classifier: Intended Audience :: Financial and Insurance Industry
13
+ Classifier: Intended Audience :: Science/Research
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Topic :: Office/Business :: Financial :: Investment
19
+ Classifier: Topic :: Scientific/Engineering :: Information Analysis
20
+ Requires-Python: >=3.11
21
+ Description-Content-Type: text/markdown
22
+ License-File: LICENSE
23
+ Requires-Dist: pandas>=2.0.0
24
+ Requires-Dist: numpy>=1.24.0
25
+ Requires-Dist: scipy>=1.11.0
26
+ Requires-Dist: requests>=2.31.0
27
+ Requires-Dist: matplotlib>=3.7.0
28
+ Requires-Dist: seaborn>=0.12.0
29
+ Provides-Extra: deploy
30
+ Requires-Dist: modal>=0.52.0; extra == "deploy"
31
+ Requires-Dist: psycopg2-binary>=2.9.0; extra == "deploy"
32
+ Requires-Dist: fastapi>=0.104.0; extra == "deploy"
33
+ Requires-Dist: python-dotenv>=1.0.0; extra == "deploy"
34
+ Requires-Dist: tenacity>=8.2.0; extra == "deploy"
35
+ Requires-Dist: pyarrow>=13.0.0; extra == "deploy"
36
+ Provides-Extra: dev
37
+ Requires-Dist: pytest>=7.0.0; extra == "dev"
38
+ Requires-Dist: pytest-bdd>=7.0.0; extra == "dev"
39
+ Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
40
+ Requires-Dist: pytest-mock>=3.10.0; extra == "dev"
41
+ Requires-Dist: pytest-benchmark>=4.0.0; extra == "dev"
42
+ Requires-Dist: pytest-xdist>=3.0.0; extra == "dev"
43
+ Requires-Dist: responses>=0.23.0; extra == "dev"
44
+ Requires-Dist: freezegun>=1.2.0; extra == "dev"
45
+ Requires-Dist: hypothesis>=6.0.0; extra == "dev"
46
+ Requires-Dist: ruff>=0.1.0; extra == "dev"
47
+ Requires-Dist: vulture; extra == "dev"
48
+ Dynamic: license-file
49
+
50
+ # StackSats
51
+
52
+ StackSats, developed by [Hypertrial](https://www.hypertrail.ai), is a Python package for developing and backtesting Bitcoin DCA ("stacking sats") allocation strategies.
53
+
54
+ Learn more at [www.stackingsats.org](https://www.stackingsats.org)
55
+
56
+ It provides:
57
+ - A clean strategy interface (`WindowStrategy`)
58
+ - Built-in and example strategies
59
+ - A rolling-window backtest engine
60
+ - Feature precomputation utilities
61
+ - Validation checks for leakage, constraints, and win-rate
62
+
63
+ ## Installation
64
+
65
+ Install core package for local model development:
66
+
67
+ ```bash
68
+ pip install stacksats
69
+ ```
70
+
71
+ For local development from source:
72
+
73
+ ```bash
74
+ pip install -e .
75
+ pip install -r requirements-dev.txt
76
+ ```
77
+
78
+ Install deployment dependencies only if needed:
79
+
80
+ ```bash
81
+ pip install "stacksats[deploy]"
82
+ ```
83
+
84
+ ## Quick Start (write your own strategy file)
85
+
86
+ Create `my_strategy.py`:
87
+
88
+ ```python
89
+ import numpy as np
90
+ import pandas as pd
91
+
92
+ from stacksats import run_backtest, validate_strategy
93
+
94
+
95
+ class MyStrategy:
96
+ def compute_weights(
97
+ self,
98
+ features_df: pd.DataFrame,
99
+ start_date: pd.Timestamp,
100
+ end_date: pd.Timestamp,
101
+ current_date: pd.Timestamp,
102
+ ) -> pd.Series:
103
+ del current_date
104
+ window = features_df.loc[start_date:end_date]
105
+ if window.empty:
106
+ return pd.Series(dtype=float)
107
+
108
+ z = window.get("mvrv_zscore", pd.Series(0.0, index=window.index)).to_numpy()
109
+ ma = window.get("price_vs_ma", pd.Series(0.0, index=window.index)).to_numpy()
110
+ raw = np.exp((-1.2 * z) + (-0.8 * ma))
111
+ w = raw / raw.sum()
112
+ return pd.Series(w, index=window.index)
113
+
114
+
115
+ if __name__ == "__main__":
116
+ strategy = MyStrategy()
117
+
118
+ validation = validate_strategy(strategy)
119
+ print(validation.summary())
120
+
121
+ result = run_backtest(strategy, strategy_label="my-strategy")
122
+ print(result.summary())
123
+ result.plot(output_dir="output")
124
+ result.to_json("output/backtest_result.json")
125
+ ```
126
+
127
+ Run it directly:
128
+
129
+ ```bash
130
+ python my_strategy.py
131
+ ```
132
+
133
+ For a complete command reference using the included example file, see
134
+ [`docs/commands.md`](docs/commands.md).
135
+
136
+ ## Public API
137
+
138
+ Top-level package exports:
139
+
140
+ - `run_backtest()`: Run a rolling-window backtest for any strategy
141
+ - `validate_strategy()`: Run submission-style validation checks
142
+ - `load_data()`: Load BTC market data (with local cache support)
143
+ - `precompute_features()`: Build model features from BTC data
144
+ - `load_strategy()`: Load a strategy from `module_or_path:ClassName`
145
+ - `BacktestResult`: Result object with summary/plot/serialization helpers
146
+ - `ValidationResult`: Structured validation output
147
+ - `WindowStrategy`, `CallableWindowStrategy`, `MVRVStrategy`
148
+
149
+ `load_data()` also supports cache controls via optional keyword args:
150
+ - `cache_dir` (default `~/.stacksats/cache`, set to `None` to disable local cache)
151
+ - `max_age_hours` (default `24`, refresh threshold for cached CoinMetrics CSV)
152
+
153
+ ## Writing a Strategy
154
+
155
+ Implement `compute_weights()` with this interface:
156
+
157
+ ```python
158
+ def compute_weights(
159
+ self,
160
+ features_df: pd.DataFrame,
161
+ start_date: pd.Timestamp,
162
+ end_date: pd.Timestamp,
163
+ current_date: pd.Timestamp,
164
+ ) -> pd.Series:
165
+ ...
166
+ ```
167
+
168
+ Rules your strategy should satisfy:
169
+
170
+ - Return a weight series indexed by dates in the selected window
171
+ - Weights should be non-negative
172
+ - Weights should sum to `1.0`
173
+ - Avoid forward-looking data usage
174
+
175
+ ### Available Features
176
+
177
+ Feature columns are generated by `precompute_features()` and typically include:
178
+
179
+ - `PriceUSD_coinmetrics`
180
+ - `price_ma`
181
+ - `price_vs_ma`
182
+ - `mvrv_zscore`
183
+ - `mvrv_gradient`
184
+ - `mvrv_percentile`
185
+ - `mvrv_acceleration`
186
+ - `mvrv_zone`
187
+ - `mvrv_volatility`
188
+ - `signal_confidence`
189
+
190
+ ## Built-in and Example Strategies
191
+
192
+ ### Built-in
193
+
194
+ - `MVRVStrategy`: Default strategy from the package model.
195
+
196
+ ### Examples
197
+
198
+ In `stacksats.strategies.examples`:
199
+
200
+ - `UniformStrategy`
201
+ - `SimpleZScoreStrategy`
202
+ - `MomentumStrategy`
203
+
204
+ These are lightweight templates for custom model development.
205
+
206
+ ## Backtesting
207
+
208
+ Run the default built-in strategy:
209
+
210
+ ```bash
211
+ stacksats-backtest
212
+ ```
213
+
214
+ Run a custom strategy class from a file:
215
+
216
+ ```bash
217
+ stacksats-backtest --strategy my_strategy.py:MyStrategy --start-date 2020-01-01 --end-date 2025-01-01
218
+ ```
219
+
220
+ Use the Python API directly:
221
+
222
+ ```python
223
+ from stacksats import MVRVStrategy, run_backtest
224
+
225
+ result = run_backtest(MVRVStrategy(), strategy_label="default-mvrv")
226
+ print(result.summary())
227
+ ```
228
+
229
+ ## Validation
230
+
231
+ Validate built-in strategy:
232
+
233
+ ```bash
234
+ stacksats-validate --start-date 2020-01-01 --end-date 2025-01-01
235
+ ```
236
+
237
+ Validate a custom strategy class:
238
+
239
+ ```bash
240
+ stacksats-validate --strategy my_strategy.py:MyStrategy --min-win-rate 50.0
241
+ ```
242
+
243
+ ## Command Line Tools
244
+
245
+ Installed scripts:
246
+
247
+ - `stacksats-backtest`
248
+ - `stacksats-export`
249
+ - `stacksats-plot-mvrv`
250
+ - `stacksats-plot-weights`
251
+ - `stacksats-validate`
252
+
253
+ Custom-strategy flags:
254
+
255
+ - `stacksats-backtest --strategy module_or_path:ClassName`
256
+ - `stacksats-validate --strategy module_or_path:ClassName`
257
+ - `stacksats-export --strategy module_or_path:ClassName`
258
+
259
+ ## Advanced: Deployment
260
+
261
+ Deployment and infrastructure modules are optional:
262
+
263
+ - `stacksats.export_weights`
264
+ - `stacksats.modal_app`
265
+
266
+ These require deployment extras:
267
+
268
+ ```bash
269
+ pip install "stacksats[deploy]"
270
+ ```
271
+
272
+ Deploy with built-in strategy:
273
+
274
+ ```bash
275
+ modal deploy stacksats/modal_app.py
276
+ ```
277
+
278
+ Deploy with custom strategy:
279
+
280
+ ```bash
281
+ STACKSATS_STRATEGY=my_strategy.py:MyStrategy modal deploy stacksats/modal_app.py
282
+ ```
283
+
284
+ ## Development
285
+
286
+ Run tests:
287
+
288
+ ```bash
289
+ pytest tests/ -v
290
+ ```
291
+
292
+ Verify documented command examples:
293
+
294
+ ```bash
295
+ # Requires ./venv (for example: python -m venv venv && source venv/bin/activate && pip install -e .)
296
+ python scripts/test_example_commands.py
297
+ ```
298
+
299
+ Run lint:
300
+
301
+ ```bash
302
+ ruff check .
303
+ ```
304
+
305
+ Release process: see `docs/release.md`.
306
+
307
+ ## Contributors
308
+
309
+ This project has benefited from contributions by researchers from the following universities:
310
+
311
+ - Columbia University (Master of Data Science)
312
+ - Cornell University (Master of Engineering in Management)
313
+ - Georgia Institute of Technology (Master of Science in Analytics)
314
+ - London School of Economics (Master of Science in Data Science)
315
+ - University of British Columbia (Master of Data Science)
316
+ - University of California, Davis (Master of Science in Business Analytics)
317
+ - University of California, Irvine (Master of Data Science)
318
+ - University of California, San Diego (Master of Quantitative Finance)
@@ -0,0 +1,269 @@
1
+ # StackSats
2
+
3
+ StackSats, developed by [Hypertrial](https://www.hypertrail.ai), is a Python package for developing and backtesting Bitcoin DCA ("stacking sats") allocation strategies.
4
+
5
+ Learn more at [www.stackingsats.org](https://www.stackingsats.org)
6
+
7
+ It provides:
8
+ - A clean strategy interface (`WindowStrategy`)
9
+ - Built-in and example strategies
10
+ - A rolling-window backtest engine
11
+ - Feature precomputation utilities
12
+ - Validation checks for leakage, constraints, and win-rate
13
+
14
+ ## Installation
15
+
16
+ Install core package for local model development:
17
+
18
+ ```bash
19
+ pip install stacksats
20
+ ```
21
+
22
+ For local development from source:
23
+
24
+ ```bash
25
+ pip install -e .
26
+ pip install -r requirements-dev.txt
27
+ ```
28
+
29
+ Install deployment dependencies only if needed:
30
+
31
+ ```bash
32
+ pip install "stacksats[deploy]"
33
+ ```
34
+
35
+ ## Quick Start (write your own strategy file)
36
+
37
+ Create `my_strategy.py`:
38
+
39
+ ```python
40
+ import numpy as np
41
+ import pandas as pd
42
+
43
+ from stacksats import run_backtest, validate_strategy
44
+
45
+
46
+ class MyStrategy:
47
+ def compute_weights(
48
+ self,
49
+ features_df: pd.DataFrame,
50
+ start_date: pd.Timestamp,
51
+ end_date: pd.Timestamp,
52
+ current_date: pd.Timestamp,
53
+ ) -> pd.Series:
54
+ del current_date
55
+ window = features_df.loc[start_date:end_date]
56
+ if window.empty:
57
+ return pd.Series(dtype=float)
58
+
59
+ z = window.get("mvrv_zscore", pd.Series(0.0, index=window.index)).to_numpy()
60
+ ma = window.get("price_vs_ma", pd.Series(0.0, index=window.index)).to_numpy()
61
+ raw = np.exp((-1.2 * z) + (-0.8 * ma))
62
+ w = raw / raw.sum()
63
+ return pd.Series(w, index=window.index)
64
+
65
+
66
+ if __name__ == "__main__":
67
+ strategy = MyStrategy()
68
+
69
+ validation = validate_strategy(strategy)
70
+ print(validation.summary())
71
+
72
+ result = run_backtest(strategy, strategy_label="my-strategy")
73
+ print(result.summary())
74
+ result.plot(output_dir="output")
75
+ result.to_json("output/backtest_result.json")
76
+ ```
77
+
78
+ Run it directly:
79
+
80
+ ```bash
81
+ python my_strategy.py
82
+ ```
83
+
84
+ For a complete command reference using the included example file, see
85
+ [`docs/commands.md`](docs/commands.md).
86
+
87
+ ## Public API
88
+
89
+ Top-level package exports:
90
+
91
+ - `run_backtest()`: Run a rolling-window backtest for any strategy
92
+ - `validate_strategy()`: Run submission-style validation checks
93
+ - `load_data()`: Load BTC market data (with local cache support)
94
+ - `precompute_features()`: Build model features from BTC data
95
+ - `load_strategy()`: Load a strategy from `module_or_path:ClassName`
96
+ - `BacktestResult`: Result object with summary/plot/serialization helpers
97
+ - `ValidationResult`: Structured validation output
98
+ - `WindowStrategy`, `CallableWindowStrategy`, `MVRVStrategy`
99
+
100
+ `load_data()` also supports cache controls via optional keyword args:
101
+ - `cache_dir` (default `~/.stacksats/cache`, set to `None` to disable local cache)
102
+ - `max_age_hours` (default `24`, refresh threshold for cached CoinMetrics CSV)
103
+
104
+ ## Writing a Strategy
105
+
106
+ Implement `compute_weights()` with this interface:
107
+
108
+ ```python
109
+ def compute_weights(
110
+ self,
111
+ features_df: pd.DataFrame,
112
+ start_date: pd.Timestamp,
113
+ end_date: pd.Timestamp,
114
+ current_date: pd.Timestamp,
115
+ ) -> pd.Series:
116
+ ...
117
+ ```
118
+
119
+ Rules your strategy should satisfy:
120
+
121
+ - Return a weight series indexed by dates in the selected window
122
+ - Weights should be non-negative
123
+ - Weights should sum to `1.0`
124
+ - Avoid forward-looking data usage
125
+
126
+ ### Available Features
127
+
128
+ Feature columns are generated by `precompute_features()` and typically include:
129
+
130
+ - `PriceUSD_coinmetrics`
131
+ - `price_ma`
132
+ - `price_vs_ma`
133
+ - `mvrv_zscore`
134
+ - `mvrv_gradient`
135
+ - `mvrv_percentile`
136
+ - `mvrv_acceleration`
137
+ - `mvrv_zone`
138
+ - `mvrv_volatility`
139
+ - `signal_confidence`
140
+
141
+ ## Built-in and Example Strategies
142
+
143
+ ### Built-in
144
+
145
+ - `MVRVStrategy`: Default strategy from the package model.
146
+
147
+ ### Examples
148
+
149
+ In `stacksats.strategies.examples`:
150
+
151
+ - `UniformStrategy`
152
+ - `SimpleZScoreStrategy`
153
+ - `MomentumStrategy`
154
+
155
+ These are lightweight templates for custom model development.
156
+
157
+ ## Backtesting
158
+
159
+ Run the default built-in strategy:
160
+
161
+ ```bash
162
+ stacksats-backtest
163
+ ```
164
+
165
+ Run a custom strategy class from a file:
166
+
167
+ ```bash
168
+ stacksats-backtest --strategy my_strategy.py:MyStrategy --start-date 2020-01-01 --end-date 2025-01-01
169
+ ```
170
+
171
+ Use the Python API directly:
172
+
173
+ ```python
174
+ from stacksats import MVRVStrategy, run_backtest
175
+
176
+ result = run_backtest(MVRVStrategy(), strategy_label="default-mvrv")
177
+ print(result.summary())
178
+ ```
179
+
180
+ ## Validation
181
+
182
+ Validate built-in strategy:
183
+
184
+ ```bash
185
+ stacksats-validate --start-date 2020-01-01 --end-date 2025-01-01
186
+ ```
187
+
188
+ Validate a custom strategy class:
189
+
190
+ ```bash
191
+ stacksats-validate --strategy my_strategy.py:MyStrategy --min-win-rate 50.0
192
+ ```
193
+
194
+ ## Command Line Tools
195
+
196
+ Installed scripts:
197
+
198
+ - `stacksats-backtest`
199
+ - `stacksats-export`
200
+ - `stacksats-plot-mvrv`
201
+ - `stacksats-plot-weights`
202
+ - `stacksats-validate`
203
+
204
+ Custom-strategy flags:
205
+
206
+ - `stacksats-backtest --strategy module_or_path:ClassName`
207
+ - `stacksats-validate --strategy module_or_path:ClassName`
208
+ - `stacksats-export --strategy module_or_path:ClassName`
209
+
210
+ ## Advanced: Deployment
211
+
212
+ Deployment and infrastructure modules are optional:
213
+
214
+ - `stacksats.export_weights`
215
+ - `stacksats.modal_app`
216
+
217
+ These require deployment extras:
218
+
219
+ ```bash
220
+ pip install "stacksats[deploy]"
221
+ ```
222
+
223
+ Deploy with built-in strategy:
224
+
225
+ ```bash
226
+ modal deploy stacksats/modal_app.py
227
+ ```
228
+
229
+ Deploy with custom strategy:
230
+
231
+ ```bash
232
+ STACKSATS_STRATEGY=my_strategy.py:MyStrategy modal deploy stacksats/modal_app.py
233
+ ```
234
+
235
+ ## Development
236
+
237
+ Run tests:
238
+
239
+ ```bash
240
+ pytest tests/ -v
241
+ ```
242
+
243
+ Verify documented command examples:
244
+
245
+ ```bash
246
+ # Requires ./venv (for example: python -m venv venv && source venv/bin/activate && pip install -e .)
247
+ python scripts/test_example_commands.py
248
+ ```
249
+
250
+ Run lint:
251
+
252
+ ```bash
253
+ ruff check .
254
+ ```
255
+
256
+ Release process: see `docs/release.md`.
257
+
258
+ ## Contributors
259
+
260
+ This project has benefited from contributions by researchers from the following universities:
261
+
262
+ - Columbia University (Master of Data Science)
263
+ - Cornell University (Master of Engineering in Management)
264
+ - Georgia Institute of Technology (Master of Science in Analytics)
265
+ - London School of Economics (Master of Science in Data Science)
266
+ - University of British Columbia (Master of Data Science)
267
+ - University of California, Davis (Master of Science in Business Analytics)
268
+ - University of California, Irvine (Master of Data Science)
269
+ - University of California, San Diego (Master of Quantitative Finance)
@@ -0,0 +1,74 @@
1
+ [build-system]
2
+ requires = ["setuptools>=69", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "stacksats"
7
+ version = "0.1.0"
8
+ description = "Bitcoin DCA model development, backtesting, and Modal deployment toolkit"
9
+ readme = { file = "README.md", content-type = "text/markdown" }
10
+ requires-python = ">=3.11"
11
+ license = { text = "MIT" }
12
+ authors = [{ name = "StackSats Contributors" }]
13
+ keywords = ["bitcoin", "dca", "backtesting", "quant", "crypto"]
14
+ classifiers = [
15
+ "Development Status :: 3 - Alpha",
16
+ "Intended Audience :: Financial and Insurance Industry",
17
+ "Intended Audience :: Science/Research",
18
+ "License :: OSI Approved :: MIT License",
19
+ "Programming Language :: Python :: 3",
20
+ "Programming Language :: Python :: 3.11",
21
+ "Programming Language :: Python :: 3.12",
22
+ "Topic :: Office/Business :: Financial :: Investment",
23
+ "Topic :: Scientific/Engineering :: Information Analysis",
24
+ ]
25
+ dependencies = [
26
+ "pandas>=2.0.0",
27
+ "numpy>=1.24.0",
28
+ "scipy>=1.11.0",
29
+ "requests>=2.31.0",
30
+ "matplotlib>=3.7.0",
31
+ "seaborn>=0.12.0",
32
+ ]
33
+
34
+ [project.urls]
35
+ Homepage = "https://github.com/stacksats/stacksats"
36
+ Repository = "https://github.com/stacksats/stacksats"
37
+ Documentation = "https://github.com/stacksats/stacksats/tree/main/docs"
38
+
39
+ [project.optional-dependencies]
40
+ deploy = [
41
+ "modal>=0.52.0",
42
+ "psycopg2-binary>=2.9.0",
43
+ "fastapi>=0.104.0",
44
+ "python-dotenv>=1.0.0",
45
+ "tenacity>=8.2.0",
46
+ "pyarrow>=13.0.0",
47
+ ]
48
+ dev = [
49
+ "pytest>=7.0.0",
50
+ "pytest-bdd>=7.0.0",
51
+ "pytest-cov>=4.0.0",
52
+ "pytest-mock>=3.10.0",
53
+ "pytest-benchmark>=4.0.0",
54
+ "pytest-xdist>=3.0.0",
55
+ "responses>=0.23.0",
56
+ "freezegun>=1.2.0",
57
+ "hypothesis>=6.0.0",
58
+ "ruff>=0.1.0",
59
+ "vulture",
60
+ ]
61
+
62
+ [project.scripts]
63
+ stacksats-backtest = "stacksats.backtest:main"
64
+ stacksats-export = "stacksats.export_weights:main"
65
+ stacksats-plot-mvrv = "stacksats.plot_mvrv:main"
66
+ stacksats-plot-weights = "stacksats.plot_weights:main"
67
+ stacksats-validate = "stacksats.api:validate_strategy_cli"
68
+
69
+ [tool.setuptools.packages.find]
70
+ where = ["."]
71
+ include = ["stacksats", "stacksats.*"]
72
+
73
+ [tool.setuptools.package-data]
74
+ stacksats = ["py.typed"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,21 @@
1
+ """StackSats package public API."""
2
+
3
+ from .api import BacktestResult, ValidationResult, run_backtest, validate_strategy
4
+ from .loader import load_strategy
5
+ from .model_development import precompute_features
6
+ from .prelude import load_data
7
+ from .strategies.base import CallableWindowStrategy, WindowStrategy
8
+ from .strategies.mvrv import MVRVStrategy
9
+
10
+ __all__ = [
11
+ "BacktestResult",
12
+ "CallableWindowStrategy",
13
+ "MVRVStrategy",
14
+ "ValidationResult",
15
+ "WindowStrategy",
16
+ "load_strategy",
17
+ "load_data",
18
+ "precompute_features",
19
+ "run_backtest",
20
+ "validate_strategy",
21
+ ]