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,273 @@
|
|
|
1
|
+
"""
|
|
2
|
+
dates.py — canonical "current date" attribution + freshness checks for
|
|
3
|
+
trade-related artifacts.
|
|
4
|
+
|
|
5
|
+
Implements the dual-tracking convention from
|
|
6
|
+
``alpha-engine-docs/private/DATE_CONVENTIONS.md``: every trade-related
|
|
7
|
+
artifact records both a ``calendar_date`` (wall-clock UTC) and a
|
|
8
|
+
``trading_day`` (last completed NYSE session). The ``trading_day``
|
|
9
|
+
attribution is strictly backward-looking — never ahead of "now" — so
|
|
10
|
+
artifacts produced on weekends, holidays, or pre-open weekday mornings
|
|
11
|
+
attribute to the most recent session that has actually closed.
|
|
12
|
+
|
|
13
|
+
Use this at every artifact-write site::
|
|
14
|
+
|
|
15
|
+
from alpha_engine_lib.dates import now_dual
|
|
16
|
+
|
|
17
|
+
dd = now_dual()
|
|
18
|
+
record = {
|
|
19
|
+
"calendar_date": dd.calendar_date,
|
|
20
|
+
"trading_day": dd.trading_day,
|
|
21
|
+
...
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
For backfilling historical rows that only have a wall-clock timestamp::
|
|
25
|
+
|
|
26
|
+
from alpha_engine_lib.dates import session_for_timestamp
|
|
27
|
+
|
|
28
|
+
trading_day = session_for_timestamp(row["created_at"])
|
|
29
|
+
|
|
30
|
+
For freshness checks across the system, use the trading-day-aware helpers
|
|
31
|
+
rather than calendar-day arithmetic::
|
|
32
|
+
|
|
33
|
+
from alpha_engine_lib.dates import is_fresh_in_trading_days
|
|
34
|
+
|
|
35
|
+
# Producer-side postflight: did macro.SPY land the most recent close?
|
|
36
|
+
if not is_fresh_in_trading_days(spy_last_date, run_date):
|
|
37
|
+
raise PostflightError(...)
|
|
38
|
+
|
|
39
|
+
# Consumer-side preflight: was the data refreshed within ≤1 trading day?
|
|
40
|
+
if not is_fresh_in_trading_days(ticker_last_date, today, max_stale=1):
|
|
41
|
+
raise PreflightError(...)
|
|
42
|
+
|
|
43
|
+
The freshness helpers replace the calendar-day-arithmetic patterns that bit
|
|
44
|
+
the 2026-05-24 SF recovery — every post-Saturday redrive trips a calendar-
|
|
45
|
+
day gate even when the data carries the most recent NYSE close. Calendar
|
|
46
|
+
days only happen to work on Saturday because Fri→Sat is +1 in both calendar
|
|
47
|
+
and trading-day arithmetic. See [[feedback_lift_invariants_to_chokepoint
|
|
48
|
+
_after_second_recurrence]] + [[feedback_sota_institutional_default_no_shortcuts]].
|
|
49
|
+
|
|
50
|
+
This module is a thin wrapper over
|
|
51
|
+
``alpha_engine_lib.trading_calendar.{last_closed_trading_day,count_trading_days}``
|
|
52
|
+
— its purpose is to standardize the *output shape* (DualDate) and provide a
|
|
53
|
+
single canonical entry point so every consumer sees the same semantics.
|
|
54
|
+
"""
|
|
55
|
+
|
|
56
|
+
from __future__ import annotations
|
|
57
|
+
|
|
58
|
+
from dataclasses import dataclass
|
|
59
|
+
from datetime import date, datetime, time, timezone
|
|
60
|
+
|
|
61
|
+
from .trading_calendar import count_trading_days, last_closed_trading_day
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
@dataclass(frozen=True)
|
|
65
|
+
class DualDate:
|
|
66
|
+
"""Calendar + trading_day attribution for a moment in time.
|
|
67
|
+
|
|
68
|
+
Both fields are ISO ``yyyy-mm-dd`` strings — easy to serialize across
|
|
69
|
+
JSON / SQLite / parquet boundaries with no timezone ambiguity.
|
|
70
|
+
|
|
71
|
+
Attributes:
|
|
72
|
+
calendar_date: wall-clock UTC date when the artifact was produced.
|
|
73
|
+
Audit trail. Same on holidays/weekends as any other day; reflects
|
|
74
|
+
*when* the process ran, not which session the data is about.
|
|
75
|
+
trading_day: last NYSE trading session whose 4:00 PM ET close has
|
|
76
|
+
occurred at or before the given moment. Strictly backward-looking;
|
|
77
|
+
equals ``last_closed_trading_day(now)``. Never ahead of "now".
|
|
78
|
+
|
|
79
|
+
Example::
|
|
80
|
+
|
|
81
|
+
>>> from datetime import datetime, timezone
|
|
82
|
+
>>> from alpha_engine_lib.dates import now_dual
|
|
83
|
+
>>> sat = datetime(2026, 4, 25, 0, 0, tzinfo=timezone.utc)
|
|
84
|
+
>>> dd = now_dual(now=sat)
|
|
85
|
+
>>> dd.calendar_date
|
|
86
|
+
'2026-04-25'
|
|
87
|
+
>>> dd.trading_day # Sat isn't a session; walk back to Fri
|
|
88
|
+
'2026-04-24'
|
|
89
|
+
"""
|
|
90
|
+
|
|
91
|
+
calendar_date: str
|
|
92
|
+
trading_day: str
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def now_dual(*, now: datetime | None = None) -> DualDate:
|
|
96
|
+
"""Canonical current-date attribution for the alpha-engine system.
|
|
97
|
+
|
|
98
|
+
Every artifact-write site should call this to populate the
|
|
99
|
+
``calendar_date`` and ``trading_day`` columns/fields, rather than
|
|
100
|
+
reaching for ``date.today()`` or ``datetime.now().date()``. Calling
|
|
101
|
+
here ensures consistent semantics across modules and prevents the
|
|
102
|
+
drift that motivated the convention (see
|
|
103
|
+
``alpha-engine-docs/private/DATE_CONVENTIONS.md``).
|
|
104
|
+
|
|
105
|
+
Args:
|
|
106
|
+
now: timezone-aware datetime. Defaults to current UTC time.
|
|
107
|
+
Naive datetimes are interpreted as UTC for ``calendar_date``
|
|
108
|
+
and forwarded to ``last_closed_trading_day`` (which itself
|
|
109
|
+
assumes NYSE-local for naive inputs — this is intentional;
|
|
110
|
+
the helper hides the conversion).
|
|
111
|
+
|
|
112
|
+
Returns:
|
|
113
|
+
DualDate where ``calendar_date`` is the UTC date of ``now`` and
|
|
114
|
+
``trading_day`` is the last NYSE session that has fully closed at
|
|
115
|
+
or before ``now``.
|
|
116
|
+
"""
|
|
117
|
+
if now is None:
|
|
118
|
+
now = datetime.now(timezone.utc)
|
|
119
|
+
elif now.tzinfo is None:
|
|
120
|
+
now = now.replace(tzinfo=timezone.utc)
|
|
121
|
+
|
|
122
|
+
cal_utc = now.astimezone(timezone.utc).date()
|
|
123
|
+
td = last_closed_trading_day(now)
|
|
124
|
+
|
|
125
|
+
return DualDate(
|
|
126
|
+
calendar_date=cal_utc.isoformat(),
|
|
127
|
+
trading_day=td.isoformat(),
|
|
128
|
+
)
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
# ── Freshness checks (trading-day-aware) ─────────────────────────────────────
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
def expected_last_close(run_date: date | str) -> date:
|
|
135
|
+
"""The most recent NYSE close that exists as of ``run_date``.
|
|
136
|
+
|
|
137
|
+
For Saturday/Sunday/holiday-Monday → the prior Friday (or earlier if a
|
|
138
|
+
holiday-adjacent week). For trading days → the same date (the day's close
|
|
139
|
+
has settled, anchored at end-of-day for the purpose of staleness checks).
|
|
140
|
+
|
|
141
|
+
This is the canonical reference point for "what's the freshest data we
|
|
142
|
+
could expect to see at this run_date?" — used by every producer-side
|
|
143
|
+
postflight + consumer-side preflight in the system.
|
|
144
|
+
|
|
145
|
+
Args:
|
|
146
|
+
run_date: ISO ``yyyy-mm-dd`` string OR a ``datetime.date``.
|
|
147
|
+
|
|
148
|
+
Returns:
|
|
149
|
+
The expected last-closed NYSE session date as a ``datetime.date``.
|
|
150
|
+
|
|
151
|
+
Example::
|
|
152
|
+
|
|
153
|
+
>>> from datetime import date
|
|
154
|
+
>>> expected_last_close(date(2026, 5, 24)) # Sunday
|
|
155
|
+
datetime.date(2026, 5, 22)
|
|
156
|
+
>>> expected_last_close("2026-05-25") # Memorial Day (Mon)
|
|
157
|
+
datetime.date(2026, 5, 22)
|
|
158
|
+
>>> expected_last_close(date(2026, 5, 26)) # Tuesday after Memorial Day
|
|
159
|
+
datetime.date(2026, 5, 26)
|
|
160
|
+
"""
|
|
161
|
+
if isinstance(run_date, str):
|
|
162
|
+
run_date = datetime.strptime(run_date, "%Y-%m-%d").date()
|
|
163
|
+
# Anchor at 23:00 UTC of run_date so the resolver sees that day's NYSE
|
|
164
|
+
# close as settled if run_date is itself a trading day. (NYSE close is
|
|
165
|
+
# 4 PM ET = 20-21 UTC depending on DST; 23 UTC is unambiguously after.)
|
|
166
|
+
anchor = datetime.combine(run_date, time(23, 0), tzinfo=timezone.utc)
|
|
167
|
+
return last_closed_trading_day(anchor)
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
def trading_days_stale(last_date: date, reference: date | str) -> int:
|
|
171
|
+
"""Number of NYSE trading sessions ``last_date`` is behind ``reference``.
|
|
172
|
+
|
|
173
|
+
Returns 0 when ``last_date`` is at or ahead of the reference's expected
|
|
174
|
+
last-closed trading day. Holiday-aware (NYSE calendar, not US Federal).
|
|
175
|
+
|
|
176
|
+
Semantically the canonical staleness metric for any "is this artifact
|
|
177
|
+
carrying the most recent close that exists?" check across the system.
|
|
178
|
+
Replaces the calendar-day arithmetic (``(reference - last_date).days``)
|
|
179
|
+
that breaks on every non-Saturday redrive.
|
|
180
|
+
|
|
181
|
+
Args:
|
|
182
|
+
last_date: the artifact's stored last_date (``datetime.date``).
|
|
183
|
+
reference: ISO ``yyyy-mm-dd`` string OR ``datetime.date`` — the
|
|
184
|
+
run_date or "today" against which freshness is being asked.
|
|
185
|
+
|
|
186
|
+
Returns:
|
|
187
|
+
Integer count of NYSE sessions in
|
|
188
|
+
``(last_date, expected_last_close(reference)]``. Zero means
|
|
189
|
+
"carries the most recent available close." Positive means
|
|
190
|
+
"missed N sessions."
|
|
191
|
+
|
|
192
|
+
Example::
|
|
193
|
+
|
|
194
|
+
>>> from datetime import date
|
|
195
|
+
>>> trading_days_stale(date(2026, 5, 22), date(2026, 5, 24)) # Fri vs Sun
|
|
196
|
+
0
|
|
197
|
+
>>> trading_days_stale(date(2026, 5, 22), date(2026, 5, 25)) # Fri vs Memorial-Mon
|
|
198
|
+
0
|
|
199
|
+
>>> trading_days_stale(date(2026, 5, 22), date(2026, 5, 26)) # Fri vs Tue close
|
|
200
|
+
1
|
|
201
|
+
>>> trading_days_stale(date(2026, 5, 13), date(2026, 5, 22)) # Wed 5/13 vs Fri 5/22
|
|
202
|
+
7
|
|
203
|
+
"""
|
|
204
|
+
expected = expected_last_close(reference)
|
|
205
|
+
if last_date >= expected:
|
|
206
|
+
return 0
|
|
207
|
+
return count_trading_days(last_date, expected)
|
|
208
|
+
|
|
209
|
+
|
|
210
|
+
def is_fresh_in_trading_days(
|
|
211
|
+
last_date: date,
|
|
212
|
+
reference: date | str,
|
|
213
|
+
*,
|
|
214
|
+
max_stale: int = 0,
|
|
215
|
+
) -> bool:
|
|
216
|
+
"""Canonical freshness predicate: is ``last_date`` ≤ ``max_stale`` trading days behind ``reference``?
|
|
217
|
+
|
|
218
|
+
Default ``max_stale=0`` means "must carry the most recent NYSE close that
|
|
219
|
+
exists as of reference" — the strictest gate, used by producer-side
|
|
220
|
+
postflights where the producer just wrote and should be current.
|
|
221
|
+
``max_stale=1`` tolerates one missing session — used by consumer-side
|
|
222
|
+
preflights that need to survive the T+1 latency of polygon's daily
|
|
223
|
+
aggregate publish.
|
|
224
|
+
|
|
225
|
+
Args:
|
|
226
|
+
last_date: artifact's stored last_date.
|
|
227
|
+
reference: run_date the freshness is being asked at.
|
|
228
|
+
max_stale: max permitted trading-day lag. Keyword-only to force
|
|
229
|
+
explicit semantics at every call site.
|
|
230
|
+
|
|
231
|
+
Returns:
|
|
232
|
+
``True`` iff the artifact carries data within ``max_stale`` trading
|
|
233
|
+
days of the most recent NYSE close that exists as of ``reference``.
|
|
234
|
+
|
|
235
|
+
Example::
|
|
236
|
+
|
|
237
|
+
>>> from datetime import date
|
|
238
|
+
>>> is_fresh_in_trading_days(date(2026, 5, 22), date(2026, 5, 24)) # Fri vs Sun
|
|
239
|
+
True
|
|
240
|
+
>>> is_fresh_in_trading_days(date(2026, 5, 13), date(2026, 5, 22)) # 7-session lag
|
|
241
|
+
False
|
|
242
|
+
>>> is_fresh_in_trading_days(date(2026, 5, 13), date(2026, 5, 22), max_stale=10)
|
|
243
|
+
True
|
|
244
|
+
"""
|
|
245
|
+
return trading_days_stale(last_date, reference) <= max_stale
|
|
246
|
+
|
|
247
|
+
|
|
248
|
+
def session_for_timestamp(ts: datetime) -> str:
|
|
249
|
+
"""Trading day a timestamp belongs to under the dual-tracking convention.
|
|
250
|
+
|
|
251
|
+
Backward-looking: returns the most recent NYSE trading session whose
|
|
252
|
+
4:00 PM ET close has occurred at or before ``ts``. Used to backfill the
|
|
253
|
+
``trading_day`` column on historical rows that only have a wall-clock
|
|
254
|
+
timestamp (``created_at``, ``fill_time``, etc.).
|
|
255
|
+
|
|
256
|
+
Args:
|
|
257
|
+
ts: timezone-aware datetime. Naive timestamps are assumed UTC.
|
|
258
|
+
|
|
259
|
+
Returns:
|
|
260
|
+
ISO ``yyyy-mm-dd`` string of the trading day.
|
|
261
|
+
|
|
262
|
+
Example::
|
|
263
|
+
|
|
264
|
+
>>> from datetime import datetime
|
|
265
|
+
>>> from zoneinfo import ZoneInfo
|
|
266
|
+
>>> # Mon 9 AM ET — session not yet closed
|
|
267
|
+
>>> ts = datetime(2026, 4, 27, 9, 0, tzinfo=ZoneInfo("America/New_York"))
|
|
268
|
+
>>> session_for_timestamp(ts)
|
|
269
|
+
'2026-04-24'
|
|
270
|
+
"""
|
|
271
|
+
if ts.tzinfo is None:
|
|
272
|
+
ts = ts.replace(tzinfo=timezone.utc)
|
|
273
|
+
return last_closed_trading_day(ts).isoformat()
|