-
Notifications
You must be signed in to change notification settings - Fork 369
Consolidate broker CI and audit fixes #1122
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
79ad0ed
fc8c36b
d562b2f
7122d23
eba56f5
53d232b
8e4fcea
77871c6
8e07ae7
230b903
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,116 @@ | ||
| name: Alpaca Live Broker | ||
|
|
||
| on: | ||
| workflow_dispatch: | ||
| push: | ||
| branches: | ||
| - dev | ||
| paths: | ||
| - "lumibot/**" | ||
| - "tests/test_alpaca_live_broker_apitest.py" | ||
| - "tests/test_agent_runtime_remote_mcp.py" | ||
| - "tests/test_agent_runtime_mcp_transports.py" | ||
| - "tests/test_agent_runtime_provider_keys.py" | ||
| - "tests/test_agent_runtime_errors.py" | ||
| - "tests/test_agent_tool_permissions.py" | ||
| - "tests/test_agent_alpaca_news_builtin.py" | ||
| - "tests/test_agent_alpaca_news_live_apitest.py" | ||
| - "tests/backtest/test_agent_runtime_backtest.py" | ||
| - "tests/backtest/test_ai_committee_builtin_tools_backtest.py" | ||
| - "requirements*.txt" | ||
| - "pyproject.toml" | ||
| - "setup.py" | ||
| - ".github/workflows/alpaca-live-broker.yml" | ||
| pull_request: | ||
| branches: [dev, main] | ||
| paths: | ||
| - "lumibot/**" | ||
| - "tests/test_alpaca_live_broker_apitest.py" | ||
| - "tests/test_agent_runtime_remote_mcp.py" | ||
| - "tests/test_agent_runtime_mcp_transports.py" | ||
| - "tests/test_agent_runtime_provider_keys.py" | ||
| - "tests/test_agent_runtime_errors.py" | ||
| - "tests/test_agent_tool_permissions.py" | ||
| - "tests/test_agent_alpaca_news_builtin.py" | ||
| - "tests/test_agent_alpaca_news_live_apitest.py" | ||
| - "tests/backtest/test_agent_runtime_backtest.py" | ||
| - "tests/backtest/test_ai_committee_builtin_tools_backtest.py" | ||
| - "requirements*.txt" | ||
| - "pyproject.toml" | ||
| - "setup.py" | ||
| - ".github/workflows/alpaca-live-broker.yml" | ||
|
|
||
| permissions: | ||
| contents: read | ||
|
|
||
| env: | ||
| AIOHTTP_NO_EXTENSIONS: 1 | ||
| BACKTESTING_DATA_SOURCE: none | ||
| BACKTESTING_SHOW_PROGRESS_BAR: "false" | ||
| ALPACA_TEST_API_KEY: ${{ secrets.ALPACA_TEST_API_KEY }} | ||
| ALPACA_TEST_API_SECRET: ${{ secrets.ALPACA_TEST_API_SECRET }} | ||
| ALPACA_NEWS_API_KEY: ${{ secrets.ALPACA_NEWS_API_KEY || secrets.ALPACA_TEST_API_KEY }} | ||
| ALPACA_NEWS_API_SECRET: ${{ secrets.ALPACA_NEWS_API_SECRET || secrets.ALPACA_TEST_API_SECRET }} | ||
|
|
||
| jobs: | ||
| alpaca-live-broker: | ||
| name: Alpaca live broker strategy | ||
| runs-on: blacksmith-2vcpu-ubuntu-2404 | ||
| timeout-minutes: 55 | ||
| if: >- | ||
| github.actor != 'dependabot[bot]' && | ||
| (github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository) | ||
| concurrency: | ||
| group: paper-broker-live-tests-${{ github.repository }} | ||
| cancel-in-progress: false | ||
|
Comment on lines
+63
to
+65
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🩺 Stability & Availability | 🟠 Major | 🏗️ Heavy lift Cross-workflow paper-account concurrency risk. Both Consider a shared concurrency group (e.g., keyed on Also applies to: 284-286 🤖 Prompt for AI Agents |
||
|
|
||
| steps: | ||
| - uses: actions/checkout@v4 | ||
| with: | ||
| persist-credentials: false | ||
|
|
||
| - name: Set up Python 3.10 | ||
| uses: actions/setup-python@v5 | ||
| with: | ||
| python-version: "3.10" | ||
| cache: pip | ||
|
|
||
| - name: Install dependencies | ||
| run: | | ||
| set -euo pipefail | ||
| echo "Set AIOHTTP_NO_EXTENSIONS=$AIOHTTP_NO_EXTENSIONS so that aiohttp doesn't try to install C extensions" | ||
| python -m pip install --upgrade pip | ||
| pip install requests | ||
| pip install -r requirements_dev.txt | ||
|
|
||
| - name: Verify Alpaca paper credentials are available | ||
| run: | | ||
| set -euo pipefail | ||
| if [ -z "${ALPACA_TEST_API_KEY}" ] || [ -z "${ALPACA_TEST_API_SECRET}" ]; then | ||
| echo "::error::ALPACA_TEST_API_KEY and ALPACA_TEST_API_SECRET repository secrets are required for Alpaca live broker CI." | ||
| exit 1 | ||
| fi | ||
| if [ -z "${ALPACA_NEWS_API_KEY}" ] || [ -z "${ALPACA_NEWS_API_SECRET}" ]; then | ||
| echo "::error::ALPACA_NEWS_API_KEY and ALPACA_NEWS_API_SECRET, or fallback ALPACA_TEST_API_KEY and ALPACA_TEST_API_SECRET, are required for Alpaca news live apitests." | ||
| exit 1 | ||
| fi | ||
|
|
||
| - name: Run agent MCP and built-in action coverage | ||
| run: | | ||
| set -euo pipefail | ||
| timeout 1500 python -m pytest -q \ | ||
| tests/test_agent_runtime_remote_mcp.py \ | ||
| tests/test_agent_runtime_mcp_transports.py \ | ||
| tests/test_agent_runtime_provider_keys.py \ | ||
| tests/test_agent_runtime_errors.py \ | ||
| tests/test_agent_tool_permissions.py \ | ||
| tests/test_agent_alpaca_news_builtin.py \ | ||
| tests/test_agent_alpaca_news_live_apitest.py \ | ||
| tests/backtest/test_agent_runtime_backtest.py \ | ||
| tests/backtest/test_ai_committee_builtin_tools_backtest.py | ||
|
|
||
| - name: Run real Alpaca broker strategy apitests | ||
| run: | | ||
| set -euo pipefail | ||
| timeout 1200 python -m pytest -q -m apitest --tb=short \ | ||
| tests/test_alpaca_live_broker_apitest.py | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,70 @@ | ||
| # Alpaca Live Broker CI | ||
|
|
||
| One-line description: Real Alpaca paper-account CI for live broker and agent-tool smoke coverage. | ||
|
|
||
| Last Updated: 2026-07-03 | ||
|
|
||
| Status: Active | ||
|
|
||
| Audience: Developers, AI Agents | ||
|
|
||
| ## Overview | ||
|
|
||
| `.github/workflows/alpaca-live-broker.yml` runs opt-in live paper API coverage for Alpaca. It is separate from the normal `not apitest` suite because it contacts Alpaca, reads broker/data endpoints, and submits then cancels real paper orders. | ||
|
|
||
| The workflow runs for internal PRs/pushes and manual dispatches when relevant broker, agent, dependency, or workflow files change. Fork PRs are skipped because repository secrets are unavailable. | ||
|
|
||
| ## Credentials | ||
|
|
||
| Repository secrets required: | ||
|
|
||
| - `ALPACA_TEST_API_KEY` | ||
| - `ALPACA_TEST_API_SECRET` | ||
|
|
||
| Optional repository secrets: | ||
|
|
||
| - `ALPACA_NEWS_API_KEY` | ||
| - `ALPACA_NEWS_API_SECRET` | ||
|
|
||
| The live news apitest uses `ALPACA_NEWS_API_KEY` / `ALPACA_NEWS_API_SECRET` when present and falls back to `ALPACA_TEST_API_KEY` / `ALPACA_TEST_API_SECRET` for CI/local smoke runs. The built-in `alpaca_news` tool intentionally does not read generic `ALPACA_API_KEY` values unless it is bound to an active Alpaca broker. Do not commit real key values. | ||
|
|
||
| ## Test Coverage | ||
|
|
||
| `tests/test_alpaca_live_broker_apitest.py` is marked `apitest` and `alpaca`. | ||
|
|
||
| - `_require_alpaca()` validates paper credentials, authenticates through the real Alpaca API, fails if the paper account is trading-blocked, and configures the broker test market as `24/7` so scheduled one-shot tests run outside NYSE hours. | ||
| - `_LiveOrderDataStrategy` calls `run_live(run_once=True)`, reads AAPL last price and daily bars, submits a non-marketable AAPL limit buy, cancels it, waits for terminal cancel state, and verifies order retrieval. | ||
| - `_LiveOptionsChainStrategy` calls `run_live(run_once=True)`, reads SPY price, pulls SPY option chains through the broker data source, selects an expiration, and resolves a valid call contract. | ||
|
|
||
| `tests/test_agent_alpaca_news_live_apitest.py` uses Alpaca news credentials, falling back to the paper test credentials, to verify the built-in Alpaca news agent tool against real historical news pagination and full-content reads. | ||
|
|
||
| The workflow also runs local-only agent runtime, MCP transport, permission, provider-key, and backtest tool coverage before the live broker apitests. | ||
|
|
||
| ## Concurrency | ||
|
|
||
| The live broker job has a repository-wide concurrency group. This prevents overlapping runs from using the same shared Alpaca paper account at once and avoids one run canceling or observing another run's test orders. | ||
|
|
||
| ## Local Run | ||
|
|
||
| Use paper credentials only: | ||
|
|
||
| ```bash | ||
| export ALPACA_TEST_API_KEY="..." | ||
| export ALPACA_TEST_API_SECRET="..." | ||
|
|
||
| python -m pytest -q \ | ||
| tests/test_agent_runtime_remote_mcp.py \ | ||
| tests/test_agent_runtime_mcp_transports.py \ | ||
| tests/test_agent_runtime_provider_keys.py \ | ||
| tests/test_agent_runtime_errors.py \ | ||
| tests/test_agent_tool_permissions.py \ | ||
| tests/test_agent_alpaca_news_builtin.py \ | ||
| tests/test_agent_alpaca_news_live_apitest.py \ | ||
| tests/backtest/test_agent_runtime_backtest.py \ | ||
| tests/backtest/test_ai_committee_builtin_tools_backtest.py | ||
|
|
||
| python -m pytest -q -m apitest --tb=short \ | ||
| tests/test_alpaca_live_broker_apitest.py | ||
| ``` | ||
|
|
||
| If credentials are missing, `alpaca`-marked apitests skip with the missing Alpaca variables instead of requiring unrelated Polygon or ThetaData credentials. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These independent fallbacks can combine
ALPACA_NEWS_API_KEYwithALPACA_TEST_API_SECRET(or the reverse) when only one optional news secret is configured. The verification step only sees non-empty environment variables, so the live news test proceeds with a mismatched key/secret pair and fails authentication instead of falling back to the complete paper pair or reporting the missing news pair.Useful? React with 👍 / 👎.