trading-platform-core 1.0.0rc2__tar.gz
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.
- trading_platform_core-1.0.0rc2/.gitignore +60 -0
- trading_platform_core-1.0.0rc2/LICENSE +106 -0
- trading_platform_core-1.0.0rc2/PKG-INFO +302 -0
- trading_platform_core-1.0.0rc2/README.md +266 -0
- trading_platform_core-1.0.0rc2/alembic.ini +51 -0
- trading_platform_core-1.0.0rc2/migrations/__init__.py +0 -0
- trading_platform_core-1.0.0rc2/migrations/env.py +87 -0
- trading_platform_core-1.0.0rc2/migrations/script.py.mako +27 -0
- trading_platform_core-1.0.0rc2/migrations/versions/.gitkeep +0 -0
- trading_platform_core-1.0.0rc2/migrations/versions/001_data_quality_log.py +143 -0
- trading_platform_core-1.0.0rc2/migrations/versions/002_execution_quality_log.py +128 -0
- trading_platform_core-1.0.0rc2/migrations/versions/003_aar_events.py +203 -0
- trading_platform_core-1.0.0rc2/migrations/versions/004_parity_drift_log.py +127 -0
- trading_platform_core-1.0.0rc2/migrations/versions/005_add_dq_provenance_columns.py +93 -0
- trading_platform_core-1.0.0rc2/migrations/versions/006_rls_policies.py +200 -0
- trading_platform_core-1.0.0rc2/pyproject.toml +94 -0
- trading_platform_core-1.0.0rc2/tests/__init__.py +0 -0
- trading_platform_core-1.0.0rc2/tests/conftest.py +28 -0
- trading_platform_core-1.0.0rc2/tests/integration/__init__.py +0 -0
- trading_platform_core-1.0.0rc2/tests/integration/test_alpaca_readiness_gate.py +888 -0
- trading_platform_core-1.0.0rc2/tests/unit/__init__.py +0 -0
- trading_platform_core-1.0.0rc2/tests/unit/test_no_stdlib_shadow.py +31 -0
- trading_platform_core-1.0.0rc2/tpcore/__init__.py +17 -0
- trading_platform_core-1.0.0rc2/tpcore/aar/__init__.py +12 -0
- trading_platform_core-1.0.0rc2/tpcore/aar/models.py +95 -0
- trading_platform_core-1.0.0rc2/tpcore/aar/writer.py +342 -0
- trading_platform_core-1.0.0rc2/tpcore/alerts/__init__.py +9 -0
- trading_platform_core-1.0.0rc2/tpcore/alerts/discord.py +341 -0
- trading_platform_core-1.0.0rc2/tpcore/alpaca/__init__.py +10 -0
- trading_platform_core-1.0.0rc2/tpcore/alpaca/broker_adapter.py +1189 -0
- trading_platform_core-1.0.0rc2/tpcore/alpaca/data_adapter.py +808 -0
- trading_platform_core-1.0.0rc2/tpcore/backtest/__init__.py +47 -0
- trading_platform_core-1.0.0rc2/tpcore/backtest/costs.py +549 -0
- trading_platform_core-1.0.0rc2/tpcore/backtest/credibility.py +752 -0
- trading_platform_core-1.0.0rc2/tpcore/backtest/harness.py +1039 -0
- trading_platform_core-1.0.0rc2/tpcore/backtest/types.py +415 -0
- trading_platform_core-1.0.0rc2/tpcore/interfaces/__init__.py +72 -0
- trading_platform_core-1.0.0rc2/tpcore/interfaces/broker_execution.py +869 -0
- trading_platform_core-1.0.0rc2/tpcore/interfaces/data_provider.py +843 -0
- trading_platform_core-1.0.0rc2/tpcore/parity/__init__.py +13 -0
- trading_platform_core-1.0.0rc2/tpcore/parity/live_paper_harness.py +767 -0
- trading_platform_core-1.0.0rc2/tpcore/quality/__init__.py +18 -0
- trading_platform_core-1.0.0rc2/tpcore/quality/data_quality.py +344 -0
- trading_platform_core-1.0.0rc2/tpcore/quality/execution_quality.py +445 -0
- trading_platform_core-1.0.0rc2/tpcore/risk/__init__.py +9 -0
- trading_platform_core-1.0.0rc2/tpcore/risk/governor.py +760 -0
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# Byte-compiled / optimized / DLL files
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
|
|
6
|
+
# Distribution / packaging
|
|
7
|
+
build/
|
|
8
|
+
dist/
|
|
9
|
+
*.egg-info/
|
|
10
|
+
*.egg
|
|
11
|
+
wheels/
|
|
12
|
+
.eggs/
|
|
13
|
+
|
|
14
|
+
# Virtual environments
|
|
15
|
+
.venv/
|
|
16
|
+
venv/
|
|
17
|
+
env/
|
|
18
|
+
ENV/
|
|
19
|
+
.python-version
|
|
20
|
+
|
|
21
|
+
# Testing / coverage
|
|
22
|
+
.pytest_cache/
|
|
23
|
+
.coverage
|
|
24
|
+
.coverage.*
|
|
25
|
+
htmlcov/
|
|
26
|
+
coverage.xml
|
|
27
|
+
.tox/
|
|
28
|
+
.nox/
|
|
29
|
+
|
|
30
|
+
# Type checking
|
|
31
|
+
.mypy_cache/
|
|
32
|
+
.pyright/
|
|
33
|
+
.ruff_cache/
|
|
34
|
+
|
|
35
|
+
# IDEs / editors
|
|
36
|
+
.vscode/
|
|
37
|
+
.idea/
|
|
38
|
+
*.swp
|
|
39
|
+
*.swo
|
|
40
|
+
.DS_Store
|
|
41
|
+
|
|
42
|
+
# Secrets / local config (CLAUDE.md: env vars only; .env never committed)
|
|
43
|
+
.env
|
|
44
|
+
.env.local
|
|
45
|
+
.env.*.local
|
|
46
|
+
*.pem
|
|
47
|
+
*.key
|
|
48
|
+
|
|
49
|
+
# Local DB / Alembic (versions/ is tracked; only local state is ignored)
|
|
50
|
+
*.db
|
|
51
|
+
*.sqlite
|
|
52
|
+
*.sqlite3
|
|
53
|
+
|
|
54
|
+
# Logs
|
|
55
|
+
*.log
|
|
56
|
+
logs/
|
|
57
|
+
|
|
58
|
+
# Build artifacts from docs (Sphinx/MkDocs setup deferred to Sprint 2)
|
|
59
|
+
docs/_build/
|
|
60
|
+
site/
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
trading-platform-core License — Proprietary, Personal Use Only
|
|
2
|
+
================================================================
|
|
3
|
+
|
|
4
|
+
Copyright (c) 2026 Michael Easterly. All rights reserved.
|
|
5
|
+
|
|
6
|
+
This software, including all source code, documentation, configuration,
|
|
7
|
+
schemas, and associated materials in this repository (the "Library"), is
|
|
8
|
+
proprietary and confidential. The Library is licensed, not sold, to the
|
|
9
|
+
licensee.
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
1. PERMITTED USE
|
|
13
|
+
|
|
14
|
+
Personal, non-commercial use by the copyright holder and by any natural
|
|
15
|
+
person expressly authorized in writing by the copyright holder.
|
|
16
|
+
Permitted uses include personal algorithmic-trading research, personal
|
|
17
|
+
backtesting against historical data, and personal use of derived
|
|
18
|
+
signals for self-directed brokerage-account activity belonging to the
|
|
19
|
+
licensee.
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
2. PROHIBITED USE
|
|
23
|
+
|
|
24
|
+
Without the prior written consent of the copyright holder, you MUST
|
|
25
|
+
NOT:
|
|
26
|
+
|
|
27
|
+
(a) Use the Library for any commercial purpose, including managing
|
|
28
|
+
capital on behalf of any third party (whether for compensation or
|
|
29
|
+
otherwise), offering trading-related services, operating a
|
|
30
|
+
capital-pool, or any activity involving third-party funds.
|
|
31
|
+
|
|
32
|
+
(b) Distribute, sublicense, sell, rent, lease, publish, or transfer
|
|
33
|
+
the Library or any derivative work, in whole or in part, to any
|
|
34
|
+
third party.
|
|
35
|
+
|
|
36
|
+
(c) Reverse engineer, decompile, or disassemble the Library beyond
|
|
37
|
+
what is expressly permitted by applicable law.
|
|
38
|
+
|
|
39
|
+
(d) Remove, obscure, or alter any proprietary notices, copyright
|
|
40
|
+
statements, license text, or scope-guard references contained in
|
|
41
|
+
the Library.
|
|
42
|
+
|
|
43
|
+
Commercial deployment is BLOCKED without explicit Legal-Hat
|
|
44
|
+
ratification per the upstream scope guard (creeper decision D-096
|
|
45
|
+
Sub-decision 6, mirrored in this repository's `CLAUDE.md` "Project
|
|
46
|
+
Identity" section).
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
3. NO WARRANTY
|
|
50
|
+
|
|
51
|
+
THE LIBRARY IS PROVIDED "AS IS" AND "AS AVAILABLE", WITHOUT WARRANTY
|
|
52
|
+
OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
|
53
|
+
IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
|
54
|
+
PURPOSE, AND NON-INFRINGEMENT. ALGORITHMIC TRADING INVOLVES SUBSTANTIAL
|
|
55
|
+
RISK OF LOSS. PAST PERFORMANCE OF ANY STRATEGY, BACKTEST, OR SIGNAL IS
|
|
56
|
+
NOT INDICATIVE OF FUTURE RESULTS.
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
4. LIMITATION OF LIABILITY
|
|
60
|
+
|
|
61
|
+
TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, IN NO EVENT SHALL
|
|
62
|
+
THE COPYRIGHT HOLDER BE LIABLE FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
|
|
63
|
+
CONSEQUENTIAL, OR PUNITIVE DAMAGES, OR FOR ANY LOSS OF PROFITS,
|
|
64
|
+
REVENUE, DATA, OR USE, ARISING OUT OF OR IN CONNECTION WITH USE OF
|
|
65
|
+
THE LIBRARY, WHETHER IN CONTRACT, TORT, OR OTHERWISE, EVEN IF ADVISED
|
|
66
|
+
OF THE POSSIBILITY OF SUCH DAMAGES.
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
5. TERMINATION
|
|
70
|
+
|
|
71
|
+
This license terminates automatically upon any breach of its terms.
|
|
72
|
+
Upon termination, the licensee must cease all use of the Library and
|
|
73
|
+
destroy all copies in their possession or control.
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
6. GOVERNING LAW AND VENUE
|
|
77
|
+
|
|
78
|
+
This License, and all claims and causes of action (whether sounding in
|
|
79
|
+
contract, tort, or statute) arising out of or relating to it, including
|
|
80
|
+
all related disputes and the validity, enforceability, and
|
|
81
|
+
interpretation hereof, shall be governed by and construed in accordance
|
|
82
|
+
with the laws of the State of Florida, United States of America,
|
|
83
|
+
including its statutes of limitations, without regard to its conflict
|
|
84
|
+
of laws principles. The parties consent to the exclusive jurisdiction
|
|
85
|
+
and venue of the state and federal courts located in Duval County,
|
|
86
|
+
Florida, for any action arising out of or relating to this License.
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
7. CONTACT
|
|
90
|
+
|
|
91
|
+
Inquiries regarding licensing, commercial-use ratification, or any
|
|
92
|
+
other matter should be directed to the copyright holder via either
|
|
93
|
+
(a) the GitHub repository at
|
|
94
|
+
https://github.com/michaeleasterly-cpu/trading-platform-core, or
|
|
95
|
+
(b) packetvoidlabs@aol.com. Formal notices required under this License
|
|
96
|
+
(including breach or termination notices) shall be sent to the email
|
|
97
|
+
address above.
|
|
98
|
+
|
|
99
|
+
---
|
|
100
|
+
|
|
101
|
+
NOTE: This license text reflects the personal-use-only scope ratified in
|
|
102
|
+
upstream creeper decision D-096 (Sub-decision 6). It is intentionally
|
|
103
|
+
terse and intended to prevent unauthorized commercial use during the
|
|
104
|
+
project's pre-public phase. It has not been reviewed by counsel; the
|
|
105
|
+
copyright holder is advised to obtain legal review prior to any
|
|
106
|
+
commercial-use exposure of this Library.
|
|
@@ -0,0 +1,302 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: trading-platform-core
|
|
3
|
+
Version: 1.0.0rc2
|
|
4
|
+
Summary: Engine-agnostic Python library providing shared infrastructure for algorithmic trading engines (Swinger, Creeper, future engines).
|
|
5
|
+
Project-URL: Homepage, https://github.com/michaeleasterly-cpu/trading-platform-core
|
|
6
|
+
Project-URL: Repository, https://github.com/michaeleasterly-cpu/trading-platform-core
|
|
7
|
+
Author: Michael Easterly
|
|
8
|
+
License-Expression: LicenseRef-Proprietary
|
|
9
|
+
License-File: LICENSE
|
|
10
|
+
Keywords: alpaca,backtest,broker,risk-governor,trading
|
|
11
|
+
Classifier: Development Status :: 4 - Beta
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
16
|
+
Classifier: Topic :: Office/Business :: Financial :: Investment
|
|
17
|
+
Requires-Python: >=3.11
|
|
18
|
+
Requires-Dist: alembic>=1.13
|
|
19
|
+
Requires-Dist: alpaca-py>=0.30.0
|
|
20
|
+
Requires-Dist: psycopg2-binary>=2.9
|
|
21
|
+
Requires-Dist: pydantic<3.0,>=2.0
|
|
22
|
+
Requires-Dist: requests>=2.31
|
|
23
|
+
Requires-Dist: sqlalchemy<3.0,>=2.0
|
|
24
|
+
Provides-Extra: dev
|
|
25
|
+
Requires-Dist: mypy>=1.8; extra == 'dev'
|
|
26
|
+
Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
|
|
27
|
+
Requires-Dist: pytest-cov>=4.1; extra == 'dev'
|
|
28
|
+
Requires-Dist: pytest>=8.0; extra == 'dev'
|
|
29
|
+
Requires-Dist: ruff>=0.3; extra == 'dev'
|
|
30
|
+
Requires-Dist: types-requests>=2.31; extra == 'dev'
|
|
31
|
+
Provides-Extra: docs
|
|
32
|
+
Requires-Dist: mkdocs-material>=9.5; extra == 'docs'
|
|
33
|
+
Requires-Dist: mkdocs>=1.5; extra == 'docs'
|
|
34
|
+
Requires-Dist: mkdocstrings[python]>=0.24; extra == 'docs'
|
|
35
|
+
Description-Content-Type: text/markdown
|
|
36
|
+
|
|
37
|
+
> **PROPRIETARY — PERSONAL USE ONLY.** This software is licensed under a proprietary, personal-use-only license. See [LICENSE](LICENSE) for full terms. Commercial deployment is BLOCKED without explicit Legal-Hat ratification per upstream creeper D-096 Sub-decision 6.
|
|
38
|
+
|
|
39
|
+
# trading-platform-core
|
|
40
|
+
|
|
41
|
+
Engine-agnostic Python library providing shared infrastructure for algorithmic trading engines (Swinger, Creeper, future engines).
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
## What it is
|
|
46
|
+
|
|
47
|
+
`trading-platform-core` is a **library**, not a service. Engines import it as a pinned dependency; it does not run as a standalone process, has no webhook listeners, no cron deployments, and no service runtime. There is no Railway / Vercel / Fly footprint.
|
|
48
|
+
|
|
49
|
+
It provides:
|
|
50
|
+
|
|
51
|
+
- Provider-abstraction ABCs (`DataProviderInterface`, `BrokerExecutionInterface`)
|
|
52
|
+
- Concrete Alpaca adapters (data, broker, paper-account readiness gate)
|
|
53
|
+
- Quality-scoring Pydantic models + DB writers (`DataQualityScore`, `ExecutionQualityScore`)
|
|
54
|
+
- `RiskGovernor` state machine (per-engine instance, hard-limit enforcement)
|
|
55
|
+
- AAR (After-Action Report) Pydantic models + writer to `platform.aar_events`
|
|
56
|
+
- Live-vs-paper parity harness (drift detection)
|
|
57
|
+
- Generic Discord alerting (engine-agnostic)
|
|
58
|
+
- Callback-driven backtest harness with 14-dimension `BacktestCredibilityScore` rubric
|
|
59
|
+
|
|
60
|
+
It does **not** contain engine-specific trading logic, hardcoded strategy parameters, or any signal-generation code. Engines inject those via the public API (e.g., `SignalGenerator` callback into the backtest harness).
|
|
61
|
+
|
|
62
|
+
See [`MASTER_PLAN.md`](MASTER_PLAN.md) for the full architecture, decision log, and component contracts.
|
|
63
|
+
|
|
64
|
+
## Mission and scope
|
|
65
|
+
|
|
66
|
+
> **PERSONAL USE ONLY.** This library is licensed Proprietary per the [`LICENSE`](LICENSE) file (declared in [`pyproject.toml`](pyproject.toml) `project.license`). Commercial deployment is BLOCKED without explicit Legal-Hat ratification. See [`CLAUDE.md`](CLAUDE.md) "Project Identity" for the upstream scope guard (creeper D-096 Sub-decision 6).
|
|
67
|
+
|
|
68
|
+
The library exists to ensure that every engine in the family shares a single source of truth for provider abstraction, point-in-time (PIT) data discipline, risk governance, AAR auditability, and backtest credibility — so engine-side code stays focused on signal generation, not infrastructure plumbing.
|
|
69
|
+
|
|
70
|
+
## Component overview
|
|
71
|
+
|
|
72
|
+
| Component | Module | Purpose |
|
|
73
|
+
|-----------|--------|---------|
|
|
74
|
+
| ABCs | `tpcore.interfaces.data_provider`, `tpcore.interfaces.broker_execution` | `DataProviderInterface` + `BrokerExecutionInterface` — every engine talks to providers exclusively through these. No direct vendor SDK calls in engine code. |
|
|
75
|
+
| Alpaca adapters | `tpcore.alpaca.data_adapter`, `tpcore.alpaca.broker_adapter`, `tpcore.alpaca.readiness_gate` | `AlpacaDataAdapter` (Market Data API v2), `AlpacaBrokerAdapter` (Trading API; paper/live via `ALPACA_PAPER`; stop→stop-limit conversion; `client_order_id` idempotency; `emergency_flatten` with limit-widening), `AlpacaReadinessGate` (pytest suite, must pass before any engine goes live). |
|
|
76
|
+
| Quality models | `tpcore.quality.data_quality`, `tpcore.quality.execution_quality` | `DataQualityScore` + `ExecutionQualityScore` Pydantic models + DB writers to `platform.data_quality_log` / `platform.execution_quality_log`. Bitemporal (`valid_at` + `recorded_at`) for PIT safety. |
|
|
77
|
+
| AAR pipeline | `tpcore.aar.models`, `tpcore.aar.writer` | Engine-agnostic AAR Pydantic models + `AARWriter` to `platform.aar_events` (canonical schema per D-139 — adopts upstream creeper D-140 framework-portable schema; 18 typed columns + UNIQUE on `(engine_id, trade_table, trade_id)` + 7 CHECK constraints + 4 indexes + RLS). Auto-normalises `setup_confidence` to 0-100; embeds `_schema_version` in JSONB; writes `engine_version`. |
|
|
78
|
+
| RiskGovernor | `tpcore.risk.governor` | Per-engine state machine; tracks daily/weekly P&L + open positions; `check_trade()` gate; `record_loss()` / `record_win()` accumulators; hard limits (`max_daily_loss_percent` 2%, `max_weekly_loss_percent` 4%, `max_open_positions` 8 — defaults; configurable per engine); `emergency_kill()` flag. No engine ships live without governor ratification of every trade. |
|
|
79
|
+
| ParityHarness | `tpcore.parity.live_paper_harness` | `LivePaperParityHarness` — submits identical orders to paper + live (when both enabled), compares fill prices / timestamps / slippage, logs to `platform.parity_drift_log`, alerts on drift threshold breach (default 0.2% per order, 1% cumulative weekly). |
|
|
80
|
+
| Discord alerts | `tpcore.alerts.discord` | Generic `send_discord_alert(webhook_url, title, fields, color)`. Engine-supplied webhook URL via env. No engine-specific formatting in the library. HTTP via `requests` (declared dep; `httpx` swap is one-line forward change — see [`MASTER_PLAN.md`](MASTER_PLAN.md) §3.7). |
|
|
81
|
+
| Backtest harness | `tpcore.backtest.harness` | Callback-driven, provider-agnostic. Accepts `DataProviderInterface` instance + `SignalGenerator: Callable[[date, DataSnapshot], List[Signal]]` callback (signature FROZEN at v1.0.0 per MP §3.8 design decision A) + slippage/spread/commission `Protocol`s. Returns full report with PIT verification, survivorship check, configurable walk-forward (calendar days), and 14-dimension `BacktestCredibilityScore` rubric (graduation threshold ≥70 default, configurable per engine). |
|
|
82
|
+
|
|
83
|
+
Full per-component specifications: [`MASTER_PLAN.md`](MASTER_PLAN.md) §3.1-§3.8.
|
|
84
|
+
|
|
85
|
+
## Installation
|
|
86
|
+
|
|
87
|
+
### From PyPI (engines, production)
|
|
88
|
+
|
|
89
|
+
Engines pin to the current major version, allowing additive minor / patch upgrades:
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
pip install "trading-platform-core>=1.0,<2.0"
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
> **Note:** The PyPI distribution name is `trading-platform-core`; the Python import name is `tpcore`. This split is intentional — see [`MASTER_PLAN.md`](MASTER_PLAN.md) §2 Naming note. Importing as `tpcore` avoids shadowing the Python stdlib `platform` module (which `setuptools`, `pip`, and many CLI tools depend on via `platform.system()`).
|
|
96
|
+
|
|
97
|
+
### Editable install (development)
|
|
98
|
+
|
|
99
|
+
For library development, including the `dev` optional-dependency block (pytest, mypy, ruff, etc., per [`pyproject.toml`](pyproject.toml) `project.optional-dependencies.dev`):
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
git clone git@github.com:michaeleasterly-cpu/trading-platform-core.git
|
|
103
|
+
cd trading-platform-core
|
|
104
|
+
pip install -e ".[dev]"
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
Minimum Python version: **3.11** (declared in `pyproject.toml` `requires-python`). Tested on 3.11 and 3.12.
|
|
108
|
+
|
|
109
|
+
## Quick start
|
|
110
|
+
|
|
111
|
+
```python
|
|
112
|
+
import os
|
|
113
|
+
from tpcore.alpaca.data_adapter import AlpacaDataAdapter
|
|
114
|
+
from tpcore.alpaca.broker_adapter import AlpacaBrokerAdapter
|
|
115
|
+
|
|
116
|
+
# Engines parse ALPACA_PAPER themselves and pass it to the adapter constructors.
|
|
117
|
+
# `ALPACA_PAPER=true` (default) → paper endpoint; `ALPACA_PAPER=false` → live endpoint.
|
|
118
|
+
paper = os.environ.get("ALPACA_PAPER", "true").lower() == "true"
|
|
119
|
+
|
|
120
|
+
data = AlpacaDataAdapter(
|
|
121
|
+
api_key=os.environ["ALPACA_API_KEY"],
|
|
122
|
+
api_secret=os.environ["ALPACA_API_SECRET"],
|
|
123
|
+
paper=paper,
|
|
124
|
+
)
|
|
125
|
+
|
|
126
|
+
broker = AlpacaBrokerAdapter(
|
|
127
|
+
api_key=os.environ["ALPACA_API_KEY"],
|
|
128
|
+
api_secret=os.environ["ALPACA_API_SECRET"],
|
|
129
|
+
paper=paper,
|
|
130
|
+
)
|
|
131
|
+
|
|
132
|
+
# Both adapters implement the engine-agnostic ABCs:
|
|
133
|
+
# tpcore.interfaces.data_provider.DataProviderInterface
|
|
134
|
+
# tpcore.interfaces.broker_execution.BrokerExecutionInterface
|
|
135
|
+
# Engine code should type-annotate against the ABCs, never the concrete class.
|
|
136
|
+
|
|
137
|
+
bars = data.get_daily_bars(symbol="SPY", start="2025-01-01", end="2025-12-31")
|
|
138
|
+
account = broker.get_account()
|
|
139
|
+
assert account.is_paper is True # paper account confirmed
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
A typical engine wires the adapters into a `RiskGovernor`, `AARWriter`, and (for backtests) the harness with an engine-specific `SignalGenerator` callback. See [`MASTER_PLAN.md`](MASTER_PLAN.md) §6 for the full integration pattern.
|
|
143
|
+
|
|
144
|
+
### Required environment variables
|
|
145
|
+
|
|
146
|
+
| Variable | Purpose |
|
|
147
|
+
|----------|---------|
|
|
148
|
+
| `ALPACA_API_KEY` | Alpaca API key (paper or live, matching `ALPACA_PAPER`) |
|
|
149
|
+
| `ALPACA_API_SECRET` | Alpaca API secret (paper or live, matching `ALPACA_PAPER`) |
|
|
150
|
+
| `ALPACA_PAPER` | `true` (default) routes to the paper endpoint; `false` routes to the live endpoint. Engines parse this and pass `paper=` to the adapter constructors. |
|
|
151
|
+
| `TPCORE_DATABASE_URL` | Postgres connection string for `platform.*` tables (engine-supplied; consumed by `migrations/env.py`) |
|
|
152
|
+
|
|
153
|
+
## Postgres setup
|
|
154
|
+
|
|
155
|
+
The library ships Alembic migrations under [`migrations/versions/`](migrations/versions/). Engines provide the connection (the library does not own credentials or pool config). Today there are five migrations:
|
|
156
|
+
|
|
157
|
+
| Migration | Table |
|
|
158
|
+
|-----------|-------|
|
|
159
|
+
| `001_data_quality_log.py` | `platform.data_quality_log` |
|
|
160
|
+
| `002_execution_quality_log.py` | `platform.execution_quality_log` |
|
|
161
|
+
| `003_aar_events.py` | `platform.aar_events` (per D-139 / upstream D-140) |
|
|
162
|
+
| `004_parity_drift_log.py` | `platform.parity_drift_log` |
|
|
163
|
+
| `005_add_dq_provenance_columns.py` | additive: `data_quality_log` provenance columns |
|
|
164
|
+
|
|
165
|
+
To apply migrations against an engine-provided database:
|
|
166
|
+
|
|
167
|
+
```bash
|
|
168
|
+
export TPCORE_DATABASE_URL="postgresql+psycopg2://user:pass@host:5432/db"
|
|
169
|
+
alembic upgrade head
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
Every `platform.*` table includes:
|
|
173
|
+
|
|
174
|
+
- `engine` column (`'creeper'`, `'swinger'`, etc.) — for engine-scoped writes / RLS
|
|
175
|
+
- `valid_at` + `recorded_at` — bitemporal columns for point-in-time (PIT) historical queries
|
|
176
|
+
|
|
177
|
+
PIT-safe historical reads use the canonical pattern:
|
|
178
|
+
|
|
179
|
+
```sql
|
|
180
|
+
WHERE valid_at <= :date AND recorded_at <= :date
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
For Alembic conventions (revision ordering, downgrade discipline, schema-version embedding in JSONB columns), see [`MIGRATION.md`](MIGRATION.md).
|
|
184
|
+
|
|
185
|
+
## Engine integration
|
|
186
|
+
|
|
187
|
+
Swinger and Creeper are the two reference consumers; both follow the integration pattern documented in [`MASTER_PLAN.md`](MASTER_PLAN.md) §6:
|
|
188
|
+
|
|
189
|
+
1. Pin `trading-platform-core>=1.0,<2.0` in the engine's dependency manifest.
|
|
190
|
+
2. Import providers + governor + writer through the ABC-typed entrypoints (`from tpcore.interfaces.data_provider import DataProviderInterface`, etc.).
|
|
191
|
+
3. Instantiate **one `RiskGovernor` per engine** (separate state files; never share an instance across engines).
|
|
192
|
+
4. Provide an engine-specific `SignalGenerator` callback to the backtest harness (the harness has zero awareness of squeeze / swing / any other strategy semantics).
|
|
193
|
+
5. Write AARs through `AARWriter` (the writer auto-attaches `engine` + `engine_version`).
|
|
194
|
+
|
|
195
|
+
Canonical engine wiring snippet:
|
|
196
|
+
|
|
197
|
+
```python
|
|
198
|
+
from tpcore.interfaces.data_provider import DataProviderInterface
|
|
199
|
+
from tpcore.interfaces.broker_execution import BrokerExecutionInterface
|
|
200
|
+
from tpcore.alpaca.data_adapter import AlpacaDataAdapter
|
|
201
|
+
from tpcore.alpaca.broker_adapter import AlpacaBrokerAdapter
|
|
202
|
+
from tpcore.risk.governor import RiskGovernor
|
|
203
|
+
from tpcore.aar.writer import AARWriter
|
|
204
|
+
|
|
205
|
+
# Engine code annotates against the ABCs, not the concrete adapter classes.
|
|
206
|
+
data: DataProviderInterface = AlpacaDataAdapter(...)
|
|
207
|
+
broker: BrokerExecutionInterface = AlpacaBrokerAdapter(...)
|
|
208
|
+
|
|
209
|
+
# Per-engine governor instance — never share across engines.
|
|
210
|
+
governor = RiskGovernor(
|
|
211
|
+
engine="swinger",
|
|
212
|
+
max_daily_loss_percent=2.0,
|
|
213
|
+
max_weekly_loss_percent=4.0,
|
|
214
|
+
max_open_positions=8,
|
|
215
|
+
)
|
|
216
|
+
|
|
217
|
+
aar_writer = AARWriter(engine=os.environ["TPCORE_DATABASE_URL"])
|
|
218
|
+
|
|
219
|
+
# Pre-trade gate
|
|
220
|
+
allowed, reason = governor.check_trade(symbol="AAPL", proposed_size_usd=2500)
|
|
221
|
+
if not allowed:
|
|
222
|
+
logger.info("trade rejected: %s", reason)
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
Engine repositories must NOT contain:
|
|
226
|
+
|
|
227
|
+
- Direct Alpaca SDK calls (use the ABCs)
|
|
228
|
+
- Hardcoded provider credentials (env vars only)
|
|
229
|
+
- Duplicate quality / risk / AAR logic (import from `tpcore`)
|
|
230
|
+
|
|
231
|
+
See [`CONTRIBUTING.md`](CONTRIBUTING.md) for the contributor workflow (adding new adapters, modifying ABCs, writing tests, opening PRs).
|
|
232
|
+
|
|
233
|
+
## Design discipline
|
|
234
|
+
|
|
235
|
+
Three non-negotiables enforced by the library and verified in CI:
|
|
236
|
+
|
|
237
|
+
1. **Provider abstraction is mandatory.** Every Alpaca SDK call lives behind an ABC method. Engines depending on `alpaca-py` directly is a process violation. The ABCs are versioned with the library and frozen at v1.0.0 (additive-only after that).
|
|
238
|
+
2. **Point-in-time (PIT) safety.** Historical reads always carry `valid_at` + `recorded_at` predicates. Bitemporal columns are required on every `platform.*` table; backtest harness verification fails the run if a snapshot includes data with `recorded_at > backtest_date`.
|
|
239
|
+
3. **Risk governor before live capital.** No engine ships live without `RiskGovernor.check_trade()` ratifying every order. The governor's `emergency_kill()` flag is engine-callable and blocks all new orders until explicitly reset.
|
|
240
|
+
|
|
241
|
+
Component-level design decisions (e.g., `SignalGenerator` signature freeze, `DataSnapshot` representation, slippage/spread/commission as `Protocol` rather than ABC, walk-forward window semantics, `BacktestCredibilityScore` graduation threshold) are locked in [`MASTER_PLAN.md`](MASTER_PLAN.md) §3.8 design-decisions A–E. The MASTER_PLAN is canonical for design — never re-litigate decisions in code comments.
|
|
242
|
+
|
|
243
|
+
## Versioning
|
|
244
|
+
|
|
245
|
+
Semantic versioning per [`MASTER_PLAN.md`](MASTER_PLAN.md) §7:
|
|
246
|
+
|
|
247
|
+
| Bump | Trigger |
|
|
248
|
+
|------|---------|
|
|
249
|
+
| **MAJOR** | Breaking changes to public ABCs or `platform.*` database schemas |
|
|
250
|
+
| **MINOR** | New optional ABC methods, new adapters, additive schema columns, non-breaking enhancements |
|
|
251
|
+
| **PATCH** | Bug fixes, documentation, internal refactors with zero API surface impact |
|
|
252
|
+
|
|
253
|
+
Pre-release tags follow PEP 440 (`v1.0.0-rc.1`, etc.). Engines pin to the current major (`>=1.0,<2.0`); new majors require a coordinated migration across consuming engines.
|
|
254
|
+
|
|
255
|
+
**Backward-compatibility commitment after v1.0.0:** zero breaking changes to public ABCs or schemas without a major bump.
|
|
256
|
+
|
|
257
|
+
## Testing
|
|
258
|
+
|
|
259
|
+
```bash
|
|
260
|
+
# All unit tests (mocked external APIs)
|
|
261
|
+
pytest tests/unit/
|
|
262
|
+
|
|
263
|
+
# Integration tests (requires Alpaca paper credentials in env + Postgres connection)
|
|
264
|
+
pytest -m integration tests/integration/
|
|
265
|
+
|
|
266
|
+
# Coverage report
|
|
267
|
+
pytest --cov=tpcore --cov-report=term-missing
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
Coverage target: **≥80%** for `tpcore.*` per `MASTER_PLAN.md` §8 / §10. Integration runtime target: **<2 minutes** per the success-metrics table in `MASTER_PLAN.md` §10.
|
|
271
|
+
|
|
272
|
+
## Repository layout
|
|
273
|
+
|
|
274
|
+
```
|
|
275
|
+
trading-platform-core/
|
|
276
|
+
├── tpcore/ # Importable library code
|
|
277
|
+
│ ├── interfaces/ # DataProviderInterface, BrokerExecutionInterface ABCs
|
|
278
|
+
│ ├── alpaca/ # AlpacaDataAdapter, AlpacaBrokerAdapter, AlpacaReadinessGate
|
|
279
|
+
│ ├── quality/ # DataQualityScore, ExecutionQualityScore
|
|
280
|
+
│ ├── risk/ # RiskGovernor
|
|
281
|
+
│ ├── aar/ # AAR models + AARWriter
|
|
282
|
+
│ ├── parity/ # LivePaperParityHarness
|
|
283
|
+
│ ├── alerts/ # Discord webhook sender
|
|
284
|
+
│ └── backtest/ # Callback-driven backtest harness
|
|
285
|
+
├── migrations/ # Alembic migrations for platform.* schema
|
|
286
|
+
├── tests/
|
|
287
|
+
│ ├── unit/ # Mocked-API unit tests
|
|
288
|
+
│ └── integration/ # Alpaca paper + Postgres integration tests
|
|
289
|
+
├── pyproject.toml # PyPI metadata, deps, dev extras
|
|
290
|
+
├── alembic.ini
|
|
291
|
+
├── README.md # This file
|
|
292
|
+
├── CONTRIBUTING.md # Contributor workflow
|
|
293
|
+
├── MIGRATION.md # Schema-migration guide
|
|
294
|
+
├── MASTER_PLAN.md # Architecture + decision log
|
|
295
|
+
└── LICENSE # Proprietary — personal use only
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
Full structural reference: [`MASTER_PLAN.md`](MASTER_PLAN.md) §2.
|
|
299
|
+
|
|
300
|
+
## License
|
|
301
|
+
|
|
302
|
+
Proprietary — personal use only. See [`LICENSE`](LICENSE) for the full text and [`pyproject.toml`](pyproject.toml) `project.license` for the declarative metadata. Commercial deployment is BLOCKED without explicit Legal-Hat ratification per the upstream scope guard (creeper D-096 Sub-decision 6, mirrored in [`CLAUDE.md`](CLAUDE.md) "Project Identity").
|