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:
- PlaySound() – NinjaTrader Help Guide
- Alert() – NinjaTrader Help Guide
- RearmAlert()– NinjaTrader Help Guide
📚 Related NinjaScript Lessons So Far
If you’re new here, make sure you check out the earlier posts too:
- Understanding the NinjaTrader Indicator Structure
- Variables and Properties in NinjaScript
- OnStateChange() Lifecycle Explained
- OnBarUpdate() Fully Explained
- Learn how to use Series<T>
- Learn NinjaScript Plots
- Learn NinjaScript Lines
- How to use NinjaScript Brushes
- Creating and Using Methods & Functions
- Add-On Your Way to Cleaner Code
- Using Lists, Dictionaries, and Arrays
- Creating and Using Classes Inside an Indicator
- Drawing on the Chart with Draw Objects
🔔 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 onrearmSeconds
.priority
– Impacts sorting in the Alerts Log (e.g.,Priority.High
,Priority.Medium
, orPriority.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
andforeBrush
– 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