alpha-engine-lib 0.32.0__py3-none-any.whl

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 (40) hide show
  1. alpha_engine_lib/__init__.py +3 -0
  2. alpha_engine_lib/agent_schemas.py +663 -0
  3. alpha_engine_lib/alerts.py +576 -0
  4. alpha_engine_lib/arcticdb.py +340 -0
  5. alpha_engine_lib/collector_results.py +69 -0
  6. alpha_engine_lib/cost.py +665 -0
  7. alpha_engine_lib/dates.py +273 -0
  8. alpha_engine_lib/decision_capture.py +462 -0
  9. alpha_engine_lib/ec2_spot.py +363 -0
  10. alpha_engine_lib/email_sender.py +206 -0
  11. alpha_engine_lib/eval_artifacts.py +361 -0
  12. alpha_engine_lib/logging.py +303 -0
  13. alpha_engine_lib/model_pricing.yaml +73 -0
  14. alpha_engine_lib/pillars.py +756 -0
  15. alpha_engine_lib/pipeline_status/__init__.py +70 -0
  16. alpha_engine_lib/pipeline_status/read.py +541 -0
  17. alpha_engine_lib/pipeline_status/registry.py +368 -0
  18. alpha_engine_lib/pipeline_status/templates.py +120 -0
  19. alpha_engine_lib/preflight.py +444 -0
  20. alpha_engine_lib/rag/__init__.py +39 -0
  21. alpha_engine_lib/rag/db.py +96 -0
  22. alpha_engine_lib/rag/embeddings.py +63 -0
  23. alpha_engine_lib/rag/migrations/0001_content_tsv.sql +39 -0
  24. alpha_engine_lib/rag/rerank.py +377 -0
  25. alpha_engine_lib/rag/retrieval.py +465 -0
  26. alpha_engine_lib/rag/schema.sql +65 -0
  27. alpha_engine_lib/reconcile.py +203 -0
  28. alpha_engine_lib/secrets.py +186 -0
  29. alpha_engine_lib/sources/__init__.py +35 -0
  30. alpha_engine_lib/sources/protocols.py +227 -0
  31. alpha_engine_lib/ssm_log_capture.py +274 -0
  32. alpha_engine_lib/telegram.py +165 -0
  33. alpha_engine_lib/trading_calendar.py +236 -0
  34. alpha_engine_lib/transparency.py +746 -0
  35. alpha_engine_lib/transparency_inventory.yaml +260 -0
  36. alpha_engine_lib/universe.py +83 -0
  37. alpha_engine_lib-0.32.0.dist-info/METADATA +217 -0
  38. alpha_engine_lib-0.32.0.dist-info/RECORD +40 -0
  39. alpha_engine_lib-0.32.0.dist-info/WHEEL +5 -0
  40. alpha_engine_lib-0.32.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,260 @@
1
+ # Phase 2 → 3 transparency inventory.
2
+ #
3
+ # Each row is a decision point in the Alpha Engine pipeline that must
4
+ # emit a measurement output. The substrate health checker reads this
5
+ # file, validates that each row's expected artifact exists with the
6
+ # expected cadence and content, and emits per-row CloudWatch metrics
7
+ # the alarm layer fires off.
8
+ #
9
+ # Source of truth for the prose form of these rows is the Phase 2
10
+ # trajectory snippet at
11
+ # alpha-engine-docs/private/presentation-layer-drafts-260505/
12
+ # 01_phase_trajectory_snippet.md. When a row changes meaning (e.g. a
13
+ # new content assertion is added by a downstream PR), update both.
14
+ #
15
+ # `effective_date` is the first date a row is expected to have data.
16
+ # Rows whose instrumentation shipped recently get a forward-dated
17
+ # value so the checker treats them as not-yet-expected until the
18
+ # first relevant event populates the artifact.
19
+
20
+ version: 1
21
+
22
+ inventory:
23
+
24
+ - id: pipeline_execution
25
+ cadence: weekly
26
+ effective_date: 2026-04-01
27
+ description: >-
28
+ SF success rate ≥ 99% across Saturday + weekday + EOD pipelines,
29
+ with per-stage durations recorded.
30
+ sources:
31
+ - kind: cloudwatch
32
+ namespace: AWS/States
33
+ metric: ExecutionsSucceeded
34
+ # Validated against ExecutionsFailed for ratio. Per-state machine
35
+ # success rate computed over a 7-day trailing window.
36
+ #
37
+ # AWS/States dimension Value is the full state machine ARN, not
38
+ # just the SF name — GetMetricStatistics filters by exact
39
+ # dimension-value match, so short names return zero datapoints.
40
+ # Verified via `aws cloudwatch list-metrics --namespace AWS/States`
41
+ # 2026-05-08 after the lib v0.5.3 Period fix unmasked this drift.
42
+ dimensions:
43
+ StateMachineArn:
44
+ - arn:aws:states:us-east-1:711398986525:stateMachine:alpha-engine-saturday-pipeline
45
+ - arn:aws:states:us-east-1:711398986525:stateMachine:alpha-engine-weekday-pipeline
46
+ - arn:aws:states:us-east-1:711398986525:stateMachine:alpha-engine-eod-pipeline
47
+ window_days: 7
48
+ assert:
49
+ op: success_rate_pct_gte
50
+ value: 99
51
+
52
+ - id: agent_decisions
53
+ cadence: weekly
54
+ # First Saturday SF observation after backtester #146 (decision
55
+ # capture coverage % published from evaluator).
56
+ effective_date: 2026-05-09
57
+ description: >-
58
+ Per-call artifact: prompt version + decision-capture record + cost
59
+ telemetry + judge rubric scores. Coverage ≥ 99%.
60
+ sources:
61
+ - kind: s3_json
62
+ bucket: alpha-engine-research
63
+ # The backtester writes the per-run JSON to backtest/{date}/.
64
+ # The most recent date's artifact is the authoritative one.
65
+ key_pattern: backtest/{date}/decision_capture_coverage.json
66
+ max_age_days: 8
67
+ assert:
68
+ - path: coverage_pct
69
+ op: gte
70
+ value: 99
71
+
72
+ - id: predictor_decisions
73
+ cadence: daily
74
+ effective_date: 2026-04-01
75
+ description: >-
76
+ Per-L1-component IC + L2 IC + confidence calibration + feature
77
+ contributions.
78
+ sources:
79
+ - kind: s3_json
80
+ bucket: alpha-engine-research
81
+ key: predictor/metrics/latest.json
82
+ max_age_days: 8
83
+ assert_keys_present:
84
+ - l1_ic
85
+ - l2_ic
86
+ - confidence_calibration
87
+
88
+ - id: trade_execution_lineage
89
+ cadence: daily
90
+ # First ENTER fill after executor #138 (signal_date + prediction_date
91
+ # lineage columns shipped 2026-05-06).
92
+ effective_date: 2026-05-07
93
+ description: >-
94
+ Per-fill: entry trigger + sizing breakdown + signal_date and
95
+ prediction_date lineage columns populated on every ENTER row.
96
+ sources:
97
+ - kind: s3_csv
98
+ bucket: alpha-engine-research
99
+ key: trades/trades_full.csv
100
+ max_age_days: 4
101
+ assert_columns_present:
102
+ - signal_date
103
+ - prediction_date
104
+ - entry_trigger
105
+ assert_columns_non_null_for_rows_after:
106
+ date_column: date
107
+ rows_after: 2026-05-07
108
+ action_filter:
109
+ column: action
110
+ equals: BUY
111
+ columns:
112
+ - signal_date
113
+ - prediction_date
114
+
115
+ - id: risk_events
116
+ cadence: daily
117
+ # First veto after executor #139 (structured risk_events table
118
+ # shipped 2026-05-06).
119
+ effective_date: 2026-05-07
120
+ description: >-
121
+ Per-event log of risk decisions (veto / override / halt) with
122
+ rule + reason + value at threshold.
123
+ sources:
124
+ # The risk_events table lives inside trades.db, mirrored to S3
125
+ # at trades/trades_latest.db after each EOD reconcile. The check
126
+ # downloads the DB, queries the table, and validates schema +
127
+ # presence (no daily-row-count assertion — vetoes may not fire
128
+ # every day, the contract is "the table exists and the rule
129
+ # captures any event that happens").
130
+ - kind: sqlite_via_s3
131
+ bucket: alpha-engine-research
132
+ key: trades/trades_latest.db
133
+ max_age_days: 4
134
+ table: risk_events
135
+ assert_columns_present:
136
+ - rule
137
+ - reason
138
+ - value
139
+ - threshold
140
+
141
+ - id: pnl_attribution
142
+ cadence: daily
143
+ # First EOD reconcile after executor #140 (unattributed_residual_pct
144
+ # + 5 attribution columns shipped 2026-05-06).
145
+ effective_date: 2026-05-07
146
+ description: >-
147
+ Per-day attributed dollars (research / predictor / sizing / market)
148
+ + unattributed residual ≤ 1% of NAV.
149
+ sources:
150
+ - kind: s3_csv
151
+ bucket: alpha-engine-research
152
+ key: trades/eod_pnl.csv
153
+ max_age_days: 4
154
+ assert_columns_present:
155
+ - unattributed_residual_pct
156
+ - position_pnl_usd
157
+ - interest_usd
158
+ - dividend_usd
159
+ - unattributed_usd
160
+ assert_value_on_latest_row:
161
+ column: unattributed_residual_pct
162
+ op: lte
163
+ value: 1.0
164
+
165
+ - id: config_changes
166
+ cadence: weekly
167
+ effective_date: 2026-04-01
168
+ description: >-
169
+ Per-change diff log + rationale + subsequent-week behavioral delta
170
+ for autonomous-loop config updates (scoring weights, executor
171
+ params, predictor veto threshold, research boost params).
172
+ sources:
173
+ # Backtester optimizers write per-run change records under
174
+ # backtest/{date}/. The aggregate changelog under config/ is the
175
+ # canonical history; the per-run record is what the checker
176
+ # validates for the most-recent run.
177
+ - kind: s3_json
178
+ bucket: alpha-engine-research
179
+ key_pattern: backtest/{date}/optimizer_changes.json
180
+ max_age_days: 8
181
+ # Optional artifact — a quiet week with no config changes is
182
+ # valid; the check passes if the file exists OR if the file
183
+ # is absent AND the most recent backtest run completed (signal
184
+ # via metrics.json presence).
185
+ treat_absent_as: ok_if_companion_present
186
+ companion_key_pattern: backtest/{date}/metrics.json
187
+
188
+ - id: data_quality
189
+ cadence: daily
190
+ # data #159 stamped per-row source attribution on daily_closes
191
+ # 2026-05-05; first weekday-SF run with the column populated was
192
+ # 2026-05-06.
193
+ effective_date: 2026-05-06
194
+ description: >-
195
+ Per-row source attribution + per-feature NaN/outlier rates +
196
+ freshness on the daily_closes intermediate parquet.
197
+ sources:
198
+ - kind: s3_parquet
199
+ bucket: alpha-engine-research
200
+ key_pattern: staging/daily_closes/{date}.parquet
201
+ max_age_days: 4
202
+ # daily_closes parquet has ``ticker`` as the index (not a column)
203
+ # and uses capital-C ``Close`` for the close price. The earlier
204
+ # ``ticker`` + ``close`` entries were inventory drift — not
205
+ # producer bugs. The producer contract has been stable since
206
+ # the staging-prefix migration (data #112, 2026-04-29).
207
+ assert_columns_present:
208
+ - source
209
+ - Close
210
+ assert_column_non_null:
211
+ - source
212
+
213
+ - id: agent_quality
214
+ cadence: weekly
215
+ effective_date: 2026-04-01
216
+ description: >-
217
+ Rolling 4-week mean of LLM-as-judge rubric scores per
218
+ (judged_agent_id, criterion, judge_model) combo. The min across
219
+ all combos is the alarm-bearing metric; the substrate check
220
+ validates the metric is being emitted weekly.
221
+ sources:
222
+ - kind: cloudwatch
223
+ namespace: AlphaEngine/Eval
224
+ metric: agent_quality_score_4w_mean_min
225
+ window_days: 14
226
+ # Presence check — alarm threshold (mean < 3.0 emits SNS) lives
227
+ # in CloudWatch alarm config, not here. Substrate check just
228
+ # validates the derived metric is being emitted weekly.
229
+ assert:
230
+ op: datapoints_gte
231
+ value: 1
232
+
233
+ - id: cost_telemetry
234
+ cadence: weekly
235
+ # Per-run LLM cost telemetry workstream shipped via alpha-engine-
236
+ # research PR #73 (merged 2026-05-01). The first Saturday SF run
237
+ # that captured a ``cost.parquet`` was 2026-05-02. Consumers
238
+ # (backtester ``analysis/cost_report.detect_anomaly``) read this
239
+ # field as the floor of the rolling baseline window so pre-launch
240
+ # Saturdays are not classified as "capture-flag-off" gaps.
241
+ effective_date: 2026-05-02
242
+ description: >-
243
+ Per-Saturday LLM cost capture parquet aggregating per-call
244
+ JSONL writes. One row per agent invocation with token totals
245
+ (input / output / cache_read / cache_create) and computed
246
+ ``cost_usd``. Consumed by the evaluator's anomaly detector +
247
+ the cost report section of the Saturday SF email.
248
+ sources:
249
+ - kind: s3_parquet
250
+ bucket: alpha-engine-research
251
+ key_pattern: decision_artifacts/_cost/{date}/cost.parquet
252
+ max_age_days: 8
253
+ assert_columns_present:
254
+ - schema_version
255
+ - run_id
256
+ - agent_id
257
+ - model_name
258
+ - cost_usd
259
+ assert_column_non_null:
260
+ - cost_usd
@@ -0,0 +1,83 @@
1
+ """Universe membership filtering — canonical predicate for the
2
+ S&P 500+400 constituent check shared by research's incumbent-exit
3
+ evaluator (alpha-engine-research#41) and executor's buy-candidate
4
+ filter (alpha-engine#77).
5
+
6
+ Design context (2026-04-20): the TSM/ASML incident shipped as a
7
+ two-layer fix with two independent implementations of the same
8
+ predicate — "is ticker in current universe?". Layer 1 drops non-S&P
9
+ incumbents at the population-exit stage; Layer 2 drops non-universe
10
+ buy_candidates at the executor signal reader. The two layers sourced
11
+ the universe from different inputs (Research from in-memory
12
+ ``scanner_universe`` derived from ``constituents.json``; Executor
13
+ from ArcticDB library symbols). Independent implementations risk
14
+ silent divergence on universe drift.
15
+
16
+ This module exposes the membership-test primitive only. It stays
17
+ IO-agnostic: callers supply the universe set however their context
18
+ sources it (``constituents.json``, ArcticDB ``list_symbols()``,
19
+ fixture for tests). The lib makes the SAME predicate available to
20
+ both layers; behavioral context (exit-event emission, log shape,
21
+ caller-side metadata) stays at the call site. Divergence becomes
22
+ impossible by construction: both consumers go through one code path.
23
+ """
24
+
25
+ from __future__ import annotations
26
+
27
+ from typing import AbstractSet, Callable, Iterable, TypeVar
28
+
29
+ T = TypeVar("T")
30
+
31
+
32
+ def _default_key(item: object) -> str | None:
33
+ """Default ticker extractor — handles plain ``str`` and ``{"ticker": str}`` dicts.
34
+
35
+ Returns ``None`` for items that don't look like either shape; the
36
+ caller's partition logic treats ``None`` as "not in universe" and
37
+ routes the item to ``dropped``.
38
+ """
39
+ if isinstance(item, str):
40
+ return item
41
+ if isinstance(item, dict):
42
+ ticker = item.get("ticker")
43
+ return ticker if isinstance(ticker, str) else None
44
+ return None
45
+
46
+
47
+ def filter_to_universe(
48
+ items: Iterable[T],
49
+ universe: AbstractSet[str],
50
+ *,
51
+ key: Callable[[T], str | None] | None = None,
52
+ ) -> tuple[list[T], list[T]]:
53
+ """Partition ``items`` into ``(kept, dropped)`` by universe membership.
54
+
55
+ ``items`` may be an iterable of ticker strings, dicts with a
56
+ ``ticker`` field, or any other type when ``key`` is supplied.
57
+ The extracted ticker is checked against ``universe``; items whose
58
+ key is ``None``, empty, or returns a value not in ``universe`` go
59
+ to ``dropped``.
60
+
61
+ Returns the partition without emitting logs or exit events —
62
+ callers apply their own context-specific behavior to the dropped
63
+ list (Research emits ``UNIVERSE_DROP`` exit events; Executor logs
64
+ a warning).
65
+
66
+ The universe is a read-only ``AbstractSet[str]`` so either
67
+ ``set`` or ``frozenset`` is accepted. Membership is O(1) per item.
68
+ """
69
+ extract = key or _default_key
70
+ kept: list[T] = []
71
+ dropped: list[T] = []
72
+ for item in items:
73
+ ticker = extract(item)
74
+ if ticker and ticker in universe:
75
+ kept.append(item)
76
+ else:
77
+ dropped.append(item)
78
+ return kept, dropped
79
+
80
+
81
+ def in_universe(ticker: str | None, universe: AbstractSet[str]) -> bool:
82
+ """Predicate — ``True`` iff ``ticker`` is a non-empty string in ``universe``."""
83
+ return isinstance(ticker, str) and bool(ticker) and ticker in universe
@@ -0,0 +1,217 @@
1
+ Metadata-Version: 2.4
2
+ Name: alpha-engine-lib
3
+ Version: 0.32.0
4
+ Summary: Shared utilities for the Alpha Engine modules: preflight, structured logging with secret-redaction, ArcticDB universe access, NYSE-calendar dates + freshness predicates, decision capture, cost telemetry, RAG, agent output schemas, SSM-backed secrets, Telegram alerts + SNS fan-out, EC2 spot-launch resilience, SSM log-capture chokepoint, and Step-Functions execution-state projection. Full surface documented in README.
5
+ Author: Brian McMahon
6
+ License: Proprietary
7
+ Requires-Python: >=3.9
8
+ Description-Content-Type: text/markdown
9
+ Requires-Dist: boto3>=1.34
10
+ Requires-Dist: pydantic>=2.0
11
+ Requires-Dist: pyyaml>=6.0
12
+ Requires-Dist: requests>=2.31
13
+ Requires-Dist: eval_type_backport>=0.2.0; python_version < "3.10"
14
+ Provides-Extra: arcticdb
15
+ Requires-Dist: arcticdb>=6.11; extra == "arcticdb"
16
+ Requires-Dist: pandas>=2.0; extra == "arcticdb"
17
+ Provides-Extra: flow-doctor
18
+ Requires-Dist: flow-doctor[diagnosis,s3]<0.5.0,>=0.4.0; extra == "flow-doctor"
19
+ Provides-Extra: rag
20
+ Requires-Dist: psycopg2-binary>=2.9; extra == "rag"
21
+ Requires-Dist: pgvector>=0.2; extra == "rag"
22
+ Requires-Dist: numpy>=1.24; extra == "rag"
23
+ Provides-Extra: rerank
24
+ Requires-Dist: sentence-transformers>=3.0; extra == "rerank"
25
+ Provides-Extra: dev
26
+ Requires-Dist: pytest>=7.0; extra == "dev"
27
+ Requires-Dist: pytest-cov>=4.0; extra == "dev"
28
+ Requires-Dist: moto>=5.0; extra == "dev"
29
+
30
+ # alpha-engine-lib
31
+
32
+ > Part of [**Nous Ergon**](https://nousergon.ai) — Autonomous Multi-Agent Trading System. Repo and S3 names use the underlying project name `alpha-engine`.
33
+
34
+ [![Part of Nous Ergon](https://img.shields.io/badge/Part_of-Nous_Ergon-1a73e8?style=flat-square)](https://nousergon.ai)
35
+ [![Python](https://img.shields.io/badge/python-3.11+-blue?style=flat-square)](https://www.python.org/)
36
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow?style=flat-square)](LICENSE)
37
+ [![Phase 2 · Reliability](https://img.shields.io/badge/Phase_2-Reliability-e9c46a?style=flat-square)](https://github.com/cipher813/alpha-engine-docs#phase-trajectory)
38
+
39
+ Shared utility library used by all 6 modules of Nous Ergon. Cross-cutting concerns only — logging, freshness checks, trading-calendar arithmetic, ArcticDB helpers, agent-decision capture, LLM cost tracking. No proprietary trading logic, no model weights, no agent prompts.
40
+
41
+ The lib's job is to keep the same code from being maintained six times.
42
+
43
+ ---
44
+
45
+ ## Install
46
+
47
+ ```
48
+ # requirements.txt
49
+ alpha-engine-lib @ git+https://github.com/cipher813/alpha-engine-lib@v0.4.0
50
+ ```
51
+
52
+ Tagged releases: `v0.1.0`, `v0.2.0`, `v0.3.0`, `v0.4.0`, etc. Consumers pin to a specific tag. Breaking changes bump the minor version while Alpha Engine is in pre-1.0.
53
+
54
+ ```bash
55
+ # With optional extras
56
+ pip install "alpha-engine-lib[arcticdb] @ git+https://github.com/cipher813/alpha-engine-lib@v0.4.0"
57
+ ```
58
+
59
+ | Extra | Pulls in | When you need it |
60
+ |---|---|---|
61
+ | `[arcticdb]` | `arcticdb`, `pandas` | Anything that calls `check_arcticdb_fresh` or the ArcticDB read/write helpers |
62
+ | `[flow_doctor]` | `flow-doctor` | Logging integration that escalates ERROR-level events to flow-doctor |
63
+ | `[rag]` | `psycopg2-binary`, `pgvector`, `numpy` | The `rag` submodule — Neon pgvector RAG retrieval/ingestion |
64
+ | `[dev]` | `pytest`, lint tooling | Local development |
65
+
66
+ ## Modules
67
+
68
+ ### `logging` — structured logging + flow-doctor attach
69
+
70
+ Replaces the near-identical `log_config.py` copies that used to live in alpha-engine-data and alpha-engine-executor. Consumers call `setup_logging` once at process startup:
71
+
72
+ ```python
73
+ from alpha_engine_lib.logging import setup_logging
74
+
75
+ setup_logging("data-collector", flow_doctor_yaml="/path/to/flow-doctor.yaml")
76
+ ```
77
+
78
+ - Text mode by default; JSON via `ALPHA_ENGINE_JSON_LOGS=1`
79
+ - Flow-doctor attaches as an ERROR-level handler when `FLOW_DOCTOR_ENABLED=1` (requires `[flow_doctor]` extra)
80
+
81
+ ### `preflight` — fail-fast connectivity + freshness checks
82
+
83
+ Runs at the top of every entrypoint, before any real work starts. Primitives live on `BasePreflight`; each consumer subclasses and overrides `run()`:
84
+
85
+ ```python
86
+ from alpha_engine_lib.preflight import BasePreflight
87
+
88
+ class DataPreflight(BasePreflight):
89
+ def __init__(self, bucket, mode):
90
+ super().__init__(bucket)
91
+ self.mode = mode
92
+
93
+ def run(self):
94
+ self.check_env_vars("AWS_REGION")
95
+ if self.mode == "phase1":
96
+ self.check_env_vars("FRED_API_KEY", "POLYGON_API_KEY")
97
+ self.check_s3_bucket()
98
+ if self.mode == "daily":
99
+ self.check_arcticdb_fresh("universe", "SPY", max_stale_days=4)
100
+ ```
101
+
102
+ Failed checks raise `RuntimeError` with an explanatory message. Consumers catch nothing — the raise propagates up through `main()` → non-zero exit → Step Function `HandleFailure` → flow-doctor notification. The point is to fail before paying for any LLM calls or downstream work.
103
+
104
+ ### `arcticdb` — read/write helpers + symbol enumeration
105
+
106
+ Wrappers around the ArcticDB Python client. Standardizes the URI format, library naming, and read paths so each consumer doesn't reinvent the connection logic.
107
+
108
+ ### `dates` — trading-day arithmetic
109
+
110
+ `now_dual()` returns a `(calendar_date, trading_day)` pair following the rule `trading_day = last_closed_trading_day(now)`. Strictly backward-looking; never ahead. `session_for_timestamp(ts)` resolves any timestamp to its trading session. Used at every artifact-write site to prevent calendar/trading-day drift between modules.
111
+
112
+ ### `trading_calendar` — NYSE holiday detection
113
+
114
+ Pure-Python NYSE calendar through 2030. No `pandas-market-calendars` dependency.
115
+
116
+ ### `decision_capture` — agent decision audit logger
117
+
118
+ Captures every agent decision as a structured artifact: prompt metadata (id + version), input snapshot, agent output, and cost. Each decision becomes replayable, auditable, and attributable to a specific prompt revision. Backbone of the Phase 2 measurement substrate.
119
+
120
+ ### `cost` — LLM cost tracking
121
+
122
+ Token-aware cost computation following Anthropic's prompt-caching semantics (cache-write vs cache-read pricing). Used by every LLM call site to attach a `cost_usd` to its output.
123
+
124
+ ### `agent_schemas` — canonical LLM-output Pydantic schemas
125
+
126
+ Shared contract surface for the 14 LLM-output classes used in `with_structured_output(...)` calls across the research pipeline (sector quant + qual + peer review, macro economist + critic, held-stock thesis update, CIO, eval-judge rubric). Lives here so downstream tooling — replay harness in alpha-engine-backtester, future cheap-model-concordance signals — can validate against the canonical contract without a heavy cross-repo dep on research.
127
+
128
+ ```python
129
+ from alpha_engine_lib.agent_schemas import (
130
+ QuantAnalystOutput,
131
+ JointFinalizationOutput,
132
+ CIORawOutput,
133
+ HeldThesisUpdateLLMOutput,
134
+ resolve_schema_for_agent,
135
+ )
136
+
137
+ # Dispatch by captured agent_id (e.g. "sector_quant:technology" → QuantAnalystOutput)
138
+ schema = resolve_schema_for_agent(agent_id)
139
+ ```
140
+
141
+ `SCHEMA_BY_AGENT_ID_BASE` covers the 6 canonical agent families: `sector_quant`, `sector_qual`, `sector_peer_review`, `macro_economist`, `ic_cio`, `thesis_update`. Validators that defend observed LLM failure modes (sector-modifier clamp, JSON-string-as-list parser, `min_length=1` on CIO decisions) move with their classes.
142
+
143
+ ### `pillars` — canonical 6-pillar attractiveness scoring shapes
144
+
145
+ Pydantic shapes for the institutional / SOTA refactor of research-module composite scoring — replaces the opaque `quant_score + qual_score` two-bucket model with a canonical 6-pillar decomposition: **Quality / Value / Momentum / Growth / Stewardship / Defensiveness**. Pillar set is the AQR Style Premia / Morningstar Economic Moat / Greenblatt / Piotroski / Fama-French / Asness "QMJ" consensus.
146
+
147
+ ```python
148
+ from alpha_engine_lib.pillars import (
149
+ PILLARS,
150
+ MoatAssessment,
151
+ PillarSubscore,
152
+ QualitativePillarAssessment,
153
+ )
154
+
155
+ # Qual Analyst emits via with_structured_output(QualitativePillarAssessment).
156
+ # Each of the 6 PillarSubscore fields carries 0-100 + confidence + evidence;
157
+ # the Quality pillar additionally carries a structured MoatAssessment
158
+ # (Morningstar wide/narrow/none + 6-archetype primary moat type + trend) —
159
+ # the qualitative core of Quality, persisted per ticker for time-series
160
+ # trend tracking.
161
+ ```
162
+
163
+ Each `PillarSubscore` decomposes into optional `quant_component` (from the factor substrate) + `qual_component` (from the agent rubric) for traceability through the composite scoring layer. Catalyst is preserved as an orthogonal `catalyst_horizon_modulation: int ∈ [-20, 20]` (a horizon shift on near-term attractiveness), not a 7th pillar weight.
164
+
165
+ Origin: 2026-05-20 attractiveness-pillars-260520 plan-doc arc. Phase 1 (this module) ships the schema layer; Phases 2-7 wire it through alpha-engine-research, alpha-engine-data, alpha-engine-backtester, and alpha-engine-dashboard.
166
+
167
+ ### `rag` — semantic retrieval over SEC filings, transcripts, and theses
168
+
169
+ Neon pgvector backbone shared by `alpha-engine-research` (qual analyst's `query_filings` tool) and `alpha-engine-data` (weekly RAGIngestion step). Re-exports a small surface — `retrieve`, `ingest_document`, `document_exists`, `embed_texts`, `get_connection`, `is_available` — and ships the canonical `schema.sql` as package data.
170
+
171
+ ```python
172
+ from alpha_engine_lib.rag import retrieve
173
+
174
+ results = retrieve(
175
+ query="competitive risks and market position",
176
+ tickers=["AAPL"],
177
+ doc_types=["10-K", "10-Q", "earnings_transcript"],
178
+ top_k=8,
179
+ )
180
+ ```
181
+
182
+ Requires the `[rag]` extra. Embeddings are Voyage `voyage-3-lite` (512d); the database backend is Neon Postgres with pgvector + HNSW indexes.
183
+
184
+ ## How it's used
185
+
186
+ All six Nous Ergon module repos depend on this lib:
187
+
188
+ | Module | Repo | What it imports from here |
189
+ |---|---|---|
190
+ | Data | [`alpha-engine-data`](https://github.com/cipher813/alpha-engine-data) | `logging`, `preflight`, `arcticdb`, `dates`, `trading_calendar`, `rag` (ingestion) |
191
+ | Research | [`alpha-engine-research`](https://github.com/cipher813/alpha-engine-research) | `logging`, `decision_capture`, `cost`, `dates`, `rag` (retrieval), `agent_schemas` (canonical LLM-output contracts) |
192
+ | Predictor | [`alpha-engine-predictor`](https://github.com/cipher813/alpha-engine-predictor) | `logging`, `preflight`, `arcticdb`, `dates` |
193
+ | Executor | [`alpha-engine`](https://github.com/cipher813/alpha-engine) | `logging`, `preflight`, `arcticdb`, `dates`, `trading_calendar` |
194
+ | Backtester | [`alpha-engine-backtester`](https://github.com/cipher813/alpha-engine-backtester) | `logging`, `preflight`, `arcticdb`, `dates`, `agent_schemas` (replay-harness Pydantic validation) |
195
+ | Dashboard | [`alpha-engine-dashboard`](https://github.com/cipher813/alpha-engine-dashboard) | `logging`, `arcticdb`, `dates` |
196
+
197
+ ## Development
198
+
199
+ ```bash
200
+ git clone https://github.com/cipher813/alpha-engine-lib.git
201
+ cd alpha-engine-lib
202
+ pip install -e ".[dev,arcticdb,flow_doctor]"
203
+ pytest
204
+ ```
205
+
206
+ ## Scope discipline
207
+
208
+ This repo is intentionally narrow. Code lands here when **at least two consumers would otherwise maintain their own copy**. New modules land as their own minor release with per-consumer adoption — no lockstep updates.
209
+
210
+ Code that **does not** belong here:
211
+ - Anything tunable (scoring weights, risk thresholds, sizing parameters) → `alpha-engine-config` (private)
212
+ - Agent prompts → `alpha-engine-config` (private)
213
+ - Module-specific business logic → that module's repo
214
+
215
+ ## License
216
+
217
+ MIT — see [LICENSE](LICENSE).
@@ -0,0 +1,40 @@
1
+ alpha_engine_lib/__init__.py,sha256=KJzr-xNURx2za6VkBE7xMbDKpnNRohzYIuAzErD7fKo,94
2
+ alpha_engine_lib/agent_schemas.py,sha256=imnuRTkFNG6ONv-qtJ_HZ0GijqKMHCDPl03q2NyAQag,29033
3
+ alpha_engine_lib/alerts.py,sha256=_ne4a1lKCKsKPw7NhT3ITicdLOSoH3woiBELHC5DlUY,23635
4
+ alpha_engine_lib/arcticdb.py,sha256=KSuuhs1BPA8XLeLXwBPgFhxW3UiaIpbvImnlU_2jArQ,12906
5
+ alpha_engine_lib/collector_results.py,sha256=XsCUZ1Jz943n7j4__l4Hd79euiH3UKSeNXuXfP62EQc,2788
6
+ alpha_engine_lib/cost.py,sha256=Sj6NKVwT_8-IKSqckrRDnbr89G6co5M4DW_j1zt7E_0,26421
7
+ alpha_engine_lib/dates.py,sha256=Oyzl0JEKWNU0wPt-rHH2AhM4Wv5n8Mbat4EnD8xmw-0,10755
8
+ alpha_engine_lib/decision_capture.py,sha256=xI7kzSqMKgsawZePK3vtR76ImKym_vYrQNRrPxzYKaw,19698
9
+ alpha_engine_lib/ec2_spot.py,sha256=bg9TAY1gDEA97U2Giw4zufQhwXHkmtiVpqtUI47oqgE,12669
10
+ alpha_engine_lib/email_sender.py,sha256=cErXdEfnFAC2DeGWzhCVXePjgFhD3a2EZDKQ7VM2rBE,8303
11
+ alpha_engine_lib/eval_artifacts.py,sha256=xNL-8cWStdiZ-tQVFtc-2iBXWFtJ4iBNXpqLKXFm_Ps,14427
12
+ alpha_engine_lib/logging.py,sha256=B_x1rb8qY7YFexbAU4XJ5x99ubdpd8IAeFbjuTtHS6Y,13162
13
+ alpha_engine_lib/model_pricing.yaml,sha256=VRl7PLwogj9-33UcjPhfXvHwXHs9vksgIky4DZLJnmY,3197
14
+ alpha_engine_lib/pillars.py,sha256=dv6JghtagcxUuox_SbtmO1gATt8ZdSXMAvgZ8wak_80,31322
15
+ alpha_engine_lib/preflight.py,sha256=aoA4rWPJ5it7exV34R_tAqbjvXVReywN_7SJRrA5jrA,18817
16
+ alpha_engine_lib/reconcile.py,sha256=S1NxHeyzPaANZ0--3r6oaxbAlFJMRW7Jr8dT3mdD0aA,7823
17
+ alpha_engine_lib/secrets.py,sha256=wd-ZsrockLLmao3r6aM832JvEfs3XQAk8aX8nLvgnBM,6504
18
+ alpha_engine_lib/ssm_log_capture.py,sha256=pYxm6SjGouSWiyQrevAZXG60gsdPLd8AT6hWOZUJoSU,10631
19
+ alpha_engine_lib/telegram.py,sha256=roJDi28IcAZnk2piJwrJl0STFp4CQUjkqSMbdQ6P6uo,6383
20
+ alpha_engine_lib/trading_calendar.py,sha256=fCtghffX1-WFVP2k8lxUXzusfF-sITn8D2sy4Xe1cfY,8184
21
+ alpha_engine_lib/transparency.py,sha256=XUZ2eqFRURxnTEDCLDNJ8zFaTatHj3U4utSbfJRksZo,25551
22
+ alpha_engine_lib/transparency_inventory.yaml,sha256=dFlTHQ3Kx4Q3RPdBfM_Vu1YR7KZxIQ5etWr4hCOhc_E,9900
23
+ alpha_engine_lib/universe.py,sha256=iMIodMCXfXcnWEdw6lD14aJJVeenQlC__ublxn7J3No,3302
24
+ alpha_engine_lib/pipeline_status/__init__.py,sha256=K7SpAGvpv9X2_Qsn7Ewb6_kgKm0X1cdPZYhVbBgDEs8,2399
25
+ alpha_engine_lib/pipeline_status/read.py,sha256=qBgNE2o6giT0QEd_X8Lfdhz1S1sxLNkU33CaMQ6lSFM,21373
26
+ alpha_engine_lib/pipeline_status/registry.py,sha256=fJbSENb7IsfDfyJM218IdyVLIev6otfOx4CsemkgCsQ,15571
27
+ alpha_engine_lib/pipeline_status/templates.py,sha256=vq_ca3tYaqzGxt9UI51cE1ruN32l31u49vb9oqX_k-s,4444
28
+ alpha_engine_lib/rag/__init__.py,sha256=zdD51ny9ciWr7MM8a9VdobkdLMMSm8aVmV3P5X07xeQ,1332
29
+ alpha_engine_lib/rag/db.py,sha256=0N_08UooNIRi1KlNXGdtWks6nJevlhs7djfmFH6_jmc,3196
30
+ alpha_engine_lib/rag/embeddings.py,sha256=xY41wuUWXbDH5y9qx0qGs9De0L3Kd4sVsgAY55A7VSw,1788
31
+ alpha_engine_lib/rag/rerank.py,sha256=WOZIk82DCXWhGiqVDTMzfbnb8fXHl4hfr1SD4Zz36mo,15357
32
+ alpha_engine_lib/rag/retrieval.py,sha256=_F0-SSvM_9XrV-uXD2_DaJ2DD1XqHZCuNmJDSkflfW0,18342
33
+ alpha_engine_lib/rag/schema.sql,sha256=ob5i43ZioC6KNOg9BHm7i_9QTW9hNkglYlargiHvCAs,2786
34
+ alpha_engine_lib/rag/migrations/0001_content_tsv.sql,sha256=6gvuGyLwxTHWVdYKqix2qmBungGWlJdJqc9CJjF707o,1873
35
+ alpha_engine_lib/sources/__init__.py,sha256=HbYUliD_nS2eBFK2aTu5mruoVRbPa3O2SuD2YbiClEw,1113
36
+ alpha_engine_lib/sources/protocols.py,sha256=NklSPHkpOoz0BSSFN7PQeprULcrvmd3_CJSSPEeJC_4,8436
37
+ alpha_engine_lib-0.32.0.dist-info/METADATA,sha256=92d2yLj6N4vrEDSEKg0eGeSUTxYkZcb1Z39nth9mD5s,11478
38
+ alpha_engine_lib-0.32.0.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
39
+ alpha_engine_lib-0.32.0.dist-info/top_level.txt,sha256=eysr0xbNhj1aDUa1F9U9c36VzVTXXNqeyHrVC-gtgBw,17
40
+ alpha_engine_lib-0.32.0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (82.0.1)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1 @@
1
+ alpha_engine_lib