Skip to content

Pine Graphics Deep Dive

The FATBot system reads indicator data through four Pine graphics MCP tools. These tools extract visual objects that Pine Script indicators draw on the chart — labels, lines, tables, and boxes.

The system never reads indicator plot() values. Everything comes through graphics objects. Indicators just need to be on the chart.


data_get_pine_labels

Reads Pine Script label.new() objects.

Default Return Format

{
  "labels": [
    { "text": "HUNT_LOW", "price": 5870.00 },
    { "text": "Bullish SMT", "price": 5868.50 }
  ]
}

Verbose Return Format (verbose: true)

{
  "labels": [
    {
      "id": "label_42",
      "text": "HUNT_LOW",
      "price": 5870.00,
      "x": 1713100800,
      "yloc": "price",
      "size": "normal",
      "textColor": "#00FF00",
      "color": "#00FF0033"
    }
  ]
}

study_filter Parameter

Limits results to labels from a specific indicator (substring match):

{ "study_filter": "Session Bias" }

data_get_pine_lines

Reads Pine Script line.new() objects. Returns horizontal price levels.

Default Return Format

{
  "horizontal_levels": [
    { "price": 5892.50 },
    { "price": 5870.00 }
  ]
}

Verbose Return Format (verbose: true)

{
  "horizontal_levels": [
    {
      "id": "line_15",
      "y1": 5892.50,
      "y2": 5892.50,
      "x1": 1713090000,
      "x2": 1713110000,
      "style": "solid",
      "width": 2,
      "color": "#FF5252"
    }
  ]
}

Line Styles

Line style field can encode meaning: - "solid" — active/unspent level - "dotted" — spent/mitigated level - "dashed" — pending/conditional level


data_get_pine_tables

Reads Pine Script table.new() objects. Tables are structured grids rendered in a chart corner.

Default Return Format

{
  "tables": [
    {
      "rows": [
        "Daily | Bullish | PDH",
        "Weekly | Bullish | --"
      ]
    }
  ]
}

Parsing

Split rows on | to extract cell values:

const cells = row.split(' | ');
// "Daily | Bullish | PDH" -> ["Daily", "Bullish", "PDH"]

data_get_pine_boxes

Reads Pine Script box.new() objects. Boxes represent rectangular price zones.

Default Return Format

{
  "zones": [
    { "high": 5878.00, "low": 5872.00 }
  ]
}

Verbose Return Format (verbose: true)

{
  "zones": [
    {
      "id": "box_8",
      "high": 5878.00,
      "low": 5872.00,
      "x1": 1713095000,
      "x2": 1713110000,
      "borderColor": "#4CAF50",
      "bgColor": "#4CAF5033"
    }
  ]
}

Color Encoding

Box colors can encode direction: - Green-family (borderColor green channel dominant): Bullish zone - Red-family (borderColor red channel dominant): Bearish zone


Common Parameters

All four tools share:

Parameter Type Default Description
study_filter string none Substring match on indicator name
verbose boolean false Include IDs, colors, coordinates
max_labels number 50 Cap on labels per study (labels only)

Usage Example

Read data from multiple indicators in parallel:

const [biasTable, sessionLabels, obBoxes, smtLabels] = await Promise.all([
  mcp.call('data_get_pine_tables', { study_filter: 'Bias' }),
  mcp.call('data_get_pine_labels', { study_filter: 'Session' }),
  mcp.call('data_get_pine_boxes',  { study_filter: 'OB', verbose: true }),
  mcp.call('data_get_pine_labels', { study_filter: 'SMT' }),
]);

Concurrent calls — total time bounded by slowest call (typically 200–500ms).