Initial commit: invest-copilot app
This commit is contained in:
@@ -0,0 +1,46 @@
|
||||
# Invest Copilot — Vision & Positioning
|
||||
|
||||
## One-Liner
|
||||
AI-native investment research and portfolio copilot for retail investors who want institutional-grade intelligence.
|
||||
|
||||
## The Problem
|
||||
Retail investors have three choices:
|
||||
1. **Free but shallow** — Yahoo Finance, Finviz, TradingView (free tier). No AI analysis. No alternative data. No smart alerts.
|
||||
2. **Expensive & clunky** — Bloomberg Terminal ($25k/year), Koyfin ($300+/year), Morningstar. Legacy UI. No AI.
|
||||
3. **Manual** — Read SEC filings, scan Reddit, track options flow across 10+ tabs. Time-inefficient, emotion-driven.
|
||||
|
||||
## Our Edge (Why This Wins)
|
||||
| Capability | TradingView | Koyfin | Bloomberg | **Invest Copilot** |
|
||||
|---|---|---|---|---|
|
||||
| Real-time charts | ✅ | ✅ | ✅ | ✅ |
|
||||
| Screener | ✅ basic | ✅ basic | ✅ pro | ✅ AI-assisted |
|
||||
| SEC filing analysis | ❌ | ❌ | ✅ $25k/yr | ✅ LLM-powered |
|
||||
| Insider trades | ✅ | ✅ | ✅ | ✅ + clustering signals |
|
||||
| Institutional ownership | ✅ | ✅ | ✅ | ✅ + 13G amendment tracking |
|
||||
| Alternative data | ❌ | ❌ | ✅ paid | ✅ free tier + paid |
|
||||
| Sentiment analysis | ❌ | ❌ | ✅ paid | ✅ multi-source |
|
||||
| Sector rotation alerts | ❌ | ❌ | ✅ | ✅ automated |
|
||||
| Strategy backtesting | Pine Script only | ❌ | ✅ | ✅ multi-strategy |
|
||||
| Watchlist agents | ❌ | ❌ | ❌ | ✅ intelligent alerts |
|
||||
| Mobile-first UX | ❌ | ❌ | ❌ | ✅ native PWA |
|
||||
| AI copilot chat | ❌ | ❌ | ❌ | ✅ context-aware |
|
||||
|
||||
## Target User
|
||||
- Self-directed retail investors with $5k-$500k portfolios
|
||||
- Tech-comfortable (use Robinhood, Webull, or similar)
|
||||
- Want institutional-grade data without institutional price tags
|
||||
- Active traders (swing trading, position trading)
|
||||
- Value-time-rich (willing to research but want tools to accelerate)
|
||||
|
||||
## Core Principles
|
||||
1. **Data depth first** — Better data than free tools, approachable pricing
|
||||
2. **AI as amplifier, not replacement** — LLMs synthesize, humans decide
|
||||
3. **Mobile-first PWA** — Works on phone, tablet, desktop. No app store dependency.
|
||||
4. **Open data, open strategies** — Community-contributed strategies (like TradingView's Pine Script)
|
||||
5. **Privacy-first** — Watchlists, strategies, and alerts are private
|
||||
|
||||
## Success Metrics
|
||||
- **Day 1**: User can search a stock, see full profile, and get AI analysis in <10 seconds
|
||||
- **Month 1**: User creates watchlist, applies 2 strategies, receives 1+ actionable alert
|
||||
- **Month 3**: User has 3+ active watchlists, 5+ strategies, sector rotation alerts firing
|
||||
- **Month 6**: User's strategy backtest results beat buy-and-hold by >5% annualized
|
||||
@@ -0,0 +1,197 @@
|
||||
# Invest Copilot — Architecture
|
||||
|
||||
## Tech Stack
|
||||
|
||||
### Frontend (SPA + Mobile-First PWA)
|
||||
| Layer | Choice | Why |
|
||||
|---|---|---|
|
||||
| Framework | **Next.js 15** (App Router) | SSR for SEO, API routes for BFF, mature ecosystem |
|
||||
| Language | **TypeScript 5** | Type safety across all layers |
|
||||
| Styling | **TailwindCSS + Radix UI** | Design system foundation, accessible primitives |
|
||||
| State | **Zustand** | Lightweight, no boilerplate, perfect for PWA |
|
||||
| Charts | **Lightweight Charts (TradingView)** | Professional-grade financial charts |
|
||||
| Real-time | **Server-Sent Events (SSE)** | Push alerts to browser, simpler than WebSockets |
|
||||
| PWA | **next-pwa** | Offline support, installable, service worker |
|
||||
| AI/LLM | **OpenAI GPT-4o / Claude Sonnet** | Context-aware copilot, SEC filing analysis |
|
||||
|
||||
### Backend (Node.js + Python Microservices)
|
||||
| Service | Language | Why |
|
||||
|---|---|---|
|
||||
| API Gateway / BFF | **Node.js + Fastify** | TypeScript, fast, handles auth + routing |
|
||||
| Data Pipeline | **Python 3.12+** | yfinance, SEC EDGAR, sentiment analysis, ML |
|
||||
| Strategy Engine | **Python 3.12+** | Backtesting, signal generation, portfolio analytics |
|
||||
| Alert Agent | **Python + APScheduler** | Scheduled monitoring, notification dispatch |
|
||||
| Cache | **Redis** | Session store, rate limiting, hot data cache |
|
||||
|
||||
### Data Layer
|
||||
| Source | Storage | Purpose |
|
||||
|---|---|---|
|
||||
| Market data (OHLCV) | **PostgreSQL + TimescaleDB** | Time-series price data, efficient queries |
|
||||
| SEC filings | **PostgreSQL (JSONB)** | Structured filing data, full-text search |
|
||||
| Alternative data | **PostgreSQL** | Sentiment scores, insider trades, institutional data |
|
||||
| User data | **PostgreSQL** | Watchlists, strategies, screeners, preferences |
|
||||
| Cache/realtime | **Redis** | Session state, rate limiting, real-time alerts |
|
||||
| File storage | **S3-compatible (MinIO)** | SEC filing PDFs, backtest reports, exports |
|
||||
|
||||
### Infrastructure
|
||||
| Component | Choice | Why |
|
||||
|---|---|---|
|
||||
| Container | **Docker Compose** (dev), **K8s** (prod) | Dev simplicity, prod scalability |
|
||||
| CI/CD | **GitHub Actions** | Free, mature, integrates with everything |
|
||||
| Monitoring | **Prometheus + Grafana** | Metrics, alerting, dashboards |
|
||||
| Logging | **Loki** (via Docker Compose) | Structured logs, queryable |
|
||||
| Domain | Self-hosted | Full control, no vendor lock-in |
|
||||
|
||||
## Architecture Diagram (Text)
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ CLIENT LAYER │
|
||||
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌─────────────────┐ │
|
||||
│ │ Web App │ │ Mobile │ │ Tablet │ │ Desktop (PWA) │ │
|
||||
│ │ (PWA) │ │ (PWA) │ │ (PWA) │ │ (installable) │ │
|
||||
│ └────┬─────┘ └────┬─────┘ └────┬─────┘ └────────┬────────┘ │
|
||||
│ │ │ │ │ │
|
||||
│ └──────────────┴──────────────┴──────────────────┘ │
|
||||
│ │ HTTPS / SSE │
|
||||
├──────────────────────────────────────────────────────────────────┤
|
||||
│ API GATEWAY (Node.js + Fastify) │
|
||||
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌─────────────────┐ │
|
||||
│ │ Auth │ │ Routing │ │ Rate │ │ Request │ │
|
||||
│ │ (JWT) │ │ │ │ Limit │ │ Validation │ │
|
||||
│ └──────────┘ └──────────┘ └──────────┘ └─────────────────┘ │
|
||||
├──────────────────────────────────────────────────────────────────┤
|
||||
│ SERVICE LAYER │
|
||||
│ ┌──────────────┐ ┌──────────────┐ ┌───────────────────────┐ │
|
||||
│ │ Stock │ │ Strategy │ │ Watchlist & Alert │ │
|
||||
│ │ Service │ │ Engine │ │ Agent Service │ │
|
||||
│ │ (Node.js) │ │ (Python) │ │ (Python + APSched) │ │
|
||||
│ └──────┬───────┘ └──────┬───────┘ └──────────┬────────────┘ │
|
||||
│ │ │ │ │
|
||||
│ ┌──────┴──────────────────┴──────────────────────┴──────────┐ │
|
||||
│ │ DATA ACCESS LAYER │ │
|
||||
│ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌───────────┐ │ │
|
||||
│ │ │PostgreSQL│ │ Timescale│ │ Redis │ │ MinIO │ │ │
|
||||
│ │ │(user) │ │ (prices) │ │ (cache) │ │ (files) │ │ │
|
||||
│ │ └──────────┘ └──────────┘ └──────────┘ └───────────┘ │ │
|
||||
│ └───────────────────────────────────────────────────────────┘ │
|
||||
├──────────────────────────────────────────────────────────────────┤
|
||||
│ DATA SOURCE LAYER │
|
||||
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌─────────────────┐ │
|
||||
│ │ Massive │ │ Finnhub │ │ SEC │ │ Alternative │ │
|
||||
│ │ / │ │ │ │ EDGAR │ │ Data Sources │ │
|
||||
│ │ Polygon │ │ (free) │ │ │ │ (Reddit, │ │
|
||||
│ └──────────┘ └──────────┘ └──────────┘ │ GDELT, │ │
|
||||
│ │ yfinance) │ │
|
||||
│ └─────────────────┘ │
|
||||
├──────────────────────────────────────────────────────────────────┤
|
||||
│ AI / LAYER │
|
||||
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌─────────────────┐ │
|
||||
│ │ SEC │ │ Sentiment│ │ Copilot │ │ Sector │ │
|
||||
│ │ Filing │ │ Analysis │ │ Chat │ │ Rotation │ │
|
||||
│ │ Parser │ │ (NLP) │ │ Agent │ │ Detection │ │
|
||||
│ └──────────┘ └──────────┘ └──────────┘ └─────────────────┘ │
|
||||
└──────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## Data Flow
|
||||
|
||||
### Stock Search & Profile
|
||||
```
|
||||
User searches "AAPL"
|
||||
→ API Gateway validates request
|
||||
→ Stock Service checks Redis cache (TTL: 5 min)
|
||||
→ If miss: fetches from Massive/Polygon API
|
||||
→ Enriches with:
|
||||
- SEC filings (last 4 quarters)
|
||||
- Insider trades (last 90 days)
|
||||
- Institutional ownership
|
||||
- News + sentiment (Finnhub)
|
||||
- Peer group relative strength
|
||||
→ Returns to frontend
|
||||
→ AI Copilot generates summary analysis
|
||||
```
|
||||
|
||||
### Watchlist Monitoring
|
||||
```
|
||||
User creates watchlist "AI Winners" with 10 stocks
|
||||
→ Alert Agent subscribes to each ticker
|
||||
→ Every 5 minutes:
|
||||
- Check price vs strategy triggers
|
||||
- Scan for new SEC filings (8-K, 4)
|
||||
- Check news sentiment shift
|
||||
- Check options unusual activity
|
||||
→ If trigger fires:
|
||||
- Generate alert message via AI
|
||||
- Push via SSE to frontend
|
||||
- Store alert in DB
|
||||
- Optional: email/push notification
|
||||
```
|
||||
|
||||
### Sector Rotation Detection
|
||||
```
|
||||
Every 24 hours at 6:00 AM UTC:
|
||||
→ Fetch OHLCV for 11 sector ETFs
|
||||
→ Compute: 20-day, 50-day, 200-day momentum
|
||||
→ Rank sectors by relative strength vs SPY
|
||||
→ Compare to previous day's ranking
|
||||
→ If rank change ≥ 3: rotation detected
|
||||
→ Generate analysis:
|
||||
- What sector entered/rotated out
|
||||
- Macro context (yield curve, inflation)
|
||||
- Recommended ETF allocations
|
||||
→ Store rotation event
|
||||
→ Push to users with active sector rotation alerts
|
||||
```
|
||||
|
||||
## Migration Strategy (Design → TDD → DDD)
|
||||
|
||||
### Phase 1: Design-Driven (Weeks 1-3)
|
||||
- Use **Open Design** to generate UI mockups and visual directions
|
||||
- Build frontend shell with static data
|
||||
- Define API contracts (OpenAPI/Swagger)
|
||||
- Set up CI/CD pipeline
|
||||
- **Deliverable**: Clickable prototype, API spec, deployed pipeline
|
||||
|
||||
### Phase 2: Backend Foundation (Weeks 4-6)
|
||||
- Implement data ingestion pipeline (Python)
|
||||
- Build PostgreSQL + TimescaleDB schema
|
||||
- Implement core API (Node.js/Fastify)
|
||||
- Set up Redis cache layer
|
||||
- **Deliverable**: Working data pipeline, REST API with real data
|
||||
|
||||
### Phase 3: TDD Frontend (Weeks 7-10)
|
||||
- Implement stock search + profile (with tests)
|
||||
- Implement watchlist management (with tests)
|
||||
- Implement charting (with tests)
|
||||
- Implement strategy engine (with tests)
|
||||
- **Deliverable**: Functional SPA with 80%+ test coverage
|
||||
|
||||
### Phase 4: DDD Domain Layer (Weeks 11-14)
|
||||
- Define domain models (Stock, Watchlist, Strategy, Screener)
|
||||
- Implement aggregate roots and bounded contexts
|
||||
- Implement domain events (RotationDetected, AlertTriggered)
|
||||
- Implement CQRS for read/write separation
|
||||
- **Deliverable**: Clean architecture with DDD primitives
|
||||
|
||||
### Phase 5: AI Integration (Weeks 15-18)
|
||||
- SEC filing parser + NLP analysis
|
||||
- Copilot chat interface
|
||||
- Sentiment analysis pipeline
|
||||
- Alternative data fusion
|
||||
- **Deliverable**: AI-powered analysis on every stock page
|
||||
|
||||
### Phase 6: Alert Engine (Weeks 19-22)
|
||||
- Watchlist monitoring agents
|
||||
- Strategy trigger evaluation
|
||||
- SSE notification system
|
||||
- Email/push notification dispatch
|
||||
- **Deliverable**: Real-time intelligent alerts
|
||||
|
||||
### Phase 7: Polish & Scale (Weeks 23-26)
|
||||
- Performance optimization
|
||||
- Load testing
|
||||
- Security hardening
|
||||
- UX polish
|
||||
- Mobile PWA optimization
|
||||
- **Deliverable**: Production-ready invest-copilot
|
||||
@@ -0,0 +1,470 @@
|
||||
# Invest Copilot — Data Model
|
||||
|
||||
## Entity-Relationship Overview
|
||||
|
||||
```
|
||||
┌──────────────┐ ┌──────────────┐ ┌──────────────────┐
|
||||
│ User │ │ Watchlist │ │ Screener │
|
||||
│──────────────│ │──────────────│ │──────────────────│
|
||||
│ id (PK) │◄──┐ │ id (PK) │ │ id (PK) │
|
||||
│ email │ │ │ name │ │ name │
|
||||
│ name │ │ │ user_id (FK) │ │ user_id (FK) │
|
||||
│ avatar_url │ │ │ created_at │ │ created_at │
|
||||
│ timezone │ │ │ updated_at │ │ conditions (JSONB)│
|
||||
│ settings │ └────┬───────────┘ │ conditions_json │
|
||||
│ created_at │ │ │ created_at │
|
||||
└──────────────┘ │ └──────────────────┘
|
||||
│
|
||||
│ ┌──────────────────┐
|
||||
└───►│ WatchlistItem │
|
||||
│──────────────────│
|
||||
│ id (PK) │
|
||||
│ watchlist_id (FK)│
|
||||
│ ticker │
|
||||
│ type (stock/etf) │
|
||||
│ added_at │
|
||||
│ custom_notes │
|
||||
└────────┬─────────┘
|
||||
│
|
||||
│ ┌──────────────────┐
|
||||
└───►│ PriceHistory │
|
||||
│──────────────────│
|
||||
│ id (PK) │
|
||||
│ ticker │
|
||||
│ date (Timescale) │
|
||||
│ open │
|
||||
│ high │
|
||||
│ low │
|
||||
│ close │
|
||||
│ volume │
|
||||
│ adjusted_close │
|
||||
└────────────────────┘
|
||||
|
||||
┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐
|
||||
│ Strategy │ │ WatchlistStrategy│ │ Alert │
|
||||
│──────────────────│ │──────────────────│ │──────────────────│
|
||||
│ id (PK) │◄────│ id (PK) │ │ id (PK) │
|
||||
│ user_id (FK) │ │ watchlist_id(FK) │ │ watchlist_id(FK) │
|
||||
│ name │ │ strategy_id(FK) │ │ strategy_id(FK) │
|
||||
│ description │ │ is_active │ │ type │
|
||||
│ type (technical/ │ │ created_at │ │ trigger_type │
|
||||
│ fundamental) │ │ conditions (JSONB)│ │ message_template │
|
||||
│ conditions (JSONB)│ │ created_at │ │ triggered_at │
|
||||
│ backtest_result │ │ updated_at │ │ resolved_at │
|
||||
│ created_at │ └────────┬─────────┘ │ resolved_at │
|
||||
│ updated_at │ │ │ created_at │
|
||||
└──────────────────┘ │ └──────────────────┘
|
||||
│
|
||||
│ ┌──────────────────┐
|
||||
└───►│ SectorRotation │
|
||||
│──────────────────│
|
||||
│ id (PK) │
|
||||
│ date │
|
||||
│ sector_ticker │
|
||||
│ rank_now │
|
||||
│ rank_previous │
|
||||
│ rank_change │
|
||||
│ momentum_20d │
|
||||
│ momentum_50d │
|
||||
│ momentum_200d │
|
||||
│ relative_strength │
|
||||
│ rotation_signal │
|
||||
│ macro_context │
|
||||
│ analysis_summary │
|
||||
└────────────────────┘
|
||||
```
|
||||
|
||||
## Detailed Schema
|
||||
|
||||
### users
|
||||
```sql
|
||||
CREATE TABLE users (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
email VARCHAR(255) UNIQUE NOT NULL,
|
||||
password_hash VARCHAR(255), -- NULL if OAuth-only
|
||||
name VARCHAR(255),
|
||||
avatar_url TEXT,
|
||||
timezone VARCHAR(50) DEFAULT 'UTC',
|
||||
settings JSONB DEFAULT '{}', -- {currency: 'USD', theme: 'dark', alerts_enabled: true}
|
||||
created_at TIMESTAMPTZ DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ DEFAULT NOW()
|
||||
);
|
||||
```
|
||||
|
||||
### watchlists
|
||||
```sql
|
||||
CREATE TABLE watchlists (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
name VARCHAR(255) NOT NULL,
|
||||
description TEXT,
|
||||
is_default BOOLEAN DEFAULT FALSE,
|
||||
created_at TIMESTAMPTZ DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ DEFAULT NOW()
|
||||
);
|
||||
|
||||
CREATE INDEX idx_watchlists_user ON watchlists(user_id);
|
||||
```
|
||||
|
||||
### watchlist_items
|
||||
```sql
|
||||
CREATE TABLE watchlist_items (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
watchlist_id UUID NOT NULL REFERENCES watchlists(id) ON DELETE CASCADE,
|
||||
ticker VARCHAR(20) NOT NULL,
|
||||
type VARCHAR(20) NOT NULL CHECK (type IN ('stock', 'etf', 'index')),
|
||||
custom_notes TEXT,
|
||||
added_at TIMESTAMPTZ DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- Prevent duplicates: a watchlist can't have the same ticker twice
|
||||
CREATE UNIQUE INDEX idx_watchlist_items_unique ON watchlist_items(watchlist_id, ticker);
|
||||
```
|
||||
|
||||
### prices (TimescaleDB hypertable)
|
||||
```sql
|
||||
-- Hypertable for time-series price data
|
||||
CREATE TABLE prices (
|
||||
ticker VARCHAR(20) NOT NULL,
|
||||
date TIMESTAMPTZ NOT NULL,
|
||||
open DECIMAL(15,4),
|
||||
high DECIMAL(15,4),
|
||||
low DECIMAL(15,4),
|
||||
close DECIMAL(15,4),
|
||||
volume BIGINT,
|
||||
adjusted_close DECIMAL(15,4),
|
||||
PRIMARY KEY (ticker, date)
|
||||
);
|
||||
|
||||
-- Convert to hypertable (TimescaleDB extension)
|
||||
SELECT create_hypertable('prices', 'date');
|
||||
|
||||
-- Compression for older data (automated by Timescale policy)
|
||||
CREATE POLICY prices_compress_policy ON prices
|
||||
FOR ALL
|
||||
USING (date < NOW() - INTERVAL '90 days');
|
||||
|
||||
-- Continuous aggregate for common timeframes
|
||||
CREATE MATERIALIZED VIEW prices_daily
|
||||
WITH (timescaledb.continuous) AS
|
||||
SELECT ticker,
|
||||
time_bucket('1 day', date) AS bucket,
|
||||
first(open, date) AS open,
|
||||
max(high) AS high,
|
||||
min(low) AS low,
|
||||
last(close, date) AS close,
|
||||
sum(volume) AS volume
|
||||
FROM prices
|
||||
GROUP BY ticker, bucket;
|
||||
```
|
||||
|
||||
### stock_profiles
|
||||
```sql
|
||||
CREATE TABLE stock_profiles (
|
||||
ticker VARCHAR(20) PRIMARY KEY,
|
||||
name VARCHAR(500),
|
||||
exchange VARCHAR(20),
|
||||
sector VARCHAR(100),
|
||||
industry VARCHAR(200),
|
||||
market_cap BIGINT,
|
||||
description TEXT,
|
||||
website TEXT,
|
||||
ceo VARCHAR(255),
|
||||
employees INTEGER,
|
||||
pe_ratio DECIMAL(10,2),
|
||||
eps DECIMAL(10,4),
|
||||
dividend_yield DECIMAL(8,4),
|
||||
beta DECIMAL(6,4),
|
||||
last_updated TIMESTAMPTZ DEFAULT NOW()
|
||||
);
|
||||
```
|
||||
|
||||
### sec_filings
|
||||
```sql
|
||||
CREATE TABLE sec_filings (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
ticker VARCHAR(20) NOT NULL,
|
||||
cik VARCHAR(20),
|
||||
form_type VARCHAR(10) NOT NULL, -- 10-K, 10-Q, 8-K, 4, 13F, 13D, 13G
|
||||
filing_date DATE NOT NULL,
|
||||
report_date DATE,
|
||||
accession_number VARCHAR(50),
|
||||
url TEXT,
|
||||
content_summary TEXT, -- AI-generated summary
|
||||
key_metrics JSONB, -- Extracted financials from 10-K/10-Q
|
||||
sentiment_score DECIMAL(5,4), -- NLP sentiment: -1 to +1
|
||||
tags TEXT[], -- e.g., ['earnings', 'executive_change', 'litigation']
|
||||
created_at TIMESTAMPTZ DEFAULT NOW()
|
||||
);
|
||||
|
||||
CREATE INDEX idx_sec_filings_ticker ON sec_filings(ticker);
|
||||
CREATE INDEX idx_sec_filings_form ON sec_filings(form_type);
|
||||
CREATE INDEX idx_sec_filings_date ON sec_filings(filing_date);
|
||||
```
|
||||
|
||||
### insider_trades
|
||||
```sql
|
||||
CREATE TABLE insider_trades (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
ticker VARCHAR(20) NOT NULL,
|
||||
insider_name VARCHAR(500),
|
||||
insider_title VARCHAR(500),
|
||||
transaction_date DATE NOT NULL,
|
||||
transaction_type VARCHAR(10), -- Buy, Sell, Gift, In-Ex
|
||||
shares INTEGER,
|
||||
price_per_share DECIMAL(10,4),
|
||||
total_value DECIMAL(15,4),
|
||||
shares_owned_after INTEGER,
|
||||
filing_date DATE,
|
||||
source_url TEXT,
|
||||
created_at TIMESTAMPTZ DEFAULT NOW()
|
||||
);
|
||||
|
||||
CREATE INDEX idx_insider_trades_ticker ON insider_trades(ticker);
|
||||
CREATE INDEX idx_insider_trades_type ON insider_trades(transaction_type);
|
||||
```
|
||||
|
||||
### strategies
|
||||
```sql
|
||||
CREATE TABLE strategies (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
name VARCHAR(255) NOT NULL,
|
||||
description TEXT,
|
||||
type VARCHAR(20) NOT NULL CHECK (type IN ('technical', 'fundamental', 'hybrid')),
|
||||
conditions JSONB NOT NULL, -- Structured strategy conditions
|
||||
backtest_results JSONB, -- Last backtest result
|
||||
created_at TIMESTAMPTZ DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ DEFAULT NOW()
|
||||
);
|
||||
```
|
||||
|
||||
### strategy_conditions (JSONB schema example)
|
||||
```json
|
||||
{
|
||||
"type": "technical",
|
||||
"rules": [
|
||||
{
|
||||
"indicator": "rsi",
|
||||
"operator": "lt",
|
||||
"value": 30,
|
||||
"description": "RSI below 30 (oversold)"
|
||||
},
|
||||
{
|
||||
"indicator": "sma",
|
||||
"params": {"period": 200, "source": "close"},
|
||||
"operator": "gt",
|
||||
"value": null,
|
||||
"description": "Price above 200-day SMA"
|
||||
},
|
||||
{
|
||||
"indicator": "volume",
|
||||
"operator": "gt",
|
||||
"value": 1.5,
|
||||
"description": "Volume > 1.5x average 20-day volume"
|
||||
}
|
||||
],
|
||||
"logic": "AND"
|
||||
}
|
||||
```
|
||||
|
||||
### watchlist_strategies
|
||||
```sql
|
||||
CREATE TABLE watchlist_strategies (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
watchlist_id UUID NOT NULL REFERENCES watchlists(id) ON DELETE CASCADE,
|
||||
strategy_id UUID NOT NULL REFERENCES strategies(id) ON DELETE CASCADE,
|
||||
is_active BOOLEAN DEFAULT TRUE,
|
||||
created_at TIMESTAMPTZ DEFAULT NOW()
|
||||
);
|
||||
|
||||
CREATE UNIQUE INDEX idx_watchlist_strategies_unique ON watchlist_strategies(watchlist_id, strategy_id);
|
||||
```
|
||||
|
||||
### alerts
|
||||
```sql
|
||||
CREATE TABLE alerts (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
watchlist_id UUID NOT NULL REFERENCES watchlists(id) ON DELETE CASCADE,
|
||||
strategy_id UUID REFERENCES strategies(id),
|
||||
ticker VARCHAR(20),
|
||||
type VARCHAR(30) NOT NULL, -- strategy_trigger, sec_filing, sentiment, rotation, price
|
||||
trigger_type VARCHAR(50),
|
||||
message TEXT NOT NULL,
|
||||
severity VARCHAR(10) DEFAULT 'info' CHECK (severity IN ('info', 'warning', 'critical')),
|
||||
status VARCHAR(20) DEFAULT 'active' CHECK (status IN ('active', 'resolved', 'dismissed')),
|
||||
triggered_at TIMESTAMPTZ DEFAULT NOW(),
|
||||
resolved_at TIMESTAMPTZ,
|
||||
metadata JSONB DEFAULT '{}'
|
||||
);
|
||||
|
||||
CREATE INDEX idx_alerts_watchlist ON alerts(watchlist_id);
|
||||
CREATE INDEX idx_alerts_status ON alerts(status);
|
||||
CREATE INDEX idx_alerts_triggered ON alerts(triggered_at);
|
||||
```
|
||||
|
||||
### sector_rotations
|
||||
```sql
|
||||
CREATE TABLE sector_rotations (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
detection_date DATE NOT NULL,
|
||||
sector_ticker VARCHAR(20) NOT NULL, -- XLK, XLF, etc.
|
||||
sector_name VARCHAR(100),
|
||||
rank_now INTEGER,
|
||||
rank_previous INTEGER,
|
||||
rank_change INTEGER,
|
||||
momentum_20d DECIMAL(8,4),
|
||||
momentum_50d DECIMAL(8,4),
|
||||
momentum_200d DECIMAL(8,4),
|
||||
relative_strength DECIMAL(8,4),
|
||||
rotation_signal VARCHAR(20), -- 'in', 'out', 'stable', 'accelerating'
|
||||
macro_context JSONB,
|
||||
analysis_summary TEXT,
|
||||
created_at TIMESTAMPTZ DEFAULT NOW()
|
||||
);
|
||||
|
||||
CREATE INDEX idx_sector_rotations_date ON sector_rotations(detection_date);
|
||||
CREATE INDEX idx_sector_rotations_signal ON sector_rotations(rotation_signal);
|
||||
```
|
||||
|
||||
### screeners
|
||||
```sql
|
||||
CREATE TABLE screeners (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
name VARCHAR(255) NOT NULL,
|
||||
description TEXT,
|
||||
conditions JSONB NOT NULL,
|
||||
results_count INTEGER DEFAULT 0,
|
||||
last_run_at TIMESTAMPTZ,
|
||||
created_at TIMESTAMPTZ DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ DEFAULT NOW()
|
||||
);
|
||||
```
|
||||
|
||||
### screener_results
|
||||
```sql
|
||||
CREATE TABLE screener_results (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
screener_id UUID NOT NULL REFERENCES screeners(id) ON DELETE CASCADE,
|
||||
ticker VARCHAR(20) NOT NULL,
|
||||
match_score DECIMAL(5,4),
|
||||
ranked_position INTEGER,
|
||||
result_data JSONB,
|
||||
generated_at TIMESTAMPTZ DEFAULT NOW()
|
||||
);
|
||||
|
||||
CREATE INDEX idx_screener_results_screener ON screener_results(screener_id);
|
||||
```
|
||||
|
||||
### peer_groups
|
||||
```sql
|
||||
CREATE TABLE peer_groups (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
ticker VARCHAR(20) NOT NULL,
|
||||
peer_ticker VARCHAR(20) NOT NULL,
|
||||
similarity_score DECIMAL(5,4), -- Based on sector, industry, market cap
|
||||
created_at TIMESTAMPTZ DEFAULT NOW(),
|
||||
UNIQUE (ticker, peer_ticker)
|
||||
);
|
||||
|
||||
CREATE INDEX idx_peer_groups_ticker ON peer_groups(ticker);
|
||||
```
|
||||
|
||||
### rotation_alerts_preferences
|
||||
```sql
|
||||
CREATE TABLE rotation_alert_preferences (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
sectors TEXT[] NOT NULL DEFAULT '{}', -- ['tech', 'healthcare', 'energy', ...]
|
||||
min_rank_change INTEGER DEFAULT 2,
|
||||
email_enabled BOOLEAN DEFAULT TRUE,
|
||||
push_enabled BOOLEAN DEFAULT TRUE,
|
||||
created_at TIMESTAMPTZ DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ DEFAULT NOW()
|
||||
);
|
||||
```
|
||||
|
||||
## TimescaleDB Optimization
|
||||
|
||||
### Compression Policy
|
||||
```sql
|
||||
-- Compress data older than 90 days
|
||||
SELECT add_compress_policy('prices', INTERVAL '90 days');
|
||||
|
||||
-- Reorder by ticker for better compression
|
||||
SELECT add_reorder_policy('prices', 'ticker');
|
||||
```
|
||||
|
||||
### Continuous Aggregates
|
||||
```sql
|
||||
-- 1-hour aggregates for intraday analysis
|
||||
CREATE MATERIALIZED VIEW prices_hourly
|
||||
WITH (timescaledb.continuous) AS
|
||||
SELECT ticker,
|
||||
time_bucket('1 hour', date) AS bucket,
|
||||
first(open, date) AS open,
|
||||
max(high) AS high,
|
||||
min(low) AS low,
|
||||
last(close, date) AS close,
|
||||
sum(volume) AS volume
|
||||
FROM prices
|
||||
GROUP BY ticker, bucket;
|
||||
|
||||
-- 1-day aggregates for trend analysis
|
||||
CREATE MATERIALIZED VIEW prices_daily
|
||||
WITH (timescaledb.continuous) AS
|
||||
SELECT ticker,
|
||||
time_bucket('1 day', date) AS bucket,
|
||||
first(open, date) AS open,
|
||||
max(high) AS high,
|
||||
min(low) AS low,
|
||||
last(close, date) AS close,
|
||||
sum(volume) AS volume
|
||||
FROM prices
|
||||
GROUP BY ticker, bucket;
|
||||
```
|
||||
|
||||
### Indexes for Common Queries
|
||||
```sql
|
||||
-- Composite indexes for frequent query patterns
|
||||
CREATE INDEX idx_prices_ticker_date ON prices(ticker, date DESC);
|
||||
CREATE INDEX idx_prices_date_ticker ON prices(date, ticker);
|
||||
CREATE INDEX idx_sec_filings_ticker_type ON sec_filings(ticker, form_type);
|
||||
CREATE INDEX idx_insider_trades_ticker_date ON insider_trades(ticker, transaction_date DESC);
|
||||
```
|
||||
|
||||
## Data Ingestion Pipeline
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ DATA INGESTION PIPELINE │
|
||||
│ │
|
||||
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────┐ │
|
||||
│ │ Price │ │ SEC │ │ Alternative │ │
|
||||
│ │ Ingestor │ │ Filing │ │ Data │ │
|
||||
│ │ (hourly) │ │ Parser │ │ Pipeline │ │
|
||||
│ │ │ │ (daily) │ │ (daily) │ │
|
||||
│ └──────┬──────┘ └──────┬──────┘ └────────┬────────┘ │
|
||||
│ │ │ │ │
|
||||
│ ▼ ▼ ▼ │
|
||||
│ ┌─────────────────────────────────────────────────────┐ │
|
||||
│ │ PostgreSQL + TimescaleDB │ │
|
||||
│ │ (prices, sec_filings, insider_trades) │ │
|
||||
│ └─────────────────────────────────────────────────────┘ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Ingestion Schedules
|
||||
| Data | Source | Frequency | Rate Limit |
|
||||
|---|---|---|---|
|
||||
| OHLCV (1min) | Massive/Polygon | Every 1 min (market hours) | Unlimited (paid tier) |
|
||||
| OHLCV (1day) | Massive/Polygon | Daily close | Unlimited (paid tier) |
|
||||
| SEC filings | EDGAR RSS/API | Every 15 min | 10 req/sec |
|
||||
| Insider trades | EDGAR | Every 6 hours | 10 req/sec |
|
||||
| Institutional holdings | EDGAR 13F | Quarterly (Feb, May, Aug, Nov) | 10 req/sec |
|
||||
| Company news | Finnhub | Every 5 min | 60 req/min (free) |
|
||||
| Sentiment scores | Finnhub + NLP pipeline | Every hour | Internal |
|
||||
| Sector rotation | Computed from prices | Daily 6 AM UTC | Internal |
|
||||
| Google Trends | pytrends | Daily | Rate limited |
|
||||
| Reddit sentiment | Reddit API | Every 6 hours | Rate limited |
|
||||
@@ -0,0 +1,374 @@
|
||||
# Invest Copilot — Domain Model (DDD)
|
||||
|
||||
## Bounded Contexts
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ INVEST COPILOT SYSTEM │
|
||||
│ │
|
||||
│ ┌──────────────┐ ┌──────────────┐ ┌───────────────────────┐ │
|
||||
│ │ RESEARCH │ │ PORTFOLIO │ │ ALERTEVENTS │ │
|
||||
│ │ CONTEXT │ │ CONTEXT │ │ CONTEXT │ │
|
||||
│ │ │ │ │ │ │ │
|
||||
│ │ Stock │ │ Watchlist │ │ Watchlist │ │
|
||||
│ │ Profile │ │ Strategy │ │ Agent │ │
|
||||
│ │ Peer Group │ │ Screener │ │ Alert Engine │ │
|
||||
│ │ SEC Filing │ │ Backtest │ │ Notification │ │
|
||||
│ │ Sentiment │ │ Rotation │ │ Monitoring │ │
|
||||
│ └──────┬───────┘ └──────┬───────┘ └──────────┬──────────┘ │
|
||||
│ │ │ │ │
|
||||
│ │ ┌──────────────┴──────────────────────┐ │
|
||||
│ │ │ SHARED KERNEL │ │
|
||||
│ │ │ MarketData, Ticker, Sector, │ │
|
||||
│ │ │ PriceEvent, SectorRotation │ │
|
||||
│ │ └───────────────────────────────────────┘ │
|
||||
│ │
|
||||
├──────────────────────────────────────────────────────────────────┤
|
||||
│ APPLICATION LAYER │
|
||||
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌─────────────────┐ │
|
||||
│ │ Stock │ │ Watch │ │ Strategy│ │ Alert │ │
|
||||
│ │ Service │ │ list │ │ Service │ │ Service │ │
|
||||
│ └──────────┘ └──────────┘ └──────────┘ └─────────────────┘ │
|
||||
├──────────────────────────────────────────────────────────────────┤
|
||||
│ DOMAIN LAYER │
|
||||
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌─────────────────┐ │
|
||||
│ │ Stock │ │ Watch- │ │ Strategy │ │ Alert │ │
|
||||
│ │ Entity │ │ list │ │ Entity │ │ Entity │ │
|
||||
│ │ Aggr │ │ Aggr │ │ Aggr │ │ Aggr │ │
|
||||
│ └──────────┘ └──────────┘ └──────────┘ └─────────────────┘ │
|
||||
├──────────────────────────────────────────────────────────────────┤
|
||||
│ INFRASTRUCTURE LAYER │
|
||||
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌─────────────────┐ │
|
||||
│ │ Price │ │ SEC │ │ Strategy│ │ SSE │ │
|
||||
│ │ Rep │ │ Rep │ │ Rep │ │ Push │ │
|
||||
│ └──────────┘ └──────────┘ └──────────┘ └─────────────────┘ │
|
||||
└──────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## Bounded Context 1: RESEARCH
|
||||
|
||||
**Responsibility**: Provide comprehensive stock information and analysis.
|
||||
|
||||
### Entities & Value Objects
|
||||
|
||||
```
|
||||
Stock (Aggregate Root)
|
||||
├── ticker: Ticker
|
||||
├── name: string
|
||||
├── sector: Sector (Value Object)
|
||||
├── industry: string
|
||||
├── marketCap: Money (Value Object)
|
||||
├── exchange: string
|
||||
└── profile: CompanyProfile (Value Object)
|
||||
|
||||
CompanyProfile (Value Object)
|
||||
├── description: string
|
||||
├── website: string
|
||||
├── ceo: string
|
||||
├── employees: int
|
||||
├── peRatio: decimal
|
||||
├── eps: decimal
|
||||
├── dividendYield: decimal
|
||||
└── beta: decimal
|
||||
|
||||
Sector (Value Object)
|
||||
├── code: string // e.g., "XLK"
|
||||
├── name: string // e.g., "Technology"
|
||||
├── gicsCode: string // e.g., "45"
|
||||
└── peers: List<Ticker>
|
||||
|
||||
PeerGroup (Aggregate Root)
|
||||
├── ticker: Ticker
|
||||
├── peers: List<Peer>
|
||||
└── similarityScores: Map<Ticker, float>
|
||||
|
||||
Peer (Value Object)
|
||||
├── ticker: Ticker
|
||||
├── name: string
|
||||
├── similarityScore: float
|
||||
└── relativeStrength: decimal
|
||||
|
||||
SecFiling (Entity within Stock aggregate)
|
||||
├── formType: FormType (enum: 10K, 10Q, 8K, 4, 13F, 13D, 13G)
|
||||
├── filingDate: Date
|
||||
├── reportDate: Date
|
||||
├── accessionNumber: string
|
||||
├── url: string
|
||||
├── contentSummary: string
|
||||
├── sentimentScore: decimal
|
||||
└── tags: List<string>
|
||||
|
||||
InsiderTrade (Entity within Stock aggregate)
|
||||
├── insiderName: string
|
||||
├── insiderTitle: string
|
||||
├── transactionDate: Date
|
||||
├── transactionType: TransactionType (enum: BUY, SELL, GIFT, IN_EX)
|
||||
├── shares: int
|
||||
├── pricePerShare: Money
|
||||
├── totalValue: Money
|
||||
└── sharesOwnedAfter: int
|
||||
|
||||
SentimentSignal (Value Object)
|
||||
├── source: string // "finnhub", "reddit", "gdelt"
|
||||
├── score: decimal // -1.0 to +1.0
|
||||
├── confidence: float
|
||||
├── timestamp: DateTime
|
||||
└── context: string
|
||||
```
|
||||
|
||||
### Domain Events
|
||||
- `StockProfileUpdated` — Stock profile refreshed from data source
|
||||
- `SecFilingReceived` — New SEC filing detected
|
||||
- `InsiderTradeDetected` — New insider trade filed
|
||||
- `SentimentShifted` — Sentiment score changed significantly
|
||||
|
||||
### Aggregates
|
||||
- **Stock** is the root aggregate. All research data (filings, insider trades, sentiment, peer info) are either entities within this aggregate or related via repository.
|
||||
|
||||
## Bounded Context 2: PORTFOLIO (WATCHLIST + STRATEGY)
|
||||
|
||||
**Responsibility**: Manage watchlists, strategies, screeners, and sector rotation.
|
||||
|
||||
### Entities & Value Objects
|
||||
|
||||
```
|
||||
Watchlist (Aggregate Root)
|
||||
├── id: UUID
|
||||
├── name: string
|
||||
├── owner: UserId
|
||||
├── items: List<WatchlistItem>
|
||||
├── strategies: List<StrategyReference>
|
||||
└── created/updated timestamps
|
||||
|
||||
WatchlistItem (Entity)
|
||||
├── ticker: Ticker
|
||||
├── type: AssetType (enum: STOCK, ETF, INDEX)
|
||||
├── addedAt: DateTime
|
||||
├── customNotes: string
|
||||
└── priceAtAddition: Money
|
||||
|
||||
Strategy (Aggregate Root)
|
||||
├── id: UUID
|
||||
├── name: string
|
||||
├── description: string
|
||||
├── type: StrategyType (enum: TECHNICAL, FUNDAMENTAL, HYBRID)
|
||||
├── conditions: StrategyConditions (Value Object)
|
||||
├── backtestResults: BacktestResult (Value Object)
|
||||
├── createdBy: UserId
|
||||
└── created/updated timestamps
|
||||
|
||||
StrategyConditions (Value Object)
|
||||
├── rules: List<StrategyRule>
|
||||
├── logic: LogicOperator (AND / OR)
|
||||
└── timeframe: string // e.g., "1D", "1W", "1M"
|
||||
|
||||
StrategyRule (Value Object)
|
||||
├── indicator: string // "rsi", "sma", "macd", "pe_ratio", etc.
|
||||
├── operator: Operator (enum: LT, GT, LTE, GTE, EQ, NEQ, CROSSOVER, CROSSBELOW)
|
||||
├── value: decimal
|
||||
├── period: int // optional, for indicators like SMA
|
||||
├── source: string // optional, for SMA: "close", "volume"
|
||||
└── description: string
|
||||
|
||||
BacktestResult (Value Object)
|
||||
├── startDate: Date
|
||||
├── endDate: Date
|
||||
├── totalReturn: decimal
|
||||
├── annualizedReturn: decimal
|
||||
├── maxDrawdown: decimal
|
||||
├── sharpeRatio: decimal
|
||||
├── winRate: float
|
||||
├── totalTrades: int
|
||||
├── avgHoldTime: string
|
||||
└── equityCurve: List<Decimal>
|
||||
|
||||
Screener (Aggregate Root)
|
||||
├── id: UUID
|
||||
├── name: string
|
||||
├── description: string
|
||||
├── conditions: ScreenerConditions (Value Object)
|
||||
├── lastRunAt: DateTime
|
||||
├── createdBy: UserId
|
||||
└── results: List<ScreenerResult> (stored in screener_results table)
|
||||
|
||||
ScreenerConditions (Value Object)
|
||||
├── filters: List<ScreenerFilter>
|
||||
├── sortBy: string
|
||||
├── sortOrder: string // "asc" / "desc"
|
||||
└── limit: int
|
||||
|
||||
ScreenerFilter (Value Object)
|
||||
├── field: string // "market_cap", "pe_ratio", "rsi", etc.
|
||||
├── operator: Operator
|
||||
├── value: decimal
|
||||
└── description: string
|
||||
|
||||
SectorRotation (Entity within Watchlist context)
|
||||
├── date: Date
|
||||
├── sector: Sector
|
||||
├── rankNow: int
|
||||
├── rankPrevious: int
|
||||
├── rankChange: int
|
||||
├── momentum20d: decimal
|
||||
├── momentum50d: decimal
|
||||
├── momentum200d: decimal
|
||||
├── relativeStrength: decimal
|
||||
├── signal: RotationSignal (enum: IN, OUT, STABLE, ACCELERATING)
|
||||
├── macroContext: jsonb
|
||||
└── analysisSummary: string
|
||||
```
|
||||
|
||||
### Domain Events
|
||||
- `WatchlistCreated` — New watchlist created
|
||||
- `WatchlistItemAdded` — Ticker added to watchlist
|
||||
- `WatchlistItemRemoved` — Ticker removed from watchlist
|
||||
- `StrategyCreated` — New strategy defined
|
||||
- `StrategyTriggered` — Strategy condition met for a ticker
|
||||
- `SectorRotationDetected` — Sector rotation event
|
||||
- `ScreenerResultsGenerated` — Screener completed run
|
||||
|
||||
### Aggregates
|
||||
- **Watchlist** is the root. Items and strategies are entities within it.
|
||||
- **Strategy** is independent (can be shared across watchlists).
|
||||
- **Screener** is independent per user.
|
||||
- **SectorRotation** is stored as events, queried for history.
|
||||
|
||||
## Bounded Context 3: ALERTEVENTS
|
||||
|
||||
**Responsibility**: Monitor watchlists, evaluate triggers, dispatch notifications.
|
||||
|
||||
### Entities & Value Objects
|
||||
|
||||
```
|
||||
Alert (Aggregate Root)
|
||||
├── id: UUID
|
||||
├── watchlist: Watchlist (reference)
|
||||
├── strategy: Strategy? (nullable, some alerts are non-strategy)
|
||||
├── ticker: Ticker
|
||||
├── type: AlertType (enum: STRATEGY_TRIGGER, SEC_FILING, SENTIMENT, ROTATION, PRICE)
|
||||
├── triggerType: string
|
||||
├── message: string
|
||||
├── severity: Severity (enum: INFO, WARNING, CRITICAL)
|
||||
├── status: AlertStatus (enum: ACTIVE, RESOLVED, DISMISSED)
|
||||
├── triggeredAt: DateTime
|
||||
├── resolvedAt: DateTime?
|
||||
└── metadata: jsonb
|
||||
|
||||
AlertTrigger (Value Object)
|
||||
├── source: string // strategy name, filing type, etc.
|
||||
├── condition: string // what triggered
|
||||
├── currentValue: decimal
|
||||
├── thresholdValue: decimal
|
||||
└── timestamp: DateTime
|
||||
|
||||
Notification (Value Object)
|
||||
├── channel: NotificationChannel (enum: SSE, EMAIL, PUSH)
|
||||
├── recipient: UserId
|
||||
├── alertId: UUID
|
||||
├── sentAt: DateTime
|
||||
├── delivered: boolean
|
||||
└── error: string?
|
||||
```
|
||||
|
||||
### Domain Events
|
||||
- `AlertTriggered` — Alert condition met
|
||||
- `AlertResolved` — Alert condition no longer applies
|
||||
- `AlertDismissed` — User dismissed alert
|
||||
- `NotificationSent` — Alert dispatched via channel
|
||||
- `NotificationFailed` — Delivery failed
|
||||
|
||||
### Aggregates
|
||||
- **Alert** is the root aggregate.
|
||||
- Notifications are derived from alerts (not part of the same aggregate).
|
||||
|
||||
## Shared Kernel
|
||||
|
||||
These concepts are shared across bounded contexts with consistent definitions:
|
||||
|
||||
```
|
||||
Ticker (Value Object)
|
||||
├── symbol: string // e.g., "AAPL"
|
||||
├── exchange: string // e.g., "NASDAQ"
|
||||
└── isPrimary: boolean // for tickers with multiple listings
|
||||
|
||||
Sector (Value Object)
|
||||
├── code: string // e.g., "XLK"
|
||||
├── name: string // e.g., "Technology"
|
||||
└── gicsCode: string // e.g., "45"
|
||||
|
||||
PriceEvent (Value Object)
|
||||
├── date: DateTime
|
||||
├── open: Money
|
||||
├── high: Money
|
||||
├── low: Money
|
||||
├── close: Money
|
||||
└── volume: long
|
||||
|
||||
Money (Value Object)
|
||||
├── amount: decimal
|
||||
├── currency: string // ISO 4217
|
||||
|
||||
UserId (Value Object)
|
||||
├── id: UUID
|
||||
└── email: string
|
||||
```
|
||||
|
||||
## Anti-Corruption Layer
|
||||
|
||||
**External APIs → Domain Models**:
|
||||
- Massive/Polygon API → PriceEvent (no external IDs leak in)
|
||||
- SEC EDGAR → SecFiling (parse raw XML/JSON, produce clean domain object)
|
||||
- Finnhub → SentimentSignal, InsiderTrade, NewsEvent
|
||||
- Reddit API → SentimentSignal (from subreddit analysis)
|
||||
- FRED → MacroeconomicData (for sector rotation context)
|
||||
|
||||
**Pattern**: Every external data source has a dedicated adapter that translates API responses into our domain models. No external schema leaks into the domain layer.
|
||||
|
||||
## Repository Interfaces (Domain Layer)
|
||||
|
||||
```typescript
|
||||
// Domain layer defines interfaces, infrastructure implements them
|
||||
|
||||
interface IStockRepository {
|
||||
findByTicker(ticker: Ticker): Promise<Stock | null>
|
||||
findByTickers(tickers: Ticker[]): Promise<Stock[]>
|
||||
save(stock: Stock): Promise<void>
|
||||
getSecFilings(ticker: Ticker, limit?: number): Promise<SecFiling[]>
|
||||
getInsiderTrades(ticker: Ticker, limit?: number): Promise<InsiderTrade[]>
|
||||
getPeerGroup(ticker: Ticker): Promise<PeerGroup>
|
||||
}
|
||||
|
||||
interface IPriceRepository {
|
||||
getHistory(ticker: Ticker, from: Date, to: Date, interval: string): Promise<PriceEvent[]>
|
||||
getLatest(ticker: Ticker): Promise<PriceEvent>
|
||||
saveBatch(prices: PriceEvent[]): Promise<void>
|
||||
getMomentum(ticker: Ticker, period: number): Promise<decimal>
|
||||
}
|
||||
|
||||
interface IWatchlistRepository {
|
||||
findByUser(userId: UserId): Promise<Watchlist[]>
|
||||
findById(id: UUID): Promise<Watchlist | null>
|
||||
save(watchlist: Watchlist): Promise<void>
|
||||
addItem(watchlistId: UUID, item: WatchlistItem): Promise<void>
|
||||
removeItem(watchlistId: UUID, ticker: Ticker): Promise<void>
|
||||
}
|
||||
|
||||
interface IStrategyRepository {
|
||||
findByUser(userId: UserId): Promise<Strategy[]>
|
||||
findById(id: UUID): Promise<Strategy | null>
|
||||
save(strategy: Strategy): Promise<void>
|
||||
}
|
||||
|
||||
interface IAlertRepository {
|
||||
findByWatchlist(watchlistId: UUID, status?: AlertStatus): Promise<Alert[]>
|
||||
save(alert: Alert): Promise<void>
|
||||
resolve(id: UUID): Promise<void>
|
||||
dismiss(id: UUID): Promise<void>
|
||||
}
|
||||
|
||||
interface ISectorRotationRepository {
|
||||
getRotations(date: Date): Promise<SectorRotation[]>
|
||||
save(rotations: SectorRotation[]): Promise<void>
|
||||
getHistorical(dateFrom: Date, dateTo: Date): Promise<SectorRotation[]>
|
||||
}
|
||||
```
|
||||
@@ -0,0 +1,260 @@
|
||||
# Invest Copilot — Open Design Integration Guide
|
||||
|
||||
## What is Open Design?
|
||||
|
||||
Open Design is an open-source, local-first design tool that uses AI coding agents to generate:
|
||||
- **UI/UX mockups** — HTML/CSS prototypes from natural language
|
||||
- **Brand design systems** — Color palettes, typography, spacing, component styles
|
||||
- **Visual directions** — Curated design moods (editorial, modern minimal, tech utility, etc.)
|
||||
- **Interactive prototypes** — Clickable HTML/CSS that can be directly used as starting points
|
||||
- **Export formats** — HTML, PDF, PPTX, MP4
|
||||
|
||||
It runs on any coding agent CLI (Claude Code, Codex, Cursor, Qwen, Hermes, etc.) and uses brand-grade design systems (Stripe, Linear, Vercel, Apple, etc.) as visual foundations.
|
||||
|
||||
## How Open Design Fits Into Our Project
|
||||
|
||||
### Phase 1: Visual Design Direction (Week 1)
|
||||
**Goal**: Define the visual identity of Invest Copilot using Open Design.
|
||||
|
||||
```
|
||||
Command pattern for Hermes/other CLI agents:
|
||||
"Using Open Design, generate a visual direction for an AI-native investment copilot app.
|
||||
Target audience: retail investors, ages 25-45, tech-savvy.
|
||||
Design constraints:
|
||||
- Dark mode primary (trading platforms default to dark)
|
||||
- Data-dense but not cluttered (like Bloomberg but modern)
|
||||
- Mobile-first responsive layouts
|
||||
- Financial data visualization (charts, heatmaps, tables)
|
||||
- Color palette: professional finance (deep navy, electric blue accents, green/red for gains/losses)
|
||||
- Brand tone: trustworthy, intelligent, cutting-edge
|
||||
- Reference: Bloomberg Terminal meets Linear.app meets TradingView
|
||||
|
||||
Generate 3 visual directions with:
|
||||
1. Color palette in CSS custom properties (OKLch recommended by Open Design)
|
||||
2. Font stack recommendation
|
||||
3. Component style definitions
|
||||
4. Layout spacing scale
|
||||
5. Example chart and data table styling"
|
||||
```
|
||||
|
||||
### Phase 2: UI Mockup Generation (Week 1-2)
|
||||
**Goal**: Generate HTML/CSS prototypes for each key screen.
|
||||
|
||||
Screens to generate:
|
||||
1. **Dashboard** — Watchlist overview with portfolio summary
|
||||
2. **Stock Search & Profile** — Search bar, stock cards, detailed profile view
|
||||
3. **Stock Detail Page** — Charts (OHLCV, volume), SEC filings, insider trades, peer comparison
|
||||
4. **Watchlist Management** — Create/edit watchlists, add/remove tickers
|
||||
5. **Strategy Builder** — Visual strategy condition builder
|
||||
6. **Screener** — Filter-based stock screening (TradingView-style)
|
||||
7. **Alerts Center** — Real-time alert feed with severity indicators
|
||||
8. **Sector Rotation Dashboard** — Sector heatmaps, momentum rankings, rotation alerts
|
||||
|
||||
```
|
||||
Command pattern:
|
||||
"Generate a fully responsive HTML/CSS prototype for the [Screen Name] page.
|
||||
Use the design system from [direction].
|
||||
Include:
|
||||
- Layout structure (mobile-first)
|
||||
- All interactive elements
|
||||
- Data visualization placeholders
|
||||
- Responsive breakpoints
|
||||
- CSS custom properties for theming
|
||||
|
||||
Output: Complete HTML file with embedded CSS and minimal JS for interactivity."
|
||||
```
|
||||
|
||||
### Phase 3: Component Library (Week 2)
|
||||
**Goal**: Generate reusable component specs that map to Radix UI + Tailwind.
|
||||
|
||||
```
|
||||
Command pattern:
|
||||
"Generate a component library specification for Invest Copilot using TailwindCSS.
|
||||
Components:
|
||||
1. StockCard — ticker, price, change %, mini-chart sparkline
|
||||
2. PriceChart — OHLCV candlestick chart (placeholder for Lightweight Charts)
|
||||
3. SEC Filing Card — form type, date, summary, sentiment badge
|
||||
4. Insider Trade Row — name, title, transaction type, shares, value
|
||||
5. Strategy Condition Builder — visual rule builder (AND/OR logic)
|
||||
6. Screener Filter — field selector, operator, value input
|
||||
7. Alert Badge — severity-based color coding (info/warning/critical)
|
||||
8. Sector Heatmap — color-coded sector performance grid
|
||||
9. Watchlist Table — sortable, filterable ticker list
|
||||
10. Navigation — mobile-first bottom nav + desktop sidebar
|
||||
|
||||
For each component:
|
||||
- HTML structure
|
||||
- TailwindCSS classes
|
||||
- State variants (hover, active, disabled, error)
|
||||
- Responsive behavior
|
||||
- Accessibility attributes (ARIA)"
|
||||
```
|
||||
|
||||
### Phase 4: Brand Design System (Week 2-3)
|
||||
**Goal**: Create a complete design token system using Open Design's brand-grade systems.
|
||||
|
||||
```
|
||||
Design tokens structure:
|
||||
{
|
||||
"color": {
|
||||
"background": {
|
||||
"primary": "OKLch(0.08 0 0)", // near-black
|
||||
"secondary": "OKLch(0.12 0 0)", // dark gray
|
||||
"tertiary": "OKLch(0.18 0 0)" // lighter gray
|
||||
},
|
||||
"surface": {
|
||||
"card": "OKLch(0.15 0 0)",
|
||||
"hover": "OKLch(0.20 0 0)",
|
||||
"active": "OKLch(0.25 0 0)"
|
||||
},
|
||||
"text": {
|
||||
"primary": "OKLch(0.95 0 0)",
|
||||
"secondary": "OKLch(0.70 0 0)",
|
||||
"tertiary": "OKLch(0.50 0 0)"
|
||||
},
|
||||
"semantic": {
|
||||
"positive": "OKLch(0.65 0.18 140)", // green
|
||||
"negative": "OKLch(0.55 0.20 20)", // red
|
||||
"accent": "OKLch(0.65 0.18 250)", // blue
|
||||
"warning": "OKLch(0.70 0.18 80)", // amber
|
||||
"critical": "OKLch(0.50 0.22 20)" // deep red
|
||||
}
|
||||
},
|
||||
"typography": {
|
||||
"fontFamily": {
|
||||
"display": "Inter, system-ui, sans-serif",
|
||||
"mono": "JetBrains Mono, monospace",
|
||||
"body": "Inter, system-ui, sans-serif"
|
||||
},
|
||||
"size": {
|
||||
"xs": "0.75rem",
|
||||
"sm": "0.875rem",
|
||||
"base": "1rem",
|
||||
"lg": "1.125rem",
|
||||
"xl": "1.25rem",
|
||||
"2xl": "1.5rem",
|
||||
"3xl": "1.875rem"
|
||||
},
|
||||
"weight": {
|
||||
"normal": "400",
|
||||
"medium": "500",
|
||||
"semibold": "600",
|
||||
"bold": "700"
|
||||
}
|
||||
},
|
||||
"spacing": {
|
||||
"1": "0.25rem",
|
||||
"2": "0.5rem",
|
||||
"3": "0.75rem",
|
||||
"4": "1rem",
|
||||
"6": "1.5rem",
|
||||
"8": "2rem",
|
||||
"12": "3rem",
|
||||
"16": "4rem"
|
||||
},
|
||||
"radius": {
|
||||
"sm": "0.375rem",
|
||||
"md": "0.5rem",
|
||||
"lg": "0.75rem",
|
||||
"xl": "1rem",
|
||||
"full": "9999px"
|
||||
},
|
||||
"breakpoints": {
|
||||
"mobile": "375px",
|
||||
"tablet": "768px",
|
||||
"desktop": "1024px",
|
||||
"wide": "1280px"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Phase 5: Interactive Prototype to Code Bridge (Week 3)
|
||||
**Goal**: Convert Open Design HTML/CSS prototypes into Next.js components.
|
||||
|
||||
Process:
|
||||
1. Open Design generates HTML/CSS prototype
|
||||
2. Developer maps HTML structure to React/Next.js components
|
||||
3. Tailwind classes transfer directly (same syntax)
|
||||
4. Replace static data with API-driven data
|
||||
5. Add interactivity (Zustand state, API calls)
|
||||
6. Ensure accessibility (ARIA, keyboard navigation)
|
||||
|
||||
```
|
||||
Mapping guide:
|
||||
┌────────────────────┬─────────────────────────────────────────┐
|
||||
│ Open Design Output │ Next.js Implementation │
|
||||
├────────────────────┼─────────────────────────────────────────┤
|
||||
│ HTML <div> │ React <div> (same) │
|
||||
│ HTML <a> │ Next.js <Link> │
|
||||
│ CSS classes │ TailwindCSS classes (same syntax) │
|
||||
│ CSS custom props │ tailwind.config.js theme extension │
|
||||
│ Static data │ API call → Zustand store → component │
|
||||
│ Hover effects │ Tailwind hover: classes │
|
||||
│ Responsive │ Tailwind responsive prefixes (sm:, md:) │
|
||||
│ Interactivity │ React useState, useEffect, API calls │
|
||||
└────────────────────┴───────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## Open Design Skill Integration
|
||||
|
||||
### For Hermes Agent
|
||||
Use Open Design as a design-phase skill for the invest-copilot project:
|
||||
|
||||
```yaml
|
||||
# In your agent session context for invest-copilot:
|
||||
skills:
|
||||
- name: open-design # if installed as a skill
|
||||
- name: architecture-diagram # for system architecture SVGs
|
||||
- name: sketch # for quick UI mockup comparisons
|
||||
```
|
||||
|
||||
### For Other CLI Agents
|
||||
Open Design works with all 16 supported coding agents. When working with:
|
||||
- **Claude Code**: Use natural language design prompts with Open Design conventions
|
||||
- **Cursor**: Use Open Design's brand systems as autocomplete context
|
||||
- **Qwen (your model)**: Generate design specs that map to the TailwindCSS + Radix UI stack
|
||||
|
||||
## Design System Selection
|
||||
|
||||
For Invest Copilot's visual direction, Open Design provides these brand systems:
|
||||
|
||||
| Brand System | Why It Works | Application |
|
||||
|---|---|---|
|
||||
| **Stripe** | Clean, data-dense, professional | Dashboard, data tables, cards |
|
||||
| **Linear** | Modern, minimal, dark mode | Navigation, sidebar, controls |
|
||||
| **Bloomberg** | Financial data visualization | Charts, heatmaps, trading UI |
|
||||
| **Vercel** | Developer-friendly, clean | Settings, configuration screens |
|
||||
| **Apple** | Premium, accessible, intuitive | Onboarding, empty states |
|
||||
|
||||
### Recommended Blend
|
||||
```
|
||||
Primary: Stripe (layout + spacing principles)
|
||||
Dark mode: Linear (dark mode design system)
|
||||
Financial charts: Bloomberg (data density)
|
||||
Navigation: Vercel (clean, minimal)
|
||||
Typography: Apple (readability at small sizes)
|
||||
```
|
||||
|
||||
## Design Validation Checklist
|
||||
|
||||
Before moving from design to implementation, validate:
|
||||
- [ ] All screens are responsive at 375px, 768px, 1024px, 1280px
|
||||
- [ ] Dark mode contrast ratios meet WCAG AA (4.5:1 for text)
|
||||
- [ ] Touch targets are ≥ 44px on mobile
|
||||
- [ ] Charts are readable at 375px width
|
||||
- [ ] Color-coding for profit/loss works for colorblind users (add icons + labels)
|
||||
- [ ] All interactive elements have hover and focus states
|
||||
- [ ] Loading states defined for all data-fetching screens
|
||||
- [ ] Empty states designed for watchlists, strategies, alerts
|
||||
- [ ] Error states defined for API failures
|
||||
- [ ] Keyboard navigation works on all screens (not just mouse/touch)
|
||||
- [ ] Semantic HTML structure (header, main, nav, aside, footer)
|
||||
|
||||
## Anti-Patterns to Avoid
|
||||
|
||||
1. **Bloomberg clutter** — Don't make it look like Bloomberg Terminal. It's a modern PWA, not a desktop trading terminal.
|
||||
2. **Over-charting** — Every stock page should have at most 3-4 charts max. More than that overwhelms.
|
||||
3. **Desktop-first thinking** — Design for 375px width first, then expand. Not the other way around.
|
||||
4. **Ignoring loading states** — Financial data takes time to fetch. Skeleton screens are mandatory.
|
||||
5. **Color-only signaling** — Never use color alone to indicate profit/loss. Use arrows, icons, and labels too.
|
||||
6. **Ignoring accessibility** — Financial tools serve all users. Screen reader support is non-negotiable.
|
||||
@@ -0,0 +1,612 @@
|
||||
# Invest Copilot — Phase 1: Design-Driven Foundation
|
||||
|
||||
> **Goal**: Establish the project foundation, generate UI directions via Open Design, set up the development environment, and define all API contracts.
|
||||
>
|
||||
> **Duration**: Weeks 1-3
|
||||
>
|
||||
> **Deliverables**: Clickable UI prototype, API specification, deployed dev environment, CI/CD pipeline
|
||||
|
||||
## Week 1: Visual Identity & UI Prototypes
|
||||
|
||||
### Day 1-2: Design Direction via Open Design
|
||||
|
||||
**Task 1: Generate 3 visual directions**
|
||||
|
||||
Use Open Design (or equivalent) with these prompts:
|
||||
|
||||
```
|
||||
Direction A: "Dark Finance Professional"
|
||||
- Deep navy background (#0a1628) with electric blue accents (#3b82f6)
|
||||
- Data-dense layout (like Bloomberg but modern)
|
||||
- Monospace numbers (JetBrains Mono), sans-serif labels (Inter)
|
||||
- Green/red for gains/losses with +/− icons (not color alone)
|
||||
- Reference: Bloomberg meets Linear
|
||||
|
||||
Direction B: "Minimal Intelligence"
|
||||
- Near-black background (#0d0d0d) with subtle blue tints
|
||||
- Maximum white space between data elements
|
||||
- Large typography for key metrics
|
||||
- Charts as the hero element
|
||||
- Reference: Apple Health meets Koyfin
|
||||
|
||||
Direction C: "Modern Terminal"
|
||||
- Dark gray background (#1a1a1a) with accent colors
|
||||
- Terminal-inspired typography and borders
|
||||
- Monospace throughout
|
||||
- Command-like navigation
|
||||
- Reference: TradingView dark mode meets VS Code
|
||||
```
|
||||
|
||||
**Task 2: Select direction and create design tokens**
|
||||
|
||||
Based on the generated directions, create `tailwind.config.ts` with:
|
||||
- Custom color palette (OKLch-based)
|
||||
- Font families (Inter + JetBrains Mono)
|
||||
- Spacing scale
|
||||
- Breakpoint definitions
|
||||
- Animation definitions
|
||||
|
||||
**Task 3: Generate key screen prototypes**
|
||||
|
||||
Generate HTML/CSS prototypes for:
|
||||
1. Dashboard (watchlist overview)
|
||||
2. Stock profile (search → profile)
|
||||
3. Sector rotation dashboard
|
||||
|
||||
### Day 3-5: Component Library
|
||||
|
||||
Generate reusable components:
|
||||
- StockCard, PriceChart placeholder, SEC Filing Card
|
||||
- Insider Trade Row, Strategy Rule Builder, Alert Badge
|
||||
- Sector Heatmap, Watchlist Table, Navigation
|
||||
|
||||
## Week 2: Development Environment
|
||||
|
||||
### Task 4: Initialize Next.js 15 project
|
||||
|
||||
```bash
|
||||
npx create-next-app@latest invest-copilot \
|
||||
--typescript \
|
||||
--tailwind \
|
||||
--app \
|
||||
--src-dir \
|
||||
--import-alias "@/*" \
|
||||
--turbopack \
|
||||
--use-npm
|
||||
```
|
||||
|
||||
### Task 5: Install core dependencies
|
||||
|
||||
```bash
|
||||
# State management
|
||||
npm install zustand
|
||||
|
||||
# UI primitives
|
||||
npm install @radix-ui/react-dialog @radix-ui/react-dropdown-menu
|
||||
npm install @radix-ui/react-tabs @radix-ui/react-tooltip
|
||||
npm install @radix-ui/react-select @radix-ui/react-switch
|
||||
|
||||
# Charts
|
||||
npm install lightweight-charts
|
||||
|
||||
# Data fetching
|
||||
npm install @tanstack/react-query
|
||||
|
||||
# Forms
|
||||
npm install react-hook-form zod @hookform/resolvers
|
||||
|
||||
# PWA
|
||||
npm install next-pwa
|
||||
|
||||
# Icons
|
||||
npm install lucide-react
|
||||
|
||||
# Date handling
|
||||
npm install date-fns
|
||||
|
||||
# Development
|
||||
npm install -D @types/node @types/react @types/react-dom
|
||||
npm install -D eslint @typescript-eslint/parser @typescript-eslint/eslint-plugin
|
||||
npm install -D prettier prettier-plugin-tailwindcss
|
||||
```
|
||||
|
||||
### Task 6: Set up Docker Compose for infrastructure
|
||||
|
||||
Create `docker-compose.dev.yml`:
|
||||
```yaml
|
||||
services:
|
||||
postgres:
|
||||
image: timescale/timescaledb:latest-pg16
|
||||
environment:
|
||||
POSTGRES_DB: invest_copilot
|
||||
POSTGRES_USER: dev
|
||||
POSTGRES_PASSWORD: dev_password
|
||||
ports:
|
||||
- "5432:5432"
|
||||
volumes:
|
||||
- pgdata:/var/lib/postgresql/data
|
||||
|
||||
redis:
|
||||
image: redis:7-alpine
|
||||
ports:
|
||||
- "6379:6379"
|
||||
volumes:
|
||||
- redisdata:/data
|
||||
|
||||
minio:
|
||||
image: minio/minio
|
||||
command: server /data --console-address ":9001"
|
||||
environment:
|
||||
MINIO_ROOT_USER: dev
|
||||
MINIO_ROOT_PASSWORD: dev_password
|
||||
ports:
|
||||
- "9000:9000"
|
||||
- "9001:9001"
|
||||
volumes:
|
||||
- miniodata:/data
|
||||
|
||||
volumes:
|
||||
pgdata:
|
||||
redisdata:
|
||||
miniodata:
|
||||
```
|
||||
|
||||
### Task 7: Set up CI/CD with GitHub Actions
|
||||
|
||||
Create `.github/workflows/ci.yml`:
|
||||
```yaml
|
||||
name: CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
pull_request:
|
||||
branches: [main]
|
||||
|
||||
jobs:
|
||||
lint-and-test:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 22
|
||||
cache: npm
|
||||
- run: npm ci
|
||||
- run: npm run lint
|
||||
- run: npm run build
|
||||
```
|
||||
|
||||
## Week 3: API Contracts & Data Pipeline
|
||||
|
||||
### Task 8: Define OpenAPI/Swagger specification
|
||||
|
||||
Create `docs/api/openapi.yaml` with:
|
||||
|
||||
```yaml
|
||||
openapi: 3.1.0
|
||||
info:
|
||||
title: Invest Copilot API
|
||||
version: 0.1.0
|
||||
description: AI-native investment research and portfolio copilot
|
||||
|
||||
paths:
|
||||
# Stock Search & Profile
|
||||
/api/v1/search:
|
||||
get:
|
||||
summary: Search stocks by ticker or name
|
||||
parameters:
|
||||
- name: q
|
||||
in: query
|
||||
required: true
|
||||
schema: { type: string }
|
||||
- name: limit
|
||||
in: query
|
||||
schema: { type: integer, default: 10, maximum: 50 }
|
||||
responses:
|
||||
200:
|
||||
description: Search results
|
||||
|
||||
/api/v1/stocks/{ticker}:
|
||||
get:
|
||||
summary: Get full stock profile
|
||||
parameters:
|
||||
- name: ticker
|
||||
in: path
|
||||
required: true
|
||||
schema: { type: string }
|
||||
responses:
|
||||
200:
|
||||
description: Stock profile with all data
|
||||
|
||||
/api/v1/stocks/{ticker}/peers:
|
||||
get:
|
||||
summary: Get peer group and relative performance
|
||||
parameters:
|
||||
- name: ticker
|
||||
in: path
|
||||
required: true
|
||||
schema: { type: string }
|
||||
responses:
|
||||
200:
|
||||
description: Peer group with relative strength
|
||||
|
||||
/api/v1/stocks/{ticker}/price/history:
|
||||
get:
|
||||
summary: Get historical prices
|
||||
parameters:
|
||||
- name: ticker
|
||||
in: path
|
||||
required: true
|
||||
schema: { type: string }
|
||||
- name: interval
|
||||
in: query
|
||||
schema: { type: string, enum: [1m, 5m, 15m, 30m, 1h, 1d, 1w, 1M] }
|
||||
- name: start
|
||||
in: query
|
||||
schema: { type: string, format: date-time }
|
||||
- name: end
|
||||
in: query
|
||||
schema: { type: string, format: date-time }
|
||||
responses:
|
||||
200:
|
||||
description: Price history
|
||||
|
||||
/api/v1/stocks/{ticker}/sec-filings:
|
||||
get:
|
||||
summary: Get SEC filings
|
||||
parameters:
|
||||
- name: ticker
|
||||
in: path
|
||||
required: true
|
||||
schema: { type: string }
|
||||
- name: form_type
|
||||
in: query
|
||||
schema: { type: string, enum: [10-K, 10-Q, 8-K, 4, 13F, 13D, 13G] }
|
||||
- name: limit
|
||||
in: query
|
||||
schema: { type: integer, default: 20 }
|
||||
responses:
|
||||
200:
|
||||
description: SEC filings
|
||||
|
||||
/api/v1/stocks/{ticker}/insider-trades:
|
||||
get:
|
||||
summary: Get insider trades
|
||||
parameters:
|
||||
- name: ticker
|
||||
in: path
|
||||
required: true
|
||||
schema: { type: string }
|
||||
- name: limit
|
||||
in: query
|
||||
schema: { type: integer, default: 20 }
|
||||
responses:
|
||||
200:
|
||||
description: Insider trades
|
||||
|
||||
/api/v1/stocks/{ticker}/sentiment:
|
||||
get:
|
||||
summary: Get sentiment signals
|
||||
parameters:
|
||||
- name: ticker
|
||||
in: path
|
||||
required: true
|
||||
schema: { type: string }
|
||||
responses:
|
||||
200:
|
||||
description: Sentiment signals from all sources
|
||||
|
||||
# Watchlists
|
||||
/api/v1/watchlists:
|
||||
get:
|
||||
summary: Get user's watchlists
|
||||
responses:
|
||||
200:
|
||||
description: List of watchlists
|
||||
post:
|
||||
summary: Create a new watchlist
|
||||
requestBody:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
required: [name]
|
||||
properties:
|
||||
name: { type: string }
|
||||
description: { type: string }
|
||||
responses:
|
||||
201:
|
||||
description: Watchlist created
|
||||
|
||||
/api/v1/watchlists/{id}:
|
||||
get:
|
||||
summary: Get watchlist with items and prices
|
||||
put:
|
||||
summary: Update watchlist name
|
||||
delete:
|
||||
summary: Delete watchlist
|
||||
|
||||
/api/v1/watchlists/{id}/items:
|
||||
get:
|
||||
summary: Get watchlist items with live prices
|
||||
post:
|
||||
summary: Add ticker to watchlist
|
||||
delete:
|
||||
summary: Remove ticker from watchlist
|
||||
|
||||
# Strategies
|
||||
/api/v1/strategies:
|
||||
get:
|
||||
summary: Get user's strategies
|
||||
post:
|
||||
summary: Create a new strategy
|
||||
/api/v1/strategies/{id}:
|
||||
get:
|
||||
summary: Get strategy details
|
||||
put:
|
||||
summary: Update strategy
|
||||
delete:
|
||||
summary: Delete strategy
|
||||
|
||||
# Screener
|
||||
/api/v1/screeners:
|
||||
get:
|
||||
summary: Get user's screeners
|
||||
post:
|
||||
summary: Create a new screener
|
||||
/api/v1/screeners/{id}/run:
|
||||
post:
|
||||
summary: Run screener and get results
|
||||
/api/v1/screeners/{id}/results:
|
||||
get:
|
||||
summary: Get screener results
|
||||
|
||||
# Sector Rotation
|
||||
/api/v1/sectors/rotation:
|
||||
get:
|
||||
summary: Get current sector rotation analysis
|
||||
post:
|
||||
summary: Trigger manual rotation scan
|
||||
/api/v1/sectors/rotation/history:
|
||||
get:
|
||||
summary: Get historical rotation data
|
||||
|
||||
# Alerts
|
||||
/api/v1/alerts:
|
||||
get:
|
||||
summary: Get user's alerts
|
||||
delete:
|
||||
summary: Clear resolved alerts
|
||||
/api/v1/alerts/{id}/resolve:
|
||||
post:
|
||||
summary: Mark alert as resolved
|
||||
/api/v1/alerts/{id}/dismiss:
|
||||
post:
|
||||
summary: Dismiss alert
|
||||
|
||||
# Real-time (SSE)
|
||||
/api/v1/stream/alerts:
|
||||
get:
|
||||
summary: Server-Sent Events stream for real-time alerts
|
||||
responses:
|
||||
200:
|
||||
description: SSE stream
|
||||
content:
|
||||
text/event-stream:
|
||||
schema:
|
||||
type: string
|
||||
```
|
||||
|
||||
### Task 9: Set up Python data pipeline
|
||||
|
||||
```bash
|
||||
mkdir -p src/data-pipeline
|
||||
cd src/data-pipeline
|
||||
pip install yfinance finnhub-python requests beautifulsoup4
|
||||
```
|
||||
|
||||
Create `src/data-pipeline/ingest_prices.py`:
|
||||
```python
|
||||
"""Price data ingestion using yfinance (free tier)."""
|
||||
import yfinance as yf
|
||||
import psycopg2
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
def fetch_prices(ticker: str, period: str = "5y") -> list[dict]:
|
||||
"""Fetch OHLCV data using yfinance."""
|
||||
tk = yf.Ticker(ticker)
|
||||
df = tk.history(period=period, auto_adjust=True)
|
||||
records = []
|
||||
for date, row in df.iterrows():
|
||||
records.append({
|
||||
"ticker": ticker,
|
||||
"date": date,
|
||||
"open": row["Open"],
|
||||
"high": row["High"],
|
||||
"low": row["Low"],
|
||||
"close": row["Close"],
|
||||
"volume": int(row["Volume"]),
|
||||
"adjusted_close": row["Close"], # adjusted = close for now
|
||||
})
|
||||
return records
|
||||
|
||||
def save_prices(records: list[dict]) -> None:
|
||||
"""Save prices to PostgreSQL/TimescaleDB."""
|
||||
conn = psycopg2.connect(
|
||||
host="localhost",
|
||||
database="invest_copilot",
|
||||
user="dev",
|
||||
password="dev_password"
|
||||
)
|
||||
cur = conn.cursor()
|
||||
for r in records:
|
||||
cur.execute("""
|
||||
INSERT INTO prices (ticker, date, open, high, low, close, volume, adjusted_close)
|
||||
VALUES (%s, %s, %s, %s, %s, %s, %s, %s)
|
||||
ON CONFLICT (ticker, date) DO UPDATE SET
|
||||
open = EXCLUDED.open,
|
||||
high = EXCLUDED.high,
|
||||
low = EXCLUDED.low,
|
||||
close = EXCLUDED.close,
|
||||
volume = EXCLUDED.volume,
|
||||
adjusted_close = EXCLUDED.adjusted_close
|
||||
""", (
|
||||
r["ticker"], r["date"], r["open"], r["high"], r["low"],
|
||||
r["close"], r["volume"], r["adjusted_close"]
|
||||
))
|
||||
conn.commit()
|
||||
cur.close()
|
||||
conn.close()
|
||||
|
||||
if __name__ == "__main__":
|
||||
import sys
|
||||
tickers = sys.argv[1:] if len(sys.argv) > 1 else ["AAPL", "MSFT", "GOOGL", "AMZN", "META"]
|
||||
for ticker in tickers:
|
||||
print(f"Ingesting {ticker}...")
|
||||
records = fetch_prices(ticker)
|
||||
save_prices(records)
|
||||
print(f" Saved {len(records)} records")
|
||||
```
|
||||
|
||||
### Task 10: Set up SEC EDGAR ingestion
|
||||
|
||||
Create `src/data-pipeline/ingest_sec.py`:
|
||||
```python
|
||||
"""SEC EDGAR filing ingestion."""
|
||||
import requests
|
||||
import json
|
||||
from datetime import datetime
|
||||
|
||||
EDGAR_BASE = "https://data.sec.gov"
|
||||
|
||||
def get_cik(ticker: str) -> str | None:
|
||||
"""Get CIK number for a ticker."""
|
||||
url = f"{EDGAR_BASE}/cgi-bin/browse-edgar?action=getcompany&CIK=TICKER&type=&date=coverage&date_range=365&count=1"
|
||||
url = url.replace("TICKER", ticker.upper())
|
||||
resp = requests.get(url, timeout=10)
|
||||
# Parse HTML to extract CIK
|
||||
import re
|
||||
match = re.search(r'CIK=(0{0,10}\d{6,10})', resp.text)
|
||||
return match.group(1) if match else None
|
||||
|
||||
def get_filings(cik: str, form_type: str | None = None, limit: int = 20) -> list[dict]:
|
||||
"""Get filings for a CIK."""
|
||||
url = f"{EDGAR_BASE}/submissions/CIK{int(cik):010d}.json"
|
||||
resp = requests.get(url, timeout=10)
|
||||
data = resp.json()
|
||||
|
||||
filings = []
|
||||
for i in range(min(limit * 20, len(data["filings"]["recent"]["form"]))):
|
||||
form = data["filings"]["recent"]["form"][i]
|
||||
if form_type and form != form_type:
|
||||
continue
|
||||
filings.append({
|
||||
"cik": cik,
|
||||
"form_type": form,
|
||||
"filing_date": data["filings"]["recent"]["filingDate"][i],
|
||||
"report_date": data["filings"]["recent"]["reportDate"][i],
|
||||
"accession_number": data["filings"]["recent"]["accessionNumber"][i],
|
||||
"primary_document": data["filings"]["recent"]["primaryDocument"][i],
|
||||
"url": f"{EDGAR_BASE}/Archives/edgar/data/{int(cik):010d}/"
|
||||
f"{data['filings']['recent']['accessionNumber'][i].replace('-', '')}/"
|
||||
f"{data['filings']['recent']['primaryDocument'][i]}",
|
||||
})
|
||||
if len([f for f in filings if "form_type" in f]) >= limit:
|
||||
break
|
||||
return filings
|
||||
|
||||
if __name__ == "__main__":
|
||||
# Test: Get filings for AAPL
|
||||
cik = get_cik("AAPL")
|
||||
print(f"AAPL CIK: {cik}")
|
||||
if cik:
|
||||
filings = get_filings(cik, limit=5)
|
||||
print(json.dumps(filings, indent=2))
|
||||
```
|
||||
|
||||
### Task 11: Create project structure
|
||||
|
||||
```
|
||||
invest-copilot/
|
||||
├── docs/ # Documentation (we already have this)
|
||||
│ ├── 00-vision.md
|
||||
│ ├── 01-architecture.md
|
||||
│ ├── 02-data-model.md
|
||||
│ ├── 03-domain-model.md
|
||||
│ ├── 04-open-design-integration.md
|
||||
│ ├── 05-phase1-plan.md
|
||||
│ └── api/
|
||||
│ └── openapi.yaml
|
||||
├── src/
|
||||
│ ├── frontend/ # Next.js app
|
||||
│ │ ├── app/
|
||||
│ │ ├── components/
|
||||
│ │ ├── lib/
|
||||
│ │ ├── styles/
|
||||
│ │ └── store/ # Zustand stores
|
||||
│ ├── backend/ # Node.js API (future)
|
||||
│ │ ├── src/
|
||||
│ │ └── tests/
|
||||
│ ├── data-pipeline/ # Python ingestion scripts
|
||||
│ │ ├── ingest_prices.py
|
||||
│ │ ├── ingest_sec.py
|
||||
│ │ ├── ingest_sentiment.py
|
||||
│ │ └── sector_rotation.py
|
||||
│ └── shared/ # Shared types (TypeScript)
|
||||
│ └── types.ts
|
||||
├── docker-compose.dev.yml
|
||||
├── docker-compose.prod.yml # (future)
|
||||
├── .github/
|
||||
│ └── workflows/
|
||||
│ ├── ci.yml
|
||||
│ └── deploy.yml # (future)
|
||||
├── prisma/ # (future, for DDD repo implementations)
|
||||
├── .eslintrc.json
|
||||
├── .prettierrc
|
||||
├── next.config.mjs
|
||||
├── tailwind.config.ts
|
||||
├── tsconfig.json
|
||||
├── package.json
|
||||
└── README.md
|
||||
```
|
||||
|
||||
## Acceptance Criteria for Phase 1
|
||||
|
||||
- [ ] 3 visual directions generated via Open Design (or manual)
|
||||
- [ ] Selected design direction converted to TailwindCSS design tokens
|
||||
- [ ] Next.js 15 project running with TypeScript, TailwindCSS, Radix UI
|
||||
- [ ] Docker Compose dev environment with PostgreSQL+TimescaleDB, Redis, MinIO
|
||||
- [ ] GitHub Actions CI pipeline (lint + build)
|
||||
- [ ] Complete OpenAPI specification for all endpoints
|
||||
- [ ] Python data pipeline ingesting prices for at least 10 tickers
|
||||
- [ ] SEC EDGAR ingestion working for at least 5 companies
|
||||
- [ ] Dashboard UI mockup working with static data
|
||||
- [ ] Stock search UI mockup working with static data
|
||||
- [ ] Stock profile UI mockup working with static data
|
||||
- [ ] README.md with project overview, setup instructions, and architecture
|
||||
|
||||
## Pre-Phase 2 Checklist
|
||||
|
||||
Before moving to Phase 2 (Backend Foundation):
|
||||
- [ ] All Phase 1 acceptance criteria met
|
||||
- [ ] Design direction finalized and approved
|
||||
- [ ] API contracts reviewed and agreed upon
|
||||
- [ ] Data pipeline tested and verified
|
||||
- [ ] Dev environment stable and documented
|
||||
|
||||
## Resource Estimation
|
||||
|
||||
| Task | Effort |
|
||||
|---|---|
|
||||
| Visual directions + design tokens | 2 days |
|
||||
| Component library | 3 days |
|
||||
| Next.js project setup | 0.5 days |
|
||||
| Docker Compose infrastructure | 0.5 days |
|
||||
| CI/CD pipeline | 0.5 days |
|
||||
| OpenAPI specification | 1 day |
|
||||
| Price data pipeline | 2 days |
|
||||
| SEC EDGAR pipeline | 2 days |
|
||||
| UI mockups (3 screens) | 3 days |
|
||||
| README + documentation | 1 day |
|
||||
| **Total** | **~16 days (3 weeks)** |
|
||||
@@ -0,0 +1,49 @@
|
||||
# Project Status — Invest Copilot
|
||||
|
||||
## Overview
|
||||
- **Phase 1: Foundation** — ✅ COMPLETE
|
||||
- 6 design docs (vision, architecture, data model, domain model, open design integration, phase 1 plan)
|
||||
- Docker compose (PostgreSQL/TimescaleDB, Redis, MinIO)
|
||||
- Data pipeline scripts (price ingestion, SEC filings, sector rotation)
|
||||
- Shared types, OpenAPI spec, CI/CD, design tokens
|
||||
|
||||
- **Phase 2: Implementation** — ✅ COMPLETE
|
||||
- **Backend (FastAPI BFF)** — 49 files
|
||||
- Core: main.py, config, database, cache, storage
|
||||
- Models: price, stock, watchlist, strategy, screener, sector_rotation, sec_filing, insider_trade, alert
|
||||
- Schemas: Pydantic response models for all entities
|
||||
- Routers: 14 endpoints (search, stocks, prices, sec_filings, insider_trades, peers, sentiment, watchlists, strategies, screeners, sectors, alerts, stream)
|
||||
- Services: PriceService, SecService, SentimentService, RotationService, ScreenerService
|
||||
- Tasks: ingest_prices, ingest_sec, sector_scan
|
||||
- 14 API endpoints matching OpenAPI spec
|
||||
|
||||
- **Frontend (Next.js 15 PWA)** — 49 files
|
||||
- Layout: Sidebar (6 nav items), Header (search bar)
|
||||
- Dashboard: Portfolio summary cards, sector heatmap, watchlist table, alerts feed
|
||||
- Stock detail: Profile, price chart (lightweight-charts), SEC filings, insider trades
|
||||
- Watchlists: CRUD with sidebar selection
|
||||
- Strategies: Grid of strategy cards with backtest results
|
||||
- Screeners: ScreenerBuilder + ScreenerResults
|
||||
- Sectors: Sector heatmap + detailed rankings
|
||||
- Alerts: Filterable alert feed
|
||||
- Hooks: useStockData, useWatchlistData, useSSE
|
||||
- Stores: useUIStore, useWatchlistStore, useStrategiesStore
|
||||
- UI Components: Button, Badge, Card, Input, Modal, Skeleton, Tooltip
|
||||
- Lib: API client (axios), constants, utils, types
|
||||
- PWA with Workbox config
|
||||
|
||||
## Current State
|
||||
- **Total files**: 187 (excluding node_modules, .next)
|
||||
- **Stack**: Next.js 15 (app router, Turbopack) + Tailwind + FastAPI + TimescaleDB + Redis + MinIO
|
||||
- **API**: Full OpenAPI spec implemented (14 endpoints)
|
||||
- **Data models**: All 8 entity types defined with SQLAlchemy models
|
||||
- **Database**: init.sql with TimescaleDB hypertables for prices, sector_rotation, equity_scores
|
||||
- **CI/CD**: GitHub Actions for lint/test/build/deploy
|
||||
|
||||
## Next Steps (Phase 3)
|
||||
1. **Infrastructure**: Fix Docker bridge (kernel issue) — may need nftables/iptables fix or podman alternative
|
||||
2. **Data sources**: Replace mock data with real APIs (Alpha Vantage, SEC EDGAR, Finnhub)
|
||||
3. **Authentication**: Add JWT-based auth (login/register endpoints)
|
||||
4. **Real-time**: Implement SSE stream for live price updates
|
||||
5. **Testing**: Add pytest tests for backend, Playwright E2E for frontend
|
||||
6. **Deployment**: Docker compose production config, Nginx reverse proxy
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,640 @@
|
||||
# Invest Copilot — Data Edge Research
|
||||
|
||||
> Created: 2025-05-26
|
||||
> Purpose: Identify all data sources, signals, and alternative data that create an investment "edge" — information that gives our users an informational advantage over retail competitors.
|
||||
>
|
||||
|
||||
---
|
||||
|
||||
## Table of Contents
|
||||
|
||||
1. [Core Market Data (Table Stakes)](#1-core-market-data-table-stakes)
|
||||
2. [Fundamental Data (The Foundation)](#2-fundamental-data-the-foundation)
|
||||
3. [Institutional & Insider Signals](#3-institutional--insider-signals)
|
||||
4. [Options Flow & Sentiment](#4-options-flow--sentiment)
|
||||
5. [Short Interest & Squeeze Potential](#5-short-interest--squeeze-potential)
|
||||
6. [SEC Filings & Regulatory Intelligence](#6-sec-filings--regulatory-intelligence)
|
||||
7. [Alternative Data (True Alpha)](#7-alternative-data-true-alpha)
|
||||
8. [Macro & Economic Indicators](#8-macro--economic-indicators)
|
||||
9. [Sector & Rotation Signals](#9-sector--rotation-signals)
|
||||
10. [AI/ML Feature Engineering](#10-aiml-feature-engineering)
|
||||
11. [API Providers & Cost Analysis](#11-api-providers--cost-analysis)
|
||||
|
||||
---
|
||||
|
||||
## 1. Core Market Data (Table Stakes)
|
||||
|
||||
*Everyone has this. You need it, but it doesn't create an edge by itself.*
|
||||
|
||||
| Data Point | Why It Matters | Frequency |
|
||||
|-----------|---------------|-----------|
|
||||
| Real-time price (bid/ask/last) | Entry/exit timing | Tick-by-tick |
|
||||
| Volume (absolute + relative) | Conviction behind moves | Tick-by-tick |
|
||||
| VWAP (Volume Weighted Avg Price) | Institutional benchmark | Real-time |
|
||||
| 52-week high/low | Psychological levels | Daily |
|
||||
| Market cap / Float | Liquidity assessment | Daily |
|
||||
| Average volume (10d/30d/90d) | Normalization baseline | Daily |
|
||||
| Intraday OHLCV (1m/5m/15m/1h) | Chart patterns, entry timing | Intraday |
|
||||
| Pre-market / After-hours price | Gap risk, overnight sentiment | Extended hours |
|
||||
| Split/dividend-adjusted prices | Historical accuracy | Event-driven |
|
||||
| Relative strength vs sector/index | Outperformance/underperformance | Daily |
|
||||
|
||||
---
|
||||
|
||||
## 2. Fundamental Data (The Foundation)
|
||||
|
||||
*Where the real story lives. This is where you separate investors from gamblers.*
|
||||
|
||||
### Income Statement
|
||||
- Revenue (quarterly + YoY + QoQ growth rates)
|
||||
- Gross margin, operating margin, net margin (trend analysis)
|
||||
- EBITDA / EBIT
|
||||
- EPS (GAAP + non-GAAP + diluted)
|
||||
- R&D spend (critical for tech — shows future investment)
|
||||
- SG&A as % of revenue (efficiency metric)
|
||||
- Free cash flow conversion
|
||||
|
||||
### Balance Sheet
|
||||
- Total assets/liabilities/debt
|
||||
- Net debt / EBITDA ratio (solvency)
|
||||
- Current ratio, quick ratio (liquidity)
|
||||
- Share count changes (dilution detection)
|
||||
- Cash & equivalents vs short-term debt
|
||||
- Goodwill & intangible assets (quality of earnings)
|
||||
|
||||
### Cash Flow
|
||||
- Operating cash flow (quality of earnings)
|
||||
- Capex (growth vs maintenance)
|
||||
- Free cash flow (FCF = OCF − Capex)
|
||||
- Share buybacks (management confidence signal)
|
||||
- Dividend payments & changes
|
||||
|
||||
### Key Ratios (Computed)
|
||||
- P/E, PEG, P/S, P/B, P/FCF
|
||||
- ROE, ROA, ROIC
|
||||
- Debt/Equity, Interest Coverage
|
||||
- Altman Z-Score (bankruptcy risk)
|
||||
- Piotroski F-Score (9-factor quality score)
|
||||
|
||||
---
|
||||
|
||||
## 3. Institutional & Insider Signals
|
||||
|
||||
*One of the strongest predictive signals available to retail.*
|
||||
|
||||
### Institutional Ownership
|
||||
- Top 10 holders (Vanguard, BlackRock, Fidelity, etc.)
|
||||
- % of float held by institutions
|
||||
- **Quarterly change in institutional ownership** (rising = bullish signal)
|
||||
- 13F filings (lagged 45 days, but comprehensive)
|
||||
- Hedge fund holdings (13F — track specific funds like Renaissance, Citadel, Bridgewater)
|
||||
- Mutual fund net inflows/outflows
|
||||
- **New positions** vs **increased positions** vs **sold positions**
|
||||
|
||||
### Insider Activity (FORM 4)
|
||||
- **Insider buys** — strongest signal (they spend their own money)
|
||||
- CEO/CFO buys are highest conviction
|
||||
- Open market buys > exercise of options
|
||||
- Cluster buying (multiple insiders buying) = very strong signal
|
||||
- **Insider sells** — need context
|
||||
- 10b5-1 plans = routine, not signal
|
||||
- Unplanned sells = potential red flag
|
||||
- Cluster sells = very bearish
|
||||
- **Form 4 filing date vs transaction date** — speed matters
|
||||
- **SEC Form 144** (proposed sales — early warning)
|
||||
|
||||
---
|
||||
|
||||
## 4. Options Flow & Sentiment
|
||||
|
||||
*Options market often moves before the stock. This is real-time institutional positioning.*
|
||||
|
||||
### Options Data
|
||||
- **Unusual options activity** — volume >> open interest
|
||||
- Large block trades (100+ contracts)
|
||||
- Out-of-the-money calls (bullish speculation)
|
||||
- Put/call ratio spikes (fear/greed)
|
||||
- **Put/Call ratio** by ticker and overall market
|
||||
- **Implied volatility** (IV) vs historical volatility (HV)
|
||||
- IV > HV = options expensive (potential move)
|
||||
- IV rank / IV percentile
|
||||
- **Options chain** — max pain, gamma exposure
|
||||
- **Block trades** — dark pool prints
|
||||
- **Dark pool volume %**
|
||||
|
||||
### Sentiment Indicators
|
||||
- **Put/Call ratio** breakdown (equity, index, single stock)
|
||||
- **CBOE Volatility Index (VIX)** and components
|
||||
- **CNN Fear & Greed Index**
|
||||
- **AAII sentiment survey**
|
||||
- **Google Trends** for stock/sector searches
|
||||
- **Reddit/Twitter sentiment** (r/wallstreetbets, r/investing)
|
||||
|
||||
---
|
||||
|
||||
## 5. Short Interest & Squeeze Potential
|
||||
|
||||
*Short squeeze setups can create 100%+ moves in days.*
|
||||
|
||||
### Short Data
|
||||
- **Short interest** (% of float)
|
||||
- **Days to cover** (short ratio)
|
||||
- **Short interest trend** (rising = bearish, but also squeeze fuel)
|
||||
- **Squeeze probability score**:
|
||||
- High short interest (>20%)
|
||||
- Low float (<50M shares)
|
||||
- High days-to-cover (>5)
|
||||
- Rising price + volume
|
||||
- Recent catalyst (earnings, FDA, product)
|
||||
|
||||
### Borrowing Data
|
||||
- **Stock borrow fees** (high fees = hard to borrow = squeeze potential)
|
||||
- **Locate availability**
|
||||
- **Cost to borrow** (% annual)
|
||||
|
||||
---
|
||||
|
||||
## 6. SEC Filings & Regulatory Intelligence
|
||||
|
||||
*Raw regulatory filings are the most authoritative source — before analysts catch up.*
|
||||
|
||||
### Key Filings
|
||||
- **10-K** (annual) — comprehensive financial picture
|
||||
- **10-Q** (quarterly) — quarterly updates
|
||||
- **8-K** (current) — material events (earnings, M&A, leadership changes)
|
||||
- **DEF 14A** (proxy) — executive comp, board changes
|
||||
- **S-1** / **S-3** — new offerings (dilution risk)
|
||||
- **SC 13D/G** — activist positions (>5% ownership)
|
||||
- **Form 4** — insider transactions (daily)
|
||||
- **Form 144** — proposed insider sales
|
||||
|
||||
### NLP Extraction Targets
|
||||
- **MD&A changes** — management commentary shifts
|
||||
- **Risk factor additions** — new risks = new concerns
|
||||
- **Auditor changes** — red flag if auditor resigns
|
||||
- **Going concern** mentions = existential threat
|
||||
- **Related party transactions** — potential tunneling
|
||||
- **Segment revenue breakdown** — growth drivers
|
||||
|
||||
---
|
||||
|
||||
## 7. Alternative Data (True Alpha)
|
||||
|
||||
*This is where you create real edge. These are hedge fund-grade signals.*
|
||||
|
||||
### Consumer Behavior
|
||||
| Signal | Source | Edge |
|
||||
|--------|--------|------|
|
||||
| App download counts | Sensor Tower, App Annie | Early revenue signal for consumer apps |
|
||||
| App usage/engagement | SimilarWeb, data.ai | Retention, engagement trends |
|
||||
| Web traffic | SimilarWeb, SEMrush | Interest, funnel performance |
|
||||
| Credit card spend | YipitData, Earnest Research | Real-time revenue proxy |
|
||||
| Grocery/retail receipts | Earnest Research | Consumer discretionary health |
|
||||
| Shipping/tracking data | Project44, Descartes | Supply chain visibility, inventory |
|
||||
|
||||
### Corporate Activity
|
||||
| Signal | Source | Edge |
|
||||
|--------|--------|------|
|
||||
| Job postings | Employment data, LinkedIn | Growth signaling, expansion plans |
|
||||
| Job posting changes | Indeed, LinkedIn | Hiring freeze = cost cutting signal |
|
||||
| Patent filings | USPTO, Google Patents | Innovation pipeline |
|
||||
| Building permits | Municipal records | Physical expansion plans |
|
||||
| Executive hires/leaves | LinkedIn, SEC filings | Leadership quality, stability |
|
||||
| Earnings call transcripts | Seeking Alpha, Motley Fool | NLP on management tone, guidance |
|
||||
|
||||
### Supply Chain
|
||||
| Signal | Source | Edge |
|
||||
|--------|--------|------|
|
||||
| Supplier revenue changes | Supplier financials | Proxy for customer demand |
|
||||
| Supplier capex increases | Supplier filings | Capacity expansion = demand confidence |
|
||||
| Supplier stock performance | Supplier tickers | Leading indicator for customers |
|
||||
| Container shipping rates | Drewry, Clarksons | Global trade volume proxy |
|
||||
| Oil/commodity prices | Bloomberg, CME | Input cost pressure |
|
||||
|
||||
### Sentiment & Social
|
||||
| Signal | Source | Edge |
|
||||
|--------|--------|------|
|
||||
| Reddit sentiment | Pushshift, Reddit API | Retail sentiment extremes = contrarian |
|
||||
| Twitter/X sentiment | X API | Real-time reaction, influencer moves |
|
||||
| StockTwits sentiment | StockTwits API | Retail trader positioning |
|
||||
| Google Trends | Google Trends API | Interest spike detection |
|
||||
| YouTube/video content | YouTube Data API | Media coverage analysis |
|
||||
| News sentiment | NewsAPI, GDELT | Sentiment scoring, event detection |
|
||||
|
||||
### Physical/Economic Proxies
|
||||
| Signal | Source | Edge |
|
||||
|--------|--------|------|
|
||||
| Satellite imagery | Planet, Sentinel | Retail parking lots, construction |
|
||||
| Credit card transaction data | YipitData, Flexport | Consumer spending in real-time |
|
||||
| Mobile location data | SafeGraph, Foursquare | Foot traffic to stores |
|
||||
| Energy consumption | Utility data | Industrial activity proxy |
|
||||
| Water usage data | Various providers | Agricultural/industrial activity |
|
||||
|
||||
### Macro Indicators (Beyond the headline)
|
||||
| Signal | Source | Edge |
|
||||
|--------|--------|------|
|
||||
| Yield curve (2s10, 3m10) | FRED, Treasury.gov | Recession predictor |
|
||||
| Inverted yield curve depth/duration | FRED | Recession probability |
|
||||
| Leading Economic Index (LEI) | Conference Board | 6-12 month outlook |
|
||||
| PMI (ISM Manufacturing/Services) | ISM | Economic activity pulse |
|
||||
| Consumer confidence | Conference Board | Consumer spending predictor |
|
||||
| Jobless claims (weekly) | DOL | Labor market health |
|
||||
| Initial vs continuing claims ratio | DOL | Trend vs noise |
|
||||
| Building permits/housing starts | Census Bureau | Housing market leading indicator |
|
||||
| Consumer credit changes | NY Fed | Consumer financial stress |
|
||||
|
||||
---
|
||||
|
||||
## 8. Macro & Economic Indicators
|
||||
|
||||
*For sector rotation and macro regime detection.*
|
||||
|
||||
### Interest Rate Environment
|
||||
- Fed funds rate / Fed expectations (CME FedWatch)
|
||||
- Treasury yields (2Y, 5Y, 10Y, 30Y)
|
||||
- **Yield curve spread** (10Y-2Y, 10Y-3M) — recession signal
|
||||
- **TED spread** (credit risk)
|
||||
- **TIPS breakeven** (inflation expectations)
|
||||
- SOFR, LIBOR successor rates
|
||||
- **Commercial paper spreads**
|
||||
- **High yield spreads** (ICE BofA HY OAS)
|
||||
|
||||
### Inflation
|
||||
- CPI (headline + core)
|
||||
- PCE (Fed's preferred measure)
|
||||
- PPI (producer prices — leading indicator)
|
||||
- Wage growth (average hourly earnings)
|
||||
- Shelter/rent component (largest CPI component)
|
||||
|
||||
### Growth
|
||||
- GDP growth (advance, second, final)
|
||||
- Non-farm payrolls
|
||||
- Unemployment rate
|
||||
- ISM Manufacturing PMI (>50 = expansion)
|
||||
- ISM Services PMI
|
||||
- Retail sales
|
||||
- Industrial production
|
||||
|
||||
### Currency & Commodities
|
||||
- DXY (US Dollar Index)
|
||||
- USD/EUR, USD/JPY, USD/CNY
|
||||
- Gold (fear/deflation hedge)
|
||||
- Oil (WTI/Brent — inflation, growth)
|
||||
- Copper (economic activity — "Dr. Copper")
|
||||
- Bitcoin (risk-on proxy)
|
||||
|
||||
---
|
||||
|
||||
## 9. Sector & Rotation Signals
|
||||
|
||||
*For the ETF/Index tracking and rotation detection feature.*
|
||||
|
||||
### ETF-Level Data
|
||||
| ETF | Sector | Signal |
|
||||
|-----|--------|--------|
|
||||
| XLK | Technology | Tech leadership |
|
||||
| XLF | Financials | Risk appetite, rate sensitivity |
|
||||
| XLI | Industrial | Economic activity |
|
||||
| XLY | Consumer Discretionary | Consumer confidence |
|
||||
| XLP | Consumer Staples | Defensive positioning |
|
||||
| XLE | Energy | Commodity cycle |
|
||||
| XLV | Healthcare | Defensive, innovation |
|
||||
| XLU | Utilities | Defensive, rate sensitivity |
|
||||
| XLB | Materials | Cyclical, commodities |
|
||||
| XLR | Real Estate | Rate sensitivity, housing |
|
||||
| XLRE | Real Estate | Same as above (alternate) |
|
||||
| XLG | Large Cap Growth | Growth tilt |
|
||||
| XSC | Small Cap | Economic outlook (IWR alternative) |
|
||||
|
||||
### Rotation Indicators (The Edge)
|
||||
1. **Relative Strength Score** — sector vs SPY over 20d/50d/200d
|
||||
2. **RSI Divergence** — sector making new high while SPY doesn't = leadership
|
||||
3. **Money Flow** — sector inflow vs outflow tracking
|
||||
4. **Sector ETF spread** — XLK vs XLE ratio changing
|
||||
5. **Breadth** — stocks above 50MA and 200MA within sector
|
||||
6. **Volume concentration** — volume shifting to specific sectors
|
||||
|
||||
### Rotation Detection Algorithm
|
||||
```
|
||||
Rotation = when 3+ of these conditions align:
|
||||
1. Sector ETF breaks above 50-day MA
|
||||
2. Sector ETF RSI crosses above 50
|
||||
3. Sector ETF volume > 20-day average
|
||||
4. Sector's top 3 stocks outperform SPY
|
||||
5. Sector relative strength vs SPY trending up (10d)
|
||||
6. Institutional money flow data shows inflows
|
||||
7. Analyst upgrades concentrated in sector
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 10. AI/ML Feature Engineering
|
||||
|
||||
*Transforming raw data into predictive features.*
|
||||
|
||||
### Technical Indicators (Engineered)
|
||||
- Moving averages (20, 50, 100, 200 day) + crossovers
|
||||
- RSI (14-day) + overbought/oversold
|
||||
- MACD (12, 26, 9) + signal line crossovers
|
||||
- Bollinger Bands (20, 2) + position relative to bands
|
||||
- ATR (14-day) — volatility measure
|
||||
- Volume MA + volume spike detection (3x avg)
|
||||
- Gap analysis (pre-market gap % + fill probability)
|
||||
- Support/resistance levels (pivot points, swing highs/lows)
|
||||
- Fibonacci retracement levels
|
||||
- Ichimoku Cloud components
|
||||
|
||||
### Sentiment Features
|
||||
- Put/Call ratio (10-day rolling avg + spike)
|
||||
- Short interest change (weekly)
|
||||
- Insider buy/sell ratio (quarterly)
|
||||
- Analyst rating changes (upgrades - downgrades)
|
||||
- Analyst price target revisions (upgrades - downgrades)
|
||||
- Social sentiment score (normalized -3 to +3)
|
||||
- News sentiment (Vader/BERT-based score)
|
||||
|
||||
### Fundamental Features
|
||||
- Revenue growth acceleration/deceleration
|
||||
- Margin expansion/contraction rate
|
||||
- Cash flow vs net income divergence
|
||||
- Working capital changes
|
||||
- Inventory turnover changes
|
||||
- Days sales outstanding (DSO) changes
|
||||
- Altman Z-Score trend
|
||||
- Piotroski F-Score
|
||||
|
||||
### Composite Scores (The Real Edge)
|
||||
1. **Momentum Score** (0-100) — price + volume + relative strength
|
||||
2. **Value Score** (0-100) — P/E vs sector, P/B, PEG, FCF yield
|
||||
3. **Quality Score** (0-100) — ROIC, margin stability, debt, FCF conversion
|
||||
4. **Sentiment Score** (0-100) — insider activity + institutional flows + analyst ratings
|
||||
5. **Catalyst Score** (0-100) — upcoming events, earnings proximity, news flow
|
||||
6. **Risk Score** (0-100) — volatility, beta, short interest, debt
|
||||
|
||||
---
|
||||
|
||||
## 11. API Providers & Cost Analysis
|
||||
|
||||
### Free / Low-Cost Tier
|
||||
| Provider | Data | Cost | Rate Limit |
|
||||
|----------|------|------|-----------|
|
||||
| **Yahoo Finance** (yfinance) | Prices, fundamentals, options | Free | ~1,000/hr |
|
||||
| **Finnhub** | Real-time + fundamentals + alternatives | Free tier | 60 calls/min |
|
||||
| **Alpha Vantage** | Prices, fundamentals, alternatives | Free tier | 5 calls/min |
|
||||
| **FRED** | Macro/economic data | Free | None |
|
||||
| **SEC EDGAR** | All filings | Free | None |
|
||||
| **Quandl/Nasdaq Data** | Economic data | Free tier | Limited |
|
||||
| **Polygon.io** | Real-time + options | Free tier | Limited |
|
||||
|
||||
### Paid Tier
|
||||
| Provider | Data | Cost | Edge Level |
|
||||
|----------|------|------|-----------|
|
||||
| **Finnhub** Pro | All + alternatives + sentiment | $100/mo | Medium |
|
||||
| **Polygon.io** | Real-time + options + fundamentals | $29-$199/mo | Medium |
|
||||
| **Twelve Data** | Prices, fundamentals, crypto | $49-$299/mo | Medium |
|
||||
| **Dataroma** | Institutional holdings | $50/mo | Medium |
|
||||
| **InsiderMonkey** | Insider + institutional | $50-$200/mo | Medium |
|
||||
| **YipitData** | Consumer spending, shipping | $500+/mo | High |
|
||||
| **Seeking Alpha Pro** | Earnings transcripts, articles | $240/yr | Medium |
|
||||
| **Koyfin** | Bloomberg-lite terminal | $50-$200/mo | Medium |
|
||||
| **Bloomberg Terminal** | Everything | $25k/yr | Highest |
|
||||
| **Refinitiv (LSEG)** | Everything | $25k+/yr | Highest |
|
||||
|
||||
### Recommended Stack (MVP → Scale)
|
||||
|
||||
**Phase 1 (MVP — Free/Low Cost):**
|
||||
- `yfinance` or `Finnhub Free` — prices + fundamentals
|
||||
- `FRED` — macro data (all free, official government source)
|
||||
- `SEC EDGAR API` — all filings (free, official)
|
||||
- `Alpha Vantage Free` — alternatives (sentiment, tech indicators)
|
||||
|
||||
**Phase 2 (Growth — ~$150/mo):**
|
||||
- `Finnhub Pro` — real-time data + alternatives
|
||||
- `Polygon.io` — options data + real-time
|
||||
- `Dataroma` — clean institutional ownership data
|
||||
- `Seeking Alpha Pro` — earnings transcripts
|
||||
|
||||
**Phase 3 (Scale — ~$500/mo):**
|
||||
- `YipitData` or `Earnest Research` — consumer spending
|
||||
- `Project44` or `Descartes` — supply chain
|
||||
- `SimilarWeb` — web traffic
|
||||
- `SafeGraph` — foot traffic
|
||||
|
||||
---
|
||||
|
||||
## Recommended Data Model (Database Schema)
|
||||
|
||||
### Core Tables
|
||||
|
||||
```sql
|
||||
-- Time series price data (granular)
|
||||
stock_prices (
|
||||
ticker VARCHAR,
|
||||
date DATE,
|
||||
open DECIMAL, high DECIMAL, low DECIMAL, close DECIMAL,
|
||||
volume BIGINT,
|
||||
vwap DECIMAL,
|
||||
source VARCHAR,
|
||||
PRIMARY KEY (ticker, date, source)
|
||||
);
|
||||
|
||||
-- Fundamental data (quarterly)
|
||||
fundamentals (
|
||||
ticker VARCHAR,
|
||||
quarter DATE,
|
||||
revenue DECIMAL,
|
||||
gross_margin DECIMAL,
|
||||
operating_margin DECIMAL,
|
||||
net_margin DECIMAL,
|
||||
eps DECIMAL,
|
||||
pe_ratio DECIMAL,
|
||||
market_cap DECIMAL,
|
||||
pb_ratio DECIMAL,
|
||||
ps_ratio DECIMAL,
|
||||
roe DECIMAL,
|
||||
roic DECIMAL,
|
||||
debt_equity DECIMAL,
|
||||
current_ratio DECIMAL,
|
||||
fcf DECIMAL,
|
||||
shares_outstanding BIGINT,
|
||||
PRIMARY KEY (ticker, quarter)
|
||||
);
|
||||
|
||||
-- Institutional ownership (quarterly)
|
||||
institutional_holdings (
|
||||
ticker VARCHAR,
|
||||
date DATE,
|
||||
holder_name VARCHAR,
|
||||
shares BIGINT,
|
||||
pct_float DECIMAL,
|
||||
holding_type VARCHAR,
|
||||
filing_form VARCHAR,
|
||||
PRIMARY KEY (ticker, date, holder_name)
|
||||
);
|
||||
|
||||
-- Insider transactions (daily)
|
||||
insider_transactions (
|
||||
ticker VARCHAR,
|
||||
date DATE,
|
||||
insider_name VARCHAR,
|
||||
title VARCHAR,
|
||||
transaction_type VARCHAR, -- BUY, SELL, EXERCISE
|
||||
shares BIGINT,
|
||||
price DECIMAL,
|
||||
value DECIMAL,
|
||||
form_4_date DATE,
|
||||
PRIMARY KEY (ticker, date, insider_name, shares)
|
||||
);
|
||||
|
||||
-- SEC filings
|
||||
sec_filings (
|
||||
ticker VARCHAR,
|
||||
date DATE,
|
||||
form_type VARCHAR, -- 10-K, 10-Q, 8-K, DEF 14A, etc.
|
||||
url VARCHAR,
|
||||
filing_date DATE,
|
||||
period_end DATE,
|
||||
nlp_summary TEXT,
|
||||
nlp_sentiment DECIMAL,
|
||||
risk_factors_added INT,
|
||||
risk_factors_removed INT,
|
||||
PRIMARY KEY (ticker, date, form_type)
|
||||
);
|
||||
|
||||
-- Options data
|
||||
options_chain (
|
||||
ticker VARCHAR,
|
||||
date DATE,
|
||||
expiry DATE,
|
||||
strike DECIMAL,
|
||||
option_type VARCHAR, -- CALL, PUT
|
||||
volume BIGINT,
|
||||
open_interest BIGINT,
|
||||
implied_vol DECIMAL,
|
||||
last_price DECIMAL,
|
||||
PRIMARY KEY (ticker, date, expiry, strike, option_type)
|
||||
);
|
||||
|
||||
-- Short interest (bi-monthly)
|
||||
short_interest (
|
||||
ticker VARCHAR,
|
||||
date DATE,
|
||||
short_shares BIGINT,
|
||||
float BIGINT,
|
||||
short_pct FLOAT,
|
||||
days_to_cover FLOAT,
|
||||
borrow_fee FLOAT,
|
||||
PRIMARY KEY (ticker, date)
|
||||
);
|
||||
|
||||
-- Sector rotation (daily)
|
||||
sector_performance (
|
||||
ticker VARCHAR, -- ETF ticker (XLK, XLF, etc.)
|
||||
date DATE,
|
||||
close DECIMAL,
|
||||
change_pct DECIMAL,
|
||||
volume BIGINT,
|
||||
rs_vs_spy DECIMAL, -- relative strength vs SPY
|
||||
above_ma50 BOOLEAN,
|
||||
above_ma200 BOOLEAN,
|
||||
rsi_14 DECIMAL,
|
||||
PRIMARY KEY (ticker, date)
|
||||
);
|
||||
|
||||
-- Watchlists
|
||||
watchlists (
|
||||
id UUID PRIMARY KEY,
|
||||
user_id UUID,
|
||||
name VARCHAR,
|
||||
created_at TIMESTAMP,
|
||||
updated_at TIMESTAMP
|
||||
);
|
||||
|
||||
watchlist_items (
|
||||
watchlist_id UUID REFERENCES watchlists(id),
|
||||
ticker VARCHAR,
|
||||
added_at TIMESTAMP,
|
||||
notes TEXT,
|
||||
PRIMARY KEY (watchlist_id, ticker)
|
||||
);
|
||||
|
||||
-- Strategies
|
||||
strategies (
|
||||
id UUID PRIMARY KEY,
|
||||
user_id UUID,
|
||||
name VARCHAR,
|
||||
description TEXT,
|
||||
created_at TIMESTAMP,
|
||||
updated_at TIMESTAMP,
|
||||
is_active BOOLEAN
|
||||
);
|
||||
|
||||
strategy_rules (
|
||||
strategy_id UUID REFERENCES strategies(id),
|
||||
rule_type VARCHAR, -- TECHNICAL, FUNDAMENTAL, SENTIMENT
|
||||
condition VARCHAR,
|
||||
threshold DECIMAL,
|
||||
direction VARCHAR, -- ABOVE, BELOW, CROSS_ABOVE, CROSS_BELOW
|
||||
PRIMARY KEY (strategy_id, condition)
|
||||
);
|
||||
|
||||
-- Alerts
|
||||
alerts (
|
||||
id UUID PRIMARY KEY,
|
||||
user_id UUID,
|
||||
watchlist_id UUID,
|
||||
strategy_id UUID,
|
||||
triggered_at TIMESTAMP,
|
||||
ticker VARCHAR,
|
||||
alert_type VARCHAR,
|
||||
message TEXT,
|
||||
is_read BOOLEAN,
|
||||
data JSONB -- raw data that triggered the alert
|
||||
);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Data Pipeline Architecture
|
||||
|
||||
```
|
||||
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
|
||||
│ API/Scraper │───▶│ Raw Data │───▶│ Normalization │
|
||||
│ (yfinance, │ │ Lake (S3/MinIO)│ │ & Enrichment │
|
||||
│ FRED, EDGAR) │ │ │ │ (PostgreSQL) │
|
||||
└─────────────────┘ └─────────────────┘ └─────────┬───────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
|
||||
│ Real-time │◀───│ Feature │◀───│ API Layer │
|
||||
│ WebSocket │ │ Engineering │ │ (FastAPI) │
|
||||
│ (prices, │ │ (technical, │ │ │
|
||||
│ options, │ │ sentiment) │ │ │
|
||||
│ alerts) │ └─────────────────┘ └─────────────────┘
|
||||
└─────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Summary: The Edge Pyramid
|
||||
|
||||
```
|
||||
┌─────────────────┐
|
||||
│ AI/ML Signals │ ← Composite scores, anomaly detection
|
||||
├─────────────────┤
|
||||
│ Alternative Data │ ← Consumer spend, web traffic, jobs
|
||||
├─────────────────┤
|
||||
│ Institutional │ ← 13F flows, insider buys, hedge funds
|
||||
├─────────────────┤
|
||||
│ Options/Short │ ← Put/call, squeeze potential
|
||||
├─────────────────┤
|
||||
│ SEC Filings │ ← NLP on 8-Ks, MD&A changes
|
||||
├─────────────────┤
|
||||
│ Fundamentals │ ← Financials, ratios, quality scores
|
||||
├─────────────────┤
|
||||
│ Technical │ ← Charts, indicators, volume
|
||||
└─────────────────┘
|
||||
│ Market Data │ ← Prices, volume (table stakes)
|
||||
```
|
||||
|
||||
**The real edge lives in layers 4-7.** Layers 1-3 everyone has. Layer 8 (AI/ML) is where you combine all signals into predictive composites.
|
||||
Reference in New Issue
Block a user