Madrid Moving Average Ribbon: 18 Color Comparisons and a 100-MA Reference
The ribbon computes nineteen moving averages, but only eighteen shorter averages provide comparisons with the 100-period reference. Each color combines an average’s own change with its position relative to that reference. It does not count independent traders or establish a probability of a future move.
Inspect the Pine ScriptThe period list and attribution
The periods are 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90 and 100. There is no 95-period line. This reference plots all nineteen: eighteen dynamically colored averages plus a gray 100-period anchor. The 5 and 90 lines are thicker for identification.
The public Madrid author page identifies the publishing account as Madrid and dates the release to March 2015. It describes EMA/SMA ribbons and a separate companion Ribbon Bar study. This example does not implement that companion study or assert an unverified real-world identity for the author.
Read the ordered color conditions
Let A be a shorter average, R the current 100-period average, and ΔA = A − A[1]. Conditions are evaluated in this order:
| Position | Change | Color |
|---|---|---|
| A > R | ΔA ≥ 0 | Lime |
| A > R | ΔA < 0 | Maroon |
| A < R | ΔA ≤ 0 | Red |
| A < R | ΔA > 0 | Green |
| A = R, or required comparison unavailable | Any | Gray |
A flat average above R is lime. A flat average below R is red because the nonpositive-change branch is tested first. Gray does not mean merely flat or close to the anchor: equality is exact, with no tolerance band. Applying the same comparison to R itself would always give gray because R equals itself.
The slope is the average’s slope, not the current price change or the reference slope. “Lime” also does not require the shorter averages to be arranged in length order; each line is compared only with R.
A price step can make all eighteen comparisons lime
Start with a long constant price of 100 and all EMA states at 100. Move price to 110 for one bar. EMA(N) updates by 2/(N+1) times the ten-point change:
| Length | First step value | State against EMA100 |
|---|---|---|
| 5 | 103.333333 | Lime |
| 10 | 101.818182 | Lime |
| 90 | 100.219780 | Lime |
| 100 | 100.198020 | Reference |
Every shorter EMA rises more than EMA100, so all eighteen colored lines are lime after one step. A large same-color count therefore does not by itself prove a long-established trend or independent agreement.
If the next close is 102, EMA5 becomes 102.888889 and falls, while EMA100 rises to about 100.233703. EMA5 is maroon even though the close remains above EMA100 and that reference is rising. This synthetic recurrence illustrates the specific comparisons; it is not a return estimate.
A count is not nineteen independent votes
The maximum number of lime or red shorter-line comparisons is eighteen. A count of fourteen means 14/18 of those comparisons, not fourteen independent observations of market participants. All averages consume the same source and heavily overlapping history. If you add a count threshold, specify which lines enter the denominator and how unavailable values are treated.
Ribbon width and line ordering can be defined separately from color count. Neither is calculated as a separate signal by this example. Adding more plotted averages does not average those outputs together, so the number of lines alone does not determine a single ribbon lag.
EMA and SMA are explicit choices in this reference
The input menu supports only EMA and SMA, both fully implemented. The periods remain fixed. An earlier incomplete helper listed other names while returning raw source for some of them; those placeholders are not presented as working average types here. This limited reference does not claim to reproduce every average option in Pineify’s broader MA module.
With valid uninterrupted data, SMA100 requires a full hundred observations; its first slope comparison would additionally need a prior valid value. EMA uses recursive state and depends on available history and its seed. When comparing charts, align the source, session, timeframe and history. Changing to SMA does not guarantee half as many color changes or a fixed delay.
The script plots current-bar values without a close-confirmation gate. Colors may change before close. A confirmed alert adaptation needs explicit event and timing rules; merely requiring several matching colors does not freeze an open bar.
Use the ribbon as a checkable display
To reproduce a condition, state the precise color count, reference-slope test, decision bar and any price-based entry or exit. Keep observed values separate from assumptions about future returns. The supplied indicator has no orders, alerts, RSI, volume filter or automated reversal classification.
GMMA groups a different set of averages, and Ichimoku uses rolling high/low midpoints and plot offsets. Those are distinct calculations, not evidence that a particular ribbon identifies trader types or universally confirms a reversal earlier.
Pine Script v6: implementation and limits
This complete reference computes all nineteen averages, restores the previously truncated final plot and adds a visible gray 100-period reference. It offers genuine EMA/SMA and source inputs; all dynamic color branches preserve their original ordering and tie behavior.
// 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="Madrid Moving Average Ribbon", overlay=true, max_labels_count=500)
sourceInput = input.source(close, "Source")
maType = input.string("EMA", "Average type", options=["EMA", "SMA"])
p_ta_ma(series float source, simple int length, simple string ma_type) =>
emaValue = ta.ema(source, length)
smaValue = ta.sma(source, length)
ma_type == "SMA" ? smaValue : emaValue
p_ta_madrid_moving_average_ribbon(series float source, simple string ma_type) =>
ma05 = p_ta_ma(source, 5, ma_type)
ma10 = p_ta_ma(source, 10, ma_type)
ma15 = p_ta_ma(source, 15, ma_type)
ma20 = p_ta_ma(source, 20, ma_type)
ma25 = p_ta_ma(source, 25, ma_type)
ma30 = p_ta_ma(source, 30, ma_type)
ma35 = p_ta_ma(source, 35, ma_type)
ma40 = p_ta_ma(source, 40, ma_type)
ma45 = p_ta_ma(source, 45, ma_type)
ma50 = p_ta_ma(source, 50, ma_type)
ma55 = p_ta_ma(source, 55, ma_type)
ma60 = p_ta_ma(source, 60, ma_type)
ma65 = p_ta_ma(source, 65, ma_type)
ma70 = p_ta_ma(source, 70, ma_type)
ma75 = p_ta_ma(source, 75, ma_type)
ma80 = p_ta_ma(source, 80, ma_type)
ma85 = p_ta_ma(source, 85, ma_type)
ma90 = p_ta_ma(source, 90, ma_type)
ma100 = p_ta_ma(source, 100, ma_type)
[ma05, ma10, ma15, ma20, ma25, ma30, ma35, ma40, ma45, ma50, ma55, ma60, ma65, ma70, ma75, ma80, ma85, ma90, ma100]
// Madrid Ribbon color logic
maColor_p_ind_1(_ma, _maRef) =>
diffMA = ta.change(_ma)
diffMA >= 0 and _ma > _maRef ? color.rgb(0, 255, 0, 0) :
diffMA < 0 and _ma > _maRef ? color.rgb(128, 0, 0, 0) :
diffMA <= 0 and _ma < _maRef ? color.rgb(255, 0, 0, 0) :
diffMA >= 0 and _ma < _maRef ? color.rgb(0, 128, 0, 0) :
color.rgb(128, 128, 128, 0)
[ma05, ma10, ma15, ma20, ma25, ma30, ma35, ma40, ma45, ma50, ma55, ma60, ma65, ma70, ma75, ma80, ma85, ma90, ma100] =
p_ta_madrid_moving_average_ribbon(sourceInput, maType)
plot(ma05, "Madrid Ribbon - MMA05", maColor_p_ind_1(ma05, ma100), 3)
plot(ma10, "Madrid Ribbon - MMA10", maColor_p_ind_1(ma10, ma100), 1)
plot(ma15, "Madrid Ribbon - MMA15", maColor_p_ind_1(ma15, ma100), 1)
plot(ma20, "Madrid Ribbon - MMA20", maColor_p_ind_1(ma20, ma100), 1)
plot(ma25, "Madrid Ribbon - MMA25", maColor_p_ind_1(ma25, ma100), 1)
plot(ma30, "Madrid Ribbon - MMA30", maColor_p_ind_1(ma30, ma100), 1)
plot(ma35, "Madrid Ribbon - MMA35", maColor_p_ind_1(ma35, ma100), 1)
plot(ma40, "Madrid Ribbon - MMA40", maColor_p_ind_1(ma40, ma100), 1)
plot(ma45, "Madrid Ribbon - MMA45", maColor_p_ind_1(ma45, ma100), 1)
plot(ma50, "Madrid Ribbon - MMA50", maColor_p_ind_1(ma50, ma100), 1)
plot(ma55, "Madrid Ribbon - MMA55", maColor_p_ind_1(ma55, ma100), 1)
plot(ma60, "Madrid Ribbon - MMA60", maColor_p_ind_1(ma60, ma100), 1)
plot(ma65, "Madrid Ribbon - MMA65", maColor_p_ind_1(ma65, ma100), 1)
plot(ma70, "Madrid Ribbon - MMA70", maColor_p_ind_1(ma70, ma100), 1)
plot(ma75, "Madrid Ribbon - MMA75", maColor_p_ind_1(ma75, ma100), 1)
plot(ma80, "Madrid Ribbon - MMA80", maColor_p_ind_1(ma80, ma100), 1)
plot(ma85, "Madrid Ribbon - MMA85", maColor_p_ind_1(ma85, ma100), 1)
plot(ma90, "Madrid Ribbon - MMA90", maColor_p_ind_1(ma90, ma100), 3)
plot(ma100, "Madrid Ribbon - MMA100 reference", color.gray, 2)

Specify a checkable adaptation in Pineify
Ask Pine Script AI Coding Agent for a defined extension, such as an eighteen-line color count and a confirmed-bar alert when that count first crosses a chosen threshold. Inspect the denominator, unavailable-value handling and timing, then compare the calculation with the synthetic step before evaluating any trading rule.
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.