Stocks · AI Analysis · Sectors · Live News · Macro Data · Satellite Intelligence
A full-stack, single-file market intelligence dashboard with dark premium UI, multi-model AI analysis, real-time FRED macroeconomic data, Google Trends sentiment, live AIS vessel tracking, and satellite target mapping across 11 global sectors.
Features · Architecture · Installation · Configuration · API Reference
STARFISH is a self-contained Flask web application that aggregates financial market intelligence from over 10 live data sources into a single, dark-themed dashboard. It supports US and Indian (NSE/BSE) equities, provides multi-model AI analysis via OpenRouter, and surfaces alternative data signals — from shipping traffic to satellite imagery targets — that institutional analysts rely on.
The entire platform ships as a single Python file (starfish__3_.py), requiring no database, no frontend build step, and no external deployment pipeline. Spin it up locally in under two minutes.
- Candlestick & Line charts rendered via Plotly with a custom dark theme
- 5 overlay indicators: SMA (20/50/200), Bollinger Bands, RSI (14), MACD (12/26/9), Volume bars
- Time range selector: 1M · 3M · 6M · 1Y · 2Y · 5Y
- Fully responsive, drag-to-pan, hover-unified tooltips
- USD and INR currency detection — appends
.NSfor NSE /.BOfor BSE stocks
Three LLMs available via OpenRouter, selectable per analysis request:
| Model | Key | Strength |
|---|---|---|
| DeepSeek R1 | deepseek/deepseek-r1 |
Chain-of-thought reasoning |
| Llama 3.3 70B | meta-llama/llama-3.3-70b-instruct |
Fast & balanced |
| Qwen3 Coder | qwen/qwen3-coder |
Quantitative focus |
The AI prompt is constructed from 12 technical indicators, OHLCV data, FRED macro, Google Trends, shipping context, and company fundamentals — giving each model a rich, structured financial brief.

Pulls 9 key macroeconomic series from the St. Louis Fed public API:
| Series ID | Metric |
|---|---|
DFF |
Fed Funds Rate (%) |
CPIAUCSL |
CPI YoY (%) |
UNRATE |
Unemployment Rate (%) |
GDP |
Real GDP QoQ (%) |
T10Y2Y |
10Y-2Y Yield Spread (bps) |
DTWEXBGS |
USD Trade-Weighted Index |
VIXCLS |
VIX Volatility Index |
BAMLH0A0HYM2 |
High-Yield Credit Spread (%) |
MORTGAGE30US |
30-Year Mortgage Rate (%) |
Results are cached with a 1-hour TTL and fetched concurrently using ThreadPoolExecutor.
Multi-source financial RSS scraper fetching from 7 outlets concurrently:
- Yahoo Finance, CNBC, MarketWatch, Benzinga, Financial Times, Wall Street Journal, Reuters, Seeking Alpha
News is filtered by sector-specific keywords across 11 GICS-aligned sectors.

- Baltic Dry Index (BDI) — scraped from public sources as a global trade proxy
- AIS vessel tracking — integrates
aisstream.ioWebSocket API for live ship positions - Major port monitoring: Houston, Los Angeles, Rotterdam, Singapore, Shanghai
/vesselspage renders a full-screen Leaflet.js map with real-time AIS vessel overlays
Each of the 11 sectors includes 30 curated latitude/longitude targets of key global industrial sites — refineries, steel mills, auto plants, airports, ports — enabling overlay with commercial satellite imagery tools.
Sectors covered: Energy, Materials, Industrials, Consumer Discretionary, Consumer Staples, Health Care, Financials, IT, Communication Services, Real Estate, Utilities.

A fully interactive satellite imagery viewer powered by the Copernicus Data Space Ecosystem (CDSE) and Sentinel Hub Process API, embedded directly in the dashboard:
- 5 spectral layers: True Color · False Color · NDVI (vegetation) · SWIR (soil/burn) · Geology
- Date range selector:
From Date/To Dateinputs for custom time windows - Cloud cover filter: Slider (0–100%) to exclude cloudy acquisitions; uses
mosaickingOrder: leastCC - Leaflet.js map with live XYZ tile proxy — each tile fetched server-side via
/sentinel/proxy-tile - Location search: Geocoding via Nominatim (OpenStreetMap) with autocomplete dropdown
- Token manager: Automatic OAuth2 token refresh (27-min cycle) against the CDSE identity endpoint — no manual re-auth needed
- Mobile responsive: Controls, map, and load button reflow correctly on narrow viewports (≤600px)
Uses pytrends to fetch 3-month search interest for each ticker's company name and stock symbol, returning current score, 30-day average, peak, and trend direction.
STARFISH (starfish.py)
│
├── Flask App (app)
│ ├── GET/POST / → Main dashboard page
│ ├── POST /api/ai-analysis → Multi-model AI analysis
│ ├── GET /api/rate-limits → Per-model rate limit status
│ ├── GET /api/live-id → YouTube live video ID lookup
│ ├── GET /api/news → Sector news aggregation
│ ├── GET /api/macro → FRED + Baltic Dry data
│ ├── GET /api/trends → Google Trends query
│ ├── GET /api/satellite → Sector satellite targets
│ ├── GET /api/ais-key → AIS stream key status
│ ├── GET /vessels → Live vessel tracking map
│ ├── GET /sentinel/token-status → CDSE OAuth2 token info
│ ├── GET /sentinel/geocode → Nominatim location search
│ ├── GET /sentinel/proxy-tile → Sentinel Hub tile proxy (XYZ)
│ └── GET /debug → Data source health check
│
├── Data Layer
│ ├── fetch_yfinance_data() → OHLCV via Yahoo Finance (v8/v7 fallback)
│ ├── fetch_all_macro() → FRED macro series (concurrent)
│ ├── fetch_fred_series() → Single FRED CSV fetch with cache
│ ├── fetch_all_news() → Multi-source RSS aggregation
│ ├── fetch_google_trends() → pytrends 3-month interest
│ ├── fetch_shipping_context() → AIS + port context
│ ├── fetch_baltic_dry() → BDI scraper
│ ├── _get_fundamentals() → yfinance ticker info
│ └── TokenManager → CDSE OAuth2 auto-refresh (27-min cycle)
│
├── Technical Analysis (12 Indicators)
│ ├── calc_sma() → Simple Moving Average
│ ├── calc_ema() → Exponential Moving Average
│ ├── calc_bb() → Bollinger Bands (±2σ)
│ ├── calc_rsi() → Relative Strength Index
│ ├── calc_macd() → MACD + Signal + Histogram
│ ├── calc_atr() → Average True Range
│ ├── calc_obv() → On-Balance Volume
│ ├── calc_stoch() → Stochastic Oscillator %K/%D
│ ├── calc_williams_r() → Williams %R
│ ├── calc_cmf() → Chaikin Money Flow
│ ├── calc_adx() → Average Directional Index
│ ├── calc_vwap() → Volume-Weighted Average Price
│ └── calc_ichimoku() → Ichimoku Cloud (Tenkan/Kijun/Span A&B)
│
├── AI Pipeline
│ ├── build_analysis_payload() → Assemble structured data dict
│ ├── build_prompt() → Construct LLM prompt string
│ └── call_openrouter() → HTTP POST to OpenRouter API
│
├── Chart Renderer
│ └── build_chart() → Plotly subplots (Price + Vol + RSI + MACD)
│
└── Rate Limiter
├── rl_check() → Sliding window availability check
├── rl_record() → Record a new request timestamp
└── rl_next_rpm_reset() → Seconds until oldest RPM slot expires
- Python 3.9+
- pip
# 1. Clone the repository
git clone https://github.com/yourusername/starfish.git
cd starfish
# 2. Install dependencies
pip install flask requests numpy pandas yfinance plotly httpx beautifulsoup4 lxml pytrends fredapi
# 3. Set environment variables (see Configuration below)
export OPEN_ROUTER_API_KEY="your_openrouter_key"
export AISSTREAM_API_KEY="your_aisstream_key" # optional
# 4. Run the server
python starfish__3_.pyOpen your browser at http://127.0.0.1:5000
| Variable | Required | Description |
|---|---|---|
OPEN_ROUTER_API_KEY |
Yes (for AI) | Your OpenRouter API key |
AISSTREAM_API_KEY |
No | AISStream.io key for live vessel tracking |
CDSE_USERNAME |
No | Copernicus Data Space email (for Sentinel-2 viewer) |
CDSE_PASSWORD |
No | Copernicus Data Space password (for Sentinel-2 viewer) |
_FRED_CACHE_TTL = 3600 # 1 hour — FRED macro data
_TRENDS_CACHE_TTL = 1800 # 30 min — Google Trends
_AIS_CACHE_TTL = 600 # 10 min — AIS shipping context
_CACHE_TTL = 1800 # 30 min — Yahoo Finance session/crumbTrigger a full AI market analysis for a ticker.
Request body (JSON):
{
"ticker": "AAPL",
"period": "6mo",
"model_id": "deepseek/deepseek-r1"
}Response:
{
"ticker": "AAPL",
"period": "6mo",
"model_id": "deepseek/deepseek-r1",
"analysis": "## Technical Analysis\n...",
"data_sources": [
"FRED Macro (9 series)",
"Google Trends (3 keywords)",
"Yahoo Fundamentals",
"12 Technical Indicators",
"30-Day OHLCV Chart",
"Candlestick Pattern Analysis",
"SPY Correlation"
]
}Error codes: 400 bad input · 404 no data · 429 rate limited · 500 server error · 502 upstream error
Returns live FRED macro indicators and Baltic Dry Index.
Response:
{
"macro": {
"DFF": { "label": "Fed Funds Rate (%)", "value": 5.33, "date": "2025-04-01", "change": 0.0 }
},
"baltic_dry": { "value": 1420, "date": "2025-04-22", "source": "BDI" },
"timestamp": "2025-04-22T10:30:00"
}Fetch latest news articles for a sector. Valid sector IDs: energy, materials, industrials, consumer-discretionary, consumer-staples, health-care, financials, information-technology, communication-services, real-estate, utilities.
Response:
{
"sector": "energy",
"sector_label": "Energy",
"count": 24,
"elapsed_seconds": 1.83,
"articles": [
{
"title": "Oil prices rise...",
"source": "Reuters",
"url": "https://...",
"published": "2 hours ago"
}
]
}Returns 30 curated latitude/longitude targets for satellite imagery analysis.
Response:
{
"sector": "energy",
"targets": [
{ "name": "Exxon Baytown Refinery", "tag": "REFINERY · US", "lat": 29.7355, "lon": -94.9774 }
]
}Fetches 3-month Google Trends data for a search query.
Returns live rate limit counters for all AI models.
{
"deepseek": { "rpm_used": 3, "rpm_max": 20, "rpd_used": 47, "rpd_max": 200, "available": true, "rpm_reset_secs": 42 }
}Looks up the active YouTube live stream video ID for a given channel handle.
Full-page AIS vessel tracking map (requires AISSTREAM_API_KEY).
Returns the current state of the CDSE OAuth2 token.
Response:
{
"fetched_at": "10:32:01 UTC",
"expires_at": "11:01:01 UTC",
"remaining_seconds": 1734,
"token_prefix": "eyJhbGciOiJSU…"
}Geocodes a location string via Nominatim (OpenStreetMap). Used by the satellite viewer's search bar.
Response:
{
"results": [
{ "display_name": "Rotterdam, South Holland, Netherlands", "lat": "51.9225", "lon": "4.47917" }
]
}GET /sentinel/proxy-tile?layer=TRUE-COLOR&dateFrom=2025-01-01&dateTo=2025-01-31&cloud=30&z=8&x=132&y=85
Server-side XYZ tile proxy for the Sentinel Hub Process API. Converts tile coordinates to a WGS84 bounding box, posts an evalscript request to Copernicus, and streams the resulting PNG back to the Leaflet map.
Query parameters:
| Param | Default | Description |
|---|---|---|
layer |
TRUE-COLOR |
Spectral layer: TRUE-COLOR · FALSE-COLOR · NDVI · SWIR · GEOLOGY |
dateFrom |
— | Start of acquisition window (YYYY-MM-DD) |
dateTo |
— | End of acquisition window (YYYY-MM-DD) |
cloud |
30 |
Max cloud coverage % (0–100) |
z, x, y |
— | Standard XYZ tile coordinates |
Returns a 512×512 PNG tile, or a 1×1 transparent fallback on error/no-data.
Health check: tests Yahoo Finance data fetch and FRED macro series. Returns colored pre-formatted output.
| Indicator | Function | Formula Notes |
|---|---|---|
| SMA 20/50/200 | calc_sma() |
rolling(w).mean() on Close |
| EMA | calc_ema() |
ewm(span=w, adjust=False).mean() |
| Bollinger Bands | calc_bb() |
SMA20 ± 2σ with fillcolor band |
| RSI (14) | calc_rsi() |
Wilder smoothing via EWMA |
| MACD (12,26,9) | calc_macd() |
EMA diff + signal + histogram |
| ATR (14) | calc_atr() |
True Range: max(H-L, |H-Cp|, |L-Cp|) |
| OBV | calc_obv() |
Cumulative volume signed by price direction |
| Stochastic %K/%D | calc_stoch() |
Rolling high/low normalization |
| Williams %R | calc_williams_r() |
Inverse stochastic |
| CMF (20) | calc_cmf() |
MFV × Volume / Σ Volume |
| ADX (14) | calc_adx() |
True directional movement via EWM |
| VWAP | calc_vwap() |
Cumulative (H+L+C)/3 × V / Cum V |
| Ichimoku | calc_ichimoku() |
Tenkan (9), Kijun (26), Senkou A & B |
| Support/Resistance | calc_support_resistance() |
Rolling min/max window peaks |
| Source | Data | Method |
|---|---|---|
| Yahoo Finance | OHLCV, fundamentals | Custom HTTP scraper (v8/v7/library fallback) |
| FRED — St. Louis Fed | 9 macro series | Public CSV endpoint |
| OpenRouter | LLM inference | REST API |
| Google Trends | Search interest | pytrends |
| AISStream.io | Live vessel positions | WebSocket API |
| Copernicus CDSE | Sentinel-2 L2A imagery | OAuth2 + Sentinel Hub Process API |
| Nominatim / OSM | Location geocoding | REST API |
| Yahoo Finance RSS | Financial news | RSS/XML scraping |
| CNBC, Reuters, FT, MW, Benzinga, WSJ | Financial news | RSS/XML scraping |
| BDI (Baltic Exchange) | Shipping index | Web scraping |
flask
requests
numpy
pandas
yfinance
plotly
httpx
beautifulsoup4
lxml
pytrends
fredapi
Install all at once:
pip install flask requests numpy pandas yfinance plotly httpx beautifulsoup4 lxml pytrends fredapiEach sector has 30 globally distributed satellite observation targets (10 US, 10 India, 10 Global):
| Sector ID | Label | ETF Proxy | Key Assets |
|---|---|---|---|
energy |
Energy | XLE | Refineries, LNG terminals, oil rigs |
materials |
Materials | XLB | Copper mines, steel mills, cement plants |
industrials |
Industrials | XLI | Aircraft factories, auto plants, ports |
consumer-discretionary |
Consumer Discretionary | XLY | Retail HQs, malls, auto dealers |
consumer-staples |
Consumer Staples | XLP | Grocery HQs, food factories, QSR chains |
health-care |
Health Care | XLV | Pharma HQs, hospitals, biotech campuses |
financials |
Financials | XLF | Bank HQs, exchanges, fintech offices |
information-technology |
Information Technology | XLK | Chip fabs, hyperscale data centers |
communication-services |
Communication Services | XLC | Broadcast towers, streaming campuses |
real-estate |
Real Estate | XLRE | REIT portfolios, data center REITs |
utilities |
Utilities | XLU | Power stations, water treatment, grid |
- The
OPEN_ROUTER_API_KEYis read from environment variables and never embedded in source code or HTML responses - The
AISSTREAM_API_KEYis served only via the same-origin/api/ais-keyendpoint, never injected into public HTML - All external requests include a realistic
User-Agentheader pool to avoid bot detection - Session and crumb caches are stored in-process memory only (no disk persistence)
Yahoo Finance periodically changes their authentication flow. STARFISH implements a 3-tier fallback:
- v8 API —
/v8/finance/chart/with crumb authentication - v7 API —
/v7/finance/download/CSV endpoint - yfinance library — official Python library as last resort
Crumbs are refreshed automatically when they expire (30-minute TTL), and the session rotates through a pool of 3 user agents.
Contributions are welcome. Please:
- Fork the repository
- Create a feature branch:
git checkout -b feature/my-feature - Make changes in
starfish__3_.py(or split into modules if refactoring) - Test your changes:
python starfish__3_.py→ verify/debugpasses - Submit a pull request with a clear description
- Add more AI models to the
AI_MODELSlist - Add additional FRED series to
FRED_SERIES - Expand sector news sources
- Add more satellite targets per sector
- WebSocket-based live price streaming
- Persistent caching (Redis / SQLite)
This project is licensed under the MIT License. See LICENSE for details.
- Yahoo Finance for OHLCV data
- FRED — Federal Reserve Bank of St. Louis for macroeconomic series
- OpenRouter for multi-model LLM routing
- Plotly for interactive charting
- AISStream.io for vessel tracking
- Copernicus Data Space Ecosystem & ESA for Sentinel-2 satellite imagery
- OpenStreetMap / Nominatim for location geocoding
BUILT TO BEAT THE BENCHMARK.
