replace multiple boolean filters with a single enum input

TRADERSAM

Active member
VIP
I’m trying to get a study to use a single enum input instead of multiple “UseX” filters. The enum is:
Code:
FilterType = { Gann, ADX, VolumeDivergence, None }
I’d like each option to control the script’s filtering logic cleanly but I just cannot get it to work right for some reason... If anyone could help me with this it would be much appreciated! Here is the full code:
Code:
# ------------------------------------------------ #
# Wick Whisper by @TraderSam
# v1.2
# Last Updated 10/24/25
# 10/22/25: Added Gann Counting
# 10/23/25: Added Volume Divergence
# 10/24/25: Tryed To Add An Input For Picking Filter Type
# ------------------------------------------------ #

input FilterType = {default Gann, ADX, VolumeDivergence, None};

# === Start of VWAP (from Charles Schwab) === #
input numDevDn = -2.0;
input numDevUp = 2.0;
input timeFrame = {default DAY, WEEK, MONTH};

def cap = GetAggregationPeriod();
def errorInAggregation =
    timeFrame == timeFrame.DAY and cap >= AggregationPeriod.WEEK or
    timeFrame == timeFrame.WEEK and cap >= AggregationPeriod.MONTH;
Assert(!errorInAggregation, "timeFrame should be not less than current chart aggregation period");

def yyyyMmDd = GetYYYYMMDD();
def periodIndx;
switch (timeFrame) {
case DAY:
    periodIndx = yyyyMmDd;
case WEEK:
    periodIndx = Floor((DaysFromDate(First(yyyyMmDd)) + GetDayOfWeek(First(yyyyMmDd))) / 7);
case MONTH:
    periodIndx = RoundDown(yyyyMmDd / 100, 0);
}
def isPeriodRolled = CompoundValue(1, periodIndx != periodIndx[1], yes);

def volumeSum;
def volumeVwapSum;
def volumeVwap2Sum;

if (isPeriodRolled) {
    volumeSum = volume;
    volumeVwapSum = volume * vwap;
    volumeVwap2Sum = volume * Sqr(vwap);
} else {
    volumeSum = CompoundValue(1, volumeSum[1] + volume, volume);
    volumeVwapSum = CompoundValue(1, volumeVwapSum[1] + volume * vwap, volume * vwap);
    volumeVwap2Sum = CompoundValue(1, volumeVwap2Sum[1] + volume * Sqr(vwap), volume * Sqr(vwap));
}
def price = volumeVwapSum / volumeSum;
def deviation = Sqrt(Max(volumeVwap2Sum / volumeSum - Sqr(price), 0));

def vwap = price;
def upperband = vwap + numDevUp * deviation;
def lowerband = vwap + deviation * numdevdn;
# === END OF VWAP === #

# === START OF VOLUME DIVERGENCE === #
input PriceLength = 20;
input VolLength = 20;
input PivotLen = 5;

def ma = expaverage(close, pricelength);
def volma = average(volume, vollength);

def mahighpivot = ma[pivotlen] == highest(ma, pivotlen * 2 + 1);
def malowpivot = ma[pivotlen] == lowest(ma, pivotlen * 2 + 1);

def volhighpivot = volma[pivotlen] == highest(volma, pivotlen * 2 + 1);
def vollowpivot = volma[pivotlen] == lowest(volma, pivotlen * 2 + 1);

def mahigh1 = if mahighpivot then ma[pivotlen] else mahigh1[1];
def mahigh2 = if mahighpivot and !mahighpivot[1] then mahigh1[1] else mahigh2[1];
def malow1 = if malowpivot then ma[pivotlen] else malow1[1];
def malow2 = if malowpivot and !malowpivot[1] then malow1[1] else malow2[1];

def volhigh1 = if volhighpivot then volma[pivotlen] else volhigh1[1];
def volhigh2 = if volhighpivot and !volhighpivot[1] then volhigh1[1] else volhigh2[1];
def vollow1 = if vollowpivot then volma[pivotlen] else vollow1[1];
def vollow2 = if vollowpivot and !vollowpivot[1] then vollow1[1] else vollow2[1];

def beardiv = mahighpivot and (mahigh1 > mahigh2) and (volhigh1 < volhigh2);
def bulldiv = malowpivot and (malow1 < malow2) and (vollow1 > vollow2);

# === END OF VOLUME DIVERGENCE === #

# === BASIC DEFS === #
input OnlyRTH = yes;

def rth = SecondsFromTime(0930) >= 0 and SecondsTillTime(1600) > 0;
def validrth = if onlyrth then rth else 1;

# === START OF RSI === #
input rsiLength = 10;
input overSold = 30;
input overBought = 70;

def rsi = RSI(rsiLength);

def os = rsi < overSold;
def ob = rsi > overBought;
# === END OF RSI === #

# === START OF ADX === #
input Use_ADX_Filter = no;
input adxLength = 14;
input StrongTrend = 25;

def adx1 = adx(adxLength);
def strongtrend1 = if use_adx_filter then (adx1 > StrongTrend) else 0;
# === END OF ADX === #

# === START OF WICK/CANDLE PATTERNS === #
input WickSizePercentage = 50;

def wsscaled = WickSizePercentage / 100;

def bodysize = AbsValue(close - open);
def upperwick = high - Max(open, close);
def lowerwick = Min(close, open) - low;

def goodupperwick = upperwick >= wsscaled * bodysize;
def goodlowerwick = lowerwick >= wsscaled * bodysize;
# === END OF WICK/CANDLE PATTERNS === #

# === START OF GANN COUNTING === #
input UseGannCounting = yes;
input BarsAfterSignal = 2;

def upbar = high > high[1] and low > low[1];
def dnbar = high < high[1] and low < low[1];
def outsidebar = high > high[1] and low < low[1];
def insidebar = high < high[1] and low > low[1];
def swingup = if upbar then 1 else if dnbar then 0 else swingup[1];
def swingdown = !swingup;
def gannflipup = swingup and !swingup[1];
def gannflipdown = swingdown and !swingdown[1];

# === START OF ENTRY CONDITIONS === #
def wickupper = if goodupperwick and (close > upperband or high > upperband) then 1 else 0;
def wicklower = if goodlowerwick and (close < lowerband or low < lowerband) then 1 else 0;

def rsiwickupper = wickupper and ob;
def rsiwicklower = wicklower and os;

def goodwickupper = rsiwickupper and !strongtrend1 and validrth;
def goodwicklower = rsiwicklower and !strongtrend1 and validrth;

def rawshort = goodwickupper;
def rawlong = goodwicklower;

def barssincerawlong  = if rawlong then 0 else barssincerawlong[1] + 1;
def barssincerawshort = if rawshort then 0 else barssincerawshort[1] + 1;

def confirmedlong = useganncounting and barssincerawlong <= barsaftersignal and gannflipup;
def confirmedshort = useganncounting and barssincerawshort <= barsaftersignal and gannflipdown;

plot arrowlong = if useganncounting and confirmedLong then low else if !useganncounting and rawLong then low else double.nan;
arrowlong.setpaintingstrategy(paintingstrategy.arrow_up);
arrowlong.setdefaultcolor(color.magenta);

plot arrowshort = if useganncounting and confirmedshort then high else if !useganncounting and rawshort then high else double.nan;
arrowshort.setpaintingstrategy(paintingstrategy.arrow_down);
arrowshort.setdefaultcolor(color.cyan);
# === END OF SCRIPT (for now) ===
 
Last edited:
Solution
Why are you not just using a 'Switch Case' to set multiple 'defs' based on one 'input'?
Ruby:
input FilterType = {default Gann, ADX, VolumeDivergence, None};

def Use_ADX_Filter;
def UseGannCounting;
 switch (FilterType) {
 case "ADX":
 Use_ADX_Filter = yes;
 UseGannCounting = no;
 case "VolumeDivergence":
 Use_ADX_Filter = no;
 UseGannCounting = no;
 case "None":
 Use_ADX_Filter = no;
 UseGannCounting = no;
 default: #Gann
 Use_ADX_Filter = no;
 UseGannCounting = yes;
 }

Join useThinkScript to post your question to a community of 21,000+ developers and traders.

Are you referring to the dropdown option in the indicator's settings?
Yep, exactly! I’m just having trouble switching everything over to a single dropdown input instead of multiple separate inputs. I am normally able to do this no problem but I just haven't been able to get it right for this script. I think it is because I haven't kept the code very organized 😂
 
Why are you not just using a 'Switch Case' to set multiple 'defs' based on one 'input'?
Ruby:
input FilterType = {default Gann, ADX, VolumeDivergence, None};

def Use_ADX_Filter;
def UseGannCounting;
 switch (FilterType) {
 case "ADX":
 Use_ADX_Filter = yes;
 UseGannCounting = no;
 case "VolumeDivergence":
 Use_ADX_Filter = no;
 UseGannCounting = no;
 case "None":
 Use_ADX_Filter = no;
 UseGannCounting = no;
 default: #Gann
 Use_ADX_Filter = no;
 UseGannCounting = yes;
 }
 
Solution
Why are you not just using a 'Switch Case' to set multiple 'defs' based on one 'input'?
Ruby:
input FilterType = {default Gann, ADX, VolumeDivergence, None};

def Use_ADX_Filter;
def UseGannCounting;
 switch (FilterType) {
 case "ADX":
 Use_ADX_Filter = yes;
 UseGannCounting = no;
 case "VolumeDivergence":
 Use_ADX_Filter = no;
 UseGannCounting = no;
 case "None":
 Use_ADX_Filter = no;
 UseGannCounting = no;
 default: #Gann
 Use_ADX_Filter = no;
 UseGannCounting = yes;
 }
Thanks a lot for pointing that out! I honestly didn’t even know you could do a switch/case like that in ThinkScript. I’m self-taught and still trying to learn this stuff as I go, so that was actually super helpful. I did end up getting everything working, and it turns out the issue I was seeing was because I had added an extra condition inside the arrow logic, so it made it look like the arrows were shifting places depending on the filter type.

This is what I ended up with... Do you think your version with the switch/case is cleaner or better practice? Here is the script:
Ruby:
# ------------------------------------------------ #
# Wick Whisper by @TraderSam
# v1.2
# Last Updated 10/28/25
# 10/22/25: Added Gann Counting
# 10/23/25: Added Volume Divergence
# 10/28/25: Added Input for Filter Type
# ------------------------------------------------ #

input FilterType = {default Gann, ADX, VolumeDivergence, None};

# === Start of VWAP (from Charles Schwab) === #
input numDevDn = -2.0;
input numDevUp = 2.0;
input timeFrame = {default DAY, WEEK, MONTH};

def cap = GetAggregationPeriod();
def errorInAggregation =
    timeFrame == timeFrame.DAY and cap >= AggregationPeriod.WEEK or
    timeFrame == timeFrame.WEEK and cap >= AggregationPeriod.MONTH;
Assert(!errorInAggregation, "timeFrame should be not less than current chart aggregation period");

def yyyyMmDd = GetYYYYMMDD();
def periodIndx;
switch (timeFrame) {
case DAY:
    periodIndx = yyyyMmDd;
case WEEK:
    periodIndx = Floor((DaysFromDate(First(yyyyMmDd)) + GetDayOfWeek(First(yyyyMmDd))) / 7);
case MONTH:
    periodIndx = RoundDown(yyyyMmDd / 100, 0);
}
def isPeriodRolled = CompoundValue(1, periodIndx != periodIndx[1], yes);

def volumeSum;
def volumeVwapSum;
def volumeVwap2Sum;

if (isPeriodRolled) {
    volumeSum = volume;
    volumeVwapSum = volume * vwap;
    volumeVwap2Sum = volume * Sqr(vwap);
} else {
    volumeSum = CompoundValue(1, volumeSum[1] + volume, volume);
    volumeVwapSum = CompoundValue(1, volumeVwapSum[1] + volume * vwap, volume * vwap);
    volumeVwap2Sum = CompoundValue(1, volumeVwap2Sum[1] + volume * Sqr(vwap), volume * Sqr(vwap));
}
def price = volumeVwapSum / volumeSum;
def deviation = Sqrt(Max(volumeVwap2Sum / volumeSum - Sqr(price), 0));

def vwap = price;
def upperband = vwap + numDevUp * deviation;
def lowerband = vwap + deviation * numDevDn;
# === END OF VWAP === #

# === BASIC DEFS === #
input OnlyRTH = yes;

def rth = SecondsFromTime(0930) >= 0 and SecondsTillTime(1600) > 0;
def validrth = if OnlyRTH then rth else 1;

# === START OF RSI === #
input rsiLength = 10;
input overSold = 30;
input overBought = 70;

def rsi = RSI(rsiLength);

def os = rsi < overSold;
def ob = rsi > overBought;
# === END OF RSI === #

# === START OF WICK/CANDLE PATTERNS === #
input WickSizePercentage = 50;

def wsscaled = WickSizePercentage / 100;

def bodysize = AbsValue(close - open);
def upperwick = high - Max(open, close);
def lowerwick = Min(close, open) - low;

def goodupperwick = upperwick >= wsscaled * bodysize;
def goodlowerwick = lowerwick >= wsscaled * bodysize;
# === END OF WICK/CANDLE PATTERNS === #

# === START OF GANN COUNTING === #
input BarsAfterSignal = 2;

def upbar = high > high[1] and low > low[1];
def dnbar = high < high[1] and low < low[1];
def outsidebar = high > high[1] and low < low[1];
def insidebar = high < high[1] and low > low[1];
def swingup = if upbar then 1 else if dnbar then 0 else swingup[1];
def swingdown = !swingup;
def gannflipup = swingup and !swingup[1];
def gannflipdown = swingdown and !swingdown[1];
# === END OF GANN COUNTING === #

# === START OF ADX === #
input adxLength = 14;
input StrongTrend = 25;

def adx1 = ADX(adxLength);
def strongtrend1 = adx1 > StrongTrend;
# === END OF ADX === #

# === START OF VOLUME DIVERGENCE === #
input PriceLength = 20;
input VolLength = 20;
input PivotLen = 5;

def ma = ExpAverage(close, PriceLength);
def volma = Average(volume, VolLength);

def mahighpivot = ma[PivotLen] == Highest(ma, PivotLen * 2 + 1);
def malowpivot = ma[PivotLen] == Lowest(ma, PivotLen * 2 + 1);

def volhighpivot = volma[PivotLen] == Highest(volma, PivotLen * 2 + 1);
def vollowpivot = volma[PivotLen] == Lowest(volma, PivotLen * 2 + 1);

def mahigh1 = if mahighpivot then ma[PivotLen] else mahigh1[1];
def mahigh2 = if mahighpivot and !mahighpivot[1] then mahigh1[1] else mahigh2[1];
def malow1 = if malowpivot then ma[PivotLen] else malow1[1];
def malow2 = if malowpivot and !malowpivot[1] then malow1[1] else malow2[1];

def volhigh1 = if volhighpivot then volma[PivotLen] else volhigh1[1];
def volhigh2 = if volhighpivot and !volhighpivot[1] then volhigh1[1] else volhigh2[1];
def vollow1 = if vollowpivot then volma[PivotLen] else vollow1[1];
def vollow2 = if vollowpivot and !vollowpivot[1] then vollow1[1] else vollow2[1];

def beardiv = mahighpivot and (mahigh1 > mahigh2) and (volhigh1 < volhigh2);
def bulldiv = malowpivot and (malow1 < malow2) and (vollow1 > vollow2);
# === END OF VOLUME DIVERGENCE === #

# === START OF ENTRY CONDITIONS === #
def rawlong = goodlowerwick and low <= lowerband and os and validrth;
def rawshort = goodupperwick and high >= upperband and ob and validrth;

def barssincerawlong  = if rawlong then 0 else barssincerawlong[1] + 1;
def barssincerawshort = if rawshort then 0 else barssincerawshort[1] + 1;

def long = if filtertype == filtertype.gann then barssincerawlong <= barsaftersignal and gannflipup else if filtertype == filtertype.adx then rawlong and !strongtrend else if filtertype == filtertype.volumedivergence then barssincerawlong <= barsaftersignal and bulldiv else rawlong;
def short = if filtertype == filtertype.gann then barssincerawshort <= barsaftersignal and gannflipdown else if filtertype == filtertype.adx then rawshort and !strongtrend else if filtertype == filtertype.volumedivergence then barssincerawlong <= barsaftersignal and beardiv else rawshort;

plot arrowLong = if long then low else double.nan;
arrowLong.setpaintingstrategy(paintingstrategy.arrow_up);
arrowlong.setdefaultcolor(color.magenta);
arrowlong.setlineweight(2);

plot arrowShort = if short then high else double.nan;
arrowShort.setpaintingstrategy(paintingstrategy.arrow_down);
arrowShort.setdefaultcolor(color.cyan);
arrowshort.setlineweight(2);
(Still Working On The Volume Divergence)
 
Last edited:

Similar threads

Not the exact question you're looking for?

Start a new thread and receive assistance from our community.

87k+ Posts
548 Online
Create Post

Similar threads

Similar threads

The Market Trading Game Changer

Join 2,500+ subscribers inside the useThinkScript VIP Membership Club
  • Exclusive indicators
  • Proven strategies & setups
  • Private Discord community
  • ‘Buy The Dip’ signal alerts
  • Exclusive members-only content
  • Add-ons and resources
  • 1 full year of unlimited support

Frequently Asked Questions

What is useThinkScript?

useThinkScript is the #1 community of stock market investors using indicators and other tools to power their trading strategies. Traders of all skill levels use our forums to learn about scripting and indicators, help each other, and discover new ways to gain an edge in the markets.

How do I get started?

We get it. Our forum can be intimidating, if not overwhelming. With thousands of topics, tens of thousands of posts, our community has created an incredibly deep knowledge base for stock traders. No one can ever exhaust every resource provided on our site.

If you are new, or just looking for guidance, here are some helpful links to get you started.

What are the benefits of VIP Membership?
VIP members get exclusive access to these proven and tested premium indicators: Buy the Dip, Advanced Market Moves 2.0, Take Profit, and Volatility Trading Range. In addition, VIP members get access to over 50 VIP-only custom indicators, add-ons, and strategies, private VIP-only forums, private Discord channel to discuss trades and strategies in real-time, customer support, trade alerts, and much more. Learn all about VIP membership here.
How can I access the premium indicators?
To access the premium indicators, which are plug and play ready, sign up for VIP membership here.
Back
Top