StackSats, developed by Hypertrial, is a Python package for strategy-first Bitcoin DCA ("stacking sats") research and execution.
Learn more at www.stackingsats.org.
Start with the docs at docs/framework.md. It is the canonical framework contract and the best first read before using StackSats.
For the full docs index, see docs/index.md.
Hosted docs site: https://hypertrial.github.io/stacksats/.
- The framework owns budget math, iteration, feasibility clipping, and lock semantics.
- Users own features, signals, hyperparameters, and daily intent.
- Strategy hooks support either day-level intent (
propose_weight(state)) or batch intent (build_target_profile(...)). - The same sealed allocation kernel runs in local, backtest, and production.
See docs/framework.md for the canonical contract.
pip install stacksatsFor local development:
pip install -e .
pip install -r requirements-dev.txtOptional deploy extras:
pip install "stacksats[deploy]"Create my_strategy.py:
import pandas as pd
from stacksats import BaseStrategy, StrategyContext, TargetProfile
class MyStrategy(BaseStrategy):
strategy_id = "my-strategy"
version = "1.0.0"
description = "Example user strategy."
def transform_features(self, ctx: StrategyContext) -> pd.DataFrame:
return ctx.features_df.loc[ctx.start_date : ctx.end_date].copy()
def build_signals(
self, ctx: StrategyContext, features_df: pd.DataFrame
) -> dict[str, pd.Series]:
del ctx
value_signal = -features_df["mvrv_zscore"].clip(-4, 4)
trend_signal = -features_df["price_vs_ma"].clip(-1, 1)
return {"value": value_signal, "trend": trend_signal}
def build_target_profile(
self,
ctx: StrategyContext,
features_df: pd.DataFrame,
signals: dict[str, pd.Series],
) -> TargetProfile:
del ctx, features_df
preference = (0.7 * signals["value"]) + (0.3 * signals["trend"])
return TargetProfile(values=preference, mode="preference")
# Optional alternative hook:
# def propose_weight(self, state) -> float:
# return state.uniform_weight
if __name__ == "__main__":
strategy = MyStrategy()
validation = strategy.validate()
print(validation.summary())
result = strategy.backtest()
print(result.summary())
result.plot(output_dir="output")
result.to_json("output/backtest_result.json")Run it:
python my_strategy.pystacksats strategy validate --strategy my_strategy.py:MyStrategy
stacksats strategy backtest --strategy my_strategy.py:MyStrategy --output-dir output
stacksats strategy export --strategy my_strategy.py:MyStrategy --output-dir outputArtifacts are written to:
output/<strategy_id>/<version>/<run_id>/
Top-level exports:
BaseStrategy,StrategyContext,DayState,TargetProfileBacktestConfig,ValidationConfig,ExportConfigStrategyArtifactSetStrategyTimeSeries,StrategyTimeSeriesBatchBacktestResult,ValidationResultload_strategy(),load_data(),precompute_features()MVRVStrategy
pytest tests/ -v
ruff check .
bash scripts/check_docs_refs.shFor command examples using the packaged strategy template, see docs/commands.md.