i had an idea for awhile for something like this, so here is my version

thanks

@Pensar for mentioning ticksize. i forget to use that, and usually use a tiny number for a vertical offset.

---------------------------------

stacked arrows on crossings of average lines

look for crossings of 3 EMA pairs, 3/8, 9/13, 8/21

draw an arrow, when a pair of average lines cross.

up arrow for fast > slow , down arrow for slow > fast

if more than 1 crossings occur on the same bar, in the same direction, it draws stacked arrows.

if lower number(1 and/or 2) arrow(s) are not triggered, the higher number(2 and/or 3) arrows will shift vertically, to be closer to the candle.

the second average line in each pair is dashed

user inputs:

parameters for 6 averages: length & type. ( defaults are EXPONENTIAL)

color of average lines (per pair) and corresponding crossing arrow (0 - 9)

show_average_lines

show_crossing_arrows

show_description_labels

the size of arrows (1 to 5)

arrow_vertical_factor

length 8 is used twice, so only 5 lines are viewable

Ruby:

```
# stack_arrows_01
def price = close;
def na = double.nan;
input show_average_lines = yes;
input show_crossing_arrows = yes;
input show_description_labels = yes;
# ----------------------------------
input avg1_color = 6;
# 6 = green
#hint avg1_color: 10 colors used with getcolor(). \n 0 = magenta, 1 = cyan, 2 = pink, 3 = gray, 4 = org \n 5 = red, 6 = green, 7 = dark gray, 8 = yellow, 9 = white \n .setDefaultColor( GetColor(1) );
input avg1a_len = 3;
input avg1a_type = AverageType.EXPONENTIAL;
def ma1a = MovingAverage(avg1a_type, price, avg1a_len);
input avg1b_len = 8;
input avg1b_type = AverageType.EXPONENTIAL;
def ma1b = MovingAverage(avg1b_type, price, avg1b_len);
plot pma1a = if show_average_lines then ma1a else na;
#pma1a.SetDefaultColor(Color.Green);
pma1a.SetDefaultColor(getcolor(avg1_color));
#pma1a.SetLineWeight(1);
plot pma1b = if show_average_lines then ma1b else na;
#pma1b.SetDefaultColor(Color.Green);
pma1b.SetDefaultColor(getcolor(avg1_color));
pma1b.SetStyle(Curve.MEDIUM_DASH);
#pma1b.SetLineWeight(1);
# ----------------------------------
input avg2_color = 0;
input avg2a_len = 9;
input avg2a_type = AverageType.EXPONENTIAL;
def ma2a = MovingAverage(avg2a_type, price, avg2a_len);
input avg2b_len = 13;
input avg2b_type = AverageType.EXPONENTIAL;
def ma2b = MovingAverage(avg2b_type, price, avg2b_len);
plot pma2a = if show_average_lines then ma2a else na;
pma2a.SetDefaultColor(getcolor(avg2_color));
#pma2a.SetLineWeight(1);
plot pma2b = if show_average_lines then ma2b else na;
pma2b.SetDefaultColor(getcolor(avg2_color));
pma2b.SetStyle(Curve.MEDIUM_DASH);
#pma2b.SetLineWeight(1);
# ----------------------------------
input avg3_color = 8;
input avg3a_len = 8;
input avg3a_type = AverageType.EXPONENTIAL;
def ma3a = MovingAverage(avg3a_type, price, avg3a_len);
input avg3b_len = 21;
input avg3b_type = AverageType.EXPONENTIAL;
def ma3b = MovingAverage(avg3b_type, price, avg3b_len);
plot pma3a = if show_average_lines then ma3a else na;
pma3a.SetDefaultColor(getcolor(avg3_color));
#pma3a.SetLineWeight(1);
plot pma3b = if show_average_lines then ma3b else na;
pma3b.SetDefaultColor(getcolor(avg3_color));
pma3b.SetStyle(Curve.MEDIUM_DASH);
#pma3b.SetLineWeight(1);
# --------------------------------------
# check if an avg pair has crossed
def x1u = (ma1a crosses above ma1b);
def x1d = (ma1a crosses below ma1b);
def x2u = (ma2a crosses above ma2b);
def x2d = (ma2a crosses below ma2b);
def x3u = (ma3a crosses above ma3b);
def x3d = (ma3a crosses below ma3b);
# ------------------------------------
input arrow_size = 3;
input arrow_vertical_factor = 10;
def vert = (ticksize() * arrow_vertical_factor * arrow_size);
# avg1 arrow is closest to bar , avg3 arrow is farthest from bar
# ------------------------------------
def adj = 0;
# calc vertical placement for arrows
def arrow3dwn = if !x3d then na else high + (vert * ((x1d + x2d + x3d) - adj));
def arrow2dwn = if !x2d then na else high + (vert * ((x1d + x2d) - adj));
def arrow1dwn = if !x1d then na else high + (vert * ((x1d) - adj));
def arrow1up = if !x1u then na else low - (vert * ((x1u) - adj));
def arrow2up = if !x2u then na else low - (vert * ((x1u + x2u) - adj));
def arrow3up = if !x3u then na else low - (vert * ((x1u + x2u + x3u) - adj));
# plot arrows for crossings, stacked if more than 1
plot pma3xdwn = if show_crossing_arrows then arrow3dwn else na;
plot pma2xdwn = if show_crossing_arrows then arrow2dwn else na;
plot pma1xdwn = if show_crossing_arrows then arrow1dwn else na;
plot pma1xup = if show_crossing_arrows then arrow1up else na;
plot pma2xup = if show_crossing_arrows then arrow2up else na;
plot pma3xup = if show_crossing_arrows then arrow3up else na;
pma3xdwn.SetPaintingStrategy(PaintingStrategy.ARROW_DOWN);
pma2xdwn.SetPaintingStrategy(PaintingStrategy.ARROW_DOWN);
pma1xdwn.SetPaintingStrategy(PaintingStrategy.ARROW_DOWN);
pma1xup.SetPaintingStrategy(PaintingStrategy.ARROW_up);
pma2xup.SetPaintingStrategy(PaintingStrategy.ARROW_up);
pma3xup.SetPaintingStrategy(PaintingStrategy.ARROW_up);
pma3xdwn.SetDefaultColor(getcolor(avg3_color));
pma2xdwn.SetDefaultColor(getcolor(avg2_color));
pma1xdwn.SetDefaultColor(getcolor(avg1_color));
pma1xup.SetDefaultColor(getcolor(avg1_color));
pma2xup.SetDefaultColor(getcolor(avg2_color));
pma3xup.SetDefaultColor(getcolor(avg3_color));
pma3xdwn.hidebubble();
pma2xdwn.hidebubble();
pma1xdwn.hidebubble();
pma1xup.hidebubble();
pma2xup.hidebubble();
pma3xup.hidebubble();
pma3xdwn.setlineweight(arrow_size);
pma2xdwn.setlineweight(arrow_size);
pma1xdwn.setlineweight(arrow_size);
pma1xup.setlineweight(arrow_size);
pma2xup.setlineweight(arrow_size);
pma3xup.setlineweight(arrow_size);
# ----------------------------------------
addlabel(show_description_labels, "avg1 " + avg1a_len + "/" + avg1b_len, getcolor(avg1_color));
addlabel(show_description_labels, "avg2 " + avg2a_len + "/" + avg2b_len, getcolor(avg2_color));
addlabel(show_description_labels, "avg3 " + avg3a_len + "/" + avg3b_len, getcolor(avg3_color));
# -------------------------------------------
input test_ticksize_label = no;
addlabel( test_ticksize_label , " ticksize " + ticksize(), color.cyan);
# -----------------------------------------
# https://tlc.thinkorswim.com/center/reference/thinkScript/Constants/AverageType
# EXPONENTIAL
# HULL
# SIMPLE
# WEIGHTED
# WILDERS
# https://tlc.thinkorswim.com/center/reference/thinkScript/functions/look---feel/getcolor
# getcolors
#
```

CVS 30D 15min

color numbers for getcolor()

https://tlc.thinkorswim.com/center/reference/thinkScript/Functions/Look---Feel/GetColor