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.
Syntax Rules
| Rule | Example |
|---|---|
| One condition per line (implicit AND) | RSI(14, "d") < 30 |
| Semicolons optional | ChangePerc(20, "d") > 5; |
| Multiple conditions same line β AND | RSI(14,"d") > 40; RSI(14,"d") < 70 |
| OR inside a line | RSI(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 comma | 61.8 or 61,8 both valid |
| Function names are case-sensitive | RSI β
rsi β |
// @ 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
| Code | Description |
|---|---|
"d" | Daily candles |
"w" | Weekly candles |
"m" | Monthly candles |
IsUpTrend(52, "w") and then refine entry timing with a daily indicator.Comparison Operators
| Operator | Meaning | Example |
|---|---|---|
> | Greater than | RSI(14,"d") > 50 |
< | Less than | RSI(14,"d") < 30 |
>= | Greater or equal | ChangePerc(5,"d") >= 5 |
<= | Less or equal | BollingerWidth(20,2,"d") <= 8 |
= | Equal (numeric) | ConsecutiveCandles(3,"red","d") = 3 |
!= | Not equal | ConsecutiveCandles(1,"green","d") != 0 |
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
OR only works within a single line. Conditions on separate lines are always AND.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 (
MyEmaandmyemarefer to the same variable). - Substitution uses word-boundary matching, so a variable named
pwill not accidentally replace thepinsideChangePerc.
📄 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
- Variables cannot reference other variables:
MyPeriod = BaseP + 10is 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
LastClose() <operator> valueReturns the most recent closing price of each ticker.
Example
LastClose() > 10
LastClose() < 500
LastPercClose(timeframe) <operator> valuePercentage change of the last closed candle vs the previous one.
Examples
LastPercClose("d") > 3
LastPercClose("d") > 5 OR LastPercClose("d") < -5
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).
| Parameter | Description |
|---|---|
| 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
(Close[0] β Close[1]) / Close[1] Γ 100 Β·
Requires only 2 candles β fastest close-change function available.
Close(period, timeframe) <operator> value / PrevClose(period, timeframe)Closing price N bars ago. Close(1,"d") = yesterday's close.
AvgClose(period, timeframe) <operator> valueAverage closing price over the last N bars.
CandleType(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")
DistancePercFromAllTimeHigh() <operator> valueDistance 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
DistancePercFromAllTimeLow() <operator> valueDistance in % from the all-time low. Always positive or zero. Alias: DistancePercFromAllTimeMin().
EvaluateIfStrongClose(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
VolumeChangePerc(period, timeframe) <operator> valuePercentage change in volume over the last N bars.
Example
VolumeChangePerc(5, "d") > 50VolumeChangeVsAvg(avgPeriod, timeframe) <operator> valueCompares latest volume to the N-bar average. Returns % difference.
Examples
VolumeChangeVsAvg(20, "d") > 100 // double the average
VolumeChangeVsAvg(20, "d") < -30 // quiet consolidation
VolumeChangeVsAvgAtTime(avgPeriod, timeframe) <operator> valueSimilar to VolumeChangeVsAvg but adjusts for time of day (intraday volume explosion detection).
AvgCounterValue(period, timeframe) <operator> valueAverage 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
VolumeProfile(period, timeframe) <operator> valueVolume 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
DistancePercFromSMA(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
DistancePercFromEMA(period, timeframe) <operator> valueSame as DistancePercFromSMA but uses an Exponential Moving Average. Alias: DistPercFromEMA.
CrossEMA(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
CrossEMAEMA(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
EMASlope(period, timeframe) <operator> valueSlope 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
SMASlope(period, timeframe) <operator> valueSame 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
CrossedEMAWithin(period, timeframe, "Up"/"Down", bars) == 1True 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.
| Parameter | Description |
|---|---|
| period | EMA period |
| timeframe | "d", "w", "m" |
| direction | "Up" = bullish cross; "Down" = bearish cross |
| bars | Window size β how many recent bars to scan for the 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
CrossedEMAEMAWithin(fast, slow, timeframe, "Up"/"Down", bars) == 1True 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.
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
Technical Indicators
RSI(period, timeframe) <operator> valueRelative 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
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)
BollingerPosition(period, stdDev, timeframe) <operator> valuePosition 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
BollingerWidth(period, stdDev, timeframe) <operator> valueBand 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
ATR(period, timeframe) <operator> valueAverage True Range β absolute price range in ticker currency. Also adds ATR% column.
ATRPerc(period, timeframe) <operator> valueATR 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 case | Example |
|---|---|
| Filter too-calm stocks | ATRPerc(14, "d") > 1.5 |
| Filter too-volatile stocks | ATRPerc(14, "d") < 4 |
| Position sizing input | Use 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
ATR(N,tf) absolute value.Stochastic(kPeriod, dPeriod, timeframe) <operator> value /
StochasticD(kPeriod, dPeriod, timeframe)
Stochastic = %K line; StochasticD = %D smoothed. Both 0β100.
ROC(period, timeframe) <operator> valueRate of Change β % price change over N periods via Skender library.
RelativeStrength(period, timeframe, benchmarkTicker) <operator> valueRelative strength vs a benchmark. Value above 1.0 = outperforming.
Example
RelativeStrength(63, "d", "^GSPC") > 1.0
Volatility & Change Functions
ChangePerc(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
ChangePercStartYear() / ChangePercStartMonth() / ChangePercStartWeek()
YTD, MTD and WTD returns. No parameters.
AvgVolatility(period, timeframe) <operator> valueAnnualised standard deviation of log returns over N periods (%).
AvgVolatilityIntraday(period, timeframe) <operator> valueAverage HighβLow range per candle from the DB intra_volatility field.
MomentumSlope(period, timeframe) <operator> valueLinear 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
ChangePercAcceleration(shortPeriod, longPeriod, timeframe) <operator> valueRatio 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
ConsecutiveCandles(n, "green"/"red", timeframe) <operator> countCounts 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
GapUp(minPercGap, timeframe) / GapDown(minPercGap, timeframe)Detects a gap between today's open and the previous close of at least minPercGap%.
InsideBar(timeframe)Last candle fully contained within the previous candle's range. Classic consolidation signal.
NarrowRangeBar(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 NR7HigherHighs(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
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
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
Highest(N,tf) β the actual high value.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
Lowest(N,tf) β the actual low value.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.
== 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
Prev High(N) or Prev Low(N) β the reference level that was broken.A family of functions that expose the individual parts of the most recent candle. All take only timeframe as parameter.
| Function | Returns | Example |
|---|---|---|
Open(tf) | Opening price | Open("d") > 10 |
High(tf) | Session high | High("d") < 500 |
Low(tf) | Session low | Low("d") > 5 |
Range(tf) | High β Low | Range("d") > 2 |
BodySize(tf) | |Close β Open| | BodySize("d") > 1 |
UpperWick(tf) | High β Max(Open, Close) | UpperWick("d") < 0.5 |
LowerWick(tf) | Min(Open, Close) β Low | LowerWick("d") > 0.3 |
IsBullishCandle(tf) | 1 if Close > Open, else 0 | IsBullishCandle("d") == 1 |
IsBearishCandle(tf) | 1 if Close < Open, else 0 | IsBearishCandle("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
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.
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.
| Parameter | Default | Description |
|---|---|---|
| threshold% | 2.0 | Maximum 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")
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.
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%.
| Parameter | Default | Description |
|---|---|---|
| threshold% | 2.0 | Maximum 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
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%").
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.
| Parameter | Default | Description |
|---|---|---|
| threshold% | 2.0 | Maximum 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
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.
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).
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.
| Parameter | Default | Description |
|---|---|---|
| tolerance% | 0.5 | Tolerance 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
PriceNearLevel(price, distPerc)Price within distPerc% of a manually specified level.
PriceNearPivotPoint(distPerc)Price within distPerc% of any saved level in tickers_pivot_point.
RelativePerformance(period, timeframe, benchmarkTicker) <operator> valueDelta: ChangePerc(ticker) β ChangePerc(benchmark). Positive = outperforming.
Example
RelativePerformance(63, "d", "^GSPC") > 5
Trend Detection Functions v1.1+
IsUpTrend and IsDownTrend combine three independent criteria for high reliability. A ticker passes only if all three conditions are met simultaneously:
- Linear Regression Slope β fits a line through the last N closing prices. Positive slope = structural uptrend, negative = downtrend. Immune to single-bar spikes.
- 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.
- 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.
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.
| Parameter | Type | Description |
|---|---|---|
| period | int β₯ 5 | Number of bars to analyse (e.g. 30 = last 30 daily bars, 52 = last 52 weekly bars) |
| timeframe | string | "d" daily, "w" weekly, "m" monthly |
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
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
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).
| Parameter | Type | Description |
|---|---|---|
| period | int β₯ 5 | Number of bars to analyse |
| timeframe | string | "d" daily, "w" weekly, "m" monthly |
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")
MomentumSlope for an additional slope threshold:IsDownTrend(30, "d")
MomentumSlope(30, "d") < -0.1
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.
| Parameter | Type | Description |
|---|---|---|
| period | int β₯ 5 | Number of bars analysed in the historical window |
| timeframe | string | "d", "w", "m" |
| barsAgo | int β₯ 1 | How many bars ago to evaluate the trend (e.g. 10 = check trend 10 bars back) |
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
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
Fibonacci Functions
0, 23.6, 38.2, 50, 61.8, 78.6, 100.
FiboNearLevel(period, timeframe, level, tolerance)FILTER Price within tolerance% of a Fibonacci retracement level.
| Parameter | Description |
|---|---|
| period | Bars to look back for swing detection |
| level | 0 / 23.6 / 38.2 / 50 / 61.8 / 78.6 / 100 |
| tolerance | Max distance from level (%) |
Examples
FiboNearLevel(63, "d", 61.8, 2) // near Golden Ratio Β±2%
FiboNearLevel(52, "w", 38.2, 2) // weekly 38.2% level
FiboPosition(period, timeframe)EXPLORE Does not filter β shows nearest Fibonacci level, distance, 0β100% position in the swing range.
DistanceFromFibo(period, timeframe, retrLevel) <operator> valueDistance in % from a Fibonacci level. Consider using FiboNearLevel for new scripts.
Candlestick Pattern Functions NEW
1 if the pattern is detected on the last candle(s). Use with == 1. They work on any timeframe.IsDoji(timeframe) == 1Last 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
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
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
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
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
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.
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.
Chart Pattern Functions
> 50 for normal quality, > 70 for high-confidence setups. The period parameter controls how many candles back the engine searches.LookForFlag(period, timeframe) > score /
LookForBullFlag(period, timeframe) > score /
LookForBearFlag(period, timeframe) > score
UPDATED
Detects flag patterns: a sharp directional move (the pole) followed by a tight consolidation channel. Returns a quality score 0β100 based on pole strength, channel tightness, and volume behavior.
LookForBullFlag filters for bullish flags only; LookForBearFlag for bearish ones.
Examples
// Any flag, score >= 60
LookForFlag(80, "d") > 60
// Bull flag only on liquid EU stocks
IsNotPriceLocked(20, "d") == 1
AvgCounterValue(20, "d") > 500000
LookForBullFlag(80, "d") > 60
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")
LookForCupWithHandle(nrCandles, timeframe, precisionLevel)Cup with handle: a rounded bottom (the cup) followed by a shallow pullback (the handle). Classic bullish continuation pattern before a breakout.
Example
LookForCupWithHandle(60, "d", 0.7)
LookForHeadAndShoulders(period, timeframe) > score /
LookForInverseHS(period, timeframe) > score
UPDATED
Head & Shoulders (bearish top reversal) and Inverse H&S (bullish bottom reversal). Returns a quality score based on shoulder symmetry, head height, and neckline alignment.
Example
// Inverse H&S with RSI confirmation
LookForInverseHS(120, "d") > 55
RSI(14, "d") > 50
LookForAscendingTriangle(period, timeframe) > score UPDATEDAscending triangle: flat resistance + rising support lows. Bullish continuation. Returns quality score based on RΒ² of trendlines and number of touch points.
LookForDescendingTriangle(period, timeframe) > scoreDescending triangle: flat support + declining highs. Bearish continuation or breakdown setup.
Example
LookForDescendingTriangle(60, "d") > 50
RSI(14, "d") < 50
LookForSymmetricTriangle(period, timeframe) > scoreSymmetric 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
LookForTriangleBreakOut(timeframe, showOnlyBreakout, nrLastCandleSignal)Any triangle breakout. Set showOnlyBreakout to true for confirmed breakouts only.
LookForAscendingTrendLine(nrCandles, timeframe, precisionLevel)Rising trendline connecting at least 2 swing lows.
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
FilterTickers(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')
QuantMetric(metric, fiscal_year, fiscal_quarter) <operator> valueFetches 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
AddSignal("signal text")Writes a text signal to the signals table for all tickers in the current result set.
SetFilter("label")Appends a label to tickers.filters for every surviving ticker. Additive β never overwrites existing values.
SetTickerField("field", "value")Writes value to a column of the tickers table for every surviving ticker. Overwrites the existing value.
| Allowed fields | Description |
|---|---|
watchlist | System watchlist (semicolon-separated) |
watchlist_user | User watchlist |
notes | Free-text notes |
sector | Sector classification |
area | Geographic area |
country | Country |
partof | Index / group membership |
filters | Filter labels (prefer SetFilter to append) |
Examples
SetTickerField("notes", "Breakout candidate Apr26")
SetTickerField("watchlist", "MyPortfolio")
AddToWatchlist to append without losing existing watchlists.AddToWatchlist("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")
RemoveFromWatchlist("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")
Comments
Lines starting with
//are completely ignored by the engine. Lines starting with// @are script directives (metadata for gStockly publishing).