tradingview-strategy¶
ICT strategy interpretation layer. Reads four Pine indicators through tradingview-mcp, interprets graphics into structured signals, and produces StrategyFlags JSON. Serves a live dashboard at localhost:8000.
Pipeline Overview¶
graph LR
subgraph Readers["Readers (parallel)"]
R1["biasReader"]
R2["sessionReader"]
R3["obReader"]
R4["smtReader"]
R5["priceReader"]
end
subgraph Interpreters["Interpreters"]
I1["biasInterpreter"]
I2["sessionInterpreter"]
I3["obInterpreter"]
I4["smtInterpreter"]
I5["priceInterpreter"]
end
subgraph Engine["Engine"]
E1["No-trade filters"]
E2["Confluence scoring"]
E3["Setup detection"]
E4["Flag builder"]
E1 --> E2 --> E3 --> E4
end
R1 --> I1
R2 --> I2
R3 --> I3
R4 --> I4
R5 --> I5
I1 & I2 & I3 & I4 & I5 --> E1
E4 --> FLAGS["StrategyFlags JSON"]
FLAGS --> DASH["Dashboard :8000"]
Readers¶
Each reader is responsible for a single indicator. It calls MCP tools with study_filter, normalizes the response, and returns raw data. Readers perform no interpretation.
| Reader | study_filter | MCP Tools Used | Output Shape |
|---|---|---|---|
biasReader |
"Bias AI" |
getPineLabels, getPineTables |
{ labels: [], tables: [] } |
sessionReader |
"Session Hunt AI" |
getPineLabels, getPineLines |
{ labels: [], lines: [] } |
obReader |
"OB AI" |
getPineBoxes, getPineLabels |
{ boxes: [], labels: [] } |
smtReader |
"SMT Divergences" |
getPineLabels, getPineLines |
{ labels: [], lines: [] } |
priceReader |
N/A | getOhlcv, quoteGet |
{ bars: [], quote: {} } |
Reader responsibilities:
- Call MCP tools with
study_filterto isolate indicator data - Handle empty responses (indicator not loaded, no visible data)
- Normalize timestamps and coordinates
- Return raw objects without interpretation
Every reader exports a single async function: async function read(options) -> { ... }
Interpreters¶
Each interpreter takes reader output and applies indicator-specific contract rules to produce a typed signal. This is where color mappings, label text parsing, and spatial logic live.
| Interpreter | Output Signal | Key Fields |
|---|---|---|
biasInterpreter |
BiasSignal |
dailyBias, weeklyBias, confidence, biasShift |
sessionInterpreter |
SessionSignal |
activeSession, activeMacro, killzoneActive, liquiditySweep |
obInterpreter |
OBSignal |
blocks[], nearestBlock, fvgFiltered, mitigated |
smtInterpreter |
SMTSignal |
divergencePresent, direction, pair, strength |
priceInterpreter |
PriceSignal |
currentPrice, atr, recentSwings, microStructure |
Interpreters are synchronous and pure. No I/O, no side effects, no MCP calls.
Interpretation Examples¶
- Bias AI: Green label = bullish, red = bearish. Tooltip regex
Confidence: (\d+)%extracts confidence. - Session Hunt AI: Label text
"NY AM | 0950-1010"parsed to session + macro. Dotted lines = liquidity levels. - OB AI: Box color = direction. Coordinates = zone boundaries. Nearby labels = FVG/mitigation status.
- SMT AI: Label pairs on correlated instruments indicate divergence. Line slope = direction.
Engine¶
The engine receives all five signals and produces StrategyFlags.
No-Trade Filters¶
Hard filters checked first. If any triggers, tradeReady: false and confluence: 0:
- No daily bias established
- Outside all session killzones
- No unmitigated order blocks visible
- Bias shift detected (transitional state)
Confluence Scoring¶
| Signal Component | Weight | Condition |
|---|---|---|
| Daily bias present | 2 | BiasSignal.dailyBias !== null |
| Weekly bias agrees with daily | 1 | Weekly matches daily |
| Active killzone | 2 | SessionSignal.killzoneActive |
| Active macro window | 1 | SessionSignal.activeMacro !== null |
| Unmitigated OB in bias direction | 3 | Direction matches bias, not mitigated |
| FVG-filtered OB | 1 | OBSignal.fvgFiltered |
| SMT divergence in bias direction | 2 | Direction matches bias |
Raw score normalized to 0-100.
Setup Detection¶
When confluence exceeds threshold and no filters are active:
- OB_FVG_BIAS -- order block + FVG filter + directional bias
- SMT_OB_SESSION -- divergence-confirmed entry with session context
- MACRO_OB_BIAS -- macro window entry
Flag Builder¶
Assembles the final StrategyFlags JSON:
{
"timestamp": "2026-04-14T14:35:00Z",
"symbol": "ES",
"timeframe": "5",
"bias": { "daily": "bearish", "weekly": "bearish", "shift": false, "confidence": 0.85 },
"session": { "name": "NY_AM", "macro": "0950-1010", "killzone": true },
"orderBlocks": [{ "direction": "bearish", "high": 5245.50, "low": 5243.00, "fvg": true, "mitigated": false }],
"smt": { "present": true, "direction": "bearish", "pair": "ES/NQ", "strength": 0.7 },
"price": { "current": 5246.25, "atr": 12.5 },
"confluence": 82,
"tradeReady": true,
"setup": "OB_FVG_BIAS",
"noTradeReasons": []
}
Orchestration¶
scan.js -- Full Pipeline¶
scan.js executes one complete scan cycle:
- All five readers execute in parallel (independent indicators)
- Interpreters run sequentially (synchronous, fast)
- Engine runs once with all signals collected
- Returns StrategyFlags
Total wall-clock time is dominated by the slowest MCP read (~100-300ms).
poll.js -- Interval Scanning¶
Wraps scan.js in an interval loop with delta detection:
- Configurable interval (default: 5 seconds)
- Emits events only when flags change
- Automatic retry on connection drops
- Graceful shutdown support
Dashboard Integration¶
The dashboard/ directory inside tradingview-strategy contains a web server and UI.
server.js¶
Express-based server at localhost:8000 with three API endpoints:
| Endpoint | Method | Returns |
|---|---|---|
/api/data |
GET | Current StrategyFlags JSON |
/api/settings |
GET/POST | Indicator configuration and thresholds |
/api/screenshot |
GET | Latest chart screenshot (PNG) |
The dashboard HTML auto-refreshes by polling /api/data on an interval. It displays:
- Current bias direction and confidence
- Active session and macro window
- Order block proximity and FVG status
- SMT divergence state
- Confluence score gauge
- Trade readiness indicator
- Live chart screenshot
- Indicator settings popup for runtime configuration
Pipeline Integration¶
scan.js writes its output to a location that server.js reads on each API request. The dashboard is always showing the latest completed scan result. No WebSocket -- simple file-based hand-off with HTTP polling.
Contracts¶
The contracts/ directory holds source-of-truth definitions:
| File | Contents |
|---|---|
schemas.js |
Zod schemas for all signal types and StrategyFlags |
constants.js |
Session times, macro windows, confluence weights |
colors.js |
Indicator-specific color-to-meaning mappings |
indicators.js |
Indicator names (for study_filter) and expected graphics types |
Contracts are the only shared dependency between readers and interpreters. When an indicator updates its output format, the contract file is the single point of change.