Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 10 additions & 11 deletions .github/workflows/insider-scan.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@ name: Daily Insider Scan

on:
schedule:
# 7:00 AM ET on weekdays (11:00 UTC Nov-Mar, 12:00 UTC Mar-Nov)
# Using 12:00 UTC to cover EDT; during EST this runs at 7 AM still fine
# 12:00 UTC on weekdays (7 AM EST / 8 AM EDT).
- cron: "0 12 * * 1-5"
workflow_dispatch:
inputs:
Expand All @@ -27,8 +26,14 @@ jobs:
with:
python-version: "3.12"

- name: Install uv
uses: astral-sh/setup-uv@v5
with:
enable-cache: true

- name: Install dependencies
run: pip install -r skills/signal-sweep/requirements.txt
working-directory: skills/signal-sweep
run: uv sync --locked

- name: Run insider scan
env:
Expand All @@ -40,16 +45,10 @@ jobs:
LOOKBACK="${{ github.event.inputs.lookback || '5' }}"
ZSCORE="${{ github.event.inputs.zscore || '1.5' }}"

WEBHOOK_ARG=""
if [ -n "$DISCORD_WEBHOOK_URL" ]; then
WEBHOOK_ARG="--webhook $DISCORD_WEBHOOK_URL"
fi

python scripts/scan_insiders.py \
uv run python scripts/scan_insiders.py \
--date "$DATE" \
--lookback "$LOOKBACK" \
--zscore "$ZSCORE" \
$WEBHOOK_ARG
--zscore "$ZSCORE"

- name: Upload scan results
if: always()
Expand Down
2 changes: 2 additions & 0 deletions .markdownlint-cli2.jsonc
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@
},
"ignores": [
".venv",
"**/.venv/**",
"node_modules",
"**/node_modules/**",
".git",
"**/sec-cache/**",
"**/signal-sweep-cache/**",
Expand Down
58 changes: 2 additions & 56 deletions skills/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,62 +54,8 @@ the skill that owns them. Load only the guide or script required for the current
- [`bottom-up-analyst`](bottom-up-analyst/) contains valuation arithmetic and memo frameworks.
- [`pitch-like-lou`](pitch-like-lou/) contains the pitch-writing workflow and reference corpus.

Each skill's README documents its own dependencies and usage. Runtime caches are generated
next to the relevant workspace and are git-ignored.

## Current snapshot

The following commands measure the entry-point surface and the explicitly referenced skill
resources from the repository root:

```bash
cloc --by-file --include-lang=Markdown \
skills/bottom-up-analyst/SKILL.md \
skills/pitch-like-lou/SKILL.md \
skills/sec-edgar-skill/SKILL.md \
skills/signal-sweep/SKILL.md \
skills/market-scout/SKILL.md
```

```bash
cloc \
skills/bottom-up-analyst/SKILL.md \
skills/bottom-up-analyst/references/memo_template.md \
skills/bottom-up-analyst/references/guide_normalization.md \
skills/bottom-up-analyst/references/guide_competitive.md \
skills/bottom-up-analyst/references/guide_valuation.md \
skills/bottom-up-analyst/references/guide_ownership_signals.md \
skills/bottom-up-analyst/references/archetypes/*.md \
skills/bottom-up-analyst/scripts/dcf.py \
skills/bottom-up-analyst/scripts/epv.py \
skills/market-scout/SKILL.md \
skills/market-scout/scripts/fetch_market_data.py \
skills/market-scout/scripts/fetch_transcripts.py \
skills/pitch-like-lou/SKILL.md \
skills/pitch-like-lou/references/corpus/*.md \
skills/sec-edgar-skill/SKILL.md \
skills/sec-edgar-skill/references/guide_core.md \
skills/sec-edgar-skill/references/guide_filings.md \
skills/sec-edgar-skill/references/guide_financials.md \
skills/sec-edgar-skill/references/guide_ownership.md \
skills/sec-edgar-skill/references/guide_proxy.md \
skills/sec-edgar-skill/references/guide_holdings.md \
skills/sec-edgar-skill/scripts/orient.py \
skills/sec-edgar-skill/scripts/fetch_filing.py \
skills/sec-edgar-skill/scripts/fetch_filings.py \
skills/sec-edgar-skill/scripts/parse_financials.py \
skills/sec-edgar-skill/scripts/list_headings.py \
skills/sec-edgar-skill/scripts/fetch_insider_trades.py \
skills/sec-edgar-skill/scripts/fetch_13f_holders.py \
skills/sec-edgar-skill/scripts/test_setup.py \
skills/signal-sweep/SKILL.md \
skills/signal-sweep/screens.json \
skills/signal-sweep/references/guide_screens.md \
skills/signal-sweep/scripts/scan_insiders.py \
skills/signal-sweep/scripts/scan_market.py \
skills/signal-sweep/scripts/search_themes.py \
skills/signal-sweep/scripts/scan_conferences.py
```
Each skill's README documents its dependencies and usage. Invoke installed artifact-producing
scripts from the research workspace so their git-ignored runtime caches stay beside the work.

## Research scope

Expand Down
44 changes: 22 additions & 22 deletions skills/market-scout/README.md
Original file line number Diff line number Diff line change
@@ -1,41 +1,41 @@
# Market Scout

Pull public market data — price, market cap, trailing returns, peers, and sector screens — for
US-listed stocks via [`yfinance`](https://github.com/ranaroussi/yfinance). An unopinionated data
layer: it surfaces facts and rankings; it decides nothing.
Public market context and earnings-call transcript retrieval for US-listed stocks via
[`yfinance`](https://github.com/ranaroussi/yfinance) and Yahoo Finance. The skill returns source
material; it does not decide whether a security is attractive.

Part of the [SecStack skills](../README.md) collection.

## Installation (do this first)
## Setup

Install this skill's dependencies and the browser runtime before using the scripts:
The SecStack bootstrap installs this skill's dependencies into the profile environment. For
standalone use:

```bash
uv sync
# The SecStack bootstrap installs agent-browser into the isolated Pi profile.
# Run this once from an active SecStack profile:
agent-browser install
uv sync --project "<skill-dir>"
```

- `yfinance`/`pandas` power market/peer data.
- `agent-browser` is required for earnings-call transcript pages (JS-rendered Yahoo/Quartr).
- In the packaged SecStack profile, its Pi-managed binary is already on PATH.
Activate the resulting environment or prefix script commands with
`uv run --project "<skill-dir>"`.

## Use
Transcript retrieval also uses the Pi-managed `agent-browser` binary. Install its browser runtime
once from an active SecStack profile:

```bash
python scripts/fetch_market_data.py --ticker AAPL --peers
agent-browser install
```

## Earnings call transcripts (Yahoo + Quartr)
## Examples

Keep the research workspace as the current directory and invoke the installed scripts by their
resolved paths so generated transcript cache stays with the research:

```bash
python scripts/fetch_transcripts.py --ticker AAPL --list
python scripts/fetch_transcripts.py --ticker AAPL --latest 1
python "<skill-dir>/scripts/fetch_market_data.py" --ticker AAPL --peers
python "<skill-dir>/scripts/fetch_transcripts.py" --ticker AAPL --list
python "<skill-dir>/scripts/fetch_transcripts.py" --ticker AAPL --latest 1
```

yfinance offers far more than the script wraps and is self-documenting (`dir()`, `help()`,
`t.info.keys()`) — see [SKILL.md](SKILL.md) for how to discover and construct what you need.

Market data is best-effort and occasionally stale or missing for thinly-covered names; confirm
anything load-bearing against a primary source.
See [SKILL.md](SKILL.md) for routing, output contracts, and runtime discovery beyond the bundled
report fields. Yahoo data is best-effort and can be stale or incomplete for thinly covered names;
verify load-bearing facts against an issuer or regulatory source.
104 changes: 54 additions & 50 deletions skills/market-scout/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,81 +1,85 @@
---
name: market-scout
description: >-
Pull public market data for US-listed stocks via Yahoo Finance: price, market cap, shares,
52-week range, trailing returns, sector/industry peer tables and pre-ranked screens, and
earnings call transcripts. Use this whenever a task needs a quick market snapshot or quote
for a ticker, trailing performance, a company's peer set, a sector/theme shortlist, or
earnings call transcripts — e.g. "what's the price/return on X", "who are X's peers",
"best-performing names in this industry", "get me the latest earnings call", or turning a
theme into a concrete list of tickers. This is an unopinionated data layer; it does not
decide what is cheap, good, or worth buying.
Retrieve current public market data and earnings-call transcripts for US-listed stocks via
Yahoo Finance: quotes, market capitalization, shares, price history and trailing returns,
industry context, peer tables, and transcript text. Use when a task needs a current market
snapshot, performance calculation, Yahoo peer or industry data, a market-data field, or an
earnings-call transcript. Use primary filings for facts that Yahoo does not author or when a
load-bearing figure needs regulatory verification.
---

# Market Scout

Pull **public market data**, **sector/peer screening**, and **earnings call transcripts**
for US-listed stocks. Unopinionated: it surfaces prices, returns, peers, rankings, and
management commentary; it does not decide what is cheap or worth buying — leave that to
whatever framework is driving.
Retrieve market context and transcript text without turning the result into an investment
conclusion.

## Setup (install first)
## Runtime and paths

Install this skill's dependencies from this directory before running any script:
Resolve bundled paths relative to this `SKILL.md`. Invoke scripts by absolute path while keeping
the shell working directory at the research workspace. This puts the default
`./transcript-cache` beside the work rather than inside the installed skill; alternatively pass
`--cache-dir`.

```bash
uv sync
# In the packaged SecStack profile, agent-browser is installed by the bootstrap.
agent-browser install
```
The packaged SecStack profile already exposes this skill's Python dependencies. For standalone
use, run `uv sync --project "<skill-dir>"`, then either activate that environment or prefix the
examples below with `uv run --project "<skill-dir>"`. `fetch_transcripts.py` also requires the
`agent-browser` binary and its one-time browser installation (`agent-browser install`). No API key
or SEC identity is required.

- `agent-browser` is required for earnings-call transcripts (`fetch_transcripts.py`).
- No API key or identity is needed — Yahoo Finance is public.
## Choose a route

## Market snapshot and peers
### Snapshot, returns, industry, and peers

`fetch_market_data.py` prints a compact Markdown summary to stdout — price, market cap,
shares outstanding, 52-week range, trailing returns, and (optionally) industry overview and
peer tables. Output is live and never cached. `--help` is the authoritative flag reference:
`fetch_market_data.py` prints a live Markdown report to stdout. It does not cache time-sensitive
market data.

```bash
python scripts/fetch_market_data.py --ticker AAPL --industry --peers
python "<skill-dir>/scripts/fetch_market_data.py" --ticker AAPL
python "<skill-dir>/scripts/fetch_market_data.py" --ticker AAPL --industry --peers
```

## Earnings call transcripts
The default report includes common trailing windows available inside the requested history period.
Use `--period` to change how much history is fetched. For a different interval or field, use the
runtime-discovery route below rather than treating the bundled report as Yahoo's full schema.

### Earnings-call transcripts

`fetch_transcripts.py` scrapes Yahoo Finance's Quartr-powered transcript pages via
`agent-browser` (Yahoo requires JS rendering). It lists available transcripts or downloads
them as LLM-friendly Markdown to `transcript-cache/<TICKER>/transcripts/`. Files are
named `Q3-FY2026.md` etc., cached and reused across runs. `--help` for all flags:
List the periods Yahoo currently exposes, then request the exact period or latest count needed:

```bash
python scripts/fetch_transcripts.py --ticker AAPL --list # list available
python scripts/fetch_transcripts.py --ticker AAPL --latest 1 # most recent
python scripts/fetch_transcripts.py --ticker AAPL --year 2025 # full fiscal year
python scripts/fetch_transcripts.py --ticker AAPL --quarter Q3 --year 2025
python "<skill-dir>/scripts/fetch_transcripts.py" --ticker AAPL --list
python "<skill-dir>/scripts/fetch_transcripts.py" --ticker AAPL --latest 1
python "<skill-dir>/scripts/fetch_transcripts.py" --ticker AAPL --year 2025
python "<skill-dir>/scripts/fetch_transcripts.py" --ticker AAPL --quarter Q3 --year 2025
```

Each cached file has a summary, `## Prepared Remarks` with `### Speaker — Title` headings,
and a `## Q&A` section — greppable by speaker name, "guidance", "margin", or any keyword.
Downloads are written to `<cache>/<TICKER>/transcripts/Q3-FY2026.md` and reused on later runs.
Artifact-producing mode emits one absolute path per completed transcript to stdout and diagnostics
to stderr. A partial or total retrieval failure exits nonzero rather than masquerading as an empty
period.

## Beyond the bundled scripts — yfinance is self-documenting
Each file preserves the Yahoo source URL and, when present, separates prepared remarks from Q&A.
Transcript text and speaker attribution are third-party data; verify a consequential quote against
the issuer's own transcript, webcast, or filing when available.

The scripts above wrap the common cases. yfinance exposes far more (financials, holders,
options, earnings dates, calendar, sector/industry screens, …). When a task needs something
the scripts don't cover, **discover at runtime** rather than guessing field names:
## Runtime discovery beyond the wrappers

The bundled scripts cover frequent jobs, not the limits of `yfinance`. Inspect the installed API
instead of guessing field names or assuming a fixed metric template:

```python
import yfinance as yf

t = yf.Ticker("AAPL")

print([a for a in dir(t) if not a.startswith("_")]) # all attributes/methods
list(t.info.keys()) # every field in the snapshot
ticker = yf.Ticker("AAPL")
print([name for name in dir(ticker) if not name.startswith("_")])
print(sorted((ticker.info or {}).keys()))
help(ticker.history)

# Sector/industry screening (theme -> shortlist):
ind = yf.Industry(t.info["industryKey"])
print([a for a in dir(ind) if not a.startswith("_")]) # top_companies, overview, ...
industry = yf.Industry((ticker.info or {})["industryKey"])
print([name for name in dir(industry) if not name.startswith("_")])
```

When a field or method isn't what you expected, `dir()` / `help()` / `.info.keys()` recover
the answer inline — prefer that over guessing.
Use this route for calendars, options, holders, financial tables, custom return windows, or other
Yahoo fields. Report the field name, period, units, and retrieval date. Treat missing or stale data
as missing; do not silently substitute a different field or period.
47 changes: 30 additions & 17 deletions skills/market-scout/scripts/_common.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,30 @@
"""Minimal shared runtime setup for market-scout scripts."""

import sys

# yfinance/pandas can emit non-ASCII text (e.g. company names like "Société");
# force UTF-8 so a Windows cp1252 console doesn't raise UnicodeEncodeError.
if sys.platform.startswith("win"):
for _stream in (sys.stdout, sys.stderr):
try:
_stream.reconfigure(encoding="utf-8")
except Exception:
pass


def log(msg: str) -> None:
"""Progress/diagnostics -> stderr (keeps stdout clean for the result)."""
print(msg, file=sys.stderr, flush=True)
"""Shared runtime and output helpers for market-scout scripts."""

import os
import sys
from pathlib import Path

# Provider data can contain non-ASCII company and speaker names.
if sys.platform.startswith("win"):
for _stream in (sys.stdout, sys.stderr):
try:
_stream.reconfigure(encoding="utf-8")
except Exception:
pass

try:
import truststore

truststore.inject_into_ssl()
except Exception:
pass


def log(msg: str) -> None:
"""Write human-readable progress to stderr."""
print(msg, file=sys.stderr, flush=True)


def emit(path: str | os.PathLike) -> None:
"""Write one absolute artifact path to stdout."""
print(str(Path(path).resolve()), flush=True)
Loading
Loading