Fed Funds Rate Projections
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © barnabygraham

//@version=5
indicator("Fed Funds Rate Projections",overlay=true,max_boxes_count=500)

// measures the x axis in number of candlesticks
n = bar_index

// defines the starting point of where the projections will be projected from
baselineChoice = input.string('Moving Average','Baseline',options=['close','Moving Average'],tooltip='defines the starting point of where the projections will be projected from')
maLength = input.int(20,'Moving Average Length',tooltip='length of the moving average when the baseline has been set to "moving average"')
base = baselineChoice == 'close' ? close : baselineChoice == 'Moving Average' ? ta.sma(close,maLength) : na

// the significance of the change in rates (10 means a 0.25bps change implies a 2.5% lower stock price)
multiplier = input.float(10,'Multiplier',tooltip='the significance of the change in rates (10 means a 0.25bps change implies a 2.5% lower stock price)')

// the minimum threshold which a change in rates requires to draw a box
threshold = input.float(0.2,'Minimum change threshold in bps',tooltip='the minimum threshold which a change in rates requires to draw a box',step=0.1)

// the fed funds rate
fedRate = request.security("FRED:EFFR", "D", close)

// checks if there has been a change in the fed funds rate and calculates the amount it has changed
update = not(fedRate==fedRate[1])
change = 0.
if update
    change := ta.change(fedRate*-1)

// Turns the change in the fed funds rate into a percentage which we can use to cast projections with
multipliedChange = 0.01*(multiplier * change)

// the projection's baseline (the vertical middle of the box)
projection = base+(multipliedChange*base)

// how many candlesticks in the future to project out (the right side of the box from the candlestick on which the box was made)
lookForward = input.int(100,'Look forward',tooltip='how many candlesticks in the future to project out (the right side of the box from the candlestick on which the box was made)')

// The opacity. Automatically makes boxes brighter for larger changes in rates and makes small rate changes almost invisible
opac = 120-(math.abs(change)*100)

// box color
boxColor = input.color(color.new(color.yellow,0),'Box Color')

// box height multiplier
boxHeight = input.float(0.03,'Box Height',step=0.01)

// draws boxes when there has been a change in the fed funds rate and meet the minimum threshold
if update and math.abs(change) >= threshold
    newLine = box.new(n,projection+(projection*(boxHeight)),n+lookForward,projection-(projection*(boxHeight)),border_color=color.new(color.white,100),bgcolor=color.new(boxColor,opac))
