How to Create an Indicator in TradingView from Scratch
A custom TradingView indicator turns a defined calculation into a chart output. The simplest useful starting point is a moving average with an editable length and source. This guide uses Pine Script v6 and a complete example you can inspect against TradingView's built-in moving average.
Open Pine Editor and Create an Indicator
Open Pine Editor from the chart's toolbar and choose a new indicator. Its position can differ with the selected editor layout; consult the current editor guide if you cannot find it.
Replace the template with this complete script:
//@version=6
indicator("First Custom SMA", overlay=true)
length = input.int(20, "MA length", minval=1)
source = input.source(close, "Source")
smaValue = ta.sma(source, length)
plot(smaValue, "SMA", color.blue, linewidth=2)
Save it and select Add to chart. Saving your working script is separate from publishing it to the community. TradingView's first-indicator tutorial explains this workflow.
Understand Each Part
| Part | Purpose |
|---|---|
| Version annotation | Selects Pine v6 language rules |
| Indicator declaration | Names the script and places its output on the main chart |
| Length input | Creates an editable integer setting with a positive minimum |
| Source input | Lets you choose the series used in the calculation |
| SMA calculation | Computes the average over the selected length |
| Plot | Draws the resulting series |
The script-structure documentation specifies that an omitted version annotation defaults to version 1. It does not necessarily produce an immediate error, but modern code should declare its intended version. Pine v5 is not the latest language version.
Verify the Output
Add TradingView's built-in Moving Average to the same chart. Set both to the same length and source, then compare values on several historical bars. Change only one input at a time. Record the symbol, interval and session when comparing results.
The initial bars may not have enough history for the selected length. On an open realtime bar, a close-based moving average can change with the price. That is expected behavior; a historical screenshot cannot demonstrate realtime stability.
If no line appears, check compilation/runtime messages, visibility settings, the selected price scale and available history. A large length can delay initialization. It is not inherently invalid or guaranteed to miss every reversal.
Inputs, Style and Pane Placement
Open the indicator's settings to change the exposed inputs. Style controls change the plot's presentation. Inputs only exist when the script defines them; not every indicator has a source selector.
Price-related averages are often easier to compare as overlays. Oscillators with a separate numerical range are often easier to read in their own pane. Placement is a design choice, not a statement about predictive accuracy.
Pineify offers a visual workflow for generating indicator logic. Review the output and compare calculations in TradingView, just as you would with a handwritten script.
Add Signals Only After the Calculation Is Clear
A buy/sell marker requires a precise condition and a decision about whether to wait for bar close. An indicator does not create a Strategy Tester performance report by itself. To evaluate simulated returns, define entries, exits, sizing and costs in a strategy and inspect its execution assumptions.
Public availability also does not mean source availability. Open-source publications allow source inspection; protected and invite-only scripts have different access controls. Respect the author's license and TradingView's publication types.
FAQ
Does an indicator place broker orders? No. This example only calculates and plots an average.
Can I edit every community script? No. You need accessible source and appropriate permission. Create a working copy when the source is available.
Does a line that matches historical prices prove a trading advantage? No. Calculation correctness and trading performance are separate questions.
Should I replace every variable with var for speed?
No. Persistent variables change initialization behavior. Use them only when the intended calculation requires persistence, not as a blanket optimization.

