Stock Index Chart Example
This example enables interactive exploration of investment returns based on the time of purchase. As the mouse position changes, the chart updates to show the resulting proportional returns for a set of technology stocks had one invested at that time.
Vega JSON Specification <>
{
"$schema": "https://vega.github.io/schema/vega/v5.json",
"description": "An interactive line chart of stock prices, with returns shown relative to a selected date.",
"width": 650,
"height": 300,
"padding": 5,
"autosize": {"type": "fit", "contains": "padding"},
"signals": [
{
"name": "indexDate",
"update": "time('Jan 1 2005')",
"on": [
{
"events": "pointermove",
"update": "invert('x', clamp(x(), 0, width))"
}
]
},
{
"name": "maxDate",
"update": "time('Mar 1 2010')"
}
],
"data": [
{
"name": "stocks",
"url": "data/stocks.csv",
"format": {"type": "csv", "parse": {"price":"number", "date":"date"}}
},
{
"name": "index",
"source": "stocks",
"transform": [
{
"type": "filter",
"expr": "month(datum.date) == month(indexDate) && year(datum.date) == year(indexDate)"
}
]
},
{
"name": "indexed_stocks",
"source": "stocks",
"transform": [
{
"type": "lookup", "from": "index", "key": "symbol",
"fields": ["symbol"], "as": ["index"], "default": {"price": 0}
},
{
"type": "formula",
"as": "indexed_price",
"expr": "datum.index.price > 0 ? (datum.price - datum.index.price)/datum.index.price : 0"
}
]
}
],
"scales": [
{
"name": "x",
"type": "time",
"domain": {"data": "stocks", "field": "date"},
"range": "width"
},
{
"name": "y",
"type": "linear",
"domain": {"data": "indexed_stocks", "field": "indexed_price"},
"nice": true, "zero": true,
"range": "height"
},
{
"name": "color",
"type": "ordinal",
"range": "category",
"domain": {"data": "stocks", "field": "symbol"}
}
],
"axes": [
{"orient": "left", "scale": "y", "grid": true, "format": "%"}
],
"marks": [
{
"type": "group",
"from": {
"facet": {
"name": "series",
"data": "indexed_stocks",
"groupby": "symbol"
}
},
"data": [
{
"name": "label",
"source": "series",
"transform": [
{ "type": "filter", "expr": "datum.date == maxDate" }
]
}
],
"marks": [
{
"type": "line",
"from": {"data": "series"},
"encode": {
"update": {
"x": {"scale": "x", "field": "date"},
"y": {"scale": "y", "field": "indexed_price"},
"stroke": {"scale": "color", "field": "symbol"},
"strokeWidth": {"value": 2}
}
}
},
{
"type": "text",
"from": {"data": "label"},
"encode": {
"update": {
"x": {"scale": "x", "field": "date", "offset": 2},
"y": {"scale": "y", "field": "indexed_price"},
"fill": {"scale": "color", "field": "symbol"},
"text": {"field": "symbol"},
"baseline": {"value": "middle"}
}
}
}
]
},
{
"type": "rule",
"encode": {
"update": {
"x": {"field": {"group": "x"}},
"x2": {"field": {"group": "width"}},
"y": {"value": 0.5, "offset": {"scale": "y", "value": 0, "round": true}},
"stroke": {"value": "black"},
"strokeWidth": {"value": 1}
}
}
},
{
"type": "rule",
"encode": {
"update": {
"x": {"scale": "x", "signal": "indexDate", "offset": 0.5},
"y": {"value": 0},
"y2": {"field": {"group": "height"}},
"stroke": {"value": "firebrick"}
}
}
},
{
"type": "text",
"encode": {
"update": {
"x": {"scale": "x", "signal": "indexDate"},
"y2": {"field": {"group": "height"}, "offset": 15},
"align": {"value": "center"},
"text": {"signal": "timeFormat(indexDate, '%b %Y')"},
"fill": {"value": "firebrick"}
}
}
}
]
}