This project generates a comprehensive suite of market intelligence reports by
combining BoundaryML (BAML) agents with targeted post-processing guardrails.
Given a diversified watchlist of tickers, the system collects historical
performance, volatility statistics, news coverage, insider activity, and
sentiment signals, then consolidates the findings into Markdown documents under
the reports/ directory.
main.py– Asynchronous entrypoint that schedules report generation for the full ticker list and writes bundled Markdown outputs.report_generator.py– Hosts theReportGeneratorclass, which orchestrates the BAML agent calls, applies data-quality filters, and formats the Markdown sections for each report type.config.py– Small helper module that validates required environment variables, emits warnings for optional providers, and resolves the report "as-of" date (honouring theREPORT_AS_OF_DATEoverride).data_utils.py– Shared utilities for vetting agent responses (e.g. bounding volatility, dividend yields, insider names) and formatting numeric output so that Markdown stays consistent.baml_src/– BAML definitions for every agent. Each.bamlfile specifies the schema, prompts, and data-quality requirements for:historical_prism.baml– Long-form historical analysisvolatility.baml– Risk and volatility profilingnews.baml– Recent news synthesis and sentimentinsider_trading.baml– Insider transaction analysissentiment.baml– Cross-source sentiment aggregationmarket_conditions.baml– Macro backdrop report
baml_client/– Generated Python bindings created bybaml-cli generate; do not edit manually.reports/– Output directory for generated Markdown summaries..env– Local configuration for API keys and optional report parameters.
- Configuration –
main.pyloads.env, checks for mandated credentials (OPENROUTER_API_KEY) and warns when optional providers (Alpaca, FMP) are absent. The report date defaults todatetime.date.today()unlessREPORT_AS_OF_DATEis provided. - Agent Execution – For each ticker,
ReportGenerator.generate_all_reportslaunches five BAML agent calls concurrently:GenerateHistoricalAnalysisReport,GenerateVolatilityReport,GenerateNewsReport,GenerateInsiderReport, andGenerateSentimentAnalysisReport. A sixth call produces the cross-marketGenerateMarketConditionsReportonce all tickers are processed. - Validation & Formatting – The raw agent payloads are passed through the
safeguards in
data_utils.py, which remove placeholder insiders, reject stale articles, clamp unrealistic statistics, and ensure consistent currency / percent formatting. - Emission – Cleaned sections are concatenated into Markdown bundles (one
file per report category) and written to the
reports/directory.
- Python: 3.10 or newer is recommended (project uses type hints and
asynciofeatures from modern versions). - Network access: Required for BAML to reach OpenRouter, Alpaca, and FMP APIs.
- API keys:
OPENROUTER_API_KEY(mandatory) – used for the Mercury Coder model.ALPACA_API_KEY/ALPACA_SECRET_KEY(optional but recommended) – enable refined volatility and market data.FMP_API_KEY(optional but recommended) – enables richer news and insider feeds.
Install dependencies into a virtual environment:
python -m venv env
source env/bin/activate # or env\Scripts\activate on Windows
pip install --upgrade pip
pip install baml python-dotenvNote: Running the agents assumes
baml-cligenerated the code insidebaml_client/. If you modify anything inbaml_src/, regenerate bindings withbaml generate(orbaml-cli generate) and reinstall the matching BAML version.
Create a .env file based on the example below:
OPENROUTER_API_KEY=sk-or-...
ALPACA_API_KEY=your_alpaca_key
ALPACA_SECRET_KEY=your_alpaca_secret
FMP_API_KEY=your_fmp_key
# Optional overrides
# REPORT_AS_OF_DATE=2025-09-19
# REPORT_BENCHMARK=SPY
# REPORT_PERIOD=1y
# REPORT_INTERVAL=1dOmitted optional keys will trigger friendly warnings and disable the corresponding data sources gracefully.
-
Activate your virtual environment.
-
Ensure the
.envfile is populated as described above. -
From the repository root, execute:
python main.py
-
Monitor the console for per-ticker progress. When the run completes, inspect the Markdown reports in
reports/:historical.mdvolatility.mdnews.mdinsider_trading.mdsentiment.mdmarket_conditions.md
If you prefer to call the orchestration logic from another script, instantiate
ReportGenerator and await generate_all_reports() from an asyncio event loop.
- Ticker universe – Modify
ReportGenerator.stock_tickers(or supply your own list) to align with a different portfolio. - Report cadence – Override
REPORT_AS_OF_DATE,REPORT_PERIOD, andREPORT_INTERVALin the environment to re-run historical comparisons for the desired timeframe. - Prompt tuning – Update the relevant
.bamlfiles underbaml_src/to adjust agent behaviour. Remember to regenerate the client bindings viabaml generateafterwards. - Quality guardrails –
data_utils.pycentralises the heuristics that reject hallucinated values. Adjust, extend, or tighten the thresholds there as your use case demands.
- Missing keys – A
RuntimeErrorfromensure_env_varindicates that the mandatoryOPENROUTER_API_KEYwas not set. - Data gaps – Sections may print “Data unavailable or did not meet quality checks.” when upstream APIs return empty or implausible results. This is intentional to avoid misleading analytics.
- Regeneration errors – If you edit the
.bamlfiles and see attribute errors at runtime, regenerate the Python bindings (baml generate) so that the client matches the new schema.
With the environment configured and dependencies installed, the project can be run end-to-end to produce multi-dimensional trading intelligence snapshots with strong safeguards against hallucinated metrics.