Intersection value function
Intersection value function
-----------------------------------------------------------------------------------
------------------------------------------------------
| █ CHALLENGE |
| |
| Create three functions that will return the exact value where two data series
intersect: |
| |
| • crossValue (source1, source2) |
| • crossoverValue (source1, source2) |
| • crossunderValue(source1, source2) |
| |
| When a cross occurs, the functions must return the intersection`s value. When no
cross occurs, they must return na. |
| |
-----------------------------------------------------------------------------------
------------------------------------------------------ '
//@version=5
indicator( title = 'Intersection Value Functions'
, max_boxes_count = 500
, max_lines_count = 500
, max_labels_count = 500
, overlay = true
)
//---------------------------------------------------------------------------------
------------------------------------}
//Challenge Functions
//---------------------------------------------------------------------------------
------------------------------------{
// getSlopes()
//
//@function Get the slope of the lines connecting source1/source2 to
source1[1]/source2[1]
//@param source1 (float) source value 1
//@param source2 (float) source value 2
//@returns Slopes of the lines
getSlopes(float source1, float source2) =>
//Get slopes
m1 = ta.change(source1)
m2 = ta.change(source2)
//Output
[m1 , m2]
// commonScalingFactor()
//
//@function Common scaling factor of the lines connecting source1/source2 to
source1[1]/source2[1]
//@param source1 (float) source value 1
//@param source2 (float) source value 2
//@param m1 (float) slope of the line originating from source1
//@param m2 (float) slope of the line originating from source2
//@returns Common scaling factor
commonScalingFactor(float source1, float source2, float m1, float m2) =>
//Output
(source1 - source2) / (m1 - m2)
// crossValue()
//
//@function Finds intersection value of 2 lines/values if any cross occurs - First
function of challenge -> crossValue(source1, source2)
//@param source1 (float) source value 1
//@param source2 (float) source value 2
//@returns Intersection value
method crossValue(float source1, float source2)=>
float insct = na
// crossoverValue()
//
//@function Finds intersection value of 2 lines/values if crossover occurs - Second
function of challenge -> crossoverValue(source1, source2)
//@param source1 (float) source value 1
//@param source2 (float) source value 2
//@returns Intersection value
method crossoverValue(float source1, float source2)=>
float insct = na
// crossunderValue()
//
//@function Finds intersect of 2 lines/values if crossunder occurs - Third function
of challenge -> crossunderValue(source1, source2)
//@param source1 (float) source value 1
//@param source2 (float) source value 2
//@returns Intersection value
method crossunderValue(float source1, float source2) =>
float insct = na
//---------------------------------------------------------------------------------
------------------------------------}
//Usage - Code used to highlight the proposed functions usage.
//---------------------------------------------------------------------------------
------------------------------------{
//Settings
//-----------------------------------------------------------------------------{
//Sources selection
sourceA = input.string('SMA', 'Source A'
, options = ['SMA', 'EMA', 'WMA', 'Hull', 'External A']
, inline = 'sourceA')
//Style
coCss = input.color(#2962ff, 'Crossover'
, inline = 'crossover')
//Magnifying Glass
magnify = input(true, 'Magnify'
, group = 'Magnifying Glass')
//----------------------------------------------------------------------------}
//Methods/Functions
//----------------------------------------------------------------------------{
//@function Return various supported moving averages outputs based on an input
string
//@param id (string) determine the function output, supported strings include
['SMA', 'EMA', 'WMA', 'Hull'], else an external value is returned
//@param len (simple int) moving average length if applicable
//@param external (float) external source
//@returns Chosen moving average output or "external" if "id" is not part of
supported options
method source(string id, simple int len, float external) =>
sma = ta.sma(close, len)
ema = ta.ema(close, len)
wma = ta.wma(close, len)
hma = ta.hma(close, len)
output = switch id
'SMA' => sma
'EMA' => ema
'WMA' => wma
'Hull' => hma
=> external
//@function Return the N * N intersection matrix from an array of values with size
N and the values in its previous instance
//@param array_series (array<float>) array of values, requires an array supporting
historical referencing
//@returns (matrix<float>) Intersection matrix showing intersection value between
all array entries
intersectionMatrix(array_series)=>
N = array_series.size()-1
ismt = matrix.new<float>(N+1, N+1)
sfmt = matrix.new<float>(N+1, N+1)
prev_array = array_series[1]
if not na(prev_array)
//Columns
for i = 0 to N
//Get source1 and previous source1 value
source1 = array_series.get(i)
prev1 = prev_array.get(i)
//source1 slope
m1 = source1 - prev1
//Rows
for j = i to N
//Na is column index = row index
if i == j
ismt.set(j, i, float(na))
else
//Get source2 and previous source2 value
source2 = array_series.get(j)
prev2 = prev_array.get(j)
//source2 slope
m2 = source2 - prev2
//Output
[ismt, sfmt]
//@function Draw graphical elements on the chart highlighting crossing events and
intersection value/area
//@param intersection_val (float) Intersection value between source1 and source2
//@param scaling_factor (float) Common scaling factor between two crossing lines
//@param max (float) area top
//@param min (float) area bottom
//@param crossover (bool) true if the lines are crossing over each other
//@param css (color) color of the line/label text
//@param css_area (color) color of the box area
//@returns [line, label, box] drawing elements
draw(intersection_val, scaling_factor, max, min, crossover, css, css_area)=>
n = bar_index
//Intersection level
lvl = line.new(
chart.point.from_index(n-1, intersection_val)
, chart.point.from_index(n, intersection_val)
, color = css)
//Intersection value label and display 1 - scaling factor when hovering over
label
lbl = label.new(
chart.point.from_index(n, crossover ? min : max)
, color = color(na)
, textcolor = css
, text = str.tostring(math.round_to_mintick(intersection_val))
, style = crossover ? label.style_label_up : label.style_label_down
, size = size.small
, tooltip = str.tostring(1 - scaling_factor, '#.##'))
n = bar_index
//Slopes run
dx1 = int(resolution * (1 - sf))
dx2 = int(resolution * sf)
//Offset
start = int(resolution * (1 - sf)) + offset
//Coordinates
l1y1 = source1 - (source1 - source1[1]) * dx1
l1y2 = source1 + (source1 - source1[1]) * dx2
//Area
cross_area.set_lefttop(n - dx1 + start, math.max(l1y1, l1y2, l2y1, l2y2))
cross_area.set_rightbottom(n + dx2 + start, math.min(l1y1, l1y2, l2y1,
l2y2))
cross_area.set_bgcolor(area_css)
else
//Update coordinates
x1 = source1_l.get_x1()
x2 = source1_l.get_x2()
source1_l.set_x1(x1 + 1) , source1_l.set_x2(x2 + 1)
source2_l.set_x1(x1 + 1) , source2_l.set_x2(x2 + 1)
intersec_l.set_x1(x1 + 1) , intersec_l.set_x2(x2 + 1)
cross_area.set_left(x1 + 1), cross_area.set_right(x2 + 1)
//----------------------------------------------------------------------------}
//Highlight crosses and intersection value
//----------------------------------------------------------------------------{
//Intersections drawing elements
var line intersection_lvl = na
var label intersection_lbl = na
var box intersection_box = na
n = bar_index
source1 = sourceA.source(lenA, externalA)
source2 = sourceB.source(lenB, externalB)
var l1 = line.new(na,na,na,na)
var l2 = line.new(na,na,na,na)
var l3 = line.new(na,na,na,na)
//Draw elements
crossover = source1 > source2
max = math.max(source1, source2, source1[1], source2[1])
min = math.min(source1, source2, source1[1], source2[1])
intersection_lvl := lvl_
intersection_lbl := lbl_
intersection_box := bx_
else
//Extend
if extend
intersection_lvl.set_x2(n)
intersection_lbl.set_x(int(math.avg(n, intersection_lvl.get_x1())))
intersection_box.set_right(n)
//Zoom
if magnify
zoomIn(source1, source2, #089981, #f23645
, source1 > source2 ? coCss : cuCss
, source1 > source2 ? coAreaCss : cuAreaCss)
//-----------------------------------------------------------------------------}
//Highlight SMA intersection matrix
//-----------------------------------------------------------------------------{
var table_position = dashLoc == 'Bottom Left' ? position.bottom_left
: dashLoc == 'Top Right' ? position.top_right
: position.bottom_right
csum = ta.cum(close)
//Table
tb = table.new(table_position, cols+2, rows+2
, bgcolor = #1e222d
, border_color = #373a46
, border_width = 1
, frame_color = #373a46
, frame_width = 1)
for i = 0 to rows-1
//SMA periods
tb.cell(0, i+1, str.tostring(minLen + i)
, text_color = color.white
, text_size = table_size)
tb.cell(i+1, 0, str.tostring(minLen + i)
, text_color = color.white
, text_size = table_size)
for j = 0 to cols-1
//Set intersection value
if not na(ismt.get(i, j))
tb.cell(i+1, j+1, str.tostring(math.round_to_mintick(ismt.get(i,
j)))
, text_color = color.white
, text_size = table_size
, tooltip = str.tostring(sfmt.get(i, j), '#.##'))
//Dashboard title
tb.cell(0, rows, 'SMA Intersection Matrix'
, text_color = color.white
, text_size = table_size)
tb.merge_cells(0, rows, cols, rows)
//----------------------------------------------------------------------------}
//Plots
//----------------------------------------------------------------------------{
plot(source1, 'Source A', #089981)
plot(source2, 'Source B', #f23645)
//----------------------------------------------------------------------------}
//---------------------------------------------------------------------------------
------------------------------------}