Part 1 of 3
Building an EMA Crossover System in TradingView with ScalpTrader TradeEvents Integration

Part 1: The Idea

June 30, 2026

·

4 min read

TradingView

This is the first post in a three-part series showing how to add live monitoring to a TradingView strategy using ScalpTrader’s TradeEvents dashboard. It mirrors an earlier series I did using a NinjaTrader strategy — same goal, different platform, and a different set of constraints to work around.

The series:

  1. The idea (this post) — what we’re monitoring and why TradingView is a good fit
  2. Implementing it in Pine Script — the actual alert/webhook plumbing
  3. Closing the loop — setup, event payloads, and the dashboard

Why TradingView is a different shape of problem

The NinjaTrader version of this series sent webhooks directly from NinjaScript — the strategy itself made an HTTP call the moment something happened. TradingView doesn’t give you that. Pine Script strategies can’t make outbound HTTP requests on their own; the only way data leaves a TradingView chart in real time is through alerts, and alerts fire through whatever you configured as the alert’s notification target — including a webhook URL.

That changes the design a bit. Instead of “call a function that sends an HTTP request,” the pattern becomes “build a JSON string and hand it to alert(),” with a TradingView alert object doing the actual delivery in the background. It’s a layer of indirection you don’t have to think about on most platforms, but once it’s set up it’s genuinely simple — there’s no server, no API key to manage outside of what’s embedded in the webhook URL, and it works the same whether you’re paper trading or live.

The example strategy

To keep this series consistent with the original, I used a simple, well-known setup: an EMA crossover on a 20/50 pair.

  • Go long when the 20-period EMA crosses above the 50-period EMA.
  • Go short when the 20-period EMA crosses below the 50-period EMA.
  • Entries only trigger on a confirmed bar close — not intrabar — so the strategy doesn’t repaint or fire early on a crossover that hasn’t actually held.

That’s it. There’s no stop-loss or target logic layered in — a crossover system is always in the market, flipping from long to short and back as the EMAs cross. I picked this specifically because the logic is generic enough that nearly anyone could substitute their own strategy.entry / strategy.close calls in its place and keep everything else in the script unchanged. The EMA crossover here is explicitly a placeholder, not the point of the post.

TradingView chart showing EMA 20/50 crossover strategy with long and short entry signals

What “monitoring” means in this context

The goal is the same as the NinjaTrader series: turn a strategy’s internal state into a handful of well-defined events that a dashboard can consume. For this script, that breaks down into:

  • position_opened — fired the moment a new position is entered (or a reversal flips into the opposite side)
  • position_closed — fired when a position is closed out, carrying P/L in both points and account currency
  • card — a recurring status snapshot: either the current open position with its unrealized P/L, or a simple “waiting” message when flat. This is also the liveness signal — TradingView’s dashboard side doesn’t get a heartbeat or ping, so the card itself has to show up often enough to prove the strategy is still running.

That last point matters more here than it did on the NinjaTrader side. Because TradingView alerts only fire on bar events, the card has to be tied to the timeframe of the chart — which is part of why this setup calls for a small timeframe (1–5 minutes) rather than something like an hourly chart, even though an EMA(20)/EMA(50) crossover would normally be just as much at home on a higher timeframe.

A wrinkle TradingView introduces: warmup replayIntermediate

One thing this version of the strategy does that the NinjaTrader one didn’t: on first going live, it looks back over a configurable window (warmupHours) and replays any trades the strategy closed within that window — tagged as warmup — before it starts sending live events. The reasoning is straightforward: a TradingView strategy might have been sitting on a chart, accumulating trade history, well before anyone bothered to wire up TradeEvents. Without the replay, the dashboard would start from a blank slate the moment you turn monitoring on, even though the strategy itself has been trading for hours. The replay gives the dashboard some recent context instead of an empty screen.

This adds some real complexity — Pine Script caps how long a single alert payload can be, so the replay has to be batched into chunks rather than sent as one call — but it’s worth it for how much better the first few minutes of using the dashboard feel.

The series covers EMACrossover_Full.pine, which includes this warmup replay. If you only need live events and want something simpler to start from, EMACrossover_Simple.pine has the same trading logic and event plumbing without the warmup section. Both files are on GitHub.

Why this is a good showcase

Same underlying reasoning as the NinjaTrader post: a small, deterministic set of events, each with an unambiguous trigger, makes for both a good demo and a good template. But this version showcases something the NinjaTrader one couldn’t: because the webhook plumbing in this script is fully decoupled from the EMA crossover logic, it works as a drop-in pattern — anyone with their own Pine Script strategy can lift the event-building and alert-firing code wholesale and wire it to their own strategy.entry/strategy.close calls, without touching the parts that talk to TradeEvents at all.

What’s next

In Part 2, I’ll go through the actual Pine Script — how alerts get shaped into the JSON envelope TradeEvents expects, how the script tracks position state across bars (since Pine doesn’t give you a persistent position ID the way a broker API might), and how the warmup replay batches trades under Pine’s string-length limit. Then in Part 3, I’ll cover the one-time setup steps, the event payloads in detail, and what it all looks like once it’s live on the dashboard.