EMA Proximity Filter Returning Inconsistent Results

Viewing 4 posts - 1 through 4 (of 4 total)
  • Author
    Posts
  • #249019 quote
    David1998P
    Participant
    New

    EMA Proximity Filter Issue in Stock Screener — Help Needed

    I’m encountering inconsistent results with my EMA proximity filter in a stock screener. The filter should only show stocks within a specified distance (in nATR units) from the 200EMA, but some stocks pass while others don’t—even when they meet the criteria.

    Examples (Scanning NASDAQ):
    $SERV
    ATR: 7.6%
    Distance from EMA: 15%
    nATR distance ≈ 1.97 → Should fail, but appears in scan

    $GRRR
    ATR: 11.6%
    Distance from EMA: 4%
    nATR distance ≈ 0.34 → Should pass, but missing from scan

    Would appreciate your help on this, thank you.

    Current ProScreener Code

    // --- Main Parameters ---
    atrPeriod = 14 // ATR calculation period
    volumePeriod = 50 // Volume averaging period
    emaPeriod = 200 // EMA period for proximity check
    smaPeriod = 200 // SMA period for proximity check
    
    // --- Moving Average Proximity Parameters ---
    ONCE EnableMovingAverageCheck = 1 // Set to 1 to enable the EMA proximity check, 0 to disable
    ONCE MaxNATRDistanceFromEMA = 1.0 // Maximum distance from EMA in nATR units
    ONCE EnableSMACheck = 0 // Set to 1 to enable the SMA proximity check, 0 to disable
    ONCE MaxNATRDistanceFromSMA = 1.0 // Maximum distance from SMA in nATR units
    
    // --- Filter Parameters ---
    minVolatility = 5 // Minimum acceptable volatility (nATR %)
    maxVolatility = 99 // Maximum acceptable volatility (nATR %)
    minLiquidity = 15000000 // Minimum avg currency volume
    maxLiquidity = 10000000000000000 // Maximum avg daily currency volume
    
    // --- Calculations ---
    // 1. Volatility measurement (nATR)
    atr = AverageTrueRange[atrPeriod](Close)
    nATR = 100 * atr / Close // nATR as percentage of price
    
    // 2. Liquidity measurement
    avgVolume = Average[volumePeriod](Close * Volume)
    
    // 3. Moving average calculations
    emaX = ExponentialAverage[emaPeriod](Close)
    smaX = Average[smaPeriod](Close)
    
    // Calculate distances in nATR units
    distanceFromEMA = 100 * ABS(Close - emaX) / Close  // Distance as percentage
    nATRDistEmaX = distanceFromEMA / nATR              // Convert to nATR units
    
    distanceFromSMA = 100 * ABS(Close - smaX) / Close
    nATRDistSmaX = distanceFromSMA / nATR
    
    // --- Apply All Filters ---
    // Ensure we have enough data for calculations
    IF BarIndex < volumePeriod OR BarIndex < emaPeriod THEN
    valid = 0
    ELSE
    // 1. Volatility filter with range
    cond1 = nATR >= minVolatility AND nATR <= maxVolatility
    
    // 2. Liquidity filter with range
    cond2 = avgVolume >= minLiquidity AND avgVolume <= maxLiquidity
    
    // 3. Moving Average proximity checks
    IF EnableMovingAverageCheck = 1 THEN
    emaFilter = nATRDistEmaX <= MaxNATRDistanceFromEMA
    ELSE
    emaFilter = 1 // Always pass if disabled
    ENDIF
    
    IF EnableSMACheck = 1 THEN
    smaFilter = nATRDistSmaX <= MaxNATRDistanceFromSMA
    ELSE
    smaFilter = 1 // Always pass if disabled
    ENDIF
    
    // Combined condition - ALL must be true
    valid = cond1 AND cond2 AND emaFilter AND smaFilter
    ENDIF
    
    // Output result sorted by volatility
    SCREENER[valid] SORT BY nATR AS "Volatility (%)"
    
    #249021 quote
    Iván González
    Moderator
    Master

    The problem may be that you’re trying to calculate a 200-period exponential moving average with the free version of PRT. In the free version the screener has a capacity of 256 bars and in the premium 1024. Therefore the exponential moving average won’t be calculated correctly. You can easily check it:

    // --- Main Parameters ---
    emaPeriod = 200 // EMA period for proximity check
    smaPeriod = 200 // SMA period for proximity check
    
    ema=average[emaPeriod,1](close)
    sma=average[smaPeriod,0](close)
    
    // Output result sorted by volatility
    screener(ema as "EMA", sma as "SMA")
    

    Check the values obtained for the EMA and you’ll see that they’re not correct, whereas those for the SMA are.
    Solution: reduce the number of periods…

    robertogozzi and David1998P thanked this post
    #249048 quote
    David1998P
    Participant
    New

    Since I compute distance between last close and its EMA with a period smaller than the 256 capacity, I do not understand why there is not enough data for accurate results.

    I could use a higher timeframe with lower MA period or purshase the premium version if capacity is the problem but I would like to understand why it is the problem in the first place.

    Can you clarify this please?

    Thank you

    #249049 quote
    JS
    Participant
    Senior

    Hi,


    An EMA is a recursive filter where each value is calculated using previous EMA values…

    To achieve a stabilized and reliable calculation, approximately 3 times the chosen period is needed — in this case, 3 × 200 = 600 (history)candles…

    Iván González and David1998P thanked this post
Viewing 4 posts - 1 through 4 (of 4 total)
  • You must be logged in to reply to this topic.

EMA Proximity Filter Returning Inconsistent Results


ProBuilder: Indicators & Custom Tools

New Reply
Author
author-avatar
David1998P @david1998p Participant
Summary

This topic contains 3 replies,
has 3 voices, and was last updated by JS
6 months, 2 weeks ago.

Topic Details
Forum: ProBuilder: Indicators & Custom Tools
Language: English
Started: 07/22/2025
Status: Active
Attachments: 1 files
Logo Logo
Loading...