gsEasyScript v1.4

gsEasyScript is the domain-specific scripting language built into gsStockAnalyzer. It lets you screen thousands of tickers using plain, human-readable conditions - no programming experience required. Each line is a filter: only tickers that satisfy all conditions (AND logic) survive to the next step. Add an OR keyword inside a single line to express alternative conditions.

💡 How it works: The script engine evaluates each line in order. After every function call the result set is updated - tickers that do not match the condition are removed. The final grid shows only the tickers that passed every filter. Use Multi-thread mode for faster execution on large universes.

Syntax Rules

RuleExample
One condition per line (implicit AND)RSI(14, "d") < 30
Semicolons optionalChangePerc(20, "d") > 5;
Multiple conditions same line → ANDRSI(14,"d") > 40; RSI(14,"d") < 70
OR inside a lineRSI(14,"d") < 30 OR ChangePerc(5,"d") < -15
Script directives (metadata)// @StrategyName: My Strategy
Comments start with //// filter only EU stocks
String parameters in double quotes"d", "w", "m"
Decimal separator: dot or comma61.8 or 61,8 both valid
Function names are case-sensitiveRSI ✅   rsi
📋 Script Directives - Lines starting with // @ are metadata tags used by the engine when publishing signals to gStockly.com. They are ignored during scanning:
// @StrategyName: Breakout from Resistance with Volume
// @StrategyCode: l1_breakout_resistance
// @StrategyDescription: Identifies stocks breaking above their 20-day high on above-average volume.
// @Area: europe
// @Timeframe: d

📄 Minimal complete script

// Screen European large-caps with strong momentum and oversold RSI
FilterTickers(country = 'EU')
AvgCounterValue(20, "d") > 1000000
ChangePerc(63, "d") > 10
RSI(14, "d") < 40

Timeframes

CodeDescription
"d"Daily candles
"w"Weekly candles
"m"Monthly candles
Tip: Mix timeframes freely in the same script. For example, confirm a weekly trend with IsUpTrend(52, "w") and then refine entry timing with a daily indicator.

Comparison Operators

OperatorMeaningExample
>Greater thanRSI(14,"d") > 50
<Less thanRSI(14,"d") < 30
>=Greater or equalChangePerc(5,"d") >= 5
<=Less or equalBollingerWidth(20,2,"d") <= 8
=Equal (numeric)ConsecutiveCandles(3,"red","d") = 3
!=Not equalConsecutiveCandles(1,"green","d") != 0
Some functions (e.g. GapUp, InsideBar, HigherHighs, IsUpTrend, IsDownTrend) do not require a comparison operator - they act as boolean filters by themselves.

AND / OR Logic

By default every line is an AND condition. Use the OR keyword (uppercase) within a single line to allow alternative conditions.

📄 AND logic (default)

// Ticker must satisfy BOTH conditions
RSI(14, "d") < 35
ChangePerc(5, "d") < -10

📄 OR logic

// Ticker passes if EITHER condition is true
RSI(14, "d") < 30 OR ChangePerc(5, "d") < -15
Note: OR only works within a single line. Conditions on separate lines are always AND.

Comments

Lines starting with // are completely ignored by the engine. Lines starting with // @ are script directives (metadata for gStockly publishing).

// @StrategyName: Squeeze Pre-Breakout Scanner
// @StrategyCode: squeeze_prebreakout
// @StrategyDescription: Finds stocks in Bollinger compression after an uptrend.
// @Area: europe
// @Timeframe: d

// Step 1 — Liquidity filter
AvgCounterValue(20, "d") > 300000

// Step 2 — Trend confirmation
ChangePerc(63, "d") > 5

Script Variables NEW

You can declare named variables at the top of your script and reuse them as parameters inside any function call. This avoids repetition and makes your script much easier to read and maintain — change a value in one place, and it is automatically applied everywhere.

Syntax

VariableName = value
  • The name must start with a letter or underscore: MyEma, _period, LiqMin.
  • Only letters, digits, and underscores are allowed — no spaces.
  • The value can be a number (200, 3000000, 1.5) or a string (d, w, europe).
  • Variable declarations are processed before execution — they do not count as conditions.
  • Variable names are case-insensitive (MyEma and myema refer to the same variable).
  • Substitution uses word-boundary matching, so a variable named p will not accidentally replace the p inside ChangePerc.
How it works: The engine resolves all variable declarations before running any condition. Each declaration line is removed from the execution queue and its value is substituted, verbatim, wherever the variable name appears as an isolated token.

📄 Basic example — reuse the same EMA period

// Declare variables
MyEma  = 200
MyTf   = w

// Conditions — MyEma and MyTf are replaced at runtime
AvgCounterValue(3, "m") > 3000000
DistancePercFromEMA(MyEma, MyTf) > 0      // becomes: DistancePercFromEMA(200, w) > 0
DistancePercFromEMA(MyEma, MyTf) < 1      // becomes: DistancePercFromEMA(200, w) < 1
AvgVolatility(4, "m") > 0

📄 Multiple variables — full strategy parameterization

// @StrategyName: Breakout near EMA
// @StrategyCode: breakout_ema

EmaPeriod    = 50
Timeframe    = d
LiquidityMin = 1000000
BreakPeriod  = 20

AvgCounterValue(20, "d") > LiquidityMin
IsUpTrend(EmaPeriod, Timeframe)
BreakoutHigh(BreakPeriod, Timeframe) == 1
DistancePercFromEMA(EmaPeriod, Timeframe) < 5   // not stretched too far from EMA
⚠️ Limitations:
  • Variables cannot reference other variables: MyPeriod = BaseP + 10 is not supported. Use only literal values.
  • Declarations must be on their own line (not combined with a condition on the same line).
  • Only simple substitution — no arithmetic expressions.

Close Price Functions

CloseLastClose() <operator> value

Returns the most recent closing price of each ticker.

Example

LastClose() > 10
LastClose() < 500
CloseLastPercClose(timeframe) <operator> value

Percentage change of the last closed candle vs the previous one.

Examples

LastPercClose("d") > 3
LastPercClose("d") > 5 OR LastPercClose("d") < -5
Close NEW LastPercClose(timeframe) <operator> value

Percentage change of the last closed candle vs the previous one. Equivalent to ChangePerc(1, tf) but more readable and optimised for single-bar queries (requires only 2 candles of history).

ParameterDescription
timeframe"d" daily, "w" weekly, "m" monthly

Examples

// Last daily candle up more than 3%
LastPercClose("d") > 3

// Strong move in either direction (big candle scanner)
LastPercClose("d") > 5 OR LastPercClose("d") < -5

// Volume explosion + positive last candle
LastPercClose("d") > 1.5
VolumeProfile(20, "d") > 80

// Weekly candle strong close
LastPercClose("w") > 2
Formula: (Close[0] − Close[1]) / Close[1] × 100  Â·  Requires only 2 candles — fastest close-change function available.
CloseClose(period, timeframe) <operator> value  /  PrevClose(period, timeframe)

Closing price N bars ago. Close(1,"d") = yesterday's close.

CloseAvgClose(period, timeframe) <operator> value

Average closing price over the last N bars.

CloseCandleType(candleNumber, timeframe, "green"/"red")

Checks whether candle N is green (close ≥ open) or red. candleNumber = 1 = most recent.

Examples

CandleType(1, "d", "green")
CandleType(2, "d", "red")
CloseDistancePercFromAllTimeHigh() <operator> value

Distance in % from the all-time high. Always negative or zero. Alias: DistancePercFromAllTimeMax().

Examples

DistancePercFromAllTimeHigh() > -10  // within 10% of ATH
DistancePercFromAllTimeHigh() < -50  // more than 50% below ATH
CloseDistancePercFromAllTimeLow() <operator> value

Distance in % from the all-time low. Always positive or zero. Alias: DistancePercFromAllTimeMin().

CloseEvaluateIfStrongClose(percentageLevel, timeframe)  /  EvaluateIfWeakClose(percentageLevel, timeframe)

Filters tickers whose last candle closed in the upper (strong) or lower (weak) portion of its H-L range.

Examples

EvaluateIfStrongClose(75, "d")  // closed in upper 25%
EvaluateIfWeakClose(30, "d")   // closed in lower 30%

Volume Functions

VolumeVolumeChangePerc(period, timeframe) <operator> value

Percentage change in volume over the last N bars.

Example

VolumeChangePerc(5, "d") > 50
VolumeVolumeChangeVsAvg(avgPeriod, timeframe) <operator> value

Compares latest volume to the N-bar average. Returns % difference.

Examples

VolumeChangeVsAvg(20, "d") > 100   // double the average
VolumeChangeVsAvg(20, "d") < -30  // quiet consolidation
VolumeVolumeChangeVsAvgAtTime(avgPeriod, timeframe) <operator> value

Similar to VolumeChangeVsAvg but adjusts for time of day (intraday volume explosion detection).

VolumeAvgCounterValue(period, timeframe) <operator> value

Average daily traded value in USD (price × volume). Essential for liquidity filtering.

Examples

AvgCounterValue(20, "d") > 500000    // minimum €500k liquidity
AvgCounterValue(20, "d") > 5000000   // large-cap filter
VolumeVolumeProfile(period, timeframe) <operator> value

Volume percentile rank (0–100) of the current bar vs the last N bars. 80 = today's volume is higher than 80% of recent sessions.

Examples

VolumeProfile(30, "d") > 80  // top 20% — volume explosion
VolumeProfile(20, "d") < 30  // bottom 30% — silent consolidation

Moving Average Functions

Moving AvgDistancePercFromSMA(period, timeframe) <operator> value

% distance of close from the Simple Moving Average. Positive = above SMA.

Examples

DistancePercFromSMA(200, "d") > 0   // above 200-day SMA
DistancePercFromSMA(50, "d") > -3
DistancePercFromSMA(50, "d") < 3    // pullback to 50-day SMA
Moving AvgDistancePercFromEMA(period, timeframe) <operator> value

Same as DistancePercFromSMA but uses an Exponential Moving Average. Alias: DistPercFromEMA.

Moving AvgCrossEMA(period, timeframe, "up"/"down")  /  CrossSMA(period, timeframe, "up"/"down")

Detects when the price crosses above or below a given EMA/SMA on the most recent two bars.

Examples

CrossEMA(50, "d", "up")    // price just crossed above EMA50
CrossSMA(200, "d", "down") // price just crossed below SMA200
Moving AvgCrossEMAEMA(fast, slow, timeframe, "up"/"down")

Golden Cross ("up") or Death Cross ("down") between two EMAs.

Examples

CrossEMAEMA(20, 50, "d", "up")    // Golden cross EMA20/EMA50
CrossEMAEMA(50, 200, "w", "down") // Death cross EMA50/EMA200 weekly
Returns: "Golden Cross" or "Death Cross" + the two EMA values.
Moving AvgEMASlope(period, timeframe) <operator> value

Slope of the EMA via linear regression on the last 5 EMA values, expressed as % per bar. Positive = rising EMA.

Examples

EMASlope(50, "d") > 0       // EMA50 is rising
EMASlope(20, "d") > 0.05    // aggressively rising EMA20
Moving AvgNEWSMASlope(period, timeframe) <operator> value

Same as EMASlope but using the Simple Moving Average. Linear regression on the last 5 SMA values, result as % per bar.

Examples

SMASlope(20, "d") > 0      // SMA20 rising
SMASlope(50, "d") > 0.05   // SMA50 accelerating upward
SMASlope(200, "d") < 0    // long-term trend turning down
Moving AvgNEWCrossedEMAWithin(period, timeframe, "Up"/"Down", bars) == 1

True if the price crossed the EMA within the last bars bars. Unlike CrossEMA which only checks the very last bar, this function catches fresh crossovers that occurred a few bars ago — avoiding missed signals.

ParameterDescription
periodEMA period
timeframe"d", "w", "m"
direction"Up" = bullish cross; "Down" = bearish cross
barsWindow size — how many recent bars to scan for the crossover
Returns: CrossUp or CrossDown + BarsAgo (how many bars ago) + EMA value at crossover

Examples

CrossedEMAWithin(20, "d", "Up", 5) = 1    // crossed EMA20 upward in last 5 days
CrossedEMAWithin(50, "w", "Down", 3) = 1  // crossed EMA50 downward in last 3 weeks

// Fresh EMA cross + volume confirmation
CrossedEMAWithin(20, "d", "Up", 5) = 1
VolumeChangeVsAvg(20, "d") > 50
Moving AvgNEWCrossedEMAEMAWithin(fast, slow, timeframe, "Up"/"Down", bars) == 1

True if the fast EMA crossed the slow EMA (Golden/Death Cross) within the last bars bars. Catches fresh crossovers that may have occurred 1–N bars ago.

Returns: Golden Cross or Death Cross + BarsAgo + EMA values at crossover date

Examples

CrossedEMAEMAWithin(20, 50, "d", "Up", 10) = 1    // golden cross in last 10 days
CrossedEMAEMAWithin(50, 200, "d", "Down", 5) = 1  // death cross in last 5 days
CrossedEMAEMAWithin(12, 26, "d", "Up", 3) = 1     // MACD-EMA cross in last 3 days
Tip: Use a small bars value (3–5) for fresh signals, larger (10–20) to allow entry after confirming the cross holds.

Technical Indicators

IndicatorRSI(period, timeframe) <operator> value

Relative Strength Index (0–100). Below 30 = oversold; above 70 = overbought. Wilder smoothing via Skender library.

Examples

RSI(14, "d") < 30   // oversold
RSI(14, "d") > 45
RSI(14, "d") < 65   // momentum zone
RSI(14, "d") < 30 OR Stochastic(14,3,"d") < 20
Indicator MACD(fast, slow, signal, timeframe)
MACDSignal(fast, slow, signal, timeframe)
MACDHistogram(fast, slow, signal, timeframe)

Three functions for the three MACD components. Standard parameters: fast=12, slow=26, signal=9.

Examples

MACD(12, 26, 9, "d") > 0           // MACD above zero
MACDHistogram(12, 26, 9, "d") > 0  // histogram positive (bullish cross)
IndicatorBollingerPosition(period, stdDev, timeframe) <operator> value

Position within Bollinger Bands: 0 = lower band, 100 = upper band, 50 = middle SMA.

Examples

BollingerPosition(20, 2, "d") < 15  // near lower band
BollingerPosition(20, 2, "d") > 85  // near upper band
IndicatorBollingerWidth(period, stdDev, timeframe) <operator> value

Band width as % of SMA: (Upper − Lower) / SMA × 100. Low = squeeze; high = volatility.

Examples

BollingerWidth(20, 2, "d") < 8   // tight squeeze
BollingerWidth(20, 2, "d") > 20  // high volatility regime
IndicatorATR(period, timeframe) <operator> value

Average True Range — absolute price range in ticker currency. Also adds ATR% column.

IndicatorNEWATRPerc(period, timeframe) <operator> value

ATR expressed as a percentage of the current close: ATR / Close × 100. More useful than raw ATR for comparing volatility across instruments at different price levels.

Use caseExample
Filter too-calm stocksATRPerc(14, "d") > 1.5
Filter too-volatile stocksATRPerc(14, "d") < 4
Position sizing inputUse ATRPerc to normalise stop distances

Examples

ATRPerc(14, "d") > 1.5   // at least 1.5% daily range — enough movement
ATRPerc(14, "d") < 5     // not too wild
ATRPerc(14, "d") > 2     // combined: 2–5% sweet spot for swing trading
ATRPerc(14, "d") < 5
Also adds column: ATR(N,tf) absolute value.
Indicator Stochastic(kPeriod, dPeriod, timeframe) <operator> value  /  StochasticD(kPeriod, dPeriod, timeframe)

Stochastic = %K line; StochasticD = %D smoothed. Both 0–100.

IndicatorROC(period, timeframe) <operator> value

Rate of Change — % price change over N periods via Skender library.

IndicatorRelativeStrength(period, timeframe, benchmarkTicker) <operator> value

Relative strength vs a benchmark. Value above 1.0 = outperforming.

Example

RelativeStrength(63, "d", "^GSPC") > 1.0

Volatility & Change Functions

VolatilityChangePerc(period, timeframe) <operator> value

% price change from N bars ago to today.

Examples

ChangePerc(63, "d") > 10   // +10% over 3 months
ChangePerc(13, "w") > 8    // +8% over 1 quarter weekly
Volatility ChangePercStartYear()  /  ChangePercStartMonth()  /  ChangePercStartWeek()

YTD, MTD and WTD returns. No parameters.

VolatilityAvgVolatility(period, timeframe) <operator> value

Annualised standard deviation of log returns over N periods (%).

VolatilityAvgVolatilityIntraday(period, timeframe) <operator> value

Average High−Low range per candle from the DB intra_volatility field.

VolatilityMomentumSlope(period, timeframe) <operator> value

Linear regression slope of closing prices over N bars, as % per bar. More robust than a single-bar change.

Examples

MomentumSlope(20, "d") > 0.3  // steady upward drift
MomentumSlope(20, "d") > 0    // any positive slope
VolatilityChangePercAcceleration(shortPeriod, longPeriod, timeframe) <operator> value

Ratio of short-term vs long-term momentum (period-normalised). Value > 1 = accelerating.

Example

ChangePercAcceleration(5, 20, "d") > 1   // short-term faster than long-term

Price Structure Functions

StructureConsecutiveCandles(n, "green"/"red", timeframe) <operator> count

Counts consecutive same-colour candles ending at the most recent bar.

Examples

ConsecutiveCandles(3, "red", "d") = 3   // exactly 3 red candles
ConsecutiveCandles(4, "green", "d") >= 4
StructureGapUp(minPercGap, timeframe)  /  GapDown(minPercGap, timeframe)

Detects a gap between today's open and the previous close of at least minPercGap%.

StructureInsideBar(timeframe)

Last candle fully contained within the previous candle's range. Classic consolidation signal.

StructureNarrowRangeBar(nrBars, lookback, timeframe)

Classic NR-N pattern: last candle has the narrowest range among the last nrBars over a lookback window.

Example

NarrowRangeBar(7, 20, "d")  // classic NR7
StructureHigherHighs(n, timeframe)  /  LowerLows(n, timeframe)

Verifies that the last N swing highs (or lows) are progressively higher (or lower). Requires ~N×10 bars of history.

Examples

HigherHighs(3, "d")  // 3 rising swing highs
LowerLows(3, "d")   // 3 falling swing lows
StructureNEW HighestHigh(period, timeframe) <operator> value  /  LowestLow(period, timeframe) <operator> value

Returns the highest High (or lowest Low) value over the last N bars. Useful for absolute price-level filters and breakout reference points.

Examples

HighestHigh(52, "w") > 100   // 52-week high above 100
LowestLow(20, "d") > 10    // 20-day low still above 10
HighestHigh(20, "d") < 500  // price cap filter
StructureNEW DistancePercFromHigh(period, timeframe) <operator> value

Distance in % from the highest High of the last N bars. Negative when below the high (the normal case). Use to find stocks near N-period highs.

Examples

DistancePercFromHigh(20, "d") > -5   // within 5% of 20-day high — momentum
DistancePercFromHigh(52, "w") > -10  // within 10% of 52-week high
DistancePercFromHigh(20, "d") < -20  // more than 20% off high — deep pullback
Also adds column: Highest(N,tf) — the actual high value.
StructureNEW DistancePercFromLow(period, timeframe) <operator> value

Distance in % from the lowest Low of the last N bars. Positive when above the low. Use to find stocks bouncing from N-period lows.

Examples

DistancePercFromLow(20, "d") < 10   // within 10% of 20-day low — reversal zone
DistancePercFromLow(52, "w") < 15  // near 52-week low — potential bottom fishing
Also adds column: Lowest(N,tf) — the actual low value.
StructureNEW BreakoutHigh(period, timeframe) == 1  /  BreakdownLow(period, timeframe) == 1

True (1) if the current close exceeds the highest High (or is below the lowest Low) of the previous N bars, excluding the current bar itself. Classic breakout/breakdown signal.

âš  The current bar is always excluded from the reference range to avoid self-comparison. Requires operator == 1.

Examples

BreakoutHigh(20, "d") == 1   // 20-day breakout — Donchian-style
BreakdownLow(52, "w") == 1   // 52-week breakdown — weakness signal

// Breakout with volume confirmation
BreakoutHigh(20, "d") == 1
VolumeChangeVsAvg(20, "d") > 50
RSI(14, "d") > 50
Also adds column: Prev High(N) or Prev Low(N) — the reference level that was broken.
StructureNEW Candle component functions (all on the last bar)

A family of functions that expose the individual parts of the most recent candle. All take only timeframe as parameter.

FunctionReturnsExample
Open(tf)Opening priceOpen("d") > 10
High(tf)Session highHigh("d") < 500
Low(tf)Session lowLow("d") > 5
Range(tf)High − LowRange("d") > 2
BodySize(tf)|Close − Open|BodySize("d") > 1
UpperWick(tf)High − Max(Open, Close)UpperWick("d") < 0.5
LowerWick(tf)Min(Open, Close) − LowLowerWick("d") > 0.3
IsBullishCandle(tf)1 if Close > Open, else 0IsBullishCandle("d") == 1
IsBearishCandle(tf)1 if Close < Open, else 0IsBearishCandle("d") == 1

Examples

// Hammer candle: small body, large lower wick, small upper wick
BodySize("d") < 1
LowerWick("d") > 2
UpperWick("d") < 0.5
IsBullishCandle("d") == 1

// Wide range bullish day
Range("d") > 3
IsBullishCandle("d") == 1
VolumeChangeVsAvg(20, "d") > 80
Structure NEW PriceNearManualStudy([threshold%] [, "studyType"])

Returns true if the current price is within threshold% of any manually-drawn study (trendlines, horizontal lines, Fibonacci retracements) that is active on the chart for that ticker. Studies are drawn by the user in the gsStockAnalyzer chart panel and saved to the database.

🖊 What counts as a manual study? Any chart annotation saved in the chart_studies table with is_active = 1: trendlines, horizontal lines, ray lines, extended lines, and Fibonacci retracements drawn via the drawing toolbar in the chart panel.
ParameterDefaultDescription
threshold%2.0Maximum distance from the study level, as % of price. E.g. 2 = within ±2%.
studyType(all)Optional filter: "trendline", "fibonacci", or "horizontal". Leave empty to match all types.

Examples

// Any manual study within 2% (default)
PriceNearManualStudy()

// Tighter threshold: within 1%
PriceNearManualStudy(1.0)

// Only fibonacci studies, within 2%
PriceNearManualStudy(2.0, "fibonacci")

// Only trendlines, within 1.5%
PriceNearManualStudy(1.5, "trendline")
Tip: This is the go-to function when you have a watchlist of stocks where you've already drawn key levels on the chart and want to be alerted when price approaches one of them.
Structure NEW PriceNearTrendline([threshold%])

Returns true if the current price is within threshold% of a manually-drawn trendline. The trendline value is computed via linear interpolation of its two anchor points, projected to today's date — so inclined trendlines are properly supported.

⚙ How the trendline value is calculated: Given two points P1 (date₁, price₁) and P2 (date₂, price₂), the engine computes the expected price at today's date using linear interpolation:
value = price₁ + (today − date₁) / (date₂ − date₁) × (price₂ − price₁)
This works even when today's date is beyond P2 (extrapolation), so inclined trendlines remain valid over time. A trendline is automatically classified as horizontal when the price difference between its two points is < 0.1%.
ParameterDefaultDescription
threshold%2.0Maximum distance from the trendline value, as % of price.

Examples

// Price within 2% of any manual trendline (default)
PriceNearTrendline()

// Tighter: within 1.5%
PriceNearTrendline(1.5)

// Trendline proximity + uptrend context
PriceNearTrendline(2.0)
IsUpTrend(30, "d")
RSI(14, "d") < 50
Structure NEW PriceNearFibonacci([threshold%] [, "level"])

Returns true if the current price is within threshold% of a level from a manually-drawn Fibonacci retracement on the chart. Supports all standard levels. Optionally filter to a specific level (e.g. "61.8%").

📐 Standard Fibonacci levels checked: 0%, 23.6%, 38.2%, 50%, 61.8%, 78.6%, 100%. Only levels enabled in the chart drawing (show_levels) are evaluated. Works for both bullish (ascending) and bearish (descending) Fibonacci drawings.
ParameterDefaultDescription
threshold%2.0Maximum distance from any Fibonacci level, as % of price.
level(all)Optional: check only a specific level string, e.g. "61.8%", "50%", "38.2%".

Examples

// Near any Fibonacci level within 2%
PriceNearFibonacci()

// Near 61.8% (Golden Ratio) within 1.5%
PriceNearFibonacci(1.5, "61.8%")

// Near 50% level within 2%
PriceNearFibonacci(2.0, "50%")

// Near 38.2% with RSI oversold — classic bounce setup
PriceNearFibonacci(2.0, "38.2%")
RSI(14, "d") < 45
✅ The difference from FiboNearLevel: FiboNearLevel calculates Fibonacci automatically from the swing high/low of the last N bars. PriceNearFibonacci uses only Fibonacci drawings that the user has manually placed on the chart — which are often more meaningful as they reflect key historical pivots the trader has identified.
Structure NEW TrendlineBreakout([tolerance%])

Returns true if the price has crossed a manually-drawn trendline in the last candle. The engine checks whether the close was on one side of the trendline yesterday and on the opposite side today (both bullish breakout ↑ and bearish breakdown ↓ are detected).

🔍 Detection logic (per trendline):
Bullish breakout: yesterday's close ≤ trendline value × (1 + tolerance) AND today's close ≥ trendline value × (1 − tolerance)
Bearish breakdown: yesterday's close ≥ trendline value × (1 − tolerance) AND today's close ≤ trendline value × (1 + tolerance)
The trendline value is interpolated to yesterday's and today's date respectively.
ParameterDefaultDescription
tolerance%0.5Tolerance band around the trendline. Avoids false signals from prices that just graze the line without committing.

Examples

// Any trendline breakout, default tolerance 0.5%
TrendlineBreakout()

// Tighter confirmation: must cross by at least 1%
TrendlineBreakout(1.0)

// Trendline breakout + volume confirmation
TrendlineBreakout()
VolumeChangeVsAvg(20, "d") > 30

// Breakout + RSI exiting oversold — strong reversal signal
TrendlineBreakout()
RSI(14, "d") > 30
RSI(14, "d") < 55
âš  Prerequisite: This function only triggers on tickers that have at least one manually-drawn trendline saved in the database. Tickers without chart studies are automatically excluded.
StructurePriceNearLevel(price, distPerc)

Price within distPerc% of a manually specified level.

StructurePriceNearPivotPoint(distPerc)

Price within distPerc% of any saved level in tickers_pivot_point.

StructureRelativePerformance(period, timeframe, benchmarkTicker) <operator> value

Delta: ChangePerc(ticker) − ChangePerc(benchmark). Positive = outperforming.

Example

RelativePerformance(63, "d", "^GSPC") > 5

Trend Detection Functions v1.1+

🧠 How trend detection works: Both IsUpTrend and IsDownTrend combine three independent criteria for high reliability. A ticker passes only if all three conditions are met simultaneously:
  1. Linear Regression Slope — fits a line through the last N closing prices. Positive slope = structural uptrend, negative = downtrend. Immune to single-bar spikes.
  2. Price vs EMA(N) — the current close must be above (uptrend) or below (downtrend) the EMA of the same period. Avoids false signals when price temporarily returns near the average.
  3. R² ≥ 0.3 — coefficient of determination of the regression. Filters out sideways/chaotic price action: if R² is low, the movement is random, not a real trend.
Trend NEW IsUpTrend(period, timeframe)

Returns true if the ticker is in a confirmed uptrend over the last N bars. No comparison operator needed — it's a boolean filter.

ParameterTypeDescription
periodint ≥ 5Number of bars to analyse (e.g. 30 = last 30 daily bars, 52 = last 52 weekly bars)
timeframestring"d" daily, "w" weekly, "m" monthly
✅ Grid columns added: TrendDir (↑ UpTrend)  Â·  Slope%/bar (normalised slope)  Â·  R² (trend quality 0–1)  Â·  EMA{N} (EMA value at period N)

Examples

// Uptrend over the last 30 daily bars
IsUpTrend(30, "d")

// Uptrend over the last 52 weekly bars (1 year)
IsUpTrend(52, "w")

// Multi-timeframe: confirmed uptrend on both daily and weekly
IsUpTrend(30, "d")
IsUpTrend(52, "w")

// Combine with RSI for a pullback entry in an uptrend
IsUpTrend(63, "d")
RSI(14, "d") < 45
AvgCounterValue(20, "d") > 500000
Typical period guidelines:
IsUpTrend(20, "d") = short-term (1 month)  Â·  IsUpTrend(63, "d") = medium-term (3 months)  Â·  IsUpTrend(252, "d") = long-term (1 year)  Â·  IsUpTrend(52, "w") = yearly weekly view
Trend IsDownTrend(period, timeframe)

Returns true if the ticker is in a confirmed downtrend over the last N bars. Uses the same three-criteria engine as IsUpTrend but with inverted conditions (negative slope, price below EMA, R² ≥ 0.3).

ParameterTypeDescription
periodint ≥ 5Number of bars to analyse
timeframestring"d" daily, "w" weekly, "m" monthly
✅ Grid columns added: TrendDir (↓ DownTrend)  Â·  Slope%/bar  Â·  R²  Â·  EMA{N}

Examples

// Downtrend over the last 30 daily bars
IsDownTrend(30, "d")

// Quarterly downtrend on weekly chart (13 weeks = 3 months)
IsDownTrend(13, "w")

// Downtrend with volume surge — possible capitulation / short squeeze
IsDownTrend(30, "d")
VolumeProfile(20, "d") > 90
CandleType(1, "d", "green")

// Find stocks to avoid: weekly downtrend AND daily downtrend
IsDownTrend(26, "w")
IsDownTrend(30, "d")
⚠ R² threshold: The R² filter of 0.3 is intentionally conservative — it keeps real noisy trends while rejecting pure sideways chop. If you need stricter filtering, combine with MomentumSlope for an additional slope threshold:
IsDownTrend(30, "d")
MomentumSlope(30, "d") < -0.1
Trend NEW WasUpTrend(period, timeframe, barsAgo) == 1  /  WasDownTrend(period, timeframe, barsAgo) == 1

Checks whether the ticker was in an uptrend (or downtrend) N bars ago, using the same three-criteria engine as IsUpTrend/IsDownTrend. Designed for pullback and reversal strategies: first confirm a prior trend, then apply current-state filters.

ParameterTypeDescription
periodint ≥ 5Number of bars analysed in the historical window
timeframestring"d", "w", "m"
barsAgoint ≥ 1How many bars ago to evaluate the trend (e.g. 10 = check trend 10 bars back)
Returns: Was UpTrend or Was DownTrend + CheckedAt (date of evaluation)

Examples — Pullback in uptrend

// Was in uptrend 10 days ago, now pulling back — classic re-entry setup
WasUpTrend(30, "d", 10) == 1
RSI(14, "d") < 45
DistancePercFromHigh(20, "d") < -5   // has pulled back at least 5%
DistancePercFromHigh(20, "d") > -15  // but not more than 15%

Examples — Trend reversal / short covering

// Was in downtrend, now showing recovery signs
WasDownTrend(20, "d", 5) == 1
IsUpTrend(10, "d")              // trend has now turned up
VolumeProfile(20, "d") > 80    // high volume on the reversal
Tip: Combine WasUpTrend with IsDownTrend to find a change of character:
WasUpTrend(30, "d", 15) == 1  // was up 15 days ago
IsDownTrend(10, "d")           // now confirmed down — trend broken
Trend NEW LookForTrendline(source, timeframe, lookback, minTouches, maxAge, tolerance%) > score

Finds a recent, still-valid trendline that may be useful for a trading setup. The detector searches for support through recent lows, resistance through recent highs, or both when using closing prices.

Unlike IsUpTrend/IsDownTrend, this function projects the detected line to the current bar and keeps the ticker only when the current close is near that projected level.

ParameterTypeDefaultDescription
sourcestring"Low""Low" searches support; "High" searches resistance; "Close" searches both.
timeframestringscript timeframe"d" daily, "w" weekly, "m" monthly, or an available intraday timeframe.
lookbackint100Maximum number of recent bars used to build the line. Older bars are ignored.
minTouchesint3Minimum number of aligned swing points required to confirm the trendline.
maxAgeint15Maximum number of bars since the last touch. This excludes old, inactive trendlines.
tolerance%number1.5Allowed alignment and current-price distance, expressed as a percentage.
scorenumber—Comparison threshold for the quality score. The score combines touches, line fit, recency and current proximity.
Detection rules: the line must have enough touches, the last touch must be recent, the source prices must not have clearly broken the line, and the current close must be near the line's projected value. This intentionally filters out old or already-invalidated trendlines.
Extra data: TrendlineQuality · TrendlineLine · TrendlineDistance · TrendlineTouches · TrendlineLastTouchBarsAgo · TrendlineSlopePctBar · TrendlineR2 · TrendlineSource · TrendlineKind

Examples

// Recent support: at least 3 touches, last touch within 15 bars
LookForTrendline("Low", "d", 100, 3, 15, 1.5) > 70

// Recent resistance on weekly highs
LookForTrendline("High", "w", 52, 3, 8, 2.0) > 65

// Either support or resistance near the current close
LookForTrendline("Close", "d", 80, 3, 10, 2.0) > 70

// Trading setup: recent support plus a bullish candle
LookForTrendline("Low", "d", 120, 3, 12, 1.5) > 75
IsBullishCandle("d") == 1
RSI(14, "d") < 55
Practical tuning: use maxAge aggressively when you only want actionable lines. For daily setups, 5–20 bars is a reasonable starting range. Increase tolerance% for volatile instruments, but wider tolerance also accepts less precise lines.
Trend NEW LookForChannel(timeframe, lookback, minTouches, maxAge, tolerance%, maxWidth%) > score
LookForRisingChannel(...)  /  LookForFallingChannel(...)  /  LookForHorizontalChannel(...)

Finds an actionable price channel near the current bar by fitting a support line on recent lows and a resistance line on recent highs. The detector keeps only channels that are still valid, reasonably parallel, and close enough to current price to matter for a trade setup.

ParameterTypeDefaultDescription
timeframestringscript timeframe"d" daily, "w" weekly, "m" monthly, or an available intraday timeframe.
lookbackint120Maximum number of recent bars used to build the channel.
minTouchesint3Minimum aligned touches required on both sides of the structure.
maxAgeint20Maximum bars since the latest support or resistance touch.
tolerance%number1.5Allowed deviation for line fitting and channel containment.
maxWidth%number18Maximum channel width, expressed as a percentage of current price.
scorenumber-Comparison threshold for the quality score. The score combines touches, fit, recency, parallelism and current proximity.
Extra data: ChannelQuality · ChannelType · ChannelSupport · ChannelResistance · ChannelWidthPct · ChannelDistanceToSupport · ChannelDistanceToResistance · ChannelSupportTouches · ChannelResistanceTouches · ChannelSupportSlopePctBar · ChannelResistanceSlopePctBar

Examples

// Any valid channel near current price
LookForChannel("d", 120, 3, 20, 1.5, 18) > 65

// Rising channel only
LookForRisingChannel("d", 120, 3, 20, 1.5, 18) > 70

// Horizontal channel on weekly bars
LookForHorizontalChannel("w", 52, 3, 12, 2.0, 15) > 65
Practical tuning: use smaller maxAge when you want fresh channels ready for a bounce or breakout, and lower maxWidth% when you only want tighter structures.

Fibonacci Functions

How auto-Fibonacci works: The engine now prefers the best recent meaningful swing by evaluating local pivot highs/lows, directional order, swing amplitude, and recency before calculating standard retracement levels. Standard levels: 0, 23.6, 38.2, 50, 61.8, 78.6, 100.
FibonacciFiboNearLevel(period, timeframe, level, tolerance) UPDATED

FILTER Keeps only tickers whose current price is within tolerance% of a Fibonacci retracement level detected from a meaningful recent swing.

ParameterDescription
periodBars to look back for swing detection
level0 / 23.6 / 38.2 / 50 / 61.8 / 78.6 / 100
toleranceMax distance from level (%)

Examples

FiboNearLevel(63, "d", 61.8, 2)   // near Golden Ratio ±2%
FiboNearLevel(52, "w", 38.2, 2)   // weekly 38.2% level
Extra data: FibonacciDirection · FibonacciLevel · FibonacciLevelPrice · FibonacciDistancePct · FibonacciSwingLow · FibonacciSwingHigh · FibonacciSwingPct · FibonacciSwingStartBarsAgo · FibonacciSwingEndBarsAgo · FibonacciLookback
Practical note: when these extra values are present in scanner results, clicking the ticker can open the chart with the detected Fibonacci retracement pre-drawn.
Fibonacci LookForFibonacci(period, timeframe, level, tolerance%) > score  /  LookForBullishFibonacci(period, timeframe, level, tolerance%) > score  /  LookForBearishFibonacci(period, timeframe, level, tolerance%) > score NEW

Finds an actionable Fibonacci retracement setup around a significant recent swing and returns a quality score. Unlike FiboNearLevel, this function is meant to rank the setup, not just confirm proximity.

LookForBullishFibonacci keeps low-to-high swings followed by a pullback; LookForBearishFibonacci keeps high-to-low swings followed by a rebound.

ParameterTypeDescription
periodintRecent bars inspected to detect the swing. Typical daily values: 63 for about 3 months, 126 for about 6 months, 252 for about 12 months, or 52 on "w" for roughly 1 year of weekly pivots.
timeframestring"d" daily, "w" weekly, "m" monthly, or an available intraday timeframe.
levelnumberTarget Fibonacci retracement level, typically 23.6, 38.2, 50, 61.8, or 78.6.
tolerance%numberHow close price must be to the requested level. Typical values: 1.0-3.0.
What the detector looks for: the absolute swing extremes inside the selected window. For bullish setups it starts from the lowest low in the lookback and then uses the highest high reached after that low; for bearish setups it starts from the highest high and then uses the lowest low reached after that high. The move must still be large enough to matter, span a reasonable part of the selected window, produce a recent retracement phase, and leave the current close close enough to the requested level to stay tradable. Directional variants also keep price on the expected side of the Fibonacci level: LookForBullishFibonacci requires the close to be above the level, while LookForBearishFibonacci requires it to be below.
Extra data: FibonacciQuality · FibonacciDirection · FibonacciStrength · FibonacciLevel · FibonacciLevelPrice · FibonacciDistancePct · FibonacciSwingLow · FibonacciSwingHigh · FibonacciSwingPct · FibonacciTolerancePct · FibonacciSwingStartBarsAgo · FibonacciSwingEndBarsAgo · FibonacciSwingStartPrice · FibonacciSwingEndPrice · FibonacciLookback

Examples

// About 3 months of daily data
LookForFibonacci(63, "d", 61.8, 2) > 60

// Better when you want a more important daily swing (about 6 months)
IsUpTrend(60, "d")
LookForBullishFibonacci(126, "d", 61.8, 1.5) > 65

// Weekly bearish retracement into resistance
LookForBearishFibonacci(52, "w", 61.8, 2.5) > 58
Practical tuning: 63, "d" only scans about the last 3 months, so it is often too short if you want Fibonacci anchors from major 6-12 month pivots. For stronger setups, try 126 or 252 daily bars, or move to "w". The detector now uses the absolute extremes of the selected window instead of trying to rank many local pivots, so long lookbacks behave in a more deterministic way. Directional variants are side-aware: bullish means price is testing the level from above, bearish means price is testing it from below. The most useful combinations are usually LookForBullishFibonacci + IsUpTrend for pullback entries, or LookForBearishFibonacci + IsDownTrend for rebound-into-resistance scans. Raising the minimum score is usually better than widening tolerance too much. Clicking the ticker can also open the chart with the detected Fibonacci retracement pre-drawn.
FibonacciFiboPosition(period, timeframe)

EXPLORE Does not filter — shows nearest Fibonacci level, distance, 0–100% position in the swing range.

FibonacciDistanceFromFibo(period, timeframe, retrLevel) <operator> value

Distance in % from a Fibonacci level. Consider using FiboNearLevel for new scripts.

Candlestick Pattern Functions NEW

All candlestick functions return 1 if the pattern is detected on the last candle(s). Use with == 1. They work on any timeframe.
CandlestickNEWIsDoji(timeframe) == 1

Last candle has a very small body relative to its total range (body < 10% of range). Signals indecision. Combine with BollingerPosition or RSI at extremes for reversal setups.

Example

IsDoji("d") == 1
BollingerPosition(20, 2, "d") > 80
CandlestickNEW IsHammer(timeframe) == 1  /  IsShootingStar(timeframe) == 1

IsHammer: small body in upper half of range, long lower wick (≥ 2× body). Bullish reversal signal after a downtrend.
IsShootingStar: same shape inverted — long upper wick. Bearish reversal after an uptrend.

Example

// Hammer on support
IsHammer("d") == 1
DistancePercFromEMA(50, "d") > -3
CandlestickNEW IsBullishEngulfing(timeframe) == 1  /  IsBearishEngulfing(timeframe) == 1

The body of the last candle completely engulfs the body of the previous candle. One of the most reliable two-candle reversal signals.

Example

// Bullish engulfing on EMA support
IsBullishEngulfing("d") == 1
DistancePercFromEMA(200, "d") > -3
CandlestickNEW IsMorningStar(timeframe) == 1  /  IsEveningStar(timeframe) == 1

3-candle patterns. Morning Star: bearish candle + small indecision candle + bullish candle closing above midpoint of first. Stronger than single-candle signals.
Evening Star: the bearish mirror pattern.

Example

IsMorningStar("w") == 1
RSI(14, "w") < 40
CandlestickNEW IsThreeWhiteSoldiers(timeframe) == 1  /  IsThreeBlackCrows(timeframe) == 1

3 consecutive bullish (or bearish) candles, each opening within the previous body and closing higher (or lower). Strong continuation signal after a breakout.

Example

IsThreeWhiteSoldiers("d") == 1
VolumeChangeVsAvg(20, "d") > 20
CandlestickNEW IsBullishMarubozu(timeframe) == 1  /  IsBearishMarubozu(timeframe) == 1

A candle where the body occupies ≥ 95% of the total range (almost no wicks). Signals strong conviction in the direction of the move.

CandlestickNEW IsBullishHarami(timeframe) == 1  /  IsBearishHarami(timeframe) == 1

A small candle whose body is contained within the body of the previous (opposite-color) candle. Weaker than Engulfing but still a valid reversal hint.

CandlestickNEW IsPiercingLine(timeframe) == 1  /  IsDarkCloudCover(timeframe) == 1

Two-candle reversal patterns: Piercing Line is the bullish version after a bearish candle; Dark Cloud Cover is its bearish mirror. The second candle must close beyond the midpoint of the first body.

CandlestickNEW IsBullishTweezer(timeframe) == 1  /  IsBearishTweezer(timeframe) == 1  /  IsOutsideBar(timeframe) == 1  /  IsNR7(timeframe) == 1

Tweezer patterns use near-equal lows/highs with opposite candle direction. Outside Bar is a full range expansion beyond the preceding candle. NR7 flags the narrowest range of the latest seven bars, a useful volatility-compression alert. IsBullishPinBar / IsBearishPinBar are directional hammer/shooting-star variants; IsGapUp, IsGapDown and IsGapFilled identify material overnight gaps and fills.

Chart Pattern Functions

Pattern functions return a quality score 0–100. Use with > 50 for normal quality, > 70 for high-confidence setups. The period parameter controls how many candles back the engine searches.
Pattern LookForFlag(period, timeframe) > score  /  LookForBullFlag(period, timeframe) > score  /  LookForBearFlag(period, timeframe) > score UPDATED

Detects continuation flags: a strong directional pole followed by a controlled pullback channel. The current detector now prefers the best valid setup in the recent window instead of the first one found, and scores the pattern using pole strength, pullback depth, channel geometry, volume contraction, and current distance from the breakout line.

LookForBullFlag keeps bullish continuation setups only; LookForBearFlag keeps bearish ones.

ParameterTypeDescription
periodintMaximum recent bars inspected for the full pattern. Typical daily values: 60-100.
timeframestring"d" daily, "w" weekly, "m" monthly, or an available intraday timeframe.
scorenumberComparison threshold for the quality score. Start around 60 and raise toward 70-75 for cleaner second-leg setups.
What the detector looks for: a sharp pole with directional conviction, then a narrower counter-move or flat channel, limited retracement, softer volume during the flag, and price still close enough to the breakout line to make the setup actionable.
Extra data: FlagQuality · FlagType · FlagStrength · FlagPolePct · FlagChannelHeightPct · FlagRetracementPct · FlagBreakoutLevel · FlagTargetPrice · FlagDistancePct · FlagRiskReward · FlagPoleVolumeRatio · FlagVolumeRatio · FlagUpperTouches · FlagLowerTouches · FlagUpperSlopePctBar · FlagLowerSlopePctBar · FlagUpperR2 · FlagLowerR2 · FlagBreakoutConfirmed · FlagBreakoutTolerancePct · FlagPatternLength

Examples

// Any continuation flag near breakout
LookForFlag(80, "d") > 60

// Bull flag for second-leg momentum entries
IsNotPriceLocked(20, "d") == 1
AvgCounterValue(20, "d") > 500000
IsUpTrend(30, "d")
LookForBullFlag(80, "d") > 68
VolumeChangeVsAvg(20, "d") > 0

// Weekly bear flag
LookForBearFlag(52, "w") > 65
Practical tuning: if your goal is to catch the second rally early, combine LookForBullFlag with an existing trend filter such as IsUpTrend, then raise the minimum score rather than widening the period too much.
Pattern LookForParabolicRun(period, timeframe) > score NEW

Detects bullish parabolic runs: price is not just trending up, but accelerating. The detector compares the first half of the move against the second half, checks whether a quadratic curve fits the price action better than a straight line, and keeps only setups that remain tight near the highs.

ParameterTypeDescription
periodintRecent bars inspected for the accelerating run. Typical daily values: 40-90.
timeframestring"d" daily, "w" weekly, "m" monthly, or an available intraday timeframe.
scorenumberQuality threshold. Start around 55-60; raise to 70 for the cleanest momentum names.
What the detector looks for: a meaningful price expansion, visibly faster second-leg slope, positive curvature, price still close to the highs, contained pullbacks, and the last close staying above short/medium trend anchors such as EMA20 and EMA50.
Extra data: ParabolicRunQuality · ParabolicRunType · ParabolicRunStrength · ParabolicRunAccelerationScore · ParabolicRunCurvature · ParabolicRunQuadraticR2 · ParabolicRunLinearR2 · ParabolicRunFirstHalfSlopePctBar · ParabolicRunSecondHalfSlopePctBar · ParabolicRunPullbackDepthPct · ParabolicRunDistanceFromHighPct · ParabolicRunDistanceFromEma20Pct · ParabolicRunDistanceFromEma50Pct · ParabolicRunVolumeExpansionRatio · ParabolicRunPct · ParabolicRunPatternLength

Examples

// Fast daily momentum leaders
IsNotPriceLocked(20, "d") == 1
AvgCounterValue(20, "d") > 500000
LookForParabolicRun(60, "d") > 62

// Weekly leaders that are still close to the highs
LookForParabolicRun(40, "w") > 68
Practical tuning: this is strongest when paired with liquidity filters and a "not too extended" rule. For example, keep ParabolicRunDistanceFromHighPct small and avoid names that are already too far above your entry plan.
Pattern LookForRoundedBottom(period, timeframe) > score  /  LookForRoundedTop(period, timeframe) > score NEW

Detects rounded reversal structures: a rounded bottom is a U-shaped base where price stabilizes, bottoms out, and then recovers toward the right rim; a rounded top is the bearish mirror image, where the advance loses momentum and rolls over gradually instead of failing in a sharp spike.

ParameterTypeDescription
periodintRecent bars inspected for the rounded structure. Typical daily values: 50-120; weekly values often work well around 30-60.
timeframestring"d" daily, "w" weekly, "m" monthly, or an available intraday timeframe.
scorenumberQuality threshold. Start around 55-60; raise to 70 when you want only the cleanest, most symmetric arcs close to the breakout / neckline area.
What the detector looks for: a quadratic curve that fits the price action better than a straight line, a vertex roughly near the middle of the window, left/right rims that are reasonably balanced, meaningful depth, and a right side that has already recovered (rounded bottom) or rolled over (rounded top) enough to make the setup actionable.
Extra data: RoundedPatternQuality · RoundedPatternType · RoundedPatternStrength · RoundedPatternCurvature · RoundedPatternQuadraticR2 · RoundedPatternLinearR2 · RoundedPatternDepthPct · RoundedPatternLeftRim · RoundedPatternRightRim · RoundedPatternExtreme · RoundedPatternRimSymmetryPct · RoundedPatternDistanceToBreakoutPct · RoundedPatternBreakoutLevel · RoundedPatternVertexPct · RoundedPatternLeftSlopePctBar · RoundedPatternRightSlopePctBar · RoundedPatternLength

Examples

// Rounded accumulation base close to the right rim breakout
LookForRoundedBottom(90, "d") > 62

// Weekly rounded bottom inside a larger uptrend
IsUpTrend(40, "w")
LookForRoundedBottom(52, "w") > 68

// Rounded distribution / topping scan
LookForRoundedTop(80, "d") > 60
RSI(14, "d") > 55
Practical tuning: rounded patterns work best on charts that really have time to build the arc. If you get noisy results, increase period or raise the minimum score rather than lowering it. For bullish scans, pair LookForRoundedBottom with liquidity filters and a trend or relative-strength filter; for bearish scans, LookForRoundedTop becomes much more useful when the instrument is already showing weakening momentum on the right side.
Pattern LookForWedge(period, timeframe) > score  /  LookForRisingWedge(period, timeframe) > score  /  LookForFallingWedge(period, timeframe) > score NEW

Detects converging wedges: both support and resistance move in the same direction, but one side advances faster so the structure compresses toward an apex. LookForWedge returns any valid wedge; the directional variants filter the geometry.

ParameterTypeDescription
periodintRecent bars inspected for the wedge. Typical daily values: 50-100.
timeframestring"d" daily, "w" weekly, "m" monthly, or an available intraday timeframe.
scorenumberQuality threshold. Start around 55; raise toward 70 when you want only the cleanest compressions near the apex.
What the detector looks for: converging trendlines on highs and lows, multiple touches on both sides, most price action still contained inside the pattern, visible width compression, and the current bar still close enough to the wedge edge/apex to be tradable.
Extra data: WedgeQuality · WedgeType · WedgeSupport · WedgeResistance · WedgeWidthStartPct · WedgeWidthEndPct · WedgeCompressionPct · WedgeDistanceToSupportPct · WedgeDistanceToResistancePct · WedgeSupportTouches · WedgeResistanceTouches · WedgeSupportSlopePctBar · WedgeResistanceSlopePctBar · WedgeSupportR2 · WedgeResistanceR2 · WedgeDaysToApex · WedgeTolerancePct · WedgeLookback

Examples

// Any wedge nearing decision point
LookForWedge(80, "d") > 58

// Falling wedge inside a broader uptrend
IsUpTrend(40, "d")
LookForFallingWedge(90, "d") > 62

// Rising wedge as an exhaustion / breakdown watchlist
LookForRisingWedge(70, "d") > 60
Practical tuning: a falling wedge is often more useful as a bullish continuation or reversal setup, while a rising wedge is often more useful as an exhaustion or breakdown alert. The geometry alone does not confirm the breakout direction, so combine with trend and momentum context. In scanner results, clicking the ticker can also open the chart with the wedge trendlines pre-drawn for faster review.
Pattern LookForDoubleTop(period, timeframe) > score  /  LookForDoubleBottom(period, timeframe) > score UPDATED

Classic double-top (bearish reversal) and double-bottom (bullish reversal). Returns a quality score based on peak symmetry, depth of the middle valley/peak, and timing between the two extremes.

Example

// Double bottom + recovery
LookForDoubleBottom(200, "d") > 50
IsUpTrend(20, "d")
PatternLookForCupWithHandle(period, timeframe) > score  /  LookForInvertedCupWithHandle(period, timeframe) > score

Detects a rounded cup followed by a shallow, contracting handle. The inverted version is the bearish mirror. Both return a 0–100 quality score and expose breakout/support, width, volume ratio and pattern length as AdvancedPattern* result data.

Example

LookForCupWithHandle(100, "d") > 60
PatternLookForVCP / LookForRectangle / LookForFlatBase / LookForDarvasBox / LookForTripleTop / LookForTripleBottom / LookForBroadening(period, timeframe) > score

Advanced compression, base and reversal detectors. LookForVCP (also LookForVolatilityContraction) requires progressively narrower ranges and contracting volume. Rectangle/FlatBase/DarvasBox identify tight horizontal bases; TripleTop/Bottom identify three aligned pivots; Broadening identifies a megaphone structure. All return a 0–100 quality score.

Examples

// Tight VCP close to a breakout
LookForVCP(60, "d") > 65

// A high-quality flat base
LookForFlatBase(40, "d") > 60
Pattern LookForHeadAndShoulders(period, timeframe) > score  /  LookForInverseHS(period, timeframe) > score  /  LookForInverseHeadAndShoulders(period, timeframe) > score UPDATED

Detects both classic bearish Head & Shoulders tops and bullish Inverse Head & Shoulders bottoms. The score reflects shoulder symmetry, how clearly the head stands out, the time balance between left/right side, and the neckline structure. Clicking a scanner result can open chart.html with the shoulders/head profile and neckline already drawn.

  • LookForHeadAndShoulders finds the bearish top-reversal version.
  • LookForInverseHS finds the bullish bottom-reversal version.
  • LookForInverseHeadAndShoulders is an alias of LookForInverseHS.

Example

// Inverse H&S with RSI confirmation
LookForInverseHS(120, "d") > 55
RSI(14, "d") > 50

Extra data returned

HsQuality
HsType
HsStrength
HsNeckline
HsTargetPrice
HsLeftShoulder / HsHead / HsRightShoulder
HsLeftNeckline / HsRightNeckline
HsLeftShoulderBarsAgo / HsHeadBarsAgo / HsRightShoulderBarsAgo
HsLeftNecklineBarsAgo / HsRightNecklineBarsAgo
HsLeftShoulderDate / HsHeadDate / HsRightShoulderDate
HsLeftNecklineDate / HsRightNecklineDate
HsTimeframe
PatternLookForAscendingTriangle(period, timeframe) > score UPDATED

Ascending triangle: flat resistance + rising support lows. Bullish continuation. Returns quality score based on R² of trendlines and number of touch points.

PatternNEWLookForDescendingTriangle(period, timeframe) > score

Descending triangle: flat support + declining highs. Bearish continuation or breakdown setup.

Example

LookForDescendingTriangle(60, "d") > 50
RSI(14, "d") < 50
PatternNEWLookForSymmetricTriangle(period, timeframe) > score

Symmetric triangle: converging highs and lows with no directional bias. Indicates a compression before a breakout. Use with DaysToConvergence logic to catch imminent breakouts.

Example

// Symmetric triangle + squeeze
LookForSymmetricTriangle(60, "d") > 55
BollingerWidth(20, 2, "d") < 5
PatternLookForTriangleBreakOut(timeframe, showOnlyBreakout, nrLastCandleSignal)

Any triangle breakout. Set showOnlyBreakout to true for confirmed breakouts only.

PatternLookForAscendingTrendLine(nrCandles, timeframe, precisionLevel)

Rising trendline connecting at least 2 swing lows.

UtilityNEW IsNotPriceLocked(period, timeframe) == 1  /  IsPriceLocked(period, timeframe) <operator> value

Detects tickers with frozen prices — typically caused by OPA (takeover bid), delisting, or trading suspension. The function calculates the (max − min) / min × 100 range of closing prices over the last period sessions.

  • IsNotPriceLocked(20, "d") == 1 — passes only tickers with a price range > 0.5% over 20 days. Recommended as the first filter in every scanner.
  • IsPriceLocked(20, "d") < 0.5 — shows only locked tickers (range < 0.5%).
  • IsPriceLocked(20, "d") > 1.0 — equivalent to IsNotPriceLocked with custom threshold.

Example — recommended usage

// Always put this first to skip OPA/delisted tickers
IsNotPriceLocked(20, "d") == 1
AvgCounterValue(20, "d") > 500000
LookForBullFlag(80, "d") > 60

Utility Functions

UtilityFilterTickers(sqlWhereClause)

Reloads the ticker list using a SQL WHERE clause on the tickers table. Use as the first line to define your universe.

Examples

FilterTickers(country = 'IT')
FilterTickers(type = 'COMM')
FilterTickers(watchlist LIKE '%MyWatchlist%')
FilterTickers(exchange = 'XETRA' AND type = 'STOCK')
UtilityQuantMetric(metric, fiscal_year, fiscal_quarter) <operator> value

Fetches a fundamental metric from the DB. Use 0 for year/quarter to get the most recent value.

Examples

QuantMetric(pe_ratio, 0, 0) < 15
QuantMetric(market_cap, 0, 0) > 1000000000
UtilityAddSignal("signal text")

Writes a text signal to the signals table for all tickers in the current result set.

UtilitySetFilter("label")

Appends a label to tickers.filters for every surviving ticker. Additive — never overwrites existing values.

âš  This function writes to the database. Place it at the end of your script, after all filters.
UtilityNEWSetTickerField("field", "value")

Writes value to a column of the tickers table for every surviving ticker. Overwrites the existing value.

Allowed fieldsDescription
watchlistSystem watchlist (semicolon-separated)
watchlist_userUser watchlist
notesFree-text notes
sectorSector classification
areaGeographic area
countryCountry
partofIndex / group membership
filtersFilter labels (prefer SetFilter to append)

Examples

SetTickerField("notes", "Breakout candidate Apr26")
SetTickerField("watchlist", "MyPortfolio")
âš  Overwrites the field completely. Use AddToWatchlist to append without losing existing watchlists.
UtilityNEWAddToWatchlist("name" [, "user"])

Appends a watchlist name to tickers.watchlist (or watchlist_user) for every surviving ticker. Additive — existing watchlists are preserved. Skips tickers where the name already exists.

Examples

AddToWatchlist("Breakout")
AddToWatchlist("MyFavourites", "user")
UtilityNEWRemoveFromWatchlist("name" [, "user"])

Removes the specified watchlist name from tickers.watchlist (or watchlist_user) for every surviving ticker. Other watchlists on the same ticker are preserved.

Examples

// Remove downtrend tickers from watchlist
IsDownTrend(30, "d")
RemoveFromWatchlist("Breakout")
UtilityNEWQuoteAge(tf)

Returns the number of calendar days elapsed since the last available quote bar for the given timeframe. Use this function to exclude tickers whose price data is not up to date — for example, stale feeds, suspended instruments, or exotic markets with irregular trading calendars.

A low value means fresh data. A high value means the last quote is old. The function reads only the most recent bar (limit = 3), so it is very fast and ideal as a first filter to quickly shrink the universe.

ParameterTypeDescription
tfstring requiredTimeframe: "d", "w", "m"
📊 Returns: double — number of calendar days since qs[^1].Date relative to DateTime.UtcNow. Returns null (ticker excluded) if no quotes are available.
📅 Calendar days vs trading days: The value is in calendar days, not market sessions. A stock traded on Friday will show ~2–3 days on Monday morning. Always add a small buffer for weekends and local holidays. A threshold of < 5 covers a typical long weekend safely; < 3 is strict and may drop valid tickers on Monday mornings.
Place QuoteAge at the very top of your script, before any expensive indicator computation. It loads only the last 3 bars and eliminates stale tickers immediately, which speeds up the rest of the scan significantly.

Examples

// Strict: only tickers updated in the last 3 calendar days
QuoteAge("d") < 3

// Recommended: covers weekends and single holidays
QuoteAge("d") < 5

// Weekly timeframe — accept up to 2 weeks old
QuoteAge("w") < 14

// Combine with IsPriceLocked for maximum data-quality pre-filtering
QuoteAge("d") < 5
IsNotPriceLocked(20, "d") == 1

Complete Script Examples

🚩 Bull Flag Scanner — Europe Daily

// @StrategyName: Bull Flag Europa Daily
// @StrategyCode: bull_flag_eu_d
// @Area: pattern
// @Timeframe: d

// 1. Exclude OPA / delisted / frozen tickers
IsNotPriceLocked(20, "d") == 1

// 2. Liquidity: avg daily counter value > 500k
AvgCounterValue(20, "d") > 500000

// 3. Penny stock exclusion
Low("d") > 1

// 4. Trend filter: price near or above EMA50, slope rising
DistancePercFromEMA(50, "d") > -8
EMASlope(50, "d") > 0

// 5. Bull flag pattern with quality score >= 60
LookForBullFlag(80, "d") > 60

📈 Momentum Breakout Scanner

// @StrategyName: Momentum Breakout
// @StrategyCode: momentum_breakout
// @StrategyDescription: EU liquid stocks with strong 3-month performance, EMA structure intact, RSI in momentum zone.
// @Area: europe
// @Timeframe: d

FilterTickers(country = 'EU' AND type = 'STOCK')
AvgCounterValue(20, "d") > 1000000
ChangePerc(63, "d") > 15
ChangePercStartYear() > 10
DistancePercFromEMA(50, "d") > 0
EMASlope(50, "d") > 0.02
RSI(14, "d") > 50
RSI(14, "d") < 70
VolumeChangeVsAvg(20, "d") > 20
HigherHighs(3, "d")

🗜️ Bollinger Squeeze Pre-Breakout

AvgCounterValue(20, "d") > 300000
ChangePerc(63, "d") > 5
EMASlope(50, "d") > 0
BollingerWidth(20, 2, "d") < 12
AvgVolatility(20, "d") < 2
BollingerPosition(20, 2, "d") > 25
BollingerPosition(20, 2, "d") < 75
RSI(14, "d") > 40
RSI(14, "d") < 68
VolumeProfile(20, "d") < 40

📉 Oversold Reversal Scanner

AvgCounterValue(20, "d") > 500000
ChangePerc(126, "d") > 10
DistancePercFromSMA(200, "d") > 0
ChangePerc(10, "d") < -5
RSI(14, "d") < 35 OR Stochastic(14,3,"d") < 25
DistancePercFromEMA(50, "d") > -5
DistancePercFromEMA(50, "d") < 5
ConsecutiveCandles(3, "red", "d") >= 3

🌀 Fibonacci Retracement Entry

AvgCounterValue(20, "d") > 500000
ChangePerc(126, "d") > 20
FiboNearLevel(126, "d", 61.8, 2)
RSI(14, "d") > 30
RSI(14, "d") < 55
VolumeChangeVsAvg(20, "d") < 0
EMASlope(200, "d") > 0

✂️ MA Crossover Scanner

AvgCounterValue(20, "d") > 800000
CrossEMAEMA(20, 50, "d", "up")
MACD(12, 26, 9, "d") > 0
RSI(14, "d") > 50
DistancePercFromEMA(50, "d") < 10

💥 Volume Explosion Scanner

AvgCounterValue(20, "d") > 300000
VolumeProfile(30, "d") > 90
LastPercClose("d") > 1.5 OR LastPercClose("d") < -1.5
ChangePerc(63, "d") > 5
CandleType(1, "d", "green")

âš¡ Multi-Signal OR Logic

FilterTickers(type = 'STOCK')
AvgCounterValue(20, "d") > 500000
ChangePerc(126, "d") > 10
DistancePercFromSMA(200, "d") > 0
RSI(14, "d") < 35 OR Stochastic(14,3,"d") < 25 OR BollingerPosition(20,2,"d") < 15
ConsecutiveCandles(3, "red", "d") >= 3

📊 Trend Detection — Multi-Timeframe

Uses IsUpTrend and IsDownTrend to confirm structural trends before applying further filters.

// @StrategyName: Multi-TF Uptrend + Pullback Entry
// @StrategyCode: multitf_uptrend_pullback
// @StrategyDescription: Weekly uptrend confirmed, daily pullback with RSI oversold. High-quality entries only.
// @Area: europe
// @Timeframe: d

// 1. Universe
AvgCounterValue(20, "d") > 500000

// 2. Long-term structure: confirmed weekly uptrend (52 weeks)
IsUpTrend(52, "w")

// 3. Medium-term structure: confirmed daily uptrend (3 months)
IsUpTrend(63, "d")

// 4. Short-term pullback: oversold on daily oscillators
RSI(14, "d") < 45 OR Stochastic(14,3,"d") < 35

// 5. Volume declining on pullback (healthy)
VolumeChangeVsAvg(20, "d") < 0
// ── Downtrend screener: stocks to avoid (or to short) ──
// Both weekly and daily confirmed downtrends
AvgCounterValue(20, "d") > 1000000
IsDownTrend(26, "w")
IsDownTrend(30, "d")
// Sort by Slope%/bar to see the steepest downtrends first

🔄 Pullback Re-entry using WasUpTrend

Identifies stocks that were in a confirmed uptrend recently and are now pulling back — ideal re-entry setups.

// @StrategyName: Pullback Re-entry
// @StrategyCode: pullback_reentry
// @StrategyDescription: Was in uptrend 10 days ago, now pulling back with oversold RSI and declining volume.
// @Area: europe
// @Timeframe: d

AvgCounterValue(20, "d") > 500000

// Was in uptrend 10 bars ago
WasUpTrend(30, "d", 10) == 1

// Pulled back 5–15% from the high
DistancePercFromHigh(20, "d") < -5
DistancePercFromHigh(20, "d") > -15

// Oversold momentum
RSI(14, "d") < 45 OR Stochastic(14, 3, "d") < 35

// Volume declining on pullback (healthy retracement)
VolumeChangeVsAvg(20, "d") < -20

// ATR confirms tradeable volatility
ATRPerc(14, "d") > 1.5
ATRPerc(14, "d") < 5

🖊 Manual Study Proximity Scanner

Scans your watchlist for stocks where the price is currently approaching or breaking key levels you have manually drawn on the chart.

// @StrategyName: Manual Study Proximity
// @StrategyCode: manual_study_proximity
// @StrategyDescription: Alerts when price is near manually drawn trendlines or Fibonacci levels.
// @Area: watchlist
// @Timeframe: d

// 1. Only scan your own annotated watchlist
FilterTickers(watchlist LIKE '%MyWatchlist%')

// 2. Exclude locked / OPA tickers
IsNotPriceLocked(20, "d") == 1

// 3. Price within 2% of any manual study
//    (trendlines + fibonacci combined)
PriceNearManualStudy()
// ── Variant A: only trendlines ──
FilterTickers(watchlist LIKE '%MyWatchlist%')
IsNotPriceLocked(20, "d") == 1
PriceNearTrendline(1.5)
RSI(14, "d") > 30
// ── Variant B: near Fibonacci 61.8% + oversold momentum ──
FilterTickers(watchlist LIKE '%MyWatchlist%')
IsNotPriceLocked(20, "d") == 1
PriceNearFibonacci(2.0, "61.8%")
RSI(14, "d") < 50
VolumeChangeVsAvg(20, "d") < 0   // quiet pullback on fibo
// ── Variant C: fresh trendline breakout with volume ──
// @StrategyName: Trendline Breakout Alert
// @StrategyCode: trendline_breakout_alert
// @Timeframe: d

FilterTickers(watchlist LIKE '%MyWatchlist%')
IsNotPriceLocked(20, "d") == 1
AvgCounterValue(20, "d") > 200000
TrendlineBreakout()
VolumeChangeVsAvg(20, "d") > 20
ATRPerc(14, "d") > 1.0   // enough volatility for a real move

🚀 Breakout Scanner with New Functions

Uses the new BreakoutHigh, CrossedEMAEMAWithin and candle functions to find fresh confirmed breakouts.

// @StrategyName: Confirmed Breakout
// @StrategyCode: confirmed_breakout
// @StrategyDescription: 20-day price breakout with golden cross in last 2 weeks, wide bullish candle, volume.
// @Area: europe
// @Timeframe: d

AvgCounterValue(20, "d") > 1000000

// 20-day price breakout
BreakoutHigh(20, "d") == 1

// Golden cross in last 10 bars — trend confirmation
CrossedEMAEMAWithin(20, 50, "d", "Up", 10) == 1

// Bullish candle with significant body
IsBullishCandle("d") == 1
BodySize("d") > 0.5
UpperWick("d") < BodySize("d")  // wick smaller than body — conviction

// Volume explosion
VolumeProfile(20, "d") > 80

// EMA slope rising
SMASlope(20, "d") > 0.05

gsEasyScript Language Reference v1.4 - gsStockAnalyzer © 2026  |  Built with care for active traders  |  Back to top ↑