See if Pine Script string ends with substring (without case differences)
See if Pine Script string ends with substring (without case differences)
Section titled “See if Pine Script string ends with substring (without case differences)”TL;DR
Convert both strings to lowercase, then compare withstr.endswith()—that’s all you need for a case-insensitive “ends with” check.
At a Glance
Section titled “At a Glance”| Difficulty | Beginner |
| Time to implement | 10-15 min |
| Category | Strings |
Quick Actions
Section titled “Quick Actions”Quick Start
Section titled “Quick Start”//@version=5indicator("Ends-with helper", overlay=false)
strEndsWith(string source, string suffix) => str.endswith(str.lower(source), str.lower(suffix))
isPerp = strEndsWith(syminfo.ticker, "perp")plotchar(isPerp, "Ends with PERP", "", location=location.top)Why It Matters
Section titled “Why It Matters”Ticker suffixes often denote contract type (-PERP, -USD), exchange-specific flags, or fund share classes. A reusable helper makes it trivial to classify instruments or locations regardless of how the exchange capitalises the suffix.
What You’ll Learn
Section titled “What You’ll Learn”- Build a case-insensitive “ends with” function in a single expression.
- Apply the helper to highlight tickers, time zones, or custom tags.
- Combine it with
syminfometadata to adapt script behaviour. - Handle edge cases (empty strings,
navalues) gracefully.
Quick Reference
Section titled “Quick Reference”| Helper | Purpose |
|---|---|
str.lower(text) | Converts a string to lowercase for normalised comparison. |
str.endswith(source, suffix) | Checks if source ends with suffix (case-sensitive). |
strEndsWith() (custom) | Wraps both operations for case-insensitive matching. |
bgcolor(color) | Optional visual cue when a suffix is detected. |
label.new() | Display classification results at the end of the chart. |
Implementation Blueprint
Section titled “Implementation Blueprint”-
Normalise both strings
Lowercase (or uppercase) the source and suffix to remove letter case differences.lowerSource = str.lower(source)lowerSuffix = str.lower(suffix) -
Run the comparison
Feed the normalised strings intostr.endswith()and return the boolean result.str.endswith(lowerSource, lowerSuffix) -
Reuse everywhere
Wrap the logic in a function so you can detect multiple suffixes or feed them into filters, labels, or alerts.strEndsWith(string source, string suffix) =>str.endswith(str.lower(source), str.lower(suffix))
Example Playbook
Section titled “Example Playbook”//@version=5indicator("Exchange suffix detector", overlay=true, max_labels_count=500)
strEndsWith(string source, string suffix) => // Guard against na inputs na(source) or na(suffix) ? false : str.endswith(str.lower(source), str.lower(suffix))
isPerp = strEndsWith(syminfo.ticker, "perp")isUsd = strEndsWith(syminfo.ticker, "usd")isLondon = strEndsWith(syminfo.timezone, "london")
bgcolor(isPerp ? color.new(color.fuchsia, 90) : na, title="PERP suffix highlight")
if barstate.islast text = "Ticker: " + syminfo.ticker + "\nPERP suffix? " + (isPerp ? "Yes" : "No") + "\nUSD suffix? " + (isUsd ? "Yes" : "No") + "\nLondon TZ? " + (isLondon ? "Yes" : "No")
label.new(bar_index, close, text, style=label.style_label_left, textcolor=color.white, bgcolor=color.new(color.blue, 70))- The helper function keeps comparisons consistent and readable throughout the script.
- Classification results drive both visuals (background colour) and labels for quick inspection.
- Guarding against `na` prevents runtime errors when metadata is missing.
Pro Tips & Pitfalls
Section titled “Pro Tips & Pitfalls”- Check for empty suffixes—
str.endswith("ABC", "")returnstrue. Add asuffix == ""guard if that’s not desired. - Combine the helper with arrays or lists (
for suffix in suffixes) to scan multiple tags quickly. - For mid-string searches, use
str.containswith the same lowercase approach instead ofstr.endswith. - Store the lowercase version of repeated inputs in
varvariables if you call the helper thousands of times per bar.
Troubleshooting & FAQ
Section titled “Troubleshooting & FAQ”Why does the function return false for BTCUSD vs usd?
Section titled “Why does the function return false for BTCUSD vs usd?”Ensure both arguments are strings. Passing numbers or na results in false. Use tostring() if you start from non-string inputs.
Can I support multiple suffixes at once?
Section titled “Can I support multiple suffixes at once?”Yes—loop through an array of suffixes or build a small helper that accepts a list and returns the first match.
Does this work with emojis or non-Latin characters?
Section titled “Does this work with emojis or non-Latin characters?”str.lower() only affects characters with case mappings. For symbols without case (e.g., Kanji), the comparison already behaves case-insensitively.
Key Takeaways
Section titled “Key Takeaways”- Pine Script is case-sensitive, so convert strings to a common case before comparing.
- Wrap the logic in a helper to keep scripts clean and reuse the check everywhere.
- Use suffix detection to adapt styling, alerts, or behaviour based on ticker naming conventions.
- Guard against empty or
nainputs to avoid misleading results.
Keep Going
Section titled “Keep Going”- Open AI Editor to apply the pattern with guided assistance
- Browse PineScript Examples for ready-to-run templates
- Connect to Live Trading when you are ready to automate
Adapted from tradingcode.net, optimised for Algo Trade Analytics users.
When it does, the label.new() function makes a new label. This text label tells we got a German stock. Its colour is fuchsia (color.fuchsia) and its letters are white (color.white).
Should the instrument neither trade in the Berlin time zone, Pine Script moves on to the final if condition:
We again code a condition with the StrEndsWith() function. Now the function tests if the instrument’s time zone ends with “new_york”. When it does, label.new() makes a text label with the message this is an American stock. That label’s colour is lime green (color.lime).
On the chart, the script recognises stocks that trade in the London, Berlin, and New York time zones. On the BMW stock chart below, the script correctly says this is a German stock:
// StrEndsWith() returns 'true' or 'false' to indicate if the specified // source string ends with the given substring, regardless of case // differences. StrEndsWith(string source, string substring) => str.endswith(str.lower(source), str.lower(substring))// Test if instrument ticker (symbol) ends with 'perp' (perpetual future) endsWithPerp = StrEndsWith(syminfo.ticker, "perp")// Turn the background fuchsia when the string ends with 'perp' bgcolor(endsWithPerp ? color.new(color.fuchsia, 90) : na)// On the last bar, see if the chart's instrument is a stock if barstate.islast and syminfo.type == "stock" // Look in which country this stock trades, based on its time zone if StrEndsWith(syminfo.timezone, "london") label.new(bar_index, high, "This is a British stock!", color=color.teal, textcolor=color.white)else if StrEndsWith(syminfo.timezone, "berlin") label.new(bar_index, high, "This is a German stock!", color=color.fuchsia, textcolor=color.white)else if StrEndsWith(syminfo.timezone, "new_york") label.new(bar_index, high, "This is an American stock!", color=color.lime)| Code example | Result |
|---|---|
| StrEndsWith(“XRPUSD”, “USD”) | true. The “XRPUSD” string ends with the phrase “USD”. |
| StrEndsWith(“XRPUSD”, “usd”) | true. The letters of “usd” appear at the end of the “XRPUSD” string. Since the function ignores case differences, “usd”, “Usd”, “USD”, and other casing alternatives are considered the same. What matters is that the letters match, not their casing. |
| StrEndsWith(“XRPUSD”, “xru”) | false. While “xru” happens inside the string, those three characters aren’t the last of the string. So the function returns false. |
| StrEndsWith(“0.35675”, “675”) | true. The “0.35675” text ends with the “675” characters. |
| StrEndsWith(“XRP USD”, ” USD”) | false. While the phrase “USD” appears in both strings, we look for a phrase prefixed with two spaces. But the source string only has one space before “USD”. So this comparison results in false. |
-
The StrEndsWith() function works with any expression that returns a string. This includes variables and the return value from functions. But also individual array and matrix elements.
-
This is how StrEndsWith() behaves with empty strings and the na value:When the source string and substring are both empty ("") or na, the function returns true. As such, both StrEndsWith("", "") and StrEndsWith(na, na) are true.When the substring is empty or na, but the source string is a non-empty string, the function returns true. That is, StrEndsWith(“EURUSD”, "") and StrEndsWith(“USDJPY”, na) are both true.When the source string is empty or na, but the substring is a non-empty string, the function returns false. Meaning, StrEndsWith("", “EUR”) and StrEndsWith(na, “GBP”) are both false.
-
When the source string and substring are both empty ("") or na, the function returns true. As such, both StrEndsWith("", "") and StrEndsWith(na, na) are true.
-
When the substring is empty or na, but the source string is a non-empty string, the function returns true. That is, StrEndsWith(“EURUSD”, "") and StrEndsWith(“USDJPY”, na) are both true.
-
When the source string is empty or na, but the substring is a non-empty string, the function returns false. Meaning, StrEndsWith("", “EUR”) and StrEndsWith(na, “GBP”) are both false.
-
When the source string and substring are both empty ("") or na, the function returns true. As such, both StrEndsWith("", "") and StrEndsWith(na, na) are true.
-
When the substring is empty or na, but the source string is a non-empty string, the function returns true. That is, StrEndsWith(“EURUSD”, "") and StrEndsWith(“USDJPY”, na) are both true.
-
When the source string is empty or na, but the substring is a non-empty string, the function returns false. Meaning, StrEndsWith("", “EUR”) and StrEndsWith(na, “GBP”) are both false.
-
The custom StrEndsWith() function tells if a string appears at the end of another string. This function ignores the difference between small and big letters.
-
The function needs two arguments. One is the string whose end we want to examine. The other string is the text to find at the first string’s end.
-
When the first string indeed ends with the second string, the function returns true regardless of case.
-
If the second string isn’t at the end of the first string, the function’s outcome is false.
- TradingView (n.d.). Pine Script Language Reference Manual. Retrieved on September 18, 2022, from https://www.tradingview.com/pine-script-reference/v5/
Ready to implement this in your own strategies?
- Open AI Editor: Get AI assistance while coding
- See More Examples: Browse complete strategy examples
- Connect to Trading: Turn your PineScript into live trades via Alpaca
This tutorial is based on content from TradingCode.net, adapted for Algo Trade Analytics users.
This tutorial is based on content from tradingcode.net, adapted for Algo Trade Analytics users.
Example Playbook
Section titled “Example Playbook”//@version=5 indicator(title="String ends with substring (case insensitive)", overlay=true) // StrEndsWith() returns 'true' or 'false' to indicate if the specified // source string ends with the given substring, regardless of case // differences. StrEndsWith(string source, string substring) => str.endswith(str.lower(source), str.lower(substring)) // On the last bar, see if the chart's instrument is a stock if barstate.islast and syminfo.type == "stock" // Look in which country this stock trades, based on its time zone if StrEndsWith(syminfo.timezone, "london") label.new(bar_index, high, "This is a British stock!", color=color.teal, textcolor=color.white) else if StrEndsWith(syminfo.timezone, "berlin") label.new(bar_index, high, "This is a German stock!", color=color.fuchsia, textcolor=color.white) else if StrEndsWith(syminfo.timezone, "new_york") label.new(bar_index, high, "This is an American stock!", color=color.lime)Keep Going
Section titled “Keep Going”- Open AI Editor to apply the pattern with guided assistance
- Browse Strategy Examples for ready-to-run templates
- Connect to Live Trading when you are ready to automate
Adapted from tradingcode.net, optimised for Algo Trade Analytics users.