Expert guides, insights and articles updated for 2026
Published 3 hours ago
Your phone isn’t buzzing all day because you “need a better indicator.” It’s buzzing because your alert logic is rewarding activity, not tradability.
A lot of TradingView alerts are built like this:
Those are signals. They’re not setups. They ignore the two things that decide whether a trigger is worth acting on: regime (trend vs. chop) and energy (expansion vs. sleep). Fix those, and you’ll naturally get fewer alerts—and a higher percentage of them will be usable.
When an alert fires 20 times a day, you end up doing one of two things:
Either way, average quality drops. Fewer alerts forces selectivity and reduces decision fatigue.
A signal is one condition changing. A tradable setup has:
Most “bad alerts” are fine triggers firing in the wrong context.
A “high win-rate alert” should mean: more alerts lead to trades that fit your rules and had a reasonable chance given the current regime.
It does not mean:
Also: win-rate alone is a trap. A 70% win-rate system that makes 0.3R on winners and loses 1R on losers is still a bad deal. Aim for better alerts, not a magical stat.
Use this model every time you build or revise an alert:
Decide whether you want longs, shorts, or both—based on one clear trend definition.
Stop taking alerts when the market is asleep. Many false signals are “valid” on paper but happen inside ranges where the move can’t pay for spread + stop distance.
Your alert should fire on an event, not a state that stays true for 10–20 bars.
Even a good setup is untradable if:
Automate what you can, leave the rest discretionary—but don’t ignore these checks.
Trend filters are where people over-stack. If three tools all measure momentum, they’ll “confirm” each other… right up until chop hits and they all fail together.
A strong default trend gate:
close > EMA and EMA is risingclose < EMA and EMA is fallingWhy it works: it’s simple, stable, and easy to audit.
Starting ranges (not magic numbers):
Slope can be as simple as: EMA > EMA[N bars ago].
Structure-based bias:
It matches how trends actually progress—but you need a consistent swing definition (pivots), or it becomes subjective fast. In Pine, that usually means pivots like ta.pivothigh/ta.pivotlow and tracking confirmed swing points.
ADX doesn’t tell you bullish vs. bearish. It tells you whether the market is trending (or at least less choppy).
Use it like:
Rough starting point:
MACD, moving averages, Supertrend—often variations of the same information. If removing one barely changes which alerts fire, it’s not adding independent confirmation. It’s redundancy.
This is where a lot of “win-rate” gets rescued—because you stop playing in conditions where edge is structurally low.
Two practical approaches:
Raw ATR threshold (simple, not portable)
ATR% (ATR/price) (portable across symbols)
ATR% usually wins because it scales across assets (FX vs. crypto vs. indices).
How to tune without overthinking:
Chop often shows up as contraction.
Two common methods:
Simple rule:
A blunt but effective anti-chop gate:
rangeN = highest(high, N) - lowest(low, N)rangeN > minimum (or rangeN > ATR × k)Example:
Don’t chase universal values. Build a filter that removes the obvious dead zones on your chart.
An alert should fire because something changed, not because something is still true.
If you alert on wick breaks, you’ll get spammed by fake-outs.
Prefer:
Optional quality upgrade:
A clean continuation alert:
Practical rejection checks:
low < level and close > level)This avoids tiny doji flips.
Example:
Many alerts look great because the condition was true mid-candle for a moment.
Live, that creates:
If you want stable alerts, use bar-close confirmation.
Ask:
Good disagreement:
Redundancy:
A practical baseline:
A fourth filter often just reduces frequency and accidentally curve-fits.
If one filter tries to do two jobs, clarity (and debugging) suffers.
Use when: you want continuation moves through obvious levels.
Logic (plain English):
Pseudo-Pine:
emaLen = 200
ema = ta.ema(close, emaLen)
trendLong = close > ema and ema > ema[5]
atr = ta.atr(14)
atrPct = atr / close
volOk = atrPct > 0.0006 // example; tune per symbol/timeframe
swingHigh = ta.highest(high, 20)[1]
breakout = ta.crossover(close, swingHigh) // event-based + close cross
alertLong = trendLong and volOk and breakout
How it often looks: EURUSD 15m around London open—range for 1–2 hours, then a clean break. This aims to alert on the close beyond the range, not every poke.
Use when: breakouts are messy but pullbacks behave.
Logic:
Simple “dip and reclaim” idea:
close > level and low < level on the same barUse when: you specifically want “compression → expansion.”
Logic:
Pseudo-Pine cooldown concept:
var int lastAlertBar = na
cooldownBars = 20
canAlert = na(lastAlertBar) or (bar_index - lastAlertBar > cooldownBars)
if alertLong and canAlert
lastAlertBar := bar_index
Use when: the market is range-bound and trend signals keep failing.
Logic:
Mean reversion alerts should explicitly avoid trending regimes, or they’ll get steamrolled.
close > ema → true for 30 bars ta.crossover(close, ema) → fires onceSame idea for structure levels: prefer break-and-close logic, not persistent states.
If your setup repeats inside a tight range, cooldown prevents “machine-gun” alerts.
Example:
Cooldown is time-based. Reset is structure-based.
Example:
Examples:
If price is in the box, triggers are usually less meaningful.
Forex example:
Crypto trades 24/7, but liquidity still cycles—time filters can still help.
Example:
This reduces countertrend spam, but you must understand how multi-timeframe values update (see below).
If your logic assumes confirmation (break-and-close, rejection on close), choose once per bar close.
If you eyeballed closed candles but run alerts intrabar, you changed the system. That’s one of the main reasons something “worked on history” and fails live.
Higher timeframe data on a lower timeframe chart can behave differently intrabar depending on your code and how series update.
Practical takeaway:
For cooldowns/resets, Pine state helps:
alertcondition(condition, title, message) defines eligibility var variables store persistent state (last alert bar, armed/disarmed status) If you’re not coding, you can still do a lot with built-in alerts + volatility gates. Cooldowns/resets are where Pine becomes a real advantage.
Treat this like a lab test, not a highlight reel:
If you only test the clean trending month, you’re not testing—you’re auditioning.
MAE is especially useful for alerts: it tells you whether your trigger is early/late and whether your stop assumptions are realistic.
Good alerts usually have a “works best when…” profile.
Example:
That’s not failure. That’s a use condition—build it into filters.
If your average win is small, costs matter a lot.
Don’t mix them. Each needs different filters and has different failure modes.
Example combination:
If you do nothing else, do this. It’s the difference between “usable” and “spam.”
Change one parameter, re-test a real sample. If you tune three things at once, you won’t know what actually improved results.
Because many “perfect” historical alerts depend on intrabar behavior or state conditions. Live, price can meet a condition mid-candle and reverse before the close, or a state can stay true and spam you. Bar-close confirmation, event-based triggers, and anti-chop logic usually make live behavior match what you see on the chart.
A signal is a single trigger (like RSI crossing 50). A setup adds context (trend + volatility/regime), then uses an event trigger (break-and-close, retest rejection), plus basic tradeability constraints (session/time, nearby levels, reasonable stop distance). Most “win-rate” frustration comes from triggers without context.
Usually 2–3 complementary filters: one for direction, one for regime/volatility, and one event trigger. A fourth filter often just cuts frequency without adding independent information—especially if it’s correlated with the others.
Price location + slope on a single moving average (e.g., price above an EMA and the EMA rising for longs). It’s clean, stable, and avoids stacking multiple tools that mostly measure the same thing.
Mostly as a permission filter (trend strength / less chop). Direction should come from price/structure or an MA bias. In practice: ADX decides whether trend logic is allowed, not whether the market is bullish or bearish.
ATR-based filters are the most straightforward: require ATR (or ATR%) above a minimum so the market can actually move enough to justify spread and stop distance. Squeeze/expansion filters (BBW or BB-inside-KC) are also strong, especially if you only alert after expansion begins.
Design alerts as events, not states: crossovers/crossunders, break-and-close triggers, retest-and-reclaim events. If you still need state-based logic, add a cooldown or require a reset condition before another alert is allowed.
Use once per bar close for stable signals that match how most people visually test setups. Use once per bar only if you intentionally want intrabar alerts and accept more false positives.
Add a volatility gate (minimum ATR/ATR% or BBW threshold) and/or restrict alerts to active sessions (especially in Forex). If you can define a clear range, only allow alerts after a break-and-close outside the boundary.
Run a fixed sample (50–100 alerts) across multiple regimes. Don’t pause to skip losers. Track more than win-rate: average R, MAE, and time-in-trade. Then adjust one parameter at a time—changing multiple thresholds is the fastest path to curve-fitting.
Would you like to contribute content to this article? Contact us today!
No comments yet. Be the first to comment on this article!