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.
- alpha_engine_lib/__init__.py +3 -0
- alpha_engine_lib/agent_schemas.py +663 -0
- alpha_engine_lib/alerts.py +576 -0
- alpha_engine_lib/arcticdb.py +340 -0
- alpha_engine_lib/collector_results.py +69 -0
- alpha_engine_lib/cost.py +665 -0
- alpha_engine_lib/dates.py +273 -0
- alpha_engine_lib/decision_capture.py +462 -0
- alpha_engine_lib/ec2_spot.py +363 -0
- alpha_engine_lib/email_sender.py +206 -0
- alpha_engine_lib/eval_artifacts.py +361 -0
- alpha_engine_lib/logging.py +303 -0
- alpha_engine_lib/model_pricing.yaml +73 -0
- alpha_engine_lib/pillars.py +756 -0
- alpha_engine_lib/pipeline_status/__init__.py +70 -0
- alpha_engine_lib/pipeline_status/read.py +541 -0
- alpha_engine_lib/pipeline_status/registry.py +368 -0
- alpha_engine_lib/pipeline_status/templates.py +120 -0
- alpha_engine_lib/preflight.py +444 -0
- alpha_engine_lib/rag/__init__.py +39 -0
- alpha_engine_lib/rag/db.py +96 -0
- alpha_engine_lib/rag/embeddings.py +63 -0
- alpha_engine_lib/rag/migrations/0001_content_tsv.sql +39 -0
- alpha_engine_lib/rag/rerank.py +377 -0
- alpha_engine_lib/rag/retrieval.py +465 -0
- alpha_engine_lib/rag/schema.sql +65 -0
- alpha_engine_lib/reconcile.py +203 -0
- alpha_engine_lib/secrets.py +186 -0
- alpha_engine_lib/sources/__init__.py +35 -0
- alpha_engine_lib/sources/protocols.py +227 -0
- alpha_engine_lib/ssm_log_capture.py +274 -0
- alpha_engine_lib/telegram.py +165 -0
- alpha_engine_lib/trading_calendar.py +236 -0
- alpha_engine_lib/transparency.py +746 -0
- alpha_engine_lib/transparency_inventory.yaml +260 -0
- alpha_engine_lib/universe.py +83 -0
- alpha_engine_lib-0.32.0.dist-info/METADATA +217 -0
- alpha_engine_lib-0.32.0.dist-info/RECORD +40 -0
- alpha_engine_lib-0.32.0.dist-info/WHEEL +5 -0
- 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
|
+
[](https://nousergon.ai)
|
|
35
|
+
[](https://www.python.org/)
|
|
36
|
+
[](LICENSE)
|
|
37
|
+
[](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 @@
|
|
|
1
|
+
alpha_engine_lib
|