Distributions
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © miivanov

//@version=5

// @description Price distribution calculation helpers
library("Distributions")

import miivanov/Colors/2
// helper to get OHLC series values
getOhlc() => [open, high, low, close]

// @function Returns price distribution zones based on HLC and for some period
// @param h high price
// @param l low price
// @param c close price
// @param window period to calculate distributions
// @returns tuple of 5 price zones in descent order, from highest to lowest 
export getZones(series float h, series float l, series float c, simple int window) =>
	avghlc = (h + l + c) / 3
	avg = ta.sma(avghlc, window)
	top = ta.highest(h, window)
	bottom = ta.lowest(l, window)

	zHighest = avg[1] + top[1] - bottom[1]
	zHigh = 2 * avg[1] - bottom[1]
	zLow = 2 * avg[1] - top[1]
	zLowest = avg[1] + bottom[1] - top[1]
	zMiddle = (zHighest + zLow) / 2
	[zHighest, zHigh, zMiddle, zLow, zLowest]

// @function Plots table of price distribution zones
// @param zHighest highest prices distribution zone
// @param zHigh upper-middle prices distribution zone
// @param zMiddle middle zone of prices distribution
// @param zLow lower-middle distribution zone
// @param zLowest lowest distribuion zone
export plotZonesTable(series float zHighest, series float zHigh, series float zMiddle, series float zLow, series float zLowest, simple int window) =>
	var colors = Colors.getColorsRange(color.green, color.red, 6)
	int resetCounter = 0
	int lowestPricesPct = 0
	int lowPricesPct = 0
	int lowerMidPricesPct = 0
	int upperMidPricesPct = 0
	int highPricesPct = 0
	int higherPricesPct = 0

	switch 
		close >= zHighest => higherPricesPct += 1
		close < zHighest and close >= zHigh => highPricesPct += 1
		close < zHigh and close >= zMiddle => upperMidPricesPct += 1
		close < zMiddle and close >= zLow => lowerMidPricesPct += 1
		close < zLow and close >= zLowest => lowPricesPct += 1
		close < zLowest => lowestPricesPct += 1
	var test = 0

	if (resetCounter < window)
		test := higherPricesPct + highPricesPct + upperMidPricesPct + lowerMidPricesPct + lowPricesPct + lowestPricesPct
	else
		resetCounter := 0
		lowestPricesPct := 0
		lowPricesPct := 0
		lowerMidPricesPct := 0
		upperMidPricesPct := 0
		highPricesPct := 0
		higherPricesPct := 0
		resetCounter := 0

	resetCounter += 1
	var distTable = table.new(position = position.top_right, columns = 6, rows = 3, bgcolor = color.yellow, border_color = color.black, border_width = 2)
	string tableTitle = str.format("Prices distributed by zones for last {0} of {1} days", resetCounter, window)
	table.cell(table_id = distTable, column = 0, row = 0, text = tableTitle, text_halign = text.align_center)
	table.merge_cells(table_id = distTable, start_column = 0, start_row = 0, end_column = 5, end_row = 0)
	table.cell(table_id = distTable, column = 5, row = 1, text = "Highest")
	table.cell(table_id = distTable, column = 4, row = 1, text = "High")
	table.cell(table_id = distTable, column = 3, row = 1, text = "Upper mid.")
	table.cell(table_id = distTable, column = 2, row = 1, text = "Lower mid.")
	table.cell(table_id = distTable, column = 1, row = 1, text = "Low")
	table.cell(table_id = distTable, column = 0, row = 1, text = "Lowest")

	table.cell(table_id = distTable, column = 5, row = 2, bgcolor = array.get(colors, 0), text = str.tostring(math.round((higherPricesPct / test) * 100, 2)) + '%')
	table.cell(table_id = distTable, column = 4, row = 2, bgcolor = array.get(colors, 1), text = str.tostring(math.round((highPricesPct / test) * 100, 2)) + '%')
	table.cell(table_id = distTable, column = 3, row = 2, bgcolor = array.get(colors, 2), text = str.tostring(math.round((upperMidPricesPct / test) * 100, 2)) + '%')
	table.cell(table_id = distTable, column = 2, row = 2, bgcolor = array.get(colors, 3), text = str.tostring(math.round((lowerMidPricesPct / test) * 100, 2)) + '%')
	table.cell(table_id = distTable, column = 1, row = 2, bgcolor = array.get(colors, 4), text = str.tostring(math.round((lowPricesPct / test) * 100, 2)) + '%')
	table.cell(table_id = distTable, column = 0, row = 2, bgcolor = array.get(colors, 5), text = str.tostring(math.round((lowestPricesPct / test) * 100, 2)) + '%')