{
  "$schema": "./language-map.schema.json",
  "schema_version": "1.0.0",
  "data_release": "2026-11-01",
  "direction": "to_lipi",
  "lipi": {
    "language_version": 2,
    "reference_version": "2.7",
    "compiler_build": "df7b3b14",
    "reference_url": "https://gocharting.com/docs/scripting/reference"
  },
  "languages": {
    "mql4": {
      "name": "MQL4",
      "owner": "MetaQuotes Ltd.",
      "docs_version_verified": "MQL4 Reference, docs.mql4.com (no build number stated)",
      "docs_home": "https://docs.mql4.com/",
      "hosts": [
        "docs.mql4.com"
      ],
      "detect": [
        {
          "pattern": "#property\\s+strict\\b",
          "weight": 3
        },
        {
          "pattern": "\\bextern\\s+(int|double|bool|string|color|datetime)\\b",
          "weight": 3
        },
        {
          "pattern": "\\bint\\s+(start|init|deinit)\\s*\\(\\s*\\)",
          "weight": 3
        },
        {
          "pattern": "\\bIndicatorBuffers\\s*\\(",
          "weight": 3
        },
        {
          "pattern": "\\bOP_(BUY|SELL)(LIMIT|STOP)?\\b",
          "weight": 3
        },
        {
          "pattern": "\\bi(MA|RSI|ATR|CCI|Bands|MACD|Stochastic|Momentum)\\s*\\(\\s*(NULL|_Symbol|Symbol\\(\\))\\s*,[^,()]*,[^,()]*,[^,()]*,[^,()]*,",
          "weight": 2
        },
        {
          "pattern": "\\bSetIndexStyle\\s*\\(",
          "weight": 3
        },
        {
          "pattern": "#property\\s+indicator_(chart|separate)_window\\b",
          "weight": 1
        },
        {
          "pattern": "\\bSetIndexBuffer\\s*\\(",
          "weight": 1
        }
      ]
    },
    "mql5": {
      "name": "MQL5",
      "owner": "MetaQuotes Ltd.",
      "docs_version_verified": "MQL5 Reference, www.mql5.com (no build number stated)",
      "docs_home": "https://www.mql5.com/en/docs",
      "hosts": [
        "www.mql5.com"
      ],
      "detect": [
        {
          "pattern": "\\bCopyBuffer\\s*\\(",
          "weight": 3
        },
        {
          "pattern": "#property\\s+indicator_plots\\b",
          "weight": 3
        },
        {
          "pattern": "\\bINDICATOR_(DATA|CALCULATIONS|COLOR_INDEX)\\b",
          "weight": 3
        },
        {
          "pattern": "\\bPLOT_(DRAW_TYPE|LINE_COLOR|LABEL|EMPTY_VALUE|DRAW_BEGIN)\\b",
          "weight": 2
        },
        {
          "pattern": "#include\\s+<Trade[\\\\/]",
          "weight": 3
        },
        {
          "pattern": "\\bCTrade\\b|\\bPositionGet(Double|Integer|String)\\s*\\(",
          "weight": 3
        },
        {
          "pattern": "\\bOnCalculate\\s*\\(\\s*const\\s+int\\s+rates_total",
          "weight": 1
        },
        {
          "pattern": "#property\\s+indicator_(chart|separate)_window\\b",
          "weight": 1
        },
        {
          "pattern": "\\bSetIndexBuffer\\s*\\(",
          "weight": 1
        }
      ]
    },
    "ninjascript": {
      "name": "NinjaScript",
      "owner": "NinjaTrader, LLC",
      "docs_version_verified": "NinjaTrader 8 Help Guide, release 8.1.8",
      "docs_home": "https://ninjatrader.com/support/helpGuides/nt8/",
      "hosts": [
        "ninjatrader.com",
        "developer.ninjatrader.com",
        "learn.microsoft.com"
      ],
      "detect": [
        {
          "pattern": "\\bnamespace\\s+NinjaTrader\\.NinjaScript\\b",
          "weight": 5
        },
        {
          "pattern": "\\busing\\s+NinjaTrader\\.",
          "weight": 4
        },
        {
          "pattern": "\\boverride\\s+void\\s+OnBarUpdate\\s*\\(",
          "weight": 4
        },
        {
          "pattern": "\\boverride\\s+void\\s+OnStateChange\\s*\\(",
          "weight": 3
        },
        {
          "pattern": "\\bState\\s*==\\s*State\\.(SetDefaults|Configure|DataLoaded|Historical)\\b",
          "weight": 3
        },
        {
          "pattern": "\\bAddPlot\\s*\\(",
          "weight": 2
        },
        {
          "pattern": "\\b(EnterLong|EnterShort|ExitLong|ExitShort)\\s*\\(",
          "weight": 2
        },
        {
          "pattern": "\\bCurrentBar\\b",
          "weight": 1
        }
      ]
    },
    "pine": {
      "name": "Pine Script",
      "owner": "TradingView, Inc.",
      "docs_version_verified": "Pine Script v6 reference and user manual",
      "docs_home": "https://www.tradingview.com/pine-script-reference/v6/",
      "hosts": [
        "www.tradingview.com"
      ],
      "detect": [
        {
          "pattern": "^[ \\t]*//[ \\t]*@version[ \\t]*=[ \\t]*\\d+",
          "weight": 5,
          "raw": true
        },
        {
          "pattern": "^[ \\t]*(indicator|strategy|study|library)\\s*\\(",
          "weight": 3
        },
        {
          "pattern": "\\brequest\\.(security|security_lower_tf|financial)\\s*\\(",
          "weight": 3
        },
        {
          "pattern": "\\bta\\.\\w+\\s*\\(",
          "weight": 2
        },
        {
          "pattern": "\\binput\\.(int|float|bool|string|source|timeframe|color|session)\\s*\\(",
          "weight": 2
        },
        {
          "pattern": "^[ \\t]*var\\s+\\w",
          "weight": 1
        },
        {
          "pattern": ":=",
          "weight": 1
        }
      ]
    },
    "thinkscript": {
      "name": "thinkScript",
      "owner": "Charles Schwab & Co., Inc.",
      "docs_version_verified": "thinkScript Reference, thinkorswim Learning Center 3.11.0",
      "docs_home": "https://toslc.thinkorswim.com/center/reference/thinkScript",
      "hosts": [
        "toslc.thinkorswim.com"
      ],
      "detect": [
        {
          "pattern": "^[ \\t]*def\\s+\\w+\\s*=",
          "weight": 4
        },
        {
          "pattern": "^[ \\t]*plot\\s+\\w+\\s*=",
          "weight": 4
        },
        {
          "pattern": "\\bdeclare\\s+(lower|upper|hide_on_intraday|hide_on_daily)\\b",
          "weight": 4
        },
        {
          "pattern": "^[ \\t]*rec\\s+\\w+\\s*=",
          "weight": 3
        },
        {
          "pattern": "\\b(AddLabel|AssignValueColor|AddCloud|AddOrder)\\s*\\(",
          "weight": 3
        },
        {
          "pattern": "\\bCrossingDirection\\.|\\bCompoundValue\\s*\\(",
          "weight": 3
        },
        {
          "pattern": "\\bGetColor\\s*\\(",
          "weight": 2
        },
        {
          "pattern": "^[ \\t]*input\\s+\\w+\\s*=",
          "weight": 1
        }
      ]
    }
  },
  "categories": [
    {
      "id": "execution-and-types",
      "title": "Execution and types",
      "intro": "How a script runs and the kinds of values it works with."
    },
    {
      "id": "history-and-state",
      "title": "History and state",
      "intro": "Reading earlier bars and keeping values from one bar to the next."
    },
    {
      "id": "control-flow-and-functions",
      "title": "Control flow, functions and collections",
      "intro": "Branches, loops, your own functions and types, operators and arrays."
    },
    {
      "id": "inputs",
      "title": "Inputs",
      "intro": "Settings the chart user can change."
    },
    {
      "id": "plots-and-drawings",
      "title": "Plots and drawings",
      "intro": "Putting values, shapes, colours, objects and tables on the chart."
    },
    {
      "id": "strategies-and-alerts",
      "title": "Strategies and alerts",
      "intro": "Simulated orders, positions and results, and notifications."
    },
    {
      "id": "market-data-and-time",
      "title": "Market data and time",
      "intro": "Prices, volume, orderflow, the instrument, the timeframe, sessions and time."
    },
    {
      "id": "indicators",
      "title": "Technical indicators",
      "intro": "Built-in indicator and series functions."
    },
    {
      "id": "math-and-strings",
      "title": "Math and strings",
      "intro": "Numeric and text functions."
    },
    {
      "id": "arrays",
      "title": "Arrays",
      "intro": "Creating and working with arrays."
    }
  ],
  "concepts": [
    {
      "id": "exec.bar-by-bar",
      "category": "execution-and-types",
      "title": "Bar-by-bar evaluation",
      "definition": "The script body runs once for every bar, oldest first, and then again as the live bar updates.",
      "lipi": {
        "symbols": [],
        "facts": [
          "F-018",
          "F-236",
          "F-237",
          "F-242"
        ],
        "note": "A closed bar runs once. A forming live bar reruns on every tick only if calc_on_every_tick is true; those reruns do not advance history.",
        "example": "//@lipi=2\nindicator(\"Bars seen so far\")\nstatic int seen = 0\nseen += 1\nplot(seen, title=\"Bars\")"
      }
    },
    {
      "id": "exec.declare-indicator",
      "category": "execution-and-types",
      "title": "Declare an indicator",
      "definition": "A statement that names the script as an indicator and sets its display options.",
      "lipi": {
        "symbols": [
          "indicator"
        ],
        "facts": [
          "F-006",
          "F-007",
          "F-009",
          "F-010",
          "F-011",
          "F-012",
          "F-013",
          "F-014"
        ],
        "note": "`title` is the only required argument. The call must be at top level. Title and shorttitle max 128 characters, checked on Add to chart."
      }
    },
    {
      "id": "exec.declare-strategy",
      "category": "execution-and-types",
      "title": "Declare a strategy",
      "definition": "A statement that names the script as a strategy and sets its simulation options.",
      "lipi": {
        "symbols": [
          "strategy"
        ],
        "facts": [
          "F-006",
          "F-007",
          "F-009",
          "F-015",
          "F-016",
          "F-017",
          "F-192",
          "F-193",
          "F-269"
        ],
        "note": "No slippage, currency or margin arguments. default_qty_type is an unchecked string; only strategy.fixed exists as a constant, \"cash\" and \"percent_of_equity\" are strings."
      }
    },
    {
      "id": "exec.overlay",
      "category": "execution-and-types",
      "title": "Price pane or own pane",
      "definition": "Whether the script draws on the price chart or in a separate pane below it.",
      "lipi": {
        "symbols": [
          "indicator"
        ],
        "facts": [
          "F-011",
          "F-147",
          "F-304"
        ],
        "note": "Default is overlay=false (own pane). `force_overlay=true` on a plot, label or box puts it on the price pane; line.new spells it `forceOverlay`."
      }
    },
    {
      "id": "exec.every-tick",
      "category": "execution-and-types",
      "title": "Recalculate on every update",
      "definition": "Whether the live bar is recalculated on each price update or only when the bar closes.",
      "lipi": {
        "symbols": [
          "indicator",
          "barstate.isconfirmed"
        ],
        "facts": [
          "F-018",
          "F-195",
          "F-206",
          "F-242",
          "F-314"
        ],
        "note": "Indicator default is calc_on_every_tick=true, strategy default false. An indicator with false is skipped on every unconfirmed bar."
      }
    },
    {
      "id": "exec.version-header",
      "category": "execution-and-types",
      "title": "Language version header",
      "definition": "A line at the top of the file that selects which version of the language compiles the script.",
      "lipi": {
        "symbols": [
          "@lipi="
        ],
        "facts": [
          "F-001",
          "F-002",
          "F-003",
          "F-004",
          "F-005",
          "F-302"
        ],
        "note": "`//@lipi=2` is required on the v2 stack. The first match anywhere in the file counts; case and spaces around `=` are free."
      }
    },
    {
      "id": "types.basic",
      "category": "execution-and-types",
      "title": "Basic value types",
      "definition": "Whole numbers, decimal numbers, true/false values, text and colours.",
      "lipi": {
        "symbols": [
          "int",
          "float",
          "bool",
          "string",
          "color"
        ],
        "facts": [
          "F-060",
          "F-070",
          "F-071",
          "F-072",
          "F-073",
          "F-074",
          "F-075",
          "F-076"
        ],
        "note": "Colour literals are #RRGGBB or #RRGGBBAA, alpha last. No hex numbers or digit separators; string escapes such as \\n are not translated."
      }
    },
    {
      "id": "types.missing-value",
      "category": "execution-and-types",
      "title": "Missing value",
      "definition": "A value that stands for \"no value on this bar\", and the functions that test for it or replace it.",
      "lipi": {
        "symbols": [
          "na",
          "nz",
          "fixnan"
        ],
        "facts": [
          "F-045",
          "F-069",
          "F-233",
          "F-234",
          "F-235"
        ],
        "note": "Arithmetic with na gives na, as does division or modulo by zero. `and`/`or` do not short-circuit, and `na and false` is na."
      }
    },
    {
      "id": "types.qualifiers",
      "category": "execution-and-types",
      "title": "Value qualifiers",
      "definition": "Markers that say whether a value is fixed at compile time, fixed after the first bar, or may change on every bar.",
      "lipi": {
        "symbols": [
          "const",
          "simple",
          "series"
        ],
        "facts": [
          "F-062",
          "F-063",
          "F-064",
          "F-065",
          "F-240",
          "F-241",
          "F-308"
        ],
        "note": "const fits any parameter, series only a series one. Titles must be const, linewidth input. Reassigning inside if, for or switch makes a variable series."
      }
    },
    {
      "id": "types.conversion",
      "category": "execution-and-types",
      "title": "Type conversion",
      "definition": "Turning a value of one type into another, such as a decimal into a whole number or a number into text.",
      "lipi": {
        "symbols": [
          "int",
          "float",
          "bool",
          "str.tostring",
          "str.tonumber"
        ],
        "facts": [
          "F-042",
          "F-066",
          "F-075",
          "F-076",
          "F-250"
        ],
        "note": "int() truncates toward zero; casts take numbers only. `+` does not join a string and a number: use str.tostring."
      }
    },
    {
      "id": "decl.variable",
      "category": "execution-and-types",
      "title": "Declare and assign a variable",
      "definition": "Giving a name to a value, and giving the name a new value later.",
      "lipi": {
        "symbols": [],
        "facts": [
          "F-037",
          "F-038",
          "F-039",
          "F-040",
          "F-041",
          "F-043",
          "F-045",
          "F-054",
          "F-055",
          "F-056",
          "F-057",
          "F-059",
          "F-229",
          "F-231"
        ],
        "note": "`=` declares, `:=` assigns. A variable keeps the type of its first value (x = 0 is an int); na cannot start an untyped variable.",
        "example": "//@lipi=2\nindicator(\"Variables\")\nspread = high - low\nsmooth = spread\nsmooth := talib.sma(spread, 5)\nplot(smooth, title=\"Average spread\")"
      }
    },
    {
      "id": "decl.enum",
      "category": "execution-and-types",
      "title": "Your own enumeration",
      "definition": "A named set of fixed options declared by the script.",
      "lipi": {
        "symbols": [
          "enum"
        ],
        "facts": [
          "F-021",
          "F-034",
          "F-134",
          "F-135",
          "F-136",
          "F-137"
        ],
        "note": "One member per line; no one-line form. Read a member as Name.A. An enum cannot be passed to str.tostring.",
        "example": "//@lipi=2\nindicator(\"Enum\")\nenum Mode {\n    Fast\n    Slow\n}\nmode = input.enum(Mode.Fast, \"Mode\")\nplot(mode == Mode.Fast ? 1 : 2)"
      }
    },
    {
      "id": "decl.user-type",
      "category": "execution-and-types",
      "title": "Your own object type",
      "definition": "A named group of fields declared by the script, with objects created from it.",
      "lipi": {
        "symbols": [
          "type"
        ],
        "facts": [
          "F-021",
          "F-125",
          "F-126",
          "F-127",
          "F-128",
          "F-129",
          "F-130",
          "F-132",
          "F-133",
          "F-324"
        ],
        "note": "A field default is a literal, na or a built-in variable. Assigning an object (q = p) shares it; Pt.copy(p) makes a shallow copy.",
        "example": "//@lipi=2\nindicator(\"Type\")\ntype Span {\n    float top\n    float bottom\n}\ns = Span.new(high, low)\nplot(s.top - s.bottom, title=\"Span\")"
      }
    },
    {
      "id": "decl.tuple",
      "category": "execution-and-types",
      "title": "Several values at once",
      "definition": "Returning or receiving more than one value from a single call.",
      "lipi": {
        "symbols": [],
        "facts": [
          "F-051",
          "F-052",
          "F-053",
          "F-113",
          "F-251"
        ],
        "note": "Counts must match: talib.macd and talib.bb return three values, talib.supertrend two. A tuple cannot be stored in one variable.",
        "example": "//@lipi=2\nindicator(\"Tuple\")\n[macdLine, signalLine, hist] = talib.macd(close, 12, 26, 9)\nplot(hist, title=\"Histogram\")"
      }
    },
    {
      "id": "history.previous-value",
      "category": "history-and-state",
      "title": "Value on an earlier bar",
      "definition": "Reading what a series was a given number of bars ago.",
      "lipi": {
        "symbols": [],
        "facts": [
          "F-085",
          "F-086",
          "F-087",
          "F-088",
          "F-238",
          "F-239"
        ],
        "note": "x[n] needs 0 <= n <= 500. A negative literal is a compile error; a computed bad index stops the script. Arrays use array.get.",
        "example": "//@lipi=2\nindicator(\"Earlier bars\")\nchange = close - close[1]\nplot(change, title=\"Change on the bar\")\nplot(math.max(high, high[1], high[2]), title=\"3-bar high\", color=color.orange)"
      }
    },
    {
      "id": "history.bar-index",
      "category": "history-and-state",
      "title": "Bar number",
      "definition": "The position of the current bar, counted from the first bar the script sees.",
      "lipi": {
        "symbols": [
          "bar_index"
        ],
        "facts": [
          "F-200",
          "F-203"
        ],
        "note": "An int series, 0 on the first bar the script receives."
      }
    },
    {
      "id": "history.last-bar",
      "category": "history-and-state",
      "title": "Last bar",
      "definition": "Identifying the most recent bar of the chart.",
      "lipi": {
        "symbols": [
          "last_bar_index",
          "barstate.islast"
        ],
        "facts": [
          "F-200",
          "F-206",
          "F-242",
          "F-321"
        ],
        "note": "`barstate.islast` is true on the last loaded bar and on every realtime run; `last_bar_index` is that bar's index."
      }
    },
    {
      "id": "history.lookback-limit",
      "category": "history-and-state",
      "title": "How far back a script can read",
      "definition": "The largest number of bars a script may reference in the past.",
      "lipi": {
        "symbols": [],
        "facts": [
          "F-087",
          "F-218",
          "F-221",
          "F-239"
        ],
        "note": "Reach is 0 to 500 bars. A longer offset or length compiles, then stops the script; ema-family lengths above 500 fail on Add to chart.",
        "example": "//@lipi=2\nindicator(\"Furthest look back\", overlay=true)\n// 500 is the largest offset a script may read\nplot(bar_index >= 500 ? close[500] : na, title=\"Close 500 bars ago\")"
      }
    },
    {
      "id": "history.call-every-bar",
      "category": "history-and-state",
      "title": "History functions on every bar",
      "definition": "Functions that keep their own history give correct results only when called on every bar, not inside a branch that skips bars.",
      "lipi": {
        "symbols": [
          "ta.sma",
          "ta.ema"
        ],
        "facts": [
          "F-236",
          "F-238",
          "F-119"
        ],
        "note": "A talib call in a skipped if branch, an unchosen ?: side or a sometimes-called function is computed over its own calls, not bars.",
        "example": "//@lipi=2\nindicator(\"Call on every bar\", overlay=true)\nfast = talib.sma(close, 10)\nslow = talib.ema(close, 20)\nuseFast = bar_index % 2 == 0\nplot(useFast ? fast : slow, title=\"Alternating average\")"
      }
    },
    {
      "id": "state.persistent",
      "category": "history-and-state",
      "title": "Keep a value across bars",
      "definition": "A variable that is set once and keeps its value from bar to bar until the script changes it.",
      "lipi": {
        "symbols": [
          "static"
        ],
        "facts": [
          "F-046",
          "F-047",
          "F-049",
          "F-237",
          "F-322"
        ],
        "note": "Committed when the bar closes. Each tick of a forming bar restarts from the saved value, so a push per tick adds once per bar.",
        "example": "//@lipi=2\nindicator(\"Highest high so far\", overlay=true)\nstatic float top = na\ntop := na(top) ? high : math.max(top, high)\nplot(top, title=\"Top\")"
      }
    },
    {
      "id": "state.intrabar",
      "category": "history-and-state",
      "title": "Keep a value across live updates",
      "definition": "A variable that also keeps its value between updates of the same live bar.",
      "lipi": {
        "symbols": [
          "intra"
        ],
        "facts": [
          "F-048",
          "F-049",
          "F-284",
          "F-322"
        ],
        "note": "`intra` is cleared when the bar closes. On history, with one run per bar, it behaves like an ordinary variable.",
        "example": "//@lipi=2\nindicator(\"Updates of the live bar\")\nintra int updates = 0\nupdates += 1\nplot(updates, title=\"Updates\")"
      }
    },
    {
      "id": "state.bar-flags",
      "category": "history-and-state",
      "title": "Bar state flags",
      "definition": "True/false values that tell the script whether the bar is the first, historical, live, new or closed.",
      "lipi": {
        "symbols": [
          "barstate.isfirst",
          "barstate.ishistory",
          "barstate.isrealtime",
          "barstate.isnew",
          "barstate.isconfirmed",
          "barstate.islastconfirmedhistory"
        ],
        "facts": [
          "F-206",
          "F-242",
          "F-314",
          "F-321"
        ],
        "note": "`barstate.isnew` is true on every history bar. `isconfirmed` is false on the last history bar while the market is open."
      }
    },
    {
      "id": "flow.if",
      "category": "control-flow-and-functions",
      "title": "Conditional block",
      "definition": "Running a block only when a condition holds, with optional alternative branches.",
      "lipi": {
        "symbols": [
          "if",
          "else"
        ],
        "facts": [
          "F-027",
          "F-028",
          "F-035",
          "F-068",
          "F-089",
          "F-234",
          "F-323"
        ],
        "note": "`if` has no value (`x = if ...` is a syntax error). Nonzero numbers are true, na is false; a string is rejected."
      }
    },
    {
      "id": "flow.switch",
      "category": "control-flow-and-functions",
      "title": "Choose by value",
      "definition": "Running one of several blocks depending on the value of an expression.",
      "lipi": {
        "symbols": [
          "switch",
          "case",
          "default"
        ],
        "facts": [
          "F-090",
          "F-091",
          "F-092",
          "F-241",
          "F-315"
        ],
        "note": "No fall-through; one value per case. A switch inside a function body fails on Add to chart (Not Implemented): use if/else there.",
        "example": "//@lipi=2\nindicator(\"Switch\")\nfloat v = 0.0\nswitch bar_index % 2 {\n    case 0: v := close\n    default: v := open\n}\nplot(v, title=\"Alternating\")"
      }
    },
    {
      "id": "flow.ternary",
      "category": "control-flow-and-functions",
      "title": "Inline condition",
      "definition": "An expression that gives one of two values depending on a condition.",
      "lipi": {
        "symbols": [],
        "facts": [
          "F-077",
          "F-083",
          "F-234",
          "F-241"
        ],
        "note": "Only the chosen branch runs; an na condition takes the else branch. The branches need compatible types.",
        "example": "//@lipi=2\nindicator(\"Up or down\", overlay=true)\nshade = close >= open ? color.green : color.red\nplot(close, title=\"Close\", color=shade, linewidth=2)"
      }
    },
    {
      "id": "flow.for-count",
      "category": "control-flow-and-functions",
      "title": "Counted loop",
      "definition": "Repeating a block with a counter that runs from a start value to an end value.",
      "lipi": {
        "symbols": [
          "for to",
          "step"
        ],
        "facts": [
          "F-094",
          "F-095",
          "F-096",
          "F-097",
          "F-102",
          "F-103",
          "F-232",
          "F-247"
        ],
        "note": "The end is inclusive and a start above the end counts down, but equal bounds run zero times. `by` is not a keyword; use `step`.",
        "example": "//@lipi=2\nindicator(\"Sum of five closes\")\ntotal = 0.0\nfor i = 0 to 4 {\n    total += close[i]\n}\nplot(total, title=\"Sum\")"
      }
    },
    {
      "id": "flow.for-each",
      "category": "control-flow-and-functions",
      "title": "Loop over a collection",
      "definition": "Repeating a block once for each element of a collection.",
      "lipi": {
        "symbols": [
          "for in"
        ],
        "facts": [
          "F-098",
          "F-099",
          "F-144"
        ],
        "note": "Iterates only an array held in a variable: no expression after `in`, no index form. Assigning the loop variable does not change the array.",
        "example": "//@lipi=2\nindicator(\"For each\")\na = array.from(1.0, 2.0, 3.0)\ntotal = 0.0\nfor x in a {\n    total += x\n}\nplot(total, title=\"Total\")"
      }
    },
    {
      "id": "flow.while",
      "category": "control-flow-and-functions",
      "title": "Conditional loop",
      "definition": "Repeating a block while a condition holds.",
      "lipi": {
        "symbols": [
          "while"
        ],
        "facts": [
          "F-093",
          "F-068",
          "F-225"
        ],
        "note": "No iteration limit, but a history run is cancelled after 45 seconds.",
        "example": "//@lipi=2\nindicator(\"While\")\nx = close\nwhile x > 100 {\n    x := x / 2\n}\nplot(x, title=\"Halved\")"
      }
    },
    {
      "id": "flow.break-continue",
      "category": "control-flow-and-functions",
      "title": "Leave or skip a loop pass",
      "definition": "Ending a loop early, or skipping to its next pass.",
      "lipi": {
        "symbols": [
          "break",
          "continue"
        ],
        "facts": [
          "F-100"
        ]
      }
    },
    {
      "id": "func.user-function",
      "category": "control-flow-and-functions",
      "title": "Your own function",
      "definition": "A named, reusable calculation declared by the script, with parameters and a result.",
      "lipi": {
        "symbols": [
          "func",
          "return"
        ],
        "facts": [
          "F-105",
          "F-106",
          "F-107",
          "F-108",
          "F-110",
          "F-111",
          "F-112",
          "F-113",
          "F-114",
          "F-115",
          "F-116",
          "F-117",
          "F-118",
          "F-119",
          "F-120",
          "F-121",
          "F-310",
          "F-315",
          "F-316"
        ],
        "note": "Declare before use; no recursion; every parameter is typed. A function cannot rebind a global, and plot-family calls are not allowed inside one.",
        "example": "//@lipi=2\nindicator(\"Typical price\", overlay=true)\nfunc typical(float h, float l, float c) => (h + l + c) / 3\nplot(typical(high, low, close), title=\"Typical\")"
      }
    },
    {
      "id": "func.method",
      "category": "control-flow-and-functions",
      "title": "Method on a type",
      "definition": "A function attached to a type and called on an object of that type.",
      "lipi": {
        "symbols": [
          "def"
        ],
        "facts": [
          "F-122",
          "F-310"
        ],
        "note": "`def` needs at least one parameter, the receiver. Call it as `value.name(...)` or `name(value, ...)`; a `func` cannot use dot syntax.",
        "example": "//@lipi=2\nindicator(\"Method\")\ndef doubled(float x) => x * 2\nplot(close.doubled(), title=\"Twice the close\")"
      }
    },
    {
      "id": "op.arithmetic",
      "category": "control-flow-and-functions",
      "title": "Arithmetic operators",
      "definition": "Adding, subtracting, multiplying, dividing and taking remainders.",
      "lipi": {
        "symbols": [
          "+",
          "-",
          "*",
          "/",
          "%"
        ],
        "facts": [
          "F-066",
          "F-067",
          "F-077",
          "F-081",
          "F-084",
          "F-235"
        ],
        "note": "`/` always returns float, even for two ints; division and modulo by zero give na. There is no `^`: use math.pow."
      }
    },
    {
      "id": "op.comparison",
      "category": "control-flow-and-functions",
      "title": "Comparison operators",
      "definition": "Testing whether values are equal, different, greater or smaller.",
      "lipi": {
        "symbols": [
          "==",
          "!=",
          ">",
          "<",
          ">=",
          "<="
        ],
        "facts": [
          "F-069",
          "F-077",
          "F-079",
          "F-080"
        ],
        "note": "Comparisons do not chain: write `a < b and b < c`. Test na with na(x); `x == na` compiles with a warning."
      }
    },
    {
      "id": "op.logical",
      "category": "control-flow-and-functions",
      "title": "Logical operators",
      "definition": "Combining or negating true/false values.",
      "lipi": {
        "symbols": [
          "and",
          "or",
          "not"
        ],
        "facts": [
          "F-077",
          "F-078",
          "F-082",
          "F-233"
        ],
        "note": "No short-circuit: both operands are always evaluated. `not` binds tighter than comparison, so `not 1 > 2` is a type error."
      }
    },
    {
      "id": "op.compound-assign",
      "category": "control-flow-and-functions",
      "title": "Update in place",
      "definition": "Changing a variable by an amount in one step, such as adding to a running total.",
      "lipi": {
        "symbols": [],
        "facts": [
          "F-039",
          "F-040"
        ],
        "note": "`+=` also joins strings. `/=` on an int variable is rejected because `/` returns float.",
        "example": "//@lipi=2\nindicator(\"Running volume\")\nstatic float total = 0.0\ntotal += volume\nplot(total, title=\"Volume so far\")"
      }
    },
    {
      "id": "coll.map",
      "category": "control-flow-and-functions",
      "title": "Key-value collection",
      "definition": "A collection that stores values under keys.",
      "lipi": {
        "absent_reason": "Lipi has no key-value collection type; use two arrays kept in step, or a user type.",
        "facts": [
          "F-061"
        ]
      }
    },
    {
      "id": "coll.matrix",
      "category": "control-flow-and-functions",
      "title": "Two-dimensional collection",
      "definition": "A collection with rows and columns.",
      "lipi": {
        "absent_reason": "Lipi has no matrix type; use an array with computed indexes.",
        "facts": [
          "F-061"
        ]
      }
    },
    {
      "id": "mod.import",
      "category": "control-flow-and-functions",
      "title": "Reuse code from another file",
      "definition": "Bringing in functions or types published in a separate file or library.",
      "lipi": {
        "absent_reason": "A Lipi script is one file; copy the functions you need into it.",
        "facts": [
          "F-007",
          "F-008",
          "F-302"
        ]
      }
    },
    {
      "id": "err.runtime-error",
      "category": "control-flow-and-functions",
      "title": "Stop with an error",
      "definition": "Ending the script on purpose with a message when a condition is not met.",
      "lipi": {
        "absent_reason": "Lipi has no function that raises a runtime error; guard the calculation and skip it instead.",
        "facts": []
      }
    },
    {
      "id": "input.int",
      "category": "inputs",
      "title": "Whole-number input",
      "definition": "A setting the chart user fills with a whole number, with optional bounds and step.",
      "lipi": {
        "symbols": [
          "input.int"
        ],
        "facts": [
          "F-162",
          "F-163",
          "F-165",
          "F-166",
          "F-167",
          "F-168",
          "F-257",
          "F-258",
          "F-259"
        ],
        "note": "`defval` must be a const int, not na and not a series. minval and maxval are not checked against it; `step=0` is accepted."
      }
    },
    {
      "id": "input.float",
      "category": "inputs",
      "title": "Decimal input",
      "definition": "A setting the chart user fills with a decimal number.",
      "lipi": {
        "symbols": [
          "input.float"
        ],
        "facts": [
          "F-162",
          "F-163",
          "F-165",
          "F-166",
          "F-167",
          "F-168",
          "F-257",
          "F-258",
          "F-259"
        ],
        "note": "An int default is accepted. `defval` must be const and not na; bounds are not checked against it."
      }
    },
    {
      "id": "input.bool",
      "category": "inputs",
      "title": "On/off input",
      "definition": "A setting the chart user switches on or off.",
      "lipi": {
        "symbols": [
          "input.bool"
        ],
        "facts": [
          "F-162",
          "F-163",
          "F-165",
          "F-257"
        ],
        "note": "display defaults to display.none for input.bool, input.color, input.time and input.text_area; the other inputs default to display.all."
      }
    },
    {
      "id": "input.string",
      "category": "inputs",
      "title": "Text or choice input",
      "definition": "A setting the chart user fills with text, or picks from a list of options.",
      "lipi": {
        "symbols": [
          "input.string"
        ],
        "facts": [
          "F-162",
          "F-163",
          "F-165",
          "F-166",
          "F-257"
        ],
        "note": "A string default must be one of `options` when options are given."
      }
    },
    {
      "id": "input.color",
      "category": "inputs",
      "title": "Colour input",
      "definition": "A setting the chart user picks a colour for.",
      "lipi": {
        "symbols": [
          "input.color"
        ],
        "facts": [
          "F-162",
          "F-163",
          "F-165",
          "F-257",
          "F-258"
        ],
        "note": "The default is a const colour. Layout arguments (group, inline, tooltip) must be const."
      }
    },
    {
      "id": "input.source",
      "category": "inputs",
      "title": "Price source input",
      "definition": "A setting that picks which price series the script reads.",
      "lipi": {
        "symbols": [
          "input.source"
        ],
        "facts": [
          "F-162",
          "F-165",
          "F-257",
          "F-260"
        ],
        "note": "Only open, high, low, close, hl2, hlc3, ohlc4 and hlcc4 are accepted as the default; volume is refused."
      }
    },
    {
      "id": "input.timeframe",
      "category": "inputs",
      "title": "Timeframe input",
      "definition": "A setting that picks a chart timeframe.",
      "lipi": {
        "symbols": [
          "input.timeframe"
        ],
        "facts": [
          "F-162",
          "F-163",
          "F-212",
          "F-257"
        ],
        "note": "Choosing a timeframe does not fetch its data: there is no request namespace. Use it with time(timeframe)."
      }
    },
    {
      "id": "input.session",
      "category": "inputs",
      "title": "Session input",
      "definition": "A setting that picks a time-of-day range.",
      "lipi": {
        "symbols": [
          "input.session"
        ],
        "facts": [
          "F-162",
          "F-163",
          "F-257",
          "F-288",
          "F-318"
        ],
        "note": "Session strings are HHMM-HHMM, ranges comma-separated; an end before the start wraps midnight; day digits follow a colon, 1 = Sunday."
      }
    },
    {
      "id": "input.time",
      "category": "inputs",
      "title": "Date and time input",
      "definition": "A setting that picks a point in time.",
      "lipi": {
        "symbols": [
          "input.time"
        ],
        "facts": [
          "F-162",
          "F-163",
          "F-171",
          "F-257",
          "F-262"
        ],
        "note": "The default must be a millisecond integer literal: timestamp(\"2024-01-01\") passes the editor check but fails on Add to chart."
      }
    },
    {
      "id": "input.price",
      "category": "inputs",
      "title": "Price level input",
      "definition": "A setting that picks a price level.",
      "lipi": {
        "symbols": [
          "input.price"
        ],
        "facts": [
          "F-162",
          "F-163",
          "F-165",
          "F-177",
          "F-257"
        ],
        "note": "It returns an input float, so it can drive hline(price)."
      }
    },
    {
      "id": "input.enum",
      "category": "inputs",
      "title": "Enumeration input",
      "definition": "A setting whose options come from the script's own enumeration.",
      "lipi": {
        "symbols": [
          "input.enum"
        ],
        "facts": [
          "F-134",
          "F-136",
          "F-163",
          "F-257"
        ],
        "note": "The default must be a const member written Name.Member."
      }
    },
    {
      "id": "input.layout",
      "category": "inputs",
      "title": "Group and lay out inputs",
      "definition": "Grouping settings under headings and placing several on one line.",
      "lipi": {
        "symbols": [
          "input.int"
        ],
        "facts": [
          "F-163",
          "F-167",
          "F-168",
          "F-258"
        ],
        "note": "`group`, `inline` and `tooltip` must be const strings. Two inputs may share a title."
      }
    },
    {
      "id": "plot.line",
      "category": "plots-and-drawings",
      "title": "Plot a series",
      "definition": "Drawing one value per bar as a line or other style.",
      "lipi": {
        "symbols": [
          "plot"
        ],
        "facts": [
          "F-172",
          "F-173",
          "F-174",
          "F-175",
          "F-182",
          "F-187",
          "F-176",
          "F-257",
          "F-270",
          "F-304"
        ],
        "note": "`plot` must be called at top level, never in a function, if or loop; make it conditional through its arguments. `title` must be const."
      }
    },
    {
      "id": "plot.style",
      "category": "plots-and-drawings",
      "title": "Plot styles",
      "definition": "The ways a plotted series can be drawn: line, histogram, area, circles, steps and others.",
      "lipi": {
        "symbols": [
          "plotStyle"
        ],
        "facts": [
          "F-174"
        ],
        "note": "Members: line, linebr, area, areabr, smoothedArea, stepLine, stepLinebr, stepArea, stepAreabr, bar, histogram, scatter, triangular, cross. No columns member."
      }
    },
    {
      "id": "plot.shape",
      "category": "plots-and-drawings",
      "title": "Mark bars with a shape",
      "definition": "Drawing a shape above, below or on bars where a condition holds.",
      "lipi": {
        "symbols": [
          "plotshape"
        ],
        "facts": [
          "F-124",
          "F-172",
          "F-173",
          "F-183",
          "F-255",
          "F-311"
        ],
        "note": "The argument is named `shape`, not `style`. A size string that is not a size name stops the compiler with `internal validator error`."
      }
    },
    {
      "id": "plot.char",
      "category": "plots-and-drawings",
      "title": "Mark bars with a character",
      "definition": "Drawing a text character above, below or on bars where a condition holds.",
      "lipi": {
        "symbols": [
          "plotchar"
        ],
        "facts": [
          "F-124",
          "F-172",
          "F-173",
          "F-184",
          "F-255",
          "F-270",
          "F-311"
        ],
        "note": "Only the first character of `char` is used."
      }
    },
    {
      "id": "plot.arrow",
      "category": "plots-and-drawings",
      "title": "Up and down arrows",
      "definition": "Drawing arrows whose direction follows the sign of a value.",
      "lipi": {
        "symbols": [
          "plotarrow"
        ],
        "facts": [
          "F-172",
          "F-173",
          "F-184"
        ],
        "note": "Arguments are colorup, colordown, minheight and maxheight; call it at top level only."
      }
    },
    {
      "id": "plot.candles",
      "category": "plots-and-drawings",
      "title": "Draw your own candles or bars",
      "definition": "Drawing open-high-low-close candles or bars from values the script computes.",
      "lipi": {
        "symbols": [
          "plotcandle",
          "plotbar"
        ],
        "facts": [
          "F-172",
          "F-173",
          "F-184",
          "F-301"
        ],
        "note": "plotcandle takes open, high, low, close and a color, plus wickcolor and bordercolor; plotbar takes the same without them."
      }
    },
    {
      "id": "plot.hline",
      "category": "plots-and-drawings",
      "title": "Horizontal level",
      "definition": "A fixed horizontal line at a price or value.",
      "lipi": {
        "symbols": [
          "hline"
        ],
        "facts": [
          "F-172",
          "F-173",
          "F-176",
          "F-177",
          "F-257"
        ],
        "note": "`price` must be an input float, not a series. Style is hlineStyle.solid, dashed or dotted; there is no force_overlay."
      }
    },
    {
      "id": "plot.fill",
      "category": "plots-and-drawings",
      "title": "Fill between two plots",
      "definition": "Shading the area between two plots or two levels.",
      "lipi": {
        "symbols": [
          "fill"
        ],
        "facts": [
          "F-172",
          "F-175",
          "F-178",
          "F-179",
          "F-180",
          "F-263"
        ],
        "note": "Fill two plots or two hlines, never one of each. The third and fourth arguments swap between the plot form and the hline form."
      }
    },
    {
      "id": "plot.bgcolor",
      "category": "plots-and-drawings",
      "title": "Colour the background",
      "definition": "Colouring the chart background behind chosen bars.",
      "lipi": {
        "symbols": [
          "bgcolor"
        ],
        "facts": [
          "F-172",
          "F-180",
          "F-182",
          "F-185",
          "F-257"
        ],
        "note": "An na colour means no background colour. `display` accepts only display.none and display.all when added to the chart."
      }
    },
    {
      "id": "plot.barcolor",
      "category": "plots-and-drawings",
      "title": "Colour the bars",
      "definition": "Colouring the price bars themselves.",
      "lipi": {
        "symbols": [
          "barcolor"
        ],
        "facts": [
          "F-172",
          "F-180",
          "F-182",
          "F-185",
          "F-257"
        ],
        "note": "No force_overlay argument. An na colour means no bar colour; display accepts only none or all."
      }
    },
    {
      "id": "plot.display",
      "category": "plots-and-drawings",
      "title": "Where a plot is shown",
      "definition": "Choosing whether a plot appears on the chart, the price scale, the data window or nowhere.",
      "lipi": {
        "symbols": [
          "display"
        ],
        "facts": [
          "F-168",
          "F-169",
          "F-170",
          "F-180",
          "F-181",
          "F-257"
        ],
        "note": "display.* are bit flags (none 0, pane 1, data_window 2, price_scale 4, status_line 8, all 15) combined with +; the terminal decides what each shows."
      }
    },
    {
      "id": "color.transparency",
      "category": "plots-and-drawings",
      "title": "Colour with transparency",
      "definition": "Making a colour partly see-through.",
      "lipi": {
        "symbols": [
          "color.new"
        ],
        "facts": [
          "F-156",
          "F-157",
          "F-264"
        ],
        "note": "Alpha is opacity from 0 to 1 (1 solid, 0 invisible), clamped. A literal 50 warns. There is no transp argument.",
        "example": "//@lipi=2\nindicator(\"Faint background\", overlay=true)\n// 1 is solid and 0 is invisible; 0.15 is a light tint\nbgcolor(close > open ? color.new(color.green, 0.15) : na)\nplot(close, title=\"Close\")"
      }
    },
    {
      "id": "color.rgb",
      "category": "plots-and-drawings",
      "title": "Colour from red, green, blue",
      "definition": "Building a colour from its red, green and blue parts.",
      "lipi": {
        "symbols": [
          "color.rgb"
        ],
        "facts": [
          "F-158",
          "F-264"
        ],
        "note": "r, g and b are integers 0 to 255, clamped; the optional a is an opacity from 0 to 1."
      }
    },
    {
      "id": "color.gradient",
      "category": "plots-and-drawings",
      "title": "Colour on a gradient",
      "definition": "Picking a colour between two colours according to where a value sits in a range.",
      "lipi": {
        "symbols": [
          "color.from_gradient"
        ],
        "facts": [
          "F-159",
          "F-264"
        ],
        "note": "All five arguments are required. The value is clamped to its bounds; equal bounds or an na argument give na."
      }
    },
    {
      "id": "draw.line",
      "category": "plots-and-drawings",
      "title": "Line object",
      "definition": "Creating a line between two points that the script can move, restyle or delete later.",
      "lipi": {
        "symbols": [
          "line.new",
          "line.delete"
        ],
        "facts": [
          "F-146",
          "F-147",
          "F-148",
          "F-150",
          "F-151",
          "F-152",
          "F-155",
          "F-252",
          "F-253"
        ],
        "note": "The overlay argument is `forceOverlay` on line.new, `force_overlay` on the other drawings. Setters on an na handle do nothing."
      }
    },
    {
      "id": "draw.line-update",
      "category": "plots-and-drawings",
      "title": "Change a line object",
      "definition": "Moving a line's end points or changing its colour, width, style or extension.",
      "lipi": {
        "symbols": [
          "line.set_xy1",
          "line.set_xy2",
          "line.set_color",
          "line.set_width",
          "line.set_style",
          "line.set_extend"
        ],
        "facts": [
          "F-150",
          "F-252",
          "F-253"
        ],
        "note": "line.set_xloc with four arguments is function-only; the method form takes just the xloc. A setter on an na or deleted handle does nothing."
      }
    },
    {
      "id": "draw.label",
      "category": "plots-and-drawings",
      "title": "Text label object",
      "definition": "Creating a text label at a point that the script can move, change or delete later.",
      "lipi": {
        "symbols": [
          "label.new",
          "label.set_text",
          "label.set_xy",
          "label.delete"
        ],
        "facts": [
          "F-124",
          "F-146",
          "F-147",
          "F-150",
          "F-154",
          "F-252"
        ],
        "note": "Text is limited to 999 characters at run time. `size` takes size.*; a string that is not a size name stops the compiler."
      }
    },
    {
      "id": "draw.box",
      "category": "plots-and-drawings",
      "title": "Rectangle object",
      "definition": "Creating a rectangle between two corners that the script can resize, restyle or delete later.",
      "lipi": {
        "symbols": [
          "box.new",
          "box.set_lefttop",
          "box.set_rightbottom",
          "box.delete"
        ],
        "facts": [
          "F-123",
          "F-124",
          "F-146",
          "F-147",
          "F-154"
        ],
        "note": "Old argument names (text_halign, text_size, ...) compile with a warning; write texthalign, textvalign, size, textcolor, textwrap."
      }
    },
    {
      "id": "draw.polyline",
      "category": "plots-and-drawings",
      "title": "Multi-point line object",
      "definition": "Creating one shape that joins many points.",
      "lipi": {
        "symbols": [
          "polyline.new"
        ],
        "facts": [
          "F-146",
          "F-147",
          "F-150",
          "F-151",
          "F-266",
          "F-320"
        ],
        "note": "At most 1000 points; an empty or larger array returns na with no error. A polyline has only new, delete and all."
      }
    },
    {
      "id": "draw.linefill",
      "category": "plots-and-drawings",
      "title": "Fill between two line objects",
      "definition": "Shading the area between two line objects.",
      "lipi": {
        "symbols": [
          "linefill.new"
        ],
        "facts": [
          "F-146",
          "F-151",
          "F-266"
        ],
        "note": "No max-count argument (fixed at 50) and no copy. Functions: new, delete, get_line1, get_line2, set_color."
      }
    },
    {
      "id": "draw.point",
      "category": "plots-and-drawings",
      "title": "Chart point",
      "definition": "A position on the chart given by bar or time and by price, used to place objects.",
      "lipi": {
        "symbols": [
          "chartPoint.new",
          "chartPoint.from_index",
          "chartPoint.from_time"
        ],
        "facts": [
          "F-149",
          "F-267"
        ],
        "note": "The type is `chartPoint`, not `chart.point`. array.from(chartPoint.now(x)) is refused: use array.new<chartPoint> and array.push."
      }
    },
    {
      "id": "draw.x-by-time",
      "category": "plots-and-drawings",
      "title": "Place objects by time",
      "definition": "Positioning an object horizontally by a timestamp instead of a bar number.",
      "lipi": {
        "symbols": [
          "xloc"
        ],
        "facts": [
          "F-148",
          "F-149",
          "F-203"
        ],
        "note": "xloc.bar_time takes times in milliseconds; xloc.bar_index, the default, takes bar numbers. Any other xloc string stops the script.",
        "example": "//@lipi=2\nindicator(\"Label by time\", overlay=true)\nif barstate.islast {\n    label.new(time, high, \"last bar\", xloc=xloc.bar_time)\n}"
      }
    },
    {
      "id": "draw.future-bars",
      "category": "plots-and-drawings",
      "title": "Draw beyond the last bar",
      "definition": "Placing an object to the right of the most recent bar.",
      "lipi": {
        "symbols": [
          "xloc"
        ],
        "facts": [
          "F-148",
          "F-203"
        ],
        "note": "The compiler accepts any future bar index or time and keeps the object; whether the terminal draws it past the last bar is not shown."
      }
    },
    {
      "id": "draw.object-limits",
      "category": "plots-and-drawings",
      "title": "How many objects a script keeps",
      "definition": "The maximum number of lines, labels, boxes and polylines a script may have on the chart at once.",
      "lipi": {
        "symbols": [
          "indicator"
        ],
        "facts": [
          "F-151",
          "F-152",
          "F-153",
          "F-222",
          "F-269"
        ],
        "note": "Default 50 per kind. Maximum 500 lines, labels, boxes and 100 polylines (larger values are clamped); 9 tables; linefills fixed at 50."
      }
    },
    {
      "id": "draw.all-objects",
      "category": "plots-and-drawings",
      "title": "List the script's objects",
      "definition": "Getting every object of a kind the script has drawn, for example to delete old ones.",
      "lipi": {
        "symbols": [
          "line.all",
          "label.all",
          "box.all"
        ],
        "facts": [
          "F-145",
          "F-152"
        ],
        "note": "The `.all` arrays hold live drawings only; a drawing trimmed over the limit is gone and its handle does nothing."
      }
    },
    {
      "id": "draw.table",
      "category": "plots-and-drawings",
      "title": "Table on the chart",
      "definition": "A grid of cells fixed to a corner of the chart, with text and colours the script sets.",
      "lipi": {
        "symbols": [
          "table.new",
          "table.cell"
        ],
        "facts": [
          "F-123",
          "F-146",
          "F-151",
          "F-254"
        ],
        "note": "One table per position.* slot (9). A new table at an occupied slot replaces the old one; a cell outside the grid is ignored."
      }
    },
    {
      "id": "draw.table-update",
      "category": "plots-and-drawings",
      "title": "Change table cells",
      "definition": "Changing a table cell's text, colours, size or alignment, or merging cells.",
      "lipi": {
        "symbols": [
          "table.cell_set_text",
          "table.cell_set_bgcolor",
          "table.merge_cells"
        ],
        "facts": [
          "F-123",
          "F-254"
        ],
        "note": "Old names such as text_halign warn; write texthalign. Merge cells with t.merge_cells(0, 0, 1, 0)."
      }
    },
    {
      "id": "draw.text-align",
      "category": "plots-and-drawings",
      "title": "Text alignment and size",
      "definition": "Choosing how text sits inside a label, box or cell, and how large it is.",
      "lipi": {
        "symbols": [
          "text",
          "size"
        ],
        "facts": [
          "F-123",
          "F-124",
          "F-311"
        ],
        "note": "text.align_* are the const strings left, center, right, top, bottom; other values stop the script. Labels use textalign, boxes and tables texthalign and textvalign."
      }
    },
    {
      "id": "strat.entry",
      "category": "strategies-and-alerts",
      "title": "Enter a position",
      "definition": "Opening or adding to a simulated long or short position.",
      "lipi": {
        "symbols": [
          "strategy.entry"
        ],
        "facts": [
          "F-188",
          "F-189",
          "F-191",
          "F-192",
          "F-193",
          "F-199",
          "F-272",
          "F-273",
          "F-276",
          "F-307"
        ],
        "note": "direction is strategy.long or strategy.short. No trail_points, qty_percent or alert_message. A market order fills at the next bar's open."
      }
    },
    {
      "id": "strat.order",
      "category": "strategies-and-alerts",
      "title": "Place an order",
      "definition": "Placing a simulated order that does not reverse an existing position.",
      "lipi": {
        "symbols": [
          "strategy.order"
        ],
        "facts": [
          "F-188",
          "F-189",
          "F-190",
          "F-277",
          "F-307"
        ],
        "note": "A raw net order with no pyramiding check: it can open, add, reduce, close or reverse."
      }
    },
    {
      "id": "strat.exit",
      "category": "strategies-and-alerts",
      "title": "Exit with stop or target",
      "definition": "Closing a simulated position with a stop-loss, take-profit or trailing stop.",
      "lipi": {
        "symbols": [
          "strategy.exit"
        ],
        "facts": [
          "F-190",
          "F-191",
          "F-274",
          "F-275",
          "F-279",
          "F-307"
        ],
        "note": "No trailing-stop arguments. profit and loss are distances in ticks of syminfo.minmove. With no limit, stop, profit or loss the call is ignored."
      }
    },
    {
      "id": "strat.close",
      "category": "strategies-and-alerts",
      "title": "Close a position",
      "definition": "Closing a simulated position, or all of them, at market.",
      "lipi": {
        "symbols": [
          "strategy.close",
          "strategy.close_all"
        ],
        "facts": [
          "F-190",
          "F-278",
          "F-307"
        ],
        "note": "strategy.close(id) does nothing when that entry is not open. close_all closes the position."
      }
    },
    {
      "id": "strat.cancel",
      "category": "strategies-and-alerts",
      "title": "Cancel pending orders",
      "definition": "Cancelling simulated orders that have not filled.",
      "lipi": {
        "symbols": [
          "strategy.cancel",
          "strategy.cancel_all"
        ],
        "facts": [
          "F-190",
          "F-278"
        ],
        "note": "cancel(id) removes every queued order with that id and does nothing when none exists; cancel_all removes all."
      }
    },
    {
      "id": "strat.position",
      "category": "strategies-and-alerts",
      "title": "Current position",
      "definition": "The size and average price of the open simulated position.",
      "lipi": {
        "symbols": [
          "strategy.position_size",
          "strategy.position_avg_price"
        ],
        "facts": [
          "F-196",
          "F-280"
        ],
        "note": "`position_size` is signed: negative for a short."
      }
    },
    {
      "id": "strat.results",
      "category": "strategies-and-alerts",
      "title": "Strategy results",
      "definition": "Running totals of the simulation: equity, net profit, drawdown, and counts of trades.",
      "lipi": {
        "symbols": [
          "strategy.equity",
          "strategy.netprofit",
          "strategy.max_drawdown",
          "strategy.closedtrades",
          "strategy.wintrades"
        ],
        "facts": [
          "F-196",
          "F-280",
          "F-282"
        ],
        "note": "equity = initial_capital + netprofit + openprofit. netprofit is realized and net of commission; unrealized profit is openprofit."
      }
    },
    {
      "id": "strat.trade-history",
      "category": "strategies-and-alerts",
      "title": "Details of each trade",
      "definition": "The entry, exit, size and profit of each closed or open simulated trade.",
      "lipi": {
        "symbols": [
          "strategy.closedtrades_profit",
          "strategy.closedtrades_entry_price",
          "strategy.opentrades_profit"
        ],
        "facts": [
          "F-197",
          "F-198",
          "F-282"
        ],
        "note": "Accessors are flat functions with zero-based trade numbers, such as strategy.closedtrades_profit(0). closedtrades_exit_bar_index always returns 0."
      }
    },
    {
      "id": "strat.settings",
      "category": "strategies-and-alerts",
      "title": "Simulation settings",
      "definition": "Starting capital, order size, commission, pyramiding and when orders fill.",
      "lipi": {
        "symbols": [
          "strategy"
        ],
        "facts": [
          "F-015",
          "F-016",
          "F-193",
          "F-194",
          "F-195",
          "F-272",
          "F-281",
          "F-284"
        ],
        "note": "Percent commission is notional x value / 100, charged on open and on close. Entries beyond pyramiding are ignored silently."
      }
    },
    {
      "id": "alert.call",
      "category": "strategies-and-alerts",
      "title": "Raise an alert from code",
      "definition": "Sending a notification with a message the script builds, when the script decides.",
      "lipi": {
        "symbols": [
          "alert"
        ],
        "facts": [
          "F-219",
          "F-256",
          "F-306"
        ],
        "note": "Fires only on realtime bars, only in alert mode, at most once per bar. One string argument; no frequency argument."
      }
    },
    {
      "id": "alert.condition",
      "category": "strategies-and-alerts",
      "title": "Declare an alert condition",
      "definition": "Declaring a condition the chart user can turn into an alert.",
      "lipi": {
        "symbols": [
          "alertcondition"
        ],
        "facts": [
          "F-172",
          "F-186",
          "F-220",
          "F-303"
        ],
        "note": "Top level only. title and message must be const strings; the condition must be a boolean series."
      }
    },
    {
      "id": "alert.webhook",
      "category": "strategies-and-alerts",
      "title": "Send to a webhook",
      "definition": "Delivering an alert's message to an outside address.",
      "lipi": {
        "symbols": [
          "alert"
        ],
        "facts": [
          "F-306"
        ],
        "note": "The script only builds the message string (write JSON in single quotes); no argument sets a webhook address.",
        "example": "//@lipi=2\nindicator(\"Alert message\", overlay=true)\nif barstate.isconfirmed and close > open {\n    alert('{\"event\":\"up\",\"price\":' + str.tostring(close) + '}')\n}"
      }
    },
    {
      "id": "data.ohlcv",
      "category": "market-data-and-time",
      "title": "Price and volume of the bar",
      "definition": "The open, high, low, close and volume of the current bar.",
      "lipi": {
        "symbols": [
          "open",
          "high",
          "low",
          "close",
          "volume"
        ],
        "facts": [
          "F-200"
        ]
      }
    },
    {
      "id": "data.derived-price",
      "category": "market-data-and-time",
      "title": "Average prices of the bar",
      "definition": "Common averages of a bar's prices, such as the mid-point of high and low.",
      "lipi": {
        "symbols": [
          "hl2",
          "hlc3",
          "ohlc4",
          "hlcc4"
        ],
        "facts": [
          "F-200"
        ],
        "note": "hlcc4 is (high + low + 2 x close) / 4."
      }
    },
    {
      "id": "data.open-interest",
      "category": "market-data-and-time",
      "title": "Open interest",
      "definition": "The number of open contracts, for instruments that report it.",
      "lipi": {
        "symbols": [
          "oi"
        ],
        "facts": [
          "F-200",
          "F-290"
        ],
        "note": "`oi` is 0, not na, on a bar that carries no open interest."
      }
    },
    {
      "id": "data.orderflow",
      "category": "market-data-and-time",
      "title": "Orderflow of the bar",
      "definition": "Buy and sell volume, delta and trade counts of the bar.",
      "lipi": {
        "symbols": [
          "orderflow.buyvolume",
          "orderflow.sellvolume",
          "orderflow.delta",
          "orderflow.trades",
          "orderflow.cvd"
        ],
        "facts": [
          "F-210",
          "F-291",
          "F-309"
        ],
        "note": "Ten integer series exist only where the chart has footprint data, else na. orderflow.cvd restarts at session.isfirst."
      }
    },
    {
      "id": "data.instrument",
      "category": "market-data-and-time",
      "title": "Instrument details",
      "definition": "The symbol, exchange, currency, tick size and type of the instrument on the chart.",
      "lipi": {
        "symbols": [
          "syminfo.ticker",
          "syminfo.exchange",
          "syminfo.currency",
          "syminfo.mintick",
          "syminfo.asset_type"
        ],
        "facts": [
          "F-208",
          "F-292",
          "F-313"
        ],
        "note": "syminfo has 14 names; no tickerid, pointvalue or type. ticker is exchange:segment:symbol; mintick = tick size / maximum tick precision."
      }
    },
    {
      "id": "data.timeframe",
      "category": "market-data-and-time",
      "title": "Chart timeframe",
      "definition": "The timeframe of the chart and tests for its kind, such as intraday or daily.",
      "lipi": {
        "symbols": [
          "interval.interval",
          "interval.isintraday",
          "interval.isdaily",
          "interval.multiplier",
          "interval.in_seconds"
        ],
        "facts": [
          "F-207",
          "F-289",
          "F-212"
        ],
        "note": "There is no `timeframe` namespace; use interval.*. in_seconds counts a month as 2628003 seconds and is na for tick and range intervals."
      }
    },
    {
      "id": "data.other-symbol",
      "category": "market-data-and-time",
      "title": "Data from another symbol or timeframe",
      "definition": "Reading a series of a different instrument or a different timeframe from the one on the chart.",
      "lipi": {
        "absent_reason": "Lipi reads only the chart's own symbol and timeframe.",
        "facts": [
          "F-212"
        ],
        "note": "There is no request namespace: request.security and every other symbol or timeframe read fail to compile."
      }
    },
    {
      "id": "data.chart-type",
      "category": "market-data-and-time",
      "title": "Chart type",
      "definition": "Whether the chart shows standard candles or another bar type.",
      "lipi": {
        "symbols": [
          "chart.is_standard",
          "chart.is_heikinashi",
          "chart.is_renko"
        ],
        "facts": [
          "F-211"
        ],
        "note": "chart.* has nine names: bg_color, fg_color, is_standard, is_heikinashi, is_kagi, is_linebreak, is_pnf, is_range, is_renko."
      }
    },
    {
      "id": "time.bar-time",
      "category": "market-data-and-time",
      "title": "Time of the bar",
      "definition": "The opening and closing time of the current bar.",
      "lipi": {
        "symbols": [
          "time",
          "time_close"
        ],
        "facts": [
          "F-200",
          "F-202",
          "F-203",
          "F-286",
          "F-287",
          "F-318"
        ],
        "note": "`time` and `time_close` are int milliseconds; time_close is the open time plus one interval."
      }
    },
    {
      "id": "time.now",
      "category": "market-data-and-time",
      "title": "Current time",
      "definition": "The present time while the script runs.",
      "lipi": {
        "symbols": [
          "timenow"
        ],
        "facts": [
          "F-249",
          "F-285"
        ],
        "note": "`timenow` is the wall clock on every run, not the bar's time. `time.now` does not exist."
      }
    },
    {
      "id": "time.parts",
      "category": "market-data-and-time",
      "title": "Parts of a date",
      "definition": "The year, month, day, weekday, hour, minute and second of a time.",
      "lipi": {
        "symbols": [
          "year",
          "month",
          "dayofmonth",
          "dayofweek",
          "hour",
          "minute",
          "second"
        ],
        "facts": [
          "F-201",
          "F-205",
          "F-286",
          "F-287",
          "F-317"
        ],
        "note": "dayofweek runs 1 (Sunday) to 7 (Saturday). hour(time, zone) needs an IANA zone name; an offset such as \"UTC-5\" gives 0."
      }
    },
    {
      "id": "time.make-timestamp",
      "category": "market-data-and-time",
      "title": "Build a time value",
      "definition": "Making a time value from a date and time of day.",
      "lipi": {
        "symbols": [
          "timestamp"
        ],
        "facts": [
          "F-204",
          "F-171",
          "F-262"
        ],
        "note": "A date string without a zone is read as UTC; a string that matches no layout gives na. The numeric form uses the exchange zone."
      }
    },
    {
      "id": "time.format",
      "category": "market-data-and-time",
      "title": "Format a time as text",
      "definition": "Turning a time value into readable text.",
      "lipi": {
        "symbols": [
          "str.format_time"
        ],
        "facts": [
          "F-293",
          "F-317"
        ],
        "note": "str.format_time reads seconds, not milliseconds: pass int(time / 1000). The layout is the reference date 2006-01-02 15:04:05."
      }
    },
    {
      "id": "time.session",
      "category": "market-data-and-time",
      "title": "Trading session",
      "definition": "Whether a bar falls inside a session, and the start of the trading day.",
      "lipi": {
        "symbols": [
          "session.isfirst",
          "session.date",
          "time_sessionday"
        ],
        "facts": [
          "F-209",
          "F-288",
          "F-313",
          "F-318"
        ],
        "note": "session.* has only `date` and `isfirst`; there is no session.islast."
      }
    },
    {
      "id": "math.abs",
      "category": "math-and-strings",
      "title": "Absolute value",
      "definition": "The absolute value of `number`: its magnitude, with the sign removed.",
      "lipi": {
        "symbols": [
          "math.abs"
        ]
      }
    },
    {
      "id": "math.rounding",
      "category": "math-and-strings",
      "title": "Rounding",
      "definition": "Rounds `number` to the nearest whole number and returns an int.",
      "lipi": {
        "symbols": [
          "math.round",
          "math.ceil",
          "math.floor"
        ]
      }
    },
    {
      "id": "math.round-to-tick",
      "category": "math-and-strings",
      "title": "Round to the tick size",
      "definition": "Rounds `number` to the nearest multiple of `syminfo.mintick` for the chart symbol.",
      "lipi": {
        "symbols": [
          "math.round_to_mintick"
        ]
      }
    },
    {
      "id": "math.min-max",
      "category": "math-and-strings",
      "title": "Smaller or larger of values",
      "definition": "The smallest of the numbers you pass.",
      "lipi": {
        "symbols": [
          "math.min",
          "math.max"
        ]
      }
    },
    {
      "id": "math.power",
      "category": "math-and-strings",
      "title": "Powers and roots",
      "definition": "`base` raised to the power of `exponent`.",
      "lipi": {
        "symbols": [
          "math.pow",
          "math.sqrt"
        ]
      }
    },
    {
      "id": "math.exp-log",
      "category": "math-and-strings",
      "title": "Exponent and logarithms",
      "definition": "Euler's number raised to the power of `number`.",
      "lipi": {
        "symbols": [
          "math.exp",
          "math.log",
          "math.log10"
        ]
      }
    },
    {
      "id": "math.trig",
      "category": "math-and-strings",
      "title": "Trigonometry",
      "definition": "The sine of `angle`, where the angle is in radians.",
      "lipi": {
        "symbols": [
          "math.sin",
          "math.cos",
          "math.tan",
          "math.asin",
          "math.acos",
          "math.atan"
        ]
      }
    },
    {
      "id": "math.angles",
      "category": "math-and-strings",
      "title": "Degrees and radians",
      "definition": "Converts an angle in radians to the same angle in degrees.",
      "lipi": {
        "symbols": [
          "math.todegrees",
          "math.toradians"
        ]
      }
    },
    {
      "id": "math.sign",
      "category": "math-and-strings",
      "title": "Sign of a number",
      "definition": "The sign of `number`: -1 for a negative number and 1 for a positive one.",
      "lipi": {
        "symbols": [
          "math.sign"
        ]
      }
    },
    {
      "id": "math.random",
      "category": "math-and-strings",
      "title": "Random number",
      "definition": "Gives your script a random float, bounded below by `min` and above by `max`.",
      "lipi": {
        "symbols": [
          "math.random"
        ]
      }
    },
    {
      "id": "math.avg-sum",
      "category": "math-and-strings",
      "title": "Average and sum of values",
      "definition": "The arithmetic mean of the numbers you pass: their sum divided by how many there are.",
      "lipi": {
        "symbols": [
          "math.avg",
          "math.sum"
        ]
      }
    },
    {
      "id": "str.tostring",
      "category": "math-and-strings",
      "title": "Number to text",
      "definition": "Renders a value as a string.",
      "lipi": {
        "symbols": [
          "str.tostring"
        ]
      }
    },
    {
      "id": "str.tonumber",
      "category": "math-and-strings",
      "title": "Text to number",
      "definition": "Reads a number out of a string.",
      "lipi": {
        "symbols": [
          "str.tonumber"
        ]
      }
    },
    {
      "id": "str.length",
      "category": "math-and-strings",
      "title": "Length of text",
      "definition": "Gives the length of a string as an int.",
      "lipi": {
        "symbols": [
          "str.length"
        ]
      }
    },
    {
      "id": "str.case",
      "category": "math-and-strings",
      "title": "Upper and lower case",
      "definition": "Converts a string to upper case; the other half of the pair with str.lower.",
      "lipi": {
        "symbols": [
          "str.upper",
          "str.lower"
        ]
      }
    },
    {
      "id": "str.search",
      "category": "math-and-strings",
      "title": "Find text",
      "definition": "Tests whether one string occurs inside another.",
      "lipi": {
        "symbols": [
          "str.contains",
          "str.pos",
          "str.startswith",
          "str.endswith"
        ]
      }
    },
    {
      "id": "str.substring",
      "category": "math-and-strings",
      "title": "Part of a text",
      "definition": "Cuts a piece out of a string.",
      "lipi": {
        "symbols": [
          "str.substring"
        ]
      }
    },
    {
      "id": "str.replace",
      "category": "math-and-strings",
      "title": "Replace text",
      "definition": "Substitutes one piece of text for another inside a string.",
      "lipi": {
        "symbols": [
          "str.replace",
          "str.replace_all"
        ]
      }
    },
    {
      "id": "str.split",
      "category": "math-and-strings",
      "title": "Split text",
      "definition": "Splits `string` wherever `separator` occurs and returns the pieces as an array of strings.",
      "lipi": {
        "symbols": [
          "str.split"
        ]
      }
    },
    {
      "id": "str.trim",
      "category": "math-and-strings",
      "title": "Trim spaces",
      "definition": "Removes whitespace from around a string and hands back the result.",
      "lipi": {
        "symbols": [
          "str.trim"
        ]
      }
    },
    {
      "id": "str.repeat",
      "category": "math-and-strings",
      "title": "Repeat text",
      "definition": "Produces a string made of repeated copies of another, with the option of something between the copies.",
      "lipi": {
        "symbols": [
          "str.repeat"
        ]
      }
    },
    {
      "id": "str.match",
      "category": "math-and-strings",
      "title": "Match a pattern",
      "definition": "Returns the first part of `source` that matches the regular expression `pattern`.",
      "lipi": {
        "symbols": [
          "str.match"
        ]
      }
    },
    {
      "id": "str.concat",
      "category": "math-and-strings",
      "title": "Join texts",
      "definition": "Joining two pieces of text into one.",
      "lipi": {
        "symbols": [
          "+"
        ]
      }
    },
    {
      "id": "array.create",
      "category": "arrays",
      "title": "Create an array",
      "definition": "Creates an array of the given length.",
      "lipi": {
        "symbols": [
          "array.new",
          "array.from",
          "array.new_float",
          "array.new_int"
        ]
      }
    },
    {
      "id": "array.object-arrays",
      "category": "arrays",
      "title": "Arrays of drawing objects",
      "definition": "Creates an array of `line` IDs with `size` elements, each set to `initial_value`.",
      "lipi": {
        "symbols": [
          "array.new_line",
          "array.new_label",
          "array.new_box"
        ]
      }
    },
    {
      "id": "array.get-set",
      "category": "arrays",
      "title": "Read and write an element",
      "definition": "Returns the element at `index`.",
      "lipi": {
        "symbols": [
          "array.get",
          "array.set"
        ]
      }
    },
    {
      "id": "array.size",
      "category": "arrays",
      "title": "Number of elements",
      "definition": "Returns the number of elements in the array.",
      "lipi": {
        "symbols": [
          "array.length"
        ]
      }
    },
    {
      "id": "array.push-pop",
      "category": "arrays",
      "title": "Add or remove at the end",
      "definition": "Appends `value` to the end of the array, growing it by one element.",
      "lipi": {
        "symbols": [
          "array.push",
          "array.pop"
        ]
      }
    },
    {
      "id": "array.shift-unshift",
      "category": "arrays",
      "title": "Add or remove at the start",
      "definition": "Inserts `value` at the beginning of the array.",
      "lipi": {
        "symbols": [
          "array.unshift",
          "array.shift"
        ]
      }
    },
    {
      "id": "array.insert-remove",
      "category": "arrays",
      "title": "Insert or remove at a position",
      "definition": "Inserts `value` at `index`, moving the element that was there, and every element after it, up one index.",
      "lipi": {
        "symbols": [
          "array.insert",
          "array.remove"
        ]
      }
    },
    {
      "id": "array.clear-fill",
      "category": "arrays",
      "title": "Empty or fill an array",
      "definition": "Removes every element, leaving an empty array.",
      "lipi": {
        "symbols": [
          "array.clear",
          "array.fill"
        ]
      }
    },
    {
      "id": "array.first-last",
      "category": "arrays",
      "title": "First and last element",
      "definition": "Returns the first element of the array.",
      "lipi": {
        "symbols": [
          "array.first",
          "array.last"
        ]
      }
    },
    {
      "id": "array.search",
      "category": "arrays",
      "title": "Find an element",
      "definition": "Returns true when `value` is one of the array's elements.",
      "lipi": {
        "symbols": [
          "array.includes",
          "array.indexof",
          "array.lastindexof",
          "array.binary_search"
        ]
      }
    },
    {
      "id": "array.copy-slice",
      "category": "arrays",
      "title": "Copy, slice and join arrays",
      "definition": "Returns a new array with the same elements.",
      "lipi": {
        "symbols": [
          "array.copy",
          "array.slice",
          "array.concat"
        ]
      }
    },
    {
      "id": "array.sort",
      "category": "arrays",
      "title": "Sort and reverse",
      "definition": "Sorts the array in place.",
      "lipi": {
        "symbols": [
          "array.sort",
          "array.sort_indices",
          "array.reverse"
        ]
      }
    },
    {
      "id": "array.stats",
      "category": "arrays",
      "title": "Statistics of an array",
      "definition": "Returns the sum of the array's elements.",
      "lipi": {
        "symbols": [
          "array.sum",
          "array.avg",
          "array.min",
          "array.max",
          "array.median",
          "array.stdev",
          "array.variance"
        ]
      }
    },
    {
      "id": "array.join",
      "category": "arrays",
      "title": "Array to text",
      "definition": "Joins the elements into one string, with `separator` between them.",
      "lipi": {
        "symbols": [
          "array.join"
        ]
      }
    },
    {
      "id": "array.every-some",
      "category": "arrays",
      "title": "Test all or any elements",
      "definition": "Returns true when every element is true.",
      "lipi": {
        "symbols": [
          "array.every",
          "array.some"
        ]
      }
    },
    {
      "id": "ta.alma",
      "category": "indicators",
      "title": "Arnaud Legoux moving average",
      "definition": "An Arnaud Legoux moving average of `source` over `length` bars.",
      "lipi": {
        "symbols": [
          "ta.alma"
        ]
      }
    },
    {
      "id": "ta.atr",
      "category": "indicators",
      "title": "Average true range",
      "definition": "Average true range over `length` bars.",
      "lipi": {
        "symbols": [
          "ta.atr"
        ]
      }
    },
    {
      "id": "ta.barssince",
      "category": "indicators",
      "title": "Bars since a condition",
      "definition": "Counts the bars that have gone by since `condition` was last true.",
      "lipi": {
        "symbols": [
          "ta.barssince"
        ]
      }
    },
    {
      "id": "ta.bb",
      "category": "indicators",
      "title": "Bollinger Bands",
      "definition": "Bollinger bands for `source` over `length` bars, with `mult` setting how far the outer bands sit from the middle one.",
      "lipi": {
        "symbols": [
          "ta.bb"
        ]
      }
    },
    {
      "id": "ta.bbw",
      "category": "indicators",
      "title": "Bollinger Bands width",
      "definition": "Bollinger band width: the same calculation as `talib.bb`, delivered as one number instead of three bands.",
      "lipi": {
        "symbols": [
          "ta.bbw"
        ]
      }
    },
    {
      "id": "ta.cci",
      "category": "indicators",
      "title": "Commodity channel index",
      "definition": "Commodity Channel Index for `source` over `length` bars.",
      "lipi": {
        "symbols": [
          "ta.cci"
        ]
      }
    },
    {
      "id": "ta.change",
      "category": "indicators",
      "title": "Change over bars",
      "definition": "The difference between the current value of `source` and its value `length` bars back.",
      "lipi": {
        "symbols": [
          "ta.change"
        ]
      }
    },
    {
      "id": "ta.cmo",
      "category": "indicators",
      "title": "Chande momentum oscillator",
      "definition": "Chande Momentum Oscillator for `source` over `length` bars.",
      "lipi": {
        "symbols": [
          "ta.cmo"
        ]
      }
    },
    {
      "id": "ta.cog",
      "category": "indicators",
      "title": "Center of gravity",
      "definition": "Centre of gravity of `source` across a window of `length` bars.",
      "lipi": {
        "symbols": [
          "ta.cog"
        ]
      }
    },
    {
      "id": "ta.correlation",
      "category": "indicators",
      "title": "Correlation coefficient",
      "definition": "Correlation between two series, `source1` and `source2`, measured over `length` bars.",
      "lipi": {
        "symbols": [
          "ta.correlation"
        ]
      }
    },
    {
      "id": "ta.cross",
      "category": "indicators",
      "title": "Cross of two series",
      "definition": "True on a bar where `source1` and `source2` cross, in either direction.",
      "lipi": {
        "symbols": [
          "ta.cross"
        ]
      }
    },
    {
      "id": "ta.crossover",
      "category": "indicators",
      "title": "Cross above",
      "definition": "Flags the bar on which `source1` crosses above `source2`.",
      "lipi": {
        "symbols": [
          "ta.crossover"
        ]
      }
    },
    {
      "id": "ta.crossunder",
      "category": "indicators",
      "title": "Cross below",
      "definition": "The mirror of `talib.crossover`: true on the bar where `source1` crosses below `source2`.",
      "lipi": {
        "symbols": [
          "ta.crossunder"
        ]
      }
    },
    {
      "id": "ta.cum",
      "category": "indicators",
      "title": "Cumulative sum",
      "definition": "Accumulates `source` as the script advances through the chart.",
      "lipi": {
        "symbols": [
          "ta.cum"
        ]
      }
    },
    {
      "id": "ta.dc",
      "category": "indicators",
      "title": "Donchian channel",
      "definition": "Donchian channel over `length` bars.",
      "lipi": {
        "symbols": [
          "ta.dc"
        ]
      }
    },
    {
      "id": "ta.dcw",
      "category": "indicators",
      "title": "Donchian channel width",
      "definition": "Donchian channel width over `length` bars, as a single figure.",
      "lipi": {
        "symbols": [
          "ta.dcw"
        ]
      }
    },
    {
      "id": "ta.dev",
      "category": "indicators",
      "title": "Mean absolute deviation",
      "definition": "A deviation measure for `source` over `length` bars.",
      "lipi": {
        "symbols": [
          "ta.dev"
        ]
      }
    },
    {
      "id": "ta.dmi",
      "category": "indicators",
      "title": "Directional movement index",
      "definition": "The directional movement family in one call, calculated from the chart's own bars.",
      "lipi": {
        "symbols": [
          "ta.dmi"
        ],
        "note": "Smooths true range and directional movement with alpha 2/(length+1); the ADX stage uses RMA."
      }
    },
    {
      "id": "ta.ema",
      "category": "indicators",
      "title": "Exponential moving average",
      "definition": "Exponential moving average of `source` over `length` bars, weighted so that recent bars count for more than older ones.",
      "lipi": {
        "symbols": [
          "ta.ema"
        ]
      }
    },
    {
      "id": "ta.falling",
      "category": "indicators",
      "title": "Falling for a number of bars",
      "definition": "Asks the same question as `talib.rising` in the other direction: has `source` been falling across `length` bars? The answer is a bool, not a number.",
      "lipi": {
        "symbols": [
          "ta.falling"
        ]
      }
    },
    {
      "id": "ta.highest",
      "category": "indicators",
      "title": "Highest value",
      "definition": "The highest value `source` reached in the last `length` bars.",
      "lipi": {
        "symbols": [
          "ta.highest"
        ],
        "note": "At this build its first valid bars can miss the true maximum."
      }
    },
    {
      "id": "ta.highestbars",
      "category": "indicators",
      "title": "Offset of the highest value",
      "definition": "Locates the highest value of `source` within the last `length` bars and returns its position rather than its value.",
      "lipi": {
        "symbols": [
          "ta.highestbars"
        ]
      }
    },
    {
      "id": "ta.hma",
      "category": "indicators",
      "title": "Hull moving average",
      "definition": "Hull moving average of `source` over `length` bars.",
      "lipi": {
        "symbols": [
          "ta.hma"
        ],
        "note": "Built on ta.wma, so it shares ta.wma's behaviour at this build. The half length rounds up."
      }
    },
    {
      "id": "ta.kc",
      "category": "indicators",
      "title": "Keltner channels",
      "definition": "Keltner channels for `source` over `length` bars, with `mult` setting the distance to the outer bands.",
      "lipi": {
        "symbols": [
          "ta.kc"
        ]
      }
    },
    {
      "id": "ta.kcw",
      "category": "indicators",
      "title": "Keltner channels width",
      "definition": "Keltner channel width for `source` over `length` bars: one figure in place of the three the channel call returns.",
      "lipi": {
        "symbols": [
          "ta.kcw"
        ]
      }
    },
    {
      "id": "ta.linreg",
      "category": "indicators",
      "title": "Linear regression",
      "definition": "Fits a linear regression to `source` across `length` bars and returns a value from that fit.",
      "lipi": {
        "symbols": [
          "ta.linreg"
        ],
        "note": "At this build a non-zero offset gives values that do not follow the fitted line."
      }
    },
    {
      "id": "ta.lowest",
      "category": "indicators",
      "title": "Lowest value",
      "definition": "The lowest value `source` reached in the last `length` bars.",
      "lipi": {
        "symbols": [
          "ta.lowest"
        ],
        "note": "At this build it returns 0 on the first length bars after it first has a value."
      }
    },
    {
      "id": "ta.lowestbars",
      "category": "indicators",
      "title": "Offset of the lowest value",
      "definition": "Gives the position of the lowest value of `source` within the last `length` bars, not the value itself.",
      "lipi": {
        "symbols": [
          "ta.lowestbars"
        ]
      }
    },
    {
      "id": "ta.macd",
      "category": "indicators",
      "title": "MACD",
      "definition": "Moving average convergence/divergence for `source`, from three lengths: `fastlen`, `slowlen` and `siglen`.",
      "lipi": {
        "symbols": [
          "ta.macd"
        ]
      }
    },
    {
      "id": "ta.median",
      "category": "indicators",
      "title": "Median",
      "definition": "The middle value of the last `length` values of `source`.",
      "lipi": {
        "symbols": [
          "ta.median"
        ]
      }
    },
    {
      "id": "ta.mfi",
      "category": "indicators",
      "title": "Money flow index",
      "definition": "Money Flow Index for `source` over `length` bars.",
      "lipi": {
        "symbols": [
          "ta.mfi"
        ]
      }
    },
    {
      "id": "ta.mode",
      "category": "indicators",
      "title": "Mode",
      "definition": "Of the last `length` values of `source`, this reports the one that recurs most often.",
      "lipi": {
        "symbols": [
          "ta.mode"
        ]
      }
    },
    {
      "id": "ta.nvi",
      "category": "indicators",
      "title": "Negative volume index",
      "definition": "Negative volume index for the chart's bars.",
      "lipi": {
        "symbols": [
          "ta.nvi"
        ]
      }
    },
    {
      "id": "ta.obv",
      "category": "indicators",
      "title": "On-balance volume",
      "definition": "On-balance volume for the chart's bars.",
      "lipi": {
        "symbols": [
          "ta.obv"
        ]
      }
    },
    {
      "id": "ta.percentile_linear_interpolation",
      "category": "indicators",
      "title": "Percentile by linear interpolation",
      "definition": "The requested `percentile` of `source` over `length` bars, interpolating between the two values that straddle the rank.",
      "lipi": {
        "symbols": [
          "ta.percentile_linear_interpolation"
        ]
      }
    },
    {
      "id": "ta.percentile_nearest_rank",
      "category": "indicators",
      "title": "Percentile by nearest rank",
      "definition": "Takes the requested `percentile` of `source` over `length` bars at the nearest rank, without interpolating.",
      "lipi": {
        "symbols": [
          "ta.percentile_nearest_rank"
        ]
      }
    },
    {
      "id": "ta.percentrank",
      "category": "indicators",
      "title": "Percent rank",
      "definition": "Ranks where `source` now stands against the last `length` bars of itself.",
      "lipi": {
        "symbols": [
          "ta.percentrank"
        ]
      }
    },
    {
      "id": "ta.pivothigh",
      "category": "indicators",
      "title": "Pivot high",
      "definition": "Looks for a pivot high in `source`, as this build implements it.",
      "lipi": {
        "symbols": [
          "ta.pivothigh"
        ]
      }
    },
    {
      "id": "ta.pivotlow",
      "category": "indicators",
      "title": "Pivot low",
      "definition": "Looks for a pivot low in `source`, as this build implements it.",
      "lipi": {
        "symbols": [
          "ta.pivotlow"
        ]
      }
    },
    {
      "id": "ta.psar",
      "category": "indicators",
      "title": "Parabolic SAR",
      "definition": "Parabolic SAR, controlled by three numbers rather than a bar count: where the calculation starts, how much it moves on each step, and how far it is allowed to go.",
      "lipi": {
        "symbols": [
          "ta.psar"
        ]
      }
    },
    {
      "id": "ta.pvi",
      "category": "indicators",
      "title": "Positive volume index",
      "definition": "Positive volume index for the chart's bars, the counterpart of `talib.nvi`.",
      "lipi": {
        "symbols": [
          "ta.pvi"
        ]
      }
    },
    {
      "id": "ta.pvt",
      "category": "indicators",
      "title": "Price-volume trend",
      "definition": "Price-volume trend for the chart's bars.",
      "lipi": {
        "symbols": [
          "ta.pvt"
        ]
      }
    },
    {
      "id": "ta.range",
      "category": "indicators",
      "title": "Range of values",
      "definition": "How much ground `source` covered over the last `length` bars, expressed as one figure.",
      "lipi": {
        "symbols": [
          "ta.range"
        ]
      }
    },
    {
      "id": "ta.rising",
      "category": "indicators",
      "title": "Rising for a number of bars",
      "definition": "Tests whether `source` has been rising across `length` bars.",
      "lipi": {
        "symbols": [
          "ta.rising"
        ]
      }
    },
    {
      "id": "ta.rma",
      "category": "indicators",
      "title": "Wilder's moving average",
      "definition": "Rolling moving average of `source` over `length` bars.",
      "lipi": {
        "symbols": [
          "ta.rma"
        ]
      }
    },
    {
      "id": "ta.roc",
      "category": "indicators",
      "title": "Rate of change",
      "definition": "Rate of change of `source` measured across `length` bars.",
      "lipi": {
        "symbols": [
          "ta.roc"
        ]
      }
    },
    {
      "id": "ta.rsi",
      "category": "indicators",
      "title": "Relative strength index",
      "definition": "Relative Strength Index for `source` over `length` bars.",
      "lipi": {
        "symbols": [
          "ta.rsi"
        ]
      }
    },
    {
      "id": "ta.sma",
      "category": "indicators",
      "title": "Simple moving average",
      "definition": "Simple moving average of `source` over `length` bars: every bar in the window counts for the same.",
      "lipi": {
        "symbols": [
          "ta.sma"
        ]
      }
    },
    {
      "id": "ta.stdev",
      "category": "indicators",
      "title": "Standard deviation",
      "definition": "Standard deviation of `source` over `length` bars.",
      "lipi": {
        "symbols": [
          "ta.stdev"
        ]
      }
    },
    {
      "id": "ta.stoch",
      "category": "indicators",
      "title": "Stochastic",
      "definition": "Stochastic reading that places `source` inside the span set by `high` and `low` over `length` bars.",
      "lipi": {
        "symbols": [
          "ta.stoch"
        ]
      }
    },
    {
      "id": "ta.sum",
      "category": "indicators",
      "title": "Sum over bars",
      "definition": "Adds up the last `length` values of `source`.",
      "lipi": {
        "symbols": [
          "ta.sum"
        ]
      }
    },
    {
      "id": "ta.supertrend",
      "category": "indicators",
      "title": "Supertrend",
      "definition": "Supertrend from a `multiplier` and an `atrLength`, calculated on the chart's own bars.",
      "lipi": {
        "symbols": [
          "ta.supertrend"
        ],
        "note": "Takes the multiplier first, then the ATR length. At this build the direction is -1 on every bar except at most one early bar (none with an ATR length of 1)."
      }
    },
    {
      "id": "ta.swma",
      "category": "indicators",
      "title": "Symmetrically weighted moving average",
      "definition": "Symmetrically weighted moving average of `source` over the last four bars, with the weights 1/6, 2/6, 2/6 and 1/6.",
      "lipi": {
        "symbols": [
          "ta.swma"
        ]
      }
    },
    {
      "id": "ta.tr",
      "category": "indicators",
      "title": "True range",
      "definition": "True range for the bar the script is on, taken from the chart's own bars.",
      "lipi": {
        "symbols": [
          "ta.tr"
        ]
      }
    },
    {
      "id": "ta.tsi",
      "category": "indicators",
      "title": "True strength index",
      "definition": "True Strength Index for `source`, smoothed by two lengths, `r` and `s`.",
      "lipi": {
        "symbols": [
          "ta.tsi"
        ]
      }
    },
    {
      "id": "ta.valuewhen",
      "category": "indicators",
      "title": "Value when a condition was true",
      "definition": "Reads `source` from the bar on which `condition` was true, going back as far as `occurrence` says.",
      "lipi": {
        "symbols": [
          "ta.valuewhen"
        ]
      }
    },
    {
      "id": "ta.variance",
      "category": "indicators",
      "title": "Variance",
      "definition": "Variance of `source` over `length` bars.",
      "lipi": {
        "symbols": [
          "ta.variance"
        ]
      }
    },
    {
      "id": "ta.vwap",
      "category": "indicators",
      "title": "Volume-weighted average price",
      "definition": "Volume-weighted average price built on `source`.",
      "lipi": {
        "symbols": [
          "ta.vwap"
        ]
      }
    },
    {
      "id": "ta.vwma",
      "category": "indicators",
      "title": "Volume-weighted moving average",
      "definition": "Volume-weighted moving average of `source` over `length` bars: bars that traded more count for more.",
      "lipi": {
        "symbols": [
          "ta.vwma"
        ]
      }
    },
    {
      "id": "ta.wma",
      "category": "indicators",
      "title": "Weighted moving average",
      "definition": "Weighted moving average of `source` over `length` bars.",
      "lipi": {
        "symbols": [
          "ta.wma"
        ],
        "note": "At this build the result does not follow standard WMA weights: a step from 0 to 1 settles at 1/length of the step."
      }
    },
    {
      "id": "ta.wpr",
      "category": "indicators",
      "title": "Williams %R",
      "definition": "Williams %R over `length` bars.",
      "lipi": {
        "symbols": [
          "ta.wpr"
        ]
      }
    },
    {
      "id": "ta.wvad",
      "category": "indicators",
      "title": "Williams variable accumulation/distribution",
      "definition": "Williams variable accumulation/distribution, calculated on the chart's own bars.",
      "lipi": {
        "symbols": [
          "ta.wvad"
        ]
      }
    }
  ],
  "mappings": [
    {
      "concept": "exec.bar-by-bar",
      "language": "mql4",
      "source": "present",
      "construct": "OnTick / OnCalculate",
      "signature": "void OnTick() | int OnCalculate(const int rates_total, const int prev_calculated, ...)",
      "relation": "different_semantics",
      "note": "Handler runs per incoming tick (Expert Advisor) or per calculate call (indicator), not once per bar; indicator code loops over bars itself using prev_calculated.",
      "differences": [
        {
          "axis": "bar_timing",
          "note": "No automatic oldest-first pass per bar; prev_calculated tells the loop where to start."
        }
      ],
      "evidence": {
        "url": "https://docs.mql4.com/basis/function/events",
        "fragment": "OnCalculate; OnTick",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "exec.bar-by-bar",
      "language": "mql5",
      "source": "present",
      "construct": "OnCalculate; OnTick",
      "signature": "int OnCalculate(const int rates_total, const int prev_calculated, const datetime &time[], const double &open[], const double &high[], const double &low[], const double &close[], const long &tick_volume[], const long &volume[], const int &spread[])",
      "relation": "different_semantics",
      "note": "The handler receives whole arrays per call, not one bar; your own loop starts at prev_calculated. Expert Advisors run OnTick once per tick.",
      "differences": [
        {
          "axis": "bar_timing",
          "note": "Calculate fires on new ticks or price-data changes; one call may cover many bars."
        },
        {
          "axis": "state_and_side_effects",
          "note": "Locals vanish after each call; globals persist between calls."
        }
      ],
      "evidence": {
        "url": "https://www.mql5.com/en/docs/event_handlers/oncalculate",
        "fragment": "OnCalculate rates_total / prev_calculated parameters",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "exec.bar-by-bar",
      "language": "ninjascript",
      "source": "present",
      "construct": "OnBarUpdate()",
      "signature": "protected override void OnBarUpdate()",
      "relation": "equivalent_with_caveat",
      "note": "A method override runs once per bar on history; live it follows the Calculate setting. One-time setup belongs in OnStateChange(), not here.",
      "differences": [
        {
          "axis": "bar_timing",
          "note": "Multi-series scripts get one call per Bars object; filter with BarsInProgress or logic runs several times per bar."
        }
      ],
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/onbarupdate.htm",
        "fragment": "OnBarUpdate() Definition and Notes (BarsInProgress)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "exec.bar-by-bar",
      "language": "pine",
      "source": "present",
      "construct": "script body runs once per bar; on the open realtime bar it reruns on every update (indicators)",
      "relation": "exact",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-docs/language/execution-model/",
        "fragment": "bar-by-bar-execution; #executions-on-realtime-bars",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "exec.bar-by-bar",
      "language": "thinkscript",
      "source": "present",
      "construct": "(implicit per-bar series evaluation)",
      "relation": "equivalent_with_caveat",
      "note": "Values are computed per bar from the first bar and the last bar is recalculated on updates; negative indexes can read later bars.",
      "differences": [
        {
          "axis": "bar_timing",
          "note": "A negative index lets a bar read later bars, so evaluation is not strictly oldest-first causal as in Lipi."
        }
      ],
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/tutorials/Basic/Chapter-1---Defining-Variables",
        "fragment": "recursive variables: cumulative volume starting from the first bar on chart",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "exec.declare-indicator",
      "language": "mql4",
      "source": "present",
      "construct": "#property indicator_chart_window / indicator_separate_window / indicator_buffers",
      "relation": "equivalent_with_caveat",
      "note": "No single declaration statement; #property lines set window and buffer count, and the OnCalculate handler marks the program as an indicator.",
      "evidence": {
        "url": "https://docs.mql4.com/basis/preprosessor/compilation",
        "fragment": "indicator_chart_window, indicator_buffers",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "exec.declare-indicator",
      "language": "mql5",
      "source": "present",
      "construct": "#property indicator_chart_window; #property indicator_separate_window; #property indicator_buffers; #property indicator_plots",
      "signature": "#property indicator_buffers N; #property indicator_plots N",
      "relation": "equivalent_with_caveat",
      "note": "No declaration call: the program is an indicator because it defines OnCalculate; display options and buffer counts come from #property lines.",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/basis/preprosessor/compilation",
        "fragment": "indicator_chart_window, indicator_buffers, indicator_plots rows",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "exec.declare-indicator",
      "language": "ninjascript",
      "source": "present",
      "construct": "class derived from Indicator, defaults set in OnStateChange() during State.SetDefaults",
      "signature": "protected override void OnStateChange() { if (State == State.SetDefaults) { ... } }",
      "relation": "equivalent_with_caveat",
      "note": "Declared as a C# class; defaults are pushed from OnStateChange. Display options are separate properties (IsOverlay, AddPlot, DrawOnPricePanel), not arguments of one call.",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/indicator.htm",
        "fragment": "Indicator configuration properties ... overridden in OnStateChange()",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "exec.declare-indicator",
      "language": "pine",
      "source": "present",
      "construct": "indicator()",
      "signature": "indicator(title, shorttitle, overlay, format, precision, scale, max_bars_back, timeframe, timeframe_gaps, explicit_plot_zorder, max_lines_count, max_labels_count, max_boxes_count, calc_bars_count, max_polylines_count, dynamic_requests, behind_chart) → void",
      "relation": "equivalent_with_caveat",
      "note": "Lipi's indicator takes fewer arguments: no timeframe, timeframe_gaps, max_bars_back, explicit_plot_zorder or dynamic_requests. Title is the only required argument in both.",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_indicator",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "exec.declare-indicator",
      "language": "thinkscript",
      "source": "present",
      "construct": "declare",
      "signature": "declare <supported_declaration_name>;",
      "relation": "equivalent_with_caveat",
      "note": "No title statement: declare only sets display or recalculation behaviour; a script is a study by being added on the Studies tab.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Reserved-Words/declare",
        "fragment": "declare <supported_declaration_name>",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "exec.declare-strategy",
      "language": "mql4",
      "source": "absent",
      "note": "No strategy declaration or simulation options in code; the #property list has no capital or commission setting. A strategy is an Expert Advisor with OnTick.",
      "evidence": {
        "url": "https://docs.mql4.com/basis/preprosessor/compilation",
        "fragment": "property table (no tester or strategy options)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "exec.declare-strategy",
      "language": "mql5",
      "source": "present",
      "construct": "Expert Advisor with OnTick",
      "signature": "void OnTick()",
      "relation": "equivalent_with_caveat",
      "note": "No strategy statement: an Expert Advisor is its own program type run per tick, and it sends real trade requests.",
      "differences": [
        {
          "axis": "state_and_side_effects",
          "note": "The same code trades live; the Strategy Tester only supplies simulated history and server."
        }
      ],
      "evidence": {
        "url": "https://www.mql5.com/en/docs/runtime/running",
        "fragment": "Program table: Expert Advisor; OnTick handler row",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "exec.declare-strategy",
      "language": "ninjascript",
      "source": "present",
      "construct": "class derived from Strategy, defaults set in OnStateChange() during State.SetDefaults",
      "signature": "protected override void OnStateChange() { if (State == State.SetDefaults) { ... } }",
      "relation": "equivalent_with_caveat",
      "note": "Simulation options are individual properties (EntriesPerDirection, EntryHandling, DefaultQuantity, Slippage, IncludeCommission) rather than arguments of one declaration call.",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/strategy.htm",
        "fragment": "In this section: EntriesPerDirection, DefaultQuantity, Slippage, IncludeCommission",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "exec.declare-strategy",
      "language": "pine",
      "source": "present",
      "construct": "strategy()",
      "signature": "strategy(title, shorttitle, overlay, format, precision, scale, pyramiding, calc_on_order_fills, calc_on_every_tick, max_bars_back, backtest_fill_limits_assumption, default_qty_type, default_qty_value, initial_capital, currency, slippage, commission_type, commission_value, process_orders_on_close, close_entries_rule, margin_long, margin_short, explicit_plot_zorder, max_lines_count, max_labels_count, max_boxes_count, calc_bars_count, risk_free_rate, use_bar_magnifier, fill_orders_on_standard_ohlc, max_polylines_count, dynamic_requests, behind_chart, calc_on_every_history_tick) → void",
      "relation": "equivalent_with_caveat",
      "note": "Lipi's strategy lacks slippage, currency, margin_long, margin_short, close_entries_rule, use_bar_magnifier and other Pine arguments, and several defaults differ (see strat.settings).",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_strategy",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "exec.declare-strategy",
      "language": "thinkscript",
      "source": "absent",
      "note": "No strategy statement: any script that calls AddOrder acts as a strategy and is added on the Strategies tab; settings live in the UI.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/tutorials/Basic/Chapter-7---Creating-Strategies",
        "fragment": "AddOrder function which will turn any technical indicator into trading strategy; Strategies tab",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "exec.overlay",
      "language": "mql4",
      "source": "present",
      "construct": "#property indicator_chart_window / #property indicator_separate_window",
      "relation": "equivalent_with_caveat",
      "note": "Two property names choose main chart or subwindow; subwindow scale is fixed with indicator_minimum and indicator_maximum.",
      "evidence": {
        "url": "https://docs.mql4.com/basis/preprosessor/compilation",
        "fragment": "indicator_chart_window, indicator_separate_window",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "exec.overlay",
      "language": "mql5",
      "source": "present",
      "construct": "#property indicator_chart_window; #property indicator_separate_window",
      "relation": "equivalent_with_caveat",
      "note": "Two separate properties instead of one boolean; a separate window can also get a fixed height and minimum/maximum scale.",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/basis/preprosessor/compilation",
        "fragment": "indicator_chart_window, indicator_separate_window, indicator_height, indicator_minimum rows",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "exec.overlay",
      "language": "ninjascript",
      "source": "present",
      "construct": "IsOverlay",
      "signature": "IsOverlay = true;",
      "relation": "equivalent_with_caveat",
      "note": "Same on/off flag with default false; set only in State.SetDefaults. True also allows use as a SuperDOM indicator.",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/isoverlay.htm",
        "fragment": "IsOverlay Property Value",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "exec.overlay",
      "language": "pine",
      "source": "present",
      "construct": "overlay argument of indicator() and strategy()",
      "relation": "exact",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_indicator (overlay)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "exec.overlay",
      "language": "thinkscript",
      "source": "present",
      "construct": "declare lower; declare upper; declare on_volume;",
      "signature": "declare lower;",
      "relation": "equivalent_with_caveat",
      "note": "Default is the price chart (upper), the opposite of Lipi's default own pane; lower gives a separate pane and on_volume the volume pane.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Declarations/upper",
        "fragment": "applied by default to all studies not containing the lower and on_volume declarations",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "exec.every-tick",
      "language": "mql4",
      "source": "present",
      "construct": "OnTick / OnCalculate",
      "relation": "different_semantics",
      "note": "Always recalculates on every tick; there is no close-only mode. To act once per bar, compare Time[0] with a saved bar time.",
      "differences": [
        {
          "axis": "bar_timing",
          "note": "No setting to wait for bar close; every price update runs the handler."
        }
      ],
      "evidence": {
        "url": "https://docs.mql4.com/basis/function/events",
        "fragment": "OnTick; OnCalculate",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "exec.every-tick",
      "language": "mql5",
      "source": "absent",
      "note": "No switch: indicators recalculate when new ticks arrive and Expert Advisors run OnTick per tick; bar-close-only logic needs your own new-bar test.",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/runtime/event_fire",
        "fragment": "Calculate event; NewTick event",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "exec.every-tick",
      "language": "ninjascript",
      "source": "present",
      "construct": "Calculate",
      "signature": "Calculate = Calculate.OnBarClose | OnEachTick | OnPriceChange",
      "relation": "equivalent_with_caveat",
      "note": "Default is OnBarClose, whereas Lipi indicators default to every tick. OnPriceChange is a third mode. History ignores it unless Tick Replay is used.",
      "differences": [
        {
          "axis": "bar_timing",
          "note": "OnPriceChange skips repeat prices and can miss volume updates; Lipi has no such mode."
        }
      ],
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/calculate.htm",
        "fragment": "Calculate Property Value and Notes",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "exec.every-tick",
      "language": "pine",
      "source": "present",
      "construct": "indicator() (always reruns on each realtime update); strategy(calc_on_every_tick)",
      "relation": "equivalent_with_caveat",
      "note": "A Pine indicator has no per-tick switch and always reruns on every update; gate with barstate.isconfirmed. Only strategy() takes calc_on_every_tick, default false.",
      "differences": [
        {
          "axis": "bar_timing",
          "note": "Lipi's indicator accepts calc_on_every_tick=false to skip unconfirmed bars; a Pine indicator cannot opt out of per-tick execution."
        }
      ],
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-docs/language/execution-model/",
        "fragment": "executions-on-realtime-bars",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "exec.every-tick",
      "language": "thinkscript",
      "source": "present",
      "construct": "declare once_per_bar",
      "signature": "declare once_per_bar;",
      "relation": "equivalent_with_caveat",
      "note": "Default recalculates the last bar on every tick; declare once_per_bar restricts that to once per bar, without saying whether at open or close.",
      "differences": [
        {
          "axis": "bar_timing",
          "note": "The docs do not say when in the bar the single recalculation happens; Lipi's off mode runs the script at bar close."
        }
      ],
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Declarations/once-per-bar",
        "fragment": "By default, last study values are recalculated after each tick",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "exec.version-header",
      "language": "mql4",
      "source": "present",
      "construct": "#property strict",
      "relation": "different_semantics",
      "note": "strict switches on stricter compilation; #property version is only the program's own version label, not a language-version selector.",
      "evidence": {
        "url": "https://docs.mql4.com/basis/preprosessor/compilation",
        "fragment": "strict; version",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "exec.version-header",
      "language": "mql5",
      "source": "absent",
      "note": "#property version only labels the program (maximum 31 characters); no property selects a language version.",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/basis/preprosessor/compilation",
        "fragment": "version row of the #property table",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "exec.version-header",
      "language": "ninjascript",
      "source": "absent",
      "note": "No per-script language-version directive appears in the language reference index; scripts follow the installed NinjaTrader release.",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/alphabetical_reference.htm",
        "fragment": "NinjaScript Language Reference alphabetical list (no version directive entry)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "exec.version-header",
      "language": "pine",
      "source": "present",
      "construct": "//@version=6",
      "relation": "equivalent_with_caveat",
      "note": "Pine's directive is //@version=N and Lipi's is //@lipi=2; the numbers are unrelated. Pine allows it anywhere but recommends the top line.",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "an_@version=",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "exec.version-header",
      "language": "thinkscript",
      "source": "absent",
      "note": "The declarations list has no version or dialect selector; scripts carry no version line.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Declarations",
        "fragment": "Declarations section contains the following declarations (on_volume, once_per_bar, lower, upper, ...)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "types.basic",
      "language": "mql4",
      "source": "present",
      "construct": "int, double, bool, string, color (also char, short, long, float, datetime)",
      "relation": "equivalent_with_caveat",
      "note": "color is a 4-byte integer holding blue-green-red bytes with no alpha; datetime is an integer count of seconds since 1970.",
      "differences": [
        {
          "axis": "numeric_types",
          "note": "color has no alpha byte; datetime is whole seconds, not milliseconds."
        }
      ],
      "evidence": {
        "url": "https://docs.mql4.com/basis/types/integer/color",
        "fragment": "Color Type",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "types.basic",
      "language": "mql5",
      "source": "present",
      "construct": "int, long, double, float, bool, string, color, datetime",
      "relation": "equivalent_with_caveat",
      "note": "Sized integers (int 32-bit, long 64-bit), float and double, and a separate datetime type; color carries no alpha channel.",
      "differences": [
        {
          "axis": "numeric_types",
          "note": "int is 32-bit; large counts and volumes need long."
        }
      ],
      "evidence": {
        "url": "https://www.mql5.com/en/docs/basis/types/integer/integertypes",
        "fragment": "Char, Short, Int and Long Types table of sizes and ranges",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "types.basic",
      "language": "ninjascript",
      "source": "present",
      "construct": "int, double, bool, string, Brush",
      "signature": "double myDouble = 2.5;",
      "relation": "equivalent_with_caveat",
      "note": "Statically typed C#: float maps to double, text to string, and colours are WPF Brush objects (Brushes.Red), not a colour value.",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/basic_syntax.htm",
        "fragment": "Variables and Value Types",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "types.basic",
      "language": "pine",
      "source": "present",
      "construct": "int, float, bool, string, color",
      "relation": "equivalent_with_caveat",
      "note": "In v6 a bool is never na and numbers no longer cast implicitly to bool; Lipi accepts nonzero numbers where a bool is expected.",
      "differences": [
        {
          "axis": "numeric_types",
          "note": "Pine v6 migration notes remove implicit number-to-bool casts; Lipi conditions and typed bool declarations accept numbers."
        }
      ],
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-docs/migration-guides/to-pine-version-6/",
        "fragment": "explicit-bool-casting",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "types.basic",
      "language": "thinkscript",
      "source": "present",
      "construct": "int, double, boolean, String, CustomColor",
      "relation": "equivalent_with_caveat",
      "note": "Types are inferred, never written on declarations. float is called double, colour is CustomColor, and booleans convert to numbers freely.",
      "differences": [
        {
          "axis": "numeric_types",
          "note": "yes/no convert to 1.0/0.0 and back; zero and NaN count as false, so booleans act as numbers."
        }
      ],
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Data-Types/Data-Conversion",
        "fragment": "boolean: 0 (0.0) and Double.NaN are converted to no (false), other numbers to yes (true)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "types.missing-value",
      "language": "mql4",
      "source": "present",
      "construct": "EMPTY_VALUE, MathIsValidNumber",
      "signature": "bool MathIsValidNumber(double number)",
      "relation": "different_semantics",
      "note": "EMPTY_VALUE is an ordinary integer sentinel (2147483647) that does not propagate through arithmetic; there is no nz or fixnan, test with ==.",
      "differences": [
        {
          "axis": "warmup_and_na",
          "note": "Leading bars hold the sentinel, not a missing marker; calculations on it give garbage rather than missing."
        }
      ],
      "evidence": {
        "url": "https://docs.mql4.com/constants/namedconstants/otherconstants",
        "fragment": "EMPTY_VALUE",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "types.missing-value",
      "language": "mql5",
      "source": "present",
      "construct": "EMPTY_VALUE; MathIsValidNumber; PLOT_EMPTY_VALUE",
      "signature": "bool MathIsValidNumber(double number)",
      "relation": "different_semantics",
      "note": "No na literal, nz or fixnan: empty plot slots hold EMPTY_VALUE (DBL_MAX), and invalid reals (NaN) are tested with MathIsValidNumber.",
      "differences": [
        {
          "axis": "warmup_and_na",
          "note": "EMPTY_VALUE is an ordinary number (DBL_MAX), not a propagating missing value."
        }
      ],
      "evidence": {
        "url": "https://www.mql5.com/en/docs/constants/namedconstants/otherconstants",
        "fragment": "EMPTY_VALUE: empty value in an indicator buffer (DBL_MAX)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "types.missing-value",
      "language": "ninjascript",
      "source": "present",
      "construct": "ISeries<T>.IsValidDataPoint(barsAgo)",
      "signature": "bool IsValidDataPoint(int barsAgo)",
      "relation": "different_semantics",
      "note": "No na value is documented. IsValidDataPoint(barsAgo) reports whether a slot was set; it works only on infinite-lookback series.",
      "differences": [
        {
          "axis": "warmup_and_na",
          "note": "An unset slot reports false; the page does not say what value a read returns, so test first. A 256-lookback series throws."
        }
      ],
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/isvaliddatapoint.htm",
        "fragment": "IsValidDataPoint() Definition and Notes",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "types.missing-value",
      "language": "pine",
      "source": "present",
      "construct": "na, na(), nz(), fixnan()",
      "signature": "nz(source, replacement) → series float",
      "relation": "equivalent_with_caveat",
      "note": "nz fills a missing color with transparent #00000000, Lipi with #483D8B. In v6 na(), nz() and fixnan() reject bool; Lipi's nz accepts it.",
      "differences": [
        {
          "axis": "warmup_and_na",
          "note": "Default replacement for a missing color differs: Pine #00000000 (transparent), Lipi #483D8B."
        }
      ],
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_nz; fun_na; fun_fixnan",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "types.missing-value",
      "language": "thinkscript",
      "source": "present",
      "construct": "Double.NaN, IsNaN()",
      "signature": "IsNaN(double value)",
      "relation": "composite",
      "note": "No nz or fixnan: replace NaN with if IsNaN(x) then 0 else x, and carry the last value with CompoundValue and a self-reference.",
      "differences": [
        {
          "axis": "warmup_and_na",
          "note": "NaN spreads through arithmetic and recursion, and an if-expression on a NaN condition returns NaN; comparing with Double.NaN never works."
        }
      ],
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/tutorials/Appendices/Appendix-D---Using-NaN-and-Infinity-Constants",
        "fragment": "NaN plus any number is not a number; use the isNan() function",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "types.qualifiers",
      "language": "mql4",
      "source": "present",
      "construct": "const",
      "relation": "different_semantics",
      "note": "const only forbids reassignment after initialisation; there is no compile-time, per-script or per-bar evaluation class like const, simple, series.",
      "evidence": {
        "url": "https://docs.mql4.com/basis/variables",
        "fragment": "Access Specifiers (const)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "types.qualifiers",
      "language": "mql5",
      "source": "present",
      "construct": "const",
      "relation": "different_semantics",
      "note": "const only forbids changing a variable at run time; simple and series qualifiers do not exist.",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/basis/variables",
        "fragment": "const specifier declares a variable as a constant",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "types.qualifiers",
      "language": "ninjascript",
      "source": "absent",
      "note": "No const, simple or series keywords; every value is an ordinary C# value. Per-bar history exists only through Series<T> and ISeries objects.",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/basic_syntax.htm",
        "fragment": "Variables and Value Types",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "types.qualifiers",
      "language": "pine",
      "source": "present",
      "construct": "const, simple, series keywords (input is implicit)",
      "relation": "equivalent_with_caveat",
      "note": "Pine accepts qualifier keywords on variable declarations (const float x = 1) and parameters; Lipi only on parameters. The hierarchy matches.",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-docs/language/type-system/",
        "fragment": "qualifiers",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "types.qualifiers",
      "language": "thinkscript",
      "source": "absent",
      "note": "No qualifier keywords exist; the type is inferred from assignment and values are per-bar series.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Data-Types",
        "fragment": "The data type for variables is automatically defined after assignment",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "types.conversion",
      "language": "mql4",
      "source": "present",
      "construct": "(int)x, int(x), DoubleToString, StringToDouble, StringToInteger",
      "relation": "equivalent_with_caveat",
      "note": "Casting a decimal to int cuts off the fraction instead of rounding; text conversion uses named functions, and string + number joins automatically.",
      "differences": [
        {
          "axis": "numeric_types",
          "note": "Decimal to int truncates; out-of-range casts wrap around silently."
        }
      ],
      "evidence": {
        "url": "https://docs.mql4.com/basis/types/casting",
        "fragment": "Casting Numeric Types",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "types.conversion",
      "language": "mql5",
      "source": "present",
      "construct": "(int)x; int(x); DoubleToString; IntegerToString; StringToDouble; StringToInteger",
      "signature": "var_1 = (type)var_2; var_1 = type(var_2);",
      "relation": "equivalent_with_caveat",
      "note": "Casting a real to an integer drops the fraction; MathRound rounds instead. Text conversion uses named functions such as DoubleToString and StringToDouble.",
      "differences": [
        {
          "axis": "numeric_types",
          "note": "Mixed operands are promoted to the higher-priority type; string outranks numbers."
        }
      ],
      "evidence": {
        "url": "https://www.mql5.com/en/docs/basis/types/casting",
        "fragment": "Typecasting: (type)var and type(var) forms; real to integer conversion",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "types.conversion",
      "language": "ninjascript",
      "source": "present",
      "construct": "C# casts and .ToString()",
      "signature": "myInteger.ToString()",
      "relation": "equivalent_with_caveat",
      "note": "Plain C# conversions; the closest page shows ToString(). Casting and parsing are standard C#, with no str.tonumber-style helper documented.",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/basic_syntax.htm",
        "fragment": "Print(myInteger.ToString()) in Operators examples",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "types.conversion",
      "language": "pine",
      "source": "present",
      "construct": "int(), float(), bool(), str.tostring(), str.tonumber()",
      "relation": "equivalent_with_caveat",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-docs/language/type-system/",
        "fragment": "type-casting",
        "accessed": "2026-11-01"
      },
      "verified": "documented",
      "note": "Pine's bool(na) is false; Lipi's bool(na) is na, so test na() first. int() truncates toward zero in both."
    },
    {
      "concept": "types.conversion",
      "language": "thinkscript",
      "source": "present",
      "construct": "AsText, implicit conversion",
      "signature": "AsText(double value, String format)",
      "relation": "composite",
      "note": "No cast functions: numbers and booleans convert implicitly, ints truncate toward zero; AsText or + builds text; docs list no text-to-number function.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Data-Types/Data-Conversion",
        "fragment": "int: yes is converted to 1, no to 0. Non-integer numbers are rounded towards zero",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "decl.variable",
      "language": "mql4",
      "source": "present",
      "construct": "type name = value;",
      "relation": "equivalent_with_caveat",
      "note": "A type is required at declaration and = both declares and reassigns; there is no separate := reassign operator.",
      "evidence": {
        "url": "https://docs.mql4.com/basis/variables",
        "fragment": "To declare a variable, you must specify its type",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "decl.variable",
      "language": "mql5",
      "source": "present",
      "construct": "type name = value;",
      "relation": "equivalent_with_caveat",
      "note": "The type is mandatory and a variable must be declared before use; locals are rebuilt on every function call, globals live for the whole program.",
      "differences": [
        {
          "axis": "state_and_side_effects",
          "note": "Globals keep values across OnCalculate calls (ticks); Lipi variables are re-declared on every bar."
        }
      ],
      "evidence": {
        "url": "https://www.mql5.com/en/docs/basis/variables/global",
        "fragment": "Global variables initialized once before OnInit and persist while the program runs",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "decl.variable",
      "language": "ninjascript",
      "source": "present",
      "construct": "type name = value;",
      "signature": "double myDouble = 2.5;",
      "relation": "equivalent_with_caveat",
      "note": "Needs an explicit type; one '=' both declares and reassigns, with no ':=' split. Locals vanish after each method call.",
      "differences": [
        {
          "axis": "state_and_side_effects",
          "note": "Only class-level fields keep values between bars; method locals are rebuilt on every OnBarUpdate call."
        }
      ],
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/basic_syntax.htm",
        "fragment": "Declaring Variables",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "decl.variable",
      "language": "pine",
      "source": "present",
      "construct": "name = value; name := value; var",
      "relation": "exact",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-docs/language/operators/",
        "fragment": "-assignment-operator; #-reassignment-operator",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "decl.variable",
      "language": "thinkscript",
      "source": "present",
      "construct": "def",
      "signature": "def <name> = <expr>; | def <name>; <name> = <expr>;",
      "relation": "equivalent_with_caveat",
      "note": "def values are per-bar series; a later assignment fills the definition inside branches, not a mutable update; self-reference starts from 0.",
      "differences": [
        {
          "axis": "warmup_and_na",
          "note": "A self-referencing def starts from 0, not na."
        },
        {
          "axis": "state_and_side_effects",
          "note": "Assignment defines the series for the bar; there is no rebinding with :=."
        }
      ],
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Reserved-Words/def",
        "fragment": "def <variable_name>=<expression>; Example 2. Recursive usage",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "decl.enum",
      "language": "mql4",
      "source": "present",
      "construct": "enum",
      "relation": "equivalent_with_caveat",
      "note": "Members are integers that can be assigned values; // comments on members become dropdown labels when the enum is used as an input.",
      "evidence": {
        "url": "https://docs.mql4.com/basis/variables/inputvariables",
        "fragment": "Enumerations as input Parameters",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "decl.enum",
      "language": "mql5",
      "source": "present",
      "construct": "enum",
      "signature": "enum name { member = value, member2 };",
      "relation": "equivalent_with_caveat",
      "note": "Members are named integers, numbered from 0 unless set; there are no title strings, though member comments label the input dropdown.",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/basis/types/integer/enumeration",
        "fragment": "Enumerations: enum name { list of values }",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "decl.enum",
      "language": "ninjascript",
      "source": "present",
      "construct": "enum (C#) used as a public property type",
      "relation": "equivalent_with_caveat",
      "note": "Plain C# enum; as a public property it presents the user with hard-coded choices.",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/creating_a_user-defined_parame.htm",
        "fragment": "Creating a user-defined parameter type (enum)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "decl.enum",
      "language": "pine",
      "source": "present",
      "construct": "enum",
      "relation": "equivalent_with_caveat",
      "note": "Pine lists enum members as indented lines without braces, and allows str.tostring on enum members, which Lipi rejects.",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-docs/language/type-system/",
        "fragment": "enum-types",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "decl.enum",
      "language": "thinkscript",
      "source": "present",
      "construct": "def <name> = {default a, b, c}",
      "relation": "equivalent_with_caveat",
      "note": "Values are strings, the enumeration belongs to one variable (no reusable named type), allows one assignment statement, and two enumerations are not interchangeable.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Reserved-Words/def",
        "fragment": "Example 3. Non-recursive and recursive enumerations",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "decl.user-type",
      "language": "mql4",
      "source": "present",
      "construct": "struct, class",
      "relation": "equivalent_with_caveat",
      "note": "Fields declared in struct or class; variables of these types are passed by reference, and class objects can be created with new.",
      "evidence": {
        "url": "https://docs.mql4.com/basis/types/classes",
        "fragment": "struct structure_name{elements_description}",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "decl.user-type",
      "language": "mql5",
      "source": "present",
      "construct": "struct; class",
      "signature": "struct name { members }; class name { access: members };",
      "relation": "equivalent_with_caveat",
      "note": "Members accessed with a dot; both can hold methods, constructors and destructors; new works for classes only, not structures.",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/basis/types/classes",
        "fragment": "Structures, Classes and Interfaces",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "decl.user-type",
      "language": "ninjascript",
      "source": "present",
      "construct": "class or struct (C#)",
      "relation": "equivalent_with_caveat",
      "note": "Ordinary C# classes with fields and methods, created with new. The help guide shows classes only in passing; it has no tutorial for them.",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/considerations_for_compiled_assemblies.htm",
        "fragment": "public static class MyDrawCustom",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "decl.user-type",
      "language": "pine",
      "source": "present",
      "construct": "type",
      "relation": "equivalent_with_caveat",
      "note": "Pine type bodies are indented fields built with Name.new(); a field can be declared varip. Lipi uses braces and static for persistence.",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "kw_type",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "decl.user-type",
      "language": "thinkscript",
      "source": "absent",
      "note": "Data types are the fixed built-in list; scripts cannot declare their own object types.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Data-Types",
        "fragment": "full list of available data types: Any, boolean, CustomColor, double, IDataHolder, int, String, Symbol",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "decl.tuple",
      "language": "mql4",
      "source": "absent",
      "note": "A function returns one value; extra results go back through reference (&) parameters or a struct.",
      "evidence": {
        "url": "https://docs.mql4.com/basis/function/parameterpass",
        "fragment": "pass by reference",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "decl.tuple",
      "language": "mql5",
      "source": "absent",
      "note": "A function returns one value and cannot return arrays or class objects; pass extra results out through reference (&) parameters or a simple struct.",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/basis/function",
        "fragment": "return operator: what can be returned",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "decl.tuple",
      "language": "ninjascript",
      "source": "present",
      "construct": "out parameters (C# tuples also available)",
      "signature": "GetMaximumVolume(bool? askVolume, out double price)",
      "relation": "equivalent_with_caveat",
      "note": "NinjaScript APIs return extra values through out parameters. Tuple returns are plain C#; the help guide documents no unpacking form.",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/order_flow_volumetric_bars2.htm",
        "fragment": "GetMaximumVolume(bool? askVolume, out double price)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "decl.tuple",
      "language": "pine",
      "source": "present",
      "construct": "[a, b] = f()",
      "relation": "exact",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-docs/language/type-system/",
        "fragment": "tuples",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "decl.tuple",
      "language": "thinkscript",
      "source": "present",
      "construct": "script with several plots, read as name(args).plotName",
      "relation": "equivalent_with_caveat",
      "note": "A script block can expose several plots, read as name(args).plot; no multi-value assignment form is documented.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/tutorials/Advanced/Chapter-13---Referencing-Other-Data",
        "fragment": "plot EMAOsc = avg(10).EMA - avg(20).EMA",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "history.previous-value",
      "language": "mql4",
      "source": "present",
      "construct": "Close[n], iClose(symbol, timeframe, shift)",
      "relation": "equivalent_with_caveat",
      "note": "Price series use shift 0 as current bar like Lipi. Own computed values need a buffer array; buffers index oldest-first unless ArraySetAsSeries flips them.",
      "differences": [
        {
          "axis": "history_indexing",
          "note": "Indicator buffer arrays count from the oldest bar by default, opposite to price series."
        }
      ],
      "evidence": {
        "url": "https://docs.mql4.com/predefined/close",
        "fragment": "Series array elements are indexed in the reverse order",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "history.previous-value",
      "language": "mql5",
      "source": "present",
      "construct": "array[index]; ArraySetAsSeries",
      "signature": "bool ArraySetAsSeries(const void& array[], bool flag)",
      "relation": "different_semantics",
      "note": "Default arrays and buffers count from the oldest bar, so n bars back is i-n; series-flagged arrays count from the newest, so it is i+n.",
      "differences": [
        {
          "axis": "history_indexing",
          "note": "Index 0 is the oldest bar by default but the newest in timeseries functions such as iClose and CopyRates."
        }
      ],
      "evidence": {
        "url": "https://www.mql5.com/en/docs/series/bufferdirection",
        "fragment": "Indexing Direction in Arrays, Buffers and Timeseries",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "history.previous-value",
      "language": "ninjascript",
      "source": "present",
      "construct": "Close[barsAgo], Series<T>[barsAgo]",
      "signature": "ISeries<double>[int barsAgo]",
      "relation": "equivalent_with_caveat",
      "note": "Same direction as Lipi x[n]: 0 is the current bar, 1 the previous one. Reading before the first bar throws, so guard with CurrentBar.",
      "differences": [
        {
          "axis": "warmup_and_na",
          "note": "Close[1] on the first bar raises an out-of-range error; Lipi gives na."
        },
        {
          "axis": "history_indexing",
          "note": "Custom Series keep 256 values by default; Lipi allows 500."
        }
      ],
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/make_sure_you_have_enough_bars.htm",
        "fragment": "Close[1] does not yet exist on the first bar; CurrentBar<1 guard",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "history.previous-value",
      "language": "pine",
      "source": "present",
      "construct": "[] history-referencing operator",
      "relation": "equivalent_with_caveat",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-docs/language/operators/",
        "fragment": "-history-referencing-operator; op_[]",
        "accessed": "2026-11-01"
      },
      "verified": "documented",
      "note": "Pine buffers can reach back up to 5000 bars; Lipi stops the script at run time when the offset exceeds 500."
    },
    {
      "concept": "history.previous-value",
      "language": "thinkscript",
      "source": "present",
      "construct": "x[n]; x from n bars ago",
      "relation": "equivalent_with_caveat",
      "note": "Positive index is the past as in Lipi, but a negative index reads future bars, which Lipi rejects, so look-ahead scripts cannot be converted.",
      "differences": [
        {
          "axis": "history_indexing",
          "note": "Negative index means a later bar; Lipi accepts only 0 or more."
        },
        {
          "axis": "warmup_and_na",
          "note": "All expressions in a study share the highest past offset, so early bars start later than a single formula implies."
        }
      ],
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Operators/Indexing",
        "fragment": "positive values of the shift represent the values in the past, the negative shift values represent the values in the future",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "history.bar-index",
      "language": "mql4",
      "source": "present",
      "construct": "Bars, shift index",
      "relation": "different_semantics",
      "note": "Index counts from the newest bar (0) to the oldest (Bars-1); there is no counter from the first bar, so bar number is Bars-1-shift.",
      "differences": [
        {
          "axis": "history_indexing",
          "note": "Direction reversed: the current bar is 0 and bars grow older with the index."
        }
      ],
      "evidence": {
        "url": "https://docs.mql4.com/predefined/close",
        "fragment": "oldest bar ... indexed as Bars-1",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "history.bar-index",
      "language": "mql5",
      "source": "present",
      "construct": "loop index i over rates_total in OnCalculate",
      "relation": "equivalent_with_caveat",
      "note": "No bar_index variable: you loop yourself, and index 0 is the first bar only while arrays keep the default direction.",
      "differences": [
        {
          "axis": "history_indexing",
          "note": "After ArraySetAsSeries(true) the same index counts from the newest bar instead."
        }
      ],
      "evidence": {
        "url": "https://www.mql5.com/en/docs/series/bufferdirection",
        "fragment": "default indexing left to right, first element index 0",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "history.bar-index",
      "language": "ninjascript",
      "source": "present",
      "construct": "CurrentBar",
      "relation": "exact",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/currentbar.htm",
        "fragment": "CurrentBar Definition (first bar is 0)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "history.bar-index",
      "language": "pine",
      "source": "present",
      "construct": "bar_index",
      "relation": "exact",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "var_bar_index",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "history.bar-index",
      "language": "thinkscript",
      "source": "present",
      "construct": "BarNumber()",
      "signature": "BarNumber()",
      "relation": "equivalent_with_caveat",
      "note": "A function call, not a variable. The reference states no first-bar value; Lipi's bar_index is 0 on the first bar.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Functions/Others/BarNumber",
        "fragment": "Returns the current bar number",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "history.last-bar",
      "language": "mql4",
      "source": "present",
      "construct": "shift 0 (Close[0], Time[0])",
      "relation": "equivalent_with_caveat",
      "note": "The last bar is shift 0; indicator loops test i==0 or start from a limit derived from prev_calculated. There is no islast flag.",
      "evidence": {
        "url": "https://docs.mql4.com/predefined/close",
        "fragment": "The current bar ... is indexed as 0",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "history.last-bar",
      "language": "mql5",
      "source": "present",
      "construct": "rates_total-1 (default arrays); index 0 (series arrays)",
      "relation": "equivalent_with_caveat",
      "note": "No flag exists: the last bar is the final element in default arrays and index 0 in series-flagged arrays or timeseries functions.",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/series/bufferdirection",
        "fragment": "timeseries element with index 0 contains the latest quote",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "history.last-bar",
      "language": "ninjascript",
      "source": "present",
      "construct": "CurrentBar == Count - 1",
      "signature": "CurrentBar == Count - 1",
      "relation": "equivalent_with_caveat",
      "note": "No islast flag; compare CurrentBar with Count - 1. Count can run ahead of CurrentBar because ticks arrive on other threads.",
      "differences": [
        {
          "axis": "bar_timing",
          "note": "CurrentBar is only guaranteed to be at most Count - 1, so equality is not guaranteed in real time."
        }
      ],
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/count.htm",
        "fragment": "Tip: CurrentBar value is guaranteed to be <= Count - 1",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "history.last-bar",
      "language": "pine",
      "source": "present",
      "construct": "last_bar_index, barstate.islast",
      "relation": "exact",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "var_last_bar_index; var_barstate.islast",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "history.last-bar",
      "language": "thinkscript",
      "source": "present",
      "construct": "!IsNaN(close) and IsNaN(close[-1])",
      "relation": "composite",
      "note": "No built-in last-bar flag: the documented idiom tests that the next bar's close is NaN, which uses a future index; map to barstate.islast.",
      "differences": [
        {
          "axis": "bar_timing",
          "note": "The idiom relies on a look-ahead index; the HighestAll alternative forces once-per-bar recalculation."
        }
      ],
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/tutorials/Advanced/Chapter-12---Past-Offset-and-Prefetch",
        "fragment": "def isLastBar = !IsNaN(close) and IsNaN(close[-1]);",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "history.lookback-limit",
      "language": "mql4",
      "source": "present",
      "construct": "TERMINAL_MAXBARS",
      "relation": "different_semantics",
      "note": "No fixed 500-bar cap; reach is bounded by the number of bars the chart holds, a terminal setting read with TerminalInfoInteger.",
      "differences": [
        {
          "axis": "history_indexing",
          "note": "Lookback depth is limited by loaded history size, not by a small constant."
        }
      ],
      "evidence": {
        "url": "https://docs.mql4.com/constants/environment_state/terminalstatus",
        "fragment": "TERMINAL_MAXBARS",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "history.lookback-limit",
      "language": "mql5",
      "source": "present",
      "construct": "TERMINAL_MAXBARS (Max bars in chart)",
      "relation": "equivalent_with_caveat",
      "note": "Reach is bounded by the bars loaded for the chart (terminal setting), not a fixed 500; OnCalculate arrays hold all loaded bars.",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/series/timeseries_access",
        "fragment": "Max bars in chart parameter and TERMINAL_MAXBARS",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "history.lookback-limit",
      "language": "ninjascript",
      "source": "present",
      "construct": "MaximumBarsLookBack",
      "signature": "new Series<double>(this, MaximumBarsLookBack.Infinite)",
      "relation": "equivalent_with_caveat",
      "note": "Custom Series default to the last 256 values (ring buffer); Infinite lifts it. Price and plot series are always unlimited, unlike Lipi's flat 500.",
      "differences": [
        {
          "axis": "history_indexing",
          "note": "Beyond 256 on a custom series, the oldest values are overwritten rather than raising an error."
        }
      ],
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/maximumbarslookback.htm",
        "fragment": "MaximumBarsLookBack.TwoHundredFiftySix and Infinite",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "history.lookback-limit",
      "language": "pine",
      "source": "present",
      "construct": "historical buffer (auto-sized); max_bars_back() and the max_bars_back argument",
      "relation": "equivalent_with_caveat",
      "note": "Pine sizes buffers automatically, up to 5000 bars (10000 for open, high, low, close, time), and max_bars_back() raises them. Lipi has a fixed 500-bar limit.",
      "differences": [
        {
          "axis": "history_indexing",
          "note": "Pine reaches 5000 bars back for most series and 10000 for price series and time; Lipi stops at 500."
        }
      ],
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-docs/writing/limitations/",
        "fragment": "maximum-bars-back",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "history.lookback-limit",
      "language": "thinkscript",
      "source": "unresolved",
      "note": "The reference states no maximum look-back distance; it only describes past-offset initialisation, so Lipi's 500-bar cap has no documented counterpart.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/tutorials/Advanced/Chapter-12---Past-Offset-and-Prefetch",
        "fragment": "Past Offset",
        "accessed": "2026-11-01"
      },
      "verified": "unresolved"
    },
    {
      "concept": "history.call-every-bar",
      "language": "mql4",
      "source": "present",
      "construct": "iMA(symbol, timeframe, ma_period, ma_shift, ma_method, applied_price, shift)",
      "signature": "double iMA(string symbol, int timeframe, int ma_period, int ma_shift, int ma_method, int applied_price, int shift)",
      "relation": "different_semantics",
      "note": "Indicator functions read history by shift and keep no per-call-site state, so skipping bars changes nothing. ma_shift offsets the line; shift picks the bar.",
      "differences": [
        {
          "axis": "state_and_side_effects",
          "note": "Stateless recomputation from history; conditional calls are safe."
        }
      ],
      "evidence": {
        "url": "https://docs.mql4.com/indicators/ima",
        "fragment": "iMA signature and parameters",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "history.call-every-bar",
      "language": "mql5",
      "source": "absent",
      "note": "No per-call-site history exists: indicator values come from a handle (iMA) read with CopyBuffer, so skipping bars in your own loop breaks nothing.",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/indicators/ima",
        "fragment": "iMA returns a handle; INVALID_HANDLE on failure",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "history.call-every-bar",
      "language": "ninjascript",
      "source": "present",
      "construct": "Update()",
      "signature": "Update()",
      "relation": "different_semantics",
      "note": "Hosted indicators update when the host accesses them; Update() catches one up to the current bar. Lipi history functions need a call every bar.",
      "differences": [
        {
          "axis": "state_and_side_effects",
          "note": "Hoist indicator calls made only inside a branch to top level when converting to Lipi."
        }
      ],
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/update.htm",
        "fragment": "Update() Definition (indicators embedded in a strategy calculate only when called)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "history.call-every-bar",
      "language": "pine",
      "source": "present",
      "construct": "ta.sma(), ta.ema() called in the global scope",
      "relation": "exact",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-docs/language/execution-model/",
        "fragment": "time-series-in-scopes",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "history.call-every-bar",
      "language": "thinkscript",
      "source": "unresolved",
      "note": "An if-expression always computes both branches, an if-statement only the taken one; docs do not say how history functions behave in a skipped branch.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Reserved-Words/if",
        "fragment": "while the if-expression always calculates both then and else branches, the if-statement only calculates the branch defined by whether the condition is true",
        "accessed": "2026-11-01"
      },
      "verified": "unresolved"
    },
    {
      "concept": "state.persistent",
      "language": "mql4",
      "source": "present",
      "construct": "static and global variables",
      "relation": "equivalent_with_caveat",
      "note": "static and global variables keep values between handler calls and are initialised once at load; every tick updates them, with no rollback to bar close.",
      "differences": [
        {
          "axis": "state_and_side_effects",
          "note": "No commit-on-close: tick writes stay, unlike Lipi static on a forming bar."
        }
      ],
      "evidence": {
        "url": "https://docs.mql4.com/basis/variables/static",
        "fragment": "Static variables exist from the moment of program execution",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "state.persistent",
      "language": "mql5",
      "source": "present",
      "construct": "static (local variable); global variables",
      "relation": "different_semantics",
      "note": "static and globals keep every change from every call, including repeated calls on the forming bar; nothing rolls back at bar close.",
      "differences": [
        {
          "axis": "state_and_side_effects",
          "note": "Initialised once; the value persists across all later calls, not only confirmed bars."
        }
      ],
      "evidence": {
        "url": "https://www.mql5.com/en/docs/basis/variables/static",
        "fragment": "Static variables: initialised once, retain values between calls",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "state.persistent",
      "language": "ninjascript",
      "source": "present",
      "construct": "class-level field",
      "signature": "private double myValue;",
      "relation": "different_semantics",
      "note": "Fields keep their value across every OnBarUpdate call, including intrabar ticks. Lipi static rolls back to the last closed-bar value on each live tick.",
      "differences": [
        {
          "axis": "state_and_side_effects",
          "note": "A field updated on every tick accumulates; the same logic in a Lipi static restarts from the committed value each tick."
        }
      ],
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/developing_indicators.htm",
        "fragment": "You can retain calculations between bar updates",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "state.persistent",
      "language": "pine",
      "source": "present",
      "construct": "var",
      "relation": "exact",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-docs/language/variable-declarations/",
        "fragment": "var; kw_var",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "state.persistent",
      "language": "thinkscript",
      "source": "present",
      "construct": "def x = x[1] + ...; rec",
      "relation": "equivalent_with_caveat",
      "note": "Persistence is self-reference with [1] on a def (rec is obsolete). It starts at 0 unless CompoundValue seeds it; there is no static keyword.",
      "differences": [
        {
          "axis": "warmup_and_na",
          "note": "An unseeded self-reference starts from 0, not na."
        }
      ],
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Reserved-Words/def",
        "fragment": "Example 2. Recursive usage: def C = C[1] + volume;",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "state.intrabar",
      "language": "mql4",
      "source": "present",
      "construct": "static or global variable",
      "relation": "equivalent_with_caveat",
      "note": "All persistent variables survive ticks and are never cleared at bar close; reset by comparing a saved bar time to Time[0].",
      "differences": [
        {
          "axis": "state_and_side_effects",
          "note": "No automatic clearing when a new bar starts."
        }
      ],
      "evidence": {
        "url": "https://docs.mql4.com/basis/variables/static",
        "fragment": "static variables retain their values",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "state.intrabar",
      "language": "mql5",
      "source": "present",
      "construct": "global variable; static local",
      "relation": "composite",
      "note": "No separate keyword: values persist through all calls, so clearing state when a new bar starts needs your own new-bar test.",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/basis/variables/global",
        "fragment": "Global variables persist while the program runs",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "state.intrabar",
      "language": "ninjascript",
      "source": "present",
      "construct": "class-level field reset when IsFirstTickOfBar is true",
      "signature": "if (IsFirstTickOfBar) { myValue = 0; }",
      "relation": "composite",
      "note": "Fields already persist across ticks of one bar but are never cleared at bar close; reset them on IsFirstTickOfBar to mimic Lipi intra.",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/isfirsttickofbar.htm",
        "fragment": "IsFirstTickOfBar Definition and Tip",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "state.intrabar",
      "language": "pine",
      "source": "present",
      "construct": "varip",
      "relation": "different_semantics",
      "note": "varip keeps its value across ticks without rollback and also across bars; Lipi's intra is cleared when a new bar starts.",
      "differences": [
        {
          "axis": "state_and_side_effects",
          "note": "Pine varip never resets between bars; Lipi intra restarts from its initializer on each new bar."
        }
      ],
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-docs/language/variable-declarations/",
        "fragment": "varip; kw_varip",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "state.intrabar",
      "language": "thinkscript",
      "source": "absent",
      "note": "No intrabar state construct is documented; the only control is recalculation on every tick or, with once_per_bar, once per bar.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Declarations/once-per-bar",
        "fragment": "forced to recalculate the last values only once per bar",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "state.bar-flags",
      "language": "mql4",
      "source": "absent",
      "note": "No first, history, new-bar or confirmed flags among predefined variables; programs compare Time[0] with a saved time, and indicators read IndicatorCounted.",
      "evidence": {
        "url": "https://docs.mql4.com/predefined",
        "fragment": "Predefined Variables table",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "state.bar-flags",
      "language": "mql5",
      "source": "absent",
      "note": "No bar-state flags: use prev_calculated (0 means full recalculation) and rates_total to find new or changed bars.",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/event_handlers/oncalculate",
        "fragment": "prev_calculated; set to zero by the terminal when price data changed",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "state.bar-flags",
      "language": "ninjascript",
      "source": "present",
      "construct": "State, IsFirstTickOfBar, Bars.IsFirstBarOfSession, CurrentBar",
      "relation": "composite",
      "note": "ishistory/isrealtime = State.Historical/Realtime; isnew = IsFirstTickOfBar; isfirst = CurrentBar == 0, not IsFirstBarOfSession; no isconfirmed flag.",
      "differences": [
        {
          "axis": "bar_timing",
          "note": "A bar is known closed only when the next bar's first tick arrives; read Close[1] on that tick."
        }
      ],
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/state.htm",
        "fragment": "State Property Value (Historical, Realtime)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "state.bar-flags",
      "language": "pine",
      "source": "present",
      "construct": "barstate.isfirst, ishistory, isrealtime, isnew, isconfirmed, islastconfirmedhistory",
      "relation": "equivalent_with_caveat",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "var_barstate.isfirst; var_barstate.isnew; var_barstate.isconfirmed",
        "accessed": "2026-11-01"
      },
      "verified": "documented",
      "note": "While the market is open, Lipi's isconfirmed is false on the last history bar and islastconfirmedhistory is false on every history bar."
    },
    {
      "concept": "state.bar-flags",
      "language": "thinkscript",
      "source": "absent",
      "note": "No bar-state flags: the first bar comes from BarNumber() (base unstated), the last from the IsNaN next-bar idiom; no live or confirmed-bar test.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/tutorials/Advanced/Chapter-12---Past-Offset-and-Prefetch",
        "fragment": "Future Offset: def isLastBar = !IsNaN(close) and IsNaN(close[-1]);",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "flow.if",
      "language": "mql4",
      "source": "present",
      "construct": "if (cond) {...} else {...}",
      "relation": "equivalent_with_caveat",
      "note": "C-style: condition in parentheses, braces optional for one statement, else if chains.",
      "evidence": {
        "url": "https://docs.mql4.com/basis/operators/if",
        "fragment": "Conditional Operator if-else",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "flow.if",
      "language": "mql5",
      "source": "present",
      "construct": "if / else",
      "signature": "if (expression) operator1 else operator2",
      "relation": "equivalent_with_caveat",
      "note": "Condition sits in parentheses and chains as else if; any non-zero number counts as true.",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/basis/operators/if",
        "fragment": "Conditional Operator if-else; else addresses the nearest if without else",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "flow.if",
      "language": "ninjascript",
      "source": "present",
      "construct": "if / else if / else",
      "relation": "exact",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/branching_commands.htm",
        "fragment": "The if Statement",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "flow.if",
      "language": "pine",
      "source": "present",
      "construct": "if / else if / else",
      "relation": "equivalent_with_caveat",
      "note": "Pine if returns a value (x = if c ...) and nests by indentation; Lipi's if is a statement with braces and returns nothing.",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-docs/language/conditional-structures/",
        "fragment": "if-structure",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "flow.if",
      "language": "thinkscript",
      "source": "present",
      "construct": "if / else (statement); if ... then ... else (expression)",
      "signature": "if <cond> [then] { <assignments> } else { <assignments> }",
      "relation": "equivalent_with_caveat",
      "note": "Statement branches assign to plot or def variables rather than run imperative code; the expression form needs both branches and computes both.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Reserved-Words/if",
        "fragment": "Syntax (if-statement); Syntax (if-expression)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "flow.switch",
      "language": "mql4",
      "source": "present",
      "construct": "switch (expr) { case const: ... break; default: }",
      "relation": "different_semantics",
      "note": "Control falls through to following cases until break; the expression must be an integer type and case labels constants.",
      "evidence": {
        "url": "https://docs.mql4.com/basis/operators/switch",
        "fragment": "Switch Operator",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "flow.switch",
      "language": "mql5",
      "source": "present",
      "construct": "switch / case / default",
      "signature": "switch(expression) { case constant: operators; break; default: operators }",
      "relation": "different_semantics",
      "note": "Without break, execution falls into the next case; case labels are constants and the switched value must be an integer.",
      "differences": [
        {
          "axis": "state_and_side_effects",
          "note": "A forgotten break silently runs several branches."
        }
      ],
      "evidence": {
        "url": "https://www.mql5.com/en/docs/basis/operators/switch",
        "fragment": "Switch Operator: case constants, default, break",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "flow.switch",
      "language": "ninjascript",
      "source": "present",
      "construct": "switch / case / break",
      "relation": "equivalent_with_caveat",
      "note": "Each C# case block ends with break; Lipi cases take exactly one value each and use case and default labels.",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/branching_commands.htm",
        "fragment": "The switch Statement",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "flow.switch",
      "language": "pine",
      "source": "present",
      "construct": "switch",
      "relation": "equivalent_with_caveat",
      "note": "Pine switch returns a value, may omit the subject to test conditions, and uses value => block with a bare => default.",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-docs/language/conditional-structures/",
        "fragment": "switch-structure",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "flow.switch",
      "language": "thinkscript",
      "source": "present",
      "construct": "switch / case / default",
      "signature": "switch (<enum input or enum def>) { case <value>: ... default: ... }",
      "relation": "equivalent_with_caveat",
      "note": "Switches only on an enum input or enum def, not on arbitrary values; default is needed unless every enum value has a case.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Reserved-Words/switch",
        "fragment": "switch (<enum input or enum_def>)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "flow.ternary",
      "language": "mql4",
      "source": "present",
      "construct": "cond ? a : b",
      "relation": "equivalent_with_caveat",
      "note": "Both branches must share a type (the wider type wins); there is no na branch, EMPTY_VALUE is the usual stand-in.",
      "evidence": {
        "url": "https://docs.mql4.com/basis/operators/ternary",
        "fragment": "Ternary Operator ?:",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "flow.ternary",
      "language": "mql5",
      "source": "present",
      "construct": "?:",
      "signature": "expression1 ? expression2 : expression3",
      "relation": "exact",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/basis/operators/ternary",
        "fragment": "Ternary Operator ?:",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "flow.ternary",
      "language": "ninjascript",
      "source": "present",
      "construct": "condition ? a : b",
      "relation": "exact",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/basic_syntax.htm",
        "fragment": "Operators: Conditional ?:",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "flow.ternary",
      "language": "pine",
      "source": "present",
      "construct": "condition ? a : b",
      "relation": "exact",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-docs/language/operators/",
        "fragment": "-ternary-operator",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "flow.ternary",
      "language": "thinkscript",
      "source": "present",
      "construct": "if <cond> then <a> else <b>; If(cond, a, b)",
      "signature": "If(double condition, double true value, double false value)",
      "relation": "equivalent_with_caveat",
      "note": "Written as if-then-else; the If() function accepts only numeric double arguments, so use the expression form for colours or text.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Functions/Others/If",
        "fragment": "input arguments can only be numerical of type double",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "flow.for-count",
      "language": "mql4",
      "source": "present",
      "construct": "for (init; cond; step)",
      "relation": "different_semantics",
      "note": "C-style loop that ends when the condition fails; no inclusive end or automatic direction, so descending loops need i-- and a matching comparison.",
      "evidence": {
        "url": "https://docs.mql4.com/basis/operators/for",
        "fragment": "Loop Operator for",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "flow.for-count",
      "language": "mql5",
      "source": "present",
      "construct": "for",
      "signature": "for(expression1; expression2; expression3) operator",
      "relation": "different_semantics",
      "note": "Start, test and step are free expressions; there is no to/step form, so inclusive end and step direction are written by hand.",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/basis/operators/for",
        "fragment": "Loop Operator for: three expressions, any may be omitted",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "flow.for-count",
      "language": "ninjascript",
      "source": "present",
      "construct": "for (initializer; condition; iterator)",
      "signature": "for (int x = 0; x < 100; x++)",
      "relation": "equivalent_with_caveat",
      "note": "Start, bound and step are written by hand in three clauses; Lipi 'for i = a to b' infers direction without a step.",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/looping_commands.htm",
        "fragment": "For Loop",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "flow.for-count",
      "language": "pine",
      "source": "present",
      "construct": "for i = a to b by step",
      "relation": "different_semantics",
      "note": "Pine's end value is inclusive, so equal bounds run once (Lipi runs zero times). The step keyword is by, not step.",
      "differences": [
        {
          "axis": "state_and_side_effects",
          "note": "Pine re-evaluates the end bound before every pass; Lipi evaluates start, end and step once."
        }
      ],
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-docs/language/loops/",
        "fragment": "for-loops",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "flow.for-count",
      "language": "thinkscript",
      "source": "present",
      "construct": "fold",
      "signature": "fold <index> = <start> to <end> [with <var> [= <init>]] [while <cond>] do <expr>",
      "relation": "different_semantics",
      "note": "fold is a reduction expression, not a statement loop: the end bound is excluded, the step is fixed at 1, one accumulated result.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Reserved-Words/fold",
        "fragment": "Once the index value becomes equal to the end parameter, the loop is terminated without calculation",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "flow.for-each",
      "language": "mql4",
      "source": "absent",
      "note": "No for-in or range loop; the operator list has for, while and do-while. Loop over indexes up to ArraySize instead.",
      "evidence": {
        "url": "https://docs.mql4.com/basis/operators/for",
        "fragment": "Operators menu list",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "flow.for-each",
      "language": "mql5",
      "source": "absent",
      "note": "The operators section lists no foreach or range loop; index through the array with a for loop.",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/basis/operators",
        "fragment": "Operators list: compound, if-else, switch, while, for, do while, break, continue",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "flow.for-each",
      "language": "ninjascript",
      "source": "present",
      "construct": "foreach (type item in collection)",
      "relation": "equivalent_with_caveat",
      "note": "Keyword is foreach with an explicit element type; Lipi writes 'for item in collection'.",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/looping_commands.htm",
        "fragment": "Foreach Loop",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "flow.for-each",
      "language": "pine",
      "source": "present",
      "construct": "for item in collection; for [index, item] in collection",
      "relation": "equivalent_with_caveat",
      "note": "Pine also offers the [index, item] form and loops over matrices and maps; Lipi has only the single-item form over an array variable.",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-docs/language/loops/",
        "fragment": "forin-loops",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "flow.for-each",
      "language": "thinkscript",
      "source": "absent",
      "note": "No arrays or collections exist, so there is nothing to iterate over; fold only counts an index.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Data-Types",
        "fragment": "full list of available data types",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "flow.while",
      "language": "mql4",
      "source": "present",
      "construct": "while (cond) {...}",
      "relation": "exact",
      "evidence": {
        "url": "https://docs.mql4.com/basis/operators/while",
        "fragment": "Loop Operator while",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "flow.while",
      "language": "mql5",
      "source": "present",
      "construct": "while; do while",
      "signature": "while(expression) operator;",
      "relation": "equivalent_with_caveat",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/basis/operators/while",
        "fragment": "Loop Operator while",
        "accessed": "2026-11-01"
      },
      "verified": "documented",
      "note": "MQL5 construct includes do-while, which runs its body once before testing; Lipi has only while and rejects do/while, so rewrite with while and break."
    },
    {
      "concept": "flow.while",
      "language": "ninjascript",
      "source": "present",
      "construct": "while (condition) { }; do { } while (condition)",
      "relation": "equivalent_with_caveat",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/looping_commands.htm",
        "fragment": "While Loop",
        "accessed": "2026-11-01"
      },
      "verified": "documented",
      "note": "C# do-while runs its body once before testing the condition; Lipi has no do-while (rejected), so rewrite with while true and break."
    },
    {
      "concept": "flow.while",
      "language": "pine",
      "source": "present",
      "construct": "while",
      "relation": "exact",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-docs/language/loops/",
        "fragment": "while-loops",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "flow.while",
      "language": "thinkscript",
      "source": "present",
      "construct": "while (inside fold)",
      "signature": "fold ... while <condition> do <expr>",
      "relation": "different_semantics",
      "note": "while only adds an early-exit test inside fold; it is not a standalone loop, and a failed test keeps the last accumulated value.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Reserved-Words/while",
        "fragment": "defines a condition upon violation of which the loop is terminated when calculating the fold function",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "flow.break-continue",
      "language": "mql4",
      "source": "present",
      "construct": "break; continue;",
      "relation": "equivalent_with_caveat",
      "evidence": {
        "url": "https://docs.mql4.com/basis/operators/break",
        "fragment": "Break Operator",
        "accessed": "2026-11-01"
      },
      "verified": "documented",
      "note": "break also ends a switch case; Lipi's break works only inside a loop. continue goes to the next loop iteration in both."
    },
    {
      "concept": "flow.break-continue",
      "language": "mql5",
      "source": "present",
      "construct": "break; continue",
      "relation": "equivalent_with_caveat",
      "note": "break also ends a switch case; Lipi's break works only inside a loop. continue goes to the next loop iteration in both.",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/basis/operators/break",
        "fragment": "break terminates the nearest outward switch, while, do-while or for",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "flow.break-continue",
      "language": "ninjascript",
      "source": "present",
      "construct": "break; continue;",
      "relation": "exact",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/looping_commands.htm",
        "fragment": "Break and Continue",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "flow.break-continue",
      "language": "pine",
      "source": "present",
      "construct": "break, continue",
      "relation": "exact",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-docs/language/loops/",
        "fragment": "common-characteristics; #keywords-and-return-expressions",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "flow.break-continue",
      "language": "thinkscript",
      "source": "absent",
      "note": "No break or continue; a while condition inside fold is the only documented way to stop early, and nothing skips a pass.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Reserved-Words/fold",
        "fragment": "You can also add a condition within the while block of the operator",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "func.user-function",
      "language": "mql4",
      "source": "present",
      "construct": "type name(params) { return value; }",
      "relation": "equivalent_with_caveat",
      "note": "Return and parameter types are declared; plain-type parameters pass by value, & passes by reference; arrays and structs are always by reference.",
      "evidence": {
        "url": "https://docs.mql4.com/basis/function/parameterpass",
        "fragment": "Passing Parameters",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "func.user-function",
      "language": "mql5",
      "source": "present",
      "construct": "return_type name(params) { return value; }",
      "signature": "return_type function_name(type param = default, ...)",
      "relation": "equivalent_with_caveat",
      "note": "Return type is declared before the name; parameters may have defaults and may be passed by reference; arrays and class objects cannot be returned.",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/basis/function",
        "fragment": "Functions: return type, parameters (max 64), default values, return operator",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "func.user-function",
      "language": "ninjascript",
      "source": "present",
      "construct": "[access] returnType Name(params) { return ...; }",
      "signature": "private double Multiply(double input)",
      "relation": "equivalent_with_caveat",
      "note": "A method needs an access modifier plus explicit parameter and return types, or void; Lipi func infers them.",
      "differences": [
        {
          "axis": "state_and_side_effects",
          "note": "A method may assign class fields; Lipi functions cannot assign global variables."
        }
      ],
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/functions_and_methods_explaine.htm",
        "fragment": "Method With a Return Type",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "func.user-function",
      "language": "pine",
      "source": "present",
      "construct": "name(params) => body",
      "relation": "equivalent_with_caveat",
      "note": "Pine declares name(args) => with parameter types optional and returns the last expression; there is no func or return keyword. Neither language allows recursion.",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-docs/language/user-defined-functions/",
        "fragment": "structure-and-syntax",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "func.user-function",
      "language": "thinkscript",
      "source": "present",
      "construct": "script",
      "signature": "script <name> { <script_code>; }",
      "relation": "equivalent_with_caveat",
      "note": "A script block is a mini-study: parameters are declared as inputs and results come back as plots, read by name.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Reserved-Words/script",
        "fragment": "script <script_name> { <script_code>; }",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "func.method",
      "language": "mql4",
      "source": "present",
      "construct": "member functions of struct or class",
      "relation": "equivalent_with_caveat",
      "note": "Methods are declared inside a struct or class, may be defined outside with the :: operator, and are called with a dot on an object.",
      "evidence": {
        "url": "https://docs.mql4.com/basis/types/classes",
        "fragment": "define the method outside the class",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "func.method",
      "language": "mql5",
      "source": "present",
      "construct": "member function of struct or class",
      "signature": "return_type ClassName::Method(params)",
      "relation": "equivalent_with_caveat",
      "note": "Methods are declared inside a struct or class (or defined outside with ::); there is no def keyword attaching a function to an existing type.",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/basis/oop/staticmembers",
        "fragment": "methods defined outside the class with the :: scope operator",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "func.method",
      "language": "ninjascript",
      "source": "present",
      "construct": "instance method of the script class (or of your own class)",
      "relation": "equivalent_with_caveat",
      "note": "Methods you declare belong to the script class; attaching one to your own type needs a separate C# class. Lipi 'def' extends a type.",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/functions_and_methods_explaine.htm",
        "fragment": "Declaring a Method",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "func.method",
      "language": "pine",
      "source": "present",
      "construct": "method",
      "relation": "equivalent_with_caveat",
      "note": "Pine uses the method keyword with an explicitly typed first parameter; Lipi uses def. Both call it as value.name(...).",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "kw_method",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "func.method",
      "language": "thinkscript",
      "source": "absent",
      "note": "No methods on user types exist; only built-in plot methods such as SetDefaultColor() are available.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Data-Types",
        "fragment": "full list of available data types",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "op.arithmetic",
      "language": "mql4",
      "source": "present",
      "construct": "+ - * / %",
      "relation": "different_semantics",
      "note": "Two integer operands divide as integers (1/2 gives 0) while Lipi / always returns a decimal; % keeps the sign of the dividend.",
      "differences": [
        {
          "axis": "numeric_types",
          "note": "Integer division truncates; make an operand double to get a fraction."
        }
      ],
      "evidence": {
        "url": "https://docs.mql4.com/basis/types/casting",
        "fragment": "int i=1/2 gives 0",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "op.arithmetic",
      "language": "mql5",
      "source": "present",
      "construct": "+ - * / %",
      "relation": "different_semantics",
      "note": "Division by zero is a critical runtime error that stops the program, whereas Lipi returns na.",
      "differences": [
        {
          "axis": "state_and_side_effects",
          "note": "The program is terminated on division by zero; guard every divisor yourself."
        }
      ],
      "evidence": {
        "url": "https://www.mql5.com/en/docs/runtime/errors",
        "fragment": "critical errors: division by zero",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "op.arithmetic",
      "language": "ninjascript",
      "source": "present",
      "construct": "+, -, *, /, %",
      "relation": "different_semantics",
      "note": "The page lists + - * /; % is the standard C# remainder operator and is not shown there.",
      "differences": [
        {
          "axis": "numeric_types",
          "note": "Two int operands divide as integers in C#; Lipi '/' always returns a float."
        }
      ],
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/basic_syntax.htm",
        "fragment": "Operators: Arithmetic",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "op.arithmetic",
      "language": "pine",
      "source": "present",
      "construct": "+  -  *  /  %",
      "relation": "equivalent_with_caveat",
      "note": "Pine's own docs disagree on % with negative operands: the reference keeps the dividend's sign (like Lipi), the Operators page computes with floor.",
      "differences": [
        {
          "axis": "numeric_types",
          "note": "Pine docs give both truncated and floored results for % with a negative operand; Lipi takes the sign of the left operand."
        }
      ],
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "op_%; op_/",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "op.arithmetic",
      "language": "thinkscript",
      "source": "present",
      "construct": "+ - * / %",
      "relation": "exact",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Operators/Arithmetic",
        "fragment": "| + | addition, string concatenation | ... | % | remainder |",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "op.comparison",
      "language": "mql4",
      "source": "present",
      "construct": "== != > < >= <=",
      "relation": "equivalent_with_caveat",
      "evidence": {
        "url": "https://docs.mql4.com/basis/operations/relation",
        "fragment": "Operations of Relation",
        "accessed": "2026-11-01"
      },
      "verified": "documented",
      "note": "MQL4 comparisons yield integer 0 or 1 usable in arithmetic; Lipi comparisons yield bool, and arithmetic or int() on a bool is rejected."
    },
    {
      "concept": "op.comparison",
      "language": "mql5",
      "source": "present",
      "construct": "== != > < >= <=",
      "relation": "equivalent_with_caveat",
      "note": "Same operators; for reals the docs advise comparing a normalised difference to zero instead of using ==.",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/basis/operations/relation",
        "fragment": "Operations of Relation; comparing two real numbers",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "op.comparison",
      "language": "ninjascript",
      "source": "present",
      "construct": "==, !=, >, <, >=, <=",
      "relation": "exact",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/basic_syntax.htm",
        "fragment": "Operators: Relational",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "op.comparison",
      "language": "pine",
      "source": "present",
      "construct": "==  !=  >  <  >=  <=",
      "relation": "equivalent_with_caveat",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-docs/language/operators/",
        "fragment": "comparison-operators",
        "accessed": "2026-11-01"
      },
      "verified": "documented",
      "note": "Pine rounds floats to nine decimals for ==/!= and never yields na; Lipi compares exactly and yields na with an na operand."
    },
    {
      "concept": "op.comparison",
      "language": "thinkscript",
      "source": "present",
      "construct": "== != <> < > <= >= between crosses",
      "relation": "equivalent_with_caveat",
      "note": "Also word forms (equals, is greater than), <> and between; crosses above/below are operators here, so use ta.crossover and ta.crossunder in Lipi.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Operators/Comparison",
        "fragment": "between | crosses | crosses above | crosses below",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "op.logical",
      "language": "mql4",
      "source": "present",
      "construct": "&& || !",
      "relation": "different_semantics",
      "note": "Written with symbols, not and/or/not. MQL4 stops evaluating once the result is known; Lipi always evaluates both operands.",
      "differences": [
        {
          "axis": "state_and_side_effects",
          "note": "Short-circuit: a right operand with side effects may not run in MQL4 but always runs in Lipi."
        }
      ],
      "evidence": {
        "url": "https://docs.mql4.com/basis/operations/bool",
        "fragment": "Boolean Operations",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "op.logical",
      "language": "mql5",
      "source": "present",
      "construct": "&& || !",
      "relation": "different_semantics",
      "note": "MQL5 stops once the result is known; Lipi evaluates both operands, so a guard such as i < n does not protect the right side.",
      "differences": [
        {
          "axis": "state_and_side_effects",
          "note": "A right-hand call or array access is skipped in MQL5 when the left side decides; in Lipi it always runs."
        }
      ],
      "evidence": {
        "url": "https://www.mql5.com/en/docs/basis/operations/bool",
        "fragment": "Boolean Operations: NOT (!), OR (||), AND (&&), brief estimate",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "op.logical",
      "language": "ninjascript",
      "source": "present",
      "construct": "&&, ||, !",
      "relation": "different_semantics",
      "note": "Written && || !. C# skips the right side once the left decides; Lipi evaluates both, so a guard such as i < n fails.",
      "evidence": {
        "url": "https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/boolean-logical-operators",
        "fragment": "conditional-logical-and-operator-",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "op.logical",
      "language": "pine",
      "source": "present",
      "construct": "and, or, not",
      "relation": "different_semantics",
      "note": "Pine v6 and/or are lazy: the right side is skipped once the left decides. Lipi evaluates both, so guards like i < n fail.",
      "differences": [
        {
          "axis": "state_and_side_effects",
          "note": "Pine skips the right operand when the left decides; Lipi always evaluates it."
        },
        {
          "axis": "warmup_and_na",
          "note": "Pine v6 bools are never na; in Lipi na and false gives na."
        }
      ],
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "kw_and; kw_or; kw_not",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "op.logical",
      "language": "thinkscript",
      "source": "present",
      "construct": "and, &&, or, !, is true, is false",
      "relation": "equivalent_with_caveat",
      "note": "Works on numbers: 0 is false and anything else true; also has word forms such as is true and is false.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Operators/Logical",
        "fragment": "Logical operators can be applied only to numeric data. Zero(0) is interpreted as a false value",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "op.compound-assign",
      "language": "mql4",
      "source": "present",
      "construct": "+= -= *= /= %=",
      "relation": "equivalent_with_caveat",
      "note": "%= keeps the sign of the dividend. Integer operands follow integer arithmetic, so /= on an int is allowed, where Lipi rejects it.",
      "differences": [
        {
          "axis": "numeric_types",
          "note": "Integer operands keep integer arithmetic under /= and %=."
        }
      ],
      "evidence": {
        "url": "https://docs.mql4.com/basis/operations/assign",
        "fragment": "Assignment Operations",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "op.compound-assign",
      "language": "mql5",
      "source": "present",
      "construct": "+= -= *= /= %= <<= >>= &= |= ^=",
      "relation": "equivalent_with_caveat",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/basis/operations/assign",
        "fragment": "Assignment Operations: y += x and the other compound forms",
        "accessed": "2026-11-01"
      },
      "verified": "documented",
      "note": "Same operators. Lipi refuses /= on an int variable, because dividing two ints gives a float; declare the variable float."
    },
    {
      "concept": "op.compound-assign",
      "language": "ninjascript",
      "source": "present",
      "construct": "+=, -=, *=, /=",
      "relation": "equivalent_with_caveat",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/basic_syntax.htm",
        "fragment": "Operators: Assignment",
        "accessed": "2026-11-01"
      },
      "verified": "documented",
      "note": "Same operators. Lipi refuses /= on an int variable, because dividing two ints gives a float; declare the variable float."
    },
    {
      "concept": "op.compound-assign",
      "language": "pine",
      "source": "present",
      "construct": "+=  -=  *=  /=  %=",
      "relation": "equivalent_with_caveat",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-docs/language/operators/",
        "fragment": "compound-assignment-operators",
        "accessed": "2026-11-01"
      },
      "verified": "documented",
      "note": "Same operators. Lipi refuses /= on an int variable, because dividing two ints gives a float; declare the variable float."
    },
    {
      "concept": "op.compound-assign",
      "language": "thinkscript",
      "source": "absent",
      "note": "Only plain = exists; accumulate with a self-referencing def such as def total = total[1] + x.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Operators",
        "fragment": "full list of available operators: Arithmetic, Comparison, Conditional, Indexing, Logical",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "coll.map",
      "language": "mql4",
      "source": "absent",
      "note": "The Data Types list has numeric, string, struct, class, dynamic array and pointer entries but no key-value collection. Use parallel arrays or your own class.",
      "evidence": {
        "url": "https://docs.mql4.com/basis/types",
        "fragment": "Dynamic Array Object",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "coll.map",
      "language": "mql5",
      "source": "present",
      "construct": "CHashMap<TKey,TValue>",
      "signature": "template<typename TKey, typename TValue> class CHashMap",
      "relation": "no_lipi_equivalent",
      "note": "A standard-library generic class of key/value pairs; the Lipi workaround is two arrays kept in step.",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/standardlibrary/generic/chashmap",
        "fragment": "CHashMap<TKey,TValue> methods Add, TryGetValue, Remove",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "coll.map",
      "language": "ninjascript",
      "source": "present",
      "construct": "Dictionary<TKey, TValue> (.NET)",
      "relation": "no_lipi_equivalent",
      "note": "Standard .NET class; the NinjaTrader page only points to the .NET class library. In Lipi use two parallel arrays or a user type.",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/c_method_functions_reference.htm",
        "fragment": "Native Methods (list of classes in the Microsoft .NET environment)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "coll.map",
      "language": "pine",
      "source": "present",
      "construct": "map<K, V>, map.new<K, V>()",
      "signature": "map.new<keyType, valueType>() → map<keyType, valueType>",
      "relation": "no_lipi_equivalent",
      "note": "Use two arrays kept in step, or an array of a user type.",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "type_map; fun_map.new%3Ctype,type%3E",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "coll.map",
      "language": "thinkscript",
      "source": "absent",
      "note": "No key-value type; the data types list contains no collections at all.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Data-Types",
        "fragment": "full list of available data types",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "coll.matrix",
      "language": "mql4",
      "source": "present",
      "construct": "multi-dimensional array, e.g. double a[][4]",
      "relation": "no_lipi_equivalent",
      "note": "Arrays may have up to four dimensions; in Lipi use one array with computed indexes.",
      "evidence": {
        "url": "https://docs.mql4.com/basis/variables",
        "fragment": "No more than four-dimensional arrays are allowed",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "coll.matrix",
      "language": "mql5",
      "source": "present",
      "construct": "matrix; matrixf; matrixc",
      "relation": "no_lipi_equivalent",
      "note": "Built-in two-dimensional types holding double, float or complex elements; the Lipi workaround is a flat array with computed indexes.",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/basis/types/matrix_vector",
        "fragment": "Matrices and vectors: matrix, matrixf, matrixc",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "coll.matrix",
      "language": "ninjascript",
      "source": "present",
      "construct": "double[,] or jagged arrays (.NET)",
      "relation": "no_lipi_equivalent",
      "note": "C# arrays are linked from the same page. Lipi has no matrix type; use one array with computed indexes.",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/c_method_functions_reference.htm",
        "fragment": "Native Methods: Arrays",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "coll.matrix",
      "language": "pine",
      "source": "present",
      "construct": "matrix<T>, matrix.new<T>()",
      "relation": "no_lipi_equivalent",
      "note": "Use one array and compute the index as row * columns + column.",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "type_matrix; fun_matrix.new%3Ctype%3E",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "coll.matrix",
      "language": "thinkscript",
      "source": "absent",
      "note": "No two-dimensional type; the data types list contains no collections at all.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Data-Types",
        "fragment": "full list of available data types",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "mod.import",
      "language": "mql4",
      "source": "present",
      "construct": "#include, #import",
      "relation": "no_lipi_equivalent",
      "note": "#include pulls in source files and #import calls functions from compiled libraries; a Lipi script is a single file.",
      "evidence": {
        "url": "https://docs.mql4.com/basis/preprosessor/include",
        "fragment": "Including Files (#include); Importing Functions (#import)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "mod.import",
      "language": "mql5",
      "source": "present",
      "construct": "#import; #include",
      "signature": "#import \"file_name\" func1 define; #import",
      "relation": "no_lipi_equivalent",
      "note": "Imports functions from compiled .ex5 or .dll modules; Lipi scripts are single files, so copy the code in.",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/basis/preprosessor/import",
        "fragment": "Importing Functions (#import)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "mod.import",
      "language": "ninjascript",
      "source": "present",
      "construct": "C# using directives, namespaces and compiled assemblies",
      "relation": "no_lipi_equivalent",
      "note": "Scripts can reference other types by namespace or through compiled DLLs. Lipi is single-file: copy the functions you need into the script.",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/considerations_for_compiled_assemblies.htm",
        "fragment": "Using Custom enum Properties (fully qualified namespace instead of a using directive)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "mod.import",
      "language": "pine",
      "source": "present",
      "construct": "import user/library/version as alias; library(); export",
      "relation": "no_lipi_equivalent",
      "note": "Copy the functions you need into the single Lipi file.",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "kw_import; kw_export",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "mod.import",
      "language": "thinkscript",
      "source": "absent",
      "note": "Scripts cannot import user code: reference only pulls built-in studies, and script blocks stay inside one file.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/tutorials/Advanced/Chapter-13---Referencing-Other-Data",
        "fragment": "Currently users are only able to reference the built-in studies",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "err.runtime-error",
      "language": "mql4",
      "source": "present",
      "construct": "Print or Alert then return; ExpertRemove()",
      "relation": "no_lipi_equivalent",
      "note": "No raise statement: report with Alert or Print and return, or call ExpertRemove to unload an Expert Advisor. Lipi: guard the calculation.",
      "evidence": {
        "url": "https://docs.mql4.com/common/expertremove",
        "fragment": "ExpertRemove note",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "err.runtime-error",
      "language": "mql5",
      "source": "present",
      "construct": "return INIT_FAILED from OnInit; ExpertRemove()",
      "relation": "no_lipi_equivalent",
      "note": "No call raises a custom error: INIT_FAILED leaves an indicator inoperative, ExpertRemove unloads an Expert Advisor only; in Lipi, guard and skip.",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/basis/function/events",
        "fragment": "OnInit return codes INIT_SUCCEEDED / INIT_FAILED",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "err.runtime-error",
      "language": "ninjascript",
      "source": "present",
      "construct": "Log(message, LogLevel.Error)",
      "signature": "Log(string message, LogLevel logLevel)",
      "relation": "no_lipi_equivalent",
      "note": "Log() writes to the Control Center Log tab and the log file; it is logging, not an exit. Lipi has no raise; guard and skip.",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/log.htm",
        "fragment": "Log() Syntax and LogLevel values",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "err.runtime-error",
      "language": "pine",
      "source": "present",
      "construct": "runtime.error()",
      "signature": "runtime.error(message) → void",
      "relation": "no_lipi_equivalent",
      "note": "Guard the calculation and skip it; Lipi cannot halt the script on purpose.",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_runtime.error",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "err.runtime-error",
      "language": "thinkscript",
      "source": "present",
      "construct": "Assert",
      "signature": "Assert(boolean condition, Any message)",
      "relation": "no_lipi_equivalent",
      "note": "Assert stops the plots and shows an error flag when the condition is false; in Lipi guard the calculation and skip it.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Functions/Others/Assert",
        "fragment": "Throws a runtime error message in case the specified condition is false",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "input.int",
      "language": "mql4",
      "source": "present",
      "construct": "input int",
      "relation": "equivalent_with_caveat",
      "note": "Global declaration input int name=default; read-only in code, no minimum, maximum or step arguments; a trailing // comment becomes the label.",
      "evidence": {
        "url": "https://docs.mql4.com/basis/variables/inputvariables",
        "fragment": "Input Variables",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "input.int",
      "language": "mql5",
      "source": "present",
      "construct": "input int",
      "signature": "input int Name = default; // label",
      "relation": "equivalent_with_caveat",
      "note": "Label comes from the trailing comment or an input(name=...) attribute. The declaration has no min, max or step; the tester or ParameterSetRange sets optimisation ranges.",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/basis/variables/inputvariables",
        "fragment": "name parameter in parentheses after the 'input' keyword; ParameterSetRange",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "input.int",
      "language": "ninjascript",
      "source": "present",
      "construct": "[NinjaScriptProperty][Range(min, max)] public int Name { get; set; }",
      "signature": "[Range(1, int.MaxValue)] [NinjaScriptProperty] [Display(Name=\"Period\", Order=1, GroupName=\"Parameters\")] public int Period { get; set; }",
      "relation": "equivalent_with_caveat",
      "note": "A class property with attributes; the default is assigned in State.SetDefaults. Range supplies bounds; no step attribute is documented.",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/creating_user_defined_input_pa.htm",
        "fragment": "Use the following template code for each parameter",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "input.int",
      "language": "pine",
      "source": "present",
      "construct": "input.int()",
      "signature": "input.int(defval, title, minval, maxval, step, tooltip, inline, group, confirm, display, active) → input int",
      "relation": "equivalent_with_caveat",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_input.int",
        "accessed": "2026-11-01"
      },
      "verified": "documented",
      "note": "Pine accepts an active argument that greys out the input; Lipi rejects it as an unknown named argument, so it must be dropped."
    },
    {
      "concept": "input.int",
      "language": "thinkscript",
      "source": "present",
      "construct": "input <name> = <integer>",
      "signature": "input <input name>=<integer_number_used_by_default>;",
      "relation": "equivalent_with_caveat",
      "note": "No bounds, step or tooltip arguments; the default alone fixes the integer type.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Reserved-Words/input/integer",
        "fragment": "input <input name>=<integer_number_used_by_default>;",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "input.float",
      "language": "mql4",
      "source": "present",
      "construct": "input double",
      "relation": "equivalent_with_caveat",
      "note": "Declared input double name=default; no bounds or step; read-only in code.",
      "evidence": {
        "url": "https://docs.mql4.com/basis/variables/inputvariables",
        "fragment": "Input Variables",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "input.float",
      "language": "mql5",
      "source": "present",
      "construct": "input double",
      "signature": "input double Name = default; // label",
      "relation": "equivalent_with_caveat",
      "note": "Label comes from the trailing comment or an input(name=...) attribute. The declaration has no min, max or step; the tester or ParameterSetRange sets optimisation ranges.",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/basis/variables/inputvariables",
        "fragment": "sample inputs: input double ExtBBDeviation = 2.0",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "input.float",
      "language": "ninjascript",
      "source": "present",
      "construct": "[NinjaScriptProperty][Range(min, max)] public double Name { get; set; }",
      "relation": "equivalent_with_caveat",
      "note": "Same property pattern with type double; Range accepts double bounds. Default is set in State.SetDefaults.",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/rangeattribute.htm",
        "fragment": "[Range(double minimum, double maximum)]",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "input.float",
      "language": "pine",
      "source": "present",
      "construct": "input.float()",
      "signature": "input.float(defval, title, minval, maxval, step, tooltip, inline, group, confirm, display, active) → input float",
      "relation": "equivalent_with_caveat",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_input.float",
        "accessed": "2026-11-01"
      },
      "verified": "documented",
      "note": "Pine accepts an active argument that greys out the input; Lipi rejects it as an unknown named argument, so it must be dropped."
    },
    {
      "concept": "input.float",
      "language": "thinkscript",
      "source": "present",
      "construct": "input <name> = <decimal>",
      "signature": "input <input name>=<float_number_used_by_default>;",
      "relation": "equivalent_with_caveat",
      "note": "The default must contain a decimal point to be a float; no bounds or step arguments.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Reserved-Words/input/float",
        "fragment": "you need to use a fullstop as a delimiter in its default value",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "input.bool",
      "language": "mql4",
      "source": "present",
      "construct": "input bool",
      "relation": "equivalent_with_caveat",
      "note": "Declared input bool name=default; read-only in code; label comes from a trailing comment.",
      "evidence": {
        "url": "https://docs.mql4.com/basis/variables/inputvariables",
        "fragment": "Input Variables",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "input.bool",
      "language": "mql5",
      "source": "present",
      "construct": "input bool",
      "relation": "exact",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/basis/variables/inputvariables",
        "fragment": "sample inputs: input bool ExtUseSL = true",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "input.bool",
      "language": "ninjascript",
      "source": "present",
      "construct": "[NinjaScriptProperty] public bool Name { get; set; }",
      "relation": "equivalent_with_caveat",
      "note": "A public bool property; [NinjaScriptProperty] also adds it as a parameter when another script creates this one.",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/ninjascriptpropertyattribute.htm",
        "fragment": "Basic usage of NinjaScriptProperty (public bool MyBool)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "input.bool",
      "language": "pine",
      "source": "present",
      "construct": "input.bool()",
      "signature": "input.bool(defval, title, tooltip, inline, group, confirm, display, active) → input bool",
      "relation": "equivalent_with_caveat",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_input.bool",
        "accessed": "2026-11-01"
      },
      "verified": "documented",
      "note": "Pine accepts an active argument that greys out the input; Lipi rejects it as an unknown named argument, so it must be dropped."
    },
    {
      "concept": "input.bool",
      "language": "thinkscript",
      "source": "present",
      "construct": "input <name> = yes | no",
      "signature": "input <input name>=<boolean_value_used_by_default>;",
      "relation": "equivalent_with_caveat",
      "note": "The default is written yes or no; there are no title or tooltip arguments.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Reserved-Words/input/boolean",
        "fragment": "The default value of the input can either be yes or no",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "input.string",
      "language": "mql4",
      "source": "present",
      "construct": "input string",
      "relation": "equivalent_with_caveat",
      "note": "Free text only; a fixed list of choices needs an enum input instead. String inputs cannot be optimised.",
      "evidence": {
        "url": "https://docs.mql4.com/basis/variables/inputvariables",
        "fragment": "Variables with sinput Modifier; Enumerations as input Parameters",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "input.string",
      "language": "mql5",
      "source": "present",
      "construct": "input string; input of an enum type",
      "relation": "equivalent_with_caveat",
      "note": "Free text is input string; a list of choices needs an enum, whose members show as a dropdown.",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/basis/variables/inputvariables",
        "fragment": "enumerations as input variables show a drop-down list",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "input.string",
      "language": "ninjascript",
      "source": "present",
      "construct": "[NinjaScriptProperty] public string Name { get; set; }",
      "relation": "equivalent_with_caveat",
      "note": "A string property takes free text. For a fixed choice list use an enum property instead of Lipi's options argument.",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/creating_user_defined_input_pa.htm",
        "fragment": "object type will vary depending on the type of parameter",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "input.string",
      "language": "pine",
      "source": "present",
      "construct": "input.string()",
      "signature": "input.string(defval, title, options, tooltip, inline, group, confirm, display, active) → input string",
      "relation": "equivalent_with_caveat",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_input.string",
        "accessed": "2026-11-01"
      },
      "verified": "documented",
      "note": "Pine accepts an active argument that greys out the input; Lipi rejects it as an unknown named argument, so it must be dropped."
    },
    {
      "concept": "input.string",
      "language": "thinkscript",
      "source": "present",
      "construct": "input <name> = \"text\"",
      "signature": "input <input name>=\"<string_value_used_by_default>\";",
      "relation": "equivalent_with_caveat",
      "note": "Free text comes from a quoted default; a pick-list is the separate enum input form, not an options argument.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Reserved-Words/input/string",
        "fragment": "you need to specify double quotes in its default value",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "input.color",
      "language": "mql4",
      "source": "present",
      "construct": "input color",
      "relation": "equivalent_with_caveat",
      "note": "Declared input color name=default using clr names or C'r,g,b'; value has no alpha.",
      "evidence": {
        "url": "https://docs.mql4.com/basis/types/casting",
        "fragment": "input color testColor=clrBlue",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "input.color",
      "language": "mql5",
      "source": "present",
      "construct": "input color",
      "signature": "input color Name = clrRed;",
      "relation": "equivalent_with_caveat",
      "note": "Value is a color constant such as clrRed; it holds no opacity.",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/basis/types/integer/color",
        "fragment": "The first byte is ignored, the remaining 3 bytes contain the RGB-components",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "input.color",
      "language": "ninjascript",
      "source": "present",
      "construct": "[XmlIgnore] public Brush Name { get; set; } plus a Browsable(false) string twin",
      "signature": "Serialize.BrushToString(BorderBrush)",
      "relation": "equivalent_with_caveat",
      "note": "Needs an [XmlIgnore] Brush property and a hidden string property using Serialize.BrushToString and StringToBrush so the choice is saved.",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/user_definable_color_inputs.htm",
        "fragment": "BorderBrushSerialize",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "input.color",
      "language": "pine",
      "source": "present",
      "construct": "input.color()",
      "signature": "input.color(defval, title, tooltip, inline, group, confirm, display, active) → input color",
      "relation": "equivalent_with_caveat",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_input.color",
        "accessed": "2026-11-01"
      },
      "verified": "documented",
      "note": "Pine accepts an active argument that greys out the input; Lipi rejects it as an unknown named argument, so it must be dropped."
    },
    {
      "concept": "input.color",
      "language": "thinkscript",
      "source": "absent",
      "note": "Colour constants cannot define an input; colours are set in code, and Color()/DefineColor() names make plot colours editable in the dialog.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Reserved-Words/input/constant",
        "fragment": "color constants cannot be used for input definition",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "input.source",
      "language": "mql4",
      "source": "present",
      "construct": "input ENUM_APPLIED_PRICE",
      "relation": "equivalent_with_caveat",
      "note": "Choice is limited to the applied-price list (close, open, high, low, median, typical, weighted); another series cannot be picked.",
      "evidence": {
        "url": "https://docs.mql4.com/constants/indicatorconstants/prices",
        "fragment": "ENUM_APPLIED_PRICE",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "input.source",
      "language": "mql5",
      "source": "present",
      "construct": "input ENUM_APPLIED_PRICE; the 'Apply to' field of an OnCalculate(price[]) indicator",
      "relation": "equivalent_with_caveat",
      "note": "Pick from the ENUM_APPLIED_PRICE list, a price kind rather than an arbitrary series; another indicator's handle works only via 'Apply to'.",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/constants/indicatorconstants/prices",
        "fragment": "ENUM_APPLIED_PRICE price constants",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "input.source",
      "language": "ninjascript",
      "source": "present",
      "construct": "Input",
      "signature": "Input[int barsAgo]",
      "relation": "equivalent_with_caveat",
      "note": "An indicator has one implicit Input series (price or another indicator). Lipi allows several named source settings.",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/input.htm",
        "fragment": "Input Definition and Property Value",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "input.source",
      "language": "pine",
      "source": "present",
      "construct": "input.source()",
      "signature": "input.source(defval, title, tooltip, inline, group, display, active, confirm) → series float",
      "relation": "equivalent_with_caveat",
      "note": "Pine also accepts volume as a default and orders display before confirm; Lipi puts confirm first and limits defaults to price series.",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_input.source",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "input.source",
      "language": "thinkscript",
      "source": "present",
      "construct": "input price = close",
      "signature": "input <input name>=<price_value_used_by_default>;",
      "relation": "equivalent_with_caveat",
      "note": "The keyword is price. Besides price series it accepts vwap, volume, open_interest, imp_volatility and tick_count.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Reserved-Words/input/price",
        "fragment": "Valid parameters for the price type are: vwap, volume, open_interest, imp_volatility, tick_count",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "input.timeframe",
      "language": "mql4",
      "source": "present",
      "construct": "input ENUM_TIMEFRAMES",
      "relation": "equivalent_with_caveat",
      "note": "Dropdown of PERIOD_ constants; PERIOD_CURRENT (0) means the chart's own timeframe.",
      "evidence": {
        "url": "https://docs.mql4.com/constants/chartconstants/enum_timeframes",
        "fragment": "ENUM_TIMEFRAMES",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "input.timeframe",
      "language": "mql5",
      "source": "present",
      "construct": "input ENUM_TIMEFRAMES",
      "signature": "input ENUM_TIMEFRAMES Name = PERIOD_CURRENT;",
      "relation": "equivalent_with_caveat",
      "note": "Dropdown of PERIOD_* constants, PERIOD_CURRENT meaning the chart timeframe; unlike Lipi, that timeframe's data can then be read.",
      "differences": [
        {
          "axis": "htf_access",
          "note": "The chosen timeframe can be passed straight to iClose, CopyRates or iMA."
        }
      ],
      "evidence": {
        "url": "https://www.mql5.com/en/docs/constants/chartconstants/enum_timeframes",
        "fragment": "ENUM_TIMEFRAMES: PERIOD_CURRENT, PERIOD_M1 ... PERIOD_MN1",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "input.timeframe",
      "language": "ninjascript",
      "source": "unresolved",
      "note": "No dedicated timeframe input type is documented. AddDataSeries arguments must be hard-coded, so a user-chosen timeframe cannot add a data series.",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/adddataseries.htm",
        "fragment": "Warning: arguments supplied to AddDataSeries() should be hardcoded and not dependent on user input",
        "accessed": "2026-11-01"
      },
      "verified": "unresolved"
    },
    {
      "concept": "input.timeframe",
      "language": "pine",
      "source": "present",
      "construct": "input.timeframe()",
      "signature": "input.timeframe(defval, title, options, tooltip, inline, group, confirm, display, active) → input string",
      "relation": "equivalent_with_caveat",
      "note": "Pine uses bare minutes ('60'), D and W; Lipi uses suffixes such as 1h. Pine also takes an options list; Lipi has none.",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_input.timeframe",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "input.timeframe",
      "language": "thinkscript",
      "source": "present",
      "construct": "input <name> = AggregationPeriod.DAY",
      "signature": "input <input name>=<constant_used_by_default>;",
      "relation": "equivalent_with_caveat",
      "note": "A constant input holding an AggregationPeriod value, fed to the period argument of price functions; Lipi can only read the chart's own timeframe.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Reserved-Words/input/constant",
        "fragment": "input secondaryPeriod = AggregationPeriod.DAY;",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "input.session",
      "language": "mql4",
      "source": "absent",
      "note": "No session input type; use two string or datetime inputs and parse them. Only simple types and enums can be inputs.",
      "evidence": {
        "url": "https://docs.mql4.com/basis/variables/inputvariables",
        "fragment": "Input Variables (types allowed)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "input.session",
      "language": "mql5",
      "source": "absent",
      "note": "No session input type exists; use string or datetime inputs, or read the symbol's own sessions with SymbolInfoSessionTrade.",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/basis/types",
        "fragment": "The basic data types are: integers, logical (bool), strings, floating-point, color, datetime, enumerations",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "input.session",
      "language": "ninjascript",
      "source": "present",
      "construct": "two TimeSpan properties ([NinjaScriptProperty][XmlIgnore]) with string twins for serialisation",
      "signature": "public TimeSpan BeginTimeSpan { get; set; }",
      "relation": "composite",
      "note": "No session-range type: use begin and end TimeSpan properties, each with a serialised string twin, and compare against the bar time yourself.",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/ninjascriptpropertyattribute.htm",
        "fragment": "Using a simple type as the NinjaScriptProperty (TimeSpan BeginTimeSpan)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "input.session",
      "language": "pine",
      "source": "present",
      "construct": "input.session()",
      "signature": "input.session(defval, title, options, tooltip, inline, group, confirm, display, active) → input string",
      "relation": "equivalent_with_caveat",
      "note": "Pine accepts an options list of allowed sessions; Lipi's input.session has no options argument.",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_input.session",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "input.session",
      "language": "thinkscript",
      "source": "present",
      "construct": "two integer HHMM inputs with SecondsFromTime / SecondsTillTime",
      "relation": "composite",
      "note": "No session input: take start and end as integer HHMM inputs, then test them with SecondsFromTime and SecondsTillTime (EST).",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Functions/Date---Time/SecondsFromTime",
        "fragment": "input OpenTime = 0930; input DurationHours = 1;",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "input.time",
      "language": "mql4",
      "source": "present",
      "construct": "input datetime",
      "relation": "equivalent_with_caveat",
      "note": "Plain datetime input counting seconds since 1970 (Lipi uses milliseconds); defaults can be D'yyyy.mm.dd' literals.",
      "differences": [
        {
          "axis": "numeric_types",
          "note": "Seconds, not milliseconds."
        }
      ],
      "evidence": {
        "url": "https://docs.mql4.com/basis/variables/inputvariables",
        "fragment": "complex types can't act as input variables",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "input.time",
      "language": "mql5",
      "source": "present",
      "construct": "input datetime",
      "signature": "input datetime Name = D'2026.01.01 00:00';",
      "relation": "equivalent_with_caveat",
      "note": "datetime counts seconds since 1970, while Lipi time values count milliseconds.",
      "differences": [
        {
          "axis": "numeric_types",
          "note": "Seconds in MQL5, milliseconds in Lipi: scale by 1000 when converting."
        }
      ],
      "evidence": {
        "url": "https://www.mql5.com/en/docs/basis/types/integer/datetime",
        "fragment": "Datetime Type: seconds since January 01, 1970; D'...' literals",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "input.time",
      "language": "ninjascript",
      "source": "present",
      "construct": "[Range(typeof(DateTime), min, max)] public DateTime Name { get; set; }",
      "signature": "[Range(typeof(DateTime), \"01/01/1990\", \"12/31/2015\")]",
      "relation": "equivalent_with_caveat",
      "note": "A DateTime property with an optional Range attribute giving date bounds; the value is a DateTime, not epoch milliseconds.",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/rangeattribute.htm",
        "fragment": "Range(typeof(DateTime), ...) example",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "input.time",
      "language": "pine",
      "source": "present",
      "construct": "input.time()",
      "signature": "input.time(defval, title, tooltip, inline, group, confirm, display, active) → input int",
      "relation": "equivalent_with_caveat",
      "note": "Pine allows a timestamp() of a constant date string as the default; Lipi needs an integer millisecond literal.",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_input.time",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "input.time",
      "language": "thinkscript",
      "source": "present",
      "construct": "input <name> = <YYYYMMDD integer>",
      "relation": "equivalent_with_caveat",
      "note": "No date picker: dates are integers in YYYYMMDD form compared with GetYYYYMMDD(); times of day are HHMM integers.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Functions/Date---Time/GetYYYYMMDD",
        "fragment": "input endDate = 20100101; def cond = GetYYYYMMDD() < endDate;",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "input.price",
      "language": "mql4",
      "source": "present",
      "construct": "input double",
      "relation": "equivalent_with_caveat",
      "note": "No price-level input type; a plain double input is used.",
      "evidence": {
        "url": "https://docs.mql4.com/basis/variables/inputvariables",
        "fragment": "Input Variables",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "input.price",
      "language": "mql5",
      "source": "absent",
      "note": "No price input type exists; use input double.",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/basis/types",
        "fragment": "no special data type for price data is provided in MQL5",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "input.price",
      "language": "ninjascript",
      "source": "present",
      "construct": "[NinjaScriptProperty] public double Name { get; set; }",
      "relation": "equivalent_with_caveat",
      "note": "No price-level input type or chart picker; a plain double property holds the level.",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/creating_user_defined_input_pa.htm",
        "fragment": "Use the following template code for each parameter",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "input.price",
      "language": "pine",
      "source": "present",
      "construct": "input.price()",
      "signature": "input.price(defval, title, tooltip, inline, group, confirm, display, active) → input float",
      "relation": "equivalent_with_caveat",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_input.price",
        "accessed": "2026-11-01"
      },
      "verified": "documented",
      "note": "Pine accepts an active argument that greys out the input; Lipi rejects it as an unknown named argument, so it must be dropped."
    },
    {
      "concept": "input.price",
      "language": "thinkscript",
      "source": "present",
      "construct": "input <name> = <decimal>",
      "relation": "equivalent_with_caveat",
      "note": "A price level is just a float input with no chart picking; the keyword price here means a data source, not a level.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Reserved-Words/input/price",
        "fragment": "Draws the EMA ... The type of price data can be adjusted using the correspondent input, which is set to close by default",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "input.enum",
      "language": "mql4",
      "source": "present",
      "construct": "enum plus input",
      "relation": "equivalent_with_caveat",
      "note": "Declare an enum, then input EnumName x=Member; comments on members become the dropdown labels.",
      "evidence": {
        "url": "https://docs.mql4.com/basis/variables/inputvariables",
        "fragment": "Enumerations as input Parameters",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "input.enum",
      "language": "mql5",
      "source": "present",
      "construct": "input <enum type>",
      "signature": "input MyEnum Name = MyEnum_Value;",
      "relation": "equivalent_with_caveat",
      "note": "Dropdown shows member names, or comments attached to the members.",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/basis/variables/inputvariables",
        "fragment": "enumerations as input variables show a drop-down list; mnemonic names or comments",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "input.enum",
      "language": "ninjascript",
      "source": "present",
      "construct": "enum (C#) used as a public property type",
      "relation": "equivalent_with_caveat",
      "note": "Declare the enum separately, then use it as a public property type; the user picks from its hard-coded members.",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/creating_a_user-defined_parame.htm",
        "fragment": "Creating a user-defined parameter type (enum)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "input.enum",
      "language": "pine",
      "source": "present",
      "construct": "input.enum()",
      "signature": "input.enum(defval, title, options, tooltip, inline, group, confirm, display, active) → input enum",
      "relation": "equivalent_with_caveat",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_input.enum",
        "accessed": "2026-11-01"
      },
      "verified": "documented",
      "note": "Pine accepts an active argument that greys out the input; Lipi rejects it as an unknown named argument, so it must be dropped."
    },
    {
      "concept": "input.enum",
      "language": "thinkscript",
      "source": "present",
      "construct": "input <name> = {default A, B, C}",
      "signature": "input <input name>={default <enum_value_used_by_default>, <enum_value_1>, ... <enum_value_N>};",
      "relation": "equivalent_with_caveat",
      "note": "Options are listed inline in the input with one default; there is no separate enum declaration to reuse.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Reserved-Words/input/enum",
        "fragment": "one value (not necessarily the first) is declared default using the default reserved word",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "input.layout",
      "language": "mql4",
      "source": "absent",
      "note": "No grouping or inline placement; the only layout aid is a trailing // comment of up to 63 characters used as the label.",
      "evidence": {
        "url": "https://docs.mql4.com/basis/variables/inputvariables",
        "fragment": "Input Variables (comment note)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "input.layout",
      "language": "mql5",
      "source": "present",
      "construct": "input group",
      "signature": "input group \"Group name\"",
      "relation": "equivalent_with_caveat",
      "note": "Group headings exist, but the docs describe no option to place several inputs on one line.",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/basis/variables/inputvariables",
        "fragment": "input group keyword divides parameters into named blocks",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "input.layout",
      "language": "ninjascript",
      "source": "present",
      "construct": "[Display(GroupName=..., Order=...)]",
      "signature": "[Display(Name=\"My Period\", Order=1, GroupName=\"My Parameters\")]",
      "relation": "equivalent_with_caveat",
      "note": "GroupName groups settings under a heading and Order sorts them; no way to place several settings on one line is documented.",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/displayattribute.htm",
        "fragment": "Display(GroupName=string), Display(Order=int)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "input.layout",
      "language": "pine",
      "source": "present",
      "construct": "group, inline and tooltip arguments of the input.* functions",
      "relation": "exact",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_input.int (group, inline)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "input.layout",
      "language": "thinkscript",
      "source": "absent",
      "note": "No groups or inline rows; inputs appear in source order and their names cannot contain spaces unless quoted.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Reserved-Words/input",
        "fragment": "Inputs are displayed on the GUI in the same order as they appear in the source code",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "plot.line",
      "language": "mql4",
      "source": "present",
      "construct": "SetIndexBuffer + SetIndexStyle(DRAW_LINE)",
      "signature": "void SetIndexStyle(int index, int type, int style=EMPTY, int width=EMPTY, color clr=clrNONE)",
      "relation": "composite",
      "note": "Bind a double array with SetIndexBuffer, set style with SetIndexStyle, then write each bar's value into the array; at most 8 lines.",
      "differences": [
        {
          "axis": "history_indexing",
          "note": "Buffer array index 0 is the oldest bar unless ArraySetAsSeries is called."
        }
      ],
      "evidence": {
        "url": "https://docs.mql4.com/customind/setindexstyle",
        "fragment": "SetIndexStyle index 0 to 7",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "plot.line",
      "language": "mql5",
      "source": "present",
      "construct": "SetIndexBuffer + #property indicator_type1 DRAW_LINE",
      "signature": "bool SetIndexBuffer(int index, double buffer[], ENUM_INDEXBUFFER_TYPE data_type)",
      "relation": "composite",
      "note": "Needs a double buffer bound with SetIndexBuffer, indicator_buffers and indicator_plots counts, a draw type, and your loop writing each bar's value.",
      "differences": [
        {
          "axis": "history_indexing",
          "note": "Buffers index from the oldest bar unless flagged as series."
        }
      ],
      "evidence": {
        "url": "https://www.mql5.com/en/docs/customind/setindexbuffer",
        "fragment": "SetIndexBuffer: INDICATOR_DATA, INDICATOR_COLOR_INDEX, INDICATOR_CALCULATIONS",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "plot.line",
      "language": "ninjascript",
      "source": "present",
      "construct": "AddPlot(); Values[i][0] = x",
      "signature": "AddPlot(Brush brush, string name)",
      "relation": "equivalent_with_caveat",
      "note": "Plots are declared once in OnStateChange; each bar you assign Values[i][0]. Plots show only after BarsRequiredToPlot bars (default 20).",
      "differences": [
        {
          "axis": "warmup_and_na",
          "note": "A 20-bar delay applies before any plot value appears unless BarsRequiredToPlot is changed."
        }
      ],
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/addplot.htm",
        "fragment": "AddPlot() Syntax and Tips (BarsRequiredToPlot)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "plot.line",
      "language": "pine",
      "source": "present",
      "construct": "plot()",
      "signature": "plot(series, title, color, linewidth, style, trackprice, histbase, offset, join, editable, show_last, display, format, precision, force_overlay, linestyle) → plot",
      "relation": "equivalent_with_caveat",
      "note": "Pine plot has extra arguments Lipi lacks: join, editable, show_last, precision and linestyle.",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_plot",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "plot.line",
      "language": "thinkscript",
      "source": "present",
      "construct": "plot",
      "signature": "plot <plot_name>=<expression>; | plot <plot_name>; <plot_name>=<expression>;",
      "relation": "equivalent_with_caveat",
      "note": "A named statement; colour and style come from methods such as SetDefaultColor(); the plot may be declared first and assigned inside if.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Reserved-Words/plot",
        "fragment": "You can separate the plot definition from its value assignment",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "plot.style",
      "language": "mql4",
      "source": "present",
      "construct": "DRAW_LINE, DRAW_SECTION, DRAW_HISTOGRAM, DRAW_ARROW, DRAW_ZIGZAG, DRAW_NONE",
      "relation": "equivalent_with_caveat",
      "note": "Only six draw styles; no area, step, circles or cross styles. Line styles solid, dash, dot, dash-dot, dash-dot-dot; width 1 to 5.",
      "evidence": {
        "url": "https://docs.mql4.com/constants/indicatorconstants/drawstyles",
        "fragment": "Drawing Styles table",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "plot.style",
      "language": "mql5",
      "source": "present",
      "construct": "ENUM_DRAW_TYPE (DRAW_LINE, DRAW_SECTION, DRAW_HISTOGRAM, DRAW_ARROW, DRAW_ZIGZAG, DRAW_FILLING ...)",
      "relation": "equivalent_with_caveat",
      "note": "Eighteen draw types chosen per plot; styles needing several buffers consume them in order, and colour variants add a colour-index buffer.",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/constants/indicatorconstants/drawstyles",
        "fragment": "ENUM_DRAW_TYPE table of data and color buffers",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "plot.style",
      "language": "ninjascript",
      "source": "present",
      "construct": "PlotStyle enum",
      "signature": "AddPlot(Stroke stroke, PlotStyle plotStyle, string name)",
      "relation": "equivalent_with_caveat",
      "note": "Listed styles: Bar (histogram-like), Block, Cross, Dot, Hash, HLine, Line, PriceBox, Square and four triangles. No area or step style is listed.",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/addplot.htm",
        "fragment": "plotStyle parameter, possible values",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "plot.style",
      "language": "pine",
      "source": "present",
      "construct": "plot.style_line, style_linebr, style_area, style_areabr, style_histogram, style_columns, style_circles, style_cross, style_stepline, style_steplinebr, style_stepline_diamond",
      "relation": "equivalent_with_caveat",
      "note": "Constants become plotStyle.X: columns is bar, circles is scatter, stepline is stepLine. stepline_diamond has no Lipi member.",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "const_plot.style_line; fun_plot (style)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "plot.style",
      "language": "thinkscript",
      "source": "present",
      "construct": "SetPaintingStrategy(PaintingStrategy.*)",
      "signature": "SetPaintingStrategy(int paintingStrategy)",
      "relation": "equivalent_with_caveat",
      "note": "Style is a method on the plot using PaintingStrategy constants such as LINE, HISTOGRAM, POINTS, SQUARES, DASHES and HORIZONTAL; names differ from plotStyle.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Functions/Look---Feel/SetPaintingStrategy",
        "fragment": "Data.SetPaintingStrategy(PaintingStrategy.HISTOGRAM);",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "plot.shape",
      "language": "mql4",
      "source": "present",
      "construct": "DRAW_ARROW + SetIndexArrow(index, code)",
      "relation": "composite",
      "note": "One arrow glyph code per buffer, drawn at the buffer value; no above/below placement, so set the value to high plus an offset yourself.",
      "evidence": {
        "url": "https://docs.mql4.com/customind/setindexarrow",
        "fragment": "SetIndexArrow code range 33 to 255",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "plot.shape",
      "language": "mql5",
      "source": "present",
      "construct": "DRAW_ARROW with PLOT_ARROW (Wingdings code); OBJ_ARROW objects",
      "relation": "composite",
      "note": "Draws a Wingdings symbol where the buffer holds a value; the condition becomes a buffer filled with a price or EMPTY_VALUE.",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/customind/indicators_examples/draw_arrow",
        "fragment": "DRAW_ARROW: PLOT_ARROW, PLOT_ARROW_SHIFT, empty values not drawn",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "plot.shape",
      "language": "ninjascript",
      "source": "present",
      "construct": "Draw.TriangleUp / TriangleDown / Diamond / Dot / Square, or PlotStyle.TriangleUp",
      "relation": "composite",
      "note": "No plotshape call: draw an object per bar with a unique tag (often CurrentBar in the tag) at a y price you offset yourself.",
      "differences": [
        {
          "axis": "state_and_side_effects",
          "note": "Reusing a tag edits the same object; unique tags create one object per bar."
        }
      ],
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/drawing.htm",
        "fragment": "Draw Methods and Associated Return Types; note 2 on unique tag values",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "plot.shape",
      "language": "pine",
      "source": "present",
      "construct": "plotshape()",
      "signature": "plotshape(series, title, style, location, color, offset, text, textcolor, editable, size, show_last, display, format, precision, force_overlay) → void",
      "relation": "equivalent_with_caveat",
      "note": "Pine's style argument is named shape in Lipi; the shape.* and location.* constants keep their names and positions line up.",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_plotshape",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "plot.shape",
      "language": "thinkscript",
      "source": "present",
      "construct": "SetPaintingStrategy(PaintingStrategy.BOOLEAN_ARROW_UP / BOOLEAN_ARROW_DOWN / BOOLEAN_WEDGE_UP / BOOLEAN_WEDGE_DOWN / BOOLEAN_POINTS)",
      "relation": "equivalent_with_caveat",
      "note": "Plot a true/false condition and pick a boolean painting strategy; shapes are limited to arrows, wedges and points, placed by the constant.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Constants/PaintingStrategy/PaintingStrategy-BOOLEAN-ARROW-UP",
        "fragment": "mark true values with up arrows below low prices of corresponding bars",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "plot.char",
      "language": "mql4",
      "source": "present",
      "construct": "DRAW_ARROW + SetIndexArrow(index, Wingdings code); OBJ_TEXT",
      "relation": "composite",
      "note": "A glyph is a Wingdings code per buffer, not a free character; arbitrary text needs an OBJ_TEXT object.",
      "evidence": {
        "url": "https://docs.mql4.com/customind/setindexarrow",
        "fragment": "Symbol code from Wingdings font",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "plot.char",
      "language": "mql5",
      "source": "present",
      "construct": "DRAW_ARROW with PLOT_ARROW",
      "relation": "equivalent_with_caveat",
      "note": "Characters come from the Wingdings set by code number (default 159); vertical offset in pixels via PLOT_ARROW_SHIFT.",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/customind/indicators_examples/draw_arrow",
        "fragment": "PLOT_ARROW Wingdings code, default 159; PLOT_ARROW_SHIFT",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "plot.char",
      "language": "ninjascript",
      "source": "present",
      "construct": "Draw.Text(owner, tag, text, barsAgo, y, textBrush)",
      "signature": "Draw.Text(NinjaScriptBase owner, string tag, string text, int barsAgo, double y, Brush textBrush)",
      "relation": "composite",
      "note": "Draw.Text per bar with the character as text and a unique tag; position is a y price you compute, not above or below the bar.",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/draw_text.htm",
        "fragment": "Draw.Text() Syntax",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "plot.char",
      "language": "pine",
      "source": "present",
      "construct": "plotchar()",
      "signature": "plotchar(series, title, char, location, color, offset, text, textcolor, editable, size, show_last, display, format, precision, force_overlay) → void",
      "relation": "equivalent_with_caveat",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_plotchar",
        "accessed": "2026-11-01"
      },
      "verified": "documented",
      "note": "Lipi plotchar lacks editable, show_last, precision; positional order differs after textcolor; float series draw at that price, whereas Pine treats them as bool."
    },
    {
      "concept": "plot.char",
      "language": "thinkscript",
      "source": "present",
      "construct": "AddChartBubble",
      "signature": "AddChartBubble(boolean time condition, double price location, Any text, CustomColor color, boolean up)",
      "relation": "equivalent_with_caveat",
      "note": "Nearest form is a text bubble pointing at a price you choose; there is no single-character marker with location presets.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Functions/Look---Feel/AddChartBubble",
        "fragment": "AddChartBubble ( boolean time condition , double price location , Any text , CustomColor color , boolean up )",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "plot.arrow",
      "language": "mql4",
      "source": "present",
      "construct": "DRAW_ARROW with up and down buffers",
      "relation": "composite",
      "note": "Arrow direction is not driven by value sign; use one buffer per direction with matching arrow codes, or arrow objects.",
      "evidence": {
        "url": "https://docs.mql4.com/customind/setindexarrow",
        "fragment": "predefined arrow constant",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "plot.arrow",
      "language": "mql5",
      "source": "present",
      "construct": "DRAW_COLOR_ARROW; OBJ_ARROW_UP; OBJ_ARROW_DOWN",
      "relation": "composite",
      "note": "Direction does not follow a value's sign: use two arrow plots, or one colour-indexed arrow plot, each fed by your own buffers.",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/constants/indicatorconstants/drawstyles",
        "fragment": "DRAW_ARROW and DRAW_COLOR_ARROW rows",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "plot.arrow",
      "language": "ninjascript",
      "source": "present",
      "construct": "Draw.ArrowUp() / Draw.ArrowDown()",
      "signature": "Draw.ArrowUp(NinjaScriptBase owner, string tag, bool isAutoScale, int barsAgo, double y, Brush brush)",
      "relation": "composite",
      "note": "Choose ArrowUp or ArrowDown yourself from the sign of the value; each call needs a unique tag and a y price. Size follows bar width.",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/draw_arrowup.htm",
        "fragment": "Draw.ArrowUp() Syntax and Tip",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "plot.arrow",
      "language": "pine",
      "source": "present",
      "construct": "plotarrow()",
      "signature": "plotarrow(series, title, colorup, colordown, offset, minheight, maxheight, editable, show_last, display, format, precision, force_overlay) → void",
      "relation": "equivalent_with_caveat",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_plotarrow",
        "accessed": "2026-11-01"
      },
      "verified": "documented",
      "note": "Lipi plotarrow omits editable, show_last and precision, and its positional order after maxheight differs from Pine."
    },
    {
      "concept": "plot.arrow",
      "language": "thinkscript",
      "source": "present",
      "construct": "PaintingStrategy.ARROW_UP / PaintingStrategy.ARROW_DOWN",
      "relation": "composite",
      "note": "Direction comes from the constant, not from the sign of a value: plot two series, one with ARROW_UP and one with ARROW_DOWN.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Constants/PaintingStrategy/PaintingStrategy-ARROW-UP",
        "fragment": "PaintingStrategy.ARROW_UP: Defines the arrow up painting strategy",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "plot.candles",
      "language": "mql4",
      "source": "absent",
      "note": "No candle or bar draw style among the six; build wicks and bodies from histogram buffers or objects.",
      "evidence": {
        "url": "https://docs.mql4.com/constants/indicatorconstants/drawstyles",
        "fragment": "Drawing Styles table",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "plot.candles",
      "language": "mql5",
      "source": "present",
      "construct": "DRAW_CANDLES; DRAW_BARS; DRAW_COLOR_CANDLES",
      "relation": "equivalent_with_caveat",
      "note": "Four buffers in fixed order open, high, low, close, plus a colour-index buffer for the colour variants.",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/customind/indicators_examples/draw_color_candles",
        "fragment": "DRAW_COLOR_CANDLES: five buffers Open, High, Low, Close, color index",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "plot.candles",
      "language": "ninjascript",
      "source": "absent",
      "note": "No custom-OHLC plot call. Draw per-bar Draw.Rectangle and Draw.Line, custom-render in OnRender, or build a custom bars type.",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/alphabetical_reference.htm",
        "fragment": "Alphabetical list: Draw.* methods and BarBrush, no candle-plot entry",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "plot.candles",
      "language": "pine",
      "source": "present",
      "construct": "plotcandle(), plotbar()",
      "signature": "plotcandle(open, high, low, close, title, color, wickcolor, editable, show_last, bordercolor, display, format, precision, force_overlay) → void",
      "relation": "equivalent_with_caveat",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_plotcandle; fun_plotbar",
        "accessed": "2026-11-01"
      },
      "verified": "documented",
      "note": "Lipi plotcandle and plotbar omit editable, show_last, format and precision; bordercolor sits earlier in Lipi's positional order."
    },
    {
      "concept": "plot.candles",
      "language": "thinkscript",
      "source": "absent",
      "note": "No function draws computed open-high-low-close candles or bars; Look and Feel only recolours the chart's own bars (AssignPriceColor) or sets the chart type.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Functions/Look---Feel",
        "fragment": "Look and Feel function list (26 entries: AddLabel, AddCloud, AssignPriceColor, SetChartType, ...; none draws candles)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "plot.hline",
      "language": "mql4",
      "source": "present",
      "construct": "#property indicator_levelN / SetLevelValue(level, value) / OBJ_HLINE",
      "relation": "equivalent_with_caveat",
      "note": "Levels (0 to 31) show only in a separate-window indicator; on the main chart use an OBJ_HLINE object.",
      "evidence": {
        "url": "https://docs.mql4.com/customind/setlevelvalue",
        "fragment": "SetLevelValue level 0-31",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "plot.hline",
      "language": "mql5",
      "source": "present",
      "construct": "#property indicator_level1; indicator_levelcolor; OBJ_HLINE",
      "relation": "equivalent_with_caveat",
      "note": "Levels apply only in a separate indicator window; on the price chart use an OBJ_HLINE object instead.",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/basis/preprosessor/compilation",
        "fragment": "indicator_levelN: horizontal level in a separate indicator window",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "plot.hline",
      "language": "ninjascript",
      "source": "present",
      "construct": "AddLine(Brush, double value, string name)",
      "signature": "AddLine(Brush brush, double value, string name)",
      "relation": "equivalent_with_caveat",
      "note": "The level is fixed when the script is configured. For a level that moves per bar use Draw.HorizontalLine or a plot.",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/addline.htm",
        "fragment": "AddLine() Syntax",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "plot.hline",
      "language": "pine",
      "source": "present",
      "construct": "hline()",
      "signature": "hline(price, title, color, linestyle, linewidth, editable, display) → hline",
      "relation": "equivalent_with_caveat",
      "note": "Pine takes linestyle (hline.style_*) before linewidth; Lipi orders linewidth first, names the argument style and uses hlineStyle.*.",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_hline",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "plot.hline",
      "language": "thinkscript",
      "source": "present",
      "construct": "plot <name> = <constant>",
      "relation": "equivalent_with_caveat",
      "note": "A horizontal level is a plot of a constant, for example plot ZeroLine = 0; there is no dedicated hline call.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Functions/Others/FPL",
        "fragment": "plot ZeroLine = 0;",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "plot.fill",
      "language": "mql4",
      "source": "absent",
      "note": "No fill draw style between plots or levels; use DRAW_HISTOGRAM or rectangle objects as a stand-in.",
      "evidence": {
        "url": "https://docs.mql4.com/constants/indicatorconstants/drawstyles",
        "fragment": "Drawing Styles table",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "plot.fill",
      "language": "mql5",
      "source": "present",
      "construct": "DRAW_FILLING",
      "relation": "equivalent_with_caveat",
      "note": "Needs two buffers; both colours are set together with #property indicator_color1 or PLOT_LINE_COLOR.",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/customind/indicators_examples/draw_filling",
        "fragment": "DRAW_FILLING: colored area between two indicator buffers",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "plot.fill",
      "language": "ninjascript",
      "source": "present",
      "construct": "Draw.Region()",
      "signature": "Draw.Region(NinjaScriptBase owner, string tag, int startBarsAgo, int endBarsAgo, ISeries<double> series1, ISeries<double> series2, Brush outlineBrush, Brush areaBrush, int areaOpacity, int displacement = 0)",
      "relation": "equivalent_with_caveat",
      "note": "One call fills over a bar range (CurrentBar down to 0) between two series, or a series and a price. Opacity is int 0-100.",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/draw_region.htm",
        "fragment": "Draw.Region() Syntax and Example",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "plot.fill",
      "language": "pine",
      "source": "present",
      "construct": "fill()",
      "signature": "fill(plot1, plot2, color, title, editable, show_last, fillgaps, display) → void",
      "relation": "equivalent_with_caveat",
      "note": "Pine's plot form takes color third; Lipi's plot form takes title third and color fourth. Name the arguments when converting.",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_fill",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "plot.fill",
      "language": "thinkscript",
      "source": "present",
      "construct": "AddCloud",
      "signature": "AddCloud(IDataHolder data1, IDataHolder data2, CustomColor color1, CustomColor color2)",
      "relation": "equivalent_with_caveat",
      "note": "Takes two colours chosen by which series is higher, is translucent with no alpha argument, and its border is off unless showBorder is yes.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Functions/Look---Feel/AddCloud",
        "fragment": "Plots a translucent cloud bounded above and below by values data1 and data2",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "plot.bgcolor",
      "language": "mql4",
      "source": "absent",
      "note": "No per-bar background colouring; closest are rectangle objects behind price.",
      "evidence": {
        "url": "https://docs.mql4.com/constants/indicatorconstants/drawstyles",
        "fragment": "Drawing Styles table",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "plot.bgcolor",
      "language": "mql5",
      "source": "absent",
      "note": "No per-bar background colouring; the chart property CHART_COLOR_BACKGROUND recolours the whole chart only.",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/constants/chartconstants/enum_chart_property",
        "fragment": "CHART_COLOR_BACKGROUND: chart background color",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "plot.bgcolor",
      "language": "ninjascript",
      "source": "present",
      "construct": "BackBrush",
      "signature": "BackBrush = Brushes.PaleGreen;",
      "relation": "equivalent_with_caveat",
      "note": "Assign BackBrush on each bar; null restores the default colour (Lipi uses na). It affects only the script's own panel; BackBrushAll covers all panels.",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/backbrush.htm",
        "fragment": "BackBrush Definition and Note",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "plot.bgcolor",
      "language": "pine",
      "source": "present",
      "construct": "bgcolor()",
      "signature": "bgcolor(color, offset, editable, show_last, title, display, force_overlay) → void",
      "relation": "equivalent_with_caveat",
      "note": "Pine orders offset before title; Lipi orders title before offset, so name these arguments when converting. Pine adds editable and show_last.",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_bgcolor",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "plot.bgcolor",
      "language": "thinkscript",
      "source": "present",
      "construct": "AssignBackgroundColor",
      "signature": "AssignBackgroundColor(CustomColor color)",
      "relation": "equivalent_with_caveat",
      "note": "Takes a colour value chosen per bar with an if-expression; no transparency argument; also colours custom-quote cells.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Functions/Look---Feel/AssignBackgroundColor",
        "fragment": "AssignBackgroundColor(if ADX > 20 then Color.DARK_ORANGE else Color.BLACK);",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "plot.barcolor",
      "language": "mql4",
      "source": "absent",
      "note": "No draw style recolours existing price bars; overlay arrows, histograms or objects instead.",
      "evidence": {
        "url": "https://docs.mql4.com/constants/indicatorconstants/drawstyles",
        "fragment": "Drawing Styles table",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "plot.barcolor",
      "language": "mql5",
      "source": "present",
      "construct": "DRAW_COLOR_CANDLES; DRAW_COLOR_BARS",
      "relation": "equivalent_with_caveat",
      "note": "Draws candles or bars from your own OHLC buffers plus a colour-index buffer, rather than recolouring the chart's own bars.",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/customind/indicators_examples/draw_color_candles",
        "fragment": "DRAW_COLOR_CANDLES colour index buffer chooses each candle's colour",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "plot.barcolor",
      "language": "ninjascript",
      "source": "present",
      "construct": "BarBrush",
      "signature": "BarBrush = Brushes.Yellow;",
      "relation": "equivalent_with_caveat",
      "note": "Assign BarBrush on each bar; null restores the chart's default bar colour. CandleOutlineBrush colours candle outlines separately.",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/barbrush.htm",
        "fragment": "BarBrush Tip and Examples",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "plot.barcolor",
      "language": "pine",
      "source": "present",
      "construct": "barcolor()",
      "signature": "barcolor(color, offset, editable, show_last, title, display) → void",
      "relation": "equivalent_with_caveat",
      "note": "Pine orders offset before title; Lipi orders title before offset, so name these arguments when converting. Pine adds editable and show_last.",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_barcolor",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "plot.barcolor",
      "language": "thinkscript",
      "source": "present",
      "construct": "AssignPriceColor",
      "signature": "AssignPriceColor(CustomColor color)",
      "relation": "equivalent_with_caveat",
      "note": "Color.CURRENT leaves a bar unchanged; only one study at a time can paint a given price bar.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Functions/Look---Feel/AssignPriceColor",
        "fragment": "you cannot paint the same price bar using multiple studies simultaneously",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "plot.display",
      "language": "mql4",
      "source": "present",
      "construct": "DRAW_NONE; SetIndexLabel(index, NULL)",
      "relation": "equivalent_with_caveat",
      "note": "DRAW_NONE hides the line on the chart; a NULL label hides the value in the DataWindow. There is no price-scale-only switch.",
      "evidence": {
        "url": "https://docs.mql4.com/customind/setindexlabel",
        "fragment": "NULL means that index value is not shown in the DataWindow",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "plot.display",
      "language": "mql5",
      "source": "present",
      "construct": "PLOT_SHOW_DATA; DRAW_NONE; INDICATOR_CALCULATIONS buffers",
      "relation": "equivalent_with_caveat",
      "note": "DRAW_NONE draws nothing, PLOT_SHOW_DATA toggles the Data Window entry, calculation buffers are never drawn: separate switches.",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/constants/indicatorconstants/drawstyles",
        "fragment": "DRAW_NONE; PLOT_SHOW_DATA data window display",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "plot.display",
      "language": "ninjascript",
      "source": "present",
      "construct": "DisplayInDataBox, PaintPriceMarkers, IsOverlay, DrawOnPricePanel",
      "relation": "composite",
      "note": "No per-plot display flag: separate properties control the data box, price markers, panel, and the panel used by draw objects.",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/indicator.htm",
        "fragment": "Methods and Properties: DisplayInDataBox, DrawOnPricePanel, PaintPriceMarkers",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "plot.display",
      "language": "pine",
      "source": "present",
      "construct": "display argument; display.none, all, pane, data_window, price_scale, status_line",
      "relation": "equivalent_with_caveat",
      "note": "Pine display constants combine with + and -; Lipi supports + only. display.pine_screener has no Lipi member.",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "const_display.all",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "plot.display",
      "language": "thinkscript",
      "source": "present",
      "construct": "Hide(), SetHiding(), HideTitle(), HideBubble(), declare hide_on_intraday",
      "signature": "SetHiding(double condition)",
      "relation": "composite",
      "note": "Visibility only: Hide() sets hidden by default and SetHiding(cond) hides conditionally; the reference lists no data-window or scale targets.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Functions/Look---Feel/SetHiding",
        "fragment": "Controls visibility of a plot depending on a condition. If this condition is true, the plot is hidden",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "color.transparency",
      "language": "mql4",
      "source": "present",
      "construct": "ColorToARGB(clr, alpha)",
      "signature": "uint ColorToARGB(color clr, uchar alpha=255)",
      "relation": "different_semantics",
      "note": "Alpha is a 0 to 255 byte (Lipi: 0 to 1); result is a uint for graphical resources; the color type has no alpha.",
      "differences": [
        {
          "axis": "numeric_types",
          "note": "Alpha scale 0-255 versus Lipi 0-1; returns uint, not a color."
        }
      ],
      "evidence": {
        "url": "https://docs.mql4.com/convert/colortoargb",
        "fragment": "ColorToARGB alpha channel",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "color.transparency",
      "language": "mql5",
      "source": "present",
      "construct": "ColorToARGB(color, alpha)",
      "signature": "uint ColorToARGB(color clr, uchar alpha=255)",
      "relation": "different_semantics",
      "note": "Alpha runs 0 to 255 (255 replaces the underlying pixel), not 0 to 1, and the result is a uint ARGB value, not a color.",
      "differences": [
        {
          "axis": "numeric_types",
          "note": "The color type itself has no alpha byte (0x00BBGGRR); opacity exists only in the ARGB uint."
        }
      ],
      "evidence": {
        "url": "https://www.mql5.com/en/docs/convert/colortoargb",
        "fragment": "ColorToARGB(color clr, uchar alpha=255): alpha 0 to 255",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "color.transparency",
      "language": "ninjascript",
      "source": "present",
      "construct": "new SolidColorBrush(Color.FromArgb(a, r, g, b)); areaOpacity argument",
      "signature": "Draw.Rectangle(..., Brush areaBrush, int areaOpacity)",
      "relation": "different_semantics",
      "note": "Draw areaOpacity runs 0-100 (0 clear); custom brushes use FromArgb alpha. Lipi alpha is 0-1, so a literal 50 clamps to solid.",
      "differences": [
        {
          "axis": "numeric_types",
          "note": "areaOpacity is an int 0-100; Lipi alpha is a float 0-1. Custom brushes must also be frozen."
        }
      ],
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/working_with_brushes.htm",
        "fragment": "Creating a Transparent Solid Color Brush; Draw.Rectangle areaOpacity (0-100)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "color.transparency",
      "language": "pine",
      "source": "present",
      "construct": "color.new()",
      "signature": "color.new(color, transp) → series color",
      "relation": "different_semantics",
      "note": "transp runs 0 (opaque) to 100 (invisible); Lipi's alpha runs 0 (invisible) to 1 (solid). Convert with alpha = 1 - transp / 100.",
      "differences": [
        {
          "axis": "numeric_types",
          "note": "Pine takes transparency 0-100 with 0 solid; Lipi takes opacity 0-1 with 1 solid, so the same number means opposite things."
        }
      ],
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_color.new (transp argument)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "color.transparency",
      "language": "thinkscript",
      "source": "absent",
      "note": "CreateColor takes only red, green and blue, and no colour function has an alpha argument; AddCloud is fixed translucent.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Functions/Look---Feel/CreateColor",
        "fragment": "CreateColor ( double red , double green , double blue )",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "color.rgb",
      "language": "mql4",
      "source": "present",
      "construct": "C'r,g,b' literal; 0x00BBGGRR integer",
      "relation": "different_semantics",
      "note": "No rgb function: colours are compile-time literals or an integer in blue-green-red byte order, the reverse of the usual RGB order.",
      "differences": [
        {
          "axis": "numeric_types",
          "note": "Byte order is BGR, so a hex value written as RGB gives wrong colour."
        }
      ],
      "evidence": {
        "url": "https://docs.mql4.com/basis/types/integer/color",
        "fragment": "Literal representation; 0x00BBGGRR",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "color.rgb",
      "language": "mql5",
      "source": "present",
      "construct": "C'R,G,B' literal",
      "signature": "color c = C'128,128,128';",
      "relation": "equivalent_with_caveat",
      "note": "Documented as a constant literal, components 0 to 255. At run time, compute the 0x00BBGGRR integer yourself or parse 'R,G,B' text with StringToColor.",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/basis/types/integer/color",
        "fragment": "Color Type: C'R,G,B' literal, 0x00BBGGRR layout",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "color.rgb",
      "language": "ninjascript",
      "source": "present",
      "construct": "new SolidColorBrush(Color.FromRgb(r, g, b)); brush.Freeze()",
      "signature": "Color.FromRgb(byte r, byte g, byte b)",
      "relation": "equivalent_with_caveat",
      "note": "Color.FromRgb gives a Color; wrap it in a SolidColorBrush and freeze it. Prefer predefined Brushes.*; up to 65535 unique brushes are allowed.",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/working_with_brushes.htm",
        "fragment": "Creating a Custom Solid Color Brush",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "color.rgb",
      "language": "pine",
      "source": "present",
      "construct": "color.rgb()",
      "signature": "color.rgb(red, green, blue, transp) → series color",
      "relation": "different_semantics",
      "note": "Fourth argument transp is transparency 0-100 with 0 opaque; Lipi's a is opacity 0-1 with 1 solid. Color components run 0-255 in both.",
      "differences": [
        {
          "axis": "numeric_types",
          "note": "Pine transp 0 is opaque and 100 invisible; Lipi a 1 is opaque and 0 invisible."
        }
      ],
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_color.rgb (transp argument)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "color.rgb",
      "language": "thinkscript",
      "source": "present",
      "construct": "CreateColor",
      "signature": "CreateColor(double red, double green, double blue)",
      "relation": "equivalent_with_caveat",
      "note": "Three components only, no alpha argument; the reference example uses 0 to 255 values.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Functions/Look---Feel/CreateColor",
        "fragment": "Price.SetDefaultColor(CreateColor(255, 220, 210));",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "color.gradient",
      "language": "mql4",
      "source": "absent",
      "note": "No gradient function; interpolate each channel by hand and build the colour from the parts.",
      "evidence": {
        "url": "https://docs.mql4.com/basis/types/integer/color",
        "fragment": "Color Type (no blend function listed)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "color.gradient",
      "language": "mql5",
      "source": "absent",
      "note": "The conversion functions include no gradient or colour-interpolation function; interpolate the R, G, B parts yourself.",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/convert",
        "fragment": "Conversion Functions list: ColorToARGB, ColorToPRGB, ColorToString, StringToColor",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "color.gradient",
      "language": "ninjascript",
      "source": "absent",
      "note": "No value-to-colour interpolation function is in the language reference index. WPF gradient brushes paint areas; they do not map a value to a colour.",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/alphabetical_reference.htm",
        "fragment": "Alphabetical Reference: no gradient entry; Brushes, BackBrush and BarBrush only",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "color.gradient",
      "language": "pine",
      "source": "present",
      "construct": "color.from_gradient()",
      "signature": "color.from_gradient(value, bottom_value, top_value, bottom_color, top_color) → series color",
      "relation": "equivalent_with_caveat",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_color.from_gradient",
        "accessed": "2026-11-01"
      },
      "verified": "documented",
      "note": "Lipi returns na when either end colour is na; for an end with no colour use a fully transparent one, color.new(c, 0)."
    },
    {
      "concept": "color.gradient",
      "language": "thinkscript",
      "source": "present",
      "construct": "AssignNormGradientColor",
      "signature": "AssignNormGradientColor(int length, CustomColor lowestColor, CustomColor highestColor)",
      "relation": "different_semantics",
      "note": "Paints the plot itself; the range is the extremes of the last length bars and the midpoint is fixed at zero, unlike from_gradient's explicit bounds.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Functions/Look---Feel/AssignNormGradientColor",
        "fragment": "The center color of the gradient is always situated on the zero level",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "draw.line",
      "language": "mql4",
      "source": "present",
      "construct": "ObjectCreate(name, OBJ_TREND, window, time1, price1, time2, price2); ObjectDelete(name)",
      "signature": "bool ObjectCreate(string object_name, ENUM_OBJECT object_type, int sub_window, datetime time1, double price1, ...)",
      "relation": "different_semantics",
      "note": "Object is reached by a unique string name (max 63 characters), not a handle; ObjectCreate returns bool; x is a time, not a bar index.",
      "differences": [
        {
          "axis": "state_and_side_effects",
          "note": "Objects stay on the chart until deleted; the name is the only way to reach them."
        }
      ],
      "evidence": {
        "url": "https://docs.mql4.com/objects/objectcreate",
        "fragment": "object_name must be unique; returns bool",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "draw.line",
      "language": "mql5",
      "source": "present",
      "construct": "ObjectCreate with OBJ_TREND; ObjectDelete",
      "signature": "bool ObjectCreate(long chart_id, string name, ENUM_OBJECT type, int sub_window, datetime time1, double price1, ...)",
      "relation": "equivalent_with_caveat",
      "note": "Objects are identified by unique string names, not handles; creation is queued and true only means the command was enqueued.",
      "differences": [
        {
          "axis": "state_and_side_effects",
          "note": "Creating an existing name changes its coordinates instead of failing."
        }
      ],
      "evidence": {
        "url": "https://www.mql5.com/en/docs/objects/objectcreate",
        "fragment": "ObjectCreate: asynchronous call, true means command enqueued; name unique per chart",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "draw.line",
      "language": "ninjascript",
      "source": "present",
      "construct": "Draw.Line(owner, tag, startBarsAgo, startY, endBarsAgo, endY, brush)",
      "signature": "Draw.Line(NinjaScriptBase owner, string tag, int startBarsAgo, double startY, int endBarsAgo, double endY, Brush brush)",
      "relation": "different_semantics",
      "note": "The x anchor is barsAgo (relative to the current bar) or a DateTime, never an absolute bar index. Reusing a tag edits the same line.",
      "differences": [
        {
          "axis": "history_indexing",
          "note": "barsAgo shifts each bar, so a stored value drifts; use a DateTime overload or recompute for fixed anchors."
        }
      ],
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/draw_line.htm",
        "fragment": "Draw.Line() Parameters: tag and startBarsAgo",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "draw.line",
      "language": "pine",
      "source": "present",
      "construct": "line.new(), line.delete()",
      "signature": "line.new(x1, y1, x2, y2, xloc, extend, color, style, width, force_overlay) → series line",
      "relation": "equivalent_with_caveat",
      "note": "Pine spells the overlay argument force_overlay, Lipi's line.new spells it forceOverlay. Pine also has a chart.point overload.",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_line.new",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "draw.line",
      "language": "thinkscript",
      "source": "absent",
      "note": "No drawing objects exist; vertical lines use AddVerticalLine and horizontal levels are plots, and none can be moved or deleted later.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Functions/Look---Feel/AddVerticalLine",
        "fragment": "AddVerticalLine ( boolean visible , Any text , CustomColor color , int stroke )",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "draw.line-update",
      "language": "mql4",
      "source": "present",
      "construct": "ObjectMove, ObjectSetInteger, ObjectSetDouble with OBJPROP_*",
      "relation": "equivalent_with_caveat",
      "note": "Properties are set by OBJPROP id on the object name; width runs 1 to 5, and extension is a ray flag.",
      "evidence": {
        "url": "https://docs.mql4.com/constants/objectconstants/enum_object_property",
        "fragment": "OBJPROP_TIME1, OBJPROP_PRICE1, OBJPROP_COLOR, OBJPROP_STYLE, OBJPROP_WIDTH, OBJPROP_RAY_RIGHT",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "draw.line-update",
      "language": "mql5",
      "source": "present",
      "construct": "ObjectMove; ObjectSetInteger with OBJPROP_COLOR, OBJPROP_WIDTH, OBJPROP_STYLE, OBJPROP_RAY_RIGHT",
      "signature": "bool ObjectMove(long chart_id, string name, int point_index, datetime time, double price)",
      "relation": "composite",
      "note": "Anchor points move with ObjectMove by point index; colour, width, style and ray extension are properties set by identifier through ObjectSetInteger.",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/objects/objectmove",
        "fragment": "ObjectMove: changes coordinates of the specified anchor point",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "draw.line-update",
      "language": "ninjascript",
      "source": "present",
      "construct": "Line.StartAnchor, Line.EndAnchor, Line.Stroke (or Draw.Line again with the same tag)",
      "relation": "equivalent_with_caveat",
      "note": "No setter calls: assign StartAnchor, EndAnchor or Stroke on the returned Line object, or call Draw.Line again with the same tag.",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/line.htm",
        "fragment": "Line Methods and Properties: StartAnchor, EndAnchor, Stroke",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "draw.line-update",
      "language": "pine",
      "source": "present",
      "construct": "line.set_xy1(), set_xy2(), set_color(), set_width(), set_style(), set_extend()",
      "relation": "exact",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_line.set_xy1; fun_line.set_xy2",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "draw.line-update",
      "language": "thinkscript",
      "source": "absent",
      "note": "Nothing to modify: lines are not objects, and AddVerticalLine and plots are declarative per-bar outputs.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Functions/Look---Feel/AddVerticalLine",
        "fragment": "Adds a vertical line with specified text; visible = condition upon which the line is displayed",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "draw.label",
      "language": "mql4",
      "source": "present",
      "construct": "ObjectCreate(... OBJ_TEXT or OBJ_LABEL), ObjectSetString(OBJPROP_TEXT), ObjectDelete",
      "relation": "different_semantics",
      "note": "OBJ_TEXT sits at a time and price; OBJ_LABEL ignores them and uses pixel distance from a chart corner. Both are addressed by name.",
      "evidence": {
        "url": "https://docs.mql4.com/objects/objectcreate",
        "fragment": "Objects of the OBJ_LABEL type ignore the coordinates",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "draw.label",
      "language": "mql5",
      "source": "present",
      "construct": "OBJ_TEXT; OBJ_LABEL; ObjectSetString with OBJPROP_TEXT",
      "relation": "composite",
      "note": "OBJ_TEXT anchors at time and price; OBJ_LABEL anchors by pixel distance from a corner; the text is the OBJPROP_TEXT property.",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/constants/objectconstants/enum_object_property",
        "fragment": "OBJPROP_TEXT, OBJPROP_XDISTANCE, OBJPROP_YDISTANCE, OBJPROP_CORNER",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "draw.label",
      "language": "ninjascript",
      "source": "present",
      "construct": "Draw.Text(owner, tag, text, barsAgo, y, textBrush); RemoveDrawObject(tag)",
      "signature": "Draw.Text(NinjaScriptBase owner, string tag, string text, int barsAgo, double y, Brush textBrush)",
      "relation": "equivalent_with_caveat",
      "note": "Anchor x is barsAgo or a DateTime. The same tag edits the existing text; RemoveDrawObject(tag) deletes it. Fill opacity is 0 to 100.",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/draw_text.htm",
        "fragment": "Draw.Text() Parameters: tag, barsAgo, areaOpacity",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "draw.label",
      "language": "pine",
      "source": "present",
      "construct": "label.new(), label.set_text(), label.set_xy(), label.delete()",
      "signature": "label.new(x, y, text, xloc, yloc, color, style, textcolor, size, textalign, tooltip, text_font_family, force_overlay, text_formatting) → series label",
      "relation": "equivalent_with_caveat",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_label.new",
        "accessed": "2026-11-01"
      },
      "verified": "documented",
      "note": "Pine label.new also has a chart.point overload and accepts numeric size; Lipi takes only the x,y form and size.* constants."
    },
    {
      "concept": "draw.label",
      "language": "thinkscript",
      "source": "present",
      "construct": "AddChartBubble",
      "signature": "AddChartBubble(boolean time condition, double price location, Any text, CustomColor color, boolean up)",
      "relation": "equivalent_with_caveat",
      "note": "Bubble shown on each bar where condition holds, with no handle to move or delete; AddLabel is a corner status line, not a bar label.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Functions/Look---Feel/AddChartBubble",
        "fragment": "Adds a bubble with a text to the specified location when the specified condition is true",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "draw.box",
      "language": "mql4",
      "source": "present",
      "construct": "OBJ_RECTANGLE (time1, price1, time2, price2)",
      "relation": "equivalent_with_caveat",
      "note": "Corners are time and price pairs on a named object; OBJPROP_BACK sets background drawing.",
      "evidence": {
        "url": "https://docs.mql4.com/constants/objectconstants/enum_object",
        "fragment": "OBJ_RECTANGLE",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "draw.box",
      "language": "mql5",
      "source": "present",
      "construct": "OBJ_RECTANGLE; ObjectMove; OBJPROP_FILL",
      "relation": "equivalent_with_caveat",
      "note": "Two time/price anchors are the corners; fill is the OBJPROP_FILL boolean. OBJPROP_BGCOLOR applies only to edit, button and rectangle-label objects.",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/constants/objectconstants/enum_object_property",
        "fragment": "OBJPROP_FILL, OBJPROP_BGCOLOR, OBJPROP_TIME, OBJPROP_PRICE",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "draw.box",
      "language": "ninjascript",
      "source": "present",
      "construct": "Draw.Rectangle(owner, tag, startBarsAgo, startY, endBarsAgo, endY, brush); RemoveDrawObject(tag)",
      "signature": "Draw.Rectangle(NinjaScriptBase owner, string tag, bool isAutoScale, int startBarsAgo, double startY, int endBarsAgo, double endY, Brush brush, Brush areaBrush, int areaOpacity)",
      "relation": "equivalent_with_caveat",
      "note": "Corners are barsAgo or DateTime plus price. Reusing a tag resizes the same box; fill opacity is an int 0 to 100.",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/draw_rectangle.htm",
        "fragment": "Draw.Rectangle() Syntax and areaOpacity",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "draw.box",
      "language": "pine",
      "source": "present",
      "construct": "box.new(), box.set_lefttop(), box.set_rightbottom(), box.delete()",
      "signature": "box.new(left, top, right, bottom, border_color, border_width, border_style, extend, xloc, bgcolor, text, text_size, text_color, text_halign, text_valign, text_wrap, text_font_family, force_overlay, text_formatting) → series box",
      "relation": "equivalent_with_caveat",
      "note": "Pine's text arguments are text_size, text_color, text_halign, text_valign, text_wrap; Lipi renamed them (size, textcolor, texthalign...) and warns on the Pine names.",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_box.new",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "draw.box",
      "language": "thinkscript",
      "source": "absent",
      "note": "No rectangle object; AddCloud shades between two series and AddVerticalLine marks single bars.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Functions/Look---Feel/AddCloud",
        "fragment": "Plots a translucent cloud bounded above and below by values data1 and data2",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "draw.polyline",
      "language": "mql4",
      "source": "absent",
      "note": "No multi-point shape type among the object types; chain several OBJ_TREND segments.",
      "evidence": {
        "url": "https://docs.mql4.com/constants/objectconstants/enum_object",
        "fragment": "Object Types table",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "draw.polyline",
      "language": "mql5",
      "source": "absent",
      "note": "The object type list contains no polyline; chain several OBJ_TREND objects instead.",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/constants/objectconstants/enum_object",
        "fragment": "ENUM_OBJECT list: OBJ_VLINE ... OBJ_RECTANGLE_LABEL (no polyline)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "draw.polyline",
      "language": "ninjascript",
      "source": "present",
      "construct": "Draw.PathTool() / Draw.Polygon()",
      "signature": "Draw.PathTool(NinjaScriptBase owner, string tag, bool isAutoScale, List<ChartAnchor> chartAnchors, Brush brush, DashStyleHelper dashStyle)",
      "relation": "equivalent_with_caveat",
      "note": "PathTool joins an open list of anchors; Polygon closes and fills it. Anchors are ChartAnchor objects (time plus price) or bar/y pairs.",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/draw_pathtool.htm",
        "fragment": "Draw.PathTool() Syntax (List<ChartAnchor> chartAnchors)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "draw.polyline",
      "language": "pine",
      "source": "present",
      "construct": "polyline.new()",
      "signature": "polyline.new(points, curved, closed, xloc, line_color, fill_color, line_style, line_width, force_overlay) → series polyline",
      "relation": "equivalent_with_caveat",
      "note": "Pine polylines can join up to 10,000 points; Lipi caps them at 1,000 and returns na beyond that.",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-docs/visuals/lines-and-boxes/",
        "fragment": "polylines",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "draw.polyline",
      "language": "thinkscript",
      "source": "absent",
      "note": "No multi-point shape object; a path is only expressible as a plotted series.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Functions/Look---Feel",
        "fragment": "Look and Feel function list (26 entries; no shape or polyline function)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "draw.linefill",
      "language": "mql4",
      "source": "absent",
      "note": "No fill between line objects; rectangle, triangle or channel objects are the closest shapes.",
      "evidence": {
        "url": "https://docs.mql4.com/constants/objectconstants/enum_object",
        "fragment": "Object Types table",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "draw.linefill",
      "language": "mql5",
      "source": "absent",
      "note": "No object shades between two line objects; shading between two lines exists only as DRAW_FILLING between indicator buffers.",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/constants/objectconstants/enum_object",
        "fragment": "ENUM_OBJECT list: no fill-between-lines object",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "draw.linefill",
      "language": "ninjascript",
      "source": "present",
      "construct": "Draw.Region()",
      "relation": "equivalent_with_caveat",
      "note": "Region fills between two Series<double> objects (or a series and a price) over a bar range, not between two drawn line objects.",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/draw_region.htm",
        "fragment": "Draw.Region() Parameters: series1, series2",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "draw.linefill",
      "language": "pine",
      "source": "present",
      "construct": "linefill.new()",
      "signature": "linefill.new(line1, line2, color) → series linefill",
      "relation": "exact",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_linefill.new",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "draw.linefill",
      "language": "thinkscript",
      "source": "absent",
      "note": "No line objects to fill between; AddCloud fills between two series instead.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Functions/Look---Feel/AddCloud",
        "fragment": "AddCloud accepts both defined variables and plots as input parameters",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "draw.point",
      "language": "mql4",
      "source": "absent",
      "note": "No point type: anchor points are separate time and price arguments, passed in pairs.",
      "evidence": {
        "url": "https://docs.mql4.com/objects/objectcreate",
        "fragment": "Coordinates must be passed in pairs: time and price",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "draw.point",
      "language": "mql5",
      "source": "present",
      "construct": "datetime time and double price anchor arguments",
      "relation": "equivalent_with_caveat",
      "note": "No point type: each anchor is a separate time and price argument pair; a bar number must first be converted to time (iTime).",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/objects/objectcreate",
        "fragment": "ObjectCreate anchor points time1, price1 ... time30, price30",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "draw.point",
      "language": "ninjascript",
      "source": "present",
      "construct": "ChartAnchor",
      "signature": "new ChartAnchor(DateTime time, double y, ChartControl chartControl)",
      "relation": "equivalent_with_caveat",
      "note": "An anchor is built from a DateTime, a price and the ChartControl. The page shows no separate from-index or from-time constructors.",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/draw_polygon.htm",
        "fragment": "anchors.Add(new ChartAnchor(new DateTime(...), 194, ChartControl))",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "draw.point",
      "language": "pine",
      "source": "present",
      "construct": "chart.point.new(), chart.point.from_index(), chart.point.from_time(), chart.point.now()",
      "signature": "chart.point.new(time, index, price) → chart.point",
      "relation": "equivalent_with_caveat",
      "note": "Pine names the type and functions chart.point.*; Lipi spells them chartPoint.*.",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_chart.point.new",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "draw.point",
      "language": "thinkscript",
      "source": "absent",
      "note": "No chart-point type exists in the data types list; positions come from the bar where a condition is true.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Data-Types",
        "fragment": "full list of available data types",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "draw.x-by-time",
      "language": "mql4",
      "source": "present",
      "construct": "datetime anchors of ObjectCreate",
      "relation": "equivalent_with_caveat",
      "note": "Objects are always placed by datetime; convert a bar shift with Time[shift] or iBarShift. There is no bar-index placement mode.",
      "evidence": {
        "url": "https://docs.mql4.com/objects/objectcreate",
        "fragment": "time1 time coordinate of the first anchor point",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "draw.x-by-time",
      "language": "mql5",
      "source": "present",
      "construct": "ObjectCreate time anchors",
      "relation": "equivalent_with_caveat",
      "note": "Anchors are always times; there is no bar-index mode, and pixel placement uses OBJ_LABEL distances instead.",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/objects/objectcreate",
        "fragment": "objects positioned by time and price anchor points",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "draw.x-by-time",
      "language": "ninjascript",
      "source": "present",
      "construct": "Draw.* overloads taking DateTime",
      "signature": "Draw.Line(NinjaScriptBase owner, string tag, bool isAutoScale, DateTime startTime, double startY, DateTime endTime, double endY, Brush brush, DashStyleHelper dashStyle, int width)",
      "relation": "equivalent_with_caveat",
      "note": "Pick the DateTime overload instead of barsAgo. The time is a DateTime, whereas Lipi xloc.bar_time takes epoch milliseconds.",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/draw_line.htm",
        "fragment": "Draw.Line() overloads with DateTime startTime",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "draw.x-by-time",
      "language": "pine",
      "source": "present",
      "construct": "xloc.bar_time",
      "relation": "exact",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "const_xloc.bar_time",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "draw.x-by-time",
      "language": "thinkscript",
      "source": "absent",
      "note": "Chart marks are tied to the bar where their condition holds; no timestamp placement argument is documented.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Functions/Look---Feel/AddChartBubble",
        "fragment": "time condition: Defines condition upon which the bubble is displayed",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "draw.future-bars",
      "language": "mql4",
      "source": "unresolved",
      "note": "ObjectCreate and the object-type pages do not say whether a time after the last bar is accepted or how it is placed.",
      "evidence": {
        "url": "https://docs.mql4.com/objects/objectcreate",
        "fragment": "time1 parameter",
        "accessed": "2026-11-01"
      },
      "verified": "unresolved"
    },
    {
      "concept": "draw.future-bars",
      "language": "mql5",
      "source": "unresolved",
      "note": "The ObjectCreate page states no limit or rule for anchor times beyond the last bar, so future placement is not established from first-party docs.",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/objects/objectcreate",
        "fragment": "ObjectCreate parameters and notes",
        "accessed": "2026-11-01"
      },
      "verified": "unresolved"
    },
    {
      "concept": "draw.future-bars",
      "language": "ninjascript",
      "source": "unresolved",
      "note": "The first-party pages checked (drawing, draw_line, draw_text) do not say whether anchors may lie right of the last bar.",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/drawing.htm",
        "fragment": "Draw Methods and Associated Return Types; numbered notes",
        "accessed": "2026-11-01"
      },
      "verified": "unresolved"
    },
    {
      "concept": "draw.future-bars",
      "language": "pine",
      "source": "present",
      "construct": "xloc.bar_index with an index past bar_index",
      "relation": "equivalent_with_caveat",
      "note": "Pine bar-index coordinates may run at most 500 bars past the current bar. Lipi's compiler accepts any future index or time; drawing is undocumented.",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-docs/writing/limitations/",
        "fragment": "maximum-bars-forward",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "draw.future-bars",
      "language": "thinkscript",
      "source": "present",
      "construct": "plot values on the right expansion (bars where IsNaN(close)); price[-n]",
      "relation": "equivalent_with_caveat",
      "note": "Bars to the right of the last one have NaN prices, so a script can plot there; negative-index plots shift forward but look ahead.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Functions/Math---Trig/IsNaN",
        "fragment": "draws the highest and the lowest close price on the right expansion of the subgraph",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "draw.object-limits",
      "language": "mql4",
      "source": "unresolved",
      "note": "Object function pages state only a 63-character name limit; no maximum object count is documented.",
      "evidence": {
        "url": "https://docs.mql4.com/objects/objectcreate",
        "fragment": "Note: object name should not exceed 63 characters",
        "accessed": "2026-11-01"
      },
      "verified": "unresolved"
    },
    {
      "concept": "draw.object-limits",
      "language": "mql5",
      "source": "unresolved",
      "note": "The Object Functions index states no maximum number of graphical objects, so no limit can be quoted from first-party docs.",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/objects",
        "fragment": "Object Functions index",
        "accessed": "2026-11-01"
      },
      "verified": "unresolved"
    },
    {
      "concept": "draw.object-limits",
      "language": "ninjascript",
      "source": "unresolved",
      "note": "No page on the allowed hosts states a cap on script drawings; DrawObjects only warns that large collections affect performance.",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/drawingtools_drawobjects.htm",
        "fragment": "DrawObjects Notes (iterating a large collection)",
        "accessed": "2026-11-01"
      },
      "verified": "unresolved"
    },
    {
      "concept": "draw.object-limits",
      "language": "pine",
      "source": "present",
      "construct": "max_lines_count, max_labels_count, max_boxes_count, max_polylines_count arguments",
      "relation": "equivalent_with_caveat",
      "note": "Same arguments, default 50, caps 500 (100 polylines). Pine deletes the oldest drawings past the limit; Lipi trims past limit plus 5.",
      "differences": [
        {
          "axis": "state_and_side_effects",
          "note": "Lipi never trims a line, label, box or linefill held directly in a static variable; Pine's docs describe plain oldest-first deletion."
        }
      ],
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-docs/writing/limitations/",
        "fragment": "line-box-polyline-and-label-limits",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "draw.object-limits",
      "language": "thinkscript",
      "source": "absent",
      "note": "No drawing objects exist, so no object-count limits are documented.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Functions/Look---Feel",
        "fragment": "Look and Feel function list (26 entries; no object-creating drawing function)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "draw.all-objects",
      "language": "mql4",
      "source": "present",
      "construct": "ObjectsTotal(), ObjectName(index), ObjectsDeleteAll(window, type or prefix)",
      "relation": "composite",
      "note": "Loop an index up to ObjectsTotal reading ObjectName; ObjectsDeleteAll removes by subwindow and type, with a prefix form that filters by name.",
      "evidence": {
        "url": "https://docs.mql4.com/objects/objectsdeleteall",
        "fragment": "prefix in object name",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "draw.all-objects",
      "language": "mql5",
      "source": "present",
      "construct": "ObjectsTotal; ObjectName; ObjectsDeleteAll",
      "signature": "int ObjectsTotal(long chart_id, int sub_window=-1, int type=-1); string ObjectName(long chart_id, int pos, int sub_window=-1, int type=-1)",
      "relation": "composite",
      "note": "Count with ObjectsTotal and read each name with ObjectName, optionally by type; the list covers the whole chart, not just your script's objects.",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/objects/objectstotal",
        "fragment": "ObjectsTotal: number of objects in the specified chart, subwindow and type",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "draw.all-objects",
      "language": "ninjascript",
      "source": "present",
      "construct": "DrawObjects (use DrawObjects.ToList())",
      "signature": "foreach (DrawingTool draw in DrawObjects.ToList())",
      "relation": "equivalent_with_caveat",
      "note": "The collection holds every object on the chart, including user-drawn ones; filter by type and IsUserDrawn, and iterate a ToList() snapshot.",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/drawingtools_drawobjects.htm",
        "fragment": "Looping through the collection to find specific draw objects",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "draw.all-objects",
      "language": "pine",
      "source": "present",
      "construct": "line.all, label.all, box.all",
      "relation": "exact",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "var_line.all; var_label.all; var_box.all",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "draw.all-objects",
      "language": "thinkscript",
      "source": "absent",
      "note": "No object registry exists because drawings are not objects.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Functions/Look---Feel",
        "fragment": "Look and Feel function list (26 entries; no object-creating drawing function)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "draw.table",
      "language": "mql4",
      "source": "absent",
      "note": "No table object; arrange OBJ_LABEL or OBJ_RECTANGLE_LABEL objects at pixel offsets from a corner.",
      "evidence": {
        "url": "https://docs.mql4.com/constants/objectconstants/enum_object",
        "fragment": "Object Types table",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "draw.table",
      "language": "mql5",
      "source": "absent",
      "note": "No table object exists; build a grid from OBJ_LABEL, OBJ_EDIT or OBJ_RECTANGLE_LABEL objects.",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/constants/objectconstants/enum_object",
        "fragment": "ENUM_OBJECT list: OBJ_LABEL, OBJ_EDIT, OBJ_RECTANGLE_LABEL (no table)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "draw.table",
      "language": "ninjascript",
      "source": "absent",
      "note": "No table object. Draw.TextFixed places text in one of five fixed chart positions; a grid needs custom OnRender drawing.",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/drawing.htm",
        "fragment": "Draw Methods and Associated Return Types (no table; Draw.TextFixed)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "draw.table",
      "language": "pine",
      "source": "present",
      "construct": "table.new(), table.cell()",
      "signature": "table.cell(table_id, column, row, text, width, height, text_color, text_halign, text_valign, text_size, bgcolor, tooltip, text_font_family, text_formatting) → void",
      "relation": "equivalent_with_caveat",
      "note": "Pine's cell text arguments are text_color, text_halign, text_valign, text_size; Lipi names them textcolor, texthalign, textvalign, size and warns on the Pine names.",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_table.cell",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "draw.table",
      "language": "thinkscript",
      "source": "absent",
      "note": "No grid object: AddLabel adds single text rows in a chart corner; several labels stack, optionally with row ownership.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Functions/Look---Feel/AddLabel",
        "fragment": "AddLabel ( boolean visible , Any text , CustomColor color , int location , int size , boolean row ownership )",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "draw.table-update",
      "language": "mql4",
      "source": "absent",
      "note": "No cell object; change each stand-in label or rectangle label through its own OBJPROP_TEXT or OBJPROP_BGCOLOR.",
      "evidence": {
        "url": "https://docs.mql4.com/constants/objectconstants/enum_object_property",
        "fragment": "OBJPROP_BGCOLOR; OBJPROP_XSIZE",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "draw.table-update",
      "language": "mql5",
      "source": "absent",
      "note": "Without a table type, each cell is a separate object changed through ObjectSetString and ObjectSetInteger.",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/constants/objectconstants/enum_object",
        "fragment": "ENUM_OBJECT list: no table object",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "draw.table-update",
      "language": "ninjascript",
      "source": "absent",
      "note": "Without tables there are no cells to change; redraw Draw.TextFixed under the same tag to update fixed text.",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/drawing.htm",
        "fragment": "Draw Methods and Associated Return Types (no table; Draw.TextFixed)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "draw.table-update",
      "language": "pine",
      "source": "present",
      "construct": "table.cell_set_text(), table.cell_set_bgcolor(), table.merge_cells()",
      "signature": "table.merge_cells(table_id, start_column, start_row, end_column, end_row) → void",
      "relation": "equivalent_with_caveat",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_table.merge_cells",
        "accessed": "2026-11-01"
      },
      "verified": "documented",
      "note": "Pine raises an error when a merged cell is merged again; Lipi completes the second merge without an error."
    },
    {
      "concept": "draw.table-update",
      "language": "thinkscript",
      "source": "absent",
      "note": "No table cells to edit; each AddLabel call is its own text line driven by a condition.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Functions/Look---Feel/AddLabel",
        "fragment": "Other labels will be pushed to adjacent rows",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "draw.text-align",
      "language": "mql4",
      "source": "present",
      "construct": "OBJPROP_ANCHOR, OBJPROP_FONTSIZE, OBJPROP_ALIGN, TextSetFont",
      "relation": "equivalent_with_caveat",
      "note": "Anchor point picks one of nine positions for text and label objects; font size is an integer; OBJPROP_ALIGN applies only to edit objects.",
      "evidence": {
        "url": "https://docs.mql4.com/constants/objectconstants/enum_object_property",
        "fragment": "OBJPROP_ANCHOR; OBJPROP_FONTSIZE",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "draw.text-align",
      "language": "mql5",
      "source": "present",
      "construct": "OBJPROP_ANCHOR; OBJPROP_ALIGN; OBJPROP_FONTSIZE",
      "relation": "equivalent_with_caveat",
      "note": "Anchor point and font size are separate properties; horizontal alignment (OBJPROP_ALIGN) exists only for edit objects, not as one alignment keyword.",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/constants/objectconstants/enum_object_property",
        "fragment": "OBJPROP_ANCHOR, OBJPROP_ALIGN, OBJPROP_FONTSIZE",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "draw.text-align",
      "language": "ninjascript",
      "source": "present",
      "construct": "TextAlignment, SimpleFont, TextPosition",
      "signature": "Draw.Text(owner, tag, isAutoScale, text, barsAgo, y, yPixelOffset, textBrush, SimpleFont font, TextAlignment alignment, outlineBrush, areaBrush, areaOpacity)",
      "relation": "equivalent_with_caveat",
      "note": "Draw.Text takes TextAlignment (Left, Center, Right, Justify) and a SimpleFont; fixed-position text uses Draw.TextFixed with five preset slots.",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/draw_text.htm",
        "fragment": "alignment and font parameters",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "draw.text-align",
      "language": "pine",
      "source": "present",
      "construct": "text_halign, text_valign, text_size arguments; text.align_* and size.* constants",
      "relation": "equivalent_with_caveat",
      "note": "Pine text_size takes size.* or a positive integer; the argument names are text_halign and text_valign where Lipi uses texthalign, textvalign and size.",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "const_text.align_center; const_size.huge",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "draw.text-align",
      "language": "thinkscript",
      "source": "present",
      "construct": "AddLabel(..., location = Location.*, size = FontSize.*)",
      "relation": "equivalent_with_caveat",
      "note": "Only label font size (FontSize constants SMALL to X_LARGE) and corner Location; no alignment control and no text inside boxes or cells.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Constants/FontSize",
        "fragment": "Font Size constants are used with the AddLabel() function to define the font size of the label text",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "strat.entry",
      "language": "mql4",
      "source": "present",
      "construct": "OrderSend(symbol, OP_BUY or OP_SELL, volume, price, slippage, stoploss, takeprofit, ...)",
      "signature": "int OrderSend(string symbol, int cmd, double volume, double price, int slippage, double stoploss, double takeprofit, string comment=NULL, int magic=0, datetime expiration=0, color arrow_color=clrNONE)",
      "relation": "different_semantics",
      "note": "Each call returns one ticket for one order; the caller supplies the Bid or Ask price, slippage, stop loss and take profit.",
      "differences": [
        {
          "axis": "state_and_side_effects",
          "note": "Each market order is separately ticketed; closing an opposite order is its own call (OrderClose or OrderCloseBy)."
        }
      ],
      "evidence": {
        "url": "https://docs.mql4.com/trading/ordersend",
        "fragment": "OrderSend signature",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "strat.entry",
      "language": "mql5",
      "source": "present",
      "construct": "OrderSend with TRADE_ACTION_DEAL",
      "signature": "bool OrderSend(MqlTradeRequest &request, MqlTradeResult &result)",
      "relation": "different_semantics",
      "note": "A real trade request: true means only basic acceptance, so check result.retcode; netting accounts hold one position per symbol.",
      "differences": [
        {
          "axis": "state_and_side_effects",
          "note": "Orders hit the live account, and OrderSend is barred in indicators."
        }
      ],
      "evidence": {
        "url": "https://www.mql5.com/en/docs/trading/ordersend",
        "fragment": "OrderSend return value; check retcode of MqlTradeResult",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "strat.entry",
      "language": "ninjascript",
      "source": "present",
      "construct": "EnterLong() / EnterShort()",
      "signature": "EnterLong(int quantity, string signalName)",
      "relation": "equivalent_with_caveat",
      "note": "Direction is in the method name and signalName replaces the id. The opposite entry reverses the position, as in Lipi.",
      "differences": [
        {
          "axis": "state_and_side_effects",
          "note": "Managed orders not resubmitted are cancelled at the end of the bar; quantity 0 becomes 1."
        }
      ],
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/managed_approach.htm",
        "fragment": "Entry() methods will reverse the position automatically",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "strat.entry",
      "language": "pine",
      "source": "present",
      "construct": "strategy.entry()",
      "signature": "strategy.entry(id, direction, qty, limit, stop, oca_name, oca_type, comment, alert_message, disable_alert) → void",
      "relation": "equivalent_with_caveat",
      "note": "Pine adds alert_message and disable_alert for per-order alerts; Lipi's strategy.entry lacks both.",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_strategy.entry",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "strat.entry",
      "language": "thinkscript",
      "source": "present",
      "construct": "AddOrder(OrderType.BUY_AUTO / SELL_AUTO, condition)",
      "signature": "AddOrder(int type, IDataHolder condition, IDataHolder price, IDataHolder tradeSize, CustomColor tickColor, CustomColor arrowColor, String name)",
      "relation": "equivalent_with_caveat",
      "note": "BUY_AUTO and SELL_AUTO open or close; the order lands on the next bar at open[-1] by default; no order id, limit or stop arguments.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Functions/Others/AddOrder",
        "fragment": "Adds an order of specified side and position effect for the next bar when the condition is true",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "strat.order",
      "language": "mql4",
      "source": "present",
      "construct": "OrderSend with OP_BUYLIMIT, OP_SELLLIMIT, OP_BUYSTOP, OP_SELLSTOP",
      "relation": "equivalent_with_caveat",
      "note": "Pending orders are limit or stop types only; price must keep the MODE_STOPLEVEL distance from market, and an expiration time is optional.",
      "evidence": {
        "url": "https://docs.mql4.com/trading/ordersend",
        "fragment": "MODE_STOPLEVEL",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "strat.order",
      "language": "mql5",
      "source": "present",
      "construct": "OrderSend with TRADE_ACTION_PENDING",
      "relation": "equivalent_with_caveat",
      "note": "Pending orders use TRADE_ACTION_PENDING with an ENUM_ORDER_TYPE and a price; stoplimit sets the trigger for stop-limit orders.",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/constants/structures/mqltraderequest",
        "fragment": "MqlTradeRequest: action, type, price, stoplimit",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "strat.order",
      "language": "ninjascript",
      "source": "present",
      "construct": "SubmitOrderUnmanaged()",
      "signature": "SubmitOrderUnmanaged(int selectedBarsInProgress, OrderAction orderAction, OrderType orderType, int quantity, double limitPrice, double stopPrice, string oco, string signalName)",
      "relation": "equivalent_with_caveat",
      "note": "Direction and type are OrderAction and OrderType arguments. Managed Enter* calls reverse positions, so they are not strategy.order.",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/submitorderunmanaged.htm",
        "fragment": "SubmitOrderUnmanaged() Syntax and Parameters",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "strat.order",
      "language": "pine",
      "source": "present",
      "construct": "strategy.order()",
      "signature": "strategy.order(id, direction, qty, limit, stop, oca_name, oca_type, comment, alert_message, disable_alert) → void",
      "relation": "equivalent_with_caveat",
      "note": "Pine adds alert_message and disable_alert for per-order alerts; Lipi's strategy.order lacks both.",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_strategy.order",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "strat.order",
      "language": "thinkscript",
      "source": "present",
      "construct": "AddOrder(OrderType.BUY_TO_OPEN / SELL_TO_OPEN, condition)",
      "relation": "equivalent_with_caveat",
      "note": "TO_OPEN and TO_CLOSE types only open or only close, the nearest thing to a non-reversing order; there is no separate order function.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/tutorials/Basic/Chapter-7---Creating-Strategies",
        "fragment": "BUY_TO_CLOSE, BUY_TO_OPEN, SELL_TO_CLOSE, and SELL_TO_OPEN ... only opens or closes a position",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "strat.exit",
      "language": "mql4",
      "source": "present",
      "construct": "stoploss and takeprofit arguments; OrderModify",
      "relation": "equivalent_with_caveat",
      "note": "Stop and target are stored on the order, set at send or by OrderModify; no trailing option is documented, so trail by modifying each tick.",
      "evidence": {
        "url": "https://docs.mql4.com/trading/ordersend",
        "fragment": "stoploss, takeprofit parameters",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "strat.exit",
      "language": "mql5",
      "source": "present",
      "construct": "MqlTradeRequest sl and tp fields; TRADE_ACTION_SLTP",
      "relation": "equivalent_with_caveat",
      "note": "Stop and target are absolute prices on the request, set at entry or later by TRADE_ACTION_SLTP; the structure has no trailing-stop field.",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/constants/structures/mqltraderequest",
        "fragment": "MqlTradeRequest sl: Stop Loss price; tp: Take Profit price",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "strat.exit",
      "language": "ninjascript",
      "source": "present",
      "construct": "SetStopLoss(), SetProfitTarget(), SetTrailStop(), or ExitLongStopMarket() / ExitLongLimit()",
      "signature": "SetStopLoss(CalculationMode mode, double value)",
      "relation": "composite",
      "note": "Set* methods attach stop and target to an entry's fills (call before entering; modes Ticks, Price, Percent and others); Exit* methods submit explicit orders.",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/setstoploss.htm",
        "fragment": "SetStopLoss() Notes and CalculationMode",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "strat.exit",
      "language": "pine",
      "source": "present",
      "construct": "strategy.exit()",
      "signature": "strategy.exit(id, from_entry, qty, qty_percent, profit, limit, loss, stop, trail_price, trail_points, trail_offset, oca_name, comment, comment_profit, comment_loss, comment_trailing, alert_message, alert_profit, alert_loss, alert_trailing, disable_alert) → void",
      "relation": "equivalent_with_caveat",
      "note": "Pine adds qty_percent, trail_price, trail_points, trail_offset and alert arguments that Lipi lacks. profit and loss are tick distances, limit and stop are prices, in both.",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_strategy.exit",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "strat.exit",
      "language": "thinkscript",
      "source": "present",
      "construct": "AddOrder(OrderType.SELL_TO_CLOSE, close > EntryPrice() + t or close < EntryPrice() - s)",
      "relation": "composite",
      "note": "No stop or target arguments: write the exit condition against EntryPrice() and send a TO_CLOSE order; it is a close-based condition.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Functions/Others/EntryPrice",
        "fragment": "AddOrder(OrderType.SELL_TO_CLOSE, close > EntryPrice() + 3 or close < EntryPrice() - 9);",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "strat.close",
      "language": "mql4",
      "source": "present",
      "construct": "OrderClose(ticket, lots, price, slippage, arrow_color)",
      "signature": "bool OrderClose(int ticket, double lots, double price, int slippage, color arrow_color)",
      "relation": "composite",
      "note": "Closes one order by ticket, in whole or by lots; closing everything means looping OrdersTotal with OrderSelect and OrderClose.",
      "evidence": {
        "url": "https://docs.mql4.com/trading/orderclose",
        "fragment": "OrderClose signature",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "strat.close",
      "language": "mql5",
      "source": "present",
      "construct": "TRADE_ACTION_DEAL with the position ticket; TRADE_ACTION_CLOSE_BY",
      "relation": "composite",
      "note": "Closing sends an opposite-direction deal naming the position ticket, or TRADE_ACTION_CLOSE_BY against an opposite position.",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/constants/structures/mqltraderequest",
        "fragment": "MqlTradeRequest position and position_by fields",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "strat.close",
      "language": "ninjascript",
      "source": "present",
      "construct": "ExitLong() / ExitShort()",
      "signature": "ExitLong(string signalName, string fromEntrySignal)",
      "relation": "equivalent_with_caveat",
      "note": "Market exits, ignored when no such position exists. For close_all call both. Avoid CloseStrategy(), which also disables the strategy.",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/exitlong.htm",
        "fragment": "Tips: This method is ignored if a long position does not exist",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "strat.close",
      "language": "pine",
      "source": "present",
      "construct": "strategy.close(), strategy.close_all()",
      "signature": "strategy.close(id, comment, qty, qty_percent, alert_message, immediately, disable_alert) → void",
      "relation": "equivalent_with_caveat",
      "note": "Pine orders the arguments close(id, comment, qty, ...); Lipi orders close(id, qty, comment). Pine adds qty_percent and immediately.",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_strategy.close",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "strat.close",
      "language": "thinkscript",
      "source": "present",
      "construct": "AddOrder(OrderType.SELL_TO_CLOSE / BUY_TO_CLOSE, condition)",
      "relation": "equivalent_with_caveat",
      "note": "Closes an open position on the next bar by default; no entry-id argument exists to choose which entry to close.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/tutorials/Basic/Chapter-7---Creating-Strategies",
        "fragment": "BUY_TO_CLOSE, BUY_TO_OPEN, SELL_TO_CLOSE, and SELL_TO_OPEN",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "strat.cancel",
      "language": "mql4",
      "source": "present",
      "construct": "OrderDelete(ticket)",
      "relation": "equivalent_with_caveat",
      "note": "Deletes one pending order by ticket; cancelling all means looping over orders.",
      "evidence": {
        "url": "https://docs.mql4.com/trading",
        "fragment": "OrderDelete: Deletes previously opened pending order",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "strat.cancel",
      "language": "mql5",
      "source": "present",
      "construct": "TRADE_ACTION_REMOVE",
      "relation": "equivalent_with_caveat",
      "note": "Each pending order is removed by its own ticket in a request; the action list has no cancel-all.",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/constants/tradingconstants/enum_trade_request_actions",
        "fragment": "TRADE_ACTION_REMOVE: delete the pending order placed previously",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "strat.cancel",
      "language": "ninjascript",
      "source": "present",
      "construct": "CancelOrder(Order order)",
      "signature": "CancelOrder(Order order)",
      "relation": "equivalent_with_caveat",
      "note": "Takes the Order object returned by the entry call, not a string id. The managed page documents no strategy-wide cancel-all method.",
      "differences": [
        {
          "axis": "state_and_side_effects",
          "note": "Resubmitting an order each bar keeps it alive; stopping resubmission cancels it."
        }
      ],
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/managed_cancelorder.htm",
        "fragment": "CancelOrder() Syntax and Parameters",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "strat.cancel",
      "language": "pine",
      "source": "present",
      "construct": "strategy.cancel(), strategy.cancel_all()",
      "signature": "strategy.cancel(id) → void",
      "relation": "exact",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_strategy.cancel; fun_strategy.cancel_all",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "strat.cancel",
      "language": "thinkscript",
      "source": "absent",
      "note": "No pending-order concept is documented: each order is added for the next bar by its condition, with nothing to cancel.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Functions/Others/AddOrder",
        "fragment": "Adds an order ... for the next bar when the condition is true",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "strat.position",
      "language": "mql4",
      "source": "present",
      "construct": "OrdersTotal, OrderSelect, OrderLots, OrderOpenPrice, OrderType",
      "relation": "composite",
      "note": "There is no single net position; loop open orders by symbol and magic number, sum signed OrderLots and weight OrderOpenPrice for the average.",
      "evidence": {
        "url": "https://docs.mql4.com/trading/orderselect",
        "fragment": "OrderSelect SELECT_BY_POS",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "strat.position",
      "language": "mql5",
      "source": "present",
      "construct": "PositionSelect; PositionGetDouble(POSITION_VOLUME, POSITION_PRICE_OPEN)",
      "signature": "double PositionGetDouble(ENUM_POSITION_PROPERTY_DOUBLE property_id)",
      "relation": "different_semantics",
      "note": "Volume is separate from direction (POSITION_TYPE buy or sell), and a position must be selected before its properties are read.",
      "differences": [
        {
          "axis": "state_and_side_effects",
          "note": "Under netting only one open position per symbol exists."
        }
      ],
      "evidence": {
        "url": "https://www.mql5.com/en/docs/constants/tradingconstants/positionproperties",
        "fragment": "POSITION_TYPE, POSITION_VOLUME, POSITION_PRICE_OPEN; one open position per symbol",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "strat.position",
      "language": "ninjascript",
      "source": "present",
      "construct": "Position.Quantity, Position.AveragePrice, Position.MarketPosition",
      "relation": "equivalent_with_caveat",
      "note": "Size and direction are separate: Quantity is an int and direction comes from MarketPosition (Flat, Long, Short); Lipi position_size is one signed number.",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/position.htm",
        "fragment": "Position Methods and Properties",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "strat.position",
      "language": "pine",
      "source": "present",
      "construct": "strategy.position_size, strategy.position_avg_price",
      "relation": "equivalent_with_caveat",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "var_strategy.position_size; var_strategy.position_avg_price",
        "accessed": "2026-11-01"
      },
      "verified": "documented",
      "note": "With a flat position strategy.position_avg_price is 0 in Lipi but na (NaN) in Pine."
    },
    {
      "concept": "strat.position",
      "language": "thinkscript",
      "source": "present",
      "construct": "EntryPrice()",
      "signature": "EntryPrice()",
      "relation": "equivalent_with_caveat",
      "note": "Only the average entry price of the held position is available; no simulated position-size function is documented.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Functions/Others/EntryPrice",
        "fragment": "For several entry orders in the same direction ... the function returns the average price for all of them",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "strat.results",
      "language": "mql4",
      "source": "present",
      "construct": "AccountEquity(), AccountBalance(), AccountProfit(), TesterStatistics(id)",
      "signature": "double TesterStatistics(ENUM_STATISTICS statistic_id)",
      "relation": "composite",
      "note": "Equity, balance and open profit are account functions; net profit, drawdown and trade counts come from TesterStatistics, only inside OnTester or OnDeinit in the tester.",
      "evidence": {
        "url": "https://docs.mql4.com/common/testerstatistics",
        "fragment": "TesterStatistics called inside OnTester or OnDeinit",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "strat.results",
      "language": "mql5",
      "source": "present",
      "construct": "AccountInfoDouble(ACCOUNT_EQUITY, ACCOUNT_BALANCE, ACCOUNT_PROFIT); TesterStatistics",
      "signature": "double TesterStatistics(ENUM_STATISTICS statistic_id)",
      "relation": "composite",
      "note": "Live equity comes from account properties; tester totals (profit, trade counts) come from TesterStatistics, callable only in OnTester or OnDeinit during testing.",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/common/testerstatistics",
        "fragment": "can be called inside OnTester() or OnDeinit() in the tester",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "strat.results",
      "language": "ninjascript",
      "source": "present",
      "construct": "SystemPerformance.AllTrades.TradesPerformance.Currency.CumProfit and related",
      "relation": "composite",
      "note": "Totals sit in nested performance objects (CumProfit, Drawdown, trade counts via Count) and need IncludeTradeHistoryInBacktest; no equity variable is listed.",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/tradesperformancevalues.htm",
        "fragment": "TradesPerformanceValues Methods and Properties; CumProfit example",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "strat.results",
      "language": "pine",
      "source": "present",
      "construct": "strategy.equity, netprofit, max_drawdown, closedtrades, wintrades",
      "relation": "equivalent_with_caveat",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "var_strategy.equity; var_strategy.netprofit; var_strategy.max_drawdown",
        "accessed": "2026-11-01"
      },
      "verified": "documented",
      "note": "Lipi netprofit falls by the entry commission when a trade opens; Pine netprofit counts only completed trades. Equity totals still match."
    },
    {
      "concept": "strat.results",
      "language": "thinkscript",
      "source": "present",
      "construct": "FPL()",
      "signature": "FPL()",
      "relation": "equivalent_with_caveat",
      "note": "Only FPL() floating profit/loss is documented as a scriptable strategy result; no equity, drawdown or trade-count function is listed.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Functions/Others/FPL",
        "fragment": "Returns floating Profit/Loss value based on strategy signals",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "strat.trade-history",
      "language": "mql4",
      "source": "present",
      "construct": "OrderSelect(i, SELECT_BY_POS, MODE_HISTORY), OrderProfit(), OrderOpenPrice(), OrderClosePrice(), OrderLots()",
      "relation": "equivalent_with_caveat",
      "note": "Select an order first, then call accessors that read the selected one; OrderSelect returns false for a bad index. History holds closed and deleted orders.",
      "differences": [
        {
          "axis": "state_and_side_effects",
          "note": "Hidden selected-order context: accessors read whichever order was selected last."
        }
      ],
      "evidence": {
        "url": "https://docs.mql4.com/trading/orderselect",
        "fragment": "MODE_HISTORY pool",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "strat.trade-history",
      "language": "mql5",
      "source": "present",
      "construct": "HistorySelect; HistoryDealsTotal; HistoryDealGetTicket; HistoryDealGetDouble(DEAL_PROFIT, DEAL_PRICE)",
      "signature": "double HistoryDealGetDouble(ulong ticket_number, ENUM_DEAL_PROPERTY_DOUBLE property_id)",
      "relation": "composite",
      "note": "Select a history range, then read each deal by ticket and property; Lipi-style indexed trade accessors do not exist.",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/trading/historydealgetdouble",
        "fragment": "See also: HistorySelect, HistoryDealsTotal, HistoryDealGetTicket; ENUM_DEAL_PROPERTY_DOUBLE",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "strat.trade-history",
      "language": "ninjascript",
      "source": "present",
      "construct": "SystemPerformance.AllTrades[i] (Trade.Entry, Trade.Exit, Quantity, ProfitCurrency)",
      "relation": "equivalent_with_caveat",
      "note": "Zero-based, oldest first, as in Lipi. A Trade holds Entry and Exit Execution objects plus profit properties, and covers completed trades.",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/trade.htm",
        "fragment": "Trade Methods and Properties",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "strat.trade-history",
      "language": "pine",
      "source": "present",
      "construct": "strategy.closedtrades.profit(), .entry_price(), strategy.opentrades.profit()",
      "signature": "strategy.closedtrades.profit(trade_num) → series float",
      "relation": "equivalent_with_caveat",
      "note": "Pine uses dotted names (strategy.closedtrades.profit(i)); Lipi uses strategy.closedtrades_profit(i). Lipi's closed-trade exit bar index and run-up and drawdown always read 0.",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_strategy.closedtrades.profit",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "strat.trade-history",
      "language": "thinkscript",
      "source": "absent",
      "note": "No per-trade accessors are documented; trade details appear only in the strategy report window.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/tutorials/Basic/Chapter-7---Creating-Strategies",
        "fragment": "view the performance report upon clicking each signal on chart",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "strat.settings",
      "language": "mql4",
      "source": "absent",
      "note": "No in-code setting for capital, order size, commission or pyramiding; the #property list has none, and orders carry explicit volume.",
      "evidence": {
        "url": "https://docs.mql4.com/basis/preprosessor/compilation",
        "fragment": "property table (no tester options)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "strat.settings",
      "language": "mql5",
      "source": "absent",
      "note": "No #property or call sets capital, commission or pyramiding; order volume is the volume field of each trade request.",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/basis/preprosessor/compilation",
        "fragment": "complete #property table: no deposit, commission or pyramiding entry",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "strat.settings",
      "language": "ninjascript",
      "source": "present",
      "construct": "EntriesPerDirection, EntryHandling, DefaultQuantity, Slippage, IncludeCommission, OrderFillResolution",
      "relation": "composite",
      "note": "Spread across separate strategy properties; a starting-capital property is not in the strategy property list.",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/strategy.htm",
        "fragment": "In this section: property list",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "strat.settings",
      "language": "pine",
      "source": "present",
      "construct": "strategy() arguments: initial_capital, default_qty_type, default_qty_value, commission_type, commission_value, pyramiding, process_orders_on_close",
      "relation": "equivalent_with_caveat",
      "note": "Defaults differ: Pine uses 100 percent of equity, 100000 capital, pyramiding 0; Lipi uses 1 unit, 1000000, pyramiding 1. Constant names are dotted (strategy.oca.cancel).",
      "differences": [
        {
          "axis": "state_and_side_effects",
          "note": "A strategy without explicit settings trades much larger positions in Pine (percent of equity) than in Lipi (one unit)."
        }
      ],
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_strategy",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "strat.settings",
      "language": "thinkscript",
      "source": "absent",
      "note": "Order size and similar settings live in the Strategy Global Settings window; AddOrder's tradeSize only overrides size per call.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Functions/Others/AddOrder",
        "fragment": "overrides the trade size specified in Strategy Global Settings",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "alert.call",
      "language": "mql4",
      "source": "present",
      "construct": "Alert(...), SendNotification(text), SendMail, PlaySound",
      "signature": "void Alert(argument, ...)",
      "relation": "equivalent_with_caveat",
      "note": "Alert takes up to 64 comma-separated values and opens a message window; arrays cannot be passed, so output elements one by one.",
      "evidence": {
        "url": "https://docs.mql4.com/common/alert",
        "fragment": "The number of parameters can not exceed 64",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "alert.call",
      "language": "mql5",
      "source": "present",
      "construct": "Alert; SendNotification; SendMail; PlaySound",
      "signature": "void Alert(argument, ...)",
      "relation": "equivalent_with_caveat",
      "note": "Alert shows a dialog; SendNotification pushes to mobile (maximum 255 characters, rate-limited); neither works in the Strategy Tester.",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/network/sendnotification",
        "fragment": "SendNotification: 255 characters, 2 calls per second, 10 per minute, not in tester",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "alert.call",
      "language": "ninjascript",
      "source": "present",
      "construct": "Alert()",
      "signature": "Alert(string id, Priority priority, string message, string soundLocation, int rearmSeconds, Brush backBrush, Brush foreBrush)",
      "relation": "equivalent_with_caveat",
      "note": "Needs an id and a rearmSeconds window instead of Lipi's once-per-bar limit. Works only in State.Realtime and writes to the Alerts Log.",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/alert.htm",
        "fragment": "Alert() Notes and Syntax",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "alert.call",
      "language": "pine",
      "source": "present",
      "construct": "alert(message, freq)",
      "signature": "alert(message, freq) → void",
      "relation": "equivalent_with_caveat",
      "note": "Pine alert has a freq argument (alert.freq_once_per_bar, once_per_bar_close, all); Lipi's takes only the message. A Pine strategy fires alerts at bar close unless calc_on_every_tick.",
      "differences": [
        {
          "axis": "bar_timing",
          "note": "Pine strategies without calc_on_every_tick fire alert() only at bar close, whatever freq says; the default frequency is once per bar."
        }
      ],
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-docs/concepts/alerts/",
        "fragment": "alert-function-events",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "alert.call",
      "language": "thinkscript",
      "source": "present",
      "construct": "Alert",
      "signature": "Alert(IDataHolder condition, String text, int alert type, String sound)",
      "relation": "equivalent_with_caveat",
      "note": "Takes the condition itself plus ONCE/BAR/TICK frequency and a sound; Lipi's alert has only a message and fires at most once per bar.",
      "differences": [
        {
          "axis": "bar_timing",
          "note": "ONCE fires once after adding the study and TICK on every tick; Lipi fires at most once per bar, in realtime only."
        }
      ],
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Functions/Others/Alert",
        "fragment": "Alert ( IDataHolder condition , String text , int alert type , String sound )",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "alert.condition",
      "language": "mql4",
      "source": "absent",
      "note": "No declaration of user-pickable alert conditions; common functions are call style only (Alert, SendMail, SendNotification, PlaySound).",
      "evidence": {
        "url": "https://docs.mql4.com/common",
        "fragment": "Common Functions list",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "alert.condition",
      "language": "mql5",
      "source": "absent",
      "note": "No declare-a-condition function exists; raise alerts from your own code with Alert or SendNotification.",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/common/alert",
        "fragment": "Alert: displays a message in a separate window",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "alert.condition",
      "language": "ninjascript",
      "source": "absent",
      "note": "No script-level alert-condition declaration is in the language reference index; alerts are built in the Alerts window from conditions on chart objects.",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/alphabetical_reference.htm",
        "fragment": "Alphabetical Reference: Alert() and RearmAlert() only; no alert condition entry",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "alert.condition",
      "language": "pine",
      "source": "present",
      "construct": "alertcondition()",
      "signature": "alertcondition(condition, title, message) → void",
      "relation": "equivalent_with_caveat",
      "note": "Pine's alertcondition works only in indicators, must start at column zero, and its const message may hold {{placeholders}} such as {{close}} for dynamic values.",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-docs/concepts/alerts/",
        "fragment": "alertcondition-events",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "alert.condition",
      "language": "thinkscript",
      "source": "absent",
      "note": "No declare-a-condition form for users to pick: alerts are scripted with Alert() and described as local alerts.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/tutorials/Appendices/Appendix-A---Creating-Local-Alerts",
        "fragment": "In thinkScript, you have the ability to create local alerts",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "alert.webhook",
      "language": "mql4",
      "source": "present",
      "construct": "WebRequest(method, url, headers, timeout, data[], result[], result_headers)",
      "signature": "int WebRequest(const string method, const string url, const string headers, int timeout, const char &data[], char &result[], string &result_headers)",
      "relation": "different_semantics",
      "note": "WebRequest posts HTTP from code to an allow-listed URL and fails in indicators. In Lipi, alert() builds the message; delivery is set outside the script.",
      "evidence": {
        "url": "https://docs.mql4.com/common/webrequest",
        "fragment": "WebRequest note on allowed URLs",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "alert.webhook",
      "language": "mql5",
      "source": "present",
      "construct": "WebRequest",
      "signature": "int WebRequest(const string method, const string url, const string headers, int timeout, const char &data[], char &result[], string &result_headers)",
      "relation": "different_semantics",
      "note": "WebRequest posts HTTP from code to an allow-listed URL, blocks until the reply, and fails in indicators. In Lipi, alert() builds the message only.",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/network/webrequest",
        "fragment": "WebRequest: list of allowed URLs; not allowed in indicators; synchronous",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "alert.webhook",
      "language": "ninjascript",
      "source": "absent",
      "note": "Alert actions are Play Sound, Share, Pop Up Dialog and Submit Order; no webhook action is documented. Share sends to configured share services.",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/configuring_alerts.htm",
        "fragment": "Understanding the action properties",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "alert.webhook",
      "language": "pine",
      "source": "present",
      "construct": "Webhook URL option in the Create Alert dialog; message text from alert() or alert_message",
      "relation": "equivalent_with_caveat",
      "note": "The script supplies only the message; the URL is set when the alert is created. A JSON-valid message is sent with a JSON content type.",
      "evidence": {
        "url": "https://www.tradingview.com/support/solutions/43000529348-how-to-configure-webhook-alerts/",
        "fragment": "How to configure webhook alerts",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "alert.webhook",
      "language": "thinkscript",
      "source": "absent",
      "note": "Alerts are local (message text and sound); the reference documents no outbound delivery to an address.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/tutorials/Appendices/Appendix-A---Creating-Local-Alerts",
        "fragment": "The sound parameter plays a sound when the alert is triggered",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "data.ohlcv",
      "language": "mql4",
      "source": "present",
      "construct": "Open[], High[], Low[], Close[], Volume[]",
      "relation": "equivalent_with_caveat",
      "note": "Series arrays with shift 0 as current bar; Volume is tick volume, a count of price changes, not traded contracts.",
      "evidence": {
        "url": "https://docs.mql4.com/predefined",
        "fragment": "Predefined Variables table",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "data.ohlcv",
      "language": "mql5",
      "source": "present",
      "construct": "open[], high[], low[], close[], tick_volume[], volume[] (OnCalculate); iOpen, iHigh, iLow, iClose, iVolume",
      "relation": "equivalent_with_caveat",
      "note": "Prices arrive as arrays whose direction you set; volume is split into tick_volume[] and real volume[], so choose which one Lipi's volume maps to.",
      "differences": [
        {
          "axis": "history_indexing",
          "note": "Array direction follows ArraySetAsSeries; iClose(shift) always counts 0 as the current bar."
        }
      ],
      "evidence": {
        "url": "https://www.mql5.com/en/docs/event_handlers/oncalculate",
        "fragment": "OnCalculate time, open, high, low, close, tick_volume, volume, spread arrays",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "data.ohlcv",
      "language": "ninjascript",
      "source": "present",
      "construct": "Open[0], High[0], Low[0], Close[0], Volume[0]",
      "relation": "equivalent_with_caveat",
      "note": "Series objects read with [barsAgo]; bare Close is the series. With Calculate.OnBarClose, [0] is the bar that just closed.",
      "differences": [
        {
          "axis": "bar_timing",
          "note": "In OnBarClose mode the script never sees a forming bar; Lipi runs on every live update by default."
        }
      ],
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/priceseries.htm",
        "fragment": "Single ISeries<double>: Close, High, Low, Open",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "data.ohlcv",
      "language": "pine",
      "source": "present",
      "construct": "open, high, low, close, volume",
      "relation": "exact",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "var_open; var_close; var_volume",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "data.ohlcv",
      "language": "thinkscript",
      "source": "present",
      "construct": "open, high, low, close, volume",
      "signature": "close(Symbol symbol, Any period, String priceType)",
      "relation": "equivalent_with_caveat",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Functions/Fundamentals/close",
        "fragment": "close ( Symbol symbol , Any period , String priceType )",
        "accessed": "2026-11-01"
      },
      "verified": "documented",
      "note": "close(), high() and the rest also take a symbol, aggregation period and price type; Lipi's variables read the chart's own symbol and timeframe only."
    },
    {
      "concept": "data.derived-price",
      "language": "mql4",
      "source": "present",
      "construct": "PRICE_MEDIAN, PRICE_TYPICAL, PRICE_WEIGHTED",
      "relation": "equivalent_with_caveat",
      "note": "Constants that select hl2, hlc3 and (H+L+C+C)/4 for indicator functions, not variables; no ohlc4 constant, so compute values yourself.",
      "evidence": {
        "url": "https://docs.mql4.com/constants/indicatorconstants/prices",
        "fragment": "ENUM_APPLIED_PRICE",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "data.derived-price",
      "language": "mql5",
      "source": "present",
      "construct": "PRICE_MEDIAN; PRICE_TYPICAL; PRICE_WEIGHTED (ENUM_APPLIED_PRICE)",
      "relation": "equivalent_with_caveat",
      "note": "Median is hl2, typical is hlc3, weighted is hlcc4; there is no OHLC/4 constant, so compute it from the arrays.",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/constants/indicatorconstants/prices",
        "fragment": "PRICE_MEDIAN (high+low)/2, PRICE_TYPICAL (high+low+close)/3, PRICE_WEIGHTED (high+low+close+close)/4",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "data.derived-price",
      "language": "ninjascript",
      "source": "present",
      "construct": "Median[0], Typical[0], Weighted[0]",
      "relation": "equivalent_with_caveat",
      "note": "Median = hl2, Typical = hlc3, Weighted = (H+L+C+C)/4 = hlcc4. There is no built-in ohlc4 series.",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/priceseries.htm",
        "fragment": "Median, Typical, Weighted",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "data.derived-price",
      "language": "pine",
      "source": "present",
      "construct": "hl2, hlc3, ohlc4, hlcc4",
      "relation": "exact",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "var_hl2; var_hlcc4",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "data.derived-price",
      "language": "thinkscript",
      "source": "present",
      "construct": "hl2, hlc3, ohlc4",
      "relation": "equivalent_with_caveat",
      "note": "hlcc4 is not documented; compute (high + low + 2 * close) / 4 yourself.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Functions/Fundamentals/ohlc4",
        "fragment": "Returns the (Open + High + Low + Close)/4 value",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "data.open-interest",
      "language": "mql4",
      "source": "absent",
      "note": "No open-interest value; symbol properties and series expose only tick volume.",
      "evidence": {
        "url": "https://docs.mql4.com/constants/environment_state/marketinfoconstants",
        "fragment": "Symbol Properties table",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "data.open-interest",
      "language": "mql5",
      "source": "present",
      "construct": "SYMBOL_SESSION_INTEREST",
      "signature": "double SymbolInfoDouble(string name, ENUM_SYMBOL_INFO_DOUBLE prop_id)",
      "relation": "different_semantics",
      "note": "A symbol property for the trading session, not a value stored per bar; MqlTick has no open-interest field.",
      "differences": [
        {
          "axis": "history_indexing",
          "note": "No per-bar history of it: only the current value is read."
        }
      ],
      "evidence": {
        "url": "https://www.mql5.com/en/docs/marketinformation/symbolinfodouble",
        "fragment": "SymbolInfoDouble: SYMBOL_SESSION_INTEREST",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "data.open-interest",
      "language": "ninjascript",
      "source": "present",
      "construct": "MarketDataType.OpenInterest in OnMarketData()",
      "signature": "protected override void OnMarketData(MarketDataEventArgs marketDataUpdate)",
      "relation": "equivalent_with_caveat",
      "note": "Arrives as a live market-data event (supported by some providers), not a per-bar series; Lipi oi is a bar series that reads 0 when missing.",
      "differences": [
        {
          "axis": "history_indexing",
          "note": "No bar history of open interest is exposed; store your own values per bar."
        }
      ],
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/marketdataeventargs.htm",
        "fragment": "MarketDataType.OpenInterest (supported by IQFeed, Kinetick)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "data.open-interest",
      "language": "pine",
      "source": "present",
      "construct": "open-interest ticker \"<id>_OI\", requested as another symbol (for example with request.security)",
      "relation": "equivalent_with_caveat",
      "note": "Pine has no built-in open-interest variable; OI comes from a ticker with _OI appended. Lipi's oi is 0, not na, when absent.",
      "evidence": {
        "url": "https://www.tradingview.com/script/Rpmobpw5-Request/",
        "fragment": "Open Interest (OI)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "data.open-interest",
      "language": "thinkscript",
      "source": "present",
      "construct": "open_interest()",
      "signature": "open_interest(String symbol, Any period, String priceType)",
      "relation": "equivalent_with_caveat",
      "note": "A function with optional symbol, period and price-type arguments; the value reported where no open interest exists is not stated.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Functions/Fundamentals/open-interest",
        "fragment": "open_interest ( String symbol , Any period , String priceType )",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "data.orderflow",
      "language": "mql4",
      "source": "absent",
      "note": "Only tick volume per bar (Volume, iVolume); no buy/sell split, delta or trade count.",
      "evidence": {
        "url": "https://docs.mql4.com/series",
        "fragment": "iVolume: Returns Tick Volume value",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "data.orderflow",
      "language": "mql5",
      "source": "present",
      "construct": "CopyTicks; MqlTick flags TICK_FLAG_BUY and TICK_FLAG_SELL; volume_real",
      "relation": "composite",
      "note": "No per-bar buy/sell volume or delta: copy ticks, split them by TICK_FLAG_BUY and TICK_FLAG_SELL, and sum per bar yourself.",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/constants/structures/mqltick",
        "fragment": "MqlTick: volume_real, flags; TICK_FLAG_BUY, TICK_FLAG_SELL",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "data.orderflow",
      "language": "ninjascript",
      "source": "present",
      "construct": "VolumetricBarsType.Volumes[CurrentBar] (BarDelta, TotalBuyingVolume, TotalSellingVolume, Trades, CumulativeDelta)",
      "relation": "equivalent_with_caveat",
      "note": "Needs a Volumetric bars series. Index with the absolute CurrentBar, not barsAgo. CumulativeDelta resets at the session break.",
      "differences": [
        {
          "axis": "history_indexing",
          "note": "Volumes[i] takes an absolute bar index, the reverse of Close[barsAgo]."
        }
      ],
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/order_flow_volumetric_bars2.htm",
        "fragment": "Methods and Properties the VolumetricBarsType exposes",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "data.orderflow",
      "language": "pine",
      "source": "present",
      "construct": "request.footprint(), footprint.buy_volume(), footprint.sell_volume(), footprint.delta(), footprint.total_volume()",
      "signature": "request.footprint(ticks_per_row, va_percent, imbalance_percent) → footprint",
      "relation": "composite",
      "note": "Call request.footprint(ticks_per_row), then footprint.buy_volume(), sell_volume(), delta(), total_volume(). No trade-count series or cvd function exists; accumulate delta with ta.cum.",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-docs/concepts/other-timeframes-and-data/",
        "fragment": "requestfootprint",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "data.orderflow",
      "language": "thinkscript",
      "source": "present",
      "construct": "tick_count",
      "signature": "tick_count(String symbol, Any period, String priceType)",
      "relation": "equivalent_with_caveat",
      "note": "Only the trade count of an intraday bar exists; buy/sell volume, delta and cumulative delta have no documented function.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Functions/Fundamentals/tick-count",
        "fragment": "Returns the number of trades corresponding to an intraday bar",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "data.instrument",
      "language": "mql4",
      "source": "present",
      "construct": "Symbol(), MarketInfo(symbol, MODE_TICKSIZE / MODE_DIGITS / MODE_POINT), SymbolInfoString, AccountCurrency()",
      "relation": "composite",
      "note": "Name from Symbol, tick size and digits from MarketInfo, base and profit currency from SymbolInfoString; no exchange or asset-type property is listed.",
      "evidence": {
        "url": "https://docs.mql4.com/constants/environment_state/marketinfoconstants",
        "fragment": "MODE_TICKSIZE; SYMBOL_CURRENCY_BASE",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "data.instrument",
      "language": "mql5",
      "source": "present",
      "construct": "SymbolInfoString(SYMBOL_EXCHANGE, SYMBOL_CURRENCY_PROFIT); SymbolInfoDouble(SYMBOL_TRADE_TICK_SIZE); SYMBOL_TRADE_CALC_MODE",
      "relation": "composite",
      "note": "Each field is a property read by identifier: exchange and currencies as strings, tick size as double, instrument kind via the calc-mode enum.",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/constants/environment_state/marketinfoconstants",
        "fragment": "SYMBOL_EXCHANGE, SYMBOL_CURRENCY_PROFIT, SYMBOL_TRADE_TICK_SIZE, SYMBOL_TRADE_CALC_MODE",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "data.instrument",
      "language": "ninjascript",
      "source": "present",
      "construct": "Instrument.MasterInstrument.Name, Instrument.Exchange, MasterInstrument.Currency, MasterInstrument.TickSize, MasterInstrument.InstrumentType",
      "relation": "composite",
      "note": "Fields sit on Instrument and MasterInstrument and are readable only from State.DataLoaded; InstrumentType is NinjaTrader's own enum.",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/masterinstrument.htm",
        "fragment": "MasterInstrument Methods and Properties",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "data.instrument",
      "language": "pine",
      "source": "present",
      "construct": "syminfo.ticker, syminfo.prefix, syminfo.currency, syminfo.mintick, syminfo.type",
      "relation": "different_semantics",
      "note": "Pine mintick is the price tick, Lipi's is minmove/pricescale. Pine ticker omits the exchange. Exchange maps to syminfo.prefix, asset_type to syminfo.type.",
      "differences": [
        {
          "axis": "numeric_types",
          "note": "Pine syminfo.mintick equals the smallest price step; in Lipi the step is syminfo.minmove and mintick is minmove divided by pricescale."
        }
      ],
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "var_syminfo.mintick; var_syminfo.ticker",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "data.instrument",
      "language": "thinkscript",
      "source": "present",
      "construct": "GetSymbol(), TickSize(), TickValue(), GetSymbolPart()",
      "signature": "GetSymbol()",
      "relation": "equivalent_with_caveat",
      "note": "Symbol, tick size and dollar tick value only; futures symbols come back with an exchange namespace such as /ES:XCME; no currency, exchange or type accessors.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Functions/Others/GetSymbol",
        "fragment": "GetSymbol() returns the corresponding futures symbol with a namespace appended",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "data.timeframe",
      "language": "mql4",
      "source": "present",
      "construct": "Period(), PeriodSeconds(), PERIOD_* constants",
      "relation": "equivalent_with_caveat",
      "note": "Period() returns minutes as an int (PERIOD_H1 is 60); there are no isintraday or isdaily flags, so compare against the constants.",
      "evidence": {
        "url": "https://docs.mql4.com/constants/chartconstants/enum_timeframes",
        "fragment": "ENUM_TIMEFRAMES values",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "data.timeframe",
      "language": "mql5",
      "source": "present",
      "construct": "Period(); _Period; ENUM_TIMEFRAMES",
      "signature": "ENUM_TIMEFRAMES Period()",
      "relation": "equivalent_with_caveat",
      "note": "Returns an ENUM_TIMEFRAMES constant such as PERIOD_M5, not text; tests like intraday or daily are your own comparisons.",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/check/period",
        "fragment": "Period: returns the contents of the _Period variable",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "data.timeframe",
      "language": "ninjascript",
      "source": "present",
      "construct": "BarsPeriod.BarsPeriodType, BarsPeriod.Value",
      "relation": "composite",
      "note": "Period type (Tick, Minute, Day, Renko and others) plus Value; no isintraday or isdaily flags, so derive them. Read only from State.DataLoaded.",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/barsperiod.htm",
        "fragment": "BarsPeriod.BarsPeriodType and BarsPeriod.Value",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "data.timeframe",
      "language": "pine",
      "source": "present",
      "construct": "timeframe.period, timeframe.isintraday, timeframe.isdaily, timeframe.multiplier, timeframe.in_seconds()",
      "relation": "equivalent_with_caveat",
      "note": "The namespace is timeframe, not interval. timeframe.period is a Pine-format string (bare minutes, S, D, W, M suffixes), unlike Lipi's unit-suffixed strings.",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "var_timeframe.period; fun_timeframe.in_seconds",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "data.timeframe",
      "language": "thinkscript",
      "source": "present",
      "construct": "GetAggregationPeriod()",
      "signature": "GetAggregationPeriod()",
      "relation": "equivalent_with_caveat",
      "note": "One number whose unit depends on chart type; compare it with AggregationPeriod constants instead of isintraday-style flags.",
      "differences": [
        {
          "axis": "numeric_types",
          "note": "Unit is milliseconds, ticks or price range by chart type, and 1 Day compares equal to 24 hours."
        }
      ],
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Functions/Others/GetAggregationPeriod",
        "fragment": "returns the current aggregation period in milliseconds for time charts, in ticks for tick charts, and in dollars for range charts",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "data.other-symbol",
      "language": "mql4",
      "source": "present",
      "construct": "iClose(symbol, timeframe, shift), iOpen, iHigh, iLow, iVolume, iTime, iCustom, CopyRates",
      "relation": "no_lipi_equivalent",
      "note": "Series functions take a symbol and timeframe plus a shift counted in that series' own bars; Lipi reads only the chart's symbol and timeframe.",
      "differences": [
        {
          "axis": "htf_access",
          "note": "Shift counts bars of the requested timeframe; shift 0 is that series' current, still-forming bar."
        }
      ],
      "evidence": {
        "url": "https://docs.mql4.com/series",
        "fragment": "iClose, iBarShift, CopyRates",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "data.other-symbol",
      "language": "mql5",
      "source": "present",
      "construct": "iClose(symbol, timeframe, shift); CopyRates; CopyBuffer",
      "signature": "double iClose(const string symbol, ENUM_TIMEFRAMES timeframe, int shift)",
      "relation": "no_lipi_equivalent",
      "note": "Any symbol and timeframe can be read directly; Lipi sees only the chart's own series.",
      "differences": [
        {
          "axis": "htf_access",
          "note": "shift counts bars of the requested timeframe, not chart bars; align them yourself with iTime or iBarShift."
        }
      ],
      "evidence": {
        "url": "https://www.mql5.com/en/docs/series/iclose",
        "fragment": "iClose(symbol, timeframe, shift)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "data.other-symbol",
      "language": "ninjascript",
      "source": "present",
      "construct": "AddDataSeries() with Closes[i][0]",
      "signature": "AddDataSeries(string instrumentName, BarsPeriodType periodType, int period)",
      "relation": "no_lipi_equivalent",
      "note": "Add extra Bars in State.Configure with hard-coded arguments, read Closes[i][0], and filter OnBarUpdate by BarsInProgress. Lipi reads only the chart series.",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/adddataseries.htm",
        "fragment": "AddDataSeries() Syntax and example",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "data.other-symbol",
      "language": "pine",
      "source": "present",
      "construct": "request.security(), request.security_lower_tf()",
      "signature": "request.security(symbol, timeframe, expression, gaps, lookahead, ignore_invalid_symbol, currency, calc_bars_count) → series <type>",
      "relation": "no_lipi_equivalent",
      "note": "Lipi reads only the chart's own symbol and timeframe; nothing replaces request.security.",
      "differences": [
        {
          "axis": "htf_access",
          "note": "request.security takes gaps and lookahead (both off by default) and shows developing higher-timeframe values on realtime bars."
        }
      ],
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-docs/concepts/other-timeframes-and-data/",
        "fragment": "requestsecurity",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "data.other-symbol",
      "language": "thinkscript",
      "source": "present",
      "construct": "close(\"IBM\", period = AggregationPeriod.WEEK)",
      "signature": "close(Symbol symbol, Any period, String priceType)",
      "relation": "no_lipi_equivalent",
      "note": "Every price function takes symbol and period arguments; Lipi reads only the chart's own symbol and timeframe, so such scripts cannot be converted.",
      "differences": [
        {
          "axis": "htf_access",
          "note": "A secondary period cannot be shorter than the chart's, and one variable cannot mix two different secondary periods."
        }
      ],
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/tutorials/Advanced/Chapter-11---Referencing-Secondary-Aggregation",
        "fragment": "plot weeklyClose = close(\"IBM\", period = AggregationPeriod.WEEK);",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "data.chart-type",
      "language": "mql4",
      "source": "present",
      "construct": "ChartGetInteger(0, CHART_MODE)",
      "relation": "equivalent_with_caveat",
      "note": "Reports candlesticks, bars or line display mode only; Heikin Ashi and Renko are not values of this property.",
      "evidence": {
        "url": "https://docs.mql4.com/constants/chartconstants/enum_chart_property",
        "fragment": "CHART_MODE",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "data.chart-type",
      "language": "mql5",
      "source": "present",
      "construct": "ChartGetInteger with CHART_MODE",
      "relation": "equivalent_with_caveat",
      "note": "CHART_MODE reports bars, candles or line only; the docs list no Heikin Ashi or Renko mode.",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/constants/chartconstants/enum_chart_property",
        "fragment": "CHART_MODE: ENUM_CHART_MODE chart type (candlesticks, bars or line)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "data.chart-type",
      "language": "ninjascript",
      "source": "present",
      "construct": "BarsPeriod.BarsPeriodType == BarsPeriodType.HeikenAshi / Renko",
      "relation": "equivalent_with_caveat",
      "note": "No is_standard flag; compare BarsPeriodType (for example HeikenAshi 9, Renko 11) yourself.",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/barsperiod.htm",
        "fragment": "BarsPeriod.BarsPeriodType possible values",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "data.chart-type",
      "language": "pine",
      "source": "present",
      "construct": "chart.is_standard, chart.is_heikinashi, chart.is_renko",
      "relation": "exact",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "var_chart.is_standard; var_chart.is_renko",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "data.chart-type",
      "language": "thinkscript",
      "source": "absent",
      "note": "SetChartType only sets the chart type; no function tests which type the chart currently shows.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Functions/Look---Feel/SetChartType",
        "fragment": "Sets a desirable non-Monkey chart type directly from the script",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "time.bar-time",
      "language": "mql4",
      "source": "present",
      "construct": "Time[shift], iTime(symbol, timeframe, shift)",
      "relation": "equivalent_with_caveat",
      "note": "Gives bar open time in seconds since 1970 (Lipi uses milliseconds); close time is open plus PeriodSeconds().",
      "differences": [
        {
          "axis": "numeric_types",
          "note": "Seconds, not milliseconds."
        }
      ],
      "evidence": {
        "url": "https://docs.mql4.com/predefined",
        "fragment": "Time: open time of each bar",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "time.bar-time",
      "language": "mql5",
      "source": "present",
      "construct": "time[] (OnCalculate); iTime(symbol, timeframe, shift)",
      "signature": "datetime iTime(const string symbol, ENUM_TIMEFRAMES timeframe, int shift)",
      "relation": "different_semantics",
      "note": "Gives only the bar's open time, as datetime in seconds since 1970; no close-time function is documented, and Lipi time is milliseconds.",
      "differences": [
        {
          "axis": "numeric_types",
          "note": "Seconds in MQL5, milliseconds in Lipi: scale by 1000."
        }
      ],
      "evidence": {
        "url": "https://www.mql5.com/en/docs/series/itime",
        "fragment": "iTime: opening time of the bar indicated by shift",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "time.bar-time",
      "language": "ninjascript",
      "source": "present",
      "construct": "Time[0]",
      "signature": "Time[int barsAgo] (DateTime)",
      "relation": "different_semantics",
      "note": "Time[0] is the bar's closing time stamp, so it matches Lipi time_close, not time (open). It returns a DateTime, not epoch milliseconds.",
      "differences": [
        {
          "axis": "bar_timing",
          "note": "A minute bar stamped 9:31:00 holds data from 9:30:00 to 9:30:59; Lipi time would read 9:30."
        }
      ],
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/how_bars_are_built.htm",
        "fragment": "Bar Time Stamp",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "time.bar-time",
      "language": "pine",
      "source": "present",
      "construct": "time, time_close",
      "relation": "equivalent_with_caveat",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "var_time; var_time_close",
        "accessed": "2026-11-01"
      },
      "verified": "documented",
      "note": "Lipi time_close is always open plus one interval; Pine yields na on the open realtime bar of tick and price-based charts."
    },
    {
      "concept": "time.bar-time",
      "language": "thinkscript",
      "source": "present",
      "construct": "GetTime()",
      "signature": "GetTime()",
      "relation": "equivalent_with_caveat",
      "note": "Returns epoch milliseconds but the reference does not say whether that is the bar's open or close; there is no separate close-time value.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Functions/Date---Time/GetTime",
        "fragment": "Returns the number of milliseconds since the epoch (January 1, 1970, 00:00:00 GMT)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "time.now",
      "language": "mql4",
      "source": "present",
      "construct": "TimeCurrent(), TimeLocal(), TimeGMT()",
      "relation": "different_semantics",
      "note": "TimeCurrent is the server time of the last quote, TimeLocal the computer clock; all in seconds, and equal to each other in the tester.",
      "differences": [
        {
          "axis": "bar_timing",
          "note": "Server time of last tick, not wall-clock now; frozen between ticks."
        }
      ],
      "evidence": {
        "url": "https://docs.mql4.com/dateandtime/timelocal",
        "fragment": "TimeLocal() is always equal to TimeCurrent()",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "time.now",
      "language": "mql5",
      "source": "present",
      "construct": "TimeCurrent(); TimeLocal()",
      "signature": "datetime TimeCurrent()",
      "relation": "different_semantics",
      "note": "TimeCurrent is the last quote's server time, not the machine clock; TimeLocal is the computer's clock and equals TimeCurrent in the tester.",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/dateandtime/timecurrent",
        "fragment": "TimeCurrent: last known server time, time of the last quote receipt",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "time.now",
      "language": "ninjascript",
      "source": "present",
      "construct": "DateTime.Now",
      "relation": "equivalent_with_caveat",
      "note": "Returns a local-time DateTime, not epoch milliseconds; it is evaluated on each call, not per bar.",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/c_method_functions_reference.htm",
        "fragment": "System.DateTime: Now property example",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "time.now",
      "language": "pine",
      "source": "present",
      "construct": "timenow",
      "relation": "exact",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "var_timenow",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "time.now",
      "language": "thinkscript",
      "source": "absent",
      "note": "The Date and Time list has no function for the present wall-clock time.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Functions/Date---Time",
        "fragment": "Date and Time function list (GetTime, GetDay, GetDayOfWeek, GetMonth, GetYear, GetYYYYMMDD, SecondsFromTime, ...)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "time.parts",
      "language": "mql4",
      "source": "present",
      "construct": "TimeYear(t), TimeMonth(t), TimeDay(t), TimeDayOfWeek(t), TimeHour(t), TimeMinute(t), TimeSeconds(t)",
      "relation": "different_semantics",
      "note": "Bare Hour() and DayOfWeek() read the last server time, not the bar; use TimeHour(Time[i]). Weekday is zero-based, Sunday 0 (Lipi 1 to 7).",
      "differences": [
        {
          "axis": "numeric_types",
          "note": "Weekday 0 to 6 from Sunday, versus Lipi 1 to 7."
        },
        {
          "axis": "bar_timing",
          "note": "No-argument forms follow server time, not the bar being calculated."
        }
      ],
      "evidence": {
        "url": "https://docs.mql4.com/dateandtime",
        "fragment": "DayOfWeek: zero-based; Hour: last known server time",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "time.parts",
      "language": "mql5",
      "source": "present",
      "construct": "TimeToStruct; MqlDateTime fields year, mon, day, hour, min, sec, day_of_week, day_of_year",
      "signature": "bool TimeToStruct(datetime dt, MqlDateTime &dt_struct)",
      "relation": "different_semantics",
      "note": "Weekday 0 is Sunday and day_of_year starts at 0, unlike Lipi's Sunday 1; all parts come from one filled struct.",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/constants/structures/mqldatetime",
        "fragment": "MqlDateTime: day_of_week 0-Sunday ... 6-Saturday; day_of_year zero for January 1",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "time.parts",
      "language": "ninjascript",
      "source": "present",
      "construct": "Time[0].Year, .Month, .Day, .DayOfWeek, .Hour, .Minute, .Second",
      "relation": "equivalent_with_caveat",
      "note": "Properties of the bar's DateTime. DayOfWeek is a .NET enum, not Lipi's 1 to 7 number.",
      "evidence": {
        "url": "https://learn.microsoft.com/en-us/dotnet/api/system.datetime",
        "fragment": "Properties: Year, Month, Day, DayOfWeek, Hour, Minute, Second",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "time.parts",
      "language": "pine",
      "source": "present",
      "construct": "year, month, dayofmonth, dayofweek, hour, minute, second",
      "relation": "equivalent_with_caveat",
      "note": "Pine's variables use the exchange time zone, and the matching functions take an optional timezone argument. Check which zone Lipi's variables read.",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-docs/concepts/time/",
        "fragment": "calendar-based-variables",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "time.parts",
      "language": "thinkscript",
      "source": "present",
      "construct": "GetYear(), GetMonth(), GetDay(), GetDayOfMonth(yyyymmdd), GetDayOfWeek(yyyymmdd)",
      "signature": "GetDayOfWeek(int yyyyMmDd)",
      "relation": "different_semantics",
      "note": "Weekday is Monday=1 to Sunday=7 (Lipi Sunday=1); GetDay is day of year; year and month use CST; no hour, minute or second.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Functions/Date---Time/GetDayOfWeek",
        "fragment": "The return value ranges from 1 (Monday) to 7 (Sunday)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "time.make-timestamp",
      "language": "mql4",
      "source": "present",
      "construct": "StructToTime(MqlDateTime), StringToTime(string)",
      "signature": "datetime StructToTime(MqlDateTime &dt_struct)",
      "relation": "equivalent_with_caveat",
      "note": "Fill an MqlDateTime struct or parse a date string; results are seconds since 1970 and no timezone argument exists.",
      "differences": [
        {
          "axis": "numeric_types",
          "note": "Seconds, not milliseconds."
        }
      ],
      "evidence": {
        "url": "https://docs.mql4.com/dateandtime/structtotime",
        "fragment": "StructToTime signature",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "time.make-timestamp",
      "language": "mql5",
      "source": "present",
      "construct": "StructToTime; StringToTime; D'yyyy.mm.dd hh:mi:ss' literal",
      "signature": "datetime StructToTime(MqlDateTime &dt_struct)",
      "relation": "equivalent_with_caveat",
      "note": "Fill an MqlDateTime and call StructToTime, or use a D'...' literal; the result counts seconds since 1970, not milliseconds.",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/dateandtime/structtotime",
        "fragment": "StructToTime: converts MqlDateTime to datetime",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "time.make-timestamp",
      "language": "ninjascript",
      "source": "present",
      "construct": "new DateTime(year, month, day, hour, minute, second)",
      "signature": "new DateTime(2018, 5, 25)",
      "relation": "equivalent_with_caveat",
      "note": "The constructor returns a DateTime, not an epoch-millisecond int; Lipi timestamp reads the parts in exchange time.",
      "evidence": {
        "url": "https://learn.microsoft.com/en-us/dotnet/api/system.datetime",
        "fragment": "Constructors: DateTime(Int32, Int32, Int32, Int32, Int32, Int32)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "time.make-timestamp",
      "language": "pine",
      "source": "present",
      "construct": "timestamp()",
      "signature": "timestamp(year, month, day, hour, minute, second) → series int",
      "relation": "equivalent_with_caveat",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_timestamp",
        "accessed": "2026-11-01"
      },
      "verified": "documented",
      "note": "Pine timestamp(dateString) is const and valid as an input.time default; Lipi's is na at compile, so Add to chart rejects it."
    },
    {
      "concept": "time.make-timestamp",
      "language": "thinkscript",
      "source": "absent",
      "note": "No builder from date parts: dates are plain YYYYMMDD integers and times of day HHMM integers.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Functions/Date---Time",
        "fragment": "Date and Time function list (no function that builds a timestamp from year, month, day)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "time.format",
      "language": "mql4",
      "source": "present",
      "construct": "TimeToString(value, mode)",
      "signature": "string TimeToString(datetime value, int mode=TIME_DATE|TIME_MINUTES)",
      "relation": "equivalent_with_caveat",
      "note": "Only flag modes giving yyyy.mm.dd, hh:mi and hh:mi:ss; there is no custom pattern or timezone argument.",
      "evidence": {
        "url": "https://docs.mql4.com/convert/timetostring",
        "fragment": "TIME_DATE, TIME_MINUTES, TIME_SECONDS",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "time.format",
      "language": "mql5",
      "source": "present",
      "construct": "TimeToString",
      "signature": "string TimeToString(datetime value, int mode=TIME_DATE|TIME_MINUTES)",
      "relation": "equivalent_with_caveat",
      "note": "Output has a fixed yyyy.mm.dd hh:mi:ss layout chosen by flags; there is no free-form pattern, and the input is in seconds.",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/convert/timetostring",
        "fragment": "TimeToString: TIME_DATE, TIME_MINUTES, TIME_SECONDS flags",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "time.format",
      "language": "ninjascript",
      "source": "present",
      "construct": "DateTime.ToString()",
      "signature": "Time[0].ToString()",
      "relation": "equivalent_with_caveat",
      "note": "ToString() with an optional .NET format string; Lipi str.format_time uses a reference-date layout and reads seconds.",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/iseries_time.htm",
        "fragment": "Print(Time[0].ToString())",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "time.format",
      "language": "pine",
      "source": "present",
      "construct": "str.format_time()",
      "signature": "str.format_time(time, format, timezone) → series string",
      "relation": "different_semantics",
      "note": "Pine takes the time in milliseconds and a pattern of tokens such as yyyy-MM-dd HH:mm; Lipi takes seconds and a Go-style reference-date layout.",
      "differences": [
        {
          "axis": "numeric_types",
          "note": "Pine time argument is milliseconds; Lipi's is seconds, so divide by 1000 when converting."
        }
      ],
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_str.format_time",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "time.format",
      "language": "thinkscript",
      "source": "absent",
      "note": "AsText formats numbers only; the Date and Time list has no function that turns a time into text.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Functions/Others/AsText",
        "fragment": "Converts a number into string with specified properties",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "time.session",
      "language": "mql4",
      "source": "present",
      "construct": "SymbolInfoSessionTrade(symbol, day_of_week, session_index, from, to)",
      "signature": "bool SymbolInfoSessionTrade(string name, ENUM_DAY_OF_WEEK day_of_week, uint session_index, datetime &from, datetime &to)",
      "relation": "composite",
      "note": "Returns a session's start and end as seconds from midnight for a weekday and index; testing a bar against sessions is manual.",
      "evidence": {
        "url": "https://docs.mql4.com/marketinformation/symbolinfosessiontrade",
        "fragment": "SymbolInfoSessionTrade signature",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "time.session",
      "language": "mql5",
      "source": "present",
      "construct": "SymbolInfoSessionTrade",
      "relation": "composite",
      "note": "Returns session start and end for a symbol, weekday and session index; first-bar-of-session tests must be built from those times.",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/marketinformation/symbolinfosessiontrade",
        "fragment": "SymbolInfoSessionTrade: start and end time of trading sessions for a symbol and day of week",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "time.session",
      "language": "ninjascript",
      "source": "present",
      "construct": "Bars.IsFirstBarOfSession, SessionIterator",
      "relation": "composite",
      "note": "session.isfirst ~ Bars.IsFirstBarOfSession; session date and day start come from a SessionIterator built in State.DataLoaded.",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/sessioniterator.htm",
        "fragment": "SessionIterator Methods and Properties; GetTradingDay, ActualTradingDayExchange",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "time.session",
      "language": "pine",
      "source": "present",
      "construct": "session.isfirstbar, time(timeframe, session), time_tradingday",
      "relation": "equivalent_with_caveat",
      "note": "session.isfirst is session.isfirstbar, time_sessionday is time_tradingday, and time(tf, session) returns na outside the session. Pine has no session.date.",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-docs/concepts/time/",
        "fragment": "testing-for-sessions; #time_tradingday",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "time.session",
      "language": "thinkscript",
      "source": "present",
      "construct": "SecondsFromTime(HHMM), SecondsTillTime(HHMM), RegularTradingStart(yyyymmdd), GetYYYYMMDD()",
      "signature": "SecondsFromTime(int fromTime)",
      "relation": "composite",
      "note": "Session tests are seconds from or to an EST clock time, always zero on daily charts; GetYYYYMMDD gives the session date; no first-of-session flag.",
      "differences": [
        {
          "axis": "bar_timing",
          "note": "Clock times are fixed to EST rather than the exchange zone, and the functions return zero when the chart period is a day or more."
        }
      ],
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Functions/Date---Time/SecondsFromTime",
        "fragment": "always returns zero when chart's aggregation period is greater than or equal to 1 day",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "math.abs",
      "language": "mql4",
      "source": "present",
      "construct": "MathAbs",
      "signature": "double MathAbs(double value)",
      "relation": "exact",
      "evidence": {
        "url": "https://docs.mql4.com/math/mathabs",
        "fragment": "MathAbs",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "math.abs",
      "language": "mql5",
      "source": "present",
      "construct": "MathAbs",
      "signature": "double MathAbs(double value)",
      "relation": "exact",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/math/mathabs",
        "fragment": "MathAbs - Return Value",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "math.abs",
      "language": "ninjascript",
      "source": "present",
      "construct": "Math.Abs",
      "signature": "Math.Abs(double value)",
      "relation": "exact",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/basic_syntax.htm",
        "fragment": "System.Math section: Math.Abs(5-6) example",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "math.abs",
      "language": "pine",
      "source": "present",
      "construct": "math.abs",
      "signature": "math.abs(number) → int or float, same qualifier as the argument",
      "relation": "exact",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_math.abs",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "math.abs",
      "language": "thinkscript",
      "source": "present",
      "construct": "AbsValue",
      "signature": "AbsValue(double value)",
      "relation": "exact",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Functions/Math---Trig/AbsValue",
        "fragment": "AbsValue ( double value )",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "math.rounding",
      "language": "mql4",
      "source": "present",
      "construct": "MathRound, MathCeil, MathFloor",
      "signature": "double MathRound(double value); double MathCeil(double val); double MathFloor(double val)",
      "relation": "equivalent_with_caveat",
      "note": "All three return double, not int, and take no precision argument; cast to int when a count is needed.",
      "differences": [
        {
          "axis": "numeric_types",
          "note": "result type is double, where Lipi rounding returns int."
        }
      ],
      "evidence": {
        "url": "https://docs.mql4.com/math/mathround",
        "fragment": "MathRound; MathCeil; MathFloor (all declared double)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "math.rounding",
      "language": "mql5",
      "source": "present",
      "construct": "MathRound, MathCeil, MathFloor",
      "signature": "double MathRound(double value)",
      "relation": "equivalent_with_caveat",
      "note": "All three return double, not int, and MathRound has no decimals argument. Cast to int, or use NormalizeDouble for decimal places.",
      "differences": [
        {
          "axis": "numeric_types",
          "note": "Results are double; Lipi's one-argument round, ceil and floor return int."
        }
      ],
      "evidence": {
        "url": "https://www.mql5.com/en/docs/math/mathround",
        "fragment": "MathRound signature: double MathRound(double value)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "math.rounding",
      "language": "ninjascript",
      "source": "present",
      "construct": "Math.Round, Math.Ceiling, Math.Floor",
      "signature": "Math.Round(double value); Math.Ceiling(double value); Math.Floor(double value)",
      "relation": "different_semantics",
      "note": "All three return double, not int. Math.Round on a midpoint defaults to round-half-to-even (2.5 gives 2); cast to int for a whole number.",
      "differences": [
        {
          "axis": "numeric_types",
          "note": "Return type is double; Lipi's one-argument forms return int."
        }
      ],
      "evidence": {
        "url": "https://learn.microsoft.com/en-us/dotnet/api/system.math",
        "fragment": "Methods: Round(Double) rounds midpoint values to the nearest even number; Ceiling(Double); Floor(Double)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "math.rounding",
      "language": "pine",
      "source": "present",
      "construct": "math.round, math.ceil, math.floor",
      "signature": "math.round(number, precision) → int, or float when precision is given; math.ceil(number) → int; math.floor(number) → int",
      "relation": "equivalent_with_caveat",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_math.round (also #fun_math.ceil, #fun_math.floor)",
        "accessed": "2026-11-01"
      },
      "verified": "documented",
      "note": "Pine rounds ties up (toward positive infinity); Lipi rounds ties away from zero, so -2.5 gives -3 in Lipi and -2 in Pine."
    },
    {
      "concept": "math.rounding",
      "language": "thinkscript",
      "source": "present",
      "construct": "Round, RoundUp, RoundDown, Ceil, Floor",
      "signature": "Round(double number, int numberOfDigits = 2); RoundUp(double number, int numberOfDigits = 2); RoundDown(double number, int numberOfDigits = 2); Ceil(double value); Floor(double value)",
      "relation": "different_semantics",
      "note": "Round() keeps 2 decimals by default, while Lipi math.round with no precision gives a whole int; RoundDown truncates toward zero, unlike floor.",
      "differences": [
        {
          "axis": "numeric_types",
          "note": "thinkScript results stay doubles; Lipi ceil, floor and one-argument round return int."
        }
      ],
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Functions/Math---Trig/Round",
        "fragment": "Round ( double number , int numberOfDigits ); default numberOfDigits: 2",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "math.round-to-tick",
      "language": "mql4",
      "source": "present",
      "construct": "NormalizeDouble",
      "signature": "double NormalizeDouble(double value, int digits)",
      "relation": "equivalent_with_caveat",
      "note": "Rounds to a decimal count (0-8), usually Digits(), not to a tick multiple; differs when the tick is not a power of ten.",
      "evidence": {
        "url": "https://docs.mql4.com/convert/normalizedouble",
        "fragment": "NormalizeDouble",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "math.round-to-tick",
      "language": "mql5",
      "source": "absent",
      "note": "No tick-size rounding function. NormalizeDouble rounds to a count of decimal digits (0 to 8), not to a multiple of the tick size.",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/convert/normalizedouble",
        "fragment": "NormalizeDouble parameter digits: number of digits after point (0-8)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "math.round-to-tick",
      "language": "ninjascript",
      "source": "present",
      "construct": "Instrument.MasterInstrument.RoundToTickSize",
      "signature": "Instrument.MasterInstrument.RoundToTickSize(double price)",
      "relation": "equivalent_with_caveat",
      "note": "Called on the instrument object; page says it rounds up to a tick multiple, where Lipi rounds to nearest. A separate RoundDownToTickSize exists.",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/roundtoticksize.htm",
        "fragment": "RoundToTickSize() definition and syntax",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "math.round-to-tick",
      "language": "pine",
      "source": "present",
      "construct": "math.round_to_mintick",
      "signature": "math.round_to_mintick(number) → float",
      "relation": "exact",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_math.round_to_mintick",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "math.round-to-tick",
      "language": "thinkscript",
      "source": "present",
      "construct": "Round, TickSize",
      "signature": "TickSize(String symbol = getSymbol())",
      "relation": "composite",
      "note": "No single function: divide by TickSize(), Round to 0 digits, multiply back by TickSize(). Lipi math.round_to_mintick does this in one call.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Functions/Math---Trig/Round",
        "fragment": "Example: 12 period SMA rounded to the nearest tick size value",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "math.min-max",
      "language": "mql4",
      "source": "present",
      "construct": "MathMin, MathMax",
      "signature": "double MathMax(double value1, double value2); double MathMin(double value1, double value2)",
      "relation": "equivalent_with_caveat",
      "note": "Exactly two arguments; nest calls to compare more values, where Lipi accepts any number.",
      "evidence": {
        "url": "https://docs.mql4.com/math/mathmax",
        "fragment": "MathMax; MathMin",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "math.min-max",
      "language": "mql5",
      "source": "present",
      "construct": "MathMin, MathMax",
      "signature": "double MathMin(double value1, double value2)",
      "relation": "equivalent_with_caveat",
      "note": "Exactly two arguments; nest calls for more values. Integer arguments keep an integer result type.",
      "differences": [
        {
          "axis": "numeric_types",
          "note": "Mixed argument types are cast to the larger type, and the result has that type."
        }
      ],
      "evidence": {
        "url": "https://www.mql5.com/en/docs/math/mathmin",
        "fragment": "MathMin parameters value1, value2 and Note on types",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "math.min-max",
      "language": "ninjascript",
      "source": "present",
      "construct": "Math.Min, Math.Max",
      "signature": "Math.Min(double a, double b); Math.Max(double a, double b)",
      "relation": "equivalent_with_caveat",
      "note": "Exactly two arguments; Lipi accepts any number of values. Nest the calls to compare more.",
      "evidence": {
        "url": "https://learn.microsoft.com/en-us/dotnet/api/system.math",
        "fragment": "Methods: Min(Double, Double), Max(Double, Double)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "math.min-max",
      "language": "pine",
      "source": "present",
      "construct": "math.min, math.max",
      "signature": "math.min(number0, number1, ...) → int or float; math.max(number0, number1, ...) → int or float",
      "relation": "exact",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_math.min (also #fun_math.max)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "math.min-max",
      "language": "thinkscript",
      "source": "present",
      "construct": "Min, Max",
      "signature": "Min(double value1, double value2); Max(double value1, double value2)",
      "relation": "equivalent_with_caveat",
      "note": "Exactly two arguments; Lipi math.min and math.max take any number. Neither looks back over bars (Lowest and Highest do).",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Functions/Math---Trig/Max",
        "fragment": "Max ( double value1 , double value2 )",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "math.power",
      "language": "mql4",
      "source": "present",
      "construct": "MathPow, MathSqrt",
      "signature": "double MathPow(double base, double exponent); double MathSqrt(double value)",
      "relation": "exact",
      "evidence": {
        "url": "https://docs.mql4.com/math/mathpow",
        "fragment": "MathPow; MathSqrt",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "math.power",
      "language": "mql5",
      "source": "present",
      "construct": "MathPow, MathSqrt",
      "signature": "double MathPow(double base, double exponent)",
      "relation": "exact",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/math/mathpow",
        "fragment": "MathPow base, exponent",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "math.power",
      "language": "ninjascript",
      "source": "present",
      "construct": "Math.Pow, Math.Sqrt",
      "signature": "Math.Pow(double x, double y); Math.Sqrt(double d)",
      "relation": "equivalent_with_caveat",
      "evidence": {
        "url": "https://learn.microsoft.com/en-us/dotnet/api/system.math",
        "fragment": "Methods: Pow(Double, Double), Sqrt(Double)",
        "accessed": "2026-11-01"
      },
      "verified": "documented",
      "note": "Math.Pow returns infinity for a zero base with a negative exponent; Lipi math.pow returns na there, changing later comparisons."
    },
    {
      "concept": "math.power",
      "language": "pine",
      "source": "present",
      "construct": "math.pow, math.sqrt",
      "signature": "math.pow(base, exponent) → float; math.sqrt(number) → float",
      "relation": "exact",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_math.pow (also #fun_math.sqrt)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "math.power",
      "language": "thinkscript",
      "source": "present",
      "construct": "Power, Sqrt, Sqr",
      "signature": "Power(double number, double power); Sqrt(double value); Sqr(double value)",
      "relation": "equivalent_with_caveat",
      "note": "Power and Sqrt map to math.pow and math.sqrt; Sqr (square) has no Lipi function, use math.pow(x, 2).",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Functions/Math---Trig/Power",
        "fragment": "Power ( double number , double power )",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "math.exp-log",
      "language": "mql4",
      "source": "present",
      "construct": "MathExp, MathLog, MathLog10",
      "signature": "double MathExp(double value); double MathLog(double val); double MathLog10(double val)",
      "relation": "equivalent_with_caveat",
      "note": "Invalid input gives NaN, and MathLog(0) gives INF, where Lipi's log10 gives na.",
      "differences": [
        {
          "axis": "warmup_and_na",
          "note": "out-of-domain input yields NaN or INF, not na."
        }
      ],
      "evidence": {
        "url": "https://docs.mql4.com/math/mathlog",
        "fragment": "MathLog Return Value; MathExp; MathLog10",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "math.exp-log",
      "language": "mql5",
      "source": "present",
      "construct": "MathExp, MathLog, MathLog10",
      "signature": "double MathLog(double val)",
      "relation": "equivalent_with_caveat",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/math/mathlog",
        "fragment": "MathLog Return Value (natural logarithm)",
        "accessed": "2026-11-01"
      },
      "verified": "documented",
      "note": "MathLog(0) returns infinity and negatives give NaN; Lipi math.log(0) and negatives return na, so later comparisons on the result differ."
    },
    {
      "concept": "math.exp-log",
      "language": "ninjascript",
      "source": "present",
      "construct": "Math.Exp, Math.Log, Math.Log10",
      "signature": "Math.Exp(double d); Math.Log(double d); Math.Log10(double d)",
      "relation": "equivalent_with_caveat",
      "evidence": {
        "url": "https://learn.microsoft.com/en-us/dotnet/api/system.math",
        "fragment": "Methods: Exp(Double), Log(Double), Log10(Double)",
        "accessed": "2026-11-01"
      },
      "verified": "documented",
      "note": "Math.Log(0) returns negative infinity; Lipi math.log(0) returns na, so later comparisons on the result differ."
    },
    {
      "concept": "math.exp-log",
      "language": "pine",
      "source": "present",
      "construct": "math.exp, math.log, math.log10",
      "signature": "math.exp(number) → float; math.log(number) → float; math.log10(number) → float",
      "relation": "exact",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_math.exp (also #fun_math.log, #fun_math.log10)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "math.exp-log",
      "language": "thinkscript",
      "source": "present",
      "construct": "Exp, Log, Lg",
      "signature": "Exp(double number); Log(double number); Lg(double number)",
      "relation": "equivalent_with_caveat",
      "note": "Log is the natural logarithm and Lg is base 10, so Lg maps to math.log10, not math.log.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Functions/Math---Trig/Lg",
        "fragment": "Lg: base-10 logarithm; Log: natural logarithm",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "math.trig",
      "language": "mql4",
      "source": "present",
      "construct": "MathSin, MathCos, MathTan, MathArcsin, MathArccos, MathArctan",
      "signature": "double MathSin(double value); double MathArcsin(double val)",
      "relation": "exact",
      "evidence": {
        "url": "https://docs.mql4.com/math/mathsin",
        "fragment": "MathSin",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "math.trig",
      "language": "mql5",
      "source": "present",
      "construct": "MathSin, MathCos, MathTan, MathArcsin, MathArccos, MathArctan",
      "signature": "double MathSin(double value)",
      "relation": "exact",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/math/mathsin",
        "fragment": "MathSin value: argument in radians",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "math.trig",
      "language": "ninjascript",
      "source": "present",
      "construct": "Math.Sin, Math.Cos, Math.Tan, Math.Asin, Math.Acos, Math.Atan",
      "signature": "Math.Sin(double a)",
      "relation": "exact",
      "evidence": {
        "url": "https://learn.microsoft.com/en-us/dotnet/api/system.math",
        "fragment": "Methods: Sin(Double), Cos(Double), Tan(Double), Asin(Double), Acos(Double), Atan(Double)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "math.trig",
      "language": "pine",
      "source": "present",
      "construct": "math.sin, math.cos, math.tan, math.asin, math.acos, math.atan",
      "signature": "math.sin(angle) → float, angle in radians; same shape for the other five",
      "relation": "exact",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_math.sin (also #fun_math.cos, #fun_math.tan, #fun_math.asin, #fun_math.acos, #fun_math.atan)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "math.trig",
      "language": "thinkscript",
      "source": "present",
      "construct": "Sin, Cos, Tan, ASin, ACos, ATan",
      "signature": "Sin(double angle); ATan(double value)",
      "relation": "exact",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Functions/Math---Trig/Sin",
        "fragment": "Sin ( double angle ): angle in radians",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "math.angles",
      "language": "mql4",
      "source": "absent",
      "note": "No degree/radian converters in the math group; multiply by the pi/180 factor yourself.",
      "evidence": {
        "url": "https://docs.mql4.com/math",
        "fragment": "Mathematical Functions table (MathAbs ... MathIsValidNumber)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "math.angles",
      "language": "mql5",
      "source": "absent",
      "note": "The math index has no degree or radian conversion function; multiply by 180 over pi yourself.",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/math",
        "fragment": "Math Functions index (MathAbs ... MathCompareByDigits)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "math.angles",
      "language": "ninjascript",
      "source": "absent",
      "note": "System.Math has no degree or radian converters; multiply by 180/Math.PI, or its inverse, by hand.",
      "evidence": {
        "url": "https://learn.microsoft.com/en-us/dotnet/api/system.math",
        "fragment": "Fields: E, PI, Tau; Methods list has no degree or radian conversion",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "math.angles",
      "language": "pine",
      "source": "present",
      "construct": "math.todegrees, math.toradians",
      "signature": "math.todegrees(radians) → float; math.toradians(degrees) → float",
      "relation": "exact",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_math.todegrees (also #fun_math.toradians)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "math.angles",
      "language": "thinkscript",
      "source": "absent",
      "note": "No degree/radian conversion function in the math section; docs multiply by 180 and divide by Double.Pi by hand.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Functions/Math---Trig/ATan",
        "fragment": "Example: ATan result converted with 180 / Double.Pi",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "math.sign",
      "language": "mql4",
      "source": "absent",
      "note": "No sign function in the math group; compare the value to zero.",
      "evidence": {
        "url": "https://docs.mql4.com/math",
        "fragment": "Mathematical Functions table (MathAbs ... MathIsValidNumber)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "math.sign",
      "language": "mql5",
      "source": "absent",
      "note": "No sign function in the math index; use a comparison expression instead.",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/math",
        "fragment": "Math Functions index (no MathSign entry)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "math.sign",
      "language": "ninjascript",
      "source": "present",
      "construct": "Math.Sign",
      "signature": "Math.Sign(double value)",
      "relation": "equivalent_with_caveat",
      "note": "Returns an int (-1, 0 or 1), while Lipi returns a float; it throws on NaN.",
      "differences": [
        {
          "axis": "numeric_types",
          "note": "int result instead of float."
        }
      ],
      "evidence": {
        "url": "https://learn.microsoft.com/en-us/dotnet/api/system.math.sign",
        "fragment": "Math.Sign Exceptions: ArithmeticException, value is equal to NaN",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "math.sign",
      "language": "pine",
      "source": "present",
      "construct": "math.sign",
      "signature": "math.sign(number) → float",
      "relation": "exact",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_math.sign",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "math.sign",
      "language": "thinkscript",
      "source": "present",
      "construct": "Sign",
      "signature": "Sign(double number)",
      "relation": "equivalent_with_caveat",
      "note": "Returns 1, 0 or -1, so zero gives 0; Lipi's reference states only -1 and 1, so check how it treats zero.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Functions/Math---Trig/Sign",
        "fragment": "Sign ( double number ): 1 positive, 0 zero, -1 negative",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "math.random",
      "language": "mql4",
      "source": "present",
      "construct": "MathRand, MathSrand",
      "signature": "int MathRand(); void MathSrand(int seed)",
      "relation": "different_semantics",
      "note": "Returns an integer 0 to 32767, not a float in a range you choose; scale it yourself. Call MathSrand first to set the seed.",
      "differences": [
        {
          "axis": "state_and_side_effects",
          "note": "generator state is seeded with MathSrand; a fixed seed repeats the sequence."
        }
      ],
      "evidence": {
        "url": "https://docs.mql4.com/math/mathrand",
        "fragment": "MathRand; MathSrand",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "math.random",
      "language": "mql5",
      "source": "present",
      "construct": "MathRand, MathSrand",
      "signature": "int MathRand()",
      "relation": "different_semantics",
      "note": "Returns an integer from 0 to 32767, not a float between two bounds. Seed with MathSrand before the first call and scale the result yourself.",
      "differences": [
        {
          "axis": "numeric_types",
          "note": "Integer result 0 to 32767 instead of a float within min and max."
        },
        {
          "axis": "state_and_side_effects",
          "note": "The generator must be seeded with MathSrand first; Lipi has no seed argument."
        }
      ],
      "evidence": {
        "url": "https://www.mql5.com/en/docs/math/mathrand",
        "fragment": "MathRand Return Value 0 to 32767 and note on MathSrand",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "math.random",
      "language": "ninjascript",
      "source": "present",
      "construct": "Random.NextDouble()",
      "signature": "double NextDouble()",
      "relation": "equivalent_with_caveat",
      "note": "An instance method on a Random object; returns 0.0 up to but excluding 1.0. Scale to min and max by hand.",
      "evidence": {
        "url": "https://learn.microsoft.com/en-us/dotnet/api/system.random.nextdouble",
        "fragment": "Random.NextDouble: greater than or equal to 0.0, and less than 1.0",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "math.random",
      "language": "pine",
      "source": "present",
      "construct": "math.random",
      "signature": "math.random(min, max, seed) → series float",
      "relation": "equivalent_with_caveat",
      "note": "Pine takes an optional seed for repeatable sequences; Lipi has none. Pine's reference excludes the lower bound, Lipi's docs include it.",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_math.random",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "math.random",
      "language": "thinkscript",
      "source": "present",
      "construct": "Random",
      "signature": "Random()",
      "relation": "equivalent_with_caveat",
      "note": "Takes no arguments and returns a value from 0.0 up to, not including, 1.0; scale it yourself to match math.random(min, max).",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Functions/Math---Trig/Random",
        "fragment": "Random ()",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "math.avg-sum",
      "language": "mql4",
      "source": "absent",
      "note": "No average or multi-value sum in the math group; MathMax and MathMin take two values only.",
      "evidence": {
        "url": "https://docs.mql4.com/math",
        "fragment": "Mathematical Functions table (MathAbs ... MathIsValidNumber)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "math.avg-sum",
      "language": "mql5",
      "source": "present",
      "construct": "MathMean, vector::Sum",
      "signature": "double MathMean(const double& array[])",
      "relation": "equivalent_with_caveat",
      "note": "MathMean averages an array, not a list of arguments. There is no per-bar windowed sum; vector::Sum totals a whole vector you fill first.",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/standardlibrary/mathematics/stat/array_stat/mathmean",
        "fragment": "MathMean signature and Return Value",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "math.avg-sum",
      "language": "ninjascript",
      "source": "present",
      "construct": "Enumerable.Average() and Enumerable.Sum() (System.Linq)",
      "signature": "double Average(this IEnumerable<double> source); double Sum(this IEnumerable<double> source)",
      "relation": "equivalent_with_caveat",
      "note": "Apply to an array or list, not to separate arguments; needs using System.Linq. Average and Sum are separate calls.",
      "evidence": {
        "url": "https://learn.microsoft.com/en-us/dotnet/api/system.linq.enumerable",
        "fragment": "Methods: Average(IEnumerable<Double>), Sum(IEnumerable<Double>)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "math.avg-sum",
      "language": "pine",
      "source": "present",
      "construct": "math.avg, math.sum",
      "signature": "math.avg(number0, number1, ...) → float; math.sum(source, length) → series float",
      "relation": "equivalent_with_caveat",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_math.avg (also #fun_math.sum)",
        "accessed": "2026-11-01"
      },
      "verified": "documented",
      "note": "Pine math.sum ignores na values; Lipi returns na on bars where the current source is na and skips na inside the window."
    },
    {
      "concept": "math.avg-sum",
      "language": "thinkscript",
      "source": "present",
      "construct": "Average, Sum",
      "signature": "Average(IDataHolder data, int length = 12); Sum(IDataHolder data, int length = 12)",
      "relation": "different_semantics",
      "note": "Average is a moving window like ta.sma, not Lipi math.avg (mean of its arguments). Sum is a window sum and matches math.sum.",
      "differences": [
        {
          "axis": "history_indexing",
          "note": "Average looks back over length bars; Lipi math.avg averages only its own arguments on the current bar."
        }
      ],
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Functions/Tech-Analysis/Average",
        "fragment": "Average ( IDataHolder data , int length ); length: 12",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "str.tostring",
      "language": "mql4",
      "source": "present",
      "construct": "DoubleToString, IntegerToString",
      "signature": "string DoubleToString(double value, int digits=8); string IntegerToString(long number, int str_len=0, ushort fill_symbol=' ')",
      "relation": "equivalent_with_caveat",
      "note": "One function per type; DoubleToString defaults to 8 decimals where Lipi trims to 4. No na or bool rendering is documented.",
      "differences": [
        {
          "axis": "numeric_types",
          "note": "decimals are set by the digits argument (0-16); negative values give scientific format."
        }
      ],
      "evidence": {
        "url": "https://docs.mql4.com/convert/doubletostring",
        "fragment": "DoubleToString digits parameter; IntegerToString",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "str.tostring",
      "language": "mql5",
      "source": "present",
      "construct": "DoubleToString, IntegerToString",
      "signature": "string DoubleToString(double value, int digits=8)",
      "relation": "equivalent_with_caveat",
      "note": "Fixed decimal places (default 8; negative digits give scientific form). Separate IntegerToString for integers; no bool or na handling.",
      "differences": [
        {
          "axis": "numeric_types",
          "note": "Digits 0 to 16 are kept as fixed places; Lipi rounds to 4 places and trims trailing zeros."
        }
      ],
      "evidence": {
        "url": "https://www.mql5.com/en/docs/convert/doubletostring",
        "fragment": "DoubleToString digits parameter",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "str.tostring",
      "language": "ninjascript",
      "source": "present",
      "construct": "ToString()",
      "signature": "double.ToString()",
      "relation": "equivalent_with_caveat",
      "note": "No default four-decimal rounding: full precision prints. Bool prints True or False. Custom patterns go in as a format string.",
      "differences": [
        {
          "axis": "numeric_types",
          "note": "Lipi rounds floats to four decimals by default; C# does not."
        }
      ],
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/basic_syntax.htm",
        "fragment": "Print(myDouble.ToString()) examples",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "str.tostring",
      "language": "pine",
      "source": "present",
      "construct": "str.tostring",
      "signature": "str.tostring(value, format) → string",
      "relation": "equivalent_with_caveat",
      "note": "Pine renders na as \"NaN\"; Lipi renders \"NA\". Lipi's unformatted float rounds to 4 decimals; Pine's reference states no such default.",
      "differences": [
        {
          "axis": "warmup_and_na",
          "note": "A na value becomes the text \"NaN\" in Pine and \"NA\" in Lipi, so string comparisons on it differ."
        }
      ],
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_str.tostring",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "str.tostring",
      "language": "thinkscript",
      "source": "present",
      "construct": "AsText",
      "signature": "AsText(double value, String format = NumberFormat.TWO_DECIMAL_PLACES)",
      "relation": "different_semantics",
      "note": "AsText defaults to 2 decimals; Lipi str.tostring rounds to 4 decimals. Concat and the + operator convert doubles with 4 decimals.",
      "differences": [
        {
          "axis": "numeric_types",
          "note": "Decimal places come from a NumberFormat constant, not a format string such as Lipi's \"#.####\"."
        }
      ],
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Functions/Others/AsText",
        "fragment": "AsText ( double value , String format )",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "str.tonumber",
      "language": "mql4",
      "source": "present",
      "construct": "StringToDouble, StringToInteger",
      "signature": "double StringToDouble(string value); long StringToInteger(string value)",
      "relation": "equivalent_with_caveat",
      "note": "Two functions by result type (double, long); Lipi always returns float. Behaviour on unparsable text is not documented.",
      "differences": [
        {
          "axis": "numeric_types",
          "note": "StringToInteger returns long, not float."
        }
      ],
      "evidence": {
        "url": "https://docs.mql4.com/convert/stringtodouble",
        "fragment": "StringToDouble; StringToInteger",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "str.tonumber",
      "language": "mql5",
      "source": "present",
      "construct": "StringToDouble, StringToInteger",
      "signature": "double StringToDouble(string value)",
      "relation": "equivalent_with_caveat",
      "note": "Two functions by result type (double or long); Lipi always returns a float. The page does not state behaviour on invalid text.",
      "differences": [
        {
          "axis": "numeric_types",
          "note": "StringToInteger returns long; Lipi returns float for every input."
        }
      ],
      "evidence": {
        "url": "https://www.mql5.com/en/docs/convert/stringtodouble",
        "fragment": "StringToDouble signature and Return Value",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "str.tonumber",
      "language": "ninjascript",
      "source": "present",
      "construct": "double.TryParse / double.Parse",
      "signature": "bool double.TryParse(string s, out double result)",
      "relation": "equivalent_with_caveat",
      "note": "TryParse reports success through a bool return and an out parameter instead of giving na on bad text.",
      "evidence": {
        "url": "https://learn.microsoft.com/en-us/dotnet/api/system.double.tryparse",
        "fragment": "Double.TryParse: a return value indicates whether the conversion succeeded",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "str.tonumber",
      "language": "pine",
      "source": "present",
      "construct": "str.tonumber",
      "signature": "str.tonumber(string) → float",
      "relation": "exact",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_str.tonumber",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "str.tonumber",
      "language": "thinkscript",
      "source": "absent",
      "note": "No text-to-number function: the conversion table shows String accepting only Symbol, and no function in the reference parses text.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Data-Types/Data-Conversion",
        "fragment": "table row: String accepts Symbol",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "str.length",
      "language": "mql4",
      "source": "present",
      "construct": "StringLen",
      "signature": "int StringLen(string string_value)",
      "relation": "equivalent_with_caveat",
      "note": "Counts symbols of a Unicode string; Lipi counts UTF-8 bytes, so non-ASCII text gives different numbers.",
      "evidence": {
        "url": "https://docs.mql4.com/strings/stringlen",
        "fragment": "StringLen Return Value",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "str.length",
      "language": "mql5",
      "source": "present",
      "construct": "StringLen",
      "signature": "int StringLen(string string_value)",
      "relation": "equivalent_with_caveat",
      "note": "Counts symbols without the terminating zero. Lipi counts UTF-8 bytes, so non-ASCII text can give different results.",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/strings/stringlen",
        "fragment": "StringLen Return Value: number of symbols without the ending zero",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "str.length",
      "language": "ninjascript",
      "source": "present",
      "construct": "string.Length",
      "signature": "string.Length (property)",
      "relation": "equivalent_with_caveat",
      "note": "A property, not a call; it counts Char objects (UTF-16 units) where Lipi counts UTF-8 bytes, so non-ASCII text can differ.",
      "evidence": {
        "url": "https://learn.microsoft.com/en-us/dotnet/api/system.string.length",
        "fragment": "String.Length: number of Char objects in this instance, not the number of Unicode characters",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "str.length",
      "language": "pine",
      "source": "present",
      "construct": "str.length",
      "signature": "str.length(string) → int",
      "relation": "equivalent_with_caveat",
      "note": "Pine's reference counts characters; Lipi counts UTF-8 bytes, so text outside ASCII gives a larger Lipi length.",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_str.length",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "str.length",
      "language": "thinkscript",
      "source": "absent",
      "note": "No string length function; the String type page describes only text constants in double quotes.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Data-Types/String",
        "fragment": "String: text constants in double quotes",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "str.case",
      "language": "mql4",
      "source": "present",
      "construct": "StringToUpper, StringToLower",
      "signature": "bool StringToUpper(string& string_var); bool StringToLower(string& string_var)",
      "relation": "different_semantics",
      "note": "Changes the variable in place and returns a success bool, not the converted text; do not use the result as the string.",
      "differences": [
        {
          "axis": "state_and_side_effects",
          "note": "the string argument is [in][out] and is modified by the call."
        }
      ],
      "evidence": {
        "url": "https://docs.mql4.com/strings/stringtoupper",
        "fragment": "StringToUpper; StringToLower",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "str.case",
      "language": "mql5",
      "source": "present",
      "construct": "StringToUpper, StringToLower",
      "signature": "bool StringToUpper(string& string_var)",
      "relation": "different_semantics",
      "note": "Changes the variable in place and returns a success flag, not the new string. Code like s = StringToUpper(s) is wrong here.",
      "differences": [
        {
          "axis": "state_and_side_effects",
          "note": "Mutates its argument by reference; Lipi returns a new string and leaves the source unchanged."
        }
      ],
      "evidence": {
        "url": "https://www.mql5.com/en/docs/strings/stringtoupper",
        "fragment": "StringToUpper string_var [in][out], Return Value bool",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "str.case",
      "language": "ninjascript",
      "source": "present",
      "construct": "ToUpper(), ToLower()",
      "signature": "string.ToUpper(); string.ToLower()",
      "relation": "equivalent_with_caveat",
      "evidence": {
        "url": "https://learn.microsoft.com/en-us/dotnet/api/system.string",
        "fragment": "Methods: ToUpper() returns a copy converted to uppercase; ToLower()",
        "accessed": "2026-11-01"
      },
      "verified": "documented",
      "note": "ToUpper() and ToLower() use the current culture's casing rules; Lipi's str.upper and str.lower do not depend on culture."
    },
    {
      "concept": "str.case",
      "language": "pine",
      "source": "present",
      "construct": "str.upper, str.lower",
      "signature": "str.upper(source) → string; str.lower(source) → string",
      "relation": "exact",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_str.upper (also #fun_str.lower)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "str.case",
      "language": "thinkscript",
      "source": "absent",
      "note": "No upper or lower case functions in the reference; text tools are limited to +, Concat and AsText.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Functions/Others",
        "fragment": "Others function list (no case conversion entry)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "str.search",
      "language": "mql4",
      "source": "present",
      "construct": "StringFind",
      "signature": "int StringFind(string string_value, string match_substring, int start_pos=0)",
      "relation": "equivalent_with_caveat",
      "note": "Returns the start position or -1, like str.pos. Contains is a test for >= 0; starts-with and ends-with have no function.",
      "evidence": {
        "url": "https://docs.mql4.com/strings/stringfind",
        "fragment": "StringFind",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "str.search",
      "language": "mql5",
      "source": "present",
      "construct": "StringFind",
      "signature": "int StringFind(string string_value, string match_substring, int start_pos=0)",
      "relation": "equivalent_with_caveat",
      "note": "One function returns a 0-based start position or -1. Contains, startswith and endswith are tests on that result or on StringSubstr.",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/strings/stringfind",
        "fragment": "StringFind Return Value: position or -1",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "str.search",
      "language": "ninjascript",
      "source": "present",
      "construct": "Contains, IndexOf, StartsWith, EndsWith",
      "signature": "string.Contains(string); string.IndexOf(string); string.StartsWith(string); string.EndsWith(string)",
      "relation": "equivalent_with_caveat",
      "note": "IndexOf returns a character index where Lipi counts bytes. StartsWith and EndsWith with a string argument are culture-sensitive by default.",
      "evidence": {
        "url": "https://learn.microsoft.com/en-us/dotnet/standard/base-types/best-practices-strings",
        "fragment": "String.StartsWith and String.EndsWith: overloads that accept a string parameter perform a culture-sensitive comparison",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "str.search",
      "language": "pine",
      "source": "present",
      "construct": "str.contains, str.pos, str.startswith, str.endswith",
      "signature": "str.contains(source, str) → bool; str.pos(source, str) → int; str.startswith(source, str) → bool; str.endswith(source, str) → bool",
      "relation": "equivalent_with_caveat",
      "note": "str.pos returns na when absent, Lipi returns -1 (byte offsets). Pine names the second parameter str in startswith and endswith; Lipi uses prefix and suffix.",
      "differences": [
        {
          "axis": "warmup_and_na",
          "note": "Not-found is na in Pine and -1 in Lipi, so a na() test on the result never fires in Lipi."
        }
      ],
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_str.pos (also #fun_str.contains, #fun_str.startswith, #fun_str.endswith)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "str.search",
      "language": "thinkscript",
      "source": "absent",
      "note": "No contains, position, starts-with or ends-with function; the docs only show whole-string == comparison.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Functions/Others/GetSymbolPart",
        "fragment": "string comparison with == on GetSymbolPart result",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "str.substring",
      "language": "mql4",
      "source": "present",
      "construct": "StringSubstr",
      "signature": "string StringSubstr(string string_value, int start_pos, int length=0)",
      "relation": "different_semantics",
      "note": "Third argument is a length, not an end index; a length of 0 or less runs to the end of the string.",
      "evidence": {
        "url": "https://docs.mql4.com/strings/stringsubstr",
        "fragment": "StringSubstr length parameter",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "str.substring",
      "language": "mql5",
      "source": "present",
      "construct": "StringSubstr",
      "signature": "string StringSubstr(string string_value, int start_pos, int length=-1)",
      "relation": "different_semantics",
      "note": "The third argument is a length, not an end index; -1 or omitted runs to the end. Lipi's second bound is an exclusive end position.",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/strings/stringsubstr",
        "fragment": "StringSubstr parameter length (-1 means to end of string)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "str.substring",
      "language": "ninjascript",
      "source": "present",
      "construct": "Substring",
      "signature": "string.Substring(int startIndex, int length)",
      "relation": "different_semantics",
      "note": "Second argument is a length, not an exclusive end index as in Lipi. .NET counts UTF-16 code units; Lipi counts whole characters.",
      "evidence": {
        "url": "https://learn.microsoft.com/en-us/dotnet/api/system.string",
        "fragment": "Methods: Substring(Int32, Int32) starts at a specified character position and has a specified length",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "str.substring",
      "language": "pine",
      "source": "present",
      "construct": "str.substring",
      "signature": "str.substring(source, begin_pos, end_pos) → string",
      "relation": "equivalent_with_caveat",
      "note": "Same 0-based, start-inclusive, end-exclusive cut with optional end. Pine's parameters are begin_pos and end_pos; Lipi's are start and end.",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_str.substring",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "str.substring",
      "language": "thinkscript",
      "source": "absent",
      "note": "No substring or slicing function; strings can only be built (Concat, +) and compared.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Functions/Others",
        "fragment": "Others function list (no substring entry)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "str.replace",
      "language": "mql4",
      "source": "present",
      "construct": "StringReplace",
      "signature": "int StringReplace(string& str, const string find, const string replacement)",
      "relation": "different_semantics",
      "note": "Edits the string in place, replaces every match, and returns the replacement count (-1 on error), not the new text.",
      "differences": [
        {
          "axis": "state_and_side_effects",
          "note": "the str argument is [in][out] and is modified."
        }
      ],
      "evidence": {
        "url": "https://docs.mql4.com/strings/stringreplace",
        "fragment": "StringReplace",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "str.replace",
      "language": "mql5",
      "source": "present",
      "construct": "StringReplace",
      "signature": "int StringReplace(string& str, const string find, const string replacement)",
      "relation": "different_semantics",
      "note": "Edits the variable in place, replaces every match and returns the replacement count (-1 on error). There is no maximum-count argument.",
      "differences": [
        {
          "axis": "state_and_side_effects",
          "note": "Mutates its argument and returns a count, not the new string."
        }
      ],
      "evidence": {
        "url": "https://www.mql5.com/en/docs/strings/stringreplace",
        "fragment": "StringReplace str [in][out] and Return Value",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "str.replace",
      "language": "ninjascript",
      "source": "present",
      "construct": "Replace",
      "signature": "string.Replace(string oldValue, string newValue)",
      "relation": "equivalent_with_caveat",
      "note": "Replaces every occurrence and has no count argument, so it matches Lipi's replace_all, not the counted replace.",
      "evidence": {
        "url": "https://learn.microsoft.com/en-us/dotnet/api/system.string",
        "fragment": "Methods: Replace(String, String) replaces all occurrences of a specified string",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "str.replace",
      "language": "pine",
      "source": "present",
      "construct": "str.replace, str.replace_all",
      "signature": "str.replace(source, target, replacement, occurrence) → string; str.replace_all(source, target, replacement) → string",
      "relation": "different_semantics",
      "note": "Pine str.replace changes only the single occurrence numbered by occurrence (0-based, default first). Lipi's str.replace changes all unless count limits it.",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_str.replace (also #fun_str.replace_all)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "str.replace",
      "language": "thinkscript",
      "source": "absent",
      "note": "No text replacement function in the reference.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Functions/Others",
        "fragment": "Others function list (no replace entry)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "str.split",
      "language": "mql4",
      "source": "present",
      "construct": "StringSplit",
      "signature": "int StringSplit(const string string_value, const ushort separator, string& result[])",
      "relation": "equivalent_with_caveat",
      "note": "Separator is one character code (ushort), pieces fill an output array, and the return value is the piece count.",
      "evidence": {
        "url": "https://docs.mql4.com/strings/stringsplit",
        "fragment": "StringSplit",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "str.split",
      "language": "mql5",
      "source": "present",
      "construct": "StringSplit",
      "signature": "int StringSplit(const string string_value, const ushort separator, string& result[])",
      "relation": "equivalent_with_caveat",
      "note": "The separator is one character code, not a string. Pieces go into an output array and the call returns their count.",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/strings/stringsplit",
        "fragment": "StringSplit separator (ushort) and result[] array",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "str.split",
      "language": "ninjascript",
      "source": "present",
      "construct": "Split",
      "signature": "string.Split(char[] separator) / string.Split(string[] separator, StringSplitOptions options)",
      "relation": "equivalent_with_caveat",
      "note": "Returns string[]. The separator is a char or an array of strings plus an options value, not one plain string argument.",
      "evidence": {
        "url": "https://learn.microsoft.com/en-us/dotnet/api/system.string",
        "fragment": "Methods: Split(Char[]); Split(String[], StringSplitOptions)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "str.split",
      "language": "pine",
      "source": "present",
      "construct": "str.split",
      "signature": "str.split(string, separator) → array<string>",
      "relation": "exact",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_str.split",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "str.split",
      "language": "thinkscript",
      "source": "absent",
      "note": "No split function, and no array type to return pieces in.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Functions/Others",
        "fragment": "Others function list (no split entry)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "str.trim",
      "language": "mql4",
      "source": "present",
      "construct": "StringTrimLeft, StringTrimRight",
      "signature": "string StringTrimLeft(const string text); string StringTrimRight(const string text)",
      "relation": "equivalent_with_caveat",
      "note": "Two functions, one per side; the page says the string is modified in place and a copy is returned. Call both to trim both ends.",
      "differences": [
        {
          "axis": "state_and_side_effects",
          "note": "The page says the string argument is modified in place as well as returned."
        }
      ],
      "evidence": {
        "url": "https://docs.mql4.com/strings/stringtrimleft",
        "fragment": "StringTrimLeft; StringTrimRight",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "str.trim",
      "language": "mql5",
      "source": "present",
      "construct": "StringTrimLeft, StringTrimRight",
      "signature": "int StringTrimLeft(string& string_var)",
      "relation": "equivalent_with_caveat",
      "note": "Two in-place calls, one per side, each returning the number of cut characters. They cut line feeds, spaces and tabs.",
      "differences": [
        {
          "axis": "state_and_side_effects",
          "note": "Mutates the variable passed in instead of returning a new string."
        }
      ],
      "evidence": {
        "url": "https://www.mql5.com/en/docs/strings/stringtrimleft",
        "fragment": "StringTrimLeft: the string is modified at place",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "str.trim",
      "language": "ninjascript",
      "source": "present",
      "construct": "Trim()",
      "signature": "string.Trim()",
      "relation": "exact",
      "evidence": {
        "url": "https://learn.microsoft.com/en-us/dotnet/api/system.string",
        "fragment": "Methods: Trim() removes all leading and trailing white-space characters",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "str.trim",
      "language": "pine",
      "source": "present",
      "construct": "str.trim",
      "signature": "str.trim(source) → string",
      "relation": "exact",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_str.trim",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "str.trim",
      "language": "thinkscript",
      "source": "absent",
      "note": "No whitespace trimming function in the reference.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Functions/Others",
        "fragment": "Others function list (no trim entry)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "str.repeat",
      "language": "mql4",
      "source": "present",
      "construct": "StringInit",
      "signature": "bool StringInit(string& string_var, int new_len=0, ushort character=0)",
      "relation": "equivalent_with_caveat",
      "note": "Fills a string with one repeated character in place; cannot repeat a multi-character text or add a separator.",
      "evidence": {
        "url": "https://docs.mql4.com/strings/stringinit",
        "fragment": "StringInit new_len, character parameters",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "str.repeat",
      "language": "mql5",
      "source": "present",
      "construct": "StringInit",
      "signature": "bool StringInit(string& string_var, int new_len=0, ushort character=0)",
      "relation": "equivalent_with_caveat",
      "note": "Fills a variable with one repeated character code to a set length. It cannot repeat a longer string or add a separator.",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/strings/stringinit",
        "fragment": "StringInit parameters new_len and character",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "str.repeat",
      "language": "ninjascript",
      "source": "present",
      "construct": "string.Concat(Enumerable.Repeat(text, count))",
      "signature": "IEnumerable<TResult> Repeat<TResult>(TResult element, int count)",
      "relation": "equivalent_with_caveat",
      "note": "No String method repeats text. Combine Enumerable.Repeat with string.Concat or string.Join; a separator needs Join.",
      "evidence": {
        "url": "https://learn.microsoft.com/en-us/dotnet/api/system.linq.enumerable",
        "fragment": "Methods: Repeat<TResult>(TResult, Int32) generates a sequence that contains one repeated value",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "str.repeat",
      "language": "pine",
      "source": "present",
      "construct": "str.repeat",
      "signature": "str.repeat(source, repeat, separator) → string",
      "relation": "equivalent_with_caveat",
      "note": "Same behaviour; the count parameter is named repeat in Pine and count in Lipi, which matters for named arguments.",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_str.repeat",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "str.repeat",
      "language": "thinkscript",
      "source": "absent",
      "note": "No text repeat function in the reference.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Functions/Others",
        "fragment": "Others function list (no repeat entry)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "str.match",
      "language": "mql4",
      "source": "absent",
      "note": "No regular-expression function in the string group; search with StringFind and cut with StringSubstr.",
      "evidence": {
        "url": "https://docs.mql4.com/strings",
        "fragment": "String Functions table (StringAdd ... StringSetChar)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "str.match",
      "language": "mql5",
      "source": "absent",
      "note": "The string function list has no regular-expression function; pattern matching needs manual string handling.",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/strings",
        "fragment": "String Functions index (StringAdd ... StringTrimRight)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "str.match",
      "language": "ninjascript",
      "source": "present",
      "construct": "Regex.Match(input, pattern)",
      "signature": "Match Regex.Match(string input, string pattern)",
      "relation": "equivalent_with_caveat",
      "note": "Returns the first match as a Match object, not a string; read its Value property. Pattern syntax is .NET regex, not RE2.",
      "evidence": {
        "url": "https://learn.microsoft.com/en-us/dotnet/api/system.text.regularexpressions.regex.match",
        "fragment": "Regex.Match: returns the first occurrence as a single Match object",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "str.match",
      "language": "pine",
      "source": "present",
      "construct": "str.match",
      "signature": "str.match(source, regex) → string",
      "relation": "equivalent_with_caveat",
      "note": "Parameter is regex in Pine, pattern in Lipi. Lipi patterns use RE2 (no lookaround or backreferences); Pine's reference names no dialect.",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_str.match",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "str.match",
      "language": "thinkscript",
      "source": "absent",
      "note": "No regular-expression or pattern matching function in the reference.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Functions/Others",
        "fragment": "Others function list (no match entry)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "str.concat",
      "language": "mql4",
      "source": "present",
      "construct": "+ operator, StringConcatenate",
      "signature": "string StringConcatenate(void argument1, void argument2, ...)",
      "relation": "equivalent_with_caveat",
      "note": "In MQL4 + joins a string and a number by converting the number; Lipi needs str.tostring first. StringConcatenate joins many values in one call.",
      "evidence": {
        "url": "https://docs.mql4.com/strings/stringconcatenate",
        "fragment": "StringConcatenate example comment (text = a + b)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "str.concat",
      "language": "mql5",
      "source": "present",
      "construct": "+",
      "relation": "equivalent_with_caveat",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/strings/stringadd",
        "fragment": "StringAdd example comparing c=a+b, StringAdd(a,b) and StringConcatenate",
        "accessed": "2026-11-01"
      },
      "verified": "documented",
      "note": "MQL5 casts the non-string operand of + to string automatically; Lipi rejects string + number, so numbers must be wrapped in str.tostring."
    },
    {
      "concept": "str.concat",
      "language": "ninjascript",
      "source": "present",
      "construct": "+",
      "signature": "string + string",
      "relation": "equivalent_with_caveat",
      "evidence": {
        "url": "https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/addition-operator",
        "fragment": "string-concatenation",
        "accessed": "2026-11-01"
      },
      "verified": "documented",
      "note": "C# + converts a non-text operand to text; Lipi's + joins text only, so wrap numbers in str.tostring."
    },
    {
      "concept": "str.concat",
      "language": "pine",
      "source": "present",
      "construct": "+",
      "signature": "expr1 + expr2",
      "relation": "exact",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "op_+",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "str.concat",
      "language": "thinkscript",
      "source": "present",
      "construct": "+, Concat",
      "signature": "Concat(Any value1, Any value2)",
      "relation": "equivalent_with_caveat",
      "note": "Concat joins exactly two values, so nest calls for more; + does the same inline. Non-text values are converted first, doubles with 4 decimals.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Functions/Others/Concat",
        "fragment": "Concat ( Any value1 , Any value2 ); note on the + sign",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "array.create",
      "language": "mql4",
      "source": "present",
      "construct": "type name[n] declaration, ArrayResize, ArrayInitialize",
      "signature": "int ArrayResize(void& array[], int new_size, int reserve_size=0); int ArrayInitialize(double array[], double value)",
      "relation": "equivalent_with_caveat",
      "note": "Fixed size at declaration, or a dynamic array sized with ArrayResize; fill values with ArrayInitialize. No from-values constructor.",
      "differences": [
        {
          "axis": "state_and_side_effects",
          "note": "elements added by ArrayResize hold undefined values until you set them."
        }
      ],
      "evidence": {
        "url": "https://docs.mql4.com/array/arrayinitialize",
        "fragment": "ArrayInitialize",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "array.create",
      "language": "mql5",
      "source": "present",
      "construct": "ArrayResize, ArrayInitialize",
      "signature": "int ArrayResize(void& array[], int new_size, int reserve_size=0)",
      "relation": "equivalent_with_caveat",
      "note": "Declare a dynamic array, size it with ArrayResize, then fill with ArrayInitialize. A brace list initialises a fixed array. New elements are undefined until set.",
      "differences": [
        {
          "axis": "state_and_side_effects",
          "note": "Elements added by ArrayResize are not initialised to any value."
        }
      ],
      "evidence": {
        "url": "https://www.mql5.com/en/docs/array/arrayinitialize",
        "fragment": "Note: elements added by ArrayResize have undefined values",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "array.create",
      "language": "ninjascript",
      "source": "present",
      "construct": "new List<double>()",
      "signature": "new List<double>(int capacity)",
      "relation": "equivalent_with_caveat",
      "note": "A List<T> grows like a Lipi array. new List<double>(n) only sets capacity: add n items to reach that length. C# arrays are fixed length.",
      "evidence": {
        "url": "https://learn.microsoft.com/en-us/dotnet/api/system.collections.generic.list-1",
        "fragment": "Properties: Capacity gets or sets the number of elements the internal data structure can hold without resizing",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "array.create",
      "language": "pine",
      "source": "present",
      "construct": "array.new<type>, array.from, array.new_float, array.new_int",
      "signature": "array.new<type>(size, initial_value) → array<type>; array.from(arg0, arg1, ...) → array<type>; array.new_float(size, initial_value); array.new_int(size, initial_value)",
      "relation": "equivalent_with_caveat",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_array.new%3Ctype%3E (also #fun_array.from, #fun_array.new_float, #fun_array.new_int)",
        "accessed": "2026-11-01"
      },
      "verified": "documented",
      "note": "Lipi caps arrays at 10000 elements versus Pine's 100000; array.new<bool>(n) holds na in Lipi."
    },
    {
      "concept": "array.create",
      "language": "thinkscript",
      "source": "absent",
      "note": "No script-created array. IDataHolder is the built-in series type (close, volume); rolling windows come from functions and fold.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Data-Types/IDataHolder",
        "fragment": "IDataHolder: an array of data such as close or volume",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "array.object-arrays",
      "language": "mql4",
      "source": "absent",
      "note": "Objects are named, not handles: ObjectCreate takes an object_name string, so keep an array of names.",
      "evidence": {
        "url": "https://docs.mql4.com/objects/objectcreate",
        "fragment": "ObjectCreate object_name parameter",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "array.object-arrays",
      "language": "mql5",
      "source": "present",
      "construct": "string[] of object names with ObjectCreate",
      "relation": "equivalent_with_caveat",
      "note": "Chart objects are addressed by a name string, unique per chart. Keep the names in a string array; there are no object id handles.",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/objects",
        "fragment": "Every graphical object should have a name unique within one chart",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "array.object-arrays",
      "language": "ninjascript",
      "source": "present",
      "construct": "List<IDrawingTool> (a typed list of draw objects)",
      "signature": "void Add(T item)",
      "relation": "equivalent_with_caveat",
      "note": "Draw.* methods return draw objects you can add to a List<T>; entries are added as created, not preallocated with an initial value.",
      "evidence": {
        "url": "https://learn.microsoft.com/en-us/dotnet/api/system.collections.generic.list-1",
        "fragment": "Methods: Add(T) adds an object to the end of the List<T>",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "array.object-arrays",
      "language": "pine",
      "source": "present",
      "construct": "array.new_line, array.new_label, array.new_box",
      "signature": "array.new_line(size, initial_value) → array<line>; same shape for new_label and new_box",
      "relation": "exact",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_array.new_line (also #fun_array.new_label, #fun_array.new_box)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "array.object-arrays",
      "language": "thinkscript",
      "source": "absent",
      "note": "No arrays and no line, label or box objects to hold in them.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Data-Types/IDataHolder",
        "fragment": "IDataHolder: an array of data such as close or volume",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "array.get-set",
      "language": "mql4",
      "source": "present",
      "construct": "array[index]",
      "relation": "equivalent_with_caveat",
      "note": "Index operator, zero-based; an out-of-range access stops the program. A series-flagged array reverses the index direction.",
      "differences": [
        {
          "axis": "history_indexing",
          "note": "ArraySetAsSeries makes index 0 the newest element; plain arrays count from the first."
        }
      ],
      "evidence": {
        "url": "https://docs.mql4.com/basis/variables",
        "fragment": "Array section: numbering starts with 0; out of range stops the program",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "array.get-set",
      "language": "mql5",
      "source": "present",
      "construct": "array[index]",
      "relation": "equivalent_with_caveat",
      "note": "Plain bracket indexing, 0-based; an out-of-range index stops the program. ArraySetAsSeries can flip direction so index 0 is the newest element.",
      "differences": [
        {
          "axis": "history_indexing",
          "note": "With the as-series flag set, index 0 is the newest element; Lipi arrays always start at the first element."
        }
      ],
      "evidence": {
        "url": "https://www.mql5.com/en/docs/basis/variables",
        "fragment": "Numbering of array elements starts with 0; access out of range stops the program",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "array.get-set",
      "language": "ninjascript",
      "source": "present",
      "construct": "list[index] (List<T> indexer)",
      "signature": "T this[int index] { get; set; }",
      "relation": "equivalent_with_caveat",
      "note": "Index syntax instead of array.get and array.set; zero-based as in Lipi. Out-of-range access throws an exception.",
      "evidence": {
        "url": "https://learn.microsoft.com/en-us/dotnet/api/system.collections.generic.list-1",
        "fragment": "Properties: Item[Int32] gets or sets the element at the specified index",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "array.get-set",
      "language": "pine",
      "source": "present",
      "construct": "array.get, array.set",
      "signature": "array.get(id, index) → element; array.set(id, index, value) → void",
      "relation": "different_semantics",
      "note": "Pine accepts negative indexes counting from the end (-1 is the last element). Lipi stops the script on any index outside 0 to length-1.",
      "differences": [
        {
          "axis": "history_indexing",
          "note": "array.get(a, -1) is the last element in Pine and a runtime error in Lipi."
        }
      ],
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_array.get (Remarks on negative index; also #fun_array.set)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "array.get-set",
      "language": "thinkscript",
      "source": "absent",
      "note": "No element read or write on a user array. Past bars of a series are read with [n] indexing or getValue inside fold.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Reserved-Words/fold",
        "fragment": "fold Example 2: getValue(price, n, length - 1)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "array.size",
      "language": "mql4",
      "source": "present",
      "construct": "ArraySize",
      "signature": "int ArraySize(const void& array[])",
      "relation": "exact",
      "evidence": {
        "url": "https://docs.mql4.com/array/arraysize",
        "fragment": "ArraySize",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "array.size",
      "language": "mql5",
      "source": "present",
      "construct": "ArraySize",
      "signature": "int ArraySize(const void& array[])",
      "relation": "exact",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/array/arraysize",
        "fragment": "ArraySize Return Value (int)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "array.size",
      "language": "ninjascript",
      "source": "present",
      "construct": "List<T>.Count (C# arrays: Length)",
      "signature": "int Count { get; }",
      "relation": "equivalent_with_caveat",
      "note": "A property, not a function call. A fixed-length C# array uses Length instead of Count.",
      "evidence": {
        "url": "https://learn.microsoft.com/en-us/dotnet/api/system.collections.generic.list-1",
        "fragment": "Properties: Count gets the number of elements contained in the List<T>",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "array.size",
      "language": "pine",
      "source": "present",
      "construct": "array.size",
      "signature": "array.size(id) → series int",
      "relation": "equivalent_with_caveat",
      "note": "Lipi has no array.size or a.size; use array.length(a) or a.length.",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_array.size",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "array.size",
      "language": "thinkscript",
      "source": "absent",
      "note": "No array length function; there are no user arrays.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Data-Types/IDataHolder",
        "fragment": "IDataHolder: an array of data such as close or volume",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "array.push-pop",
      "language": "mql4",
      "source": "absent",
      "note": "No append or pop; grow with ArrayResize(array, n+1) and assign the last slot, read it and shrink to pop.",
      "evidence": {
        "url": "https://docs.mql4.com/array",
        "fragment": "Array Functions table (ArrayBsearch ... ArrayDimension)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "array.push-pop",
      "language": "mql5",
      "source": "present",
      "construct": "ArrayResize",
      "signature": "int ArrayResize(void& array[], int new_size, int reserve_size=0)",
      "relation": "equivalent_with_caveat",
      "note": "No push or pop: grow with ArrayResize and assign the last slot. To pop, read the last element, then shrink the array.",
      "differences": [
        {
          "axis": "state_and_side_effects",
          "note": "A reserve_size argument avoids repeated reallocation; static arrays and indicator buffers cannot be resized."
        }
      ],
      "evidence": {
        "url": "https://www.mql5.com/en/docs/array/arrayresize",
        "fragment": "ArrayResize new_size, reserve_size and notes",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "array.push-pop",
      "language": "ninjascript",
      "source": "present",
      "construct": "List<T>.Add() with RemoveAt(Count - 1)",
      "signature": "void Add(T item); void RemoveAt(int index)",
      "relation": "equivalent_with_caveat",
      "note": "Add appends like push. List<T> has no Pop: read the last element, then call RemoveAt(Count - 1).",
      "evidence": {
        "url": "https://learn.microsoft.com/en-us/dotnet/api/system.collections.generic.list-1",
        "fragment": "Methods: Add(T); RemoveAt(Int32) removes the element at the specified index",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "array.push-pop",
      "language": "pine",
      "source": "present",
      "construct": "array.push, array.pop",
      "signature": "array.push(id, value) → void; array.pop(id) → element",
      "relation": "equivalent_with_caveat",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_array.push (also #fun_array.pop)",
        "accessed": "2026-11-01"
      },
      "verified": "documented",
      "note": "Pushing past 10000 elements stops a Lipi script; Pine allows 100000."
    },
    {
      "concept": "array.push-pop",
      "language": "thinkscript",
      "source": "absent",
      "note": "No append or remove operations; a series cannot be grown or shrunk by script.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Data-Types/IDataHolder",
        "fragment": "IDataHolder: an array of data such as close or volume",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "array.shift-unshift",
      "language": "mql4",
      "source": "absent",
      "note": "No front insert or removal; ArrayCopy moves ranges, but copying an array onto itself is documented as undefined.",
      "evidence": {
        "url": "https://docs.mql4.com/array/arraycopy",
        "fragment": "ArrayCopy Note: if an array is copied to itself, the result is undefined",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "array.shift-unshift",
      "language": "mql5",
      "source": "present",
      "construct": "ArrayRemove, ArrayInsert",
      "signature": "bool ArrayRemove(void& array[], uint start, uint count=WHOLE_ARRAY)",
      "relation": "equivalent_with_caveat",
      "note": "Remove index 0 with a count of 1; it returns a bool, not the element. ArrayInsert takes elements from a source array, not one value.",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/array/arrayremove",
        "fragment": "ArrayRemove start, count, Return Value bool",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "array.shift-unshift",
      "language": "ninjascript",
      "source": "present",
      "construct": "List<T>.Insert(0, value) and RemoveAt(0)",
      "signature": "void Insert(int index, T item)",
      "relation": "equivalent_with_caveat",
      "note": "Insert(0, value) matches unshift. List<T> has no Shift: read item 0, then RemoveAt(0). Both move every later element.",
      "evidence": {
        "url": "https://learn.microsoft.com/en-us/dotnet/api/system.collections.generic.list-1",
        "fragment": "Methods: Insert(Int32, T) inserts an element into the List<T> at the specified index",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "array.shift-unshift",
      "language": "pine",
      "source": "present",
      "construct": "array.unshift, array.shift",
      "signature": "array.unshift(id, value) → void; array.shift(id) → element",
      "relation": "equivalent_with_caveat",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_array.unshift (also #fun_array.shift)",
        "accessed": "2026-11-01"
      },
      "verified": "documented",
      "note": "Unshifting past 10000 elements stops a Lipi script; Pine allows 100000."
    },
    {
      "concept": "array.shift-unshift",
      "language": "thinkscript",
      "source": "absent",
      "note": "No insert or remove at the start of a collection.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Data-Types/IDataHolder",
        "fragment": "IDataHolder: an array of data such as close or volume",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "array.insert-remove",
      "language": "mql4",
      "source": "absent",
      "note": "No insert or remove at a position; rebuild with ArrayCopy into a second array and ArrayResize.",
      "evidence": {
        "url": "https://docs.mql4.com/array",
        "fragment": "Array Functions table (ArrayBsearch ... ArrayDimension)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "array.insert-remove",
      "language": "mql5",
      "source": "present",
      "construct": "ArrayInsert, ArrayRemove",
      "signature": "bool ArrayInsert(void& dst_array[], const void& src_array[], uint dst_start, uint src_start=0, uint count=WHOLE_ARRAY)",
      "relation": "equivalent_with_caveat",
      "note": "Insert copies elements from a source array at a destination index; remove takes a start and a count. Both return bool.",
      "differences": [
        {
          "axis": "state_and_side_effects",
          "note": "On a fixed-size receiving array, the array's own size does not change."
        }
      ],
      "evidence": {
        "url": "https://www.mql5.com/en/docs/array/arrayinsert",
        "fragment": "ArrayInsert parameters and Note on fixed-size arrays",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "array.insert-remove",
      "language": "ninjascript",
      "source": "present",
      "construct": "List<T>.Insert() and RemoveAt()",
      "signature": "void Insert(int index, T item); void RemoveAt(int index)",
      "relation": "equivalent_with_caveat",
      "note": "Same effect as inserting and removing at an index; both are methods on the list. RemoveAt returns nothing, as array.remove does.",
      "evidence": {
        "url": "https://learn.microsoft.com/en-us/dotnet/api/system.collections.generic.list-1",
        "fragment": "Methods: Insert(Int32, T); RemoveAt(Int32)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "array.insert-remove",
      "language": "pine",
      "source": "present",
      "construct": "array.insert, array.remove",
      "signature": "array.insert(id, index, value) → void; array.remove(id, index) → element",
      "relation": "equivalent_with_caveat",
      "note": "Pine's array.remove returns the removed value; Lipi's returns nothing. Pine accepts negative indexes for both; Lipi errors outside 0 to length-1.",
      "differences": [
        {
          "axis": "history_indexing",
          "note": "A negative index counts from the end in Pine and stops the script in Lipi."
        }
      ],
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_array.remove (also #fun_array.insert)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "array.insert-remove",
      "language": "thinkscript",
      "source": "absent",
      "note": "No positional insert or remove on any collection.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Data-Types/IDataHolder",
        "fragment": "IDataHolder: an array of data such as close or volume",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "array.clear-fill",
      "language": "mql4",
      "source": "present",
      "construct": "ArrayFree, ArrayInitialize, ArrayFill",
      "signature": "void ArrayFree(void& array[]); void ArrayFill(void& array[], int start, int count, void value)",
      "relation": "equivalent_with_caveat",
      "note": "ArrayFree empties dynamic arrays only; ArrayFill takes a start and a count, not an end index; ArrayInitialize sets every element.",
      "differences": [
        {
          "axis": "history_indexing",
          "note": "ArrayFill always runs left to right and ignores the series-direction flag."
        }
      ],
      "evidence": {
        "url": "https://docs.mql4.com/array/arrayfill",
        "fragment": "ArrayFill; ArrayFree; ArrayInitialize",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "array.clear-fill",
      "language": "mql5",
      "source": "present",
      "construct": "ArrayFree, ArrayFill, ArrayInitialize",
      "signature": "void ArrayFill(void& array[], int start, int count, void value)",
      "relation": "equivalent_with_caveat",
      "note": "ArrayFree empties a dynamic array. ArrayFill takes a start and a count, not an end index, and ignores the as-series direction.",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/array/arrayfill",
        "fragment": "ArrayFill start, count and note on indexing direction",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "array.clear-fill",
      "language": "ninjascript",
      "source": "present",
      "construct": "List<T>.Clear()",
      "signature": "void Clear()",
      "relation": "equivalent_with_caveat",
      "note": "Clear() empties the list. List<T> has no fill method; assign each index in a loop.",
      "evidence": {
        "url": "https://learn.microsoft.com/en-us/dotnet/api/system.collections.generic.list-1",
        "fragment": "Methods: Clear() removes all elements from the List<T>",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "array.clear-fill",
      "language": "pine",
      "source": "present",
      "construct": "array.clear, array.fill",
      "signature": "array.clear(id) → void; array.fill(id, value, index_from, index_to) → void",
      "relation": "exact",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_array.clear (also #fun_array.fill)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "array.clear-fill",
      "language": "thinkscript",
      "source": "absent",
      "note": "No clear or fill; a number passed as IDataHolder is read as a series of that constant.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Data-Types/Data-Conversion",
        "fragment": "table row: IDataHolder accepts number as array of equal elements",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "array.first-last",
      "language": "mql4",
      "source": "absent",
      "note": "No first or last helper; read array[0] and array[ArraySize(array)-1].",
      "evidence": {
        "url": "https://docs.mql4.com/array",
        "fragment": "Array Functions table (ArrayBsearch ... ArrayDimension)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "array.first-last",
      "language": "mql5",
      "source": "absent",
      "note": "No dedicated functions; use index 0 and ArraySize minus 1, which swap meaning when the array is as-series.",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/array",
        "fragment": "Array Functions index (no first or last entry)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "array.first-last",
      "language": "ninjascript",
      "source": "present",
      "construct": "list[0] and list[list.Count - 1]",
      "signature": "T this[int index] { get; set; }",
      "relation": "equivalent_with_caveat",
      "note": "No First or Last property on List<T>: index the ends directly. LINQ First() and Last() also exist.",
      "evidence": {
        "url": "https://learn.microsoft.com/en-us/dotnet/api/system.collections.generic.list-1",
        "fragment": "Properties: Item[Int32]; Count",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "array.first-last",
      "language": "pine",
      "source": "present",
      "construct": "array.first, array.last",
      "signature": "array.first(id) → element; array.last(id) → element",
      "relation": "exact",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_array.first (also #fun_array.last)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "array.first-last",
      "language": "thinkscript",
      "source": "absent",
      "note": "No first or last element accessor on user arrays; there are none.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Data-Types/IDataHolder",
        "fragment": "IDataHolder: an array of data such as close or volume",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "array.search",
      "language": "mql4",
      "source": "present",
      "construct": "ArrayBsearch",
      "signature": "int ArrayBsearch(const double& array[], double value, int count=WHOLE_ARRAY, int start=0, int direction=MODE_ASCEND)",
      "relation": "different_semantics",
      "note": "Needs a sorted numeric array and, when the value is missing, returns the index of the nearest element, not -1 or false.",
      "evidence": {
        "url": "https://docs.mql4.com/array/arraybsearch",
        "fragment": "ArrayBsearch Return Value",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "array.search",
      "language": "mql5",
      "source": "present",
      "construct": "ArrayBsearch",
      "signature": "int ArrayBsearch(const double& array[], double value)",
      "relation": "different_semantics",
      "note": "Needs a sorted array and returns the nearest element's index when the value is absent, not -1. No includes or indexof function exists.",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/array/arraybsearch",
        "fragment": "ArrayBsearch Return Value: index of nearest element if not found",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "array.search",
      "language": "ninjascript",
      "source": "present",
      "construct": "List<T>.Contains(), IndexOf(), LastIndexOf(), BinarySearch()",
      "signature": "bool Contains(T item); int IndexOf(T item); int LastIndexOf(T item); int BinarySearch(T item)",
      "relation": "equivalent_with_caveat",
      "note": "Same job with close names. BinarySearch needs a sorted list.",
      "evidence": {
        "url": "https://learn.microsoft.com/en-us/dotnet/api/system.collections.generic.list-1",
        "fragment": "Methods: Contains(T); IndexOf(T); LastIndexOf(T); BinarySearch(T) searches the entire sorted List<T>",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "array.search",
      "language": "pine",
      "source": "present",
      "construct": "array.includes, array.indexof, array.lastindexof, array.binary_search",
      "signature": "array.includes(id, value) → bool; array.indexof(id, value) → int; array.lastindexof(id, value) → int; array.binary_search(id, val) → int",
      "relation": "equivalent_with_caveat",
      "note": "Same results, -1 when missing. Pine's binary_search target is named val (Lipi value) and has an extra sort_field overload for arrays of user types.",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_array.includes (also #fun_array.indexof, #fun_array.lastindexof, #fun_array.binary_search)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "array.search",
      "language": "thinkscript",
      "source": "absent",
      "note": "No element search on collections. Highest, Lowest and GetMaxValueOffset locate extremes in a bar window only.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Data-Types/IDataHolder",
        "fragment": "IDataHolder: an array of data such as close or volume",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "array.copy-slice",
      "language": "mql4",
      "source": "present",
      "construct": "ArrayCopy",
      "signature": "int ArrayCopy(void& dst_array[], const void& src_array[], int dst_start=0, int src_start=0, int count=WHOLE_ARRAY)",
      "relation": "equivalent_with_caveat",
      "note": "Copies into an existing destination (grown as needed) and returns the copied count; slice by src_start and count, concat by dst_start.",
      "differences": [
        {
          "axis": "history_indexing",
          "note": "copying runs left to right; series arrays have their start position adjusted for that."
        },
        {
          "axis": "state_and_side_effects",
          "note": "writes into the destination array; does not return a new array."
        }
      ],
      "evidence": {
        "url": "https://docs.mql4.com/array/arraycopy",
        "fragment": "ArrayCopy",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "array.copy-slice",
      "language": "mql5",
      "source": "present",
      "construct": "ArrayCopy",
      "signature": "int ArrayCopy(void& dst_array[], const void& src_array[], int dst_start=0, int src_start=0, int count=WHOLE_ARRAY)",
      "relation": "equivalent_with_caveat",
      "note": "Copies a range into an existing destination and returns the count copied. A slice is a partial copy; concat copies at a destination offset.",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/array/arraycopy",
        "fragment": "ArrayCopy parameters dst_start, src_start, count",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "array.copy-slice",
      "language": "ninjascript",
      "source": "present",
      "construct": "List<T>.GetRange() and AddRange()",
      "signature": "List<T> GetRange(int index, int count); void AddRange(IEnumerable<T> collection)",
      "relation": "equivalent_with_caveat",
      "note": "GetRange(index, count) copies a range given a start and a count; AddRange appends another collection.",
      "evidence": {
        "url": "https://learn.microsoft.com/en-us/dotnet/api/system.collections.generic.list-1",
        "fragment": "Methods: GetRange(Int32, Int32) creates a shallow copy of a range of elements; AddRange(IEnumerable<T>)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "array.copy-slice",
      "language": "pine",
      "source": "present",
      "construct": "array.copy, array.slice, array.concat",
      "signature": "array.copy(id) → array; array.slice(id, index_from, index_to) → array; array.concat(id1, id2) → array",
      "relation": "equivalent_with_caveat",
      "note": "Both slices are live views of the original. Pine says insertions and removals in a slice change the original; Lipi says adding may detach storage.",
      "differences": [
        {
          "axis": "state_and_side_effects",
          "note": "Growing a slice keeps writing through to the original in Pine; in Lipi it may separate from the original."
        }
      ],
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_array.slice (also #fun_array.copy, #fun_array.concat)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "array.copy-slice",
      "language": "thinkscript",
      "source": "absent",
      "note": "No copy, slice or concatenate operations on collections.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Data-Types/IDataHolder",
        "fragment": "IDataHolder: an array of data such as close or volume",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "array.sort",
      "language": "mql4",
      "source": "present",
      "construct": "ArraySort",
      "signature": "bool ArraySort(void& array[], int count=WHOLE_ARRAY, int start=0, int direction=MODE_ASCEND)",
      "relation": "equivalent_with_caveat",
      "note": "Numeric arrays only, sorted in place, returning a bool. No sort_indices or reverse function.",
      "differences": [
        {
          "axis": "history_indexing",
          "note": "the series-direction flag is taken into account when sorting."
        }
      ],
      "evidence": {
        "url": "https://docs.mql4.com/array/arraysort",
        "fragment": "ArraySort",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "array.sort",
      "language": "mql5",
      "source": "present",
      "construct": "ArraySort, ArrayReverse",
      "signature": "bool ArraySort(void& array[])",
      "relation": "equivalent_with_caveat",
      "note": "Ascending only, in place, ignoring the as-series flag. Sort descending with ArraySort then ArrayReverse. No index-sorting function.",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/array/arraysort",
        "fragment": "ArraySort: always ascending irrespective of AS_SERIES",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "array.sort",
      "language": "ninjascript",
      "source": "present",
      "construct": "List<T>.Sort() and Reverse()",
      "signature": "void Sort(); void Reverse()",
      "relation": "equivalent_with_caveat",
      "note": "Sort() and Reverse() work in place, as array.sort and array.reverse do. There is no equivalent of sort_indices.",
      "evidence": {
        "url": "https://learn.microsoft.com/en-us/dotnet/api/system.collections.generic.list-1",
        "fragment": "Methods: Sort() sorts the elements in the entire List<T> using the default comparer; Reverse()",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "array.sort",
      "language": "pine",
      "source": "present",
      "construct": "array.sort, array.sort_indices, array.reverse",
      "signature": "array.sort(id, order) → void; array.sort_indices(id, order) → array<int>; array.reverse(id) → void",
      "relation": "equivalent_with_caveat",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_array.sort (also #fun_array.sort_indices, #fun_array.reverse)",
        "accessed": "2026-11-01"
      },
      "verified": "documented",
      "note": "Pine array.sort and sort_indices have a sort_field overload for arrays of objects; Lipi takes only id and order."
    },
    {
      "concept": "array.sort",
      "language": "thinkscript",
      "source": "absent",
      "note": "No sort or reverse function; Median sorts internally over a window but exposes only the middle value.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Functions/Tech-Analysis/Median",
        "fragment": "Median ( IDataHolder data , int length )",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "array.stats",
      "language": "mql4",
      "source": "present",
      "construct": "ArrayMaximum, ArrayMinimum",
      "signature": "int ArrayMaximum(const void& array[], int count=WHOLE_ARRAY, int start=0)",
      "relation": "different_semantics",
      "note": "Return the index of the extreme element, not its value. Sum, average, median, deviation and variance have no array functions.",
      "evidence": {
        "url": "https://docs.mql4.com/array/arraymaximum",
        "fragment": "ArrayMaximum Return Value; ArrayMinimum",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "array.stats",
      "language": "mql5",
      "source": "present",
      "construct": "ArrayMaximum, ArrayMinimum, MathMean, MathMedian, MathStandardDeviation, MathVariance",
      "signature": "int ArrayMaximum(const void& array[], int start=0, int count=WHOLE_ARRAY)",
      "relation": "different_semantics",
      "note": "ArrayMaximum and ArrayMinimum return an index, not the value. Mean, median, deviation and variance are separate Math functions; there is no array sum.",
      "differences": [
        {
          "axis": "history_indexing",
          "note": "The returned index honours the as-series flag of the array."
        }
      ],
      "evidence": {
        "url": "https://www.mql5.com/en/docs/array/arraymaximum",
        "fragment": "ArrayMaximum Return value: index of a found element",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "array.stats",
      "language": "ninjascript",
      "source": "present",
      "construct": "Enumerable.Sum(), Average(), Min(), Max() (System.Linq)",
      "signature": "double Sum(this IEnumerable<double> source)",
      "relation": "equivalent_with_caveat",
      "note": "LINQ covers sum, average, min and max. Median, standard deviation and variance are not in LINQ; compute them by hand. Needs using System.Linq.",
      "evidence": {
        "url": "https://learn.microsoft.com/en-us/dotnet/api/system.linq.enumerable",
        "fragment": "Methods: Sum(IEnumerable<Double>), Average(IEnumerable<Double>), Min(IEnumerable<Double>), Max(IEnumerable<Double>)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "array.stats",
      "language": "pine",
      "source": "present",
      "construct": "array.sum, array.avg, array.min, array.max, array.median, array.stdev, array.variance",
      "signature": "array.sum(id); array.avg(id); array.min(id, nth); array.max(id, nth); array.median(id); array.stdev(id, biased); array.variance(id, biased)",
      "relation": "equivalent_with_caveat",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_array.sum (also #fun_array.avg, #fun_array.min, #fun_array.max, #fun_array.median, #fun_array.stdev, #fun_array.variance)",
        "accessed": "2026-11-01"
      },
      "verified": "documented",
      "note": "For int arrays Pine's avg, median, stdev and variance return int; Lipi's return float."
    },
    {
      "concept": "array.stats",
      "language": "thinkscript",
      "source": "absent",
      "note": "No statistics on user arrays. Rolling statistics over bars come from Sum, Average, Highest, Lowest, Median and StDev.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Data-Types/IDataHolder",
        "fragment": "IDataHolder: an array of data such as close or volume",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "array.join",
      "language": "mql4",
      "source": "absent",
      "note": "No array-to-text function; loop over the elements and append with StringConcatenate or +.",
      "evidence": {
        "url": "https://docs.mql4.com/array",
        "fragment": "Array Functions table (ArrayBsearch ... ArrayDimension)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "array.join",
      "language": "mql5",
      "source": "absent",
      "note": "No join function; build the text in a loop with StringConcatenate or StringAdd.",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/function_indices",
        "fragment": "List of MQL5 Functions (no Join entry)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "array.join",
      "language": "ninjascript",
      "source": "present",
      "construct": "string.Join(separator, list)",
      "signature": "string Join(string separator, IEnumerable<string> values)",
      "relation": "equivalent_with_caveat",
      "note": "A static string method: separator first, then the collection of elements to join.",
      "evidence": {
        "url": "https://learn.microsoft.com/en-us/dotnet/api/system.string.join",
        "fragment": "String.Join: concatenates the elements of a specified array or the members of a collection, using the specified separator",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "array.join",
      "language": "pine",
      "source": "present",
      "construct": "array.join",
      "signature": "array.join(id, separator) → string",
      "relation": "exact",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_array.join",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "array.join",
      "language": "thinkscript",
      "source": "absent",
      "note": "No array-to-text function; there are no user arrays.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Data-Types/IDataHolder",
        "fragment": "IDataHolder: an array of data such as close or volume",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "array.every-some",
      "language": "mql4",
      "source": "absent",
      "note": "No all-or-any test over elements; loop and test each one.",
      "evidence": {
        "url": "https://docs.mql4.com/array",
        "fragment": "Array Functions table (ArrayBsearch ... ArrayDimension)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "array.every-some",
      "language": "mql5",
      "source": "absent",
      "note": "No all-true or any-true function in the array list; loop over the elements.",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/array",
        "fragment": "Array Functions index (ArrayBsearch ... ArrayFromFP8)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "array.every-some",
      "language": "ninjascript",
      "source": "present",
      "construct": "Enumerable.All() and Any() (System.Linq)",
      "signature": "bool All<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate)",
      "relation": "equivalent_with_caveat",
      "note": "LINQ All and Any take a condition function, so pass x => x for a list of bools. Needs using System.Linq.",
      "evidence": {
        "url": "https://learn.microsoft.com/en-us/dotnet/api/system.linq.enumerable",
        "fragment": "Methods: All<TSource> determines whether all elements of a sequence satisfy a condition; Any<TSource>",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "array.every-some",
      "language": "pine",
      "source": "present",
      "construct": "array.every, array.some",
      "signature": "array.every(id) → bool; array.some(id) → bool",
      "relation": "exact",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_array.every (also #fun_array.some)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "array.every-some",
      "language": "thinkscript",
      "source": "absent",
      "note": "No all/any test on collections. A fold loop with a while condition can scan a bar window.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Reserved-Words/fold",
        "fragment": "fold syntax: with ... while <condition> do",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.alma",
      "language": "mql4",
      "source": "absent",
      "note": "No Arnaud Legoux average among the indicator functions; code the weights by hand.",
      "evidence": {
        "url": "https://docs.mql4.com/indicators",
        "fragment": "Technical Indicator Functions table (iAC ... iWPR)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.alma",
      "language": "mql5",
      "source": "absent",
      "note": "No ALMA among the built-in indicators; a custom indicator loaded through iCustom would have to supply it.",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/indicators",
        "fragment": "table of technical indicator functions (iAC ... iVolumes)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.alma",
      "language": "ninjascript",
      "source": "absent",
      "note": "No ALMA in NinjaTrader's system indicator list; weights must be coded by hand.",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/indicators.htm",
        "fragment": "System Indicator Methods index: no ALMA entry",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.alma",
      "language": "pine",
      "source": "present",
      "construct": "ta.alma",
      "signature": "ta.alma(series, length, offset, sigma, floor) → series float",
      "relation": "equivalent_with_caveat",
      "note": "Pine adds an optional floor flag (default false) that floors the offset calculation; Lipi's ta.alma has no floor argument.",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_ta.alma",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.alma",
      "language": "thinkscript",
      "source": "absent",
      "note": "No ALMA function or study in the functions list or the study library.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/Tech-Indicators/studies-library",
        "fragment": "study library index (no ALMA entry)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.atr",
      "language": "mql4",
      "source": "present",
      "construct": "iATR",
      "signature": "double iATR(string symbol, int timeframe, int period, int shift)",
      "relation": "equivalent_with_caveat",
      "note": "Called with symbol, timeframe, period and shift; returns the value at that shift, not the current bar's.",
      "differences": [
        {
          "axis": "history_indexing",
          "note": "shift counts bars back from the current bar; shift 0 is the still-forming bar, and any shift can be read in one call."
        },
        {
          "axis": "htf_access",
          "note": "symbol and timeframe arguments read another symbol or period directly; Lipi ta calls use the chart's own bars."
        }
      ],
      "evidence": {
        "url": "https://docs.mql4.com/indicators/iatr",
        "fragment": "iATR",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.atr",
      "language": "mql5",
      "source": "present",
      "construct": "iATR",
      "signature": "int iATR(string symbol, ENUM_TIMEFRAMES period, int ma_period)",
      "relation": "equivalent_with_caveat",
      "note": "Returns a handle, one buffer. Symbol and timeframe are arguments; the smoothing method is not stated on the page.",
      "differences": [
        {
          "axis": "state_and_side_effects",
          "note": "Returns a handle; values are read later with CopyBuffer and are not ready right after creation."
        },
        {
          "axis": "history_indexing",
          "note": "CopyBuffer start_pos 0 is the current bar and counts toward the past; copied data lands oldest-first."
        },
        {
          "axis": "htf_access",
          "note": "Symbol and timeframe are explicit arguments, so another symbol or timeframe is requested directly."
        }
      ],
      "evidence": {
        "url": "https://www.mql5.com/en/docs/indicators/iatr",
        "fragment": "iATR signature and Return Value (handle)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.atr",
      "language": "ninjascript",
      "source": "present",
      "construct": "ATR",
      "signature": "ATR(ISeries<double> input, int period)[int barsAgo]",
      "relation": "exact",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/average_true_range_atr.htm",
        "fragment": "Syntax: ATR(int period); Wilder smoothing k = 1/period",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.atr",
      "language": "pine",
      "source": "present",
      "construct": "ta.atr",
      "signature": "ta.atr(length) → series float",
      "relation": "exact",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_ta.atr",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.atr",
      "language": "thinkscript",
      "source": "present",
      "construct": "ATR",
      "signature": "ATR(length, average type)",
      "relation": "equivalent_with_caveat",
      "note": "Defaults to a 14-bar Wilder average of true range; thinkScript also takes an average type (simple, exponential, weighted, Wilder, Hull) that Lipi ta.atr lacks.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/Tech-Indicators/studies-library/A-B/ATR",
        "fragment": "Input Parameters: length, average type",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.barssince",
      "language": "mql4",
      "source": "absent",
      "note": "No built-in; walk back through the series in a loop until the condition holds.",
      "evidence": {
        "url": "https://docs.mql4.com/indicators",
        "fragment": "Technical Indicator Functions table (iAC ... iWPR)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.barssince",
      "language": "mql5",
      "source": "absent",
      "note": "No bars-since function in the reference; keep a counter variable updated on each bar.",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/function_indices",
        "fragment": "List of MQL5 Functions (no BarsSince entry; only Bars and BarsCalculated)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.barssince",
      "language": "ninjascript",
      "source": "present",
      "construct": "MRO",
      "signature": "MRO(Func<bool> condition, int instance, int lookBackPeriod)",
      "relation": "equivalent_with_caveat",
      "note": "Condition is a lambda, with an occurrence number (1 = latest) and a required look-back limit. Returns -1 if none; unsupported in multi-series scripts.",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/most_recent_occurence_mro.htm",
        "fragment": "Most Recent Occurrence (MRO): syntax, return value -1",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.barssince",
      "language": "pine",
      "source": "present",
      "construct": "ta.barssince",
      "signature": "ta.barssince(condition) → series int",
      "relation": "different_semantics",
      "note": "While the condition has never been true Pine returns na; Lipi returns -1. So barssince < 5 is false in Pine, true in Lipi.",
      "differences": [
        {
          "axis": "warmup_and_na",
          "note": "Never-true gives na in Pine and -1 in Lipi, so comparisons and nz() guards behave differently."
        }
      ],
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_ta.barssince (Remarks: returns na if never met)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.barssince",
      "language": "thinkscript",
      "source": "absent",
      "note": "No bars-since function. Build it with a recursive def variable that references its own earlier value, seeded with CompoundValue.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Reserved-Words/rec",
        "fragment": "rec / recursion description",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.bb",
      "language": "mql4",
      "source": "present",
      "construct": "iBands",
      "signature": "double iBands(string symbol, int timeframe, int period, double deviation, int bands_shift, int applied_price, int mode, int shift)",
      "relation": "equivalent_with_caveat",
      "note": "One call returns one line by mode (0 main, 1 upper, 2 lower); Lipi returns a tuple. Source is an applied-price constant, not any series.",
      "differences": [
        {
          "axis": "history_indexing",
          "note": "shift counts bars back from the current bar; shift 0 is the still-forming bar, and any shift can be read in one call."
        },
        {
          "axis": "htf_access",
          "note": "symbol and timeframe arguments read another symbol or period directly; Lipi ta calls use the chart's own bars."
        }
      ],
      "evidence": {
        "url": "https://docs.mql4.com/indicators/ibands",
        "fragment": "iBands mode parameter",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.bb",
      "language": "mql5",
      "source": "present",
      "construct": "iBands",
      "signature": "int iBands(string symbol, ENUM_TIMEFRAMES period, int bands_period, int bands_shift, double deviation, ENUM_APPLIED_PRICE applied_price)",
      "relation": "equivalent_with_caveat",
      "note": "Buffers are 0 base, 1 upper, 2 lower, the same order as Lipi's tuple. Adds a shift argument; price is an applied-price constant.",
      "differences": [
        {
          "axis": "state_and_side_effects",
          "note": "Returns a handle; each band is read with its own CopyBuffer call on buffer 0, 1 or 2."
        },
        {
          "axis": "history_indexing",
          "note": "CopyBuffer start_pos 0 is the current bar and counts toward the past; copied data lands oldest-first."
        },
        {
          "axis": "htf_access",
          "note": "Symbol and timeframe are explicit arguments, so another symbol or timeframe is requested directly."
        }
      ],
      "evidence": {
        "url": "https://www.mql5.com/en/docs/indicators/ibands",
        "fragment": "Note: buffer numbers 0 - BASE_LINE, 1 - UPPER_BAND, 2 - LOWER_BAND",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.bb",
      "language": "ninjascript",
      "source": "present",
      "construct": "Bollinger",
      "signature": "Bollinger(ISeries<double> input, double numStdDev, int period).Upper[int barsAgo]",
      "relation": "equivalent_with_caveat",
      "note": "Order is multiplier then period (input first if given). Bands come back as .Upper and .Lower series, not a tuple.",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/bollinger_bands.htm",
        "fragment": "Syntax: Bollinger(double numStdDev, int period).Upper / .Lower",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.bb",
      "language": "pine",
      "source": "present",
      "construct": "ta.bb",
      "signature": "ta.bb(series, length, mult) → [series float, series float, series float]",
      "relation": "equivalent_with_caveat",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_ta.bb (example destructures [middle, upper, lower])",
        "accessed": "2026-11-01"
      },
      "verified": "documented",
      "note": "Pine's reference says na source values are ignored; Lipi's ta.bb returns na on a bar whose source is na."
    },
    {
      "concept": "ta.bb",
      "language": "thinkscript",
      "source": "present",
      "construct": "BollingerBands",
      "signature": "BollingerBands(price, displace, length, num dev dn, num dev up, average type)",
      "relation": "equivalent_with_caveat",
      "note": "Separate lower and upper deviation counts, a displace shift and a selectable average type; plots are MidLine, LowerBand, UpperBand versus Lipi's [middle, upper, lower].",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/Tech-Indicators/studies-library/A-B/BollingerBands",
        "fragment": "Input Parameters and Plots tables",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.bbw",
      "language": "mql4",
      "source": "absent",
      "note": "No band-width function; compute it from the main, upper and lower iBands lines.",
      "evidence": {
        "url": "https://docs.mql4.com/indicators",
        "fragment": "Technical Indicator Functions table (iAC ... iWPR)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.bbw",
      "language": "mql5",
      "source": "absent",
      "note": "No band-width indicator; derive it from the iBands base, upper and lower buffers.",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/indicators",
        "fragment": "table of technical indicator functions (no band width entry)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.bbw",
      "language": "ninjascript",
      "source": "absent",
      "note": "No band-width indicator; derive it from the Bollinger Upper and Lower series.",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/indicators.htm",
        "fragment": "System Indicator Methods index: no Bollinger width entry",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.bbw",
      "language": "pine",
      "source": "present",
      "construct": "ta.bbw",
      "signature": "ta.bbw(series, length, mult) → series float",
      "relation": "different_semantics",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_ta.bbw",
        "accessed": "2026-11-01"
      },
      "verified": "documented",
      "note": "Lipi returns upper minus lower in price units; Pine divides that width by the middle band (a fraction, or x100 in its own example)."
    },
    {
      "concept": "ta.bbw",
      "language": "thinkscript",
      "source": "present",
      "construct": "BollingerBandwidth",
      "signature": "BollingerBandwidth(average type, price, displace, length, num dev dn, num dev up, bulge length, squeeze length)",
      "relation": "different_semantics",
      "note": "BollingerBandwidth gives band distance as a percent of the middle band, plus Bulge and Squeeze plots. Lipi's ta.bbw is top minus bottom, in price units.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/Tech-Indicators/studies-library/A-B/BollingerBandwidth",
        "fragment": "Description and Plots: Bandwidth, Bulge, Squeeze",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.cci",
      "language": "mql4",
      "source": "present",
      "construct": "iCCI",
      "signature": "double iCCI(string symbol, int timeframe, int period, int applied_price, int shift)",
      "relation": "equivalent_with_caveat",
      "note": "Source is an applied-price constant, not any series. iCCIOnArray takes array data instead.",
      "differences": [
        {
          "axis": "history_indexing",
          "note": "shift counts bars back from the current bar; shift 0 is the still-forming bar, and any shift can be read in one call."
        },
        {
          "axis": "htf_access",
          "note": "symbol and timeframe arguments read another symbol or period directly; Lipi ta calls use the chart's own bars."
        }
      ],
      "evidence": {
        "url": "https://docs.mql4.com/indicators/icci",
        "fragment": "iCCI",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.cci",
      "language": "mql5",
      "source": "present",
      "construct": "iCCI",
      "signature": "int iCCI(string symbol, ENUM_TIMEFRAMES period, int ma_period, ENUM_APPLIED_PRICE applied_price)",
      "relation": "equivalent_with_caveat",
      "note": "Price is an applied-price constant or another indicator's handle, not an arbitrary series. One buffer.",
      "differences": [
        {
          "axis": "state_and_side_effects",
          "note": "Returns a handle; values are read later with CopyBuffer and are not ready right after creation."
        },
        {
          "axis": "history_indexing",
          "note": "CopyBuffer start_pos 0 is the current bar and counts toward the past; copied data lands oldest-first."
        },
        {
          "axis": "htf_access",
          "note": "Symbol and timeframe are explicit arguments, so another symbol or timeframe is requested directly."
        }
      ],
      "evidence": {
        "url": "https://www.mql5.com/en/docs/indicators/icci",
        "fragment": "iCCI signature (applied_price: type of price or handle)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.cci",
      "language": "ninjascript",
      "source": "present",
      "construct": "CCI",
      "signature": "CCI(ISeries<double> input, int period)[int barsAgo]",
      "relation": "equivalent_with_caveat",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/entering_calculation_logic6.htm",
        "fragment": "core calculation logic from the @CCI indicator",
        "accessed": "2026-11-01"
      },
      "verified": "documented",
      "note": "NinjaTrader's CCI has values from the first bar (0, then partial windows); Lipi's ta.cci is na until bar length-1."
    },
    {
      "concept": "ta.cci",
      "language": "pine",
      "source": "present",
      "construct": "ta.cci",
      "signature": "ta.cci(source, length) → series float",
      "relation": "equivalent_with_caveat",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_ta.cci",
        "accessed": "2026-11-01"
      },
      "verified": "documented",
      "note": "Pine's reference says na source values are ignored; Lipi's ta.cci returns na on a bar whose source is na."
    },
    {
      "concept": "ta.cci",
      "language": "thinkscript",
      "source": "present",
      "construct": "CCI",
      "signature": "CCI(length, over sold, over bought, show breakout signals)",
      "relation": "equivalent_with_caveat",
      "note": "Study page lists no price input, only length and level settings; Lipi ta.cci takes an explicit source series.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/Tech-Indicators/studies-library/C-D/CCI",
        "fragment": "Input Parameters table",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.change",
      "language": "mql4",
      "source": "absent",
      "note": "No built-in; subtract timeseries elements yourself, such as Close[0] - Close[n].",
      "evidence": {
        "url": "https://docs.mql4.com/indicators",
        "fragment": "Technical Indicator Functions table (iAC ... iWPR)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.change",
      "language": "mql5",
      "source": "absent",
      "note": "No change function in the reference; subtract the value at the older bar offset yourself. iMomentum is a handle-based price-change indicator.",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/function_indices",
        "fragment": "List of MQL5 Functions (no Change entry)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.change",
      "language": "ninjascript",
      "source": "present",
      "construct": "Momentum",
      "signature": "Momentum(ISeries<double> input, int period)[int barsAgo]",
      "relation": "equivalent_with_caveat",
      "note": "Page gives no formula for Momentum; plain subtraction of Input[0] and Input[n] is the safe equivalent.",
      "differences": [
        {
          "axis": "warmup_and_na",
          "note": "Reading a bar before the first one throws an index-out-of-range exception; guard with CurrentBar."
        }
      ],
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/momentum.htm",
        "fragment": "Syntax: Momentum(int period); see also make_sure_you_have_enough_bars.htm",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.change",
      "language": "pine",
      "source": "present",
      "construct": "ta.change",
      "signature": "ta.change(source, length) → series int, float or bool; length defaults to 1",
      "relation": "equivalent_with_caveat",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_ta.change",
        "accessed": "2026-11-01"
      },
      "verified": "documented",
      "note": "Pine's result is na on the na bar and length bars later; Lipi's ta.change is na only on the na bar."
    },
    {
      "concept": "ta.change",
      "language": "thinkscript",
      "source": "absent",
      "note": "No change function. Subtract the indexed value, price minus price[n]; positive indexes reach into the past.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Operators/Indexing",
        "fragment": "Indexing operator []: positive shift is the past",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.cmo",
      "language": "mql4",
      "source": "absent",
      "note": "No Chande Momentum Oscillator among the indicator functions.",
      "evidence": {
        "url": "https://docs.mql4.com/indicators",
        "fragment": "Technical Indicator Functions table (iAC ... iWPR)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.cmo",
      "language": "mql5",
      "source": "absent",
      "note": "No Chande Momentum Oscillator among the built-in indicators.",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/indicators",
        "fragment": "table of technical indicator functions (iAC ... iVolumes)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.cmo",
      "language": "ninjascript",
      "source": "present",
      "construct": "CMO",
      "signature": "CMO(ISeries<double> input, int period)[int barsAgo]",
      "relation": "exact",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/chande_momentum_oscillator_cmo.htm",
        "fragment": "Syntax: CMO(int period)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.cmo",
      "language": "pine",
      "source": "present",
      "construct": "ta.cmo",
      "signature": "ta.cmo(series, length) → series float",
      "relation": "equivalent_with_caveat",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_ta.cmo",
        "accessed": "2026-11-01"
      },
      "verified": "documented",
      "note": "Pine's reference says na source values are ignored; Lipi's ta.cmo returns na on a bar whose source is na."
    },
    {
      "concept": "ta.cmo",
      "language": "thinkscript",
      "source": "present",
      "construct": "ChandeMomentumOscillator",
      "signature": "ChandeMomentumOscillator(length)",
      "relation": "equivalent_with_caveat",
      "note": "Study page lists only length (no source input) and adds fixed +50/-50 level plots; scale is -100 to 100.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/Tech-Indicators/studies-library/C-D/ChandeMomentumOscillator",
        "fragment": "Input Parameters and Plots tables",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.cog",
      "language": "mql4",
      "source": "absent",
      "note": "No centre-of-gravity function among the indicator functions.",
      "evidence": {
        "url": "https://docs.mql4.com/indicators",
        "fragment": "Technical Indicator Functions table (iAC ... iWPR)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.cog",
      "language": "mql5",
      "source": "absent",
      "note": "No centre-of-gravity indicator among the built-in indicators.",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/indicators",
        "fragment": "table of technical indicator functions (iAC ... iVolumes)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.cog",
      "language": "ninjascript",
      "source": "absent",
      "note": "No centre-of-gravity indicator in the system list; code the weighted sum by hand.",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/indicators.htm",
        "fragment": "System Indicator Methods index: no centre of gravity entry",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.cog",
      "language": "pine",
      "source": "present",
      "construct": "ta.cog",
      "signature": "ta.cog(source, length) → series float",
      "relation": "equivalent_with_caveat",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_ta.cog",
        "accessed": "2026-11-01"
      },
      "verified": "documented",
      "note": "Pine's reference says na source values are ignored; Lipi's ta.cog returns na on a bar whose source is na."
    },
    {
      "concept": "ta.cog",
      "language": "thinkscript",
      "source": "absent",
      "note": "No centre-of-gravity function or study in the functions list or the study library.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/Tech-Indicators/studies-library",
        "fragment": "study library index (no COG entry)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.correlation",
      "language": "mql4",
      "source": "absent",
      "note": "No correlation function among the indicator functions or math group.",
      "evidence": {
        "url": "https://docs.mql4.com/indicators",
        "fragment": "Technical Indicator Functions table (iAC ... iWPR)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.correlation",
      "language": "mql5",
      "source": "present",
      "construct": "vector::CorrCoef",
      "signature": "scalar vector::CorrCoef(const vector& b)",
      "relation": "equivalent_with_caveat",
      "note": "A method on two vectors you fill first; it returns the Pearson coefficient. The bar window is whatever you copy into the vectors.",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/matrix/matrix_products/matrix_corrcoef",
        "fragment": "CorrCoef: Pearson product-moment correlation coefficients",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.correlation",
      "language": "ninjascript",
      "source": "present",
      "construct": "Correlation",
      "signature": "Correlation(ISeries<double> input, int period, string correlationSeries)[int barsAgo]",
      "relation": "equivalent_with_caveat",
      "note": "Correlates the chart series with another instrument given by name, not any two series.",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/correlation.htm",
        "fragment": "Syntax: Correlation(int period, string correlationSeries)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.correlation",
      "language": "pine",
      "source": "present",
      "construct": "ta.correlation",
      "signature": "ta.correlation(source1, source2, length) → series float",
      "relation": "equivalent_with_caveat",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_ta.correlation",
        "accessed": "2026-11-01"
      },
      "verified": "documented",
      "note": "Pine's reference says na source values are ignored; Lipi's ta.correlation returns na on a bar whose source is na."
    },
    {
      "concept": "ta.correlation",
      "language": "thinkscript",
      "source": "present",
      "construct": "Correlation",
      "signature": "Correlation(IDataHolder data1, IDataHolder data2, int length = 10)",
      "relation": "equivalent_with_caveat",
      "note": "Length defaults to 10. thinkScript can feed another symbol's close as data2; Lipi reads only the chart symbol.",
      "differences": [
        {
          "axis": "htf_access",
          "note": "data2 may come from a secondary symbol, which Lipi cannot read."
        }
      ],
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Functions/Statistical/Correlation",
        "fragment": "Correlation ( IDataHolder data1 , IDataHolder data2 , int length ); length: 10",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.cross",
      "language": "mql4",
      "source": "absent",
      "note": "No built-in; compare the two values at shift 0 and shift 1 yourself.",
      "evidence": {
        "url": "https://docs.mql4.com/indicators",
        "fragment": "Technical Indicator Functions table (iAC ... iWPR)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.cross",
      "language": "mql5",
      "source": "absent",
      "note": "No cross function; compare the current and previous values of both series yourself.",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/function_indices",
        "fragment": "List of MQL5 Functions (no Cross entry)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.cross",
      "language": "ninjascript",
      "source": "absent",
      "note": "No single both-direction cross method; combine CrossAbove and CrossBelow with OR.",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/market_data.htm",
        "fragment": "Analytical index: CrossAbove(), CrossBelow() only",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.cross",
      "language": "pine",
      "source": "present",
      "construct": "ta.cross",
      "signature": "ta.cross(source1, source2) → series bool",
      "relation": "exact",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_ta.cross",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.cross",
      "language": "thinkscript",
      "source": "present",
      "construct": "Crosses",
      "signature": "Crosses(IDataHolder data1, IDataHolder data2, double direction = CrossingDirection.ANY)",
      "relation": "exact",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Functions/Math---Trig/Crosses",
        "fragment": "Crosses ( ... direction: CrossingDirection.ANY )",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.crossover",
      "language": "mql4",
      "source": "absent",
      "note": "No built-in; test below-or-equal at shift 1 and above at shift 0 yourself.",
      "evidence": {
        "url": "https://docs.mql4.com/indicators",
        "fragment": "Technical Indicator Functions table (iAC ... iWPR)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.crossover",
      "language": "mql5",
      "source": "absent",
      "note": "No crossover function; test previous below-or-equal and current above, using two bar values.",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/function_indices",
        "fragment": "List of MQL5 Functions (no Cross entry)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.crossover",
      "language": "ninjascript",
      "source": "present",
      "construct": "CrossAbove",
      "signature": "CrossAbove(ISeries<double> series1, ISeries<double> series2, int lookBackPeriod) / CrossAbove(ISeries<double> series1, double value, int lookBackPeriod)",
      "relation": "equivalent_with_caveat",
      "note": "Extra required lookBackPeriod (1 = current bar only). NinjaTrader excludes a cross that starts from equal values; Lipi's ta.crossover counts it.",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/crossabove.htm",
        "fragment": "Syntax: CrossAbove(series1, series2, lookBackPeriod)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.crossover",
      "language": "pine",
      "source": "present",
      "construct": "ta.crossover",
      "signature": "ta.crossover(source1, source2) → series bool",
      "relation": "exact",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_ta.crossover",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.crossover",
      "language": "thinkscript",
      "source": "present",
      "construct": "Crosses",
      "signature": "Crosses(IDataHolder data1, IDataHolder data2, double direction = CrossingDirection.ANY)",
      "relation": "equivalent_with_caveat",
      "note": "Pass CrossingDirection.ABOVE: the default is ANY, so a bare Crosses call is ta.cross, not crossover.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Functions/Math---Trig/Crosses",
        "fragment": "direction parameter: CrossingDirection.ABOVE",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.crossunder",
      "language": "mql4",
      "source": "absent",
      "note": "No built-in; test above-or-equal at shift 1 and below at shift 0 yourself.",
      "evidence": {
        "url": "https://docs.mql4.com/indicators",
        "fragment": "Technical Indicator Functions table (iAC ... iWPR)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.crossunder",
      "language": "mql5",
      "source": "absent",
      "note": "No crossunder function; test previous above-or-equal and current below, using two bar values.",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/function_indices",
        "fragment": "List of MQL5 Functions (no Cross entry)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.crossunder",
      "language": "ninjascript",
      "source": "present",
      "construct": "CrossBelow",
      "signature": "CrossBelow(ISeries<double> series1, ISeries<double> series2, int lookBackPeriod) / CrossBelow(ISeries<double> series1, double value, int lookBackPeriod)",
      "relation": "equivalent_with_caveat",
      "note": "Extra required lookBackPeriod (1 = current bar only). NinjaTrader excludes a cross that starts from equal values; Lipi's ta.crossunder counts it.",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/crossbelow.htm",
        "fragment": "Syntax: CrossBelow(series1, series2, lookBackPeriod)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.crossunder",
      "language": "pine",
      "source": "present",
      "construct": "ta.crossunder",
      "signature": "ta.crossunder(source1, source2) → series bool",
      "relation": "exact",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_ta.crossunder",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.crossunder",
      "language": "thinkscript",
      "source": "present",
      "construct": "Crosses",
      "signature": "Crosses(IDataHolder data1, IDataHolder data2, double direction = CrossingDirection.ANY)",
      "relation": "equivalent_with_caveat",
      "note": "Pass CrossingDirection.BELOW: the default is ANY, so a bare Crosses call is ta.cross, not crossunder.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Functions/Math---Trig/Crosses",
        "fragment": "direction parameter: CrossingDirection.BELOW",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.cum",
      "language": "mql4",
      "source": "absent",
      "note": "No running-total function; keep a variable or array updated per bar.",
      "evidence": {
        "url": "https://docs.mql4.com/indicators",
        "fragment": "Technical Indicator Functions table (iAC ... iWPR)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.cum",
      "language": "mql5",
      "source": "present",
      "construct": "vector::CumSum",
      "relation": "equivalent_with_caveat",
      "note": "Cumulative sum over a whole vector at once, not a running total carried from bar to bar.",
      "differences": [
        {
          "axis": "state_and_side_effects",
          "note": "No state kept between calls; an incremental total needs a variable you maintain."
        }
      ],
      "evidence": {
        "url": "https://www.mql5.com/en/docs/matrix/matrix_statistics",
        "fragment": "CumSum: cumulative sum of matrix/vector elements",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.cum",
      "language": "ninjascript",
      "source": "absent",
      "note": "No running-total indicator (SUM is a rolling window); keep a Series<double> or field and add each bar.",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/indicators.htm",
        "fragment": "System Indicator Methods index: only Summation (SUM), a windowed sum",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.cum",
      "language": "pine",
      "source": "present",
      "construct": "ta.cum",
      "signature": "ta.cum(source) → series float",
      "relation": "exact",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_ta.cum",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.cum",
      "language": "thinkscript",
      "source": "present",
      "construct": "TotalSum",
      "signature": "TotalSum(IDataHolder data)",
      "relation": "exact",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Functions/Math---Trig/TotalSum",
        "fragment": "TotalSum ( IDataHolder data ): sum from the first bar to the current",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.dc",
      "language": "mql4",
      "source": "absent",
      "note": "No Donchian channel; combine iHighest and iLowest with iHigh and iLow.",
      "evidence": {
        "url": "https://docs.mql4.com/indicators",
        "fragment": "Technical Indicator Functions table (iAC ... iWPR)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.dc",
      "language": "mql5",
      "source": "absent",
      "note": "No Donchian channel indicator; build it from iHighest and iLowest over the window.",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/indicators",
        "fragment": "table of technical indicator functions (no Donchian entry)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.dc",
      "language": "ninjascript",
      "source": "present",
      "construct": "DonchianChannel",
      "signature": "DonchianChannel(ISeries<double> input, int period).Upper[int barsAgo]",
      "relation": "equivalent_with_caveat",
      "note": "Read as .Upper and .Lower series plus the default series, not a tuple; the plain call needs only a period.",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/donchian_channel.htm",
        "fragment": "Syntax: DonchianChannel(int period).Upper / .Lower",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.dc",
      "language": "pine",
      "source": "absent",
      "note": "The ta namespace lists no Donchian function. A script must compose it from ta.highest and ta.lowest (our inference, not stated in the reference).",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "ta.* function list: no ta.dc entry (ta.cum is followed by ta.dev)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.dc",
      "language": "thinkscript",
      "source": "present",
      "construct": "PriceChannel",
      "signature": "PriceChannel(displace, length)",
      "relation": "equivalent_with_caveat",
      "note": "Plots only LowerBand and UpperBand, no midline; Highest and Lowest give the same bands (the docs shift them by [1] to skip the current bar).",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/Tech-Indicators/studies-library/O-Q/PriceChannel",
        "fragment": "Input Parameters and Plots tables",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.dcw",
      "language": "mql4",
      "source": "absent",
      "note": "No Donchian width function; derive it from iHighest/iHigh and iLowest/iLow.",
      "evidence": {
        "url": "https://docs.mql4.com/indicators",
        "fragment": "Technical Indicator Functions table (iAC ... iWPR)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.dcw",
      "language": "mql5",
      "source": "absent",
      "note": "No Donchian width indicator; derive it from the highest and lowest values yourself.",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/indicators",
        "fragment": "table of technical indicator functions (no Donchian entry)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.dcw",
      "language": "ninjascript",
      "source": "absent",
      "note": "No width indicator; subtract DonchianChannel Lower from Upper.",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/indicators.htm",
        "fragment": "System Indicator Methods index: no Donchian width entry",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.dcw",
      "language": "pine",
      "source": "absent",
      "note": "No Donchian width function in the ta namespace. Compose it from ta.highest and ta.lowest (our inference, not stated in the reference).",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "ta.* function list: no ta.dcw entry (ta.cum is followed by ta.dev)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.dcw",
      "language": "thinkscript",
      "source": "absent",
      "note": "No channel-width study; subtract the PriceChannel LowerBand from its UpperBand.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/Tech-Indicators/studies-library/O-Q/PriceChannel",
        "fragment": "Plots: LowerBand, UpperBand",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.dev",
      "language": "mql4",
      "source": "absent",
      "note": "No mean-deviation function among the indicator functions.",
      "evidence": {
        "url": "https://docs.mql4.com/indicators",
        "fragment": "Technical Indicator Functions table (iAC ... iWPR)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.dev",
      "language": "mql5",
      "source": "present",
      "construct": "MathAverageDeviation",
      "signature": "double MathAverageDeviation(const double& array[])",
      "relation": "equivalent_with_caveat",
      "note": "Average absolute deviation of an array you fill with the window. Lipi's reference does not define its dev measure, so confirm they match.",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/standardlibrary/mathematics/stat/array_stat/mathaveragedeviation",
        "fragment": "MathAverageDeviation: average absolute deviation of array elements",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.dev",
      "language": "ninjascript",
      "source": "absent",
      "note": "No mean-absolute-deviation indicator in the system list; compute it by hand.",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/indicators.htm",
        "fragment": "System Indicator Methods index: only StdDev and StdError",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.dev",
      "language": "pine",
      "source": "present",
      "construct": "ta.dev",
      "signature": "ta.dev(source, length) → series float",
      "relation": "equivalent_with_caveat",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_ta.dev",
        "accessed": "2026-11-01"
      },
      "verified": "documented",
      "note": "Pine's reference says na source values are ignored; Lipi's ta.dev returns na on a bar whose source is na."
    },
    {
      "concept": "ta.dev",
      "language": "thinkscript",
      "source": "present",
      "construct": "LinDev",
      "signature": "LinDev(IDataHolder data, int length = 12)",
      "relation": "equivalent_with_caveat",
      "note": "LinDev's length defaults to 12, Lipi's dev requires it, so a converter must insert 12 when omitted; the deviation formula matches.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Functions/Statistical/LinDev",
        "fragment": "LinDev: linear deviation, average absolute difference from the mean",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.dmi",
      "language": "mql4",
      "source": "present",
      "construct": "iADX",
      "signature": "double iADX(string symbol, int timeframe, int period, int applied_price, int mode, int shift)",
      "relation": "equivalent_with_caveat",
      "note": "One call returns one line by mode (0 ADX, 1 +DI, 2 -DI) from a single period; Lipi takes two lengths and returns a tuple.",
      "differences": [
        {
          "axis": "history_indexing",
          "note": "shift counts bars back from the current bar; shift 0 is the still-forming bar, and any shift can be read in one call."
        },
        {
          "axis": "htf_access",
          "note": "symbol and timeframe arguments read another symbol or period directly; Lipi ta calls use the chart's own bars."
        }
      ],
      "evidence": {
        "url": "https://docs.mql4.com/indicators/iadx",
        "fragment": "iADX mode parameter",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.dmi",
      "language": "mql5",
      "source": "present",
      "construct": "iADX",
      "signature": "int iADX(string symbol, ENUM_TIMEFRAMES period, int adx_period)",
      "relation": "different_semantics",
      "note": "One period argument, not two. Buffers are 0 ADX, 1 plus DI, 2 minus DI, while Lipi returns plus DI, minus DI, then ADX.",
      "differences": [
        {
          "axis": "state_and_side_effects",
          "note": "Returns a handle; values are read later with CopyBuffer and are not ready right after creation."
        },
        {
          "axis": "history_indexing",
          "note": "CopyBuffer start_pos 0 is the current bar and counts toward the past; copied data lands oldest-first."
        },
        {
          "axis": "htf_access",
          "note": "Symbol and timeframe are explicit arguments, so another symbol or timeframe is requested directly."
        }
      ],
      "evidence": {
        "url": "https://www.mql5.com/en/docs/indicators/iadx",
        "fragment": "Note: buffer numbers 0 - MAIN_LINE, 1 - PLUSDI_LINE, 2 - MINUSDI_LINE",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.dmi",
      "language": "ninjascript",
      "source": "present",
      "construct": "DM",
      "signature": "DM(ISeries<double> input, int period).DiPlus[int barsAgo]",
      "relation": "equivalent_with_caveat",
      "note": "One period only, with no separate ADX smoothing length. Default series is ADX; read .DiPlus and .DiMinus as properties, not a tuple.",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/directional_movement_dm.htm",
        "fragment": "Syntax: DM(int period).DiPlus / .DiMinus; same as ADX plus +DI and -DI",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.dmi",
      "language": "pine",
      "source": "present",
      "construct": "ta.dmi",
      "signature": "ta.dmi(diLength, adxSmoothing) → [series float, series float, series float]",
      "relation": "equivalent_with_caveat",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_ta.dmi (returns +DI, -DI, ADX)",
        "accessed": "2026-11-01"
      },
      "verified": "documented",
      "note": "The reference does not state Pine's smoothing. Lipi smooths true range and movement with alpha 2/(length+1) and ADX with RMA; compare values."
    },
    {
      "concept": "ta.dmi",
      "language": "thinkscript",
      "source": "present",
      "construct": "DMI",
      "signature": "DMI(length, average type)",
      "relation": "equivalent_with_caveat",
      "note": "One length drives DI+, DI- and ADX, with Wilder smoothing by default; Lipi ta.dmi takes separate diLength and adxSmoothing.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/Tech-Indicators/studies-library/C-D/DMI",
        "fragment": "Input Parameters and Plots: DI+, DI-, ADX",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.ema",
      "language": "mql4",
      "source": "present",
      "construct": "iMA with MODE_EMA",
      "signature": "double iMA(string symbol, int timeframe, int ma_period, int ma_shift, int ma_method, int applied_price, int shift)",
      "relation": "equivalent_with_caveat",
      "note": "One iMA covers four averages via ma_method (MODE_EMA = 1). ma_shift offsets the line, which Lipi lacks. Source is an applied-price constant, not any series.",
      "differences": [
        {
          "axis": "history_indexing",
          "note": "shift counts bars back from the current bar; shift 0 is the still-forming bar, and any shift can be read in one call."
        },
        {
          "axis": "htf_access",
          "note": "symbol and timeframe arguments read another symbol or period directly; Lipi ta calls use the chart's own bars."
        }
      ],
      "evidence": {
        "url": "https://docs.mql4.com/indicators/ima",
        "fragment": "iMA ma_method; ENUM_MA_METHOD MODE_EMA",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.ema",
      "language": "mql5",
      "source": "present",
      "construct": "iMA with MODE_EMA",
      "signature": "int iMA(string symbol, ENUM_TIMEFRAMES period, int ma_period, int ma_shift, ENUM_MA_METHOD ma_method, ENUM_APPLIED_PRICE applied_price)",
      "relation": "equivalent_with_caveat",
      "note": "Same iMA as the simple average with ma_method set to MODE_EMA. An extra ma_shift shifts the line; price is an applied-price constant.",
      "differences": [
        {
          "axis": "state_and_side_effects",
          "note": "Returns a handle; values are read later with CopyBuffer and are not ready right after creation."
        },
        {
          "axis": "history_indexing",
          "note": "CopyBuffer start_pos 0 is the current bar and counts toward the past; copied data lands oldest-first."
        },
        {
          "axis": "htf_access",
          "note": "Symbol and timeframe are explicit arguments, so another symbol or timeframe is requested directly."
        }
      ],
      "evidence": {
        "url": "https://www.mql5.com/en/docs/constants/indicatorconstants/enum_ma_method",
        "fragment": "ENUM_MA_METHOD: MODE_EMA Exponential averaging",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.ema",
      "language": "ninjascript",
      "source": "present",
      "construct": "EMA",
      "signature": "EMA(ISeries<double> input, int period)[int barsAgo]",
      "relation": "exact",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/moving_average_-_exponential_e.htm",
        "fragment": "Syntax: EMA(int period)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.ema",
      "language": "pine",
      "source": "present",
      "construct": "ta.ema",
      "signature": "ta.ema(source, length) → series float",
      "relation": "equivalent_with_caveat",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_ta.ema",
        "accessed": "2026-11-01"
      },
      "verified": "documented",
      "note": "Pine's reference says na source values are ignored; Lipi's ta.ema returns na on a bar whose source is na."
    },
    {
      "concept": "ta.ema",
      "language": "thinkscript",
      "source": "present",
      "construct": "ExpAverage",
      "signature": "ExpAverage(IDataHolder data, int length = 12)",
      "relation": "equivalent_with_caveat",
      "note": "Same alpha, 2/(length+1), and both seed from the first value. thinkScript's length defaults to 12, so pass it explicitly.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Functions/Tech-Analysis/ExpAverage",
        "fragment": "ExpAverage ( IDataHolder data , int length ); EMA1 = price1",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.falling",
      "language": "mql4",
      "source": "absent",
      "note": "No built-in; compare successive series values in a loop.",
      "evidence": {
        "url": "https://docs.mql4.com/indicators",
        "fragment": "Technical Indicator Functions table (iAC ... iWPR)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.falling",
      "language": "mql5",
      "source": "absent",
      "note": "No falling-test function; compare the bar values in a loop or a chain of comparisons.",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/function_indices",
        "fragment": "List of MQL5 Functions (no Falling entry)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.falling",
      "language": "ninjascript",
      "source": "present",
      "construct": "IsFalling",
      "signature": "IsFalling(ISeries<double> series)",
      "relation": "equivalent_with_caveat",
      "note": "No length argument: it only tests that the current value is below the previous bar's value.",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/falling.htm",
        "fragment": "IsFalling(): true when current value is less than the value of 1 bar ago",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.falling",
      "language": "pine",
      "source": "present",
      "construct": "ta.falling",
      "signature": "ta.falling(source, length) → series bool",
      "relation": "different_semantics",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_ta.falling",
        "accessed": "2026-11-01"
      },
      "verified": "documented",
      "note": "Pine compares the current value with earlier values in the window; Lipi's ta.falling needs a fall on every bar. Compare each earlier bar explicitly."
    },
    {
      "concept": "ta.falling",
      "language": "thinkscript",
      "source": "present",
      "construct": "IsDescending",
      "signature": "IsDescending(IDataHolder value, int length = 3)",
      "relation": "different_semantics",
      "note": "Tests the average slope of trendlines from the mid-body value of past bars to the current value, not bar-by-bar declines like ta.falling.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Functions/Tech-Analysis/IsDescending",
        "fragment": "IsDescending: average slope of trendlines starting at MidBodyVal",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.highest",
      "language": "mql4",
      "source": "present",
      "construct": "iHighest",
      "signature": "int iHighest(string symbol, int timeframe, int type, int count, int start)",
      "relation": "different_semantics",
      "note": "Returns the bar offset of the maximum, not its value; read the searched MODE_* series at that offset, e.g. iHigh for MODE_HIGH.",
      "differences": [
        {
          "axis": "history_indexing",
          "note": "result is a shift counted back from the current bar, reusable as the shift in iHigh."
        }
      ],
      "evidence": {
        "url": "https://docs.mql4.com/series/ihighest",
        "fragment": "iHighest Returned value (shift of the maximum)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.highest",
      "language": "mql5",
      "source": "present",
      "construct": "iHighest",
      "signature": "int iHighest(const string symbol, ENUM_TIMEFRAMES timeframe, ENUM_SERIESMODE type, int count=WHOLE_ARRAY, int start=0)",
      "relation": "different_semantics",
      "note": "Returns the bar shift of the highest value, not the value; read the price at that shift. The series comes from a mode enum.",
      "differences": [
        {
          "axis": "history_indexing",
          "note": "Shift 0 is the current bar and counts toward older bars; -1 signals an error."
        }
      ],
      "evidence": {
        "url": "https://www.mql5.com/en/docs/series/ihighest",
        "fragment": "iHighest Return Value: index of the highest value (shift) or -1",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.highest",
      "language": "ninjascript",
      "source": "present",
      "construct": "MAX",
      "signature": "MAX(ISeries<double> input, int period)[int barsAgo]",
      "relation": "equivalent_with_caveat",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/maximum_max.htm",
        "fragment": "Syntax: MAX(int period); returns the highest value over the specified period",
        "accessed": "2026-11-01"
      },
      "verified": "documented",
      "note": "At this build Lipi's ta.highest can be wrong on its first valid bars and is na until bar length-1; values match after warm-up."
    },
    {
      "concept": "ta.highest",
      "language": "pine",
      "source": "present",
      "construct": "ta.highest",
      "signature": "ta.highest(source, length) → series float; ta.highest(length) → series float",
      "relation": "equivalent_with_caveat",
      "note": "Pine also has a one-argument form that reads high; Lipi always needs the source, so expand ta.highest(n) to ta.highest(high, n).",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_ta.highest (Remarks: one arg version uses high)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.highest",
      "language": "thinkscript",
      "source": "present",
      "construct": "Highest",
      "signature": "Highest(IDataHolder data, int length = 12)",
      "relation": "equivalent_with_caveat",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Functions/Tech-Analysis/Highest",
        "fragment": "Highest ( IDataHolder data , int length ); length: 12",
        "accessed": "2026-11-01"
      },
      "verified": "documented",
      "note": "Highest's length defaults to 12, Lipi requires it; Lipi's first valid bars can also be wrong, and it is na until bar length-1."
    },
    {
      "concept": "ta.highestbars",
      "language": "mql4",
      "source": "present",
      "construct": "iHighest",
      "signature": "int iHighest(string symbol, int timeframe, int type, int count, int start)",
      "relation": "equivalent_with_caveat",
      "note": "Same offset-style result. Source is a MODE_* series id, with count and start arguments; returns -1 on error.",
      "differences": [
        {
          "axis": "history_indexing",
          "note": "shift counts bars back from the current bar; shift 0 is the still-forming bar, and any shift can be read in one call."
        }
      ],
      "evidence": {
        "url": "https://docs.mql4.com/series/ihighest",
        "fragment": "iHighest Returned value (shift of the maximum)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.highestbars",
      "language": "mql5",
      "source": "present",
      "construct": "iHighest",
      "signature": "int iHighest(const string symbol, ENUM_TIMEFRAMES timeframe, ENUM_SERIESMODE type, int count=WHOLE_ARRAY, int start=0)",
      "relation": "equivalent_with_caveat",
      "note": "Returns the shift of the highest bar, 0 at the current bar, as Lipi's ta.highestbars does; -1 on error. Series come from the mode enum.",
      "differences": [
        {
          "axis": "history_indexing",
          "note": "Shift 0 is the current bar and counts toward older bars."
        }
      ],
      "evidence": {
        "url": "https://www.mql5.com/en/docs/series/ihighest",
        "fragment": "iHighest Return Value: shift relative to the current bar",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.highestbars",
      "language": "ninjascript",
      "source": "present",
      "construct": "HighestBar",
      "signature": "HighestBar(ISeries<double> series, int period)",
      "relation": "equivalent_with_caveat",
      "note": "Returns an int count of bars ago (0 = current bar); the page documents no value for a not-found case.",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/highestbar.htm",
        "fragment": "HighestBar(): number of bars ago the highest value occurred",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.highestbars",
      "language": "pine",
      "source": "present",
      "construct": "ta.highestbars",
      "signature": "ta.highestbars(source, length) → series int; ta.highestbars(length) → series int",
      "relation": "equivalent_with_caveat",
      "note": "Pine returns 0 or a negative offset (-3 is three bars back). Lipi's docs do not state the sign. Pine's one-argument form reads high.",
      "differences": [
        {
          "axis": "history_indexing",
          "note": "Pine offsets are zero or negative; confirm the sign Lipi returns before comparing with positive values."
        }
      ],
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-docs/visuals/text-and-shapes/",
        "fragment": "highestBarOffset = - ta.highestbars(LOOKBACK) (comment: change its sign so it is positive); reference #fun_ta.highestbars",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.highestbars",
      "language": "thinkscript",
      "source": "present",
      "construct": "GetMaxValueOffset",
      "signature": "GetMaxValueOffset(IDataHolder data, int length = 25)",
      "relation": "equivalent_with_caveat",
      "note": "Counts bars back with 0 at the current bar, as Lipi's ta.highestbars does. The length defaults to 25.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Functions/Tech-Analysis/GetMaxValueOffset",
        "fragment": "GetMaxValueOffset ( IDataHolder data , int length ); length: 25",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.hma",
      "language": "mql4",
      "source": "absent",
      "note": "No Hull average among the indicator functions; build it from LWMA iMA calls.",
      "evidence": {
        "url": "https://docs.mql4.com/indicators",
        "fragment": "Technical Indicator Functions table (iAC ... iWPR)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.hma",
      "language": "mql5",
      "source": "absent",
      "note": "No Hull moving average among the built-in indicators; compose weighted averages with iMA or use iCustom.",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/indicators",
        "fragment": "table of technical indicator functions (iAC ... iVolumes)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.hma",
      "language": "ninjascript",
      "source": "present",
      "construct": "HMA",
      "signature": "HMA(ISeries<double> input, int period)[int barsAgo]",
      "relation": "different_semantics",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/moving_average_-_hull_hma.htm",
        "fragment": "Syntax: HMA(int period)",
        "accessed": "2026-11-01"
      },
      "verified": "documented",
      "note": "Lipi's ta.hma is built on its ta.wma, which does not follow standard weights at this build, so values differ."
    },
    {
      "concept": "ta.hma",
      "language": "pine",
      "source": "present",
      "construct": "ta.hma",
      "signature": "ta.hma(source, length) → series float",
      "relation": "different_semantics",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_ta.hma",
        "accessed": "2026-11-01"
      },
      "verified": "documented",
      "note": "Lipi's ta.hma uses its ta.wma, which does not follow standard weights at this build, so values differ. Its half length rounds up."
    },
    {
      "concept": "ta.hma",
      "language": "thinkscript",
      "source": "present",
      "construct": "HullMovingAvg",
      "signature": "HullMovingAvg(price, length, displace)",
      "relation": "different_semantics",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/Tech-Indicators/studies-library/G-L/HullMovingAvg",
        "fragment": "Input Parameters: price, length, displace",
        "accessed": "2026-11-01"
      },
      "verified": "documented",
      "note": "Lipi's ta.hma uses its ta.wma, which does not follow standard weights at this build, so values differ. The study also has a displace input."
    },
    {
      "concept": "ta.kc",
      "language": "mql4",
      "source": "absent",
      "note": "No Keltner channel; iEnvelopes is a fixed-percent envelope around an average, not ATR-based.",
      "evidence": {
        "url": "https://docs.mql4.com/indicators",
        "fragment": "Technical Indicator Functions table (iAC ... iWPR)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.kc",
      "language": "mql5",
      "source": "absent",
      "note": "No Keltner channel among the built-in indicators; combine a moving average with iATR.",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/indicators",
        "fragment": "table of technical indicator functions (iAC ... iVolumes)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.kc",
      "language": "ninjascript",
      "source": "present",
      "construct": "KeltnerChannel",
      "signature": "KeltnerChannel(ISeries<double> input, double offsetMultiplier, int period).Upper[int barsAgo]",
      "relation": "equivalent_with_caveat",
      "note": "Multiplier comes before period, with no true-range switch. Bands are .Upper and .Lower series; the page does not state how the width is built.",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/keltner_channel.htm",
        "fragment": "Syntax: KeltnerChannel(double offsetMultiplier, int period).Upper / .Lower",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.kc",
      "language": "pine",
      "source": "present",
      "construct": "ta.kc",
      "signature": "ta.kc(series, length, mult, useTrueRange) → [series float, series float, series float]",
      "relation": "equivalent_with_caveat",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_ta.kc (example destructures [middle, upper, lower])",
        "accessed": "2026-11-01"
      },
      "verified": "documented",
      "note": "Bands match the page formula after the first bars; Lipi seeds the range EMA on bar 0 from high-low, the page's ta.tr is na there."
    },
    {
      "concept": "ta.kc",
      "language": "thinkscript",
      "source": "present",
      "construct": "KeltnerChannels",
      "signature": "KeltnerChannels(displace, factor, length, price, average type, true range average type)",
      "relation": "equivalent_with_caveat",
      "note": "Width is always ATR times factor (default 2), with separate average types for the centre line and ATR; plots Avg, Upper_Band, Lower_Band.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/Tech-Indicators/studies-library/G-L/KeltnerChannels",
        "fragment": "Input Parameters and Plots tables",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.kcw",
      "language": "mql4",
      "source": "absent",
      "note": "No Keltner width; no Keltner channel is built in.",
      "evidence": {
        "url": "https://docs.mql4.com/indicators",
        "fragment": "Technical Indicator Functions table (iAC ... iWPR)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.kcw",
      "language": "mql5",
      "source": "absent",
      "note": "No Keltner width indicator; derive it from your own channel bands.",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/indicators",
        "fragment": "table of technical indicator functions (iAC ... iVolumes)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.kcw",
      "language": "ninjascript",
      "source": "absent",
      "note": "No width indicator; derive it from KeltnerChannel Upper and Lower.",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/indicators.htm",
        "fragment": "System Indicator Methods index: no Keltner width entry",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.kcw",
      "language": "pine",
      "source": "present",
      "construct": "ta.kcw",
      "signature": "ta.kcw(series, length, mult, useTrueRange) → series float",
      "relation": "equivalent_with_caveat",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_ta.kcw",
        "accessed": "2026-11-01"
      },
      "verified": "documented",
      "note": "Width fraction matches the page formula after the first bars; Lipi seeds the range EMA on bar 0, the page's ta.tr is na there."
    },
    {
      "concept": "ta.kcw",
      "language": "thinkscript",
      "source": "absent",
      "note": "No Keltner width study; derive it from the Upper_Band, Lower_Band and Avg plots.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/Tech-Indicators/studies-library/G-L/KeltnerChannels",
        "fragment": "Plots: Avg, Upper_Band, Lower_Band",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.linreg",
      "language": "mql4",
      "source": "absent",
      "note": "No linear-regression function among the indicator functions.",
      "evidence": {
        "url": "https://docs.mql4.com/indicators",
        "fragment": "Technical Indicator Functions table (iAC ... iWPR)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.linreg",
      "language": "mql5",
      "source": "present",
      "construct": "vector::LinearRegression",
      "signature": "vector vector::LinearRegression()",
      "relation": "equivalent_with_caveat",
      "note": "Returns the whole fitted line for a vector; pick the element you need. No offset argument; fill the vector with the window first.",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/matrix/matrix_statistics/matrix_linearregression",
        "fragment": "LinearRegression: vector of calculated linear regression values",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.linreg",
      "language": "ninjascript",
      "source": "present",
      "construct": "LinReg",
      "signature": "LinReg(ISeries<double> input, int period)[int barsAgo]",
      "relation": "equivalent_with_caveat",
      "note": "No offset argument; the call gives the least-squares line value. Page states no formula or which point of the fit is returned.",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/linear_regression.htm",
        "fragment": "Syntax: LinReg(int period); least squares method",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.linreg",
      "language": "pine",
      "source": "present",
      "construct": "ta.linreg",
      "signature": "ta.linreg(source, length, offset) → series float",
      "relation": "equivalent_with_caveat",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_ta.linreg",
        "accessed": "2026-11-01"
      },
      "verified": "documented",
      "note": "Matches the page's fit at offset 0; at other offsets Lipi's values do not follow the fit at this build, and Lipi resumes after na."
    },
    {
      "concept": "ta.linreg",
      "language": "thinkscript",
      "source": "present",
      "construct": "Inertia",
      "signature": "Inertia(IDataHolder data, int length)",
      "relation": "equivalent_with_caveat",
      "note": "Least-squares regression value at the current bar; no offset argument and no default length, unlike Lipi ta.linreg's offset.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Functions/Statistical/Inertia",
        "fragment": "Inertia ( IDataHolder data , int length )",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.lowest",
      "language": "mql4",
      "source": "present",
      "construct": "iLowest",
      "signature": "int iLowest(string symbol, int timeframe, int type, int count, int start)",
      "relation": "different_semantics",
      "note": "Returns the bar offset of the minimum, not its value; read the value with iLow at that offset. Source is a MODE_* series id.",
      "differences": [
        {
          "axis": "history_indexing",
          "note": "result is a shift counted back from the current bar, reusable as the shift in iLow."
        }
      ],
      "evidence": {
        "url": "https://docs.mql4.com/series/ilowest",
        "fragment": "iLowest Returned value (shift of the lowest)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.lowest",
      "language": "mql5",
      "source": "present",
      "construct": "iLowest",
      "signature": "int iLowest(const string symbol, ENUM_TIMEFRAMES timeframe, ENUM_SERIESMODE type, int count=WHOLE_ARRAY, int start=0)",
      "relation": "different_semantics",
      "note": "Returns the bar shift of the lowest value, not the value; read the price at that shift. The series comes from a mode enum.",
      "differences": [
        {
          "axis": "history_indexing",
          "note": "Shift 0 is the current bar and counts toward older bars; -1 signals an error."
        }
      ],
      "evidence": {
        "url": "https://www.mql5.com/en/docs/series/ilowest",
        "fragment": "iLowest Return Value: index of the lowest value (shift) or -1",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.lowest",
      "language": "ninjascript",
      "source": "present",
      "construct": "MIN",
      "signature": "MIN(ISeries<double> input, int period)[int barsAgo]",
      "relation": "equivalent_with_caveat",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/minimum_min.htm",
        "fragment": "Syntax: MIN(int period); returns the lowest value over the specified period",
        "accessed": "2026-11-01"
      },
      "verified": "documented",
      "note": "At this build Lipi's ta.lowest returns 0 on its first length valid bars and is na before that; values match after warm-up."
    },
    {
      "concept": "ta.lowest",
      "language": "pine",
      "source": "present",
      "construct": "ta.lowest",
      "signature": "ta.lowest(source, length) → series float; ta.lowest(length) → series float",
      "relation": "equivalent_with_caveat",
      "note": "Pine also has a one-argument form that reads low; Lipi always needs the source, so expand ta.lowest(n) to ta.lowest(low, n).",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_ta.lowest (Remarks: one arg version uses low)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.lowest",
      "language": "thinkscript",
      "source": "present",
      "construct": "Lowest",
      "signature": "Lowest(IDataHolder data, int length = 12)",
      "relation": "equivalent_with_caveat",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Functions/Tech-Analysis/Lowest",
        "fragment": "Lowest ( IDataHolder data , int length ); length: 12",
        "accessed": "2026-11-01"
      },
      "verified": "documented",
      "note": "Lowest's length defaults to 12, Lipi requires it; Lipi also returns 0 for its first length valid bars and is na before that."
    },
    {
      "concept": "ta.lowestbars",
      "language": "mql4",
      "source": "present",
      "construct": "iLowest",
      "signature": "int iLowest(string symbol, int timeframe, int type, int count, int start)",
      "relation": "equivalent_with_caveat",
      "note": "Same offset-style result. Source is a MODE_* series id, with count and start arguments; returns -1 on error.",
      "differences": [
        {
          "axis": "history_indexing",
          "note": "shift counts bars back from the current bar; shift 0 is the still-forming bar, and any shift can be read in one call."
        }
      ],
      "evidence": {
        "url": "https://docs.mql4.com/series/ilowest",
        "fragment": "iLowest Returned value (shift of the lowest)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.lowestbars",
      "language": "mql5",
      "source": "present",
      "construct": "iLowest",
      "signature": "int iLowest(const string symbol, ENUM_TIMEFRAMES timeframe, ENUM_SERIESMODE type, int count=WHOLE_ARRAY, int start=0)",
      "relation": "equivalent_with_caveat",
      "note": "Returns the shift of the lowest bar, 0 at the current bar, as Lipi's ta.lowestbars does; -1 on error. Series come from the mode enum.",
      "differences": [
        {
          "axis": "history_indexing",
          "note": "Shift 0 is the current bar and counts toward older bars."
        }
      ],
      "evidence": {
        "url": "https://www.mql5.com/en/docs/series/ilowest",
        "fragment": "iLowest Return Value: shift relative to the current bar",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.lowestbars",
      "language": "ninjascript",
      "source": "present",
      "construct": "LowestBar",
      "signature": "LowestBar(ISeries<double> series, int period)",
      "relation": "equivalent_with_caveat",
      "note": "Returns an int count of bars ago (0 = current bar); the page documents no value for a not-found case.",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/lowestbar.htm",
        "fragment": "LowestBar(): number of bars ago the lowest value occurred",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.lowestbars",
      "language": "pine",
      "source": "present",
      "construct": "ta.lowestbars",
      "signature": "ta.lowestbars(source, length) → series int; ta.lowestbars(length) → series int",
      "relation": "equivalent_with_caveat",
      "note": "Reference states no sign for the offset; the docs' highestbars example negates it, implying zero or negative values. Lipi's sign is undocumented.",
      "differences": [
        {
          "axis": "history_indexing",
          "note": "Pine offsets are probably zero or negative; confirm the sign Lipi returns before comparing with positive values."
        }
      ],
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_ta.lowestbars (offset sign by analogy with ta.highestbars in pine-script-docs/visuals/text-and-shapes/)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.lowestbars",
      "language": "thinkscript",
      "source": "present",
      "construct": "GetMinValueOffset",
      "signature": "GetMinValueOffset(IDataHolder data, int length = 25)",
      "relation": "equivalent_with_caveat",
      "note": "Counts bars back with 0 at the current bar, as Lipi's ta.lowestbars does, which returns -1 during warm-up. The length defaults to 25.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Functions/Tech-Analysis/GetMinValueOffset",
        "fragment": "GetMinValueOffset ( IDataHolder data , int length ); length: 25",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.macd",
      "language": "mql4",
      "source": "present",
      "construct": "iMACD",
      "signature": "double iMACD(string symbol, int timeframe, int fast_ema_period, int slow_ema_period, int signal_period, int applied_price, int mode, int shift)",
      "relation": "equivalent_with_caveat",
      "note": "One call returns the main or signal line by mode; no histogram mode (use iOsMA or subtract). Source is an applied-price constant, not any series.",
      "differences": [
        {
          "axis": "history_indexing",
          "note": "shift counts bars back from the current bar; shift 0 is the still-forming bar, and any shift can be read in one call."
        },
        {
          "axis": "htf_access",
          "note": "symbol and timeframe arguments read another symbol or period directly; Lipi ta calls use the chart's own bars."
        }
      ],
      "evidence": {
        "url": "https://docs.mql4.com/indicators/imacd",
        "fragment": "iMACD mode parameter (MODE_MAIN, MODE_SIGNAL)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.macd",
      "language": "mql5",
      "source": "present",
      "construct": "iMACD",
      "signature": "int iMACD(string symbol, ENUM_TIMEFRAMES period, int fast_ema_period, int slow_ema_period, int signal_period, ENUM_APPLIED_PRICE applied_price)",
      "relation": "equivalent_with_caveat",
      "note": "Buffers are 0 main and 1 signal only; there is no histogram buffer (iOsMA provides it). Lipi returns three values.",
      "differences": [
        {
          "axis": "state_and_side_effects",
          "note": "Returns a handle; values are read later with CopyBuffer and are not ready right after creation."
        },
        {
          "axis": "history_indexing",
          "note": "CopyBuffer start_pos 0 is the current bar and counts toward the past; copied data lands oldest-first."
        },
        {
          "axis": "htf_access",
          "note": "Symbol and timeframe are explicit arguments, so another symbol or timeframe is requested directly."
        }
      ],
      "evidence": {
        "url": "https://www.mql5.com/en/docs/indicators/imacd",
        "fragment": "buffer numbers: 0 - MAIN_LINE, 1 - SIGNAL_LINE",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.macd",
      "language": "ninjascript",
      "source": "present",
      "construct": "MACD",
      "signature": "MACD(ISeries<double> input, int fast, int slow, int smooth).Avg[int barsAgo]",
      "relation": "equivalent_with_caveat",
      "note": "Line, signal and histogram come back as the default series, .Avg and .Diff properties, not a tuple. Arguments are fast, slow, smooth.",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/moving_average_convergence-divergence_macd.htm",
        "fragment": "Syntax: MACD(int fast, int slow, int smooth).Avg / .Diff",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.macd",
      "language": "pine",
      "source": "present",
      "construct": "ta.macd",
      "signature": "ta.macd(source, fastlen, slowlen, siglen) → [series float, series float, series float]",
      "relation": "equivalent_with_caveat",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_ta.macd (returns MACD line, signal line, histogram)",
        "accessed": "2026-11-01"
      },
      "verified": "documented",
      "note": "Pine's reference says na source values are ignored; Lipi's ta.macd returns na on a bar whose source is na."
    },
    {
      "concept": "ta.macd",
      "language": "thinkscript",
      "source": "present",
      "construct": "MACD",
      "signature": "MACD(fast length, slow length, macd length, average type)",
      "relation": "equivalent_with_caveat",
      "note": "Adds a selectable average type for all averages; plots Value, Avg, Diff in that order, matching Lipi's [macd, signal, histogram] order.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/Tech-Indicators/studies-library/M-N/MACD",
        "fragment": "Input Parameters and Plots: Value, Avg, Diff",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.median",
      "language": "mql4",
      "source": "absent",
      "note": "No median function; copy to an array, ArraySort it and read the middle element.",
      "evidence": {
        "url": "https://docs.mql4.com/indicators",
        "fragment": "Technical Indicator Functions table (iAC ... iWPR)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.median",
      "language": "mql5",
      "source": "present",
      "construct": "MathMedian, vector::Median",
      "signature": "double MathMedian(const double& array[])",
      "relation": "equivalent_with_caveat",
      "note": "Takes an array you fill with the window first; it returns NaN on error. A Median method also exists on vectors.",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/standardlibrary/mathematics/stat/array_stat/mathmedian",
        "fragment": "MathMedian signature and Return Value",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.median",
      "language": "ninjascript",
      "source": "present",
      "construct": "GetMedian",
      "signature": "GetMedian(ISeries<double> series, int lookBackPeriod)",
      "relation": "equivalent_with_caveat",
      "note": "A plain method returning one double, not an indicator series. For an even look-back it averages the two middle values.",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/getmedian.htm",
        "fragment": "GetMedian(): statistical median; even look-back averages two middle values",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.median",
      "language": "pine",
      "source": "present",
      "construct": "ta.median",
      "signature": "ta.median(source, length) → series int or float",
      "relation": "equivalent_with_caveat",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_ta.median",
        "accessed": "2026-11-01"
      },
      "verified": "documented",
      "note": "Pine's reference says na source values are ignored; Lipi's ta.median returns na on a bar whose source is na."
    },
    {
      "concept": "ta.median",
      "language": "thinkscript",
      "source": "present",
      "construct": "Median",
      "signature": "Median(IDataHolder data, int length = 12)",
      "relation": "equivalent_with_caveat",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Functions/Tech-Analysis/Median",
        "fragment": "Median ( IDataHolder data , int length ); length: 12",
        "accessed": "2026-11-01"
      },
      "verified": "documented",
      "note": "Median's length defaults to 12, Lipi requires it; the middle-or-average-of-two rule matches."
    },
    {
      "concept": "ta.mfi",
      "language": "mql4",
      "source": "present",
      "construct": "iMFI",
      "signature": "double iMFI(string symbol, int timeframe, int period, int shift)",
      "relation": "equivalent_with_caveat",
      "note": "No source argument. Not iBWMFI, which is the Bill Williams Market Facilitation Index.",
      "differences": [
        {
          "axis": "history_indexing",
          "note": "shift counts bars back from the current bar; shift 0 is the still-forming bar, and any shift can be read in one call."
        },
        {
          "axis": "htf_access",
          "note": "symbol and timeframe arguments read another symbol or period directly; Lipi ta calls use the chart's own bars."
        }
      ],
      "evidence": {
        "url": "https://docs.mql4.com/indicators/imfi",
        "fragment": "iMFI",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.mfi",
      "language": "mql5",
      "source": "present",
      "construct": "iMFI",
      "signature": "int iMFI(string symbol, ENUM_TIMEFRAMES period, int ma_period, ENUM_APPLIED_VOLUME applied_volume)",
      "relation": "equivalent_with_caveat",
      "note": "Volume type is chosen with applied_volume; the price input is not an argument. Lipi takes a source series instead.",
      "differences": [
        {
          "axis": "state_and_side_effects",
          "note": "Returns a handle; values are read later with CopyBuffer and are not ready right after creation."
        },
        {
          "axis": "history_indexing",
          "note": "CopyBuffer start_pos 0 is the current bar and counts toward the past; copied data lands oldest-first."
        },
        {
          "axis": "htf_access",
          "note": "Symbol and timeframe are explicit arguments, so another symbol or timeframe is requested directly."
        }
      ],
      "evidence": {
        "url": "https://www.mql5.com/en/docs/indicators/imfi",
        "fragment": "iMFI signature (applied_volume: ENUM_APPLIED_VOLUME)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.mfi",
      "language": "ninjascript",
      "source": "present",
      "construct": "MFI",
      "signature": "MFI(ISeries<double> input, int period)[int barsAgo]",
      "relation": "exact",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/money_flow_index_mfi.htm",
        "fragment": "Syntax: MFI(int period)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.mfi",
      "language": "pine",
      "source": "present",
      "construct": "ta.mfi",
      "signature": "ta.mfi(series, length) → series float",
      "relation": "equivalent_with_caveat",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_ta.mfi",
        "accessed": "2026-11-01"
      },
      "verified": "documented",
      "note": "Pine's reference says na source values are ignored; Lipi's ta.mfi returns na on a bar whose source is na."
    },
    {
      "concept": "ta.mfi",
      "language": "thinkscript",
      "source": "present",
      "construct": "MoneyFlowIndex",
      "signature": "MoneyFlowIndex(over sold, over bought, length, moving avg length)",
      "relation": "equivalent_with_caveat",
      "note": "Built on typical price and volume, with no source input, and an extra moving-average length setting; Lipi ta.mfi takes a source.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/Tech-Indicators/studies-library/M-N/MoneyFlowIndex",
        "fragment": "Input Parameters table",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.mode",
      "language": "mql4",
      "source": "absent",
      "note": "No mode function; sort a copy and count runs in a loop.",
      "evidence": {
        "url": "https://docs.mql4.com/indicators",
        "fragment": "Technical Indicator Functions table (iAC ... iWPR)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.mode",
      "language": "mql5",
      "source": "absent",
      "note": "No mode function among the array statistics (mean, variance, skewness, kurtosis, median, deviation).",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/standardlibrary/mathematics/stat/array_stat",
        "fragment": "Statistical Characteristics function table",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.mode",
      "language": "ninjascript",
      "source": "absent",
      "note": "No statistical-mode indicator or method in the system list; compute it by hand.",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/indicators.htm",
        "fragment": "System Indicator Methods index: no mode entry",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.mode",
      "language": "pine",
      "source": "present",
      "construct": "ta.mode",
      "signature": "ta.mode(source, length) → series int or float",
      "relation": "equivalent_with_caveat",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_ta.mode",
        "accessed": "2026-11-01"
      },
      "verified": "documented",
      "note": "Pine ignores na source values; Lipi's ta.mode returns na on a bar whose source is na, and float even for int sources."
    },
    {
      "concept": "ta.mode",
      "language": "thinkscript",
      "source": "absent",
      "note": "No mode function; Median is the nearest windowed statistic offered.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Functions/Tech-Analysis",
        "fragment": "Technical Analysis function list (no mode entry)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.nvi",
      "language": "mql4",
      "source": "absent",
      "note": "No negative volume index among the indicator functions.",
      "evidence": {
        "url": "https://docs.mql4.com/indicators",
        "fragment": "Technical Indicator Functions table (iAC ... iWPR)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.nvi",
      "language": "mql5",
      "source": "absent",
      "note": "No negative volume index among the built-in indicators.",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/indicators",
        "fragment": "table of technical indicator functions (iAC ... iVolumes)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.nvi",
      "language": "ninjascript",
      "source": "absent",
      "note": "No negative volume index in the system list; code it by hand.",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/indicators.htm",
        "fragment": "System Indicator Methods index: no NVI entry",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.nvi",
      "language": "pine",
      "source": "present",
      "construct": "ta.nvi",
      "signature": "ta.nvi → series float (a variable)",
      "relation": "equivalent_with_caveat",
      "note": "In Pine ta.nvi is a variable written without parentheses; Lipi exposes it as the function ta.nvi().",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "var_ta.nvi",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.nvi",
      "language": "thinkscript",
      "source": "present",
      "construct": "NegativeVolumeIndex",
      "signature": "NegativeVolumeIndex()",
      "relation": "equivalent_with_caveat",
      "note": "thinkScript starts the index at 100; Lipi's ta.nvi starts at 1.0, so the levels differ.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/Tech-Indicators/studies-library/M-N/NegativeVolumeIndex",
        "fragment": "The initial value of NVI is 100",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.obv",
      "language": "mql4",
      "source": "present",
      "construct": "iOBV",
      "signature": "double iOBV(string symbol, int timeframe, int applied_price, int shift)",
      "relation": "equivalent_with_caveat",
      "note": "Takes an applied-price constant that Lipi's argument-free obv lacks.",
      "differences": [
        {
          "axis": "history_indexing",
          "note": "shift counts bars back from the current bar; shift 0 is the still-forming bar, and any shift can be read in one call."
        },
        {
          "axis": "htf_access",
          "note": "symbol and timeframe arguments read another symbol or period directly; Lipi ta calls use the chart's own bars."
        }
      ],
      "evidence": {
        "url": "https://docs.mql4.com/indicators/iobv",
        "fragment": "iOBV",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.obv",
      "language": "mql5",
      "source": "present",
      "construct": "iOBV",
      "signature": "int iOBV(string symbol, ENUM_TIMEFRAMES period, ENUM_APPLIED_VOLUME applied_volume)",
      "relation": "equivalent_with_caveat",
      "note": "Takes an applied_volume argument to choose the volume type; Lipi's call has no arguments. One buffer.",
      "differences": [
        {
          "axis": "state_and_side_effects",
          "note": "Returns a handle; values are read later with CopyBuffer and are not ready right after creation."
        },
        {
          "axis": "history_indexing",
          "note": "CopyBuffer start_pos 0 is the current bar and counts toward the past; copied data lands oldest-first."
        },
        {
          "axis": "htf_access",
          "note": "Symbol and timeframe are explicit arguments, so another symbol or timeframe is requested directly."
        }
      ],
      "evidence": {
        "url": "https://www.mql5.com/en/docs/indicators/iobv",
        "fragment": "iOBV signature and Return Value (handle)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.obv",
      "language": "ninjascript",
      "source": "present",
      "construct": "OBV",
      "signature": "OBV(ISeries<double> input)[int barsAgo]",
      "relation": "exact",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/on_balance_volume_obv.htm",
        "fragment": "Syntax: OBV()",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.obv",
      "language": "pine",
      "source": "present",
      "construct": "ta.obv",
      "signature": "ta.obv → series float (a variable)",
      "relation": "equivalent_with_caveat",
      "note": "In Pine ta.obv is a variable written without parentheses; Lipi exposes it as the function ta.obv().",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "var_ta.obv",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.obv",
      "language": "thinkscript",
      "source": "present",
      "construct": "OnBalanceVolume",
      "signature": "OnBalanceVolume()",
      "relation": "exact",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/Tech-Indicators/studies-library/O-Q/OnBalanceVolume",
        "fragment": "Plots: OBV",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.percentile_linear_interpolation",
      "language": "mql4",
      "source": "absent",
      "note": "No percentile function; sort a copy with ArraySort and interpolate by hand.",
      "evidence": {
        "url": "https://docs.mql4.com/indicators",
        "fragment": "Technical Indicator Functions table (iAC ... iWPR)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.percentile_linear_interpolation",
      "language": "mql5",
      "source": "present",
      "construct": "vector::Percentile",
      "relation": "equivalent_with_caveat",
      "note": "A vector method; percent runs 0 to 100 and a linear algorithm is used. The page asks for sorted input. Fill the vector first.",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/matrix/matrix_statistics/matrix_percentile",
        "fragment": "Percentile: percent in [0, 100], linear algorithm",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.percentile_linear_interpolation",
      "language": "ninjascript",
      "source": "absent",
      "note": "No percentile method in the system indicator or Analytical lists; compute it by hand.",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/market_data.htm",
        "fragment": "Analytical index: no percentile entry (GetMedian only)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.percentile_linear_interpolation",
      "language": "pine",
      "source": "present",
      "construct": "ta.percentile_linear_interpolation",
      "signature": "ta.percentile_linear_interpolation(source, length, percentage) → series float",
      "relation": "equivalent_with_caveat",
      "note": "Same calculation; the third parameter is named percentage in Pine and percentile in Lipi, which matters for named arguments.",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_ta.percentile_linear_interpolation",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.percentile_linear_interpolation",
      "language": "thinkscript",
      "source": "absent",
      "note": "No percentile function in the functions list or study library.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Functions/Tech-Analysis",
        "fragment": "Technical Analysis function list (no percentile entry)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.percentile_nearest_rank",
      "language": "mql4",
      "source": "absent",
      "note": "No percentile function; sort a copy with ArraySort and pick the rank by hand.",
      "evidence": {
        "url": "https://docs.mql4.com/indicators",
        "fragment": "Technical Indicator Functions table (iAC ... iWPR)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.percentile_nearest_rank",
      "language": "mql5",
      "source": "absent",
      "note": "The documented Percentile method uses a linear algorithm only; no nearest-rank variant is described.",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/matrix/matrix_statistics/matrix_percentile",
        "fragment": "A linear algorithm is used to calculate percentiles",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.percentile_nearest_rank",
      "language": "ninjascript",
      "source": "absent",
      "note": "No percentile method in the system indicator or Analytical lists; compute it by hand.",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/market_data.htm",
        "fragment": "Analytical index: no percentile entry (GetMedian only)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.percentile_nearest_rank",
      "language": "pine",
      "source": "present",
      "construct": "ta.percentile_nearest_rank",
      "signature": "ta.percentile_nearest_rank(source, length, percentage) → series float",
      "relation": "equivalent_with_caveat",
      "note": "Same calculation; the third parameter is named percentage in Pine and percentile in Lipi, which matters for named arguments.",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_ta.percentile_nearest_rank",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.percentile_nearest_rank",
      "language": "thinkscript",
      "source": "absent",
      "note": "No percentile function in the functions list or study library.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Functions/Tech-Analysis",
        "fragment": "Technical Analysis function list (no percentile entry)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.percentrank",
      "language": "mql4",
      "source": "absent",
      "note": "No percent-rank function among the indicator functions.",
      "evidence": {
        "url": "https://docs.mql4.com/indicators",
        "fragment": "Technical Indicator Functions table (iAC ... iWPR)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.percentrank",
      "language": "mql5",
      "source": "absent",
      "note": "No percent-rank method in the matrix and vector statistics list; count the values below the current one yourself.",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/matrix/matrix_statistics",
        "fragment": "Statistics method list (ArgMax ... LinearRegression)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.percentrank",
      "language": "ninjascript",
      "source": "absent",
      "note": "No percent-rank method in the system indicator or Analytical lists; compute it by hand.",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/market_data.htm",
        "fragment": "Analytical index: no percent rank entry",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.percentrank",
      "language": "pine",
      "source": "present",
      "construct": "ta.percentrank",
      "signature": "ta.percentrank(source, length) → series float",
      "relation": "equivalent_with_caveat",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_ta.percentrank",
        "accessed": "2026-11-01"
      },
      "verified": "documented",
      "note": "Same ranking on clean data; Pine yields na when an na is in the window, Lipi keeps computing after the na bar."
    },
    {
      "concept": "ta.percentrank",
      "language": "thinkscript",
      "source": "absent",
      "note": "No percent-rank function in the functions list or study library.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Functions/Tech-Analysis",
        "fragment": "Technical Analysis function list (no percent-rank entry)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.pivothigh",
      "language": "mql4",
      "source": "present",
      "construct": "iFractals",
      "signature": "double iFractals(string symbol, int timeframe, int mode, int shift)",
      "relation": "equivalent_with_caveat",
      "note": "Closest built-in: no leftBars or rightBars arguments, mode picks upper or lower, value read at a shift.",
      "differences": [
        {
          "axis": "history_indexing",
          "note": "shift counts bars back from the current bar; shift 0 is the still-forming bar, and any shift can be read in one call."
        },
        {
          "axis": "htf_access",
          "note": "symbol and timeframe arguments read another symbol or period directly; Lipi ta calls use the chart's own bars."
        }
      ],
      "evidence": {
        "url": "https://docs.mql4.com/indicators/ifractals",
        "fragment": "iFractals",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.pivothigh",
      "language": "mql5",
      "source": "present",
      "construct": "iFractals",
      "signature": "int iFractals(string symbol, ENUM_TIMEFRAMES period)",
      "relation": "equivalent_with_caveat",
      "note": "Buffers are 0 upper and 1 lower. The page shows no left or right bar-count arguments and gives no window definition.",
      "differences": [
        {
          "axis": "state_and_side_effects",
          "note": "Returns a handle; values are read later with CopyBuffer and are not ready right after creation."
        },
        {
          "axis": "history_indexing",
          "note": "CopyBuffer start_pos 0 is the current bar and counts toward the past; copied data lands oldest-first."
        }
      ],
      "evidence": {
        "url": "https://www.mql5.com/en/docs/indicators/ifractals",
        "fragment": "Note: buffer numbers 0 - UPPER_LINE, 1 - LOWER_LINE",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.pivothigh",
      "language": "ninjascript",
      "source": "present",
      "construct": "Swing",
      "signature": "Swing(ISeries<double> input, int strength).SwingHigh[int barsAgo]",
      "relation": "equivalent_with_caveat",
      "note": "One strength covers both sides. SwingHigh gives 0, not na, when no swing exists; SwingHighBar returns bars ago, or -1.",
      "differences": [
        {
          "axis": "warmup_and_na",
          "note": "Zero is returned until the bar count exceeds strength or a pivot is found."
        },
        {
          "axis": "bar_timing",
          "note": "A swing is only definite after strength further bars, so earlier values are updated later."
        }
      ],
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/swing.htm",
        "fragment": "Syntax: Swing(int strength).SwingHigh[barsAgo] / SwingHighBar(barsAgo, instance, lookBackPeriod)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.pivothigh",
      "language": "pine",
      "source": "present",
      "construct": "ta.pivothigh",
      "signature": "ta.pivothigh(source, leftbars, rightbars) → series float; ta.pivothigh(leftbars, rightbars) → series float",
      "relation": "different_semantics",
      "note": "Pine returns the price of the pivot bar itself, or na. Lipi returns the current bar's source when the window high sits leftBars back.",
      "differences": [
        {
          "axis": "bar_timing",
          "note": "Pine reports the pivot bar's own price; Lipi's value is the current bar's source, not the pivot bar's."
        }
      ],
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_ta.pivothigh",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.pivothigh",
      "language": "thinkscript",
      "source": "absent",
      "note": "No left/right-bar pivot function; the ZigZagHighLow study marks swing points filtered by a reversal threshold, and PivotPoints gives previous-period levels.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/Tech-Indicators/studies-library/V-Z/ZigZagHighLow",
        "fragment": "A high swing point is a bar with a selected price",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.pivotlow",
      "language": "mql4",
      "source": "present",
      "construct": "iFractals",
      "signature": "double iFractals(string symbol, int timeframe, int mode, int shift)",
      "relation": "equivalent_with_caveat",
      "note": "Closest built-in: no leftBars or rightBars arguments, mode picks upper or lower, value read at a shift.",
      "differences": [
        {
          "axis": "history_indexing",
          "note": "shift counts bars back from the current bar; shift 0 is the still-forming bar, and any shift can be read in one call."
        },
        {
          "axis": "htf_access",
          "note": "symbol and timeframe arguments read another symbol or period directly; Lipi ta calls use the chart's own bars."
        }
      ],
      "evidence": {
        "url": "https://docs.mql4.com/indicators/ifractals",
        "fragment": "iFractals",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.pivotlow",
      "language": "mql5",
      "source": "present",
      "construct": "iFractals",
      "signature": "int iFractals(string symbol, ENUM_TIMEFRAMES period)",
      "relation": "equivalent_with_caveat",
      "note": "Lower buffer (1) holds the low fractals. The page shows no left or right bar-count arguments and gives no window definition.",
      "differences": [
        {
          "axis": "state_and_side_effects",
          "note": "Returns a handle; values are read later with CopyBuffer and are not ready right after creation."
        },
        {
          "axis": "history_indexing",
          "note": "CopyBuffer start_pos 0 is the current bar and counts toward the past; copied data lands oldest-first."
        }
      ],
      "evidence": {
        "url": "https://www.mql5.com/en/docs/indicators/ifractals",
        "fragment": "Note: buffer numbers 0 - UPPER_LINE, 1 - LOWER_LINE",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.pivotlow",
      "language": "ninjascript",
      "source": "present",
      "construct": "Swing",
      "signature": "Swing(ISeries<double> input, int strength).SwingLow[int barsAgo]",
      "relation": "equivalent_with_caveat",
      "note": "One strength covers both sides. SwingLow gives 0, not na, when no swing exists; SwingLowBar returns bars ago, or -1.",
      "differences": [
        {
          "axis": "warmup_and_na",
          "note": "Zero is returned until the bar count exceeds strength or a pivot is found."
        },
        {
          "axis": "bar_timing",
          "note": "A swing is only definite after strength further bars, so earlier values are updated later."
        }
      ],
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/swing.htm",
        "fragment": "Syntax: Swing(int strength).SwingLow[barsAgo] / SwingLowBar(barsAgo, instance, lookBackPeriod)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.pivotlow",
      "language": "pine",
      "source": "present",
      "construct": "ta.pivotlow",
      "signature": "ta.pivotlow(source, leftbars, rightbars) → series float; ta.pivotlow(leftbars, rightbars) → series float",
      "relation": "different_semantics",
      "note": "Pine returns the price of the pivot bar itself, or na. Lipi returns the current bar's source when the window low sits leftBars back.",
      "differences": [
        {
          "axis": "bar_timing",
          "note": "Pine reports the pivot bar's own price; Lipi's value is the current bar's source, not the pivot bar's."
        }
      ],
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_ta.pivotlow",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.pivotlow",
      "language": "thinkscript",
      "source": "absent",
      "note": "No left/right-bar pivot function; the ZigZagHighLow study marks swing points filtered by a reversal threshold, and PivotPoints gives previous-period levels.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/Tech-Indicators/studies-library/V-Z/ZigZagHighLow",
        "fragment": "A low swing point is a bar with a selected price",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.psar",
      "language": "mql4",
      "source": "present",
      "construct": "iSAR",
      "signature": "double iSAR(string symbol, int timeframe, double step, double maximum, int shift)",
      "relation": "equivalent_with_caveat",
      "note": "Two parameters (step, maximum) where Lipi has start, step and max_step; no source argument.",
      "differences": [
        {
          "axis": "history_indexing",
          "note": "shift counts bars back from the current bar; shift 0 is the still-forming bar, and any shift can be read in one call."
        },
        {
          "axis": "htf_access",
          "note": "symbol and timeframe arguments read another symbol or period directly; Lipi ta calls use the chart's own bars."
        }
      ],
      "evidence": {
        "url": "https://docs.mql4.com/indicators/isar",
        "fragment": "iSAR step, maximum parameters",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.psar",
      "language": "mql5",
      "source": "present",
      "construct": "iSAR",
      "signature": "int iSAR(string symbol, ENUM_TIMEFRAMES period, double step, double maximum)",
      "relation": "equivalent_with_caveat",
      "note": "Takes step and maximum only; Lipi also has a start value. Usual values per the page are 0.02 and 0.2. One buffer.",
      "differences": [
        {
          "axis": "state_and_side_effects",
          "note": "Returns a handle; values are read later with CopyBuffer and are not ready right after creation."
        },
        {
          "axis": "history_indexing",
          "note": "CopyBuffer start_pos 0 is the current bar and counts toward the past; copied data lands oldest-first."
        },
        {
          "axis": "htf_access",
          "note": "Symbol and timeframe are explicit arguments, so another symbol or timeframe is requested directly."
        }
      ],
      "evidence": {
        "url": "https://www.mql5.com/en/docs/indicators/isar",
        "fragment": "iSAR parameters step and maximum",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.psar",
      "language": "ninjascript",
      "source": "present",
      "construct": "ParabolicSAR",
      "signature": "ParabolicSAR(ISeries<double> input, double acceleration, double accelerationMax, double accelerationStep)[int barsAgo]",
      "relation": "equivalent_with_caveat",
      "note": "Order is acceleration, max, step, whereas Lipi is start, step, max_step. The page's own syntax lines disagree on the last two.",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/parabolic_sar.htm",
        "fragment": "Syntax: ParabolicSAR(double acceleration, double accelerationMax, double accelerationStep)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.psar",
      "language": "pine",
      "source": "present",
      "construct": "ta.sar",
      "signature": "ta.sar(start, inc, max) → series float",
      "relation": "equivalent_with_caveat",
      "note": "Pine's function is ta.sar; there is no ta.psar. Positional arguments start, inc, max line up with Lipi's start, step, max_step.",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_ta.sar",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.psar",
      "language": "thinkscript",
      "source": "present",
      "construct": "ParabolicSAR",
      "signature": "ParabolicSAR(acceleration factor, acceleration limit)",
      "relation": "equivalent_with_caveat",
      "note": "Two inputs: initial acceleration factor and its limit. Lipi ta.psar has three (start, step, max_step), so the step is not separately set.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/Tech-Indicators/studies-library/O-Q/ParabolicSAR",
        "fragment": "Input Parameters: acceleration factor, acceleration limit",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.pvi",
      "language": "mql4",
      "source": "absent",
      "note": "No positive volume index among the indicator functions.",
      "evidence": {
        "url": "https://docs.mql4.com/indicators",
        "fragment": "Technical Indicator Functions table (iAC ... iWPR)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.pvi",
      "language": "mql5",
      "source": "absent",
      "note": "No positive volume index among the built-in indicators.",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/indicators",
        "fragment": "table of technical indicator functions (iAC ... iVolumes)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.pvi",
      "language": "ninjascript",
      "source": "absent",
      "note": "No positive volume index in the system list; code it by hand.",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/indicators.htm",
        "fragment": "System Indicator Methods index: no PVI entry",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.pvi",
      "language": "pine",
      "source": "present",
      "construct": "ta.pvi",
      "signature": "ta.pvi → series float (a variable)",
      "relation": "equivalent_with_caveat",
      "note": "In Pine ta.pvi is a variable written without parentheses; Lipi exposes it as the function ta.pvi().",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "var_ta.pvi",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.pvi",
      "language": "thinkscript",
      "source": "present",
      "construct": "PositiveVolumeIndex",
      "signature": "PositiveVolumeIndex()",
      "relation": "equivalent_with_caveat",
      "note": "thinkScript starts the index at 100; Lipi's ta.pvi starts at 1.0, so the levels differ.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/Tech-Indicators/studies-library/O-Q/PositiveVolumeIndex",
        "fragment": "The initial value of PVI is 100",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.pvt",
      "language": "mql4",
      "source": "absent",
      "note": "No price-volume trend among the indicator functions.",
      "evidence": {
        "url": "https://docs.mql4.com/indicators",
        "fragment": "Technical Indicator Functions table (iAC ... iWPR)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.pvt",
      "language": "mql5",
      "source": "absent",
      "note": "No price-volume trend among the built-in indicators.",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/indicators",
        "fragment": "table of technical indicator functions (iAC ... iVolumes)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.pvt",
      "language": "ninjascript",
      "source": "absent",
      "note": "No price-volume trend in the system list; code it by hand.",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/indicators.htm",
        "fragment": "System Indicator Methods index: no PVT entry",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.pvt",
      "language": "pine",
      "source": "present",
      "construct": "ta.pvt",
      "signature": "ta.pvt → series float (a variable)",
      "relation": "equivalent_with_caveat",
      "note": "In Pine ta.pvt is a variable written without parentheses; Lipi exposes it as the function ta.pvt().",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "var_ta.pvt",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.pvt",
      "language": "thinkscript",
      "source": "present",
      "construct": "PriceAndVolumeTrend",
      "signature": "PriceAndVolumeTrend()",
      "relation": "equivalent_with_caveat",
      "note": "thinkScript multiplies volume by the percent change of close; Lipi's ta.pvt uses the fractional change, so its values are 100 times smaller.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/Tech-Indicators/studies-library/O-Q/PriceAndVolumeTrend",
        "fragment": "PVT: cumulative sum of volume times percent change of Close",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.range",
      "language": "mql4",
      "source": "absent",
      "note": "No range function; use iHigh/iHighest and iLow/iLowest over the window.",
      "evidence": {
        "url": "https://docs.mql4.com/indicators",
        "fragment": "Technical Indicator Functions table (iAC ... iWPR)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.range",
      "language": "mql5",
      "source": "present",
      "construct": "vector::Ptp",
      "relation": "equivalent_with_caveat",
      "note": "Range of values of a whole vector; fill it with the window first. Lipi's range is a per-bar windowed figure.",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/matrix/matrix_statistics",
        "fragment": "Ptp: range of values of a matrix/vector",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.range",
      "language": "ninjascript",
      "source": "present",
      "construct": "Range",
      "signature": "Range()[int barsAgo] / Range(ISeries<double> input)[int barsAgo]",
      "relation": "different_semantics",
      "note": "Range() is the current bar's own range with no window length; Lipi's takes a source and length. Use MAX minus MIN for a window.",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/range.htm",
        "fragment": "Range: returns the range of a bar; syntax Range()",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.range",
      "language": "pine",
      "source": "present",
      "construct": "ta.range",
      "signature": "ta.range(source, length) → series int or float",
      "relation": "equivalent_with_caveat",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_ta.range",
        "accessed": "2026-11-01"
      },
      "verified": "documented",
      "note": "Equal after warm-up; Lipi's first length valid bars are wrong because its lowest returns 0 there, so the range is overstated."
    },
    {
      "concept": "ta.range",
      "language": "thinkscript",
      "source": "absent",
      "note": "No range function; subtract Lowest from Highest over the same length.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Functions/Tech-Analysis/Highest",
        "fragment": "Highest and Lowest over length bars",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.rising",
      "language": "mql4",
      "source": "absent",
      "note": "No built-in; compare successive series values in a loop.",
      "evidence": {
        "url": "https://docs.mql4.com/indicators",
        "fragment": "Technical Indicator Functions table (iAC ... iWPR)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.rising",
      "language": "mql5",
      "source": "absent",
      "note": "No rising-test function; compare the bar values in a loop or a chain of comparisons.",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/function_indices",
        "fragment": "List of MQL5 Functions (no Rising entry)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.rising",
      "language": "ninjascript",
      "source": "present",
      "construct": "IsRising",
      "signature": "IsRising(ISeries<double> series)",
      "relation": "equivalent_with_caveat",
      "note": "No length argument: it only tests that the current value is above the previous bar's value.",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/rising.htm",
        "fragment": "IsRising(): true when current value is greater than the value of 1 bar ago",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.rising",
      "language": "pine",
      "source": "present",
      "construct": "ta.rising",
      "signature": "ta.rising(source, length) → series bool",
      "relation": "different_semantics",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_ta.rising",
        "accessed": "2026-11-01"
      },
      "verified": "documented",
      "note": "Pine compares the current value with earlier values in the window; Lipi's ta.rising needs a rise on every bar. Compare each earlier bar explicitly."
    },
    {
      "concept": "ta.rising",
      "language": "thinkscript",
      "source": "present",
      "construct": "IsAscending",
      "signature": "IsAscending(IDataHolder value, int length = 3)",
      "relation": "different_semantics",
      "note": "Tests the average slope of trendlines from the mid-body value of past bars to the current value, not bar-by-bar rises like ta.rising.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Functions/Tech-Analysis/IsAscending",
        "fragment": "IsAscending: average slope of trendlines starting at MidBodyVal",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.rma",
      "language": "mql4",
      "source": "present",
      "construct": "iMA with MODE_SMMA",
      "signature": "double iMA(string symbol, int timeframe, int ma_period, int ma_shift, int ma_method, int applied_price, int shift)",
      "relation": "equivalent_with_caveat",
      "note": "MODE_SMMA is the smoothed average; the page gives no formula. Lipi's ta.rma uses alpha 1/length, seeded with the SMA of the first length bars.",
      "differences": [
        {
          "axis": "history_indexing",
          "note": "shift counts bars back from the current bar; shift 0 is the still-forming bar, and any shift can be read in one call."
        },
        {
          "axis": "htf_access",
          "note": "symbol and timeframe arguments read another symbol or period directly; Lipi ta calls use the chart's own bars."
        }
      ],
      "evidence": {
        "url": "https://docs.mql4.com/indicators/ima",
        "fragment": "ENUM_MA_METHOD MODE_SMMA (smoothed averaging)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.rma",
      "language": "mql5",
      "source": "present",
      "construct": "iMA with MODE_SMMA",
      "signature": "int iMA(string symbol, ENUM_TIMEFRAMES period, int ma_period, int ma_shift, ENUM_MA_METHOD ma_method, ENUM_APPLIED_PRICE applied_price)",
      "relation": "equivalent_with_caveat",
      "note": "MODE_SMMA is the smoothed average; the page gives no formula. Lipi's ta.rma uses alpha 1/length, seeded with the SMA of the first length bars.",
      "differences": [
        {
          "axis": "state_and_side_effects",
          "note": "Returns a handle; values are read later with CopyBuffer and are not ready right after creation."
        },
        {
          "axis": "history_indexing",
          "note": "CopyBuffer start_pos 0 is the current bar and counts toward the past; copied data lands oldest-first."
        },
        {
          "axis": "htf_access",
          "note": "Symbol and timeframe are explicit arguments, so another symbol or timeframe is requested directly."
        }
      ],
      "evidence": {
        "url": "https://www.mql5.com/en/docs/constants/indicatorconstants/enum_ma_method",
        "fragment": "ENUM_MA_METHOD: MODE_SMMA Smoothed averaging",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.rma",
      "language": "ninjascript",
      "source": "absent",
      "note": "No RMA indicator; Wilder smoothing is used inside RSI and ATR but not exposed on its own.",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/indicators.htm",
        "fragment": "System Indicator Methods index: no RMA entry",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.rma",
      "language": "pine",
      "source": "present",
      "construct": "ta.rma",
      "signature": "ta.rma(source, length) → series float",
      "relation": "equivalent_with_caveat",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_ta.rma",
        "accessed": "2026-11-01"
      },
      "verified": "documented",
      "note": "Pine's reference says na source values are ignored; Lipi's ta.rma returns na on a bar whose source is na."
    },
    {
      "concept": "ta.rma",
      "language": "thinkscript",
      "source": "present",
      "construct": "WildersAverage",
      "signature": "WildersAverage(IDataHolder data, int length = 12)",
      "relation": "equivalent_with_caveat",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Functions/Tech-Analysis/WildersAverage",
        "fragment": "WildersAverage ( IDataHolder data , int length ); alpha 1/length, SMA seed",
        "accessed": "2026-11-01"
      },
      "verified": "documented",
      "note": "Length defaults to 12 and seeding uses prefetched bars; Lipi needs the length and seeds with the SMA of the first length bars."
    },
    {
      "concept": "ta.roc",
      "language": "mql4",
      "source": "present",
      "construct": "iMomentum",
      "signature": "double iMomentum(string symbol, int timeframe, int period, int applied_price, int shift)",
      "relation": "equivalent_with_caveat",
      "note": "Nearest built-in; the docs give no formula or scale, so confirm it matches a percentage rate of change before use.",
      "differences": [
        {
          "axis": "history_indexing",
          "note": "shift counts bars back from the current bar; shift 0 is the still-forming bar, and any shift can be read in one call."
        },
        {
          "axis": "htf_access",
          "note": "symbol and timeframe arguments read another symbol or period directly; Lipi ta calls use the chart's own bars."
        }
      ],
      "evidence": {
        "url": "https://docs.mql4.com/indicators/imomentum",
        "fragment": "iMomentum",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.roc",
      "language": "mql5",
      "source": "unresolved",
      "note": "Nearest built-in is iMomentum, but its page does not say whether it is a ratio, percent or difference, so the mapping is unconfirmed.",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/indicators/imomentum",
        "fragment": "iMomentum mom_period: bars count for the calculation of the price change",
        "accessed": "2026-11-01"
      },
      "verified": "unresolved"
    },
    {
      "concept": "ta.roc",
      "language": "ninjascript",
      "source": "present",
      "construct": "ROC",
      "signature": "ROC(ISeries<double> input, int period)[int barsAgo]",
      "relation": "equivalent_with_caveat",
      "note": "Percent change against the value period bars ago, the same percent scale as Lipi's ta.roc.",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/rate_of_change_roc.htm",
        "fragment": "Syntax: ROC(int period); percent change in price",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.roc",
      "language": "pine",
      "source": "present",
      "construct": "ta.roc",
      "signature": "ta.roc(source, length) → series float",
      "relation": "equivalent_with_caveat",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_ta.roc",
        "accessed": "2026-11-01"
      },
      "verified": "documented",
      "note": "Same percent change on clean data; Pine gives na when the source or its lagged value is na, Lipi resumes right after."
    },
    {
      "concept": "ta.roc",
      "language": "thinkscript",
      "source": "present",
      "construct": "RateOfChange",
      "signature": "RateOfChange(length, color norm length, price)",
      "relation": "equivalent_with_caveat",
      "note": "Percent change against the price length bars back, the same scale as Lipi's ta.roc. The study also takes a price input.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/Tech-Indicators/studies-library/R-S/RateOfChange",
        "fragment": "ROC: percentage change relative to price a specified number of periods before",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.rsi",
      "language": "mql4",
      "source": "present",
      "construct": "iRSI",
      "signature": "double iRSI(string symbol, int timeframe, int period, int applied_price, int shift)",
      "relation": "equivalent_with_caveat",
      "note": "Source is an applied-price constant, not any series. iRSIOnArray takes array data instead.",
      "differences": [
        {
          "axis": "history_indexing",
          "note": "shift counts bars back from the current bar; shift 0 is the still-forming bar, and any shift can be read in one call."
        },
        {
          "axis": "htf_access",
          "note": "symbol and timeframe arguments read another symbol or period directly; Lipi ta calls use the chart's own bars."
        }
      ],
      "evidence": {
        "url": "https://docs.mql4.com/indicators/irsi",
        "fragment": "iRSI",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.rsi",
      "language": "mql5",
      "source": "present",
      "construct": "iRSI",
      "signature": "int iRSI(string symbol, ENUM_TIMEFRAMES period, int ma_period, ENUM_APPLIED_PRICE applied_price)",
      "relation": "equivalent_with_caveat",
      "note": "Price is an applied-price constant or another indicator's handle, not an arbitrary series. One buffer.",
      "differences": [
        {
          "axis": "state_and_side_effects",
          "note": "Returns a handle; values are read later with CopyBuffer and are not ready right after creation."
        },
        {
          "axis": "history_indexing",
          "note": "CopyBuffer start_pos 0 is the current bar and counts toward the past; copied data lands oldest-first."
        },
        {
          "axis": "htf_access",
          "note": "Symbol and timeframe are explicit arguments, so another symbol or timeframe is requested directly."
        }
      ],
      "evidence": {
        "url": "https://www.mql5.com/en/docs/indicators/irsi",
        "fragment": "iRSI signature (ma_period, applied_price)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.rsi",
      "language": "ninjascript",
      "source": "present",
      "construct": "RSI",
      "signature": "RSI(ISeries<double> input, int period, int smooth)[int barsAgo]",
      "relation": "equivalent_with_caveat",
      "note": "Extra required smooth argument; the .Avg series is the smoothed line. Wilder smoothing is stated on the page.",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/relative_strength_index_rsi.htm",
        "fragment": "Syntax: RSI(int period, int smooth).Avg",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.rsi",
      "language": "pine",
      "source": "present",
      "construct": "ta.rsi",
      "signature": "ta.rsi(source, length) → series float",
      "relation": "equivalent_with_caveat",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_ta.rsi",
        "accessed": "2026-11-01"
      },
      "verified": "documented",
      "note": "Pine's reference says na source values are ignored; Lipi's ta.rsi returns na on a bar whose source is na."
    },
    {
      "concept": "ta.rsi",
      "language": "thinkscript",
      "source": "present",
      "construct": "RSI",
      "signature": "RSI(length, over bought, over sold, price, average type, show breakout signals)",
      "relation": "equivalent_with_caveat",
      "note": "Wilder smoothing by default but the average type is selectable; also takes a price input and level settings. Lipi ta.rsi takes only source and length.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/Tech-Indicators/studies-library/R-S/RSI",
        "fragment": "Input Parameters table: length, price, average type",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.sma",
      "language": "mql4",
      "source": "present",
      "construct": "iMA with MODE_SMA",
      "signature": "double iMA(string symbol, int timeframe, int ma_period, int ma_shift, int ma_method, int applied_price, int shift)",
      "relation": "equivalent_with_caveat",
      "note": "One iMA covers four averages via ma_method (MODE_SMA = 0). ma_shift offsets the line. Source is an applied-price constant, not any series. iMAOnArray takes arrays.",
      "differences": [
        {
          "axis": "history_indexing",
          "note": "shift counts bars back from the current bar; shift 0 is the still-forming bar, and any shift can be read in one call."
        },
        {
          "axis": "htf_access",
          "note": "symbol and timeframe arguments read another symbol or period directly; Lipi ta calls use the chart's own bars."
        }
      ],
      "evidence": {
        "url": "https://docs.mql4.com/indicators/ima",
        "fragment": "iMA ma_method; ENUM_MA_METHOD MODE_SMA",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.sma",
      "language": "mql5",
      "source": "present",
      "construct": "iMA with MODE_SMA",
      "signature": "int iMA(string symbol, ENUM_TIMEFRAMES period, int ma_period, int ma_shift, ENUM_MA_METHOD ma_method, ENUM_APPLIED_PRICE applied_price)",
      "relation": "equivalent_with_caveat",
      "note": "One iMA covers every average type via ma_method; MODE_SMA is simple averaging. An extra ma_shift shifts the line on the chart.",
      "differences": [
        {
          "axis": "state_and_side_effects",
          "note": "Returns a handle; values are read later with CopyBuffer and are not ready right after creation."
        },
        {
          "axis": "history_indexing",
          "note": "CopyBuffer start_pos 0 is the current bar and counts toward the past; copied data lands oldest-first."
        },
        {
          "axis": "htf_access",
          "note": "Symbol and timeframe are explicit arguments, so another symbol or timeframe is requested directly."
        }
      ],
      "evidence": {
        "url": "https://www.mql5.com/en/docs/indicators/ima",
        "fragment": "iMA signature with ma_method (ENUM_MA_METHOD) and applied_price",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.sma",
      "language": "ninjascript",
      "source": "present",
      "construct": "SMA",
      "signature": "SMA(ISeries<double> input, int period)[int barsAgo]",
      "relation": "exact",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/moving_average_-_simple_sma.htm",
        "fragment": "Syntax: SMA(int period)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.sma",
      "language": "pine",
      "source": "present",
      "construct": "ta.sma",
      "signature": "ta.sma(source, length) → series float",
      "relation": "equivalent_with_caveat",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_ta.sma",
        "accessed": "2026-11-01"
      },
      "verified": "documented",
      "note": "Same average on clean data; at an na source bar Lipi returns na, TradingView returns the average of the last length non-na values."
    },
    {
      "concept": "ta.sma",
      "language": "thinkscript",
      "source": "present",
      "construct": "Average",
      "signature": "Average(IDataHolder data, int length = 12)",
      "relation": "equivalent_with_caveat",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Functions/Tech-Analysis/Average",
        "fragment": "Average ( IDataHolder data , int length ); length: 12",
        "accessed": "2026-11-01"
      },
      "verified": "documented",
      "note": "Average's length defaults to 12, Lipi requires it, so a converter must insert 12 when omitted."
    },
    {
      "concept": "ta.stdev",
      "language": "mql4",
      "source": "present",
      "construct": "iStdDev",
      "signature": "double iStdDev(string symbol, int timeframe, int ma_period, int ma_shift, int ma_method, int applied_price, int shift)",
      "relation": "equivalent_with_caveat",
      "note": "Takes a moving-average method and shift; the docs do not say population or sample division. Source is an applied-price constant, not any series.",
      "differences": [
        {
          "axis": "history_indexing",
          "note": "shift counts bars back from the current bar; shift 0 is the still-forming bar, and any shift can be read in one call."
        },
        {
          "axis": "htf_access",
          "note": "symbol and timeframe arguments read another symbol or period directly; Lipi ta calls use the chart's own bars."
        }
      ],
      "evidence": {
        "url": "https://docs.mql4.com/indicators/istddev",
        "fragment": "iStdDev ma_method parameter",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.stdev",
      "language": "mql5",
      "source": "present",
      "construct": "iStdDev",
      "signature": "int iStdDev(string symbol, ENUM_TIMEFRAMES period, int ma_period, int ma_shift, ENUM_MA_METHOD ma_method, ENUM_APPLIED_PRICE applied_price)",
      "relation": "equivalent_with_caveat",
      "note": "Also takes ma_method and ma_shift, so the mean it measures around is selectable; use MODE_SMA. The divisor is not stated on the page.",
      "differences": [
        {
          "axis": "state_and_side_effects",
          "note": "Returns a handle; values are read later with CopyBuffer and are not ready right after creation."
        },
        {
          "axis": "history_indexing",
          "note": "CopyBuffer start_pos 0 is the current bar and counts toward the past; copied data lands oldest-first."
        },
        {
          "axis": "htf_access",
          "note": "Symbol and timeframe are explicit arguments, so another symbol or timeframe is requested directly."
        }
      ],
      "evidence": {
        "url": "https://www.mql5.com/en/docs/indicators/istddev",
        "fragment": "iStdDev signature (ma_method, applied_price)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.stdev",
      "language": "ninjascript",
      "source": "present",
      "construct": "StdDev",
      "signature": "StdDev(ISeries<double> input, int period)[int barsAgo]",
      "relation": "equivalent_with_caveat",
      "note": "Lipi divides by length (population). The page does not state NinjaTrader's divisor; dividing by length minus one gives larger values.",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/standard_deviation_stddev.htm",
        "fragment": "Syntax: StdDev(int period); no formula given",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.stdev",
      "language": "pine",
      "source": "present",
      "construct": "ta.stdev",
      "signature": "ta.stdev(source, length, biased) → series float",
      "relation": "equivalent_with_caveat",
      "note": "Pine adds a biased flag (default true, the population form Lipi always uses). biased=false has no Lipi counterpart; use ta.variance with biased and math.sqrt.",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_ta.stdev",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.stdev",
      "language": "thinkscript",
      "source": "present",
      "construct": "StDev",
      "signature": "StDev(IDataHolder data, int length = 12)",
      "relation": "equivalent_with_caveat",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Functions/Statistical/StDev",
        "fragment": "StDev: square root of variance, the average of squared deviations",
        "accessed": "2026-11-01"
      },
      "verified": "documented",
      "note": "StDev's length defaults to 12, Lipi requires it; both are population deviations (divide by length)."
    },
    {
      "concept": "ta.stoch",
      "language": "mql4",
      "source": "present",
      "construct": "iStochastic",
      "signature": "double iStochastic(string symbol, int timeframe, int Kperiod, int Dperiod, int slowing, int method, int price_field, int mode, int shift)",
      "relation": "different_semantics",
      "note": "Built-in has slowing, a %D line and a price_field (0 Low/High, 1 Close/Close), with no source, high or low series; not Lipi's raw form.",
      "differences": [
        {
          "axis": "history_indexing",
          "note": "shift counts bars back from the current bar; shift 0 is the still-forming bar, and any shift can be read in one call."
        },
        {
          "axis": "htf_access",
          "note": "symbol and timeframe arguments read another symbol or period directly; Lipi ta calls use the chart's own bars."
        }
      ],
      "evidence": {
        "url": "https://docs.mql4.com/indicators/istochastic",
        "fragment": "iStochastic",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.stoch",
      "language": "mql5",
      "source": "present",
      "construct": "iStochastic",
      "signature": "int iStochastic(string symbol, ENUM_TIMEFRAMES period, int Kperiod, int Dperiod, int slowing, ENUM_MA_METHOD ma_method, ENUM_STO_PRICE price_field)",
      "relation": "different_semantics",
      "note": "Returns smoothed lines (K, D, slowing) from the bar's own prices; Lipi gives one raw reading on supplied series. Buffers: 0 main, 1 signal.",
      "differences": [
        {
          "axis": "state_and_side_effects",
          "note": "Returns a handle; values are read later with CopyBuffer and are not ready right after creation."
        },
        {
          "axis": "history_indexing",
          "note": "CopyBuffer start_pos 0 is the current bar and counts toward the past; copied data lands oldest-first."
        },
        {
          "axis": "htf_access",
          "note": "Symbol and timeframe are explicit arguments, so another symbol or timeframe is requested directly."
        }
      ],
      "evidence": {
        "url": "https://www.mql5.com/en/docs/indicators/istochastic",
        "fragment": "iStochastic signature and buffer numbers 0 - MAIN_LINE, 1 - SIGNAL_LINE",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.stoch",
      "language": "ninjascript",
      "source": "present",
      "construct": "StochasticsFast",
      "signature": "StochasticsFast(ISeries<double> input, int periodD, int periodK).K[int barsAgo]",
      "relation": "equivalent_with_caveat",
      "note": "Closest is StochasticsFast with .K and .D, taking periods only, with no high and low series.",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/stochastics_fast.htm",
        "fragment": "Syntax: StochasticsFast(int periodD, int periodK).K / .D",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.stoch",
      "language": "pine",
      "source": "present",
      "construct": "ta.stoch",
      "signature": "ta.stoch(source, high, low, length) → series float",
      "relation": "equivalent_with_caveat",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_ta.stoch",
        "accessed": "2026-11-01"
      },
      "verified": "documented",
      "note": "Lipi's ta.stoch returns values from bar 0 over a partial window, and na on a bar whose source is na."
    },
    {
      "concept": "ta.stoch",
      "language": "thinkscript",
      "source": "present",
      "construct": "FastKCustom",
      "signature": "FastKCustom(IDataHolder data, int length = 14)",
      "relation": "equivalent_with_caveat",
      "note": "Scales one series between its own highest and lowest over length bars (0 on a flat range); Lipi ta.stoch takes separate high and low series.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Functions/Tech-Analysis/FastKCustom",
        "fragment": "FastKCustom ( IDataHolder data , int length ); length: 14",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.sum",
      "language": "mql4",
      "source": "absent",
      "note": "No windowed-sum function in the math or array groups; add the values in a loop.",
      "evidence": {
        "url": "https://docs.mql4.com/indicators",
        "fragment": "Technical Indicator Functions table (iAC ... iWPR)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.sum",
      "language": "mql5",
      "source": "present",
      "construct": "vector::Sum",
      "signature": "double vector::Sum()",
      "relation": "equivalent_with_caveat",
      "note": "Totals a whole vector; a moving window means copying the last n values into a vector first.",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/matrix/matrix_statistics/matrix_sum",
        "fragment": "vector::Sum signature and Return Value",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.sum",
      "language": "ninjascript",
      "source": "present",
      "construct": "SUM",
      "signature": "SUM(ISeries<double> input, int period)[int barsAgo]",
      "relation": "exact",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/summation_sum.htm",
        "fragment": "Syntax: SUM(int period); sum of values over a specified period",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.sum",
      "language": "pine",
      "source": "present",
      "construct": "math.sum",
      "signature": "math.sum(source, length) → series float",
      "relation": "equivalent_with_caveat",
      "note": "Pine v6 has no ta.sum; the moving-window sum is math.sum(source, length). Lipi accepts either name.",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_math.sum",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.sum",
      "language": "thinkscript",
      "source": "present",
      "construct": "Sum",
      "signature": "Sum(IDataHolder data, int length = 12)",
      "relation": "equivalent_with_caveat",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Functions/Math---Trig/Sum",
        "fragment": "Sum ( IDataHolder data , int length ); length: 12",
        "accessed": "2026-11-01"
      },
      "verified": "documented",
      "note": "Sum's length defaults to 12, Lipi requires it, so a converter must insert 12 when omitted."
    },
    {
      "concept": "ta.supertrend",
      "language": "mql4",
      "source": "absent",
      "note": "No Supertrend among the indicator functions; build it from iATR and price.",
      "evidence": {
        "url": "https://docs.mql4.com/indicators",
        "fragment": "Technical Indicator Functions table (iAC ... iWPR)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.supertrend",
      "language": "mql5",
      "source": "absent",
      "note": "No Supertrend among the built-in indicators; it would come from a custom indicator via iCustom or your own code on iATR.",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/indicators",
        "fragment": "table of technical indicator functions (iAC ... iVolumes)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.supertrend",
      "language": "ninjascript",
      "source": "absent",
      "note": "No Supertrend in NinjaTrader's system indicator list; build it from ATR by hand.",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/indicators.htm",
        "fragment": "System Indicator Methods index: no Supertrend entry",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.supertrend",
      "language": "pine",
      "source": "present",
      "construct": "ta.supertrend",
      "signature": "ta.supertrend(factor, atrPeriod) → [series float, series float]",
      "relation": "equivalent_with_caveat",
      "note": "Same signs: -1 up-trend, 1 down-trend. Lipi takes multiplier, then ATR length; its direction is -1 on all but at most one early bar.",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_ta.supertrend (Returns: 1 down direction, -1 up direction)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.supertrend",
      "language": "thinkscript",
      "source": "absent",
      "note": "No Supertrend study or function in the functions list or the study library.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/Tech-Indicators/studies-library",
        "fragment": "study library index (no Supertrend entry)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.swma",
      "language": "mql4",
      "source": "absent",
      "note": "No symmetric weighted average; use iMA with MODE_LWMA or weight four bars by hand.",
      "evidence": {
        "url": "https://docs.mql4.com/indicators",
        "fragment": "Technical Indicator Functions table (iAC ... iWPR)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.swma",
      "language": "mql5",
      "source": "absent",
      "note": "No symmetrically weighted average among the built-in indicators; weight four bar values yourself.",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/indicators",
        "fragment": "table of technical indicator functions (iAC ... iVolumes)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.swma",
      "language": "ninjascript",
      "source": "absent",
      "note": "No symmetrically weighted average in the system list; code the 1-2-2-1 weights by hand.",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/indicators.htm",
        "fragment": "System Indicator Methods index: no SWMA entry",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.swma",
      "language": "pine",
      "source": "present",
      "construct": "ta.swma",
      "signature": "ta.swma(source) → series float",
      "relation": "equivalent_with_caveat",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_ta.swma",
        "accessed": "2026-11-01"
      },
      "verified": "documented",
      "note": "Same weights on clean data; Pine yields na for four bars after an na source value, Lipi keeps computing."
    },
    {
      "concept": "ta.swma",
      "language": "thinkscript",
      "source": "absent",
      "note": "No symmetrically weighted average; WMA weights linearly over a length you choose.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Functions/Tech-Analysis/WMA",
        "fragment": "WMA ( IDataHolder data , int length ); length: 9",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.tr",
      "language": "mql4",
      "source": "absent",
      "note": "No true-range function; derive it from High, Low and the previous Close, or use iATR.",
      "evidence": {
        "url": "https://docs.mql4.com/indicators",
        "fragment": "Technical Indicator Functions table (iAC ... iWPR)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.tr",
      "language": "mql5",
      "source": "absent",
      "note": "No true-range indicator; only the averaged iATR exists. Compute true range from high, low and previous close.",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/indicators",
        "fragment": "table of technical indicator functions (iATR present, no true range entry)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.tr",
      "language": "ninjascript",
      "source": "absent",
      "note": "No standalone true-range indicator; true range appears only inside the ATR page's description. Compute it from High, Low and the prior Close.",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/indicators.htm",
        "fragment": "System Indicator Methods index: ATR listed, no true range entry",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.tr",
      "language": "pine",
      "source": "present",
      "construct": "ta.tr",
      "signature": "ta.tr(handle_na) → series float; ta.tr (variable) → series float",
      "relation": "equivalent_with_caveat",
      "note": "Pine has both a variable ta.tr (same as ta.tr(false)) and the function; Lipi has only the function, so write the bare variable as ta.tr().",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_ta.tr and #var_ta.tr",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.tr",
      "language": "thinkscript",
      "source": "present",
      "construct": "TrueRange",
      "signature": "TrueRange(IDataHolder high, IDataHolder close, IDataHolder low)",
      "relation": "equivalent_with_caveat",
      "note": "Takes high, close and low series as explicit arguments and uses the previous close; Lipi ta.tr reads chart bars and has a handle_na option.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Functions/Tech-Analysis/TrueRange",
        "fragment": "TrueRange ( IDataHolder high , IDataHolder close , IDataHolder low )",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.tsi",
      "language": "mql4",
      "source": "absent",
      "note": "No True Strength Index among the indicator functions.",
      "evidence": {
        "url": "https://docs.mql4.com/indicators",
        "fragment": "Technical Indicator Functions table (iAC ... iWPR)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.tsi",
      "language": "mql5",
      "source": "absent",
      "note": "No True Strength Index among the built-in indicators.",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/indicators",
        "fragment": "table of technical indicator functions (iAC ... iVolumes)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.tsi",
      "language": "ninjascript",
      "source": "present",
      "construct": "TSI",
      "signature": "TSI(ISeries<double> input, int fast, int slow)[int barsAgo]",
      "relation": "equivalent_with_caveat",
      "note": "Arguments are fast then slow; the page does not map them onto Lipi's r and s, so check the pairing.",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/true_strength_index_tsi.htm",
        "fragment": "Syntax: TSI(int fast, int slow)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.tsi",
      "language": "pine",
      "source": "present",
      "construct": "ta.tsi",
      "signature": "ta.tsi(source, short_length, long_length) → series float",
      "relation": "different_semantics",
      "note": "Pine returns -1 to 1; Lipi multiplies by 100. Pine takes short then long length; Lipi takes r (long) then s (short).",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_ta.tsi",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.tsi",
      "language": "thinkscript",
      "source": "present",
      "construct": "TrueStrengthIndex",
      "signature": "TrueStrengthIndex(long length, short length, signal length, average type)",
      "relation": "equivalent_with_caveat",
      "note": "Study also yields a Signal average and takes an average type; the long length comes first, so map it to Lipi's r and s carefully.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/Tech-Indicators/studies-library/T-U/TrueStrengthIndex",
        "fragment": "Input Parameters: long length, short length, signal length, average type",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.valuewhen",
      "language": "mql4",
      "source": "absent",
      "note": "No built-in; loop back through the series and read the value where the condition held.",
      "evidence": {
        "url": "https://docs.mql4.com/indicators",
        "fragment": "Technical Indicator Functions table (iAC ... iWPR)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.valuewhen",
      "language": "mql5",
      "source": "absent",
      "note": "No value-when function; store the value in a variable each time the condition is true.",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/function_indices",
        "fragment": "List of MQL5 Functions (no ValueWhen entry)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.valuewhen",
      "language": "ninjascript",
      "source": "absent",
      "note": "No single method; read MRO's bars-ago result back into the series, for example Close[barsAgo], after a -1 check.",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/market_data.htm",
        "fragment": "Analytical index: Most Recent Occurrence (MRO) returns bars ago; no value-when entry",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.valuewhen",
      "language": "pine",
      "source": "present",
      "construct": "ta.valuewhen",
      "signature": "ta.valuewhen(condition, source, occurrence) → series color, int, float or bool",
      "relation": "equivalent_with_caveat",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_ta.valuewhen",
        "accessed": "2026-11-01"
      },
      "verified": "documented",
      "note": "Lipi's ta.valuewhen takes number sources only; Pine also accepts bool and color sources."
    },
    {
      "concept": "ta.valuewhen",
      "language": "thinkscript",
      "source": "absent",
      "note": "No value-when function. Build it with a recursive def variable that keeps its prior value until the condition is true.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Reserved-Words/rec",
        "fragment": "rec / recursion description",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.variance",
      "language": "mql4",
      "source": "absent",
      "note": "No variance function; square iStdDev or compute it in a loop.",
      "evidence": {
        "url": "https://docs.mql4.com/indicators",
        "fragment": "Technical Indicator Functions table (iAC ... iWPR)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.variance",
      "language": "mql5",
      "source": "present",
      "construct": "vector::Var, MathVariance",
      "signature": "double vector::Var(int ddof=0)",
      "relation": "equivalent_with_caveat",
      "note": "Divisor is N minus ddof: ddof 0 is the biased form, ddof 1 the unbiased. Fill the vector with the window first.",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/matrix/matrix_statistics/matrix_var",
        "fragment": "Var ddof: divisor N - ddof, default zero",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.variance",
      "language": "ninjascript",
      "source": "absent",
      "note": "No variance indicator; only StdDev and StdError exist, so square StdDev or compute by hand.",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/indicators.htm",
        "fragment": "System Indicator Methods index: StdDev, StdError, no variance entry",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.variance",
      "language": "pine",
      "source": "present",
      "construct": "ta.variance",
      "signature": "ta.variance(source, length, biased) → series float",
      "relation": "equivalent_with_caveat",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_ta.variance",
        "accessed": "2026-11-01"
      },
      "verified": "documented",
      "note": "Pine skips na values in the window; Lipi's ta.variance returns na on a bar whose source is na."
    },
    {
      "concept": "ta.variance",
      "language": "thinkscript",
      "source": "absent",
      "note": "No variance function; square StDev with Sqr. StDev divides by length, so the result is the biased (population) variance.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Functions/Math---Trig/Sqr",
        "fragment": "Example: variance as square of StDev",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.vwap",
      "language": "mql4",
      "source": "absent",
      "note": "No volume-weighted average price among the indicator functions.",
      "evidence": {
        "url": "https://docs.mql4.com/indicators",
        "fragment": "Technical Indicator Functions table (iAC ... iWPR)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.vwap",
      "language": "mql5",
      "source": "absent",
      "note": "No VWAP among the built-in indicators.",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/indicators",
        "fragment": "table of technical indicator functions (iAC ... iVolumes)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.vwap",
      "language": "ninjascript",
      "source": "present",
      "construct": "OrderFlowVWAP",
      "signature": "OrderFlowVWAP(ISeries<double> input, VWAPResolution resolution, TradingHours tradingHoursInstance, VWAPStandardDeviations numStandardDeviations, double sD1Multiplier, double sD2Multiplier, double sD3Multiplier).VWAP[int barsAgo]",
      "relation": "equivalent_with_caveat",
      "note": "Needs a resolution, a trading-hours template that sets the reset point, and deviation settings; deviation bands are separate series.",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/order_flow_vwap2.htm",
        "fragment": "Syntax: OrderFlowVWAP(resolution, tradingHoursInstance, numStandardDeviations, sD1Multiplier, ...).VWAP",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.vwap",
      "language": "pine",
      "source": "present",
      "construct": "ta.vwap",
      "signature": "ta.vwap(source, anchor) → series float; ta.vwap(source, anchor, stdev_mult) → [series float, series float, series float]; ta.vwap (variable, hlc3)",
      "relation": "equivalent_with_caveat",
      "note": "Pine resets on an anchor condition (default daily) and has a bare hlc3 variable and band overload; Lipi's takes only source with no anchor argument.",
      "differences": [
        {
          "axis": "state_and_side_effects",
          "note": "Pine's accumulation restarts on the anchor; Lipi offers no anchor control and its reset rule is undocumented."
        }
      ],
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_ta.vwap and #var_ta.vwap",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.vwap",
      "language": "thinkscript",
      "source": "present",
      "construct": "vwap",
      "signature": "vwap(String symbol = getSymbol(), Any period, String priceType)",
      "relation": "equivalent_with_caveat",
      "note": "Takes an aggregation period (day, week, month) that sets the reset window, plus symbol and price type; Lipi ta.vwap has only a source.",
      "differences": [
        {
          "axis": "htf_access",
          "note": "The period argument can read another aggregation or symbol; Lipi cannot."
        }
      ],
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Functions/Fundamentals/vwap",
        "fragment": "vwap ( String symbol , Any period , String priceType )",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.vwma",
      "language": "mql4",
      "source": "absent",
      "note": "No volume-weighted moving average among the indicator functions.",
      "evidence": {
        "url": "https://docs.mql4.com/indicators",
        "fragment": "Technical Indicator Functions table (iAC ... iWPR)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.vwma",
      "language": "mql5",
      "source": "absent",
      "note": "No volume-weighted moving average among the built-in indicators; iMA has no volume weighting.",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/constants/indicatorconstants/enum_ma_method",
        "fragment": "ENUM_MA_METHOD: MODE_SMA, MODE_EMA, MODE_SMMA, MODE_LWMA only",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.vwma",
      "language": "ninjascript",
      "source": "present",
      "construct": "VWMA",
      "signature": "VWMA(ISeries<double> input, int period)[int barsAgo]",
      "relation": "exact",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/moving_average_-_volume_weight.htm",
        "fragment": "Syntax: VWMA(int period)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.vwma",
      "language": "pine",
      "source": "present",
      "construct": "ta.vwma",
      "signature": "ta.vwma(source, length) → series float",
      "relation": "equivalent_with_caveat",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_ta.vwma",
        "accessed": "2026-11-01"
      },
      "verified": "documented",
      "note": "Pine's reference says na source values are ignored; Lipi's ta.vwma returns na on a bar whose source is na."
    },
    {
      "concept": "ta.vwma",
      "language": "thinkscript",
      "source": "absent",
      "note": "No volume-weighted moving average; build it as Sum(price*volume, n) divided by Sum(volume, n).",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/Tech-Indicators/studies-library",
        "fragment": "study library index (no VWMA entry; only VolumeWeightedMACD)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.wma",
      "language": "mql4",
      "source": "present",
      "construct": "iMA with MODE_LWMA",
      "signature": "double iMA(string symbol, int timeframe, int ma_period, int ma_shift, int ma_method, int applied_price, int shift)",
      "relation": "equivalent_with_caveat",
      "note": "One iMA covers four averages via ma_method (MODE_LWMA = 3). ma_shift offsets the line. Source is an applied-price constant, not any series.",
      "differences": [
        {
          "axis": "history_indexing",
          "note": "shift counts bars back from the current bar; shift 0 is the still-forming bar, and any shift can be read in one call."
        },
        {
          "axis": "htf_access",
          "note": "symbol and timeframe arguments read another symbol or period directly; Lipi ta calls use the chart's own bars."
        }
      ],
      "evidence": {
        "url": "https://docs.mql4.com/indicators/ima",
        "fragment": "ENUM_MA_METHOD MODE_LWMA (linear-weighted averaging)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.wma",
      "language": "mql5",
      "source": "present",
      "construct": "iMA with MODE_LWMA",
      "signature": "int iMA(string symbol, ENUM_TIMEFRAMES period, int ma_period, int ma_shift, ENUM_MA_METHOD ma_method, ENUM_APPLIED_PRICE applied_price)",
      "relation": "equivalent_with_caveat",
      "note": "MODE_LWMA is linear-weighted averaging, set through ma_method on iMA. An extra ma_shift shifts the line on the chart.",
      "differences": [
        {
          "axis": "state_and_side_effects",
          "note": "Returns a handle; values are read later with CopyBuffer and are not ready right after creation."
        },
        {
          "axis": "history_indexing",
          "note": "CopyBuffer start_pos 0 is the current bar and counts toward the past; copied data lands oldest-first."
        },
        {
          "axis": "htf_access",
          "note": "Symbol and timeframe are explicit arguments, so another symbol or timeframe is requested directly."
        }
      ],
      "evidence": {
        "url": "https://www.mql5.com/en/docs/constants/indicatorconstants/enum_ma_method",
        "fragment": "ENUM_MA_METHOD: MODE_LWMA Linear-weighted averaging",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.wma",
      "language": "ninjascript",
      "source": "present",
      "construct": "WMA",
      "signature": "WMA(ISeries<double> input, int period)[int barsAgo]",
      "relation": "different_semantics",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/moving_average_-_weighted_wma.htm",
        "fragment": "Syntax: WMA(int period)",
        "accessed": "2026-11-01"
      },
      "verified": "documented",
      "note": "At this build Lipi's ta.wma does not follow standard weights: a step from 0 to 1 settles at 1/length. Compare values before porting."
    },
    {
      "concept": "ta.wma",
      "language": "pine",
      "source": "present",
      "construct": "ta.wma",
      "signature": "ta.wma(source, length) → series float",
      "relation": "different_semantics",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_ta.wma",
        "accessed": "2026-11-01"
      },
      "verified": "documented",
      "note": "At this build Lipi's ta.wma does not follow standard weights: a step from 0 to 1 settles at 1/length. Compare values before porting."
    },
    {
      "concept": "ta.wma",
      "language": "thinkscript",
      "source": "present",
      "construct": "WMA",
      "signature": "WMA(IDataHolder data, int length = 9)",
      "relation": "different_semantics",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Functions/Tech-Analysis/WMA",
        "fragment": "WMA ( IDataHolder data , int length ); length: 9",
        "accessed": "2026-11-01"
      },
      "verified": "documented",
      "note": "WMA's length defaults to 9. At this build Lipi's ta.wma does not follow standard weights: a step from 0 to 1 settles at 1/length."
    },
    {
      "concept": "ta.wpr",
      "language": "mql4",
      "source": "present",
      "construct": "iWPR",
      "signature": "double iWPR(string symbol, int timeframe, int period, int shift)",
      "relation": "equivalent_with_caveat",
      "note": "Value is read at the shift you pass. Lipi's wpr reads the previous bar, so compare with a shift of 1.",
      "differences": [
        {
          "axis": "history_indexing",
          "note": "shift counts bars back from the current bar; shift 0 is the still-forming bar, and any shift can be read in one call."
        },
        {
          "axis": "bar_timing",
          "note": "Lipi's wpr lags the chart by one bar; iWPR has no stated lag."
        }
      ],
      "evidence": {
        "url": "https://docs.mql4.com/indicators/iwpr",
        "fragment": "iWPR",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.wpr",
      "language": "mql5",
      "source": "present",
      "construct": "iWPR",
      "signature": "int iWPR(string symbol, ENUM_TIMEFRAMES period, int calc_period)",
      "relation": "equivalent_with_caveat",
      "note": "One buffer, period is calc_period. Lipi's reference says its wpr lags one bar; CopyBuffer position 0 is the current bar's reading.",
      "differences": [
        {
          "axis": "bar_timing",
          "note": "Lipi's wpr reads the previous bar's values; here position 0 is the current bar."
        },
        {
          "axis": "state_and_side_effects",
          "note": "Returns a handle; values are read later with CopyBuffer and are not ready right after creation."
        },
        {
          "axis": "htf_access",
          "note": "Symbol and timeframe are explicit arguments, so another symbol or timeframe is requested directly."
        }
      ],
      "evidence": {
        "url": "https://www.mql5.com/en/docs/indicators/iwpr",
        "fragment": "iWPR signature (calc_period) and Return Value (handle)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.wpr",
      "language": "ninjascript",
      "source": "present",
      "construct": "WilliamsR",
      "signature": "WilliamsR(ISeries<double> input, int period)[int barsAgo]",
      "relation": "equivalent_with_caveat",
      "note": "Scale runs 0 to -100. Lipi's build reads the previous bar, so its value lags one bar; NinjaTrader documents no such lag.",
      "differences": [
        {
          "axis": "bar_timing",
          "note": "Lipi's value is the previous bar's reading."
        }
      ],
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/williams_r.htm",
        "fragment": "Syntax: WilliamsR(int period); scale 0 to -100",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.wpr",
      "language": "pine",
      "source": "present",
      "construct": "ta.wpr",
      "signature": "ta.wpr(length) → series float",
      "relation": "different_semantics",
      "note": "Pine reads the current bar's high, low and close. Lipi's build reads the previous bar's, so its value lags Pine's by one bar.",
      "differences": [
        {
          "axis": "bar_timing",
          "note": "Lipi shows %R as of the prior bar; Pine shows it for the current bar."
        }
      ],
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "fun_ta.wpr",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.wpr",
      "language": "thinkscript",
      "source": "present",
      "construct": "WilliamsPercentR",
      "signature": "WilliamsPercentR(length, over bought, over sold)",
      "relation": "different_semantics",
      "note": "The thinkScript formula uses highest and lowest including the current bar; Lipi ta.wpr is lagged one bar. Scale is 0 to -100 in both.",
      "differences": [
        {
          "axis": "bar_timing",
          "note": "thinkScript reads the current bar's high, low and close; Lipi reads the previous bar's values."
        }
      ],
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/thinkScript/Functions/Tech-Analysis/Lowest",
        "fragment": "Example: Williams %R built from Highest and Lowest including the current bar",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.wvad",
      "language": "mql4",
      "source": "absent",
      "note": "No Williams variable accumulation/distribution among the indicator functions.",
      "evidence": {
        "url": "https://docs.mql4.com/indicators",
        "fragment": "Technical Indicator Functions table (iAC ... iWPR)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.wvad",
      "language": "mql5",
      "source": "absent",
      "note": "No Williams variable accumulation/distribution among the built-in indicators (iAD and iBWMFI are different indicators).",
      "evidence": {
        "url": "https://www.mql5.com/en/docs/indicators",
        "fragment": "table of technical indicator functions (iAC ... iVolumes)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.wvad",
      "language": "ninjascript",
      "source": "absent",
      "note": "No Williams variable accumulation/distribution in the system list; code it by hand.",
      "evidence": {
        "url": "https://ninjatrader.com/support/helpGuides/nt8/indicators.htm",
        "fragment": "System Indicator Methods index: no WVAD entry",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.wvad",
      "language": "pine",
      "source": "present",
      "construct": "ta.wvad",
      "signature": "ta.wvad → series float (a variable)",
      "relation": "equivalent_with_caveat",
      "note": "Pine ta.wvad is a variable with no arguments; Lipi calls ta.wvad(length) and ignores length. Both give the per-bar (close-open)/(high-low)*volume.",
      "evidence": {
        "url": "https://www.tradingview.com/pine-script-reference/v6/",
        "fragment": "var_ta.wvad (example gives the same as (close - open) / (high - low) * volume)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    },
    {
      "concept": "ta.wvad",
      "language": "thinkscript",
      "source": "absent",
      "note": "No Williams variable accumulation/distribution; WilliamsAD is the different Williams Accumulation/Distribution study.",
      "evidence": {
        "url": "https://toslc.thinkorswim.com/center/reference/Tech-Indicators/studies-library",
        "fragment": "study library index (WilliamsAD only, no variable AD entry)",
        "accessed": "2026-11-01"
      },
      "verified": "documented"
    }
  ]
}
