Install
$ agentstack add skill-deeleeramone-pywry-tvchart ✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
About
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 @ attachment (the chat prepends --- Attached: ---\nwidget_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:
- Call
tvchart_compare(widget_id, query="")to add the
secondary ticker as a compare series and confirm it landed in state.compareSymbols.
- 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].typeis"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)
tvchart_redo(widget_id)
tvchart_save_layout(widget_id, name)
tvchart_open_layout(widget_id, name)
tvchart_save_state(widget_id)
Misc UI
tvchart_show_indicators(widget_id) # open indicator panel
tvchart_show_settings(widget_id)
tvchart_screenshot(widget_id)
tvchart_fullscreen(widget_id)
tvchart_toggle_dark_mode(widget_id)
Adding a compare overlay
tvchart_compare(widget_id, query, auto_add=True,
symbol_type=None, exchange=None)
→ { "widget_id": "chart", "compareSymbols": { "compare-spy": "SPY" },
"state": {...} }
query is the ticker to add. Pass symbol_type to disambiguate: SPY without it may resolve to SPYM (a near-prefix equity); symbol_type="etf" routes it to the SPDR ETF. exchange narrows to a specific venue. Both are case-insensitive and silently dropped when the datafeed doesn't know the value.
The tool polls state.compareSymbols for up to ~10s (compares require a full datafeed round-trip) before reporting a note. Calling tvchart_compare(widget_id) with no query just opens the dialog for the user — no state confirmation.
Series and bar updates (non-datafeed mode)
Use these only when the chart is NOT in datafeed mode (the datafeed manages its own streams). In datafeed mode, new symbol / interval data is fetched automatically via tvchart:data-request — don't try to push bars yourself.
tvchart_update_series(widget_id, series_id, bars, volume=None)
tvchart_update_bar(widget_id, series_id, bar) # live tick
tvchart_add_series(widget_id, series_id, bars, series_type="Line", series_options={...})
tvchart_remove_series(widget_id, series_id)
tvchart_apply_options(widget_id, chart_options=..., series_id=..., series_options=...)
Last-resort escape hatch
If no typed tool exists for a specific event, use:
send_event(widget_id, event_type, data)
Event types are namespaced tvchart:. This is a raw passthrough — prefer the typed tools above in every other case.
Don'ts
- Do NOT fabricate chart state, bars, or timestamps. Call the tool.
- Do NOT emit "Updated Chart State" or "Chart Update Response"
pseudo-JSON blocks in replies — only quote real tool returns.
- Do NOT guess a
widget_id— read it from the attachment or call
list_widgets().
- Do NOT call
send_eventwhen a typed tool already exists for the
event.
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: deeleeramone
- Source: deeleeramone/PyWry
- License: Apache-2.0
- Homepage: https://deeleeramone.github.io/PyWry/
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet — be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.