Indicator · Pine Script v6 · On the chart

Portfolio Tracker

by etnt· code credited to kruskakli

This indicator tracks and displays open portfolio positions in an on-chart table overlay.

View on GitHub

GitHub stars2on the repository
Pine versionv6current
Lines of code190
Settings21inputs
LicenceMPL-2.0
Last update1 year ago3 Aug 2025

Add It to Your TradingView Chart

  1. 1Copy the scriptPress Copy script above, or the copy button on the code below.
  2. 2Open the Pine EditorOpen a TradingView chart and choose Pine Editor at the bottom of the screen.
  3. 3Paste over the templateCreate a new indicator, select all of the template text and paste. Press Save and give it a name.
  4. 4Add it to the chartPress Add to chart, then adjust the settings with the gear icon next to its name.

Source Code

190 lines of Pine Script v6 from PineScript/portfolio-tracker.pine, published under MPL-2.0. Keep the author's credit and licence lines when you reuse it.

portfolio-tracker.pine
// This Pine Script™ code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © kruskakli
//
// Portfolio Tracker
// This indicator allows you to track up to 10 stocks in your portfolio by displaying:
// - Entry price for each position
// - Current price for each position
// - Percentage change from entry
// 
// Features:
// - Support for up to 10 different symbols
// - Color-coded percentage changes (green for positive, red for negative)
// - Configurable table position (Upper Right, Middle Right, Lower Right)
// - Easy input of symbols and their entry prices
// - Real-time price tracking and percentage change calculations
//
//@version=6
indicator("Portfolio Tracker", overlay=true)

// Table styling
var columns = 4
var int rows = 1

var text_size = size.small
var pos_color = color.new(color.green, 0)
var neg_color = color.new(color.red, 0)
var header_color = color.new(color.yellow, 0)
var text_color = color.new(color.white, 0)


// Input for portfolio positions - 10 stocks
sym1 = input.symbol("", "Stock 1 Symbol", confirm=true)
var float price1 = input.float(0.0, "Stock 1 Buy Price", minval=0.0)
if (sym1 != "")
    rows := rows + 1

sym2 = input.symbol("", "Stock 2 Symbol", confirm=true)
var float price2 = input.float(0.0, "Stock 2 Buy Price", minval=0.0)
if (sym2 != "")
    rows := rows + 1


sym3 = input.symbol("", "Stock 3 Symbol", confirm=true)
var float price3 = input.float(0.0, "Stock 3 Buy Price", minval=0.0)
if (sym3 != "")
    rows := rows + 1


sym4 = input.symbol("", "Stock 4 Symbol", confirm=true)
var float price4 = input.float(0.0, "Stock 4 Buy Price", minval=0.0)
if (sym4 != "")
    rows := rows + 1

sym5 = input.symbol("", "Stock 5 Symbol", confirm=true)
var float price5 = input.float(0.0, "Stock 5 Buy Price", minval=0.0)
if (sym5 != "")
    rows := rows + 1

sym6 = input.symbol("", "Stock 6 Symbol", confirm=true)
var float price6 = input.float(0.0, "Stock 6 Buy Price", minval=0.0)
if (sym6 != "")
    rows := rows + 1

sym7 = input.symbol("", "Stock 7 Symbol", confirm=true)
var float price7 = input.float(0.0, "Stock 7 Buy Price", minval=0.0)
if (sym7 != "")
    rows := rows + 1

sym8 = input.symbol("", "Stock 8 Symbol", confirm=true)
var float price8 = input.float(0.0, "Stock 8 Buy Price", minval=0.0)
if (sym8 != "")
    rows := rows + 1

sym9 = input.symbol("", "Stock 9 Symbol", confirm=true)
var float price9 = input.float(0.0, "Stock 9 Buy Price", minval=0.0)
if (sym9 != "")
    rows := rows + 1

sym10 = input.symbol("", "Stock 10 Symbol", confirm=true)
var float price10 = input.float(0.0, "Stock 10 Buy Price", minval=0.0)
if (sym10 != "")
    rows := rows + 1


// Function to calculate percentage change
calc_percent_change(current, entry) =>
    100.0 * ((current / entry) - 1.0)

// Create table
tabLoc = input.string(title="Table Location", defval="Upper Right", options=["Upper Right","Middle Right","Lower Right"])
tabPos = (tabLoc == "Upper Right") ? position.top_right : (tabLoc == "Middle Right") ? position.middle_right : position.bottom_right
var table t = table.new(position=tabPos, columns=columns, rows=rows, bgcolor=color.new(color.black, 60), border_width=1)

// Update table on each bar
if barstate.islast
    // Set headers
    table.cell(t, 0, 0, "Symbol", bgcolor=color.new(color.black, 0), text_color=header_color, text_size=text_size, text_halign=text.align_left)
    table.cell(t, 1, 0, "Entry", bgcolor=color.new(color.black, 0), text_color=header_color, text_size=text_size, text_halign=text.align_right)
    table.cell(t, 2, 0, "Current", bgcolor=color.new(color.black, 0), text_color=header_color, text_size=text_size, text_halign=text.align_right)
    table.cell(t, 3, 0, "% Change", bgcolor=color.new(color.black, 0), text_color=header_color, text_size=text_size, text_halign=text.align_right)

    // Stock 1
    if str.length(sym1) > 0 and price1 > 0
        current1 = request.security(sym1, timeframe.period, close)
        pct1 = calc_percent_change(current1, price1)
        table.cell(t, 0, 1, sym1, text_color=text_color, text_size=text_size, text_halign=text.align_left)
        table.cell(t, 1, 1, str.tostring(price1, "#.##"), text_color=text_color, text_size=text_size, text_halign=text.align_right)
        table.cell(t, 2, 1, str.tostring(current1, "#.##"), text_color=text_color, text_size=text_size, text_halign=text.align_right)
        table.cell(t, 3, 1, str.tostring(pct1, "#.##") + "%", text_color=(pct1 >= 0 ? pos_color : neg_color), text_size=text_size, text_halign=text.align_right)

    // Stock 2
    if str.length(sym2) > 0 and price2 > 0
        current2 = request.security(sym2, timeframe.period, close)
        pct2 = calc_percent_change(current2, price2)
        table.cell(t, 0, 2, sym2, text_color=text_color, text_size=text_size, text_halign=text.align_left)
        table.cell(t, 1, 2, str.tostring(price2, "#.##"), text_color=text_color, text_size=text_size, text_halign=text.align_right)
        table.cell(t, 2, 2, str.tostring(current2, "#.##"), text_color=text_color, text_size=text_size, text_halign=text.align_right)
        table.cell(t, 3, 2, str.tostring(pct2, "#.##") + "%", text_color=(pct2 >= 0 ? pos_color : neg_color), text_size=text_size, text_halign=text.align_right)

    // Stock 3
    if str.length(sym3) > 0 and price3 > 0
        current3 = request.security(sym3, timeframe.period, close)
        pct3 = calc_percent_change(current3, price3)
        table.cell(t, 0, 3, sym3, text_color=text_color, text_size=text_size, text_halign=text.align_left)
        table.cell(t, 1, 3, str.tostring(price3, "#.##"), text_color=text_color, text_size=text_size, text_halign=text.align_right)
        table.cell(t, 2, 3, str.tostring(current3, "#.##"), text_color=text_color, text_size=text_size, text_halign=text.align_right)
        table.cell(t, 3, 3, str.tostring(pct3, "#.##") + "%", text_color=(pct3 >= 0 ? pos_color : neg_color), text_size=text_size, text_halign=text.align_right)

    // Stock 4
    if str.length(sym4) > 0 and price4 > 0
        current4 = request.security(sym4, timeframe.period, close)
        pct4 = calc_percent_change(current4, price4)
        table.cell(t, 0, 4, sym4, text_color=text_color, text_size=text_size, text_halign=text.align_left)
        table.cell(t, 1, 4, str.tostring(price4, "#.##"), text_color=text_color, text_size=text_size, text_halign=text.align_right)
        table.cell(t, 2, 4, str.tostring(current4, "#.##"), text_color=text_color, text_size=text_size, text_halign=text.align_right)
        table.cell(t, 3, 4, str.tostring(pct4, "#.##") + "%", text_color=(pct4 >= 0 ? pos_color : neg_color), text_size=text_size, text_halign=text.align_right)

    // Stock 5
    if str.length(sym5) > 0 and price5 > 0
        current5 = request.security(sym5, timeframe.period, close)
        pct5 = calc_percent_change(current5, price5)
        table.cell(t, 0, 5, sym5, text_color=text_color, text_size=text_size, text_halign=text.align_left)
        table.cell(t, 1, 5, str.tostring(price5, "#.##"), text_color=text_color, text_size=text_size, text_halign=text.align_right)
        table.cell(t, 2, 5, str.tostring(current5, "#.##"), text_color=text_color, text_size=text_size, text_halign=text.align_right)
        table.cell(t, 3, 5, str.tostring(pct5, "#.##") + "%", text_color=(pct5 >= 0 ? pos_color : neg_color), text_size=text_size, text_halign=text.align_right)

    // Stock 6
    if str.length(sym6) > 0 and price6 > 0
        current6 = request.security(sym6, timeframe.period, close)
        pct6 = calc_percent_change(current6, price6)
        table.cell(t, 0, 6, sym6, text_color=text_color, text_size=text_size, text_halign=text.align_left)
        table.cell(t, 1, 6, str.tostring(price6, "#.##"), text_color=text_color, text_size=text_size, text_halign=text.align_right)
        table.cell(t, 2, 6, str.tostring(current6, "#.##"), text_color=text_color, text_size=text_size, text_halign=text.align_right)
        table.cell(t, 3, 6, str.tostring(pct6, "#.##") + "%", text_color=(pct6 >= 0 ? pos_color : neg_color), text_size=text_size, text_halign=text.align_right)

    // Stock 7
    if str.length(sym7) > 0 and price7 > 0
        current7 = request.security(sym7, timeframe.period, close)
        pct7 = calc_percent_change(current7, price7)
        table.cell(t, 0, 7, sym7, text_color=text_color, text_size=text_size, text_halign=text.align_left)
        table.cell(t, 1, 7, str.tostring(price7, "#.##"), text_color=text_color, text_size=text_size, text_halign=text.align_right)
        table.cell(t, 2, 7, str.tostring(current7, "#.##"), text_color=text_color, text_size=text_size, text_halign=text.align_right)
        table.cell(t, 3, 7, str.tostring(pct7, "#.##") + "%", text_color=(pct7 >= 0 ? pos_color : neg_color), text_size=text_size, text_halign=text.align_right)

    // Stock 8
    if str.length(sym8) > 0 and price8 > 0
        current8 = request.security(sym8, timeframe.period, close)
        pct8 = calc_percent_change(current8, price8)
        table.cell(t, 0, 8, sym8, text_color=text_color, text_size=text_size, text_halign=text.align_left)
        table.cell(t, 1, 8, str.tostring(price8, "#.##"), text_color=text_color, text_size=text_size, text_halign=text.align_right)
        table.cell(t, 2, 8, str.tostring(current8, "#.##"), text_color=text_color, text_size=text_size, text_halign=text.align_right)
        table.cell(t, 3, 8, str.tostring(pct8, "#.##") + "%", text_color=(pct8 >= 0 ? pos_color : neg_color), text_size=text_size, text_halign=text.align_right)

    // Stock 9
    if str.length(sym9) > 0 and price9 > 0
        current9 = request.security(sym9, timeframe.period, close)
        pct9 = calc_percent_change(current9, price9)
        table.cell(t, 0, 9, sym9, text_color=text_color, text_size=text_size, text_halign=text.align_left)
        table.cell(t, 1, 9, str.tostring(price9, "#.##"), text_color=text_color, text_size=text_size, text_halign=text.align_right)
        table.cell(t, 2, 9, str.tostring(current9, "#.##"), text_color=text_color, text_size=text_size, text_halign=text.align_right)
        table.cell(t, 3, 9, str.tostring(pct9, "#.##") + "%", text_color=(pct9 >= 0 ? pos_color : neg_color), text_size=text_size, text_halign=text.align_right)

    // Stock 10
    if str.length(sym10) > 0 and price10 > 0
        current10 = request.security(sym10, timeframe.period, close)
        pct10 = calc_percent_change(current10, price10)
        table.cell(t, 0, 10, sym10, text_color=text_color, text_size=text_size, text_halign=text.align_left)
        table.cell(t, 1, 10, str.tostring(price10, "#.##"), text_color=text_color, text_size=text_size, text_halign=text.align_right)
        table.cell(t, 2, 10, str.tostring(current10, "#.##"), text_color=text_color, text_size=text_size, text_halign=text.align_right)
        table.cell(t, 3, 10, str.tostring(pct10, "#.##") + "%", text_color=(pct10 >= 0 ? pos_color : neg_color), text_size=text_size, text_halign=text.align_right)

Overview

Portfolio Tracker monitors up to ten user-defined symbols alongside their respective buy prices, retrieving current market prices and calculating the unrealized percentage change for each position. Values are color-coded in green for gains and red for losses. Main settings allow customization of ticker symbols, entry prices, and table placement on the screen. It performs purely informational tracking and does not generate trade alerts or execution signals.

Details

Published by

etnt on GitHub

Code credit

kruskakli, as written in the script's header

Type

Indicator, Pine Script v6

Draws

On the price chart

Category

Screeners & dashboards

Markets

Stocks

Timeframes

Any timeframe

Risk Notes

No repainting, lookahead or stacked entries were found in its code or README. That says nothing about how well it works: test it first.

Settings

The inputs you can change from the gear icon on the chart. Defaults are the author's.

SettingTypeDefaultVariable
Stock 1 Symbolsymbolsym1
Stock 1 Buy Pricefloat0.0price1
Stock 2 Symbolsymbolsym2
Stock 2 Buy Pricefloat0.0price2
Stock 3 Symbolsymbolsym3
Stock 3 Buy Pricefloat0.0price3
Stock 4 Symbolsymbolsym4
Stock 4 Buy Pricefloat0.0price4
Stock 5 Symbolsymbolsym5
Stock 5 Buy Pricefloat0.0price5
Stock 6 Symbolsymbolsym6
Stock 6 Buy Pricefloat0.0price6
Show all 21 settings
SettingTypeDefaultVariable
Stock 7 Symbolsymbolsym7
Stock 7 Buy Pricefloat0.0price7
Stock 8 Symbolsymbolsym8
Stock 8 Buy Pricefloat0.0price8
Stock 9 Symbolsymbolsym9
Stock 9 Buy Pricefloat0.0price9
Stock 10 Symbolsymbolsym10
Stock 10 Buy Pricefloat0.0price10
Table LocationstringUpper RighttabLoc
Third-party code. ForexR did not write, test or endorse this script, and the summary above was generated automatically from its code and README. Indicators describe the past, and a strategy's backtest can look better than live trading, especially when a script repaints. Check it in the Strategy Tester and on a demo account before you rely on it.

Similar Pine Scripts

Symbol Info Helper

by everget
948 stars

Symbol Info Helper is an informational utility script that displays metadata about the currently selected instrument directly on the main price chart. It gathers built-in symbol properties including ticker identifier, description, instrument type, point value,

Indicator v4 Screeners & dashboards
Updated 10 days ago · GPL-3.0 GitHub repository of Symbol Info Helper
575 stars

The indicator plots ICT displacement candles on the price chart and can switch to retracement scanning. Displacement requires a move larger than a set share of the 14-bar average high-low range, lasting at least a chosen number of bars, with optional close, pr

Indicator v6 SMC / ICT / price actionCandlestick patterns
Updated 1 year ago · MPL-2.0 GitHub repository of ICT Displacement Candles Indicator
330 stars

This indicator monitors multiple cryptocurrency symbols for trading signals. It calculates and plots entry prices, take profit, and stop loss levels for each symbol including BTCUSDT, ETHUSDT, BNBUSDT and others. Price crossovers trigger buy, sell or close ale

Indicator v5 Support & resistanceScreeners & dashboards
Updated 2 months ago · None stated GitHub repository of Multi Alert Long/Short [Alorse]

Pricing Table

by namuan
318 stars

This indicator calculates theoretical options contract values and in-the-money probabilities using historical realized volatility across multiple standard deviations. It displays these metrics in a table overlay directly on the price chart. Users can adjust th

Indicator v4 Volatility & bandsScreeners & dashboards
Updated 2 months ago · MIT GitHub repository of Pricing Table

3938 Tracker

by Allen1212
303 stars

3938 Tracker visualizes historical buying and selling activity from ARK Invest funds directly on the main price chart. It plots labels at specific timestamps corresponding to trade dates, indicating buy or sell actions along with the count of participating ETF

Indicator v4 Screeners & dashboards
Updated 2 years ago · None stated GitHub repository of 3938 Tracker

More indicators

Trade Your Charts With a Regulated Broker

Compare brokers that connect to TradingView, with spreads, minimum deposits and leverage side by side.

Compare brokers