How it works · architecture v1

Two layers.
One decision per tick.

Alpha Factory is a two-layer combinator. Layer 1 produces individual alpha signals from any recipe. Layer 2 fuses them, ranks them, and emits one actionable decision per symbol per tick. Same architecture in Python (backtest) and C++23 (live).

Layers2Signal Factory · Combinator
Fusion methods5Equal · Confidence · Voting · Max · Min
Latency · live · C++23<1 mstick-to-decision · per-symbol · lockless ring
Output3 + 1LONG / SHORT / NEUTRAL + confidence ∈ [0,1]

System overview · signal → combinator → scoreboard → portfolio

LAYER 1 · SIGNAL FACTORYLAYER 2 · COMBINATORSCOREBOARD · RANKPORTFOLIO
Indicator
rsi · macd · bb
HMM · n-gram
regime · L1
ML ensemble
classifier · L1+L2
Factor
Fama-French · L2
Combinator
5 methods · conf-weighted
eqconfvotemaxmin
Signal Scoreboard
SPYLONG · 0.81
QQQLONG · 0.74
IWMNEUT · 0.18
XLFSHORT · 0.55
GLDLONG · 0.42
Portfolio
CONSTRUCTION
INPUTS · L1/L2/L3 ─── FUSION ─── RANKING ─── EXECUTION
01 · The architecture

Two layers. By design.

Why split? Because the recipe layer and the scheduling layer change at different rates. Signals get added monthly. The combinator gets touched once a quarter. The boundary makes both safer.

Layer 1

Signal Factory

recipe

Produces individual alpha signals. One class per recipe: indicator, HMM, ML, factor. Each takes a window of data (L1 / L2 / L3) and emits a typed direction + confidence. No fusion happens here. No portfolio decisions. Just the read.

# Layer 1 — every signal implements this contract.
class AlphaSignal(Protocol):
    def name(self) -> str: ...
    def required_data(self) -> DataSpec: ...
    def emit(self, w: Window) -> SignalOut:
        # direction ∈ {-1, 0, +1}
        # confidence ∈ [0.0, 1.0]
        ...
Indicator · RSI/MACD/BBHMM · n-gram regimeML · classifier/regressorFactor · Fama-French
Layer 2

Combinator

scheduler · moat

Fuses the per-tick output of N signals into one bet per symbol. Five built-in methods. Confidence is a first-class output, not a derived quantity. The downstream Scoreboard sorts across symbols, surfacing the top conviction reads for portfolio construction.

// Layer 2 — combinator contract (Python & C++23 share the shape).
class Combinator(Protocol):
    method:    FusionMethod   # equal/conf/vote/max/min
    def fuse(self, ss: list[SignalOut]) -> FusedOut: ...
    def rank(self, all: dict[Symbol, FusedOut])
              -> Scoreboard: ...
5 methods · built-inOutput · LONG/SHORT/NEUT + confScoreboard · rankedHot-swap · method per env
02 · The fusion methods

Five methods. Same contract.

All five take the same input, a list of SignalOut structs, and emit the same shape. Method is a runtime parameter, not a code path. Hot-swap per asset class or per environment.

01 · Equal Weight

Average everyone.

f = (Σ sᵢ) / n

Every signal gets one vote. Baseline that survives any regime by refusing to over-trust any single read.

Best for New deployments where confidence calibration isn't yet validated; sanity checks against more aggressive methods.
02 · Confidence Weighted

Loud voices win.

f = Σ sᵢ·cᵢ / Σ cᵢ

Each signal's contribution scales with its own confidence. The default, and the closest analog to Medallion-style ensembles.

Best for Production deployments with calibrated confidence; the recommended default.
03 · Voting

Majority wins.

f = sign( Σ sign(sᵢ) )

Count directional votes; ignore magnitude. Robust to a single outlier signal blowing up the average.

Best for Adversarial environments, low-quality signal mixes, sanity checks for ensemble agreement.
04 · Max Confidence

Trust the loudest.

f = sₖ  where k = argmax cᵢ

Defer to whichever signal is most confident at this tick. Aggressive, and only safe when at least one signal's confidence is genuinely well calibrated.

Best for High-conviction setups (event-driven), pair with hard risk limits to bound the downside.
05 · Min Confidence

Trust the chorus.

f = sₖ  where k = argmin cᵢ

Conservative: act only when the least-sure signal still agrees with the direction. Lots of NEUT output; small but high-quality positions.

Best for Capital-preservation modes, drawdown control, regimes where you'd rather skip than take a low-quality trade.

All five are pure functions. Switching method at runtime is a one-line config change, with no recompile, no recalibration, no signal redeployment.

03 · Runtime topology

Python for the lab. C++23 for the wire.

Same combinator. Two runtimes. Backtest in Python for fast iteration and a full ecosystem of factor / data libraries. Live in C++23 for sub-millisecond fusion, lockless ring buffers, deterministic latency.

Python · backtest

The lab side.

Recipe iteration, data exploration, parameter sweeps, walk-forward validation. Loads any HDF5 / Parquet / pandas frame, supports arbitrary lookback windows, full vectorization where signals permit.

NumPy / pandas / pyarrow native
Same fuse() contract as live
Parameter sweeps · walk-forward
Notebook-first iteration
Shared · contract

The contract is the protocol.

Python and C++23 share types (SignalOut, FusedOut, Scoreboard) through a small IDL. A signal validated in the lab ships to live without a port. The combinator method is a string at runtime.

Strict IDL · zero-copy where the layout permits
Method ∈ {equal, conf, vote, max, min}
Confidence calibration shared by both runtimes
Identical output bit-for-bit on test fixtures
C++23 · live

The wire side.

Lockless ring buffers, NUMA-pinned threads, monotonic timestamps. Tick-to-decision latency under 1 ms on commodity hardware. Designed to plug into existing OEMS stacks via the StratCraft execution adapters.

std::expected · concepts · mdspan
Lockless SPSC + MPMC ring buffers
Deterministic latency · no allocations on the hot path
Plugs into OEMS via StratCraft adapters
04 · One tick · end to end

What happens when a tick arrives.

From market data to portfolio order, in under a millisecond. The combinator is the third step.

MARKET FEEDSIGNAL FACTORYCOMBINATORSCOREBOARDPORTFOLIO1 · tick · SPY @ 472.812 · 4× SignalOut {dir, conf}3 · fuse(method="conf")4 · FusedOut · LONG · 0.815 · ranked Scoreboard · 32 symbols T = 0 ────────── tick to decision ── < 1 ms ──────────── T = +1 ms
Layer 1: Signal Factory
Layer 2: Combinator (fuse + method)
Scoreboard: rank + select
Portfolio Construction: sizing & orders
05 · The numbers

Specs.

KeyValue
protocolalpha-factory · v1 · internal codename Sigma
layers2: Signal Factory (recipes) + Combinator (fusion)
signal_pack4 categories: indicator · hmm · ml · factor
data_layers3 tiers: L1 OHLCV · L2 318-factor · L3 alt-data
fusion_methodsequal · conf · vote · max · min · runtime parameter
output_shapeFusedOut { dir ∈ [-1,0,+1], conf ∈ [0,1] } · per symbol · per tick
runtimesPython (backtest · lab) · C++23 (live · production)
latency_live< 1 ms tick-to-decision · commodity hardware · NUMA-pinned
distributionStratCraft Marketplace plugin · Pro tier
executionOEMS adapter · IBKR · Alpaca · Tradier · OANDA · per-broker risk overlay
backtest_engineStratCraft LEAN-compatible runner · walk-forward built in
licensingcommercial · plugin license · source-available to Enterprise
How it works · /alpha-factory/how-it-works

Two layers.
Five methods. One decision per tick.