Spaces:
Running
Running
Bibhu Mishra commited on
Commit Β·
cfaf11b
1
Parent(s): 6ca2c8f
claude memory update
Browse files
CLAUDE.md
ADDED
|
@@ -0,0 +1,123 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# CLAUDE.md
|
| 2 |
+
|
| 3 |
+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
| 4 |
+
|
| 5 |
+
## What this project is
|
| 6 |
+
|
| 7 |
+
StockAdvisor is an autonomous AI paper-trading system. Three Python agents run on a schedule via GitHub Actions, write results to a shared PostgreSQL database (Neon.tech in production, SQLite locally), and a NestJS + Vue 3 web app lets users view reports, portfolio performance, and control agents.
|
| 8 |
+
|
| 9 |
+
## Development commands
|
| 10 |
+
|
| 11 |
+
### Full-stack dev (runs API + UI concurrently)
|
| 12 |
+
```bash
|
| 13 |
+
npm run dev # API on :3000, UI on :5173
|
| 14 |
+
```
|
| 15 |
+
|
| 16 |
+
### Individual workspaces
|
| 17 |
+
```bash
|
| 18 |
+
npm run dev:api # NestJS watch mode
|
| 19 |
+
npm run dev:ui # Vite dev server
|
| 20 |
+
npm run build # build both workspaces
|
| 21 |
+
```
|
| 22 |
+
|
| 23 |
+
### API (NestJS) β run from repo root
|
| 24 |
+
```bash
|
| 25 |
+
npm run lint --workspace=api
|
| 26 |
+
npm run test --workspace=api # jest
|
| 27 |
+
npm run test --workspace=api -- --testPathPattern=auth # single spec file
|
| 28 |
+
npm run test:e2e --workspace=api
|
| 29 |
+
```
|
| 30 |
+
|
| 31 |
+
### UI (Vue 3) β run from repo root
|
| 32 |
+
```bash
|
| 33 |
+
npm run lint --workspace=ui # oxlint + eslint
|
| 34 |
+
```
|
| 35 |
+
|
| 36 |
+
**Important**: `@nestjs/cli` and `vite` live in `api/node_modules/` and `ui/node_modules/` respectively, not the root. The root `npm run` scripts handle this; never try to call `nest` or `vite` directly from the root shell.
|
| 37 |
+
|
| 38 |
+
### Python agents
|
| 39 |
+
```bash
|
| 40 |
+
pip install -e . # install agents package + deps
|
| 41 |
+
|
| 42 |
+
# Run individual agents manually (bypasses market hours check)
|
| 43 |
+
FORCE_RUN=true python -m agents.market_analyst.run_market_analyst manual
|
| 44 |
+
FORCE_RUN=true python -m agents.paper_trader.run_paper_trader manual
|
| 45 |
+
FORCE_RUN=true python -m agents.retrospective.run_retrospective --triggered-by manual
|
| 46 |
+
|
| 47 |
+
# DB init/seed
|
| 48 |
+
python -c "from agents.core.db import init_db; init_db()"
|
| 49 |
+
# or:
|
| 50 |
+
npm run init-db
|
| 51 |
+
```
|
| 52 |
+
|
| 53 |
+
### Environment variables (`.env` at repo root)
|
| 54 |
+
```
|
| 55 |
+
ANTHROPIC_API_KEY, OPENAI_API_KEY, GEMINI_API_KEY
|
| 56 |
+
DATABASE_URL # postgresql://... for Neon; omit to use SQLite
|
| 57 |
+
JWT_SECRET
|
| 58 |
+
API_PORT # default 3000; HuggingFace sets this to 7860
|
| 59 |
+
VITE_API_URL # /api in prod, http://localhost:3000/api in dev
|
| 60 |
+
GITHUB_TOKEN # PAT with actions=write for workflow dispatch + repo write for artifacts
|
| 61 |
+
GITHUB_REPO # bibhu2020/stockadvisor
|
| 62 |
+
ARTIFACTS_PATH # https://github.com/<owner>/<media-repo>/<path> for PDF storage
|
| 63 |
+
```
|
| 64 |
+
|
| 65 |
+
## Architecture
|
| 66 |
+
|
| 67 |
+
### Runtime layers
|
| 68 |
+
|
| 69 |
+
```
|
| 70 |
+
GitHub Actions (cron) β Python Agents β PostgreSQL (Neon) β NestJS API β Vue 3 UI
|
| 71 |
+
```
|
| 72 |
+
|
| 73 |
+
The NestJS API serves the compiled Vue SPA at `/` and all API routes under `/api`. In production both run from a single Docker container on HuggingFace Spaces (port 7860).
|
| 74 |
+
|
| 75 |
+
### Python agents (`agents/`)
|
| 76 |
+
|
| 77 |
+
Each agent pipeline is a sequential chain of sub-agents. Every run is tracked via an `agent_runs` DB row whose `log` column is appended live so NestJS can stream it to the UI via SSE polling.
|
| 78 |
+
|
| 79 |
+
**`agents/core/`** β shared infrastructure:
|
| 80 |
+
- `base_agent.py` β `BaseAgent` class with LLM fallback chain: Anthropic (`claude-sonnet-4-6`) β OpenAI (`gpt-4o`) β Gemini (`gemini-2.0-flash`). Each provider uses tool-use loops (up to 10 rounds). Anthropic uses its native SDK; GPT-4o and Gemini share the OpenAI-compatible `_run_openai()` path.
|
| 81 |
+
- `orchestrator.py` β `AgentOrchestrator` context manager: creates `agent_runs` row on `__enter__`, flushes each log line to DB immediately, marks run completed/failed on `__exit__`.
|
| 82 |
+
- `db.py` β SQLAlchemy models + `SessionLocal` factory. Auto-detects `DATABASE_URL` for Postgres vs SQLite fallback. TypeORM (in `api/`) uses the same schema via separate entity files.
|
| 83 |
+
- `data_fetcher.py` β all market data: yfinance (primary) β Stooq CSV β Google Finance scrape for price; Yahoo/Google News RSS for sentiment; Finviz + Yahoo trending + Reddit RSS for candidates.
|
| 84 |
+
- `day_cache.py` β JSON file cache at `data/cache/YYYY-MM-DD.json`. Expensive fetches (fundamentals, technicals, sentiment) are cached per calendar day so re-runs within a day are fast and deterministic.
|
| 85 |
+
- `github_storage.py` β stores PDF artifacts to a GitHub repo via the Contents API (parsed from `ARTIFACTS_PATH` env var).
|
| 86 |
+
- `market_hours.py` β checks NYSE hours (America/New_York). Set `FORCE_RUN=true` to bypass.
|
| 87 |
+
|
| 88 |
+
**Market Analyst pipeline** (`agents/market_analyst/`):
|
| 89 |
+
1. `trend_spotter.py` β collects up to `MAX_CANDIDATES=20` tickers from Yahoo trending, Finviz, Reddit RSS; filters with `NOISE` set and `_valid_ticker()`.
|
| 90 |
+
2. `fundamental_analyst.py` β yfinance fundamentals; skips tickers with no price across all 3 sources.
|
| 91 |
+
3. `technical_analyst.py` β RSI, MACD, Bollinger, MA crossovers via `ta` library.
|
| 92 |
+
4. `sentiment_analyst.py` β LLM scores headlines from Yahoo + Google News RSS.
|
| 93 |
+
5. `volatility_analyst.py` β VIX, beta, sector volatility.
|
| 94 |
+
6. `synthesizer.py` β LLM call combining all sub-agent outputs + active strategy β top picks JSON.
|
| 95 |
+
|
| 96 |
+
**Paper Trader** (`agents/paper_trader/`): `position_monitor.py` checks stop-loss/profit-target/expiry οΏ½οΏ½ `trade_decision.py` (LLM) decides new buys β `trade_executor.py` writes positions/transactions/snapshots.
|
| 97 |
+
|
| 98 |
+
**Retrospective** (`agents/retrospective/`): `performance_calculator.py` β `pattern_analyzer.py` (LLM) β `strategy_tuner.py` (LLM, only if P&L < SPY) β `report_generator.py`. Strategy tuner inserts a new `strategies` row and sets it active.
|
| 99 |
+
|
| 100 |
+
### NestJS API (`api/src/`)
|
| 101 |
+
|
| 102 |
+
All routes are prefixed `/api`. Entities live in `api/src/common/entities/`; each module follows the standard NestJS pattern (module / controller / service). TypeORM uses `synchronize: false` β schema changes must be done via migrations or by running `init_db()` from the Python side first.
|
| 103 |
+
|
| 104 |
+
- **Auth**: JWT access + refresh tokens, bcrypt passwords. Role enum: `admin | guest | pending`. Users self-register (role=pending), admin approves via PATCH.
|
| 105 |
+
- **`agent-runs`**: `GET /agent-runs/:id/stream` polls DB every 500 ms and sends new log bytes as SSE. `POST /agent-runs/trigger/:type` dispatches a GitHub Actions workflow via the GitHub REST API (requires `GITHUB_TOKEN` with `actions=write`).
|
| 106 |
+
- **Database**: `app.module.ts` detects Postgres vs SQLite the same way `db.py` does; strips `channel_binding` from Neon connection strings (psycopg2 doesn't support it).
|
| 107 |
+
|
| 108 |
+
### Vue 3 UI (`ui/src/`)
|
| 109 |
+
|
| 110 |
+
- `ui/src/api/index.ts` β single axios instance; `VITE_API_URL` sets base URL; attaches JWT from `localStorage`; 401 on non-auth routes redirects to `/login`.
|
| 111 |
+
- `ui/src/stores/auth.ts` β Pinia store; `router/index.ts` calls `auth.fetchMe()` on every navigation and guards `meta.admin` routes.
|
| 112 |
+
- Views: Dashboard, Transactions, Reports, Strategies, Admin (agent runs + user management + settings + manual triggers), Profile.
|
| 113 |
+
|
| 114 |
+
### Deployment (HuggingFace Spaces)
|
| 115 |
+
|
| 116 |
+
Docker is a 4-stage build: `deps` (npm ci with native build tools) β `ui-builder` (Vite) β `api-builder` (nest build) β production image. Each stage explicitly copies workspace-level `node_modules` from `deps` because npm workspaces don't hoist `@nestjs/cli` or `vite` to the root.
|
| 117 |
+
|
| 118 |
+
SPA routing is handled by Express middleware registered in `main.ts` **before** `app.listen()` (which internally calls `app.init()`). It serves `ui/dist/index.html` for any request that doesn't start with `/api`. `ServeStaticModule` is intentionally absent β it is incompatible with Express 5 / path-to-regexp v8.
|
| 119 |
+
|
| 120 |
+
Push to `main` triggers `deploy-hf.yml` which force-pushes to the HuggingFace git remote. A `keepalive.yml` workflow pings the Space every 35 minutes to prevent it from sleeping.
|
| 121 |
+
|
| 122 |
+
### GitHub Actions secrets required (for agents to work)
|
| 123 |
+
`DATABASE_URL`, `ANTHROPIC_API_KEY`, `OPENAI_API_KEY`, `GEMINI_API_KEY`, `GH_TOKEN` (PAT with `actions=write` + repo write), `ARTIFACTS_PATH`, `HF_TOKEN` (for deploy).
|