# 🧠📈 CrewAI Stock Picker — Industry-Driven Multi-Agent Crew

End-to-end CrewAI pipeline: given an industry (and optional region + constraints), it discovers public companies, screens fundamentals, ranks valuation/quality/growth, scans recent news/risks, and outputs a ranked shortlist with a crisp thesis per pick.

> Python: Project targets 3.12.x and enforces < 3.13.

---

## ▶️ Quickstart (Windows PowerShell, uv-based)

We recommend using uv instead of manually managing `venv + pip`. uv ensures the correct Python (3.12) and reproducible dependencies.

```powershell
# 1) Ensure uv is installed (https://docs.astral.sh/uv/getting-started/installation/)
uv self update

# 2) Pin Python 3.12 for this project (toolchain libraries may not support 3.13 yet)
uv python pin 3.12

# (One-time) If you previously synced with another Python or copied a lockfile:
del uv.lock

# 3) Sync environment (creates .venv & installs deps from pyproject.toml)
uv sync

# 4) (Optional) install browsers for scraping
uv run playwright install

# 5) Set keys (Serper for web search; OpenAI for LLM)
# Option A: environment variables
setx OPENAI_API_KEY "sk-..."
setx SERPER_API_KEY "serper_..."
# Option B: copy .env.example to .env and fill values (auto-loaded)

# 6) Run (no manual venv activation needed; `uv run` auto-activates)
uv run python -m stock_picker.main --industry "semiconductors" --region "US" --n-picks 5 --min-mcap 1000000000 --valuation-pref balanced
```

Inputs:

- industry (str, required)
- region (str, optional)
- n_picks (int, default 5)
- min_mcap (int, default 500_000_000)
- valuation_pref (value | growth | balanced)

## 🗂️ Project layout

```
src/
  stock_picker/
    __init__.py
    crew.py
    main.py
    schemas.py
    config/
      agents.yaml
      tasks.yaml
outputs/
pyproject.toml
uv.lock
.python-version
```

- `pyproject.toml` → declare dependencies (`crewai[tools]`, `pydantic`, `yfinance`, `python-dotenv`, etc.)
- `uv.lock` → pinned versions (auto-generated by `uv sync`)
- `.python-version` → pins interpreter to 3.12 for this project

No requirements.txt needed — generate one only if you must hand off to pip-based systems:

```powershell
uv export --format=requirements-txt > requirements.txt
```

## Configuration

- Agents and tasks are defined in YAML under `src/stock_picker/config/`.
- Task context entries reference YAML task IDs (e.g., `company_discovery`), not Python names.
- Default process is sequential; the manager agent is available for hierarchical mode.

### Switch process mode

- Sequential (default): configured in `crew.py` via `process=Process.sequential`
- Hierarchical: change to `Process.hierarchical` and set `manager_agent=self.manager()`

### Planning

- Task planning is enabled (`planning=True` in `crew.py`) so CrewAI can break tasks into sub-steps. Set to `False` to disable.

### LLM models

- Default LLM is set in `crew.py`. Example:
  - `default_llm = LLM(model="gpt-4o-mini")` (main reasoning)
  - `function_llm = LLM(model="gpt-4o-mini")` (tool/function calls)
- You can upgrade select agents (e.g., manager, shortlist writer) to `gpt-4o` for richer synthesis

## Outputs

Artifacts are saved to `outputs/` for auditability:

- 01_industry_mapping.yaml
- 02_candidates.json
- 03_screened_metrics.json
- 04_valuation_rank.json
- 05_news_risks.json
- 06_shortlist.md

## Memory

- Crew memory is enabled and persists between runs (short-term, long-term, and entity memory).
- Storage uses ChromaDB (STM + Entities) and SQLite (LTM) under your OS user data dir.
  - Default base dir: `AppData/Local/CrewAI/<project_name>/` on Windows.
  - Control the base dir by setting `CREWAI_STORAGE_DIR` (e.g., in `.env`).
- Embeddings use OpenAI (`text-embedding-3-small`) via `OPENAI_API_KEY`.

Tips:
- Reset memories in code: `crew.reset_memories('short'|'long'|'entity'|'knowledge'|'agent_knowledge'|'kickoff_outputs'|'all')`.
- To fully clear local stores, remove the corresponding folder under the base dir above.

If you prefer the CLI, CrewAI exposes the same options:

```
crewai reset-memories --short
crewai reset-memories --long
crewai reset-memories --entities
crewai reset-memories --knowledge
crewai reset-memories --agent-knowledge
crewai reset-memories --kickoff-outputs
crewai reset-memories --all
```

Tip: if you use uv (or don’t have the venv activated), prefix with `uv run`:

```
uv run crewai reset-memories --all
```

## Troubleshooting

- Wrong Python version → Ensure you pinned 3.12 (`uv python pin 3.12`). Some tool deps do not support 3.13 yet.
- Dependency mismatch → delete `uv.lock`, rerun `uv sync`
- Serper TypeError → Ensure tools receive kwargs (the crew uses function-calling LLMs). Direct tests must call `SerperDevTool().run(query="...")`
- Serper 401/403/429 → recheck `SERPER_API_KEY`, quota, or network egress
- Playwright missing → run `uv run playwright install`
- Windows build tools → if `chroma-hnswlib` fails, install Microsoft C++ Build Tools

## Notes

- uv workflow: Use `uv add ...` instead of `pip install ...`
- uv workflow: Use `uv run python ...` instead of activating venv manually
- uv workflow: Don’t hand-edit `uv.lock`. Use `uv lock --upgrade` to refresh
- Data sources: This template uses generic web tools (Serper + WebsiteSearch + Scrape). For production fundamentals, consider a paid API and a custom tool
- Determinism: You can pin models and add stricter validation for outputs if needed
- Non-advice: Research tool only — not investment advice
