Script Creator Message - This may repaint..
Fair value bands, like other band tools, depict dynamic points in price where price behaviour is normal or abnormal, i.e. trading at/around mean (price at fair value) or deviating from mean (price outside fair value). Unlike constantly readjusting standard deviation based bands, fair value bands are designed to be smooth and constant, based on typical historical deviations. The script calculates pivots that take place above/below fair value basis and forms median deviation bands based on this information. These points are then multiplied up to 3, representing more extreme deviations.
CODE:
CSS:
#/ This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
#// © quantifytools
#https://www.tradingview.com/v/eos9U1qM/
#indicator("Fair value bands", overlay=true, max_labels_count=500, max_lines_count=500)
#//Settings
# Converted by Sam4Cok@Samer800 - 02/2023 - Not Complete conv.
input BarColor = yes;
input ShowNotificationLebel = yes;
input NoOfCalculatingBars = 500;
input ShowExtremeBandLines = yes;
input ShowThresholdBand = yes;
input ShowDeviationBand = yes;
input ThresholdBandWidth = 1.0; # "Threshold band width"
input DeviationBandWidth = 1.0; # "Deviation band width"
input sourceString = {Default "OHLC4", "Open", "High", "Low", "Close", "HL2", "HLC3", "HLCC4"};
input smoothingType = {Default "SMA", "EMA", "HMA", "RMA", "WMA", "VWMA", "Median"};
input smoothingLength = 20;
input trendMode = {default "Cross", "Direction"};
input thresholdUpString = {"OHLC4", "Open", "High",Default "Low", "Close", "HL2", "HLC3", "HLCC4"};
input thresholdDownString = {"OHLC4", "Open",Default "High", "Low", "Close", "HL2", "HLC3", "HLCC4"};
def na = Double.NaN;
def CrossMode = trendMode==trendMode."Cross";
#--- Color
DefineGlobalColor("extremeUpFill" , Color.DARK_RED);
DefineGlobalColor("extremeDownFill" , CreateColor(32,84,151));
DefineGlobalColor("blue" , CreateColor(33,150,243));
DefineGlobalColor("purple" , CreateColor(124,147,239));
DefineGlobalColor("aqua" , CreateColor(0,188,212));
DefineGlobalColor("yellow" , CreateColor(255,235,59));
DefineGlobalColor("orange" , CreateColor(255,152,0));
DefineGlobalColor("red" , CreateColor(255,82,82));
script fixnan{
input source = close;
def fix = if !isNaN(source) then source else fix[1];
plot result = fix;
}
#stringSrc(source) =>
script stringSrc {
input source = "OHLC4";
def src = if source == "Open" then open else
if source == "High" then high else
if source == "Low" then low else
if source == "Close" then close else
if source == "HL2" then hl2 else
if source == "HLC3" then hlc3 else
if source == "HLCC4" then (high+low+close+close)/4 else ohlc4;
plot return = src;
}
#//User defined source and smoothing
#smoothedValue(source, length) =>
script smoothedValue {
input source = close;
input length = 20;
input i_smoothingType = "SMA";
def vwma = SimpleMovingAvg(source * volume, length) / SimpleMovingAvg(volume, length);
def ma = if i_smoothingType == "SMA" then SimpleMovingAvg(source, length) else
if i_smoothingType == "EMA" then ExpAverage(source, length) else
if i_smoothingType == "HMA" then HullMovingAvg(source, length) else
if i_smoothingType == "RMA" then WildersAverage(source, length) else
if i_smoothingType == "VWMA" then vwma else
if i_smoothingType == "Median" then median(source, length) else wma(source, length);
plot out = ma;
}
script FindPivots {
input dat = close; # default data or study being evaluated
input HL = 0; # default high or low pivot designation, -1 low, +1 high
input lbL = 5; # default Pivot Lookback Left
input lbR = 1; # default Pivot Lookback Right
##############
def _nan; # used for non-number returns
def _BN; # the current barnumber
def _VStop; # confirms that the lookforward period continues the pivot trend
def _V; # the Value at the actual pivot point
##############
_BN = BarNumber();
_nan = Double.NaN;
_VStop = if !IsNaN(dat) and lbR > 0 and lbL > 0 then
fold a = 1 to lbR + 1 with b=1 while b do
if HL > 0 then dat > GetValue(dat, -a) else dat < GetValue(dat, -a) else _nan;
if (HL > 0) {
_V = if _BN > lbL and dat == Highest(dat, lbL + 1) and _VStop
then dat else _nan;
} else {
_V = if _BN > lbL and dat == Lowest(dat, lbL + 1) and _VStop
then dat else _nan;
}
plot result = if !IsNaN(_V) and _VStop then _V else _nan;
}
#// Fair value basis
#//Converting settings table source string to price source
def i_source = stringSrc(sourceString);
def i_thresholdUpSrc = stringSrc(thresholdUpString);
def i_thresholdDownSrc = stringSrc(thresholdDownString);
#//User defined source and smoothing
#//Fair value basis
def fairPriceSmooth = smoothedValue(i_source, smoothingLength, smoothingType);
#// Threshold band
#//Percentage distance between high/low and fair value basis
def lowSpread = low / fairPriceSmooth;
def highSpread = high / fairPriceSmooth;
#//Calculate low/high deviations from fair value basis
def deviationDown1 = if low < fairPriceSmooth and high > fairPriceSmooth then lowSpread else deviationDown1[1];
def deviationUp1 = if low < fairPriceSmooth and high > fairPriceSmooth then highSpread else deviationUp1[1];
def deviationDown = if deviationDown1==0 then lowSpread[1] else deviationDown1;
def deviationUp = if deviationUp1==0 then highSpread[1] else deviationUp1;
#//Median deviations
def sizeLimitDev = NoOfCalculatingBars;
def medianUpDeviation = Median(deviationUp, sizeLimitDev);
def medianDownDeviation = Median(deviationDown, sizeLimitDev);
#//Defining threshold band based on median deviations
def upperBand = fairPriceSmooth * medianUpDeviation;
def lowerBand = fairPriceSmooth * medianDownDeviation;
#//Calculating band spread from fair value basis
def bandUpSpread = upperBand - fairPriceSmooth;
def bandDownSpread = fairPriceSmooth - lowerBand;
#//Threshold band
def upperBandBoosted = fairPriceSmooth + (bandUpSpread * ThresholdBandWidth);
def lowerBandBoosted = fairPriceSmooth - (bandDownSpread * ThresholdBandWidth);
#//Switch for trend logic
def dirSwitch;
#//Trend rules up/down
def trendRuleUp = if CrossMode then i_thresholdUpSrc > upperBandBoosted else
fairPriceSmooth > fairPriceSmooth[1];
def trendRuleDown = if CrossMode then i_thresholdDownSrc < lowerBandBoosted else
fairPriceSmooth < fairPriceSmooth[1];
#//Trend up/down switch as per user defined rules
if trendRuleDown {
dirSwitch = -1;
} else
if trendRuleUp {
dirSwitch = 1;
} else {
dirSwitch = dirSwitch[1];
}
#//Percentage spread between fair value basis and OHLC4
def ohlc = ohlc4;
def ohlcSpread = ohlc / fairPriceSmooth;
#/Spread pivots
def Ph = findpivots(ohlcSpread, 1, 5, 5);
def Pl = findpivots(ohlcSpread, -1, 5, 5);
def pivotUp1 = if !IsNaN(Ph) then Ph else pivotUp1[1];
def pivotDown1 = if !IsNaN(Pl) then Pl else pivotDown1[1];
def pivotUp = if pivotUp1==0 then ohlcSpread else pivotUp1;
def pivotDown = if pivotDown1==0 then ohlcSpread else pivotDown1;
def upper_Boosted = upperBandBoosted; # Upper threshold
def lower_Boosted = lowerBandBoosted; # lower threshold
def pivotUps1;
def pivotDowns1;
if low > upperBand {
pivotUps1 = pivotUp;
pivotDowns1 = pivotDowns1[1];
} else
if high < lowerBand {
pivotUps1 = pivotUps1[1];
pivotDowns1 = pivotDown;
} else {
pivotUps1 = pivotUps1[1];
pivotDowns1 = pivotDowns1[1];
}
def pivotUps = if pivotUps1==0 then pivotUp[1] else pivotUps1;
def pivotDowns = if pivotDowns1==0 then pivotDown[1] else pivotDowns1;
#/Calculating median pivots from arrays
def sizeLimitBand = NoOfCalculatingBars;
def medianPivotUp = Median(pivotUps, sizeLimitBand);
def medianPivotDown = Median(pivotDowns, sizeLimitBand);
#//Pivot bands 1x median
def pivotBandUpBase = fairPriceSmooth * (medianPivotUp);
def pivotBandDownBase = fairPriceSmooth * (medianPivotDown);
#//Spread between pivot band and fair value basis
def pBandUpSpread = (pivotBandUpBase - fairPriceSmooth) * DeviationBandWidth;
def pBandDownSpread = (fairPriceSmooth - pivotBandDownBase) * DeviationBandWidth;
#//Pivot bands 1x median
def pivotBandUp = fairPriceSmooth + pBandUpSpread;
def pivotBandDown = fairPriceSmooth - pBandDownSpread;
#//Pivot bands 2x median
def pivotBandUp2 = pivotBandUp + pBandUpSpread;
def pivotBandDown2 = pivotBandDown - pBandDownSpread;
#//Pivot bands 3x median
def pivotBandUp3 = pivotBandUp2 + pBandUpSpread;
def pivotBandDown3 = pivotBandDown2 - pBandDownSpread;
#// Metrics
#//Defining fair value deviation lots
def abovePos2 = (i_source > pivotBandUp2);
def betweenPos1AndPos2 = (i_source > pivotBandUp) and (i_source <= pivotBandUp2);
def betweenMidAndPos1 = (i_source > fairPriceSmooth) and (i_source <= pivotBandUp);
def betweenMidAndNeg1 = (i_source < fairPriceSmooth) and (i_source >= pivotBandDown);
def betweenNeg1AndNeg2 = (i_source < pivotBandDown) and (i_source >= pivotBandDown2);
def belowNeg2 = (i_source < pivotBandDown2);
#//Colors
def dir = dirSwitch == 1;
plot pUpper = if ShowThresholdBand then upperBandBoosted else na;#, "Threshold band up"
plot pLower = if ShowThresholdBand then lowerBandBoosted else na;#, "Threshold band down"
pUpper.SetDefaultColor(Color.GRAY);
pLower.SetDefaultColor(Color.GRAY);
plot pMid = fairPriceSmooth;#, "Fair value basis"
pMid.AssignValueColor(if dir then CreateColor(16, 128, 255) else Color.RED);
plot p1U = pivotBandUp;#, "Fair value deviation band up 1x"
p1U.SetHiding(!ShowDeviationBand);
p1U.SetDefaultColor(Color.GRAY);
p1U.SetStyle(Curve.SHORT_DASH);
plot p1D = pivotBandDown;#, "Fair value deviation band down 1x",
p1D.SetHiding(!ShowDeviationBand);
p1D.SetDefaultColor(Color.GRAY);
p1D.SetStyle(Curve.SHORT_DASH);
def p2U = pivotBandUp2;#, "Fair value deviation band up 2x",
def p2D = pivotBandDown2;#, "Fair value deviation band down 2x"
def p3U = pivotBandUp3;#, "Fair value deviation band up 3x",
def p3D = pivotBandDown3;#, "Fair value deviation band down 3x"
#//Fills
AddCloud(p3U, p2U,GlobalColor("extremeUpFill"),GlobalColor("extremeUpFill"),ShowExtremeBandLines); #"Extreme deviation up"
AddCloud(p2D, p3D,GlobalColor("extremeDownFill"),GlobalColor("extremeDownFill"),ShowExtremeBandLines);#"Extreme deviation down"
AddCloud(if ohlc4>p2U then ohlC4 else na,p1U , Color.DARK_RED);
AddCloud(if ohlc4<p2D then p1D else na, ohlc4, CreateColor(51,41,193));
AssignPriceColor(if !BarColor then Color.CURRENT else
if belowNeg2 then GlobalColor("blue") else
if betweenNeg1AndNeg2 then GlobalColor("purple") else
if betweenMidAndNeg1 then GlobalColor("aqua") else
if betweenMidAndPos1 then GlobalColor("yellow") else
if betweenPos1AndPos2 then GlobalColor("orange") else
if abovePos2 then GlobalColor("red") else Color.GRAY);
#//Price at fair value basis during trend scenarios
def fairPriceInUp = dirSwitch == 1 and low <= upperBandBoosted;
def fairPriceInDown = dirSwitch == -1 and high >= lowerBandBoosted;
AddLabel(ShowNotificationLebel and fairPriceInUp, "Low at fair value in uptrend", Color.GREEN);
AddLabel(ShowNotificationLebel and fairPriceInDown, "High at fair value basis in downtrend", Color.RED);
#--- END Code