#9/17/2025 - CJE - CREATED BASED ON PREVIOUS PERIOD VOLUME PROFILE FROM UTHINKSCRIPT. AUTHOR UNKNOWN. STIPPED OUT MOST NON-ESSENTIALS SO IT PLOTS ONLY THE MOVING AVERAGE OF THE POC. CAN CHOOSE PERIOD AND TIME/VOLUME. IF MA IS TOO CHOPPY, CHOOSE A SMALLER PROFILE PERIOD. IF YOU NEED MORE DATA, INCREASE THE NUMBER OF PROFILES.
input length = 14;
input averageType = AverageType.SIMPLE;
# Profile TPO & Volume
input profileType = {Time, default Volume};
input pricePerRowHeightMode = {default Ticksize, Automatic, Custom};
def customRowHeight = 1.0;
input timePerProfile = {default Day, Week, Month, QUARTER, Year, Hour, "Fifteen Minutes", Chart, Bar, "Opt Exp"};
def multiplier = 1;
def OnExpansionProfile = No;
def OnExpansionValueArea = No;
input profiles = 500;
def showPointOfControl = Yes;
def ValueAreaPercent = 70;
input POCCrossAlert = no;
input showBreakoutSignals = NO;
input showDevBands = no;
input stdDevs = 0.5;
def period;
def yyyymmdd = GetYYYYMMDD();
def seconds = SecondsFromTime(0);
def month = GetYear() * 12 + GetMonth();
def qtr = GetYear() * 4 + (if GetMonth() < 4 then 1
else if GetMonth() < 7 then 2
else if GetMonth() < 10 then 3
else 4);
def year = GetYear();
def day_number = DaysFromDate(First(yyyymmdd)) + GetDayOfWeek(First(yyyymmdd));
def dom = GetDayOfMonth(yyyymmdd);
def dow = GetDayOfWeek(yyyymmdd - dom + 1);
def expthismonth = (if dow > 5 then 27 else 20) - dow;
def exp_opt = month + (dom > expthismonth);
switch (timePerProfile) {
case Chart:
period = 0;
case "Fifteen Minutes":
period = Floor(seconds / 900 + day_number * 24);
case Hour:
period = Floor(seconds / 3600 + day_number * 24);
case Day:
period = CountTradingDays(Min(First(yyyymmdd), yyyymmdd), yyyymmdd) - 1;
case Week:
period = Floor(day_number / 7);
case Month:
period = Floor(month - First(month));
case QUARTER:
period = Floor(qtr - First(qtr));
case Year:
period = Floor(year - First(year));
case "Opt Exp":
period = exp_opt - First(exp_opt);
case Bar:
period = BarNumber() - 1;
}
def CloseByPeriod = close(Period = timePerProfile)[-1];
def Openbyperiod = open(Period = timePerProfile)[-1];
def NewDay = if !IsNaN(CloseByPeriod) then 0 else 1;
rec Count = if period != period[1] then (Count[1] + period - period[1]) % 1 else Count[1];
def Cond = Count < Count[1] + period - period[1];
def height;
switch (pricePerRowHeightMode) {
case Automatic:
height = PricePerRow.AUTOMATIC;
case Ticksize:
height = PricePerRow.TICKSIZE;
case Custom:
height = customRowHeight;
}
profile VOL = if profileType == profileType.Volume then VolumeProfile("startNewProfile" = Cond, "onExpansion" = OnExpansionProfile, "NumberOfProfiles" = profiles, "PricePerRow" = height, "Value Area Percent" = ValueAreaPercent) else TimeProfile("startNewProfile" = Cond, "OnExpansion" = OnExpansionProfile, "NumberOfProfiles" = profiles, "PricePerRow" = height, "Value Area Percent" = ValueAreaPercent);
def con = CompoundValue(1, OnExpansionProfile, no);
rec pc = if IsNaN(VOL.GetPointOfControl()) and con then pc[1] else VOL.GetPointOfControl();
rec hVA = if IsNaN(VOL.GetHighestValueArea()) and con then hVA[1] else VOL.GetHighestValueArea();
rec lVA = if IsNaN(VOL.GetLowestValueArea()) and con then lVA[1] else VOL.GetLowestValueArea();
rec HVA_Last = if period == period[1] then HVA_Last[1] else hVA[1];
rec PC_Last = if period == period[1] then PC_Last[1] else pc[1];
rec PC_2P = if period == period[1] then PC_2P[1] else PC_Last[1];
rec LVA_Last = if period == period[1] then LVA_Last[1] else lVA[1];
rec hProfile = if IsNaN(VOL.GetHighest()) and con then hProfile[1] else VOL.GetHighest();
rec lProfile = if IsNaN(VOL.GetLowest()) and con then lProfile[1] else VOL.GetLowest();
def plotsDomain = IsNaN(close) == OnExpansionProfile;
rec hP_Last = if period == period[1] then hP_Last[1] else hProfile[1];
rec lP_Last = if period == period[1] then lP_Last[1] else lProfile[1];
def VAH = if IsNaN(close[0]) then HVA_Last[0] else if !OnExpansionValueArea then HVA_Last[0] else Double.NaN;
def POC = if IsNaN(close[0]) then PC_Last[0] else if !OnExpansionValueArea then PC_Last[0] else Double.NaN;
def VAL = if IsNaN(close[0]) then LVA_Last[0] else if !OnExpansionValueArea then LVA_Last[0] else Double.NaN;
plot POC_avg = MovingAverage(data = POC, length = length, averageType = AverageType);
POC_avg.SetDefaultColor(Color.MAGENTA);
POC_avg.SetLineWeight(2);
def dev = ATR();
plot dev_Hi = POC_avg + dev * stdDevs;
plot dev_Lo = POC_avg - (dev * stdDevs);
dev_Hi.SetDefaultColor(Color.GRAY);
dev_Hi.SetLineWeight(2);
dev_Hi.SetHiding(!showDevBands);
dev_Lo.SetDefaultColor(Color.GRAY);
dev_Lo.SetLineWeight(2);
dev_Lo.SetHiding(!showDevBands);
def revBull2 = CLOSE() crosses ABOVE POc_avg;
def revBear2 = CLOSE() crosses BELOW POc_avg ;
plot UpSignalL = revBull2;
plot DownSignalL = revBear2;
UpSignalL.SetHiding(!showBreakoutSignals);
DownSignalL.SetHiding(!showBreakoutSignals);
UpSignalL.SetDefaultColor(Color.UPTICK);
UpSignalL.SetPaintingStrategy(PaintingStrategy.BOOLEAN_ARROW_UP);
DownSignalL.SetDefaultColor(Color.DOWNTICK);
DownSignalL.SetPaintingStrategy(PaintingStrategy.BOOLEAN_ARROW_DOWN);
Alert(UpSignalL and POCCrossAlert,"POC Cross Above", Alert.Bar, Sound.Bell);
Alert(DownSignalL and POCCrossAlert,"POC Cross Below", Alert.Bar, Sound.Ding);