A canonical, decision-first terminal for SIGNAL_ONLY USDT perpetual-futures research.
Live Decision Terminal · Architecture · Decision contract · Developer onboarding · Operations
Important
WaterfallHunter is SIGNAL_ONLY. LIVE_TRADING_ENABLED=false is mandatory, and the supported runtime does not place or cancel exchange orders. Only canonical ENTRY_READY is a proactive signal state. Research rankings, lifecycle labels, replay results, execution observations, historical outcomes, and AI output are non-actionable evidence surfaces.
Caution
This repository is research software, not financial advice. entry_readiness is a versioned evidence score—not a probability, promise, or expected return.
This repository is now documented as a finalization handoff, not as a claim that every deferred production concern has been closed.
| Surface | Finalization snapshot |
|---|---|
| Production application revision | e06d874797d936dd134655b606aab5f22ea221ac |
| Release state | DEPLOYED_UNVERIFIED — post-deploy soak and current-state schema-10 DR certification remain pending (#19) |
| Database | schema 10; quick_check=ok; 0 foreign-key violations |
| Runtime | backend/frontend/watchdog/Prometheus/Grafana healthy; restart count 0; OOMKilled=false in the finalization checks |
| Backtest Lab | HMAC-backed Production bundle and authenticated replay verified operational |
| Gemini | configured model gemini-flash-lite-latest; direct provider probe succeeded; advisory-only |
| CoinGlass | optional derivatives packet UNAVAILABLE under the current provider plan (#20) |
| Telegram | credentials validated; signal delivery intentionally disabled; no cutover configured (#21) |
| Decision snapshot | 173 candidates: 108 LATE, 65 NO_TRADE, 0 ENTRY_READY, 0 FORMING, 0 ACTIVE (#22) |
| Safety | LIVE_TRADING_ENABLED=false; no live order placement |
The authoritative return point is Current Status. The latest Git main may contain documentation-only commits newer than the deployed application revision; documentation movement is not a Production deployment.
- At a glance
- Why WaterfallHunter exists
- Canonical decision contract
- System architecture
- Product surfaces
- Evidence model
- Scientific and promotion boundaries
- Repository map
- Repository governance
- Quick start with Docker Compose
- Native development
- Configuration contract
- API and health surface
- Data, schema, and recovery
- CI, release, and deployment
- Observability and incident response
- Documentation index
- Contributing
- Non-goals
- License
| Contract | Current boundary |
|---|---|
| Product | Read-only decision terminal, evidence recorder, replay, outcomes, and operational diagnostics |
| Market | Linear USDT perpetual futures |
| Direction | Short-side cascade research only |
| Actionable state | ENTRY_READY only |
| Execution | No order placement or cancellation; execution evidence is observational |
| Runtime | Docker Compose behind nginx, with bounded systemd recovery |
| Application | FastAPI backend, Next.js frontend, Python watchdog |
| Persistence | Managed SQLite schema with durable decision, outcome, replay, and notification records |
| Observability | Prometheus, Grafana, Alertmanager, structured health/readiness endpoints |
| Optional integrations | Telegram notification delivery, Gemini advisory, and additional public-data providers |
| Safety posture | Fail closed on mandatory missing, stale, contradictory, or invalid evidence |
Crypto monitoring systems often mix discovery, ranking, lifecycle, research scores, and entry timing into one ambiguous list. WaterfallHunter keeps those concerns separate:
- Discover eligible contracts and normalize market evidence.
- Bind evidence to the correct economic contract and freshness window.
- Build one canonical decision packet per symbol.
- Evaluate hard invalidators, anti-chase, timing, and weighted evidence.
- Emit one public entry decision with explicit reasons and blockers.
- Persist transitions, outcomes, replay evidence, and notification state.
- Present actionability before research detail.
The result is deliberately conservative: a high research score, an interesting lifecycle stage, or a model advisory can never silently become an entry command.
Every evaluated symbol receives exactly one public entry state:
| State | Meaning | Enter now? |
|---|---|---|
NO_TRADE |
Evidence does not support a valid setup, or a deterministic veto applies | No |
FORMING |
Evidence is developing but the canonical entry contract is incomplete | No |
ENTRY_READY |
Timing, direction, execution geometry, freshness, and mandatory checks pass | Canonical signal state |
ACTIVE |
A previously emitted entry-ready setup is now in progress | No new entry instruction |
LATE |
The move is too extended or the entry window has passed | No |
INVALIDATED |
A previously valid setup has failed an explicit invariant | No |
EXPIRED |
The decision aged beyond its valid horizon | No |
UNAVAILABLE |
Required evidence or runtime state cannot be established honestly | No |
Lifecycle is a separate context model:
WATCH → FUEL-RICH → PRE-TRIGGER → ARMED → TRIGGERED → EXHAUSTED
↘ INVALIDATED
Lifecycle TRIGGERED does not mean ENTRY_READY. An immutable entry event cannot silently disappear; later changes are recorded as explicit transitions with timestamps, reason codes, model/evidence version, and provenance.
The protected entry_policy_v1 bands are ENTRY_READY >= 78 and FORMING >= 55; lower readiness remains NO_TRADE. Anti-Chase uses a 1.2 ATR hard-extension boundary. The canonical Anti-Chase ordering recorded in Model Change Ledger is present in the deployed Production lineage: freshness and deterministic invalidators are evaluated first, and Anti-Chase only converts an otherwise FORMING, ENTRY_READY, or ACTIVE decision to LATE. Anti-Chase does not turn sub-FORMING evidence into LATE, lower either readiness threshold, or manufacture missing evidence. Genuine lifecycle EXHAUSTED remains explicitly terminal LATE, including when other blockers apply. New LATE packets record late_origin provenance while lifecycle_state continues to reflect the current evaluation.
Read the full contracts in Decision Engine, Model, and Dashboard.
flowchart LR
O["Browser / operator"] --> N["nginx public edge"]
N --> F["Next.js Decision Terminal"]
F -->|"/dashboard/api/* + SSE"| B["FastAPI backend"]
subgraph EVIDENCE["Market and evidence inputs"]
L["LBank canonical catalogue + market data"]
X["Cross-exchange CCXT evidence"]
C["CoinGlass optional derivatives evidence"]
D["DEX / on-chain optional context"]
G["Gemini optional advisory"]
end
L --> B
X --> B
C -.-> B
D -.-> B
G -.-> B
B --> S[("Managed SQLite schema 10")]
S --> H["Canonical decisions / outcomes / replay"]
H --> R["Backtest Lab — signed, read-only"]
S --> Q["Durable notification outbox"]
Q -.-> T["Telegram — disabled until release cutover"]
B --> P["Prometheus"]
P --> GR["Grafana"]
P --> A["Alertmanager"]
W["Watchdog"] --> B
W --> A
SD["systemd bounded recovery"] --> DC["Docker Compose"]
DC --> F
DC --> B
DC --> W
DC --> P
DC --> GR
DC --> A
B --> SAFE["SIGNAL_ONLY boundary"]
SAFE --> LT["LIVE_TRADING_ENABLED=false"]
Runtime topology:
browser → nginx → Next.js frontend → FastAPI backend → managed SQLite volume
↘ watchdog / Prometheus / Grafana / Alertmanager
The frontend is the public edge. The backend and stateful services remain on internal Compose networks. Container filesystems are read-only where practical, Linux capabilities are dropped, no-new-privileges is enabled, logs are bounded, and persistent state is isolated in named volumes.
The live dashboard is ordered by decision safety rather than raw rank:
- canonical counts for
ENTRY_READY,FORMING,ACTIVE, and blocked/other states; - at most three
ENTRY_READYcards; - at most six nearest
FORMINGcards; - explicit no-signal and dominant-blocker explanations;
- recent decision transitions;
- searchable, filterable, paginated all-candidates table;
- price, OI, funding, taker flow, cascade, spread, cross-exchange, freshness, anti-chase, and execution-plan context where available.
When nothing is ready, the terminal says so. It does not turn a top-ranked observational list into a trading cue.
Secondary panels are collapsed and loaded on demand. They include:
- production evidence recorder status;
- feature-equivalent replay;
- natural and imported historical outcomes;
- execution-suitability and execution-outcome observations;
- lifecycle-v2 shadow evidence;
- signal-funnel diagnostics;
- bounded Backtest Lab workflows.
These surfaces explain and validate the system; they cannot create, veto, promote, or downgrade a canonical signal.
- Telegram is notification-only. Canonical events use a durable outbox with leases, retries, rate-limit handling, dead-letter state, and a release-scoped cutover boundary.
- Gemini is optional advisory context. Missing credentials or provider failure yields
UNAVAILABLE; deterministic evaluation continues. - No local model runtime is required by the canonical architecture.
WaterfallHunter combines evidence families without pretending that every optional source is always present:
| Evidence family | Examples | Safety treatment |
|---|---|---|
| Market identity | symbol, venue, contract type, quote/settlement asset | Contract mismatch can invalidate the packet |
| Structure and timing | price behavior, breakdown geometry, extension | Drives timing and mandatory anti-chase checks |
| Derivatives | open interest, funding, crowding | Weighted evidence; freshness and provenance are explicit |
| Aggressive flow | taker imbalance, CVD-like observations | Supports or contradicts directional evidence |
| Liquidation/cascade | observed liquidation flow and cascade context | Observed and estimated evidence are labelled separately |
| Liquidity/execution | spread, depth, slippage geometry, venue constraints | Invalid geometry can block actionability |
| Cross-exchange | agreement for the same economic contract | Contradictory fresh identity/evidence can invalidate |
| Relative context | market regime and relative weakness | Contextual evidence, never a standalone command |
Missing optional evidence lowers coverage. Missing mandatory evidence produces an explicit blocker or UNAVAILABLE; it is never silently replaced with synthetic market data.
entry_readinessis a versioned readiness score, not a calibrated probability.- Deterministic fixtures and golden replay corpora are regression evidence, not live profitability evidence.
- Imported historical datasets and naturally observed production outcomes remain distinct.
- New thresholds and evidence families require provenance, replay, walk-forward/holdout evaluation, and explicit promotion evidence.
- Experimental pre-triggers remain observational and cannot place orders or bypass canonical decisions.
- Execution suitability cannot become a signal gate without its own calibrated promotion contract.
See Strict Scientific Validation, Feature-equivalent Replay, and Operational Historical Outcomes.
| Path | Responsibility |
|---|---|
backend/ |
FastAPI application, discovery, evidence normalization, decision engine, persistence, migrations, replay, outcomes, and APIs |
frontend/ |
Next.js Decision Terminal and lazily mounted research panels |
watchdog/ |
Health watcher, heartbeat, and optional alert/notification bridge |
deploy/ |
nginx, systemd, Prometheus, Grafana, and Alertmanager assets |
scripts/ |
Validation, backup, migration, replay, calibration, certification, and release tooling |
docs/ |
Canonical product, engineering, data, scientific, and operational documentation |
research/ |
Curated research inputs; generated outputs and datasets stay out of Git |
skills/waterfallhunter/ |
Repository-local engineering workflows and verification contracts |
.github/workflows/ |
Exact-SHA CI artifact construction and guarded production deployment |
The canonical repository is protected main in cavack/WFH-ORG. Required CI checks are strict, linear history is enforced, force pushes/deletion are blocked, review conversations must be resolved, and Production deployment is an explicit exact-SHA action rather than a side effect of push.
GitHub Actions reaches Production through a dedicated SSH identity stored in the production Environment. The Production host uses authenticated HTTPS/gh for normal repository operations and has a repository-scoped read-only SSH fallback for fetch continuity. Runtime recovery is layered across systemd boot assertion, Docker restart: unless-stopped, and the bounded one-minute health-recovery timer.
See Repository Governance, Security Policy, Contributing, and Support.
- Git
- Docker Engine with Compose v2
- Enough local resources to build the backend, frontend, and watchdog images
git clone https://github.com/cavack/WFH-ORG.git
cd WFH-ORG
cp .env.example .env
# Validate the resolved configuration before starting anything.
docker compose config --quiet
# Build the backend image, then bootstrap the managed SQLite schema
# in the persistent waterfall_data volume before runtime startup.
docker compose build waterfall-backend
docker compose run --rm \
-e SOURCE_REVISION="$(git rev-parse HEAD)" \
waterfall-backend sh -ec '
python -m waterfallhunter.migrate_database \
--db-path "$REGISTRY_DB_PATH" \
--apply \
--source-revision "$SOURCE_REVISION"
'
# Build the remaining images and start the local SIGNAL_ONLY stack.
docker compose up --build -d
docker compose psLocal interfaces bind to loopback by default:
| Surface | URL |
|---|---|
| Decision Terminal | http://127.0.0.1:3000/dashboard/ |
| Grafana | http://127.0.0.1:3001/ |
Stop containers without deleting persistent state:
docker compose downWarning
Do not use docker compose down -v against a stack whose SQLite volume matters. The -v option removes named volumes and can destroy the only local database copy.
Canonical runtimes are recorded in .github/runtime-versions.json: Python 3.13 and Node.js 26. make setup refuses to build a virtualenv from a different Python; pass PYTHON=python3.13 when python3 is not the canonical runtime.
make setup
make validateIndividual developer commands:
make test
make typecheck
make buildA partial direct sequence for backend/frontend tests and build is:
python -m pip install --only-binary=:all: --require-hashes -r backend/requirements.lock
PYTHONPATH=backend/src:. pytest -q backend/tests
npm --prefix frontend ci
npm --prefix frontend run test:contract
npm --prefix frontend run typecheck
npm --prefix frontend run buildThe release-candidate validator requires a clean committed SHA. It exports that exact revision, validates Compose, builds the production image family, executes backend tests inside the built backend image, applies migrations to a throwaway SQLite database, and verifies OCI revision labels. It never starts Production or mounts the Production database.
./scripts/validate_clean_install.shCopy .env.example for local development. Never commit the resulting .env.
| Variable | Default | Contract |
|---|---|---|
LIVE_TRADING_ENABLED |
false |
Mandatory invariant; the supported runtime is signal-only |
REGISTRY_DB_PATH |
/app/data/waterfall_registry.db |
Managed SQLite database path inside the backend container |
EXPERIMENTAL_PRETRIGGER_ENABLED |
false |
Observational discovery only; never order execution |
LBANK_EXECUTION_SHADOW_ENABLED |
false in .env.example |
Read-only execution observation; Compose may explicitly enable the worker |
TELEGRAM_SIGNAL_DELIVERY_ENABLED |
false |
Requires credentials and a release-scoped cutover timestamp |
GEMINI_API_KEY |
empty | Optional advisory provider; absence does not break deterministic evaluation |
COINGLASS_API_KEY |
empty | Optional external evidence provider |
DEXSCREENER_ENABLED |
false |
Optional contextual discovery path |
BACKTEST_ARTIFACT_HMAC_KEY |
empty | Optional signing key for bounded backtest artifacts |
Provider credentials, chat identifiers, production environment files, database files, evidence packets, logs, backups, and generated research datasets must never be committed.
Common backend routes:
| Route | Purpose |
|---|---|
GET /livez |
Process liveness only |
GET /readyz |
Scanner, hunter, database, and runtime-progress readiness |
GET /healthz |
Readiness-compatible health alias |
GET /api/health |
Structured application health snapshot |
GET /api/candidates |
Canonical dashboard snapshot |
GET /api/stream |
Server-Sent Events dashboard stream with replay support |
GET /api/recent-signals |
Durable recent canonical signal history |
GET /api/notification-delivery |
Durable notification/outbox health |
GET /api/production-evidence |
Recorder and production-evidence report |
GET /api/feature-replay |
Feature-equivalent replay report |
GET /api/historical-outcomes |
Historical-outcome datasets and summaries |
GET /api/execution-suitability |
Read-only execution-suitability report |
GET /api/execution-outcome-validation |
Execution-observation validation report |
GET /api/lifecycle-v2-shadow |
Lifecycle-v2 shadow evidence |
GET /metrics |
Prometheus metrics |
When accessed through the public Next.js frontend, API paths are exposed under the dashboard base path—for example, /dashboard/api/health. Research endpoints are requested only when their corresponding UI section is opened.
- The application database lives in the
waterfall_datavolume, not in Git. - Schema ownership is migration-based; the current migration chain lives under
backend/src/waterfallhunter/migrations/. - Runtime startup fails closed on unsupported or inconsistent schema state.
- A production migration requires a certified backup, preflight, isolated rehearsal, and rollback evidence.
- Restore is always performed into a new file or volume first. The only good backup is never overwritten.
- SQLite backup equality is established through integrity and logical-content evidence, not by assuming raw online-backup bytes must match.
- A bounded recovery set normally retains two certified backups, including a valid pre-migration recovery point until post-cutover certification completes.
Read Data and Database, Backup and Restore, and the Deployment Certification Runbook before any schema, cutover, cleanup, or restore operation.
The CI workflow runs:
- locked Python installation and the backend test suite;
- WaterfallHunter skill and runtime-parity validation;
- frontend contract tests, typechecking, and production build;
- Python and npm dependency audits;
- Compose validation and production image builds;
- backend tests and migration smoke tests inside the exact backend artifact;
- OCI revision-label verification;
- repository hygiene and credential-pattern checks;
- upload of the exact built, digest-recorded, revision-labelled backend/frontend/watchdog image bundle; the backend artifact is additionally exercised by backend tests and migration smoke.
Production deployment is deliberately separate from an ordinary push:
protected main
→ exact-SHA CI
→ backup / migration / rollback / recovery gates
→ explicit workflow_dispatch with deploy_production=true
→ repeated required checks
→ exact CI-built, digest-recorded artifact bundle
→ guarded host deployment
→ health, schema, safety, and OCI revision certification
Pull requests do not receive production credentials. A push to main runs CI but does not deploy. Rollback is allowed only when schema compatibility is proven; otherwise the runtime is quarantined and recovery evidence is preserved.
See Deployment, Operations, and Automatic Production Deployment.
/livezanswers only whether the process is alive.- readiness endpoints include scanner catalogue freshness, hunter progress, database readiness, and read-only execution-shadow progress.
- Prometheus records candidate states, evidence quality, cycle progress, notification health, and service metrics.
- Grafana provides dashboards; Alertmanager and the watchdog provide bounded health alerting.
- Container logs use bounded JSON-file rotation.
- systemd asserts the canonical Compose stack after boot and uses bounded recovery rather than unlimited restart loops.
Healthy endpoints do not by themselves prove decision correctness, backup validity, schema compatibility, or release readiness. Those are separate evidence gates.
| Topic | Canonical document |
|---|---|
| Current production/finalization status | Current Status |
| New developer or AI-session handoff | Project Handoff |
| Runtime topology and data flow | Architecture |
| Market and evidence rules | Model |
| Entry states and readiness | Decision Engine |
| Dashboard information architecture | Dashboard |
| SQLite ownership and schema lineage | Data and Database |
| Local setup | Developer Onboarding |
| Runtime operations | Operations |
| Production release | Deployment |
| Recovery | Backup and Restore |
| Notification boundary | Telegram |
| Advisory boundary | AI Advisory |
| Common failures | Troubleshooting |
| Program sequencing | Dependency Graph |
| Model and decision changes | Model Change Ledger |
| Repository controls and trust paths | Repository Governance |
- Start from current
mainin a short-lived branch or isolated worktree. - Keep changes narrow and add focused regression coverage for behavior changes.
- Preserve
SIGNAL_ONLY, canonical state semantics, and fail-closed data handling. - Use migration and backup/rehearsal coverage for persistent-schema changes.
- Run
make validate; run./scripts/validate_clean_install.shfor a clean release-candidate commit. - Open a reviewed pull request and require exact-head CI before merge.
Read CONTRIBUTING.md, SECURITY.md, CODE_OF_CONDUCT.md, and SUPPORT.md before submitting changes, requesting support, or reporting a vulnerability.
The supported runtime intentionally does not provide:
- exchange order placement, cancellation, or account management;
- automatic threshold promotion from replay or historical results;
- a claim that readiness is a calibrated probability;
- synthetic fallback market data when required evidence is missing;
- AI authority over canonical decisions;
- unreviewed push-to-production deployment;
- destructive database cleanup without certified recovery evidence.
Copyright © 2026 cavack. All rights reserved.
The source is publicly viewable for inspection and collaboration, but no permission is granted to copy, modify, distribute, sublicense, sell, or use the software or substantial portions of it without prior written permission from the copyright holder. See LICENSE for the controlling terms.