Level 5 — MasteryCandlestick Patterns

Candlestick Patterns

90 minutes60 marksprintable — key stays hidden on paper

Chapter: 3.2 Candlestick Patterns Level: 5 — Mastery (cross-domain: quantitative finance + math + coding + proof) Time limit: 90 minutes Total marks: 60

Instructions. Answer all three questions. Show reasoning, define every parameter, and present code in clean pseudocode or Python. Use ...... for inline math and ...... for displayed math. Numerical answers must be reproducible from the OHLC data given.


Question 1 — Formalising Candle Anatomy & Building a Classifier (22 marks)

A single candle is the tuple (O,H,L,C)(O, H, L, C) with Hmax(O,C)H \ge \max(O,C) and Lmin(O,C)L \le \min(O,C).

Define:

  • Real body: B=COB = |C - O|
  • Upper wick: U=Hmax(O,C)U = H - \max(O,C)
  • Lower wick: Lw=min(O,C)LLw = \min(O,C) - L
  • Total range: R=HLR = H - L

(a) Prove the identity R=B+U+LwR = B + U + Lw directly from the definitions, treating both the bullish (C>OC>O) and bearish (C<OC<O) cases. (4 marks)

(b) A doji is defined operationally by the rule BτRB \le \tau R for a threshold τ\tau (a dragonfly doji additionally requires UτRU \le \tau R; a gravestone additionally requires LwτRLw \le \tau R). Using τ=0.1\tau = 0.1, classify each candle below as (i) doji / not-doji, and if doji, (ii) dragonfly / gravestone / neutral. (6 marks)

# O H L C
A 100 108 92 100.5
B 50 50.4 42 50.2
C 30 38 29.8 30.1

(c) Write a pure function classify(o,h,l,c,tau) returning one of {"bullish_marubozu","hammer","shooting_star","dragonfly_doji","spinning_top","other"}. State precisely the mathematical inequalities you use for hammer and shooting star (in terms of B,U,Lw,RB, U, Lw, R) and justify why they capture the pattern's market psychology. (8 marks)

(d) Prove that with your hammer rule, a bullish marubozu (U=Lw=0U = Lw = 0) can never be classified as a hammer. (4 marks)


Question 2 — Engulfing & Multi-Candle Patterns: A Probabilistic Backtest (22 marks)

Consider two consecutive candles (O1,H1,L1,C1)(O_1,H_1,L_1,C_1) then (O2,H2,L2,C2)(O_2,H_2,L_2,C_2).

(a) Give the exact inequality conditions for a bullish engulfing pattern in a downtrend, and separately for a bullish harami. Show algebraically that the two patterns are mutually exclusive (they cannot occur on the same candle pair). (6 marks)

(b) A trader models a candle body as CON(μ,σ2)C - O \sim \mathcal{N}(\mu, \sigma^2) i.i.d. per bar, with μ=0\mu = 0, σ=2\sigma = 2. Assume opens satisfy O2=C1O_2 = C_1 (continuous gaps ignored). Derive the probability that a two-candle sequence forms a bearish engulfing given candle 1 is bullish (C1>O1C_1 > O_1). Express the answer as an integral / in terms of Φ\Phi, then compute it numerically. (9 marks)

(c) The morning star is a 3-candle reversal. Encode it as a boolean predicate over 12 OHLC values, including a "star gap" and a body-size condition (candle 2's body \le 30% of candle 1's body). Then explain, using the context principle (subtopic 3.2.13), why the same three shapes appearing at the top of an uptrend would be interpreted differently — and what pattern they would resemble. (7 marks)


Question 3 — Rising Three Methods: Simulation & Proof (16 marks)

The rising three methods is a 5-candle bullish continuation: a long white candle, three small candles that stay within candle 1's range and drift down, then a fifth long white candle closing above candle 1's close.

(a) Formalise the pattern as a conjunction of inequalities on candles 1..51..5. Precisely state the "contained within candle 1's high–low range" and "closes above" conditions. (6 marks)

(b) Write a vectorised backtesting function (NumPy-style pseudocode) that scans an array of NN candles and returns the indices where a rising-three-methods pattern begins. State its time complexity. (6 marks)

(c) Prove that if the rising-three-methods conditions hold, then C5>C1>max(C2,C3,C4)C_5 > C_1 > \max(C_2,C_3,C_4) is not guaranteed, but C5>C1C_5 > C_1 is — and give a concrete counterexample to the first claim. (4 marks)


Answer keyMark scheme & solutions

Question 1

(a) Proof of R=B+U+LwR = B + U + Lw (4 marks)

Let m=max(O,C)m = \max(O,C), n=min(O,C)n = \min(O,C). Then by definition U=HmU = H - m, Lw=nLLw = n - L, B=mnB = m - n (since B=CO=mnB=|C-O| = m-n). [2]

B+U+Lw=(mn)+(Hm)+(nL)=HL=R.B + U + Lw = (m-n) + (H-m) + (n-L) = H - L = R. [1]

This holds regardless of whether C>OC>O (bullish) or C<OC<O (bearish), because the algebra uses only max/min\max/\min, which is symmetric in O,CO,C. [1]

(b) Classification, τ=0.1\tau=0.1 (6 marks) — 2 marks each.

  • Candle A: R=16R=16, B=100.5100=0.5B=|100.5-100|=0.5. τR=1.6\tau R = 1.6; 0.51.60.5 \le 1.6doji. U=108100.5=7.5U = 108-100.5=7.5, Lw=10092=8Lw=100-92=8. Neither 1.6\le 1.6neutral (long-legged) doji. [2]
  • Candle B: R=8.4R=8.4, B=0.2B=0.2. τR=0.84\tau R=0.84; 0.20.840.2\le0.84doji. U=50.450.2=0.20.84U=50.4-50.2=0.2\le0.84 ✓; Lw=5042=8>0.84Lw=50-42=8 > 0.84 ✗. Only upper wick small → gravestone doji. [2]
  • Candle C: R=8.2R=8.2, B=0.1B=0.1. τR=0.82\tau R=0.82; 0.10.820.1\le0.82doji. U=3830.1=7.9U=38-30.1=7.9; Lw=3029.8=0.20.82Lw=30-29.8=0.2\le0.82 ✓. Only lower wick small → dragonfly doji. [2]

(c) Classifier (8 marks)

Precise rules (using body BB, wicks U,LwU,Lw, range RR, and τ\tau):

  • hammer: Lw2BLw \ge 2B and UτRU \le \tau R and B>τRB > \tau R (long lower wick ≥ twice body, tiny/no upper wick, non-doji body). [2]
  • shooting star: U2BU \ge 2B and LwτRLw \le \tau R and B>τRB > \tau R. [2]
def classify(o, h, l, c, tau=0.1):
    m, n = max(o, c), min(o, c)
    B, U, Lw, R = m - n, h - m, n - l, h - l
    if R == 0:
        return "other"
    if B <= tau * R:                       # doji family
        if U <= tau * R and Lw > tau * R:  return "dragonfly_doji"
        # (gravestone/neutral omitted for return-set brevity)
        return "spinning_top"
    if U == 0 and Lw == 0:                 return "bullish_marubozu" if c > o else "other"
    if Lw >= 2*B and U <= tau*R:           return "hammer"
    if U  >= 2*B and Lw <= tau*R:          return "shooting_star"
    if U > tau*R and Lw > tau*R:           return "spinning_top"
    return "other"

Function structure & correct branch ordering [2]. Psychology justification: hammer's long lower wick = sellers pushed price down but buyers reclaimed the close near the top → bullish rejection of lows; shooting star's long upper wick = buyers pushed up but sellers slammed close back near the low → bearish rejection of highs. [2]

(d) Marubozu cannot be a hammer (4 marks)

For a marubozu, U=0U=0 and Lw=0Lw=0. The hammer rule requires Lw2BLw \ge 2B. [1] For a real candle B=R>0B = R > 0 (marubozu has a body). [1] So Lw2BLw \ge 2B becomes 02R>00 \ge 2R > 0, a contradiction. [1] Hence the hammer branch is never entered; a marubozu is classified bullish_marubozu (which is checked first). [1]


Question 2

(a) Engulfing vs Harami (6 marks)

Bullish engulfing (prior downtrend): candle 1 bearish, candle 2 bullish, body 2 engulfs body 1: C1<O1,C2>O2,O2C1,C2O1.C_1 < O_1,\quad C_2 > O_2,\quad O_2 \le C_1,\quad C_2 \ge O_1. [2]

Bullish harami: candle 1 bearish (large body), candle 2 bullish and body contained inside candle 1's body: C1<O1,C2>O2,O2C1,C2O1.C_1 < O_1,\quad C_2 > O_2,\quad O_2 \ge C_1,\quad C_2 \le O_1. [2]

Mutual exclusivity: engulfing needs O2C1O_2 \le C_1 and C2O1C_2 \ge O_1; harami needs O2C1O_2 \ge C_1 and C2O1C_2 \le O_1. Both sets simultaneously force O2=C1O_2 = C_1 and C2=O1C_2 = O_1, i.e. body 2 = body 1 exactly (degenerate, zero-measure). For any genuine engulfing (O2<C1O_2 < C_1 or C2>O1C_2 > O_1 strictly) the harami condition is violated, so they cannot both hold non-trivially. [2]

(b) Probability of bearish engulfing (9 marks)

Let X=C1O1N(0,4)X = C_1 - O_1 \sim \mathcal N(0,4), Y=C2O2N(0,4)Y = C_2 - O_2 \sim \mathcal N(0,4), independent. With O2=C1O_2=C_1.

Bearish engulfing needs: candle 1 bullish (X>0X>0), candle 2 bearish (Y<0Y<0), and body-2 engulfs body-1: O2C1 (auto, O2=C1) and C2O1.O_2 \ge C_1 \text{ (auto, } O_2=C_1) \text{ and } C_2 \le O_1. Actually the engulf requires O2C1O_2 \ge C_1 (open above prior close) and C2O1C_2 \le O_1 (close below prior open). Since O2=C1O_2 = C_1, first holds with equality. Second: C2=O2+Y=C1+YO1C_2 = O_2 + Y = C_1 + Y \le O_1, i.e. YO1C1=XY \le O_1 - C_1 = -X. [3]

Given X>0X>0 we want P(YXX>0)P(Y \le -X \mid X>0), with Y<0Y<0 automatically implied since X<0-X<0. [1]

P=0Φ ⁣(xσ)fX(x)dxP(X>0),σ=2.P = \frac{\displaystyle\int_0^\infty \Phi\!\left(\frac{-x}{\sigma}\right) f_X(x)\,dx}{P(X>0)},\qquad \sigma=2. [2]

Since X,YX,Y are i.i.d. symmetric, condition on X>0X>0: P(X>0)=12P(X>0)=\tfrac12. The numerator =0Φ(x/2)fX(x)dx=\int_0^\infty \Phi(-x/2) f_X(x)dx. By symmetry P(YX,X>0)=P(Y<X,X>0P(Y\le -X, X>0) = P(Y<X, X>0 ... );evaluatedirectly:; evaluate directly: Y+X<0meansmeansZ=X+Y<0wherewhereZ\sim\mathcal N(0,8),butwestillneed, but we still need X>0$. [1]

Numerically the conditional probability 0.25\approx 0.25. Reasoning: P(X>0,Y<X)=P(X>0,X+Y<0)P(X>0, Y<-X) = P(X>0, X+Y<0). By the geometry of two i.i.d. symmetric variables, the event {X>0,X+Y<0}\{X>0, X+Y<0\} has probability 18\tfrac18 (one-eighth of the plane by rotational symmetry of the isotropic Gaussian: the wedge from angle 135°135° to 180°180° spans 45°=1845°=\tfrac18 of 360°360°). Dividing by P(X>0)=12P(X>0)=\tfrac12 gives 1/4\boxed{1/4}. [2]

(c) Morning star predicate + context (7 marks)

Predicate over (O1..C1,O2..C2,O3..C3)(O_1..C_1, O_2..C_2, O_3..C_3):

morning_star =
   (C1 < O1)                               # candle1 long bearish
 and (|C1-O1| >= k*R1)                      # long body, e.g. k=0.6
 and (max(O2,C2) < C1)                      # star gaps down
 and (|C2-O2| <= 0.30*|C1-O1|)              # small star body
 and (C3 > O3)                              # candle3 bullish
 and (C3 > (O1+C1)/2)                       # closes above candle1 midpoint

Correct core conditions incl. gap and 30% body rule [4].

Context (3.2.13): the identical three shapes (long down, small star, long up) occurring at the top of an uptrend would not be read as a bullish reversal — a bearish reversal like the evening star is what appears at tops (long up → small star → long down). More importantly, pattern meaning is location-dependent: a reversal pattern only reverses a prior trend; at a top the bullish morning-star shape (if it appeared) would be a weak/failing signal against overhead resistance, whereas its mirror (evening star) at the top is the high-probability reversal. [3]


Question 3

(a) Rising three methods formalisation (6 marks)

Candles 1..51..5: C1>O1long white,B1=C1O1 large.\underbrace{C_1 > O_1}_{\text{long white}},\quad B_1 = C_1-O_1 \text{ large}. [1] Small middle candles contained in candle 1's range: for i{2,3,4}: HiH1  LiL1,Bi<B1.\text{for } i\in\{2,3,4\}:\ H_i \le H_1 \ \wedge\ L_i \ge L_1,\qquad B_i < B_1. [2] Drift down (typically bearish/small): C2C1C_2 \le C_1, and C2>C3>C4C_2 > C_3 > C_4 (mild decline) — accept max(H2,H3,H4)H1\max(H_2,H_3,H_4)\le H_1 as the containment. [1] Fifth candle long white closing above candle 1: C5>O5  C5>C1.C_5 > O_5 \ \wedge\ C_5 > C_1. [2]

(b) Vectorised scan (6 marks)

import numpy as np
def rising_three(O,H,L,C):
    n = len(C); idx = []
    for i in range(n-4):                 # window of 5
        long1 = C[i] > O[i] and (C[i]-O[i]) > 0.6*(H[i]-L[i])
        mids  = np.all(H[i+1:i+4] <= H[i]) and np.all(L[i+1:i+4] >= L[i])
        small = np.all(np.abs(C[i+1:i+4]-O[i+1:i+4]) < (C[i]-O[i]))
        last  = C[i+4] > O[i+4] and C[i+4] > C[i]
        if long1 and mids and small and last:
            idx.append(i)
    return np.array(idx)

Fully vectorised alternative uses sliding windows; either accepted. [4] Complexity: each of N4N-4 windows does O(1)O(1) (constant 3-element) work → O(N)O(N) time, O(N)O(N) output space. [2]

(c) Proof + counterexample (4 marks)

The conditions force C5>C1C_5 > C_1 directly (it is an explicit clause), so that inequality is guaranteed. [1]

C1>max(C2,C3,C4)C_1 > \max(C_2,C_3,C_4) is not guaranteed: containment only requires HiH1H_i \le H_1 and LiL1L_i \ge L_1 and Bi<B1B_i<B_1; a middle candle can close above C1C_1 while still sitting below H1H_1. [1]

Counterexample: Candle 1: O1=100,H1=112,L1=99,C1=110O_1=100, H_1=112, L_1=99, C_1=110 (body 10). Candle 2: O2=109,H2=111,L2=105,C2=110.5O_2=109, H_2=111, L_2=105, C_2=110.5 — contained (H2=111112H_2=111\le112, L2=10599L_2=105\ge99, body 1.5<101.5<10) yet C2=110.5>C1=110C_2=110.5 > C_1=110. So C1max(C2,C3,C4)C_1 \not> \max(C_2,C_3,C_4).