Start Here

3 AI-Generated TradingView Indicators I Actually Use

intermediate 20 min · · By Alpha Guy · claude-code cursor pine-script

Most AI-Generated Indicators Are Garbage

I need to be honest about this upfront. Over the past few months, I have generated somewhere north of 40 Pine Script indicators using Claude Code and Cursor. I loaded them onto TradingView charts, watched them for a few sessions, and deleted most of them within a week.

The failure modes are predictable. Some indicators repaint — they change their signals after the candle closes, which makes backtesting useless and live trading misleading. Others are so noisy that they fire on every other candle, which defeats the purpose of having a filter. A few were technically interesting but practically useless because they lagged too far behind price action to help with entry timing.

Out of all that experimentation, three indicators survived. They are still on my charts today. Not because they are magic, but because each one does a specific job well enough to be worth the screen space.

I am sharing the full Pine Script v5 code for all three (see the Pine Script language reference for function details). You can paste them directly into TradingView. But I also want to explain why these particular indicators made the cut and what criteria I use to evaluate AI-generated indicators in general.

Indicator 1: Smart EMA Ribbon with Trend Strength

What It Does

This is a multi-EMA ribbon (8, 13, 21, 34, 55) that does something most ribbons do not: it changes color based on how aligned the EMAs are. When all five EMAs are stacked in order (shortest on top for uptrend, shortest on bottom for downtrend), the ribbon turns bright green or red. When the EMAs are tangled and crossing each other, the ribbon turns gray.

That gray state is the most useful part. It tells me “this is a choppy mess, stay out” — which is information I consistently failed to act on before I had it visualized.

The AI Prompt That Generated It

I used Claude Code for this one. Here is the prompt, roughly:

Write a TradingView Pine Script v5 indicator that:
1. Plots 5 EMAs: 8, 13, 21, 34, 55
2. Fills the space between the outermost EMAs
3. The fill color should indicate trend strength:
   - Bright green when all EMAs are perfectly stacked bullish (8 > 13 > 21 > 34 > 55)
   - Bright red when all EMAs are perfectly stacked bearish (8 < 13 < 21 < 34 < 55)
   - Gray/transparent when EMAs are mixed (choppy market)
4. Add a "trend strength" score from 0-100 and display it as a label
5. Make all EMA periods configurable via inputs

Claude Code got it about 80% right on the first pass. The initial version had a bug where the trend strength score was always showing 100 or 0 with nothing in between. I had to go back and ask it to calculate the score as a percentage of how many EMA pairs are in the correct order (there are 10 possible pairs from 5 EMAs). That second iteration worked.

Full Pine Script v5 Code

//@version=5
indicator("Smart EMA Ribbon", overlay=true)

// Inputs
ema1Len = input.int(8, "EMA 1", minval=1)
ema2Len = input.int(13, "EMA 2", minval=1)
ema3Len = input.int(21, "EMA 3", minval=1)
ema4Len = input.int(34, "EMA 4", minval=1)
ema5Len = input.int(55, "EMA 5", minval=1)

// EMA calculations
ema1 = ta.ema(close, ema1Len)
ema2 = ta.ema(close, ema2Len)
ema3 = ta.ema(close, ema3Len)
ema4 = ta.ema(close, ema4Len)
ema5 = ta.ema(close, ema5Len)

// Trend strength: count how many of the 10 pairs are in bullish order
bullPairs = 0
bullPairs += ema1 > ema2 ? 1 : 0
bullPairs += ema1 > ema3 ? 1 : 0
bullPairs += ema1 > ema4 ? 1 : 0
bullPairs += ema1 > ema5 ? 1 : 0
bullPairs += ema2 > ema3 ? 1 : 0
bullPairs += ema2 > ema4 ? 1 : 0
bullPairs += ema2 > ema5 ? 1 : 0
bullPairs += ema3 > ema4 ? 1 : 0
bullPairs += ema3 > ema5 ? 1 : 0
bullPairs += ema4 > ema5 ? 1 : 0

trendScore = bullPairs * 10  // 0 to 100

// Determine ribbon color
ribbonColor = trendScore >= 80 ? color.new(color.green, 40) :
              trendScore <= 20 ? color.new(color.red, 40) :
              color.new(color.gray, 70)

// Plot EMAs
p1 = plot(ema1, "EMA 8", color=color.new(color.white, 80), linewidth=1)
p2 = plot(ema2, "EMA 13", color=color.new(color.white, 80), linewidth=1)
p3 = plot(ema3, "EMA 21", color=color.new(color.white, 80), linewidth=1)
p4 = plot(ema4, "EMA 34", color=color.new(color.white, 80), linewidth=1)
p5 = plot(ema5, "EMA 55", color=color.new(color.white, 80), linewidth=1)

// Fill between outermost EMAs
fill(p1, p5, color=ribbonColor)

// Trend strength label (shows every 50 bars to reduce clutter)
if bar_index % 50 == 0
    labelColor = trendScore >= 80 ? color.green :
                 trendScore <= 20 ? color.red : color.gray
    label.new(bar_index, ema1, str.tostring(trendScore),
        style=label.style_label_down, color=labelColor,
        textcolor=color.white, size=size.small)

How I Use It

I keep this on the 4H timeframe for BTC/USDT and ETH/USDT. The main signal I look for is the transition from gray to green or red. When the ribbon has been gray (choppy) for multiple sessions and then all EMAs align, that transition often coincides with the start of a directional move.

I do not trade the ribbon in isolation. It is a context filter. If the ribbon is gray, I do not take trend-following trades. If it is green and the trend score is above 80, I look for pullback entries on lower timeframes. If it is red with a score below 20, I look for short setups or stay in stablecoins.

What this looks like on a chart: imagine the space between the fastest and slowest EMA filled with a wash of color. During a clean BTC rally, the entire ribbon is a translucent green cloud with price riding above it. During chop, the EMAs criss-cross and the fill turns a dim gray — visually, the chart looks “noisy,” which matches how it actually trades.

Indicator 2: Volume Anomaly Detector

What It Does

This indicator calculates the simple moving average of volume over the last 20 periods and flags any bar where volume exceeds a configurable multiple of that average (default is 2x). When a volume spike occurs, it draws a colored column behind the bar — green if the close was above the open (bullish volume), red if it was bearish.

It sounds simple, and it is. That is precisely why it works. I tried getting AI to build more sophisticated volume indicators with Bollinger Bands on volume, VWAP deviations, and on-balance volume derivatives. All of them added complexity without adding clarity.

Why Volume Anomalies Matter for Crypto

Crypto markets are thin relative to equities. A sudden 3x or 4x volume spike on a 15-minute candle almost always means something happened — a whale moved, a liquidation cascade fired, or news broke. I do not need the indicator to tell me what happened. I need it to tell me that something happened so I pay attention to that candle instead of scrolling past it.

The other reason is that volume precedes price in many setups. A sustained series of above-average volume bars during a range often signals accumulation or distribution before the range breaks. This indicator makes those patterns immediately visible.

The AI Prompt

I used Cursor for this one. The prompt was straightforward:

Pine Script v5 indicator:
- Calculate 20-period SMA of volume
- Input: volume multiplier threshold (default 2.0)
- When current volume > SMA * multiplier, highlight the bar background
- Green background if bullish candle (close > open)
- Red background if bearish candle (close < open)
- Plot the volume SMA as a line in a separate pane
- Plot the current volume as columns, colored by candle direction
- Add a label showing the exact volume multiple (e.g. "3.2x") on anomaly bars

Cursor nailed this on the first try. I only made one manual edit: I reduced the label size from size.normal to size.tiny because the labels were cluttering the chart.

Full Code

//@version=5
indicator("Volume Anomaly Detector", format=format.volume)

// Inputs
volPeriod = input.int(20, "Volume SMA Period", minval=1)
volMultiplier = input.float(2.0, "Anomaly Threshold (x)", minval=1.0, step=0.1)

// Volume calculations
volSma = ta.sma(volume, volPeriod)
isAnomaly = volume > volSma * volMultiplier
isBullish = close > open

// Volume columns
volColor = isBullish ? color.new(color.green, 30) : color.new(color.red, 30)
plot(volume, "Volume", color=volColor, style=plot.style_columns)

// SMA line
plot(volSma, "Volume SMA", color=color.new(color.white, 40), linewidth=2)

// Threshold line
plot(volSma * volMultiplier, "Anomaly Threshold",
    color=color.new(color.yellow, 60), linewidth=1, style=plot.style_cross)

// Background highlight on anomaly
bgColor = isAnomaly and isBullish ? color.new(color.green, 85) :
          isAnomaly and not isBullish ? color.new(color.red, 85) :
          na
bgcolor(bgColor)

// Label showing volume multiple
if isAnomaly
    multiple = volume / volSma
    lbl = str.tostring(multiple, "#.#") + "x"
    labelColor = isBullish ? color.green : color.red
    label.new(bar_index, volume, lbl,
        style=label.style_label_down, color=labelColor,
        textcolor=color.white, size=size.tiny)

How I Combine It with Other Signals

The Volume Anomaly Detector lives on my main chart as a lower pane indicator. Here is my actual workflow:

  1. I scan my watchlist charts and look for volume anomaly labels (the “2.3x” or “3.1x” markers).
  2. If I see an anomaly on a candle that is also touching a key support or resistance level, I pay attention.
  3. I check the EMA Ribbon on the same chart. If the ribbon is aligned (green or red) and a volume anomaly appears in the direction of the trend, that is a higher-conviction signal.
  4. I never trade a volume anomaly against the trend. A 3x volume bullish candle during a bearish ribbon has historically been a trap more often than a reversal, at least in my experience.

One thing I got wrong initially: I set the threshold too low at 1.5x. On crypto pairs, especially during Asian session hours, volume fluctuates enough that 1.5x triggers too often. I bumped it to 2.0x and the signal quality improved noticeably. On smaller-cap altcoins, I sometimes raise it to 2.5x or 3.0x because their volume profiles are even spikier.

Indicator 3: Multi-Timeframe RSI Dashboard

What It Does

This is a panel indicator (not overlaid on the chart) that shows the current RSI value for five timeframes simultaneously: 15 minutes, 1 hour, 4 hours, daily, and weekly. Each RSI value is color-coded: green below 30 (oversold), red above 70 (overbought), and white in between. It also draws horizontal reference lines at 30, 50, and 70.

The insight is simple: when RSI is overbought or oversold on multiple timeframes at once, the signal is much stronger than any single timeframe reading. I used to flip between timeframes manually to check this, which was slow and error-prone. Having it all in one panel changed how quickly I can assess a setup.

The AI Prompt and Iteration History

This one took three iterations with Claude Code, and I want to be transparent about that.

Attempt 1: I asked for a table-style panel using Pine Script’s table object. Claude Code generated code that compiled, but the table overlapped with the price chart in an unreadable way. Adjusting position and size parameters did not fully fix it.

Attempt 2: I switched to asking for a separate pane indicator using plot and hline. This worked visually but only showed one timeframe’s RSI as a line. Showing five lines in one pane was too cluttered.

Attempt 3: I asked Claude Code to use the table object but place it in a separate pane indicator (using overlay=false), with each timeframe as a row. This is the version that stuck. The prompt:

Pine Script v5 indicator (overlay=false):
- Create a table in the bottom-right of the pane
- 6 rows, 3 columns: Timeframe | RSI Value | Status
- Row 1 header: "TF", "RSI", "Signal"
- Row 2: 15m RSI
- Row 3: 1H RSI
- Row 4: 4H RSI
- Row 5: 1D RSI
- Row 6: 1W RSI
- RSI period: configurable, default 14
- Color the RSI cell green if < 30, red if > 70, white otherwise
- Color the Signal cell with text: "OVERSOLD", "OVERBOUGHT", or "-"
- Use request.security() for multi-timeframe data
- Also plot the current timeframe RSI as a line for reference

Full Code

//@version=5
indicator("MTF RSI Dashboard", overlay=false)

// Inputs
rsiLen = input.int(14, "RSI Period", minval=1)
obLevel = input.int(70, "Overbought Level")
osLevel = input.int(30, "Oversold Level")

// Current timeframe RSI (plotted as line)
currentRsi = ta.rsi(close, rsiLen)
plot(currentRsi, "Current TF RSI", color=color.new(color.aqua, 0), linewidth=2)
hline(obLevel, "Overbought", color=color.red, linestyle=hline.style_dashed)
hline(50, "Midline", color=color.gray, linestyle=hline.style_dotted)
hline(osLevel, "Oversold", color=color.green, linestyle=hline.style_dashed)

// Multi-timeframe RSI values
rsi15 = request.security(syminfo.tickerid, "15", ta.rsi(close, rsiLen))
rsi60 = request.security(syminfo.tickerid, "60", ta.rsi(close, rsiLen))
rsi240 = request.security(syminfo.tickerid, "240", ta.rsi(close, rsiLen))
rsiD = request.security(syminfo.tickerid, "D", ta.rsi(close, rsiLen))
rsiW = request.security(syminfo.tickerid, "W", ta.rsi(close, rsiLen))

// Helper function for RSI cell color
getRsiColor(val) =>
    val >= obLevel ? color.new(color.red, 20) :
    val <= osLevel ? color.new(color.green, 20) :
    color.new(color.gray, 60)

// Helper function for signal text
getSignal(val) =>
    val >= obLevel ? "OVERBOUGHT" :
    val <= osLevel ? "OVERSOLD" : "-"

getSignalColor(val) =>
    val >= obLevel ? color.red :
    val <= osLevel ? color.green :
    color.gray

// Build table
var tbl = table.new(position.bottom_right, 3, 6,
    bgcolor=color.new(color.black, 30), border_width=1,
    border_color=color.new(color.white, 70))

if barstate.islast
    // Header row
    table.cell(tbl, 0, 0, "TF", text_color=color.white,
        text_size=size.small, bgcolor=color.new(color.gray, 40))
    table.cell(tbl, 1, 0, "RSI", text_color=color.white,
        text_size=size.small, bgcolor=color.new(color.gray, 40))
    table.cell(tbl, 2, 0, "Signal", text_color=color.white,
        text_size=size.small, bgcolor=color.new(color.gray, 40))

    // 15m
    table.cell(tbl, 0, 1, "15m", text_color=color.white, text_size=size.small)
    table.cell(tbl, 1, 1, str.tostring(rsi15, "#.#"),
        text_color=color.white, text_size=size.small, bgcolor=getRsiColor(rsi15))
    table.cell(tbl, 2, 1, getSignal(rsi15),
        text_color=getSignalColor(rsi15), text_size=size.small)

    // 1H
    table.cell(tbl, 0, 2, "1H", text_color=color.white, text_size=size.small)
    table.cell(tbl, 1, 2, str.tostring(rsi60, "#.#"),
        text_color=color.white, text_size=size.small, bgcolor=getRsiColor(rsi60))
    table.cell(tbl, 2, 2, getSignal(rsi60),
        text_color=getSignalColor(rsi60), text_size=size.small)

    // 4H
    table.cell(tbl, 0, 3, "4H", text_color=color.white, text_size=size.small)
    table.cell(tbl, 1, 3, str.tostring(rsi240, "#.#"),
        text_color=color.white, text_size=size.small, bgcolor=getRsiColor(rsi240))
    table.cell(tbl, 2, 3, getSignal(rsi240),
        text_color=getSignalColor(rsi240), text_size=size.small)

    // Daily
    table.cell(tbl, 0, 4, "1D", text_color=color.white, text_size=size.small)
    table.cell(tbl, 1, 4, str.tostring(rsiD, "#.#"),
        text_color=color.white, text_size=size.small, bgcolor=getRsiColor(rsiD))
    table.cell(tbl, 2, 4, getSignal(rsiD),
        text_color=getSignalColor(rsiD), text_size=size.small)

    // Weekly
    table.cell(tbl, 0, 5, "1W", text_color=color.white, text_size=size.small)
    table.cell(tbl, 1, 5, str.tostring(rsiW, "#.#"),
        text_color=color.white, text_size=size.small, bgcolor=getRsiColor(rsiW))
    table.cell(tbl, 2, 5, getSignal(rsiW),
        text_color=getSignalColor(rsiW), text_size=size.small)

Why Multi-Timeframe Visibility Changes How You Trade

Before I had this dashboard, I would check the 4H RSI, see it at 65, and think “still room to run.” Then I would discover the daily RSI was already at 78 and the weekly was pushing 72. The trade looked fine on one timeframe but was pushing into overbought territory on the bigger picture.

The reverse is also true and arguably more useful. When I see the 1H and 4H RSI both below 30 while the daily RSI is at 45 (still neutral), that tells me the short-term oversold condition is a pullback within a broader trend — which is often a buying opportunity rather than a sign of a broader reversal.

I check this panel before entering any trade. It takes about five seconds to glance at the color-coded cells and decide whether the multi-timeframe RSI picture supports or contradicts my idea.

What Makes an AI-Generated Indicator Worth Keeping

After discarding 37-ish indicators, I developed a rough checklist for evaluating new ones:

1. Does It Do One Thing Clearly?

If I cannot explain what the indicator shows in one sentence, I delete it. “Shows when volume is abnormally high” is one sentence. “Combines MACD divergence with Bollinger Band squeeze and volume-weighted momentum oscillator” is not — and every indicator like that I generated was confusing to read and impossible to act on quickly.

2. Does It Change My Behavior?

An indicator that confirms what I can already see on the chart is wasting screen space. The gray state on the EMA Ribbon actively stops me from taking trades during chop. The MTF RSI Dashboard stops me from entering a 4H trade without checking the daily picture. If an indicator does not cause me to do something differently than I would without it, it goes.

3. Does It Survive Two Weeks of Live Charts?

I have a rule: every new indicator stays on my chart for 14 calendar days before I decide to keep or remove it. During those two weeks, I note each time it was useful and each time it was misleading. If the misleading count is higher, it is gone. This sounds obvious but I used to add and remove indicators daily, chasing the feeling of having the “right” setup. The two-week rule fixed that.

4. Does It Not Repaint?

This is non-negotiable. I ask the AI explicitly to avoid repainting, but I still test manually by comparing the indicator’s signals on historical bars versus what it showed in real-time. If signals appear on historical bars that I do not remember seeing live, it repaints, and I delete it immediately.

Summary Table

IndicatorWhat It DetectsTimeframe I UseAI ToolFirst-Try Success
Smart EMA RibbonTrend strength and chop zones4HClaude CodeNo — needed 2 iterations
Volume Anomaly DetectorUnusual volume spikes15m and 1HCursorYes — one manual tweak
MTF RSI DashboardOverbought/oversold across timeframesAny (it reads all TFs)Claude CodeNo — needed 3 iterations

The Honest Caveat

None of these indicators predict the future. I have had losing trades with all three indicators aligned in my favor, and I have missed winning trades because the indicators told me to stay out. They are filters, not signals. They reduce the noise and help me make faster, more consistent decisions — but they do not remove the fundamental uncertainty of trading.

If someone tells you they have an AI-generated indicator that is a crystal ball, they are selling something. These three indicators save me time and reduce impulsive trades. That is the realistic ceiling for what indicators — AI-generated or otherwise — can do.

The real value of using AI here is iteration speed. Without Claude Code and Cursor, writing and testing 40 Pine Script indicators would have taken months. With AI, I did it in a few weeks. Most of the output was trash, but the three survivors are genuinely useful tools. That hit rate — roughly 7% — is probably about right for any creative process where you are experimenting fast and filtering ruthlessly.

Next Steps

Disclaimer: This article is for educational purposes only and is not financial advice. Trading cryptocurrencies involves substantial risk of loss. Past performance does not guarantee future results. Always do your own research before making any trading decisions. Read full disclaimer →
Alpha Guy
Alpha Guy

Founder of VibeTradingLab. Ex-Goldman Sachs engineer, 2025 Binance Top 1% Trader. Writes about using AI tools to build trading systems that actually work. Currently nomading between Bali, Dubai, and the Mediterranean.

Got stuck? Have questions?

Join our Telegram group to ask questions, share your bots, and connect with other AI traders.

Join Telegram