Interquartile_Range_IQR_Anomaly_Detection
# ─────────────────────────────────────────────
# │ MarketFragments.com | DNA & Market │
# │ info@marketfragments.com │
# │ www.marketfragments.com │
# ──────────────────────────────────────────────
# Time →
# │
# █ █ █│ █
# █ █ █ │ █ █
# █ █ █ │ █ █ █ ╭─╮
# █ █ █ │ █ █ █ █ ╭─╯ ╰─╮
# █ █ █ │ █ █ █ █ █ █ ╭─╯ ╰─╮
# █ █ █ │ █ █ █ █ █ █ █ █ ╭─╯ ╰─╮
# █ █ █ │ █ █ █ █ █ █ █ █ █ █╭─╯ ╰─╮
# █ █ █ │ █ █ █ █ █ █ █ █ ╰─╮ ╭─╯
# █ █ █ │ █ █ █ █ █ █ ╰─╮ ╭─╯
# █ █ █ │ █ █ █ █ ╰─╮ ╭─╯
# █ █ █ │ █ █ ╰─╮ ╭─╯
# █ █ █ │ █ ╰─────╯
# ──────┴──────────────────────────────────────────────────────────────
# T1 T2 T3 T4 T5 T6
#
# Name: Interquartile Range (IQR) Anomaly Detection
declare lower;
#info:The primary purpose of this indicator is to identify potential outliers or abnormal movements in the daily returns of the stock.
# Define inputs
input price = close;
input length = 100;
input k = 1.5;
# Custom PercentileRank function
script PercentileRank {
Input arr = close;
Input value = close;
Input Length = 20;
def count = fold i = 0 to Length - 1 with d = arr do if GetValue(d, i) <= value then count[1] + 1 else count[1];
plot return = (count / Length) * 100;
}
# Calculate daily returns
def daily_return = (price / price[1] - 1) * 100;
# Calculate IQR
def sortedData = fold i1 = 0 to length
with p1 = daily_return
do if GetValue(p1, i1) > GetValue(p1, i1 + 1) then
Double.NaN
else p1;
def sortedPrices = fold i2 = 0 to length
with p2 = price
do if GetValue(p2, i2) > GetValue(p2, i2 + 1) then
Double.NaN
else p2;
#def Q1 = PercentileRank(arr=daily_return, value=PercentileRank(arr=daily_return, value=0.25, Length=length), Length=length);
#def Q3 = PercentileRank(arr=daily_return, value=PercentileRank(arr=daily_return, value=0.75, Length=length), Length=length);
def Q1 = GetValue(sortedData, RoundDown(0.25 * length));
def Q3 = GetValue(sortedData, RoundDown(0.75 * length));
def IQR = Q3 - Q1;
# Detect outliers using IQR
def isOutlier = if daily_return < Q1 - k * IQR then -1 else if daily_return > Q3 + k * IQR then 1 else 0;
# Plotting
plot Outliers =if isOutlier then daily_return else Double.NaN;#if isOutlier then close else Double.NaN;#
Outliers.SetPaintingStrategy(PaintingStrategy.POINTS);
Outliers.SetLineWeight(3);
Outliers.assignValueColor(if isOutlier==1 then color.green else color.red) ;
Outliers.SetStyle(Curve.POINTS);
Outliers.HideTitle();
# Plot daily returns
plot DailyReturn =IQR ;
DailyReturn.SetPaintingStrategy(PaintingStrategy.LINE);
DailyReturn.SetDefaultColor(Color.BLUE);
#DailyReturn.HideTitle();
# Add labels
AddLabel(yes, "Outlier", Color.RED);
AddLabel(yes, "Daily Return", Color.BLUE);

