// market-structure.afl
// Part 4 - Market Structure: Trends, Ranges and Transitions
//
// Classifies the chart into one of three labels using the confirmed swing
// points from the previous lesson:
//
//   higher highs and higher lows   -> "up structure"
//   lower highs and lower lows     -> "down structure"
//   anything else                  -> "unclassified"
//
// The classification is a definition applied consistently. It describes what
// the recent swing points did. It says nothing about what comes next.
//
// Assumptions:
//   - Swing strength is the only free parameter. Change it and the labels
//     change; comparing two settings is the honest way to use this formula.
//   - Every label is late by at least Strength bars, because a swing point
//     cannot be confirmed until Strength bars have printed after it.
//   - "Unclassified" is a real answer and, on most instruments, a common one.

_SECTION_BEGIN("Market structure");

Strength = Param( "Swing strength (bars either side)", 5, 1, 25, 1 );
Window   = 2 * Strength + 1;

BarNumber = Cum( 1 );
HasWindow = BarNumber >= Window;

CandidateHigh = Ref( High, -Strength );
CandidateLow  = Ref( Low,  -Strength );

SwingHigh = HasWindow AND CandidateHigh == HHV( High, Window );
SwingLow  = HasWindow AND CandidateLow  == LLV( Low,  Window );

// ValueWhen's third argument selects the n-th most recent occurrence:
// 1 is the latest, 2 is the one before it. Two of each is the minimum needed
// to say whether highs and lows are rising or falling.
HighNow  = ValueWhen( SwingHigh, CandidateHigh, 1 );
HighPrev = ValueWhen( SwingHigh, CandidateHigh, 2 );
LowNow   = ValueWhen( SwingLow,  CandidateLow,  1 );
LowPrev  = ValueWhen( SwingLow,  CandidateLow,  2 );

HigherHigh = HighNow > HighPrev;
HigherLow  = LowNow  > LowPrev;
LowerHigh  = HighNow < HighPrev;
LowerLow   = LowNow  < LowPrev;

UpStructure   = HigherHigh AND HigherLow;
DownStructure = LowerHigh AND LowerLow;

Plot( Close, "Price", colorDefault, styleCandle );

// The ribbon is a convenience, not the message. Colour is never the only way to
// read the classification here: the title states it in words as well, which is
// also what makes the chart usable by a reader who cannot distinguish the hues.
RibbonColour = IIf( UpStructure, colorPaleGreen,
               IIf( DownStructure, colorRose, colorLightGrey ) );

Plot( 2, "Structure", RibbonColour,
      styleOwnScale | styleArea | styleNoLabel | styleNoTitle, -0.5, 100 );

StructureText = WriteIf( UpStructure, "Higher highs and higher lows",
                WriteIf( DownStructure, "Lower highs and lower lows",
                         "Unclassified - the swings disagree" ) );

_N( Title =
    Name() + " - " + Interval( 2 ) +
    StrFormat( " - structure at swing strength %g\n", Strength ) +
    StructureText + "\n" +
    StrFormat( "Swing highs: %g then %g\n", HighPrev, HighNow ) +
    StrFormat( "Swing lows:  %g then %g\n", LowPrev, LowNow ) +
    StrFormat( "This label could not have been known until %g bars "
             + "after the newer swing formed.", Strength ) );

_SECTION_END();
