Balance of Force (BOF)
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © peacefulLizard50262

//@version=5
indicator("Balance of Force")

import lastguru/DominantCycle/2 as d
length = input.int(20, "Length", 1)
rng    = input.bool(true, "Open/Close", "Toggle High/Low or Open/Close")
bes(float source = close, float length = 9)=>
    alpha = 2 / (length + 1)
    var float smoothed = na
    smoothed := alpha * (source) + (1 - alpha) * nz(smoothed[1])

var int   count = na
var float deviation = na
var int   count_bearish = na
var int   count_bullish = na
var float bearish = na
var float bullish = na

if open > close
    bearish := nz(bearish[1]) + math.abs((rng ? open  : high) - (rng ? close : low)) 
    count_bearish := nz(count_bearish[1]) + 1
if close > open
    bullish := nz(bullish[1]) + math.abs((rng ? close : high) - (rng ? open : low)) 
    count_bullish := nz(count_bullish[1]) + 1

bearish_true_range = (bearish - nz(bearish[length]))/(count_bearish - count_bearish[length])
bullish_true_range = (bullish - nz(bullish[length]))/(count_bullish - count_bullish[length])
bullish_bearish_ratio = math.log(bullish_true_range/bearish_true_range)

if 1 == 1//lol
    count := nz(count[1]) + 1
    deviation := nz(deviation[1]) + math.pow(bullish_bearish_ratio - math.log(1), 2)

square_diff = math.sqrt(deviation/(count-1))

smooth_length = d.mamaPeriod(bullish_bearish_ratio, 2, 4096)
smoothed_ratio = bes(bullish_bearish_ratio, smooth_length)
center = plot(math.log(1), color = color.new(color.silver, 20))
plot(smoothed_ratio, color = color.orange)
plot(bullish_bearish_ratio)
band_top_1 = plot(square_diff, color = color.new(color.silver, 95))
band_bot_1 = plot(-square_diff, color = color.new(color.silver, 95))
band_top_2 = plot(square_diff * 2, color = color.new(color.silver, 95))
band_bot_2 = plot(-square_diff * 2, color = color.new(color.silver, 95))
band_top_3 = plot(square_diff * 3, color = color.new(color.silver, 95))
band_bot_3 = plot(-square_diff * 3, color = color.new(color.silver, 95))
fill(band_top_3, center, top_value = square_diff * 3, bottom_value = math.log(1), top_color = color.new(color.red, 90), bottom_color = color.new(color.green, 90))
fill(band_bot_3, center, top_value = math.log(1), bottom_value = -square_diff * 3, bottom_color = color.new(color.red, 90), top_color = color.new(color.green, 90))
