Gravity Trend Levels [BOSWaves]
Acceleration-Derived Gravity Modeling with Adaptive Cloud Trail and Fail Level Projection
Original code: https://www.tradingview.com/script/nCUyWa7D-Gravity-Trend-Levels-BOSWaves/
Overview
Gravity Trend Levels [BOSWaves] is a momentum acceleration-based trend system that models directional gravity through the normalized rate of change of an EMA-derived velocity measurement, where cloud thickness, trail distance, and trend state are continuously adapted based on whether gravitational pull is building, sustained, or decaying rather than through fixed volatility multipliers or static band thresholds.
Acceleration-Derived Gravity Modeling with Adaptive Cloud Trail and Fail Level Projection
Original code: https://www.tradingview.com/script/nCUyWa7D-Gravity-Trend-Levels-BOSWaves/
Overview
Gravity Trend Levels [BOSWaves] is a momentum acceleration-based trend system that models directional gravity through the normalized rate of change of an EMA-derived velocity measurement, where cloud thickness, trail distance, and trend state are continuously adapted based on whether gravitational pull is building, sustained, or decaying rather than through fixed volatility multipliers or static band thresholds.
Code:
# ============================================================
# Gravity Trend Levels [BOSWaves]
# Original Pine Script: https://www.tradingview.com/script/nCUyWa7D-Gravity-Trend-Levels-BOSWaves/
# Converted by Chewie 6/2/2026
# ============================================================
declare upper;
# ─────────────────────────────────────────────────────────────
# INPUTS
# ─────────────────────────────────────────────────────────────
input alert = yes;
input len = 14; # Trend Length — higher = smoother, fewer flips
input gravLen = 19; # Gravity Lookback — lower = more reactive
input decayRate = 0.96; # Gravity Decay — higher = gravity lingers longer
input madLen = 24; # MAD Length — higher = smoother trail
input trailMin = 1.0; # Trail Min (Strong Pull)
input trailMax = 1.0; # Trail Max (Weak Pull)
input showCloud = yes; # Show Gravity Cloud
input paintBars = yes; # Color Bars
input showSignals = yes; # Show Buy/Sell Signals
input showLevels = yes; # Show Gravity Fail Levels
input levelLen = 50; # Level Projection Length (bars forward)
input showDots = yes; # Retest Diamonds
input dotCooldown = 12; # Retest Cooldown (min bars between diamonds)
input signalBuffer = 10; # Signal Buffer Period (bars after flip before diamonds)
# ─────────────────────────────────────────────────────────────
# COLORS
# ─────────────────────────────────────────────────────────────
DefineGlobalColor("Bull", Color.GREEN);
DefineGlobalColor("Bear", Color.RED);
# ─────────────────────────────────────────────────────────────
# CORE — Basis & Volatility (MAD)
# ─────────────────────────────────────────────────────────────
def basis = ExpAverage(close, len);
def meanC = Average(close, madLen);
def mad = Average(AbsValue(close - meanC), madLen);
# ─────────────────────────────────────────────────────────────
# GRAVITY DETECTION
# ─────────────────────────────────────────────────────────────
def velocity = basis - basis[gravLen];
def accelRaw = velocity - velocity[1];
def normAccel = if mad > 0 then AbsValue(accelRaw) / mad else 0.0;
def gravity;
if normAccel > 0.01 {
gravity = Min(normAccel * 8.0, 2.0);
} else {
gravity = gravity[1] * decayRate;
}
def pull = Min(gravity / 1.5, 1.0);
# ─────────────────────────────────────────────────────────────
# ADAPTIVE TRAIL BANDS
# ─────────────────────────────────────────────────────────────
def trailMult = trailMax - (trailMax - trailMin) * pull;
def upper_band = basis + mad * trailMult;
def lower_band = basis - mad * trailMult;
# ─────────────────────────────────────────────────────────────
# SIGNAL / TREND LOGIC
# ─────────────────────────────────────────────────────────────
def longCond = close crosses above upper_band;
def shortCond = close crosses below lower_band;
def lastSignal;
if longCond {
lastSignal = 1;
} else if shortCond {
lastSignal = -1;
} else {
lastSignal = lastSignal[1];
}
def switchUp = lastSignal == 1 and lastSignal[1] == -1;
def switchDown = lastSignal == -1 and lastSignal[1] == 1;
def lastSignalBar;
if switchUp or switchDown {
lastSignalBar = BarNumber();
} else {
lastSignalBar = lastSignalBar[1];
}
# ─────────────────────────────────────────────────────────────
# GRAVITY CLOUD
# ─────────────────────────────────────────────────────────────
def cloudThick = mad * (0.3 + 0.5 * pull);
def cloudOuter = if lastSignal == 1 then lower_band else upper_band;
def cloudInner = if lastSignal == 1 then lower_band + cloudThick else upper_band - cloudThick;
def cloudOuterVis = ExpAverage(cloudOuter, 5);
def cloudInnerVis = ExpAverage(cloudInner, 5);
plot CloudOuterPlot = if showCloud then cloudOuterVis else Double.NaN;
CloudOuterPlot.SetLineWeight(2);
CloudOuterPlot.AssignValueColor(if lastSignal == 1 then GlobalColor("Bull") else GlobalColor("Bear"));
CloudOuterPlot.SetPaintingStrategy(PaintingStrategy.LINE);
plot CloudInnerPlot = if showCloud then cloudInnerVis else Double.NaN;
CloudInnerPlot.SetLineWeight(1);
CloudInnerPlot.AssignValueColor(if lastSignal == 1
then CreateColor(0, 200, 0)
else CreateColor(200, 0, 0));
CloudInnerPlot.SetPaintingStrategy(PaintingStrategy.LINE);
# Cloud fill — AddCloud draws between two named plots
AddCloud(CloudOuterPlot, CloudInnerPlot,
CreateColor(100, 0, 0),
CreateColor(0, 100, 0));
# ─────────────────────────────────────────────────────────────
# BAR COLORING
# ─────────────────────────────────────────────────────────────
AssignPriceColor(
if !paintBars then Color.CURRENT
else if lastSignal == 1 then GlobalColor("Bull")
else GlobalColor("Bear")
);
# ─────────────────────────────────────────────────────────────
# BUY / SELL SIGNALS
# ─────────────────────────────────────────────────────────────
plot BuySignal = if showSignals and switchUp then low - mad * 1.5 else Double.NaN;
BuySignal.SetPaintingStrategy(PaintingStrategy.ARROW_UP);
BuySignal.SetDefaultColor(GlobalColor("Bull"));
BuySignal.SetLineWeight(3);
BuySignal.Hide(); # we use AddChartBubble below for labeling
AddChartBubble(showSignals and switchUp,
low - mad * 1.5,
"B",
GlobalColor("Bull"),
no);
AddChartBubble(showSignals and switchDown,
high + mad * 1.5,
"S",
GlobalColor("Bear"),
yes);
# ─────────────────────────────────────────────────────────────
# GRAVITY FAIL LEVELS
# ─────────────────────────────────────────────────────────────
# Bull flip level — project from the low of the switchUp bar
def flipBullPrice = if switchUp then low else Double.NaN;
def flipBearPrice = if switchDown then high else Double.NaN;
# Carry the level forward for levelLen bars
def barsAfterBullFlip;
if switchUp {
barsAfterBullFlip = 0;
} else if barsAfterBullFlip[1] < levelLen {
barsAfterBullFlip = barsAfterBullFlip[1] + 1;
} else {
barsAfterBullFlip = levelLen + 1;
}
def carriedBullLevel;
if switchUp {
carriedBullLevel = low;
} else if barsAfterBullFlip <= levelLen {
carriedBullLevel = carriedBullLevel[1];
} else {
carriedBullLevel = Double.NaN;
}
def barsAfterBearFlip;
if switchDown {
barsAfterBearFlip = 0;
} else if barsAfterBearFlip[1] < levelLen {
barsAfterBearFlip = barsAfterBearFlip[1] + 1;
} else {
barsAfterBearFlip = levelLen + 1;
}
def carriedBearLevel;
if switchDown {
carriedBearLevel = high;
} else if barsAfterBearFlip <= levelLen {
carriedBearLevel = carriedBearLevel[1];
} else {
carriedBearLevel = Double.NaN;
}
plot BullLevel = if showLevels then carriedBullLevel else Double.NaN;
BullLevel.SetDefaultColor(CreateColor(0, 200, 0));
BullLevel.SetPaintingStrategy(PaintingStrategy.DASHES);
BullLevel.SetLineWeight(2);
BullLevel.HideBubble();
plot BearLevel = if showLevels then carriedBearLevel else Double.NaN;
BearLevel.SetDefaultColor(CreateColor(200, 0, 0));
BearLevel.SetPaintingStrategy(PaintingStrategy.DASHES);
BearLevel.SetLineWeight(2);
BearLevel.HideBubble();
# ─────────────────────────────────────────────────────────────
# RETEST DIAMONDS
# ─────────────────────────────────────────────────────────────
def farEnough = (BarNumber() - lastSignalBar) >= signalBuffer;
def bullRetest = showDots and lastSignal == 1 and low < cloudInnerVis and farEnough;
def bearRetest = showDots and lastSignal == -1 and high > cloudInnerVis and farEnough;
# Cooldown tracking
def lastBullDotBar;
if bullRetest and (IsNaN(lastBullDotBar[1]) or (BarNumber() - lastBullDotBar[1]) >= dotCooldown) {
lastBullDotBar = BarNumber();
} else {
lastBullDotBar = lastBullDotBar[1];
}
def lastBearDotBar;
if bearRetest and (IsNaN(lastBearDotBar[1]) or (BarNumber() - lastBearDotBar[1]) >= dotCooldown) {
lastBearDotBar = BarNumber();
} else {
lastBearDotBar = lastBearDotBar[1];
}
def bullDotOk = bullRetest and lastBullDotBar == BarNumber();
def bearDotOk = bearRetest and lastBearDotBar == BarNumber();
plot BullDot = if bullDotOk then low else Double.NaN;
BullDot.SetPaintingStrategy(PaintingStrategy.TRIANGLES);
BullDot.SetDefaultColor(GlobalColor("Bull"));
BullDot.SetLineWeight(3);
plot BearDot = if bearDotOk then high else Double.NaN;
BearDot.SetPaintingStrategy(PaintingStrategy.TRIANGLES);
BearDot.SetDefaultColor(GlobalColor("Bear"));
BearDot.SetLineWeight(3);
# ─────────────────────────────────────────────────────────────
# ALERTS
# ─────────────────────────────────────────────────────────────
Alert(alert and switchUp, "Gravity Long — " + GetSymbol(), Alert.BAR, Sound.Ring);
Alert(alert and switchDown, "Gravity Short — " + GetSymbol(), Alert.BAR, Sound.Ring);
Alert(alert and bullDotOk or bearDotOk, "Gravity Retest — " + GetSymbol(), Alert.BAR, Sound.Ding);