SiamCafe.net Blog
Technology

แพทเทิร์น Head and Shoulders — วิเคราะห์ Chart Pattern กลับตัวที่น่าเชื่อถือที่สุด

แพทเทิร์น head and shoulders | SiamCafe Blog
2025-11-19· อ. บอม — SiamCafe.net· 1,092 คำ

Head and Shoulders Pattern คืออะไร

Head and Shoulders เป็น chart pattern ที่บ่งบอกถึงการกลับตัวของแนวโน้ม (trend reversal) จัดเป็นหนึ่งใน pattern ที่น่าเชื่อถือมากที่สุดใน Technical Analysis ประกอบด้วย 3 ยอดคือ Left Shoulder ที่เป็นยอดแรก Head ที่เป็นยอดสูงสุดตรงกลาง และ Right Shoulder ที่เป็นยอดสุดท้ายอยู่ระดับเดียวกับ Left Shoulder

Neckline คือเส้นที่ลากผ่านจุดต่ำสุดระหว่าง Left Shoulder กับ Head และจุดต่ำสุดระหว่าง Head กับ Right Shoulder เมื่อราคาทะลุ neckline ลงมาถือว่า pattern สมบูรณ์และเป็นสัญญาณขาย

Head and Shoulders แบ่งเป็น 2 ประเภทคือ Head and Shoulders Top ที่เกิดหลังขาขึ้นและบ่งบอกว่าราคาจะกลับตัวลง และ Inverse Head and Shoulders (Head and Shoulders Bottom) ที่เกิดหลังขาลงและบ่งบอกว่าราคาจะกลับตัวขึ้น

ปริมาณการซื้อขาย (Volume) มีบทบาทสำคัญในการยืนยัน pattern โดยทั่วไป volume จะสูงที่ Left Shoulder ลดลงที่ Head และลดลงอีกที่ Right Shoulder เมื่อราคาทะลุ neckline volume ควรเพิ่มขึ้นอย่างมากเพื่อยืนยันการ breakout

วิธีระบุ Head and Shoulders บน Chart

ขั้นตอนการระบุ Head and Shoulders Pattern อย่างเป็นระบบ

# ขั้นตอนระบุ Head and Shoulders Top Pattern
#
# 1. ระบุ Uptrend ก่อนหน้า
#    - ราคาต้องอยู่ในขาขึ้นก่อนจะเกิด pattern
#    - ถ้าไม่มี uptrend ก่อนหน้า ไม่ใช่ H&S
#
# 2. ระบุ Left Shoulder
#    - ราคาขึ้นไปถึงจุดสูงสุดแล้วย่อตัวลง
#    - Volume สูง
#
# 3. ระบุ Head
#    - ราคาขึ้นไปสูงกว่า Left Shoulder
#    - แล้วย่อตัวลงมาใกล้ระดับเดียวกับจุดต่ำสุดของ Left Shoulder
#    - Volume อาจเท่าหรือน้อยกว่า Left Shoulder
#
# 4. ระบุ Right Shoulder
#    - ราคาขึ้นไปอีกครั้งแต่ไม่ถึงระดับ Head
#    - ควรอยู่ระดับใกล้เคียงกับ Left Shoulder
#    - Volume ลดลงอย่างชัดเจน (สำคัญมาก)
#
# 5. วาด Neckline
#    - ลากเส้นจากจุดต่ำสุดระหว่าง LS-Head ถึง Head-RS
#    - Neckline อาจเอียงขึ้นหรือลงเล็กน้อย
#    - Neckline แนวนอนถือว่าน่าเชื่อถือกว่า
#
# 6. รอ Breakout
#    - ราคาทะลุ neckline ลงมาพร้อม volume สูง
#    - อาจมี pullback มาทดสอบ neckline แล้วลงต่อ
#
# 7. คำนวณ Target Price
#    - Distance = Head Price - Neckline Price
#    - Target = Neckline Price - Distance
#    - เรียกว่า "Measured Move"
#
# ตัวอย่าง:
#   Left Shoulder:  $150
#   Head:           $165
#   Right Shoulder: $152
#   Neckline:       $140
#   Distance:       $165 - $140 = $25
#   Target:         $140 - $25 = $115

# เกณฑ์ประเมินคุณภาพ H&S Pattern:
# ✓ Symmetry: RS ใกล้เคียง LS (ดี)
# ✓ Volume: ลดลงจาก LS → Head → RS
# ✓ Neckline: แนวนอนหรือเอียงลงเล็กน้อย
# ✓ Breakout Volume: สูงกว่าค่าเฉลี่ย
# ✓ Prior Trend: มี uptrend ชัดเจน
# ✗ RS สูงกว่า Head: ไม่ใช่ H&S
# ✗ Volume เพิ่มขึ้นที่ RS: สัญญาณอ่อน

Inverse Head and Shoulders สำหรับขาขึ้น

Inverse Head and Shoulders เป็น bullish reversal pattern ที่เกิดหลังขาลง

# Inverse Head and Shoulders (H&S Bottom)
#
# โครงสร้าง:
#        Neckline
#   ___/          \___
#  /  \    /  \    /  \
# /    \  / Head\  /    \
#       \/       \/
#    Left         Right
#   Shoulder     Shoulder
#
# ขั้นตอน:
# 1. ระบุ Downtrend ก่อนหน้า
# 2. Left Shoulder: ราคาลงไปถึงจุดต่ำสุดแล้วเด้งกลับขึ้น
# 3. Head: ราคาลงไปต่ำกว่า Left Shoulder แล้วเด้งกลับ
# 4. Right Shoulder: ราคาลงอีกครั้งแต่ไม่ต่ำเท่า Head
# 5. Neckline: ลากจากจุดสูงสุดระหว่าง LS-Head ถึง Head-RS
# 6. Breakout: ราคาทะลุ neckline ขึ้นไปพร้อม volume สูง
#
# Volume Profile:
# - Left Shoulder: volume สูง
# - Head: volume ลดลง
# - Right Shoulder: volume เริ่มเพิ่มขึ้น (ต่างจาก H&S Top)
# - Breakout: volume สูงมาก (สำคัญมากสำหรับ bullish breakout)
#
# ตัวอย่าง:
#   Left Shoulder:  $80
#   Head:           $65
#   Right Shoulder: $78
#   Neckline:       $95
#   Distance:       $95 - $65 = $30
#   Target:         $95 + $30 = $125

# Complex Head and Shoulders
# บางครั้งอาจเจอ pattern ที่ซับซ้อนกว่า:
# - Double Left Shoulder
# - Double Right Shoulder
# - Tilted Neckline (เอียงขึ้นหรือลง)
# - Extended Right Shoulder
# ยังคงใช้หลักการเดียวกันแต่ต้องยืดหยุ่นในการวิเคราะห์

ตรวจจับ Pattern อัตโนมัติด้วย Python

สร้างระบบตรวจจับ Head and Shoulders Pattern อัตโนมัติ

#!/usr/bin/env python3
# hs_detector.py — Head and Shoulders Pattern Detector
import pandas as pd
import numpy as np
import yfinance as yf

class HSDetector:
    def __init__(self, data, lookback=5, tolerance=0.03):
        self.data = data.copy()
        self.lookback = lookback
        self.tolerance = tolerance  # 3% tolerance สำหรับ symmetry

    def find_peaks(self):
        """หาจุดยอด (peaks) และจุดต่ำสุด (troughs)"""
        high = self.data["High"].values
        low = self.data["Low"].values
        n = self.lookback
        peaks = []
        troughs = []

        for i in range(n, len(high) - n):
            if high[i] == max(high[i-n:i+n+1]):
                peaks.append((i, high[i]))
            if low[i] == min(low[i-n:i+n+1]):
                troughs.append((i, low[i]))

        return peaks, troughs

    def detect_hs_top(self):
        """ตรวจจับ Head and Shoulders Top"""
        peaks, troughs = self.find_peaks()
        patterns = []

        for i in range(len(peaks) - 2):
            ls_idx, ls_price = peaks[i]
            head_idx, head_price = peaks[i + 1]
            rs_idx, rs_price = peaks[i + 2]

            # เงื่อนไข: Head สูงกว่า LS และ RS
            if head_price <= ls_price or head_price <= rs_price:
                continue

            # เงื่อนไข: LS และ RS ใกล้เคียงกัน
            symmetry = abs(ls_price - rs_price) / ls_price
            if symmetry > self.tolerance:
                continue

            # หา Neckline
            trough1 = None
            trough2 = None
            for t_idx, t_price in troughs:
                if ls_idx < t_idx < head_idx:
                    trough1 = (t_idx, t_price)
                if head_idx < t_idx < rs_idx:
                    trough2 = (t_idx, t_price)

            if trough1 is None or trough2 is None:
                continue

            neckline = (trough1[1] + trough2[1]) / 2
            distance = head_price - neckline
            target = neckline - distance

            # ตรวจสอบ breakout
            broken = False
            breakout_idx = None
            for j in range(rs_idx + 1, min(rs_idx + 30, len(self.data))):
                if self.data["Close"].iloc[j] < neckline:
                    broken = True
                    breakout_idx = j
                    break

            patterns.append({
                "type": "H&S Top",
                "left_shoulder": (self.data.index[ls_idx], ls_price),
                "head": (self.data.index[head_idx], head_price),
                "right_shoulder": (self.data.index[rs_idx], rs_price),
                "neckline": round(neckline, 2),
                "target": round(target, 2),
                "distance": round(distance, 2),
                "symmetry": round(symmetry * 100, 1),
                "broken": broken,
                "breakout_date": self.data.index[breakout_idx] if broken else None,
            })

        return patterns

    def detect_inverse_hs(self):
        """ตรวจจับ Inverse Head and Shoulders"""
        peaks, troughs = self.find_peaks()
        patterns = []

        for i in range(len(troughs) - 2):
            ls_idx, ls_price = troughs[i]
            head_idx, head_price = troughs[i + 1]
            rs_idx, rs_price = troughs[i + 2]

            if head_price >= ls_price or head_price >= rs_price:
                continue

            symmetry = abs(ls_price - rs_price) / ls_price
            if symmetry > self.tolerance:
                continue

            peak1 = None
            peak2 = None
            for p_idx, p_price in peaks:
                if ls_idx < p_idx < head_idx:
                    peak1 = (p_idx, p_price)
                if head_idx < p_idx < rs_idx:
                    peak2 = (p_idx, p_price)

            if peak1 is None or peak2 is None:
                continue

            neckline = (peak1[1] + peak2[1]) / 2
            distance = neckline - head_price
            target = neckline + distance

            broken = False
            breakout_idx = None
            for j in range(rs_idx + 1, min(rs_idx + 30, len(self.data))):
                if self.data["Close"].iloc[j] > neckline:
                    broken = True
                    breakout_idx = j
                    break

            patterns.append({
                "type": "Inverse H&S",
                "left_shoulder": (self.data.index[ls_idx], ls_price),
                "head": (self.data.index[head_idx], head_price),
                "right_shoulder": (self.data.index[rs_idx], rs_price),
                "neckline": round(neckline, 2),
                "target": round(target, 2),
                "distance": round(distance, 2),
                "symmetry": round(symmetry * 100, 1),
                "broken": broken,
                "breakout_date": self.data.index[breakout_idx] if broken else None,
            })

        return patterns

if __name__ == "__main__":
    data = yf.download("AAPL", period="1y")
    detector = HSDetector(data, lookback=5, tolerance=0.05)

    hs_patterns = detector.detect_hs_top()
    ihs_patterns = detector.detect_inverse_hs()

    print(f"=== Head & Shoulders Patterns: AAPL ===\n")
    for p in hs_patterns:
        status = "CONFIRMED" if p["broken"] else "FORMING"
        print(f"[{p['type']}] {status}")
        print(f"  LS: {p['left_shoulder'][0].strftime('%Y-%m-%d')} @ {p['left_shoulder'][1]:.2f}")
        print(f"  Head: {p['head'][0].strftime('%Y-%m-%d')} @ {p['head'][1]:.2f}")
        print(f"  RS: {p['right_shoulder'][0].strftime('%Y-%m-%d')} @ {p['right_shoulder'][1]:.2f}")
        print(f"  Neckline: {p['neckline']} | Target: {p['target']}")
        print(f"  Symmetry: {p['symmetry']}%\n")

    for p in ihs_patterns:
        status = "CONFIRMED" if p["broken"] else "FORMING"
        print(f"[{p['type']}] {status}")
        print(f"  LS: {p['left_shoulder'][0].strftime('%Y-%m-%d')} @ {p['left_shoulder'][1]:.2f}")
        print(f"  Head: {p['head'][0].strftime('%Y-%m-%d')} @ {p['head'][1]:.2f}")
        print(f"  RS: {p['right_shoulder'][0].strftime('%Y-%m-%d')} @ {p['right_shoulder'][1]:.2f}")
        print(f"  Neckline: {p['neckline']} | Target: {p['target']}\n")

กลยุทธ์การเทรดด้วย Head and Shoulders

ขั้นตอนการเทรดด้วย H&S Pattern อย่างมีระบบ

# กลยุทธ์การเทรด Head and Shoulders
#
# === Entry Strategies ===
#
# 1. Breakout Entry (ปลอดภัยที่สุด)
#    - รอราคาทะลุ neckline แล้วเข้า sell/buy ทันที
#    - ข้อดี: ยืนยันแล้วว่า pattern สมบูรณ์
#    - ข้อเสีย: อาจพลาดส่วนหนึ่งของ move
#
# 2. Pullback Entry (ดีที่สุดสำหรับ Risk:Reward)
#    - รอราคา pullback กลับมาทดสอบ neckline
#    - เข้าเมื่อราคาเด้งจาก neckline
#    - ข้อดี: entry ดีกว่า, stop loss แคบกว่า
#    - ข้อเสีย: อาจไม่มี pullback
#
# 3. Aggressive Entry (ความเสี่ยงสูง)
#    - เข้าเมื่อ right shoulder กำลังก่อตัว
#    - ข้อดี: entry เร็วมาก, RR สูง
#    - ข้อเสีย: pattern อาจไม่สมบูรณ์

# === Stop Loss Placement ===
# H&S Top:
#   - Above right shoulder (ปลอดภัย)
#   - Above neckline + ATR (แน่น)
#
# Inverse H&S:
#   - Below right shoulder (ปลอดภัย)
#   - Below neckline - ATR (แน่น)

# === Take Profit ===
# Target 1: Measured Move (distance from head to neckline)
# Target 2: 1.618x Measured Move (Fibonacci extension)
# Target 3: Next support/resistance level

# Position Sizing
# Risk per trade: 1-2% of account
# Position size = (Account * Risk%) / (Entry - Stop Loss)
#
# ตัวอย่าง H&S Top:
#   Account: $100,000
#   Risk: 1% = $1,000
#   Entry (short): $140 (neckline break)
#   Stop Loss: $153 (above right shoulder)
#   Risk per share: $153 - $140 = $13
#   Position size: $1,000 / $13 = 76 shares
#   Target: $115 (measured move)
#   Reward: ($140 - $115) * 76 = $1,900
#   Risk:Reward = 1:1.9

Backtesting และวัดผล Pattern

ทดสอบประสิทธิภาพของ H&S Pattern ด้วยข้อมูลจริง

#!/usr/bin/env python3
# hs_backtest.py — Backtest Head and Shoulders Strategy
import yfinance as yf
import numpy as np

def backtest_hs(symbol="SPY", period="5y"):
    data = yf.download(symbol, period=period)
    detector = HSDetector(data, lookback=7, tolerance=0.05)

    # ตรวจจับ patterns
    hs_top = detector.detect_hs_top()
    ihs = detector.detect_inverse_hs()

    results = []

    # Backtest H&S Top (Short)
    for p in hs_top:
        if not p["broken"] or p["breakout_date"] is None:
            continue

        entry_price = p["neckline"]
        stop_loss = p["right_shoulder"][1] * 1.01  # 1% above RS
        target = p["target"]

        # ดูผลลัพธ์ 30 วันหลัง breakout
        bo_idx = data.index.get_loc(p["breakout_date"])
        hit_target = False
        hit_stop = False

        for j in range(bo_idx + 1, min(bo_idx + 60, len(data))):
            if data["High"].iloc[j] >= stop_loss:
                hit_stop = True
                results.append({
                    "type": "H&S Top", "result": "LOSS",
                    "pnl_pct": -abs(stop_loss - entry_price) / entry_price * 100
                })
                break
            if data["Low"].iloc[j] <= target:
                hit_target = True
                results.append({
                    "type": "H&S Top", "result": "WIN",
                    "pnl_pct": abs(entry_price - target) / entry_price * 100
                })
                break

        if not hit_target and not hit_stop:
            final_price = data["Close"].iloc[min(bo_idx + 60, len(data) - 1)]
            pnl = (entry_price - final_price) / entry_price * 100
            results.append({
                "type": "H&S Top",
                "result": "WIN" if pnl > 0 else "LOSS",
                "pnl_pct": pnl
            })

    # สรุปผล
    if results:
        wins = [r for r in results if r["result"] == "WIN"]
        losses = [r for r in results if r["result"] == "LOSS"]
        total_pnl = sum(r["pnl_pct"] for r in results)

        print(f"\n=== H&S Backtest: {symbol} ({period}) ===")
        print(f"Total Patterns: {len(results)}")
        print(f"Wins: {len(wins)} | Losses: {len(losses)}")
        print(f"Win Rate: {len(wins)/len(results)*100:.1f}%")
        print(f"Avg Win: {np.mean([r['pnl_pct'] for r in wins]):.2f}%" if wins else "")
        print(f"Avg Loss: {np.mean([r['pnl_pct'] for r in losses]):.2f}%" if losses else "")
        print(f"Total P&L: {total_pnl:.2f}%")
    else:
        print("No confirmed H&S patterns found")

    return results

# backtest_hs("SPY", "5y")

FAQ คำถามที่พบบ่อย

Q: Head and Shoulders มี success rate เท่าไหร่?

A: จากการศึกษาของ Thomas Bulkowski ใน Encyclopedia of Chart Patterns พบว่า H&S Top มี success rate ประมาณ 83% สำหรับการกลับตัวลง และ Inverse H&S มี success rate ประมาณ 89% สำหรับการกลับตัวขึ้น ตัวเลขนี้วัดจากราคาที่ทะลุ neckline แล้วเคลื่อนที่ไปในทิศทางที่คาดไว้

Q: Neckline ต้องเป็นเส้นตรงแนวนอนเท่านั้นไหม?

A: ไม่จำเป็น Neckline อาจเอียงขึ้นหรือลงได้ สำหรับ H&S Top neckline ที่เอียงลงมักให้ผลลัพธ์ดีกว่าเพราะแสดงว่าแนวโน้มอ่อนตัวแล้ว ส่วน neckline ที่เอียงขึ้นมากอาจลดความน่าเชื่อถือของ pattern ลง สิ่งสำคัญคือ neckline ต้องเชื่อมจุดต่ำสุด 2 จุดได้ชัดเจน

Q: ใช้ timeframe ไหนสำหรับ Head and Shoulders?

A: H&S ใน timeframe สูงเช่น Daily หรือ Weekly มีความน่าเชื่อถือมากที่สุดเพราะมี volume สนับสนุนมากกว่า timeframe ต่ำเช่น 15M หรือ 1H สามารถใช้ได้แต่มี false signal มากกว่า สำหรับ swing trading แนะนำ Daily chart สำหรับ position trading ใช้ Weekly chart

Q: ถ้า Right Shoulder สูงกว่า Left Shoulder ยังเป็น H&S ไหม?

A: ยังเป็นได้แต่ pattern จะอ่อนกว่า Right Shoulder ที่สูงกว่า Left Shoulder แสดงว่าแรงซื้อยังไม่หมด pattern อาจล้มเหลว ในทางตรงกันข้าม Right Shoulder ที่ต่ำกว่า Left Shoulder แสดงว่าแรงซื้ออ่อนลงชัดเจนและ pattern มีโอกาสสำเร็จมากกว่า

📖 บทความที่เกี่ยวข้อง

head and shoulders cool mentholอ่านบทความ → head and shoulders clinical strength 2 in 1อ่านบทความ → head shoulders knees and toes songอ่านบทความ → เพลง head shoulders knees and toesอ่านบทความ → head and shoulders ประวัติอ่านบทความ →

📚 ดูบทความทั้งหมด →