Price Structure plus Volume Participation Module
How I’d read it
How I’d read it
Best long setup sequence
On SPY, the cleaner long sequence is:- participation oscillator stops falling
- yellow early-up dot appears
- histogram flips positive
- companion line turns up
- structure shifts from mixed to bull
- green up arrow appears
- internals improved first
- then price structure caught up
- then the move became more trustworthy
Weak bounce / tactical only sequence
If you get:- structure still bear or mixed
- oscillator turns up
- histogram improves
- early dot prints
- but no confirmed bull alignment
- bounce potential
- early repair
- not yet a clean swing continuation state
Warning sequence
If structure still says bull but:- oscillator drops below zero
- histogram weakens
- labels shift to conflict
- price still looks okay on surface
- participation is no longer backing it
- next few bars are more vulnerable to stall, fade, or failed continuation
Code:
declare lower;
input price = close;
input fastEMALength = 8;
input slowEMALength = 21;
input structureLookback = 20;
input volumeLength = 20;
input partFastLength = 5;
input partSlowLength = 13;
input normalizeLength = 50;
input signalLength = 5;
input showZeroLine = yes;
input showMarkers = yes;
input showStretchMarkers = yes;
input stretchLength = 20;
input stretchTrigger = 1.5;
def na = Double.NaN;
# -----------------------------
# PRICE STRUCTURE MODULE
# -----------------------------
def fastEMAValue = ExpAverage(price, fastEMALength);
def slowEMAValue = ExpAverage(price, slowEMALength);
def fastEMASlope = fastEMAValue - fastEMAValue[1];
def highestRange = Highest(high, structureLookback);
def lowestRange = Lowest(low, structureLookback);
def structureMid = (highestRange + lowestRange) / 2;
def structureScore =
(if fastEMAValue > slowEMAValue then 1 else -1) +
(if fastEMASlope > 0 then 1 else -1) +
(if price > structureMid then 1 else -1);
def structureBull = structureScore >= 2;
def structureBear = structureScore <= -2;
def structureMixed = !structureBull and !structureBear;
# -----------------------------
# VOLUME PARTICIPATION MODULE
# price change weighted by relative volume
# -----------------------------
def avgVolumeValue = Average(volume, volumeLength);
def relativeVolume = if avgVolumeValue > 0 then volume / avgVolumeValue else 1;
def priceDelta = price - price[1];
def weightedDelta = priceDelta * relativeVolume;
def partFastValue = ExpAverage(weightedDelta, partFastLength);
def partSlowValue = ExpAverage(weightedDelta, partSlowLength);
def rawParticipationOsc = partFastValue - partSlowValue;
def oscMean = Average(rawParticipationOsc, normalizeLength);
def oscStDev = StDev(rawParticipationOsc, normalizeLength);
def participationOsc =
if oscStDev > 0
then (rawParticipationOsc - oscMean) / oscStDev
else 0;
def companionSignal = ExpAverage(participationOsc, signalLength);
def participationHist = participationOsc - companionSignal;
# -----------------------------
# PARTICIPATION STATES
# -----------------------------
def partPositive = participationOsc > 0;
def partNegative = participationOsc < 0;
def partRising = participationOsc > participationOsc[1];
def partFalling = participationOsc < participationOsc[1];
def earlyUpTurn =
participationOsc > participationOsc[1] and
participationOsc[1] <= participationOsc[2] and
participationHist > 0 and
!structureBull;
def earlyDownTurn =
participationOsc < participationOsc[1] and
participationOsc[1] >= participationOsc[2] and
participationHist < 0 and
!structureBear;
def confirmedUp =
structureBull and
participationOsc > 0 and
companionSignal > 0 and
participationHist > 0;
def confirmedDown =
structureBear and
participationOsc < 0 and
companionSignal < 0 and
participationHist < 0;
# -----------------------------
# SYNTHESIS LOGIC
# explicit precedence
# -----------------------------
def bullConfirmed = confirmedUp;
def bearConfirmed = confirmedDown;
def bullConflict =
structureBull and
partNegative;
def bearConflict =
structureBear and
partPositive;
def improvingBeforePrice =
!structureBull and
partPositive and
partRising and
participationHist > 0;
def weakeningBeforePrice =
!structureBear and
partNegative and
partFalling and
participationHist < 0;
def chopRisk =
structureMixed or
(structureBull and partNegative and participationHist >= 0) or
(structureBear and partPositive and participationHist <= 0);
def nextBarsUpBias =
bullConfirmed or
(structureBull and partRising) or
improvingBeforePrice;
def nextBarsDownBias =
bearConfirmed or
(structureBear and partFalling) or
weakeningBeforePrice;
# -----------------------------
# STRETCH / DEVIATION MODULE
# -----------------------------
def stretchBasis = Average(price, stretchLength);
def stretchStDev = StDev(price, stretchLength);
def stretchZ =
if stretchStDev > 0
then (price - stretchBasis) / stretchStDev
else 0;
def stretchHigh = stretchZ > stretchTrigger;
def stretchLow = stretchZ < -stretchTrigger;
# -----------------------------
# PLOTS
# -----------------------------
plot ZeroLine = if showZeroLine then 0 else na;
ZeroLine.SetDefaultColor(Color.GRAY);
ZeroLine.SetStyle(Curve.SHORT_DASH);
plot ParticipationLine = participationOsc;
ParticipationLine.SetLineWeight(2);
ParticipationLine.AssignValueColor(
if participationOsc >= 0 and partRising then Color.GREEN
else if participationOsc >= 0 then Color.DARK_GREEN
else if participationOsc < 0 and partFalling then Color.RED
else Color.DARK_RED
);
plot CompanionLine = companionSignal;
CompanionLine.SetDefaultColor(Color.CYAN);
CompanionLine.SetLineWeight(2);
plot Hist = participationHist;
Hist.SetPaintingStrategy(PaintingStrategy.HISTOGRAM);
Hist.SetLineWeight(3);
Hist.AssignValueColor(
if participationHist > 0 and participationHist > participationHist[1] then Color.UPTICK
else if participationHist > 0 then Color.GREEN
else if participationHist < 0 and participationHist < participationHist[1] then Color.DOWNTICK
else Color.RED
);
# -----------------------------
# EARLY / LATE MARKERS
# -----------------------------
plot EarlyUpDot = if showMarkers and earlyUpTurn then participationOsc else na;
EarlyUpDot.SetPaintingStrategy(PaintingStrategy.POINTS);
EarlyUpDot.SetDefaultColor(Color.YELLOW);
EarlyUpDot.SetLineWeight(3);
plot EarlyDownDot = if showMarkers and earlyDownTurn then participationOsc else na;
EarlyDownDot.SetPaintingStrategy(PaintingStrategy.POINTS);
EarlyDownDot.SetDefaultColor(Color.ORANGE);
EarlyDownDot.SetLineWeight(3);
plot LateUpArrow = if showMarkers and bullConfirmed then participationOsc else na;
LateUpArrow.SetPaintingStrategy(PaintingStrategy.ARROW_UP);
LateUpArrow.SetDefaultColor(Color.GREEN);
LateUpArrow.SetLineWeight(2);
plot LateDownArrow = if showMarkers and bearConfirmed then participationOsc else na;
LateDownArrow.SetPaintingStrategy(PaintingStrategy.ARROW_DOWN);
LateDownArrow.SetDefaultColor(Color.RED);
LateDownArrow.SetLineWeight(2);
# -----------------------------
# STRETCH MARKERS
# -----------------------------
plot StretchHighDot = if showStretchMarkers and stretchHigh and partFalling then participationOsc else na;
StretchHighDot.SetPaintingStrategy(PaintingStrategy.POINTS);
StretchHighDot.SetDefaultColor(Color.MAGENTA);
StretchHighDot.SetLineWeight(2);
plot StretchLowDot = if showStretchMarkers and stretchLow and partRising then participationOsc else na;
StretchLowDot.SetPaintingStrategy(PaintingStrategy.POINTS);
StretchLowDot.SetDefaultColor(Color.CYAN);
StretchLowDot.SetLineWeight(2);
# -----------------------------
# LABELS
# -----------------------------
AddLabel(
yes,
if structureBull then "Structure: Bull"
else if structureBear then "Structure: Bear"
else "Structure: Mixed",
if structureBull then Color.GREEN
else if structureBear then Color.RED
else Color.GRAY
);
AddLabel(
yes,
if partPositive and partRising then "Participation: Positive and Rising"
else if partPositive then "Participation: Positive but Slowing"
else if partNegative and partFalling then "Participation: Negative and Falling"
else if partNegative then "Participation: Negative but Improving"
else "Participation: Flat",
if partPositive and partRising then Color.GREEN
else if partPositive then Color.DARK_GREEN
else if partNegative and partFalling then Color.RED
else if partNegative then Color.ORANGE
else Color.GRAY
);
AddLabel(
yes,
if bullConfirmed then "Synthesis: Participation Confirms Price"
else if bearConfirmed then "Synthesis: Participation Confirms Downside"
else if bullConflict then "Synthesis: Bull Structure, Participation Not Confirming"
else if bearConflict then "Synthesis: Bear Structure, Participation Improving"
else if improvingBeforePrice then "Synthesis: Participation Improving Before Price"
else if weakeningBeforePrice then "Synthesis: Participation Weakening Before Price"
else "Synthesis: Mixed or Transitional",
if bullConfirmed then Color.GREEN
else if bearConfirmed then Color.RED
else if improvingBeforePrice then Color.CYAN
else if weakeningBeforePrice then Color.MAGENTA
else Color.YELLOW
);
AddLabel(
yes,
if nextBarsUpBias and !nextBarsDownBias then "Next Few Bars: Up Bias"
else if nextBarsDownBias and !nextBarsUpBias then "Next Few Bars: Down Bias"
else if chopRisk then "Next Few Bars: Stall or Chop Risk"
else "Next Few Bars: Balanced",
if nextBarsUpBias and !nextBarsDownBias then Color.GREEN
else if nextBarsDownBias and !nextBarsUpBias then Color.RED
else Color.GRAY
);
Last edited by a moderator: