# https://www.tradingview.com/v/kdK5Uh0q/
#//@SprintInvestor
#study(title="Tennis Ball Action", shorttitle="Tennis Ball Action", overlay=false)
# Converted by Sam4Cok@Samer800 - 01/2024
Declare lower;
#// Condition 1: Ants
#// Function to update the upCloseCounter
input colorBars = yes;
def na = Double.NaN;
def last = isNaN(Close);
def c = close;
def h = high;
def l = low;
def o = open;
def v = volume;
def sma50 = Average(c, 50);
def sma20 = Average(c, 20);
def sma20Volume = Average(v, 20);
def range_top = (h + l) / 2;
#// Update the upCloseCounter and check the condition on each bar
def upCloseCounter = Sum(if c > c[1] then 1 else 0, 15);
#// Check if there are 12 or more up closes in the last 15 days
def up_days = upCloseCounter >= 12;
#// Condition 2: 9 or more out of the last 15 closes in the upper 50% of the range
#// Calculate the upper 50% of the range
def upper50Condition = Sum(if c >= range_top then 1 else 0, 15);
#// TRUE if 9 or more out of the last 15 closes are in the upper 50% of the range
def conditionMet = upper50Condition >= 9;
#// Condition 3: Bullish engulfing outside day
def bullish_engulfing = (c > o and c >= h[1] and o <= c[1]);
#// Condition 4: Stock is up 3% or more on the dayl
def change = c/o;
def up_condition_4 = (change >= 1.03);
#// Condition 5: Inside day condition
def up_condition_5 = h < h[1] and l > l[1];
#// Condition 6: Negative confirmation when the stock closes below the 50-day SMA
def down_condition_6 = c < sma50;
#// Conidition 7: Weak close
#// Calculate the condition
def lower50Condition = Sum(if c <= range_top then 1 else 0, 15);
#// TRUE if 9 or more out of the last 15 closes are in the upper 50% of the range
def down_condition_7 = lower50Condition >= 9;
#// Condition 8: Negative confirmation when the stock closes below the 50-day SMA
def down_condition_8 = c < sma20;
#// Condition 9: 3 lower lows
def down_condition_9 = c < c[1] and c < c[2];
#// Condition 10: down on above average volume
def down_condition_10 = c < c[1] and v > sma20Volume;
#// Initialize counts for Confirmations and Violations
#// Update Confirmations and Violations counts
def confirmations = up_days + conditionMet + bullish_engulfing + up_condition_4 + up_condition_5;
def violations = down_condition_6 + down_condition_7 + down_condition_8 + down_condition_9 + down_condition_10;
def trend = confirmations - violations;
AssignPriceColor(if !colorBars then Color.CURRENT else
if trend > 2 then Color.GREEN else
if trend > 0 then Color.DARK_GREEN else
if trend <-2 then Color.RED else
if trend < 0 then Color.DARK_RED else Color.GRAY);
#// Plot Confirmations and Violations on the same histogram
plot conf = if last then na else confirmations; # "Confirmations"
plot viol = if last then na else -violations; # "Violations"
conf.SetDefaultColor(Color.GREEN);
viol.SetDefaultColor(Color.RED);
conf.SetPaintingStrategy(PaintingStrategy.SQUARED_HISTOGRAM);
viol.SetPaintingStrategy(PaintingStrategy.SQUARED_HISTOGRAM);
#-- END of CODE