0% found this document useful (0 votes)
28 views14 pages

Seasonality Calculation

This document defines the inputs, variables, constants, and functions used in a seasonal analysis indicator for trading data. It retrieves historical price data, saves daily performance statistics, and contains functions for plotting the seasonal analysis including dividers and highlighting the current period's performance.

Uploaded by

Chirag Ramani
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
28 views14 pages

Seasonality Calculation

This document defines the inputs, variables, constants, and functions used in a seasonal analysis indicator for trading data. It retrieves historical price data, saves daily performance statistics, and contains functions for plotting the seasonal analysis including dividers and highlighting the current period's performance.

Uploaded by

Chirag Ramani
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 14

// This source code is subject to the terms of the Mozilla Public License 2.

0 at
https://mozilla.org/MPL/2.0/

// © tradeforopp

//@version=5

indicator("Seasonality [TFO]", "Seasonality v1.0 [TFO]", false, max_lines_count = 500,


max_boxes_count = 500, max_labels_count = 500)

// -------------------- Inputs --------------------

var g_ANALYSIS = "Analysis"

show_table = input.bool(true, "Statistics Table", tooltip = "Summarized table describing


seasonal data for the selected timeframe", group = g_ANALYSIS)

show_analysis = input.bool(true, "Performance Analysis", inline = "ANALYSIS", tooltip =


"Histogram showing the average percentage performance for the selected timeframe", group =
g_ANALYSIS)

analysis_period = input.string('Daily', "", ['Daily', 'Monthly', 'Quarterly'], inline = "ANALYSIS", group


= g_ANALYSIS)

szn_pivots = input.bool(false, "Seasonal Pivots", tooltip = "Shows when the current asset tends
to make highs and lows throughout the year, based on an aggregation of daily performance", group
= g_ANALYSIS)

pivot_strength = input.int(10, "Pivot Strength", tooltip = "Using a value of 10 for example, a high
must be greater than the 10 bars to the left and 10 bars to the right of it in order to be a valid pivot,
and vice versa for lows", group = g_ANALYSIS)

var g_EXTRAS = "Extras"

highlight_today = input.bool(true, "Highlight Current Trading Day", tooltip = "Easily find where the
current trading day meets up with seasonal averages", group = g_EXTRAS)

show_labels = input.bool(true, "Performance Labels", tooltip = "Labels will be shown in the


Performance Analysis to describe the average percent move over the specified period of time",
group = g_EXTRAS)

track_change = input.bool(false, "Track Changes", tooltip = "Follows the changes in average


performance throughout the year", group = g_EXTRAS)

var g_INDEX = "Indexing"


anchor_boy = input.bool(true, "Anchor to Beginning of Year", tooltip = "All drawings will start
anchored to the first trading day of the current year, to easily overlay past performance on the
current Daily chart", group = g_INDEX)

use_manual_offset = input.bool(false, "Manual Offset", inline = "OFFSET", tooltip = "Offers a


secondary offset so users can overlay these drawings on previous years (with an offset of ~252 *
number of years, for example)", group = g_INDEX)

manual_offset = input.int(252, "", inline = "OFFSET", group = g_INDEX)

var g_DIV = "Dividers"

month_div = input.bool(false, "Month", inline = "MDIV", group = g_DIV)

mdiv_style = input.string('Dotted', "", ['Dotted', 'Dashed', 'Solid'], inline = "MDIV", group =


g_DIV)

mdiv_color = input.color(color.white, "", inline = "MDIV", group = g_DIV)

qr_div = input.bool(false, "Quarter", inline = "QDIV", group = g_DIV)

qdiv_style = input.string('Dotted', "", ['Dotted', 'Dashed', 'Solid'], inline = "QDIV", group = g_DIV)

qdiv_color = input.color(color.white, "", inline = "QDIV", group = g_DIV)

var g_STYLE = "Style"

main_color = input.color(color.white, "Main Color", group = g_STYLE)

track_color = input.color(color.yellow, "Track Changes", group = g_STYLE)

upper_color = input.color(#08998180, "Performance", inline = "PERFORMANCE", group =


g_STYLE)

lower_color = input.color(#f2364580, "", inline = "PERFORMANCE", group = g_STYLE)

high_color = input.color(#08998180, "Seasonal Pivots", inline = "PIVOTS", group = g_STYLE)

low_color = input.color(#f2364580, "", inline = "PIVOTS", group = g_STYLE)

pivot_width = input.int(2, "Seasonal Pivot Width", group = g_STYLE)

divider_width = input.int(1, "Divider Width", group = g_STYLE)

text_size = input.string('Normal', "Text Size", options = ['Auto', 'Tiny', 'Small', 'Normal', 'Large',
'Huge'], group = g_STYLE)

var g_TABLE = "Table"

table_pos = input.string('Top Right', "Position", options = ['Bottom Center', 'Bottom Left',


'Bottom Right', 'Middle Center', 'Middle Left', 'Middle Right', 'Top Center', 'Top Left', 'Top Right'],
group = g_TABLE)
table_text = input.color(color.black, "Text Color", group = g_TABLE)

table_frame = input.color(color.black, "Frame Color", group = g_TABLE)

table_border = input.color(color.black, "Border Color", group = g_TABLE)

table_bg = input.color(color.white, "Background Color", group = g_TABLE)

// -------------------- Inputs --------------------

// -------------------- Basic Functions --------------------

get_table_pos(i) =>

result = switch i

"Bottom Center" => position.bottom_center

"Bottom Left" => position.bottom_left

"Bottom Right" => position.bottom_right

"Middle Center" => position.middle_center

"Middle Left" => position.middle_left

"Middle Right" => position.middle_right

"Top Center" => position.top_center

"Top Left" => position.top_left

"Top Right" => position.top_right

result

get_text_size(i) =>

result = switch i

'Tiny' => size.tiny

'Small' => size.small

'Normal' => size.normal

'Large' => size.large

'Huge' => size.huge

'Auto' => size.auto

result
get_line_style(i) =>

result = switch i

'Dotted' => line.style_dotted

'Dashed' => line.style_dashed

'Solid' => line.style_solid

result

get_month(i) =>

result = switch i

1 => 'JAN'

2 => 'FEB'

3 => 'MAR'

4 => 'APR'

5 => 'MAY'

6 => 'JUN'

7 => 'JUL'

8 => 'AUG'

9 => 'SEP'

10 => 'OCT'

11 => 'NOV'

12 => 'DEC'

get_qr(i) =>

result = switch i

1 => 'Q1'

2 => 'Q2'

3 => 'Q3'

4 => 'Q4'

get_period() =>

result = switch analysis_period


'Daily' => 'D'

'Monthly' => 'M'

'Quarterly' => 'Q'

// -------------------- Basic Functions --------------------

// -------------------- Variables & Constants --------------------

[d_open, d_close] = request.security(syminfo.tickerid, "D", [open, close], barmerge.gaps_off,


barmerge.lookahead_on)

[m_open, m_close] = request.security(syminfo.tickerid, "M", [open, close], barmerge.gaps_off,


barmerge.lookahead_on)

[q_open, q_close] = request.security(syminfo.tickerid, "3M", [open, close], barmerge.gaps_off,


barmerge.lookahead_on)

//

var arr_days = array.new_int()

var d_pct = array.new_float()

var d_points = array.new_float()

var d_count = array.new_int()

var d_day = array.new_string()

var d_sorted_pct = array.new_float()

var d_sorted_points = array.new_float()

var d_sorted_count = array.new_int()

var d_sorted_day = array.new_string()

var m_pct_avg = array.new_float()

var q_pct_avg = array.new_float()

//
var int doy = na

var int first_year = na

var int first_xoy = na

var float first_yoy = na

//

if month == 1 and month[1] != 1

first_xoy := bar_index

first_yoy := close[1]

doy := 0

if na(first_year)

first_year := year

if not na(doy)

doy += 1

//

offset = use_manual_offset ? manual_offset : 0

start_idx = anchor_boy ? first_xoy - offset : bar_index

highlight_offset = 20

days_in_year = 252

days_in_month = 21

days_in_qr = 63

period = get_period()

text_size := get_text_size(text_size)

mdiv_style := get_line_style(mdiv_style)

qdiv_style := get_line_style(qdiv_style)
table_pos := get_table_pos(table_pos)

//

szn_idx = switch period

'D' => doy - 1

'M' => month - 1

'Q' => month % 3 - 1

szn_arr = switch period

'D' => d_sorted_pct

'M' => m_pct_avg

'Q' => q_pct_avg

current_pct = switch period

'D' => (d_close - d_open) / d_open

'M' => (m_close - m_open) / m_open

'Q' => (q_close - q_open) / q_open

current_pts = switch period

'D' => (d_close - d_open)

'M' => (m_close - m_open)

'Q' => (q_close - q_open)

num_days = switch period

'D' => days_in_year

'M' => days_in_month

'Q' => days_in_qr

// -------------------- Variables & Constants --------------------


// -------------------- Saving Performance Data --------------------

if not na(doy) and doy <= days_in_year

idx = arr_days.indexof(doy)

pct = (d_close - d_open) / d_open

points = (d_close - d_open)

if idx == -1

arr_days.push(doy)

d_pct.push(pct)

d_points.push(points)

d_count.push(1)

d_day.push(str.tostring(month) + "/" + str.tostring(dayofmonth))

else

d_pct.set(idx, d_pct.get(idx) + pct)

d_points.set(idx, d_points.get(idx) + points)

d_count.set(idx, d_count.get(idx) + 1)

// -------------------- Saving Performance Data --------------------

// -------------------- Plotting Functions --------------------

dividers(base) =>

if month_div

for i = 0 to m_pct_avg.size()

left = start_idx + i * days_in_month

line.new(left, base, left, base, color = mdiv_color, style = mdiv_style, extend = extend.both,
width = divider_width)

if qr_div

for i = 0 to q_pct_avg.size()

left = start_idx + i * days_in_qr

line.new(left, base, left, base, color = qdiv_color, style = qdiv_style, extend = extend.both,
width = divider_width)
plot_analysis(period, szn_arr, szn_idx, num_days, base) =>

for i = 0 to szn_arr.size() - 1

not_daily = period != 'D'

left = start_idx + i * (not_daily ? num_days : 1)

right = left + (not_daily ? num_days - 1 : 1)

label_x = math.floor(math.avg(left, right))

box_text = switch period

'D' => na

'M' => get_month(i + 1)

'Q' => get_qr(i + 1)

perf = szn_arr.get(i)

col = perf > 0 ? upper_color : lower_color

if not_daily

box.new(left, base + perf, right, base, bgcolor = col, border_color = col, text = box_text,
text_color = col)

else

line.new(left, base + perf, left, base, color = col, width = 5)

if show_labels

label.new(label_x, base + perf, str.tostring(perf * 100, format.percent), style = perf > 0 ?


label.style_label_down : label.style_label_up, textcolor = main_color, size = text_size, color =
#ffffff00)

if track_change and i != szn_arr.size() - 1

next_perf = szn_arr.get(i + 1)

line.new(label_x, base + perf, label_x + (not_daily ? num_days : 1), base + next_perf, color =
track_color, width = 2)

if highlight_today and i == szn_idx


line.new(left, base + perf, start_idx + days_in_year - 1, base + perf, style = line.style_dotted,
color = main_color, width = 2)

label.new(start_idx + days_in_year - 1 + highlight_offset, base + perf, "Current Avg: " +


str.tostring(perf * 100, format.percent), style = label.style_label_center, textcolor = main_color, size
= text_size, color = #ffffff00)

if i == szn_arr.size() - 1

line.new(start_idx, base, start_idx + days_in_year - 1, base, color = main_color, width = 2)

// -------------------- Plotting Functions --------------------

// -------------------- Statistics Table --------------------

var table stats = table.new(table_pos, 50, 50, bgcolor = table_bg, frame_color = table_frame,
border_color = table_border, frame_width = 1, border_width = 1)

if barstate.islast

if timeframe.in_seconds() != timeframe.in_seconds("D")

table.cell(stats, 0, 0, "Please Use the 'D' Timeframe")

else

// Sort daily arrays by day --------------------------------------------------

temp_arr_days = arr_days.copy()

for i = temp_arr_days.size() - 1 to 0

min = arr_days.indexof(temp_arr_days.min())

d_sorted_pct.push(d_pct.get(min))

d_sorted_points.push(d_points.get(min))

d_sorted_count.push(d_count.get(min))

d_sorted_day.push(d_day.get(min))

temp_arr_days.set(min, na)

for i = 0 to d_sorted_pct.size() - 1
d_sorted_pct.set(i, d_sorted_pct.get(i) / d_sorted_count.get(i))

d_sorted_points.set(i, d_sorted_points.get(i) / d_sorted_count.get(i))

// Sort daily arrays by day --------------------------------------------------

// Get month performance --------------------------------------------------

m_pct_avg.clear()

for i = 0 to 11

sum = 0.0

for j = 0 to days_in_month - 1

sum += d_sorted_pct.get(i * days_in_month + j)

m_pct_avg.push(sum)

q_pct_avg.clear()

for i = 0 to 3

sum = 0.0

for j = 0 to days_in_qr - 1

sum += d_sorted_pct.get(i * days_in_qr + j)

q_pct_avg.push(sum)

// Get month performance --------------------------------------------------

// Seasonal highs and lows --------------------------------------------------

szn_pct = szn_arr.get(szn_idx)

base = 1.0

var price_projection = array.new_float()

var szn_lows = array.new_string()

var szn_highs = array.new_string()

if szn_pivots
x1 = start_idx

y1 = base

x2 = x1 + 1

for i = 0 to d_pct.size() - 1

price_projection.push(y1)

y2 = y1 * (1 + d_sorted_pct.get(i))

y1 := y2

x1 += 1

x2 += 1

left_bound = pivot_strength

right_bound = price_projection.size() - pivot_strength - 1

for i = left_bound to right_bound

new_low = true

new_high = true

for j = -pivot_strength to pivot_strength

if i != j

if price_projection.get(i) > price_projection.get(i + j)

new_low := false

break

for j = -pivot_strength to pivot_strength

if i != j

if price_projection.get(i) < price_projection.get(i + j)

new_high := false

break

if new_low

new_low_month = get_month(math.ceil(i / days_in_month))

if szn_lows.indexof(new_low_month) == -1

szn_lows.push(new_low_month)
line.new(start_idx + i, base, start_idx + i, base, extend = extend.both, color = low_color,
width = pivot_width)

label.new(start_idx + i, math.min(base, base + szn_arr.min()), "SEASONAL\nLOW", color =


color.new(low_color, 0), textcolor = main_color, size = text_size, style = label.style_label_up)

if new_high

new_high_month = get_month(math.ceil(i / days_in_month))

if szn_highs.indexof(new_high_month) == -1

szn_highs.push(new_high_month)

line.new(start_idx + i, base, start_idx + i, base, extend = extend.both, color = high_color,


width = pivot_width)

label.new(start_idx + i, math.max(base, base + szn_arr.max()), "SEASONAL\nHIGH", color


= color.new(high_color, 0), textcolor = main_color, size = text_size, style = label.style_label_down)

// Seasonal highs and lows --------------------------------------------------

// Plotting analysis --------------------------------------------------

dividers(base)

if show_analysis

plot_analysis(period, szn_arr, szn_idx, num_days, base)

// Plotting analysis --------------------------------------------------

// Table --------------------------------------------------

if show_table

curr_month_pct = (m_close - m_open) / m_open

curr_month_points = (m_close - m_open)

table.cell(stats, 0, 0, "Timeframe: ", text_size = text_size, text_color = table_text)

table.cell(stats, 1, 0, str.tostring(period), text_size = text_size, text_color = table_text)

table.cell(stats, 0, 1, "Collected Over: ", text_size = text_size, text_color = table_text)

table.cell(stats, 1, 1, str.tostring(year - first_year) + " Years", text_size = text_size, text_color =


table_text)
table.cell(stats, 0, 2, "Seasonality: ", text_size = text_size, text_color = table_text)

table.cell(stats, 1, 2, str.tostring(szn_pct > 0 ? 'BULLISH' : 'BEARISH'), bgcolor = szn_pct > 0 ?


upper_color : lower_color, text_size = text_size, text_color = table_text)

table.cell(stats, 0, 3, "Average % Change: ", text_size = text_size, text_color = table_text)

table.cell(stats, 1, 3, str.tostring(math.round(szn_pct * 10000) / 100, format.percent), bgcolor


= szn_pct > 0 ? upper_color : lower_color, text_size = text_size, text_color = table_text)

table.cell(stats, 0, 4, "Current % Change: ", text_size = text_size, text_color = table_text)

table.cell(stats, 1, 4, str.tostring(math.round(current_pct * 10000) / 100, format.percent),


bgcolor = current_pct > 0 ? upper_color : lower_color, text_size = text_size, text_color = table_text)

table.cell(stats, 0, 5, "Current Point Change: ", text_size = text_size, text_color = table_text)

table.cell(stats, 1, 5, str.tostring(current_pts), bgcolor = current_pts > 0 ? upper_color :


lower_color, text_size = text_size, text_color = table_text)

if szn_pivots

table.cell(stats, 0, 6, "Major Lows Made in: ", text_size = text_size, text_color = table_text)

table.cell(stats, 1, 6, str.tostring(szn_lows), text_size = text_size, text_color = table_text)

table.cell(stats, 0, 7, "Major Highs Made in: ", text_size = text_size, text_color = table_text)

table.cell(stats, 1, 7, str.tostring(szn_highs), text_size = text_size, text_color = table_text)

// Table --------------------------------------------------

// -------------------- Statistics Table --------------------

You might also like