Ripster EMA Clouds: Pair Colors and Display Limits
Ripster EMA Clouds fills the space between pairs of moving averages. The Pineify copy below calculates five pairs on HL2, while displaying only the first three. Its colors report the relative order of each pair; they do not measure the slope of either line, the position of the close, or a probability of a profitable trade.
Inspect the Pine ScriptThe author’s publication and this fixed copy
Ripster47’s public TradingView script dates to March 2021. The published source offers EMA or SMA, source and length inputs, visibility controls, and a leading plot displacement. This page’s v6 helper has a broader custom MA dispatcher, but its actual call selects EMA and fixes all arguments.
Neither this copy nor the author’s local-cloud calculation requests a higher timeframe. A longer EMA on the current chart remains an average of that chart’s bars. A separate multi-timeframe cloud implementation needs different code and a stated confirmation policy.
Five pairs calculated, three clouds displayed
| Cloud | EMA lengths | Short ≥ long | Short < long | Copy display |
|---|---|---|---|---|
| 1 | 8 / 9 | Dark green | Dark pink | Visible |
| 2 | 5 / 12 | Green | Red | Visible |
| 3 | 34 / 50 | Blue | Orange | Visible |
| 4 | 72 / 89 | Teal | Pink | Hidden |
| 5 | 180 / 200 | Cyan | Dark orange | Hidden |
The comparison includes equality in the first color branch. When both averages coincide, the cloud has zero width even though the condition selects that color. “All bullish colors” therefore means matching pair conditions, not literally identical hues: Cloud 3 uses blue where Cloud 1 uses green.
The boundary plots are fully transparent. Clouds 4 and 5 pass na to their plots and fill colors through hardcoded false conditions; changing a style color cannot restore missing series. Enabling them requires editing those conditions or adding inputs. The declared label limit does not create labels, and this copy includes no alerts or trade orders.
Reproduce one update before interpreting a color
For an EMA of length n, alpha = 2 / (n + 1), and the update is alpha × source + (1 − alpha) × previous EMA. This copy’s source is HL2 = (high + low) / 2, not close. A 50-period EMA does not discard every observation older than 50 bars: earlier observations retain decaying weight.
Assume every EMA has settled at 100, then the next HL2 is 106. The three visible pairs become 101.333333 / 101.200000, 102.000000 / 100.923077, and 100.342857 / 100.235294. All select their first color. These values follow directly from each coefficient; they are synthetic inputs, not backtest results.
A valid bar with high 114, low 98 and close 99 has HL2 = 106. Its close is below every average just calculated despite all three pair conditions being positive. If the next HL2 is 100, the 8/9 pair becomes 101.037037 / 100.960000. Both averages fall while the cloud stays dark green. Pair order, line slope and close position are three different tests.
The 8/9 cloud’s width falls from 0.133333 to 0.077037 in that second update. Width is an absolute difference in price units, not a normalized measure comparable across all assets. Multiplying the whole price history by a positive constant multiplies the width while leaving pair ordering unchanged.
Know which arguments actually take effect
The helper accepts source, MA type and ten lengths; its call fixes them to HL2, EMA and the pairs above. It declares offset and leadingPeriod but never reads either. All plot calls separately use offset = 0. Changing those two helper arguments alone therefore does not move a cloud.
The author’s original leading-period input is wired to plot displacement. Such displacement places an existing calculation at a different horizontal position; it does not obtain future prices or make the calculation predictive. The unused arguments in this copy are not evidence that this behavior has been implemented here.
The custom p_ta_ma function is not a Pine built-in. It dispatches several averaging formulas, but this page’s fixed call uses only EMA. Selecting a different branch requires reviewing its formula and initialization as well as changing code. There is no supported fixed claim that switching to SMA doubles smoothness, adds two bars of lag, or reduces false signals by a given percentage.
Read the chart context before testing a rule
All lengths count chart observations. On a four-hour chart, EMA50 is not a 50-day EMA. Clouds overlap in data and do not provide independent votes. The 5/12 and 8/9 pairs also do not admit a universal fastest-to-slowest ordering: one has the shorter fast average and the other the shorter slow average.
HL2 can change while a bar develops, so current cloud boundaries and colors can update before close. The script has no confirmation gate. On alternative chart types, it consumes the chart’s supplied high and low; the arithmetic still has a definition, but those observations need not be standard traded-price candles or fixed elapsed-time intervals.
If studying consensus, specify which visible or hidden pairs count, whether equality counts, and whether entry occurs only on the first agreeing closed bar. Specify a separate exit, execution timing and costs. A color flip alone does not establish a trade, and no tested win rate or preferred market is supplied here.
Pine Script v6: implementation and limits
The complete code retains the existing EMA calculation and fixed three-cloud display. Other custom MA branches and unused helper arguments are visible for inspection, not advertised as configurable input controls.
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © Pineify
//@version=6
indicator(title="Ripster EMA Clouds", overlay=true, max_labels_count=500)
p_comm_time_range_to_unix_time(string time_range, int date_time = time, string timezone = syminfo.timezone) =>
int start_unix_time = na
int end_unix_time = na
int start_time_hour = na
int start_time_minute = na
int end_time_hour = na
int end_time_minute = na
if str.length(time_range) == 11
start_time_hour := math.floor(str.tonumber(str.substring(time_range, 0, 2)))
start_time_minute := math.floor(str.tonumber(str.substring(time_range, 3, 5)))
end_time_hour := math.floor(str.tonumber(str.substring(time_range, 6, 8)))
end_time_minute := math.floor(str.tonumber(str.substring(time_range, 9, 11)))
else if str.length(time_range) == 9
start_time_hour := math.floor(str.tonumber(str.substring(time_range, 0, 2)))
start_time_minute := math.floor(str.tonumber(str.substring(time_range, 2, 4)))
end_time_hour := math.floor(str.tonumber(str.substring(time_range, 5, 7)))
end_time_minute := math.floor(str.tonumber(str.substring(time_range, 7, 9)))
start_unix_time := timestamp(timezone, year(date_time, timezone), month(date_time, timezone), dayofmonth(date_time, timezone), start_time_hour, start_time_minute, 0)
end_unix_time := timestamp(timezone, year(date_time, timezone), month(date_time, timezone), dayofmonth(date_time, timezone), end_time_hour, end_time_minute, 0)
[start_unix_time, end_unix_time]
p_comm_time_range_to_start_unix_time(string time_range, int date_time = time, string timezone = syminfo.timezone) =>
int start_time_hour = na
int start_time_minute = na
if str.length(time_range) == 11
start_time_hour := math.floor(str.tonumber(str.substring(time_range, 0, 2)))
start_time_minute := math.floor(str.tonumber(str.substring(time_range, 3, 5)))
else if str.length(time_range) == 9
start_time_hour := math.floor(str.tonumber(str.substring(time_range, 0, 2)))
start_time_minute := math.floor(str.tonumber(str.substring(time_range, 2, 4)))
timestamp(timezone, year(date_time, timezone), month(date_time, timezone), dayofmonth(date_time, timezone), start_time_hour, start_time_minute, 0)
p_comm_time_range_to_end_unix_time(string time_range, int date_time = time, string timezone = syminfo.timezone) =>
int end_time_hour = na
int end_time_minute = na
if str.length(time_range) == 11
end_time_hour := math.floor(str.tonumber(str.substring(time_range, 6, 8)))
end_time_minute := math.floor(str.tonumber(str.substring(time_range, 9, 11)))
else if str.length(time_range) == 9
end_time_hour := math.floor(str.tonumber(str.substring(time_range, 5, 7)))
end_time_minute := math.floor(str.tonumber(str.substring(time_range, 7, 9)))
timestamp(timezone, year(date_time, timezone), month(date_time, timezone), dayofmonth(date_time, timezone), end_time_hour, end_time_minute, 0)
p_comm_timeframe_to_seconds(simple string tf) =>
float seconds = 0
tf_lower = str.lower(tf)
value = str.tonumber(str.substring(tf_lower, 0, str.length(tf_lower) - 1))
if str.endswith(tf_lower, 's')
seconds := value
else if str.endswith(tf_lower, 'd')
seconds := value * 86400
else if str.endswith(tf_lower, 'w')
seconds := value * 604800
else if str.endswith(tf_lower, 'm')
seconds := value * 2592000
else
seconds := str.tonumber(tf_lower) * 60
seconds
p_custom_sources() =>
[open, high, low, close, volume]
p_ta_Var_Func(src, length) =>
valpha = 2 / (length + 1)
vud1 = src > src[1] ? src - src[1] : 0
vdd1 = src < src[1] ? src[1] - src : 0
vUD = math.sum(vud1, 9)
vDD = math.sum(vdd1, 9)
vCMO = nz((vUD - vDD) / (vUD + vDD))
VAR = 0.0
VAR := nz(valpha * math.abs(vCMO) * src) + (1 - valpha * math.abs(vCMO)) * nz(VAR[1])
VAR
p_ta_Wwma_Func(src, length) =>
wwalpha = 1 / length
WWMA = 0.0
WWMA := wwalpha * src + (1 - wwalpha) * nz(WWMA[1])
WWMA
p_ta_Zlema_Func(src, length) =>
zxLag = length / 2 == math.round(length / 2) ? length / 2 : (length - 1) / 2
zxEMAData = src + src - src[zxLag]
ZLEMA = ta.ema(zxEMAData, length)
ZLEMA
p_ta_Tsf_Func(src, length) =>
lrc = ta.linreg(src, length, 0)
lrc1 = ta.linreg(src, length, 1)
lrs = lrc - lrc1
TSF = ta.linreg(src, length, 0) + lrs
TSF
p_ta_ma(series float source, simple int length, simple string ma_type) =>
switch ma_type
"SMA" => ta.sma(source, length)
"EMA" => ta.ema(source, length)
"RMA" => ta.rma(source, length)
"HMA" => ta.hma(source, length)
"WMA" => ta.wma(source, length)
"TMA" => ta.sma(ta.sma(source, math.ceil(length / 2)), math.floor(length / 2) + 1)
"VAR" => p_ta_Var_Func(source, length)
"WWMA" => p_ta_Wwma_Func(source, length)
"ZLEMA" => p_ta_Zlema_Func(source, length)
"TSF" => p_ta_Tsf_Func(source, length)
"VWMA" => ta.vwma(source, length)
p_ta_ripster_ema_clouds(series float source, simple string maType, simple int shortEma1Length, simple int longEma1Length, simple int shortEma2Length, simple int longEma2Length, simple int shortEma3Length, simple int longEma3Length, simple int shortEma4Length, simple int longEma4Length, simple int shortEma5Length, simple int longEma5Length, simple int offset, simple int leadingPeriod) =>
shortEma1 = p_ta_ma(source, shortEma1Length, maType)
longEma1 = p_ta_ma(source, longEma1Length, maType)
shortEma2 = p_ta_ma(source, shortEma2Length, maType)
longEma2 = p_ta_ma(source, longEma2Length, maType)
shortEma3 = p_ta_ma(source, shortEma3Length, maType)
longEma3 = p_ta_ma(source, longEma3Length, maType)
shortEma4 = p_ta_ma(source, shortEma4Length, maType)
longEma4 = p_ta_ma(source, longEma4Length, maType)
shortEma5 = p_ta_ma(source, shortEma5Length, maType)
longEma5 = p_ta_ma(source, longEma5Length, maType)
[shortEma1, longEma1, shortEma2, longEma2, shortEma3, longEma3, shortEma4, longEma4, shortEma5, longEma5]
[p_ind_1_shortEma1, p_ind_1_longEma1, p_ind_1_shortEma2, p_ind_1_longEma2, p_ind_1_shortEma3, p_ind_1_longEma3, p_ind_1_shortEma4, p_ind_1_longEma4, p_ind_1_shortEma5, p_ind_1_longEma5] = p_ta_ripster_ema_clouds(hl2, "EMA", 8, 9, 5, 12, 34, 50, 72, 89, 180, 200, 0, 0)
// Cloud 1 fill (8 vs 9)
p_ind_1_shortEma1_plot = plot(true ? p_ind_1_shortEma1 : na, title="Short EMA1", color=color.new(color.white, 100), linewidth=1, offset=0)
p_ind_1_longEma1_plot = plot(true ? p_ind_1_longEma1 : na, title="Long EMA1", color=color.new(color.white, 100), linewidth=1, offset=0)
fill(p_ind_1_shortEma1_plot, p_ind_1_longEma1_plot, title="Cloud 1", color=true ? (p_ind_1_shortEma1 >= p_ind_1_longEma1 ? color.rgb(3, 97, 3, 45) : color.rgb(136, 14, 79, 45)) : na)
// Cloud 2 fill (5 vs 12)
p_ind_1_shortEma2_plot = plot(true ? p_ind_1_shortEma2 : na, title="Short EMA2", color=color.new(color.white, 100), linewidth=1, offset=0)
p_ind_1_longEma2_plot = plot(true ? p_ind_1_longEma2 : na, title="Long EMA2", color=color.new(color.white, 100), linewidth=1, offset=0)
fill(p_ind_1_shortEma2_plot, p_ind_1_longEma2_plot, title="Cloud 2", color=true ? (p_ind_1_shortEma2 >= p_ind_1_longEma2 ? color.rgb(76, 175, 80, 65) : color.rgb(244, 67, 54, 65)) : na)
// Cloud 3 fill (34 vs 50)
p_ind_1_shortEma3_plot = plot(true ? p_ind_1_shortEma3 : na, title="Short EMA3", color=color.new(color.white, 100), linewidth=1, offset=0)
p_ind_1_longEma3_plot = plot(true ? p_ind_1_longEma3 : na, title="Long EMA3", color=color.new(color.white, 100), linewidth=1, offset=0)
fill(p_ind_1_shortEma3_plot, p_ind_1_longEma3_plot, title="Cloud 3", color=true ? (p_ind_1_shortEma3 >= p_ind_1_longEma3 ? color.rgb(33, 150, 243, 70) : color.rgb(255, 183, 77, 70)) : na)
// Cloud 4 fill (72 vs 89) - disabled by default
p_ind_1_shortEma4_plot = plot(false ? p_ind_1_shortEma4 : na, title="Short EMA4", color=color.new(color.white, 100), linewidth=1, offset=0)
p_ind_1_longEma4_plot = plot(false ? p_ind_1_longEma4 : na, title="Long EMA4", color=color.new(color.white, 100), linewidth=1, offset=0)
fill(p_ind_1_shortEma4_plot, p_ind_1_longEma4_plot, title="Cloud 4", color=false ? (p_ind_1_shortEma4 >= p_ind_1_longEma4 ? color.rgb(0, 150, 136, 65) : color.rgb(240, 98, 146, 65)) : na)
// Cloud 5 fill (180 vs 200) - disabled by default
p_ind_1_shortEma5_plot = plot(false ? p_ind_1_shortEma5 : na, title="Short EMA5", color=color.new(color.white, 100), linewidth=1, offset=0)
p_ind_1_longEma5_plot = plot(false ? p_ind_1_longEma5 : na, title="Long EMA5", color=color.new(color.white, 100), linewidth=1, offset=0)
fill(p_ind_1_shortEma5_plot, p_ind_1_longEma5_plot, title="Cloud 5", color=false ? (p_ind_1_shortEma5 >= p_ind_1_longEma5 ? color.rgb(5, 190, 213, 65) : color.rgb(230, 81, 0, 65)) : na)
Specify a checkable adaptation in Pineify
Give the Pine Script AI Coding Agent a precise specification: which pairs to expose, how equality counts, whether cloud visibility uses inputs, and whether an alert fires only on a confirmed transition. Use the synthetic EMA values above as checkpoints, then compare the generated result in TradingView before adding strategy execution.
Open Pine Script AI Coding AgentEducational indicator analysis. No measured trading performance is established here. Syntax validation does not prove formula equivalence, execution assumptions or profitability.