When you’re developing indicators in NinjaTrader, it’s easy to focus only on the visuals — plotting lines, marking highs and lows, or coloring candles. But charts alone don’t help much if you’re not watching the screen at the exact moment something important happens.

That’s where alerts and sound notifications come in.

✅ With just a few lines of code, you can make your indicators more responsive, more informative, and much easier to use in real-time by:

  • Triggering visual alerts when a condition is met
  • Playing a sound the moment a breakout happens
  • Giving traders a way to turn alerts on or off
  • Letting them customize which sound file is used
  • Controlling alert behavior so it doesn’t spam every bar

Whether you want a loud “ding” when price breaks the session high, or a full alert window with color-coded popups — NinjaScript gives you all the tools to do it.

👉 Save this official NinjaTrader Help Guide link:

If you’re new here, make sure you check out the earlier posts too:

🔔 What Are Alerts and PlaySound?

In NinjaScript, you have two core tools to notify the trader when something important happens: PlaySound() and Alert(). Both are used to capture attention, but they serve different purposes and operate in different ways.

Before we dive into code, it’s important to understand what each one actually does — and when you’d want to use them.

🧠 Key Differences

Feature PlaySound() Alert()
Plays a .wav sound? ✅ Yes ✅ Yes
Displays popup / log message? ❌ No ✅ Yes (in the Alerts Log window)
Customizable message text? ❌ No ✅ Yes
Requires real-time state? ✅ Yes ✅ Yes
Repeats automatically? ✅ Yes (on each trigger) ✅ If called after rearmSeconds, ❌ if called too soon
Manual rearming available? ❌ Not needed ✅ Yes — via RearmAlert("alertId")
Sound overlap behavior? ✅ May overlap (unless queued in settings) ❌ Blocks until rearmed or timeout expires
Ease of use 🟢 Very simple 🟡 Medium complexity (requires multiple parameters)

🧭 When to Use Each

Use PlaySound() when you want a quick, sound-only cue — like a “ding” when price crosses a level. Use Alert() when you want a full message with a timestamp, log entry, visual styling, and sound — especially when the signal is meaningful enough to warrant extra attention.

And in many cases, you might use both at the same time: one for sound, one for logging and visual alerting.

🔊 Using PlaySound for Simple Audio Alerts

PlaySound() is the simplest way to trigger audio alerts in NinjaTrader. It’s perfect for scalpers or visual traders who want a quick “ding” or custom sound when a condition is met — without cluttering the Alerts Log or opening popup messages.

It’s just sound. But as simple as it seems, there are a few rules that determine whether it works properly — or does nothing at all.

📘 What Is PlaySound?

PlaySound(string filePath) is a NinjaScript method that plays a .wav file on your computer only during real-time trading. This means it won’t play during backtests or while historical bars are loading.

If you call it on every bar, it will play every time — possibly overlapping itself unless NinjaTrader is configured to handle sounds one at a time.

💡 Syntax & Example

// Play a custom sound from the default NinjaTrader folder
PlaySound(NinjaTrader.Core.Globals.InstallDir + @"\sounds\Alert1.wav");

// Or play a custom local file
PlaySound(@"C:\MyCustomSounds\Breakout.wav");

⚠️ Always make sure your .wav file exists and is compatible. If not, your code may silently fail or throw a runtime error.

📁 Where to Store Sound Files

NinjaTrader expects sound files to be placed in a known location, like its built-in sounds folder:

C:\Program Files\NinjaTrader 8\sounds

To access that folder in NinjaScript, use:

NinjaTrader.Core.Globals.InstallDir + @"\sounds\"

✅ This approach ensures the path will work across any user’s machine.

🧠 Important Notes from the NinjaTrader Docs

1. Only Works in State.Realtime

if (State == State.Realtime) // The realtime check is not needed, but added for demonstration of what is happening
    PlaySound(mySoundPath);

PlaySound is ignored during State.Historical, so if you try to use it during backtesting or when your chart first loads, it won’t do anything. You must wait until State.Realtime.

2. Sound Format Must Be PCM .wav

PlaySound requires audio files to be uncompressed .wav in PCM format. Other formats like .mp3, .ogg, or .aac will fail.

  • ✅ OK: Alert1.wav (default format)
  • ❌ Bad: beep.mp3, notify.ogg

💡 Convert formats using free tools like Audacity.

3. Default Behavior Is Asynchronous

When PlaySound() is called multiple times in a row, sounds can overlap. NinjaTrader doesn’t wait for one sound to finish before playing another.

// All 3 may play at once
PlaySound(path);
PlaySound(path);
PlaySound(path);

4. Prevent Overlapping: “Play Consecutively” Option

To change this behavior, go to:

Tools > Options > Sounds > Play consecutively

Turning this on forces sounds to queue up instead of overlapping — useful when multiple triggers can happen close together.

✅ Real-World Example: Trigger on Price Break

if (Close[0] > 4200 && Close[1] <= 4200)
{
    PlaySound(NinjaTrader.Core.Globals.InstallDir + @"\sounds\Alert3.wav");
}

This plays a sound only once when the price crosses above 4200. It checks that you’re in real-time mode and that the condition just triggered.

🎛️ Optional User Input for Sound File

Want users to choose their own sound? Add a string input:

[NinjaScriptProperty]
[Display(Name = "Alert Sound File", GroupName = "Parameters", Order = 1)]
public string AlertSoundFile { get; set; } = "Alert3.wav";

And then use:

string path = NinjaTrader.Core.Globals.InstallDir + @"\sounds\" + AlertSoundFile;
PlaySound(path);

✅ This makes your indicator customizable without modifying the code each time.

❌ Common Mistakes to Avoid

Mistake Result Fix
Using wrong file format (e.g., .mp3) Sound fails silently Convert to .wav (PCM)
Calling PlaySound in State.Historical No sound plays Add a check for State == State.Realtime
Sound triggers every bar Annoying noise Add proper conditions or cooldown logic
Path hardcoded incorrectly Runtime error or silence Use Globals.InstallDir + @"\sounds\"

📢 Using Alert() for Full Visual + Sound Alerts

While PlaySound() gives you quick, one-off sound cues, the Alert() method is a much more powerful tool. It allows you to generate a complete alert with a log message, an optional sound, and visual styling inside the Alerts Log window. If you need to track specific events or conditions over time, this is your go-to.

But because Alert() is more powerful, it also comes with more parameters and some important behaviors you need to understand.

💡 Basic Syntax

Alert(
    string id,
    Priority priority,
    string message,
    string soundLocation,
    int rearmSeconds,
    Brush backBrush,
    Brush foreBrush
);

Let’s break this down:

  • id – A unique name for the alert (e.g., "myAlert1"). If you use the same ID for multiple alerts, the system will control how often it fires based on rearmSeconds.
  • priority – Impacts sorting in the Alerts Log (e.g., Priority.High, Priority.Medium, or Priority.Low).
  • message – The text that shows up in the Alerts Log window.
  • soundLocation – The full file path to the .wav file you want to play.
  • rearmSeconds – How many seconds must pass before the same alert ID can fire again.
  • backBrush and foreBrush – Control the row color of the alert in the Alerts Log (not the chart).

🛠 Example: Trigger Alert on RSI Threshold

if (RSI(14, 3)[0] >= 70)
{
    Alert(
        "rsiOverbought",
        Priority.High,
        "RSI has reached overbought territory!",
        NinjaTrader.Core.Globals.InstallDir + @"\sounds\Alert2.wav",
        10,
        Brushes.DarkRed,
        Brushes.White
    );
}

📝 This will:

  • Show a red alert in the Alerts Log with white text
  • Play a sound (once every 10 seconds maximum)
  • Prevent repeated alerts from spamming the log

⏱ Understanding rearmSeconds

This parameter controls how often the same alert ID can trigger. For example, if you set rearmSeconds to 10:

  • The alert will only trigger once every 10 seconds, even if the condition is true on every bar
  • NinjaTrader tracks the last time each alert ID was fired
  • If it’s too soon, the alert call will be ignored silently

This behavior makes Alert() useful for reducing noise in high-frequency environments.

🔁 What If You Want the Alert to Trigger Again Immediately?

That’s where RearmAlert() comes in — and we’ll cover it in the next section.

But first, let’s make sure you can control when and how alerts fire with the flexibility your script needs. From toggling alerts on and off to letting users pick their sound, you can expose options through inputs. That’s next.

♾️ Rearming Alerts with RearmAlert()

By default, NinjaTrader prevents an Alert() from firing again too soon — even if you set rearmSeconds to 0. If you want an alert to fire again immediately, you must manually rearm it using RearmAlert().

This method resets NinjaTrader’s internal block for a given alert ID, allowing it to trigger again even if it was just fired.

🔧 Syntax

RearmAlert("myAlertId");

You just pass the string ID of the alert you want to rearm.

🧠 When to Use RearmAlert()

  • ✅ You want the alert to fire every time the condition is met, even if that happens multiple times quickly
  • ✅ You’re looping over bars and want the alert to reset inside the same session
  • ✅ You need full manual control over alert timing

🛠 Practical Example: Rearm on Session Start

protected override void OnBarUpdate()
{
    if (Bars.IsFirstBarOfSession)
        RearmAlert("rsiOverbought");

    if (RSI(14, 3)[0] > 70)
    {
        Alert(
            "rsiOverbought",
            Priority.High,
            "RSI crossed 70!",
            NinjaTrader.Core.Globals.InstallDir + @"\sounds\Alert2.wav",
            0,
            Brushes.DarkRed,
            Brushes.White
        );
    }
}

In this example:

  • The alert only fires if RSI crosses 70.
  • rearmSeconds is set to 0, meaning we want no delay.
  • But because NinjaTrader won’t re-fire it again without manual intervention, we explicitly rearm the alert once per session using Bars.IsFirstBarOfSession.

You can also rearm alerts based on price reversals, indicator resets, or user input changes — any logical moment when it makes sense to “reset” the system’s alert block.

✅ Best Practice

  • Only use RearmAlert() when needed — don’t call it constantly or blindly every bar.
  • Track your alert logic carefully. Repeated alerts can be helpful, or annoying and noisy depending on your conditions.

Next up, we’ll make your alerts flexible for the trader by exposing options to turn them on or off, or even change the sound.

🎛️ Adding User Inputs for Alert Control

One of the most powerful features of NinjaScript is the ability to expose properties to users. When it comes to alerts, this means giving traders the ability to:

  • Enable or disable alerts
  • Choose their preferred .wav sound from a dropdown menu
  • Customize how often alerts can fire with a rearm delay

We’ll walk through both the basic input method and a refined dropdown approach using a custom TypeConverter.

✅ Enable or Disable Alerts

A simple bool property lets users toggle alerts:

[NinjaScriptProperty]
[Display(Name = "Enable Alerts", GroupName = "Alerts", Order = 0)]
public bool EnableAlerts { get; set; } = true;

Usage:

if (EnableAlerts && RSI(14, 3)[0] > 70)
{
    Alert("rsiAlert", Priority.High, "RSI > 70", soundPath, 10, Brushes.Black, Brushes.White);
}

🎵 Let Users Select a Sound File

There are two ways to handle this.

1. Basic String Input

[NinjaScriptProperty]
[Display(Name = "Sound File", GroupName = "Alerts", Order = 1)]
public string AlertSoundFile { get; set; } = "Alert1.wav";

Then construct the full file path in your logic:

string soundPath = NinjaTrader.Core.Globals.InstallDir + @"\sounds\" + AlertSoundFile;
PlaySound(soundPath);

2. 🔽 Dropdown File Selector Using TypeConverter

You can improve UX by allowing the user to select from a list of .wav files in NinjaTrader’s sounds folder:

private string soundAlert = string.Empty;

[NinjaScriptProperty]
[TypeConverter(typeof(AlertFolderFinder))]
[Display(Name = "Sound File", Description = "Select a .wav file from the sounds folder. Clear to disable.", GroupName = "Alerts", Order = 2)]
public string SoundAlert
{
    get { return soundAlert; }
    set { soundAlert = value; }
}

And define the converter:

public class AlertFolderFinder : TypeConverter
{
    public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)
    {
        var list = new List<string>();
        var dir = new DirectoryInfo(NinjaTrader.Core.Globals.InstallDir + "sounds");
        foreach (var file in dir.GetFiles("*.wav"))
            list.Add(file.Name);

        return new StandardValuesCollection(list);
    }

    public override bool GetStandardValuesSupported(ITypeDescriptorContext context) => true;
}

This will present users with a clean dropdown of all valid .wav files in their install folder, making configuration smoother and less error-prone.

⏱ Rearm Seconds

Allowing traders to customize how often alerts can fire:

[NinjaScriptProperty]
[Display(Name = "Rearm Seconds", GroupName = "Alerts", Order = 3)]
public int RearmSeconds { get; set; } = 10;

Usage:

Alert("myAlert", Priority.Medium, "Condition met!", soundPath, RearmSeconds, Brushes.Black, Brushes.White);

🧠 Summary

By exposing just a few properties, you give users meaningful control over how and when they get alerted:

  • ✔ Turn alerts on/off
  • ✔ Choose custom sounds from a dropdown
  • ✔ Adjust rearm delay to fit their trading style

These enhancements don’t just improve usability — they also make your indicators look polished and professional.

🧠 Final Thoughts

Alerts and sounds in NinjaScript might seem simple at first, but as you’ve seen, they offer a surprising amount of flexibility and control. Whether you’re using PlaySound() for quick audio cues or Alert() for full visual and audible notifications, how and when you trigger these can make a huge difference in how usable (or annoying) your indicator becomes.

Here’s what to keep in mind as you implement them:

  • Don’t over-alert. Alerts should help, not overwhelm.
  • Use RearmAlert() wisely. It’s essential for conditions that might happen multiple times quickly.
  • Let users configure the behavior. On/off toggles, sound file selection, and rearm seconds make your indicator feel polished.
  • Use distinct IDs when you have multiple alert conditions to avoid unexpected suppression.

With this knowledge, you now have everything you need to build responsive, trader-friendly indicators that talk back when the market does something interesting.

✅ Whether it’s a breakout, a reversal, or a signal from your custom logic — now you can make it heard.

🎉 Prop Trading Discounts

💥91% off at Bulenox.com with the code MDT91

Categorized in:

Learn NinjaScript,

Tagged in: