LangGraph-backed · FastAPI · real-time

A technical indicator
analysis service.

Computes 20+ technical indicators, and combines sentiment signals into a single decision score. It outputs a clear buy / hold / sell recommendation with interactive charts and locally stored run history.

Python 3.12 FastAPI LangGraph LangChain tools pandas-ta yfinance · ccxt FinBERT · LLM sentiment Chart.js · TailwindCSS Docker · Helm · Kubernetes

What it does

Framework-agnostic core, three consumption surfaces: a LangGraph subgraph, a set of LangChain @tool functions, and a single-page web UI.

1 · Data fan-out

Any asset, any provider

yfinance for stocks, ccxt (binance/bybit/…) for crypto, polygon/alpha-vantage/alpaca for real-time. Provider strings accept a head:extra form. Zero-key providers just work.

2 · Technical indicators

20+ indicators, three stacked levels

Core (RSI, MACD, Bollinger, ATR, stochastic, OBV, SMAs/EMAs) → Extended (ADX/DMI, Ichimoku, VWAP, CCI, Williams %R, MFI, Aroon, PSAR) → Full (the entire pandas-ta catalog).

3 · Multi-source sentiment

FinBERT · Fear&Greed · social · LLM

Each source normalises to [-1, 1] with a confidence. A confidence-weighted mean yields the composite; per-source rationales surface in the UI.

4 · BUY / HOLD / SELL

One weighted decision

15 components collapse to three category scores (momentum · trend · volatility) and then to a single composite in [−1, +1], thresholded into a discrete label.

5 · Price + volume chart

Live OHLCV render

500-bar history by default; line + filled-area close price with a secondary volume axis. Runs entirely in-browser via Chart.js.

6 · History & UX

LocalStorage-backed recall

Past runs live as re-runnable chips. Click one and the form + request replay. Nothing is persisted server-side.

How it flows

A LangGraph subgraph fans out from a single fetch, then fans back in. The whole pipeline is stateless, cached at the module level, and pluggable at three seams: providers, indicators, sentiment sources.

input
AnalysisRequest
symbol · class · tf · level
node
fetch_data
provider.fetch_ohlcv()
fan-out
compute_indicators
IndicatorSnapshot
fan-out
compute_sentiment
CompositeSentiment
fan-in
assemble → MarketAnalysis
served via FastAPI POST /api/analyze
weighted indicator combination

The BUY / HOLD / SELL signal

Each indicator is normalised to a score in [−1, +1] — +1 is maximally bullish, −1 maximally bearish. Scores are averaged within three categories, then combined with category weights into a single composite. A ±0.20 dead-zone separates actionable signals from noise.

Category weights

s = 0.30·smom + 0.50·strend + 0.20·svol
momentum · 30% contrarian oscillators
trend · 50% directional indicators
volatility · 20% band position

When a category has no available components, its weight is redistributed proportionally to the others — missing indicators never silently drag the composite toward zero.

Component formulas (15 components)

CategoryIndicatorFormula+1 / −1 anchors
MRSI (14)(50 − RSI) / 2030 → +1 · 70 → −1
MStochastic %K(50 − %K) / 3020 → +1 · 80 → −1
MWilliams %R (14)(−50 − WR) / 30−80 → +1 · −20 → −1
MCCI (20)−CCI / 150−150 → +1 · +150 → −1
MMFI (14)(50 − MFI) / 3020 → +1 · 80 → −1
VBollinger %B(0.5 − %B) × 20 → +1 · 1 → −1
TPrice vs SMA(50)(close − SMA₅₀) / SMA₅₀ / 0.05±5% distance saturates
TPrice vs SMA(200)(close − SMA₂₀₀) / SMA₂₀₀ / 0.10±10% distance saturates
TEMA(12) vs EMA(26)(EMA₁₂ − EMA₂₆) / (close × 0.02)spread = 2% close
TMACD histogramhist / (close × 0.005)|hist| = 0.5% close
TAroon oscillatoraroon / 50±50 on [−100, +100]
TPrice vs PSAR(close − PSAR) / close / 0.02±2% distance saturates
TPrice vs VWAP(close − VWAP) / VWAP / 0.03±3% distance saturates
TIchimokucloud (±0.6) + T/K (±0.4)cloud position + tenkan-kijun
TDI+/DI− (ADX-gated)((DI+ − DI−)/25) × min(ADX/25, 1)25pt spread, weak-trend scale-down

Momentum oscillators are read contrarianly (oversold → BUY), trend indicators are read directionally, Bollinger %B is contrarian (price at lower band → BUY). Every result is clamped to [−1, +1].

Try it

slide category means · live composite
+0.60
+0.40
-0.20
Composite
BUY
+41%
−100% SELL 0 HOLD +100% BUY
Decision rule: s ≥ +0.20 → BUY · s ≤ −0.20 → SELL · else HOLD

Run it three ways

Framework-agnostic core means the same pipeline ships as a local Python library, a Docker image, and a Helm release on Kubernetes.

local

Editable install

pip install -e ".[web]"
./web/run.sh
# → http://127.0.0.1:8000
docker

Single-service compose

cp .env.example .env
docker compose up --build
# → http://127.0.0.1:8000
kubernetes

Helm chart + redeploy

kubectl create ns indicators
kubectl -n indicators create secret generic \
  indictor-api-keys --from-env-file=.env
./redeploy.sh   # build → push → helm upgrade
HTTPS ingress indicators.findipend.com nginx non-root pod liveness · readiness · startup probes envFrom Secret

See it in action

Type an asset like BTC/USDT or AAPL, hit Analyze, and watch the full stack collapse into one number in under 2 seconds.