Skip to content
Development
Skill

/tvchart

Drive a live TradingView Lightweight Charts widget end-to-end via PyWry MCP tools — symbol, interval, indicators, markers, price lines, layouts, state.

From plugin
pywry
9318 skills1 agent2 commands1 MCP
Install
$ npx -y skills add deeleeramone/PyWry --skill tvchart --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/tvchart

Context preview

The summary Claude sees to decide when to auto-load this skill.

Drive a live TradingView Lightweight Charts widget end-to-end via PyWry MCP tools — symbol, interval, indicators, markers, price lines, layouts, state.

SKILL.md

tvchart.SKILL.md
description: Drive a live TradingView Lightweight Charts widget end-to-end via PyWry MCP tools — symbol, interval, indicators, markers, price lines, layouts, state.

TradingView Chart — Agent Reference

> **Use this when an agent needs to read or mutate a live `tvchart` > widget.** Every action is an MCP tool call on the PyWry FastMCP > server — there are no local helpers, no side channels, no custom > tools. Pick the typed tool that matches the user's intent, pass the > required arguments, and quote the tool's return values in your > reply.

Every tool takes `widget_id`

`widget_id` identifies which chart to operate on. On a single-chart server the framework auto-resolves it from the registry; on a multi-chart server you must pass it explicitly. Read the value from the user's `@<name>` attachment (the chat prepends `--- Attached: <name> ---\nwidget_id: <id>`) or call `list_widgets()` to enumerate.

Reading chart state — always via `tvchart_request_state`

Never report symbol / interval / indicators / bars / last close from memory. Call the tool, quote the return.

tvchart_request_state(widget_id)
  → {
      "widget_id": "chart",
      "state": {
        "symbol": "AAPL",
        "interval": "1D",
        "series": [{ "seriesId": "main", "bars": [...], ... }],
        "indicators": [...],
        "visibleRange": { "from": ..., "to": ... },
        "chartType": "Candles",
        ...
      }
    }

When the user asks "what's on the chart", "what's the current price", "what indicators are applied", call this and quote from `state`.

Mutating tools — all confirm the change

Every mutation returns the real post-change state. The model never has to guess whether the change took effect. If the mutation didn't land within the settle window, the tool includes a `note` field — relay it to the user.

Symbol change

tvchart_symbol_search(widget_id, query, auto_select=True,
                      symbol_type=None, exchange=None)
  → { "widget_id": "chart", "symbol": "MSFT", "state": {...} }

Use this to switch the ticker. `auto_select=True` commits the selection; `auto_select=False` just opens the search dialog for the user. The tool polls chart state until the symbol actually changes to the target (up to ~6s) so the return reflects reality.

Pass `symbol_type` to narrow the datafeed search to a specific security class — values come from the datafeed, typically `equity`, `etf`, `index`, `mutualfund`, `future`, `cryptocurrency`, `currency`. Use it whenever the user's query is ambiguous: `SPY` with `symbol_type="etf"` resolves to the SPDR S&P 500 ETF instead of picking a near-prefix equity like `SPYM`. `exchange` narrows to a specific venue the same way. Both are case-insensitive; unknown values are silently dropped rather than erroring.

Interval / timeframe

tvchart_change_interval(widget_id, value)
  → { "widget_id": "chart", "interval": "1W", "state": {...} }

Valid values: `1m 3m 5m 15m 30m 45m 1h 2h 3h 4h 1d 1w 1M 3M 6M 12M`. Tool confirms the change via state polling.

Indicators

tvchart_add_indicator(widget_id, name, period=..., color=..., ...)
tvchart_remove_indicator(widget_id, series_id)
tvchart_list_indicators(widget_id)

Supported names: `SMA`, `EMA`, `WMA`, `RSI`, `ATR`, `VWAP`, `Bollinger Bands`, plus the rest of the built-in library. `period` defaults to a sensible value per indicator; override when the user asks.

Compare-derivative indicators

`Spread`, `Ratio`, `Sum`, `Product`, `Correlation` require a **secondary series** — a second ticker to spread/ratio/etc. against the main series. The flow is two steps:

1. Call `tvchart_compare(widget_id, query="<ticker>")` to add the secondary ticker as a compare series and confirm it landed in `state.compareSymbols`. 2. Call `tvchart_add_indicator(widget_id, name="Spread", ...)`. The chart picks up the most recent compare series as the secondary automatically; pass `source` / `method` / `multiplier` to tune.

State reporting for these indicators:

  • `state.indicators[i].type` is `"spread"` / `"ratio"` / etc.
  • `state.indicators[i].secondarySeriesId` — the compare seriesId.
  • `state.indicators[i].secondarySymbol` — the ticker it resolves to

(this is what the user actually cares about when you describe the indicator).

  • `state.indicatorSourceSymbols` — the compare-series map restricted

to indicator inputs; these are NOT user-facing compares (they're hidden from the Compare panel). Don't conflate with `state.compareSymbols` when listing "what's compared on the chart".

If the user asks "what's on the chart" for a chart with a Spread against MSFT, quote it as `Spread(AAPL, MSFT)` using the indicator's `secondarySymbol`, not the raw seriesId.

Chart type / rendering

tvchart_chart_type(widget_id, value)
  # value ∈ { "Candles", "Line", "Heikin Ashi", "Bars", "Area" }

tvchart_log_scale(widget_id, value)    # true / false
tvchart_auto_scale(widget_id, value)

Visible range / zoom

tvchart_set_visible_range(widget_id, from_time, to_time)
  # times are Unix seconds

tvchart_fit_content(widget_id)
tvchart_time_range(widget_id, value)    # "1D", "5D", "1M", "6M", "YTD", "1Y", "5Y", "All"
tvchart_time_range_picker(widget_id)    # opens custom picker UI

Markers and price lines

tvchart_add_markers(widget_id, markers)
  # markers = [{ time, position, color, shape, text }, ...]
  # position: "aboveBar" | "belowBar" | "inBar"
  # shape: "arrowUp" | "arrowDown" | "circle" | "square"

tvchart_add_price_line(widget_id, price, title="", color="#2196F3", line_width=1)

Use markers for signals / events on specific bars. Use price lines for support / resistance / targets (horizontal lines across the whole chart).

Drawing tools

tvchart_drawing_tool(widget_id, tool)
  # tool ∈ { "trendline", "horizontal", "rectangle", "brush", "eraser", "cursor", ... }

History and layout

tvchart_undo(widget_id)
tvcha
Read more
Ships withpywry

PyWry is a cross-platform app factory, rendering engine and UI toolkit for Python that produces native desktop, web, and notebook experiences from a single API.

Get the whole plugin

Other skills on pywry.