STRATA — Market State Framework
A trainable, stateful model architecture specialised for market trading — analogous to LSTM/GRU but built for regime estimation and decision support, not price prediction.
pip install strata-market
Quick Start — High Level (v2.4+)
from strata import StrataModel, StrataTrainer
# ── Use a pretrained model (zero setup) ──────────────────────────────────
model = StrataModel.from_pretrained("AAPL") # also: TSLA, SPY, NVDA, QQQ
result = model.predict(candles)
# {"action": "LONG", "confidence": 0.71, "regime": "TRENDING",
# "approved": True, "guard_reason": "", "state": {...}}
# ── Train your own model from OHLCV data ─────────────────────────────────
trainer = StrataTrainer(asset="MSFT")
windows = StrataTrainer.prepare_windows(my_candles) # sliding windows
model = trainer.train(windows, n_trials=100)
model.save("msft_model.json")
# ── Load and deploy anywhere ─────────────────────────────────────────────
model = StrataModel.load("msft_model.json")
result = model.predict(latest_candles)
print(result["action"]) # "LONG" / "SHORT" / "HOLD"
Quick Start — Low Level
from strata import initial_state, update_state, decide, StrataGUARD, StrataMEMORY, sense
# 1. Initialize
state = initial_state()
memory = StrataMEMORY()
guard = StrataGUARD(asset="AAPL") # optional: asset-aware guard thresholds
# 2. Per-bar update loop
candles = [...] # list of OHLCV dicts, oldest → newest, minimum 3
inp = sense(candles) # raw OHLCV → semantic signals
mem_signal = memory.snapshot() # pattern memory state
state = update_state(state, inp, mem_signal)
decision = decide(state) # {"action": "LONG"|"SHORT"|"HOLD", "confidence": ..., "regime": ...}
approved, reason = guard.evaluate(state, decision, decision["confidence"])
final_action = decision["action"] if approved else "HOLD"
print(f"{final_action} ({reason})")
StrataModel — Trainable Model
StrataModel.from_pretrained(ticker) — zero setup
model = StrataModel.from_pretrained("AAPL") # AAPL | TSLA | SPY | NVDA | QQQ
print(model.summary())
StrataTrainer — train from your own data
from strata import StrataModel, StrataTrainer
# Your candles: flat list of OHLCV dicts, oldest → newest
candles = [{"open": ..., "high": ..., "low": ..., "close": ..., "volume": ...}, ...]
# Prepare sliding windows (window_size=31 recommended)
windows = StrataTrainer.prepare_windows(candles, window_size=31)
# Train
trainer = StrataTrainer(asset="MSFT", verbose=True)
model = trainer.train(windows, n_trials=100)
# Save — share with anyone who has strata-market installed
model.save("msft_model.json")
StrataModel.load() — deploy anywhere
model = StrataModel.load("msft_model.json")
model.reset() # start fresh session
# Per-bar prediction
result = model.predict(candles_window)
# {
# "action": "LONG", # LONG | SHORT | HOLD
# "confidence": 0.71,
# "regime": "TRENDING", # TRENDING | RANGING | TRANSITIONING | CHOPPY
# "risk": "LOW", # LOW | MEDIUM | HIGH
# "approved": True, # False = GUARD blocked the action
# "guard_reason": "", # e.g. "TRAP_RISK_HIGH (0.67 > 0.60 [RANGING])"
# "state": {...}, # full internal state snapshot
# }
# Feed outcome to circuit breaker
model.record_outcome(was_loss=False)
StrataNet — PyTorch Neural Network (v2.5+)
STRATA-NET is a novel recurrent neural network architecture purpose-built for market trading — not a vanilla LSTM or GRU, but a new architecture where the hidden state directly encodes interpretable market concepts.
Hidden State Design
h = [bias, momentum, trap_risk, uncertainty] ← 4 dimensions, always interpretable
bias ∈ [-1, 1] directional conviction (negative = bearish, positive = bullish)
momentum ∈ [ 0, 1] structural energy from breakouts
trap_risk ∈ [ 0, 1] adverse selection / liquidity trap pressure
uncertainty ∈ [ 0, 1] volatility-driven ambiguity
Unlike LSTM/GRU hidden states (opaque vectors), these dimensions have enforced hard bounds and semantic meaning at every step of inference.
Architecture
Input: OHLCV window (B, T, 5)
│
▼
StrataEmbedding learned OHLCV → semantic features (replaces hand-crafted SENSE)
│
▼
StrataCoreCell ×T custom GRU-like cell with 4 structured gates
│ — update gate z, reset gate r (like GRU)
│ — but projected back to 4-dim interpretable hidden state
│ — bounds enforced per dimension every step
▼
StrataHead hidden state → LONG/SHORT/HOLD + confidence + regime
│
▼
Output: action logits (3) + confidence (1) + regime logits (4)
Quick Start
import torch
from strata import StrataNet, StrataNetConfig, StrataNetTrainer, StrataNetDataset
# ── Train from OHLCV candles (no manual labeling needed) ─────────────────
# Labels are auto-generated by the STRATA state machine (teacher-student)
dataset = StrataNetDataset.from_candles(my_candles, seq_len=30, asset="AAPL")
trainer = StrataNetTrainer(asset="AAPL")
model = trainer.train(dataset, epochs=30)
# Save as .pt — standard PyTorch format
model.save("aapl_net.pt")
# ── Load and deploy ───────────────────────────────────────────────────────
model = StrataNet.load("aapl_net.pt")
# Predict from a (30, 5) tensor of normalised OHLCV features
result = model.predict_action(x_tensor)
# {
# "action": "LONG", # LONG | SHORT | HOLD
# "confidence": 0.71,
# "regime": "TRENDING", # TRENDING | RANGING | TRANSITIONING | CHOPPY
# "state": {
# "bias": 0.89, # interpretable — always in [-1, 1]
# "momentum": 0.43, # interpretable — always in [0, 1]
# "trap_risk": 0.21, # interpretable — always in [0, 1]
# "uncertainty": 0.54, # interpretable — always in [0, 1]
# }
# }
Normalise your OHLCV before feeding to StrataNet
from strata.net_trainer import _normalise_window
window = candles[-30:] # last 30 candles
x = torch.tensor(_normalise_window(window), dtype=torch.float32) # (30, 5)
result = model.predict_action(x)
Custom config
cfg = StrataNetConfig(
asset = "TSLA",
seq_len = 60, # longer lookback for volatile assets
embed_dim = 64, # larger embedding for more complex patterns
core_expand = 32, # wider recurrent cell
head_dim = 32,
dropout = 0.15,
)
model = StrataNet(cfg)
print(model.summary())
# StrataNet v1.0
# asset : TSLA
# seq_len : 60
# hidden_dim : 4 [bias, momentum, trap_risk, uncertainty]
# parameters : ~18,000
Comparison: STRATA vs LSTM/GRU/Transformer
| LSTM / GRU | Transformer | StrataNet | |
|---|---|---|---|
| Domain | General | General | Market trading only |
| Hidden state | Opaque N-dim vector | Attention weights | 4-dim, fully interpretable |
| State bounds | None | None | Hard bounds per dimension |
| Output | Price / probability | Token / probability | LONG/SHORT/HOLD + regime |
| Label source | Future price needed | Manual labels | Auto from STRATA teacher |
| Model file | .pt |
.pt / .bin |
.pt |
| Parameters | Millions | Millions | ~5,000 (default) |
Architecture (State Machine — Classic API)
Raw OHLCV
│
▼
┌─────────┐
│ SENSE │ OHLCV → {trend, vol, liquidity_above, break_structure}
└────┬────┘
│
▼
┌─────────┐ ┌──────────┐
│ CORE │◄────│ MEMORY │ pattern bank (Short/Mid/Long layers)
└────┬────┘ └──────────┘
│
▼
┌─────────┐
│ DECIDE │ state → {action, confidence, risk, regime}
└────┬────┘
│
▼
┌─────────┐
│ GUARD │ hard-rule override (NOT learned — explicit, auditable)
└────┬────┘
│
▼
Final Action
│
▼
┌─────────┐
│ LOOP │ P&L feedback → weight adaptation (optional)
└─────────┘
Modules
strata.sense(candles) → signals
Converts a window of OHLCV candles into semantic signals.
| Signal | Range | Meaning |
|---|---|---|
trend |
[-1, 1] | Directional EMA crossover, ATR-normalized |
vol |
[0, 1] | Volatility intensity (ATR / median price) |
liquidity_above |
[0, 1] | Volume spike vs rolling average |
break_structure |
[0, 1] | Price closing beyond prior N-bar high/low |
from strata import sense
candles = [
{"open": 150.0, "high": 151.2, "low": 149.5, "close": 150.8, "volume": 1_200_000},
# ... at least 3 candles, oldest → newest
]
signals = sense(candles)
# {"trend": 0.12, "vol": 0.03, "liquidity_above": 0.15, "break_structure": 0.0}
strata.update_state(state, inp, memory) → state
Core state transition. Updates the internal state vector based on current signals and memory.
from strata import initial_state, update_state
state = initial_state() # {"bias": 0, "momentum": 0, "trap_risk": 0, "uncertainty": 0}
state = update_state(state, signals, memory_snapshot)
# {"bias": 0.08, "momentum": 0.04, "trap_risk": 0.12, "uncertainty": 0.02, "regime_score": 0.06}
State dimensions:
| Key | Range | Meaning |
|---|---|---|
bias |
[-1, 1] | Directional conviction. Positive = bullish, negative = bearish |
momentum |
[0, 1] | Structural energy from breakouts and volume |
trap_risk |
[0, 1] | Probability of adverse selection / liquidity trap |
uncertainty |
[0, 1] | Volatility-driven ambiguity in current conditions |
strata.decide(state) → decision
Produces a structured action proposal from current state.
from strata import decide
decision = decide(state)
# {"action": "LONG", "confidence": 0.62, "risk": "LOW", "regime": "TRENDING"}
Regimes: TRENDING | RANGING | TRANSITIONING | CHOPPY
strata.StrataGUARD
Hard-rule risk gate. Blocks actions that violate explicit risk constraints. Rules are regime-aware and asset-aware.
from strata import StrataGUARD
guard = StrataGUARD(asset="TSLA") # HIGH vol: relaxed min_abs_bias
guard = StrataGUARD(asset="SPY") # LOW vol ETF: relaxed max_trap_risk
guard = StrataGUARD() # no asset profile — use regime defaults
approved, reason = guard.evaluate(state, decision, decision["confidence"])
# (True, "OK")
# (False, "TRAP_RISK_HIGH (0.67 > 0.60 [RANGING])")
guard.record_outcome(was_loss=True) # drives circuit breaker
Guard rules (checked in order):
| Rule | Fires when |
|---|---|
TRAP_RISK_HIGH |
trap_risk > max_trap_risk |
LOW_CONFIDENCE |
confidence < min_confidence |
CHAOS_REGIME |
uncertainty > max_uncertainty |
NO_CONVICTION |
|bias| < min_abs_bias |
CIRCUIT_BREAKER |
consecutive_losses >= max |
strata.StrataMEMORY
Three-layer pattern memory (Short → Mid → Long). Patterns are promoted by consistency and frequency.
from strata import StrataMEMORY
memory = StrataMEMORY()
# Feed observations each bar
memory.observe("fake_breakout", score=0.75)
memory.observe("trend_strength", score=0.60)
memory.step() # advance time: promote, decay
# Use in state update
mem_signal = memory.snapshot() # {"fake_breakout": 0.71, "trend_strength": 0.58}
state = update_state(state, signals, mem_signal)
strata.StrataLOOP
Closed-loop weight adaptation based on P&L feedback. Optional — STRATA works without it.
from strata import StrataLOOP
loop = StrataLOOP()
# After each closed trade:
loop.record_outcome(state, decision["action"], pnl=+0.012)
# Get adapted weights for next update
weights = loop.weights
state = update_state(state, signals, mem_signal, weights=weights)
print(loop)
# STRATA-LOOP | updates=47 | recent_wr=61.70% | step=0.00476 | outcomes=47
Supported Assets
STRATA ships with pre-calibrated volatility profiles for common assets:
| Class | Assets | Adjustment |
|---|---|---|
| HIGH vol | TSLA, NVDA, AMD, COIN, PLTR, MSTR | min_abs_bias relaxed by -0.010 |
| MED vol | AAPL, MSFT, GOOGL, META, AMZN, NFLX | No adjustment (baseline) |
| LOW vol ETF | SPY, QQQ, IWM, DIA, VTI, GLD, TLT | max_trap_risk relaxed by +0.10 |
Pass asset="TICKER" to StrataGUARD to activate profile. Unknown tickers default to MED.
Installation
# No external dependencies beyond Python 3.9+
# Clone and run directly:
git clone <repo>
cd STRATA-FRAMEWORK-MARKET-TRADING
py -3.11 tests/test_harness.py # verify installation
Running Tests
# Core behavior (1000-step simulation)
py -3.11 tests/test_harness.py
# STRATA-LOOP weight adaptation
py -3.11 tests/test_loop.py
# Extreme scenario stress test (5 scenarios)
py -3.11 tests/test_stress.py
Running Calibration
# Single asset calibration (requires parquet data in data/raw/)
py -3.11 replay/multi_year_calibration.py --ticker AAPL --save
# Cross-asset comparison report (requires all 5 calibrations)
py -3.11 replay/comparison_report.py
# Walk-forward IS/OOS test
py -3.11 replay/walk_forward_test.py --ticker AAPL
Calibration Results (V2 Weights, 5-year data 2020–2024)
| Asset | Guard Rate | HOLD% | LONG% | SHORT% | Guard Spread |
|---|---|---|---|---|---|
| AAPL | 40.6% | 53.0% | 34.5% | 12.5% | — |
| TSLA | 37.8% | 52.9% | 36.1% | 11.0% | — |
| SPY | 39.9% | 50.6% | 36.2% | 13.2% | — |
| NVDA | 36.2% | 50.6% | 37.2% | 12.1% | — |
| QQQ | 39.3% | 49.7% | 37.4% | 12.8% | — |
| Max-min spread | 4.3% ✓ |
All assets: state drift STABLE, long memory formed, cross-year std < 2%.
Stress Test Results
| Scenario | Guard Block | LONG% | Result |
|---|---|---|---|
| Crash | 100% | 0% | ✓ SANE |
| Fake Breakout | 11.5% | 38% | ✓ SANE |
| Sideways Chop | 100% | 0% | ✓ SANE |
| Strong Trend | 9.2% | 90% | ✓ SANE |
| Slow Grind | 0.3% | 99% | ✓ SANE |
Design Philosophy
STRATA is a cognitive layer, not a trading system. It answers one question: "what kind of market are we in right now, and what constraints should that impose on action?"
Key principles:
- State, not prediction — STRATA estimates regime, not price
- Hard rules, not learned risk — guard thresholds are explicit and auditable
- Structural adaptation, not per-asset retraining — one weight set, asset profiles for adjustment
- Bounded learning — LOOP weights stay within ±0.3 of calibrated seed values
See MANIFESTO.md for the full academic/theoretical treatment.
Project Structure
strata/
├── __init__.py public API
├── sense.py OHLCV → semantic signals
├── core.py state transition engine + weights
├── memory.py 3-layer pattern memory
├── decide.py state → action proposal
├── guard.py hard-rule risk gate (regime + asset aware)
└── loop.py closed-loop weight adaptation
replay/
├── multi_year_calibration.py 5-year calibration runner
├── comparison_report.py V1 vs V2 + cross-asset report
└── walk_forward_test.py IS/OOS generalization test
tests/
├── test_harness.py core behavior checks (1000 steps)
├── test_loop.py STRATA-LOOP unit tests
└── test_stress.py 5 extreme scenario tests
data/
├── raw/ parquet OHLCV files (not included)
└── results/ calibration CSV outputs
Metadata
Release files for strata-market 2.6.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| strata_market-2.6.0-py3-none-any.whl | Python 3 | none | any | Details |
Release files / strata_market-2.6.0-py3-none-any.whl
| Download URL | strata_market-2.6.0-py3-none-any.whl |
|---|---|
| Size | 39.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
df647ae62f055399b3f3fab1f0ee944b840b7663ddba5a27aebde00d0c8c5f73
|
|
BLAKE2b-256 checksum How to use checksums |
39322ef5ac389d90910350360c17ea9aef6ae6326c88552646d2431df1277371
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.11.7
|
Security for strata-market 2.6.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.