Candlestick Patterns
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 with and .
Define:
- Real body:
- Upper wick:
- Lower wick:
- Total range:
(a) Prove the identity directly from the definitions, treating both the bullish () and bearish () cases. (4 marks)
(b) A doji is defined operationally by the rule for a threshold (a dragonfly doji additionally requires ; a gravestone additionally requires ). Using , 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 ) and justify why they capture the pattern's market psychology. (8 marks)
(d) Prove that with your hammer rule, a bullish marubozu () can never be classified as a hammer. (4 marks)
Question 2 — Engulfing & Multi-Candle Patterns: A Probabilistic Backtest (22 marks)
Consider two consecutive candles then .
(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 i.i.d. per bar, with , . Assume opens satisfy (continuous gaps ignored). Derive the probability that a two-candle sequence forms a bearish engulfing given candle 1 is bullish (). Express the answer as an integral / in terms of , 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 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 . 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 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 is not guaranteed, but is — and give a concrete counterexample to the first claim. (4 marks)
Answer keyMark scheme & solutions
Question 1
(a) Proof of (4 marks)
Let , . Then by definition , , (since ). [2]
[1]
This holds regardless of whether (bullish) or (bearish), because the algebra uses only , which is symmetric in . [1]
(b) Classification, (6 marks) — 2 marks each.
- Candle A: , . ; → doji. , . Neither → neutral (long-legged) doji. [2]
- Candle B: , . ; → doji. ✓; ✗. Only upper wick small → gravestone doji. [2]
- Candle C: , . ; → doji. ; ✓. Only lower wick small → dragonfly doji. [2]
(c) Classifier (8 marks)
Precise rules (using body , wicks , range , and ):
- hammer: and and (long lower wick ≥ twice body, tiny/no upper wick, non-doji body). [2]
- shooting star: and and . [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, and . The hammer rule requires . [1] For a real candle (marubozu has a body). [1] So becomes , 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: [2]
Bullish harami: candle 1 bearish (large body), candle 2 bullish and body contained inside candle 1's body: [2]
Mutual exclusivity: engulfing needs and ; harami needs and . Both sets simultaneously force and , i.e. body 2 = body 1 exactly (degenerate, zero-measure). For any genuine engulfing ( or strictly) the harami condition is violated, so they cannot both hold non-trivially. [2]
(b) Probability of bearish engulfing (9 marks)
Let , , independent. With .
Bearish engulfing needs: candle 1 bullish (), candle 2 bearish (), and body-2 engulfs body-1: Actually the engulf requires (open above prior close) and (close below prior open). Since , first holds with equality. Second: , i.e. . [3]
Given we want , with automatically implied since . [1]
[2]
Since are i.i.d. symmetric, condition on : . The numerator . By symmetry ... )Y+X<0Z=X+Y<0Z\sim\mathcal N(0,8)X>0$. [1]
Numerically the conditional probability . Reasoning: . By the geometry of two i.i.d. symmetric variables, the event has probability (one-eighth of the plane by rotational symmetry of the isotropic Gaussian: the wedge from angle to spans of ). Dividing by gives . [2]
(c) Morning star predicate + context (7 marks)
Predicate over :
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] Small middle candles contained in candle 1's range: [2] Drift down (typically bearish/small): , and (mild decline) — accept as the containment. [1] Fifth candle long white closing above candle 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 windows does (constant 3-element) work → time, output space. [2]
(c) Proof + counterexample (4 marks)
The conditions force directly (it is an explicit clause), so that inequality is guaranteed. [1]
is not guaranteed: containment only requires and and ; a middle candle can close above while still sitting below . [1]
Counterexample: Candle 1: (body 10). Candle 2: — contained (, , body ) yet . So .