Strasmore Research
การเรียนรู้ Matt Connorโดย Matt Connor · data as of September 28, 2026 · refreshed weekly

Double Top สองยอด: สถิติจริงหลังหลุดเนคไลน์

Double Top หรือรูปแบบสองยอดคืออะไร นิยามเชิงกลไกที่วัดได้ พร้อมสถิติหลังราคาปิดต่ำกว่าเนคไลน์บนหุ้นใหญ่สหรัฐ และค่าฐานของวันปกติไว้เทียบกันตรงๆ

Double Top หรือที่เทรดเดอร์ไทยเรียกกันว่ารูปแบบสองยอดหรือรูปแบบ M คือราคาที่ขึ้นไปทำจุดสูงสองครั้งในระดับใกล้เคียงกัน มีการย่อคั่นกลางหนึ่งรอบ แล้วปิดต่ำกว่าจุดต่ำสุดของรอบย่อนั้น ตำราเกือบทุกเล่มเรียกมันว่าสัญญาณกลับตัวลง แต่น้อยเล่มมากที่ยอมบอกเป็นตัวเลขว่าหลังยืนยันแล้วเกิดอะไรขึ้น และแทบไม่มีเล่มไหนเอาไปเทียบกับวันธรรมดาที่ไม่มีรูปแบบอะไรเลย หน้านี้ตั้งกฎนับที่วัดซ้ำได้ แล้ววัดจริงกับหุ้นใหญ่สหรัฐสิบตัวที่คนไทยถือผ่านโบรกต่างประเทศกันบ่อย

Double Top คืออะไร เมื่อต้องเขียนเป็นกฎที่นับได้

ปัญหาใหญ่ที่สุดของรูปแบบกราฟคือสายตาคนเราหาเจอเสมอ เปิดกราฟแล้วตั้งใจมองหาสองยอด เราจะเจอได้ในทุกหุ้นและทุกไทม์เฟรม การวัดจึงต้องเริ่มจากนิยามที่ไม่ต้องพึ่งสายตา กฎที่ใช้ทั้งหน้านี้มีสี่ข้อ

  1. ยอดที่สองคือวันที่ราคาสูงสุดของวัน สูงกว่าทุกวันในกรอบ 21 วันทำการรอบตัวมันเอง คือย้อนหลัง 10 วันและนับไปข้างหน้าอีก 10 วัน
  2. ยอดแรกต้องเป็นยอดแบบเดียวกัน ห่างจากยอดที่สอง 15 ถึง 60 วันทำการ และสูงต่างจากกันไม่เกิน 3%
  3. ระหว่างสองยอดต้องมีการย่อลงอย่างน้อย 5% จากยอดที่เตี้ยกว่า จุดต่ำสุดของช่วงย่อนั้นคือเนคไลน์
  4. ถือว่ายืนยันเมื่อมีราคาปิดรายวันต่ำกว่าเนคไลน์ ภายในวันทำการที่ 11 ถึง 30 นับจากยอดที่สอง

ข้อสี่คือข้อที่คนข้ามกันมากที่สุด ยอดที่สองจะรู้ว่าเป็นยอดก็ต่อเมื่อเวลาผ่านไปอีก 10 วันทำการโดยราคาไม่ทำจุดสูงใหม่ ถ้าเรานับการหลุดเนคไลน์ที่เกิดก่อนหน้านั้น เท่ากับเรากำลังใช้ข้อมูลที่คนดูกราฟ ณ วันนั้นยังไม่มีทางรู้ กฎข้อสี่จึงเริ่มนับที่วันทำการที่ 11 และแลกมาด้วยการตัดเคสที่ราคาดิ่งเร็วออกไปทั้งหมด นี่คือราคาที่ต้องจ่ายเพื่อให้ตัวเลขซื่อสัตย์ และเป็นกับดักตัวเดียวกับที่อธิบายไว้ใน look-ahead bias ในการทดสอบย้อนหลัง

เนคไลน์อยู่ตรงไหน และเป้าหมาย measured move วัดอย่างไร

เนคไลน์คือแนวราคาที่ลากผ่านจุดต่ำสุดระหว่างสองยอด งานวัดชุดนี้ใช้ราคาต่ำสุดของวันที่ต่ำที่สุดในช่วงนั้นเป็นตัวเลขเดียวที่ชัดเจน ไม่ลากเป็นเส้นเฉียง เพราะเส้นเฉียงเปิดช่องให้ตีความได้หลายแบบและทำให้ผลนับซ้ำไม่ได้

เป้าหมายแบบ measured move คือธรรมเนียมการวัดที่เก่าแก่ที่สุดของรูปแบบนี้ วัดความสูงจากยอดลงมาถึงเนคไลน์ แล้วเอาความสูงเท่ากันนั้นไปวางต่อลงข้างใต้เนคไลน์ ผลลัพธ์คือระดับราคาหนึ่งระดับ มันเป็นวิธีวัดระยะ ไม่ใช่คำพยากรณ์ และหน้านี้ใช้มันในฐานะเส้นวัดผลอย่างเดียวว่าราคาเคยลงไปแตะหรือไม่

สองเรื่องที่คนมักถามต่อทันที เรื่องแรกคือบางครั้งราคาเปิดกระโดดข้ามเนคไลน์ลงไปเลยโดยไม่มีจังหวะให้เข้าไม้ ใครสนใจว่าช่องว่างแบบนั้นถูกปิดบ่อยแค่ไหน อ่านต่อได้ที่ ช่องว่างราคาถูกปิดบ่อยแค่ไหน เรื่องที่สองคือวอลุ่มตอนหลุดเนคไลน์ ซึ่งจะเทียบข้ามหุ้นได้ก็ต่อเมื่อปรับเป็นสัดส่วนก่อน วิธีปรับอยู่ใน Relative Volume คืออะไร

รูปแบบสองยอดเกิดบ่อยแค่ไหน

ก่อนจะถามว่าได้ผลไหม ต้องรู้ก่อนว่าเจอบ่อยแค่ไหน แผงข้างล่างนับจำนวนครั้งที่กฎทั้งสี่ข้อครบถ้วนในแต่ละปี พร้อมค่ากลางของความลึกจากยอดลงมาถึงเนคไลน์

คำสั่งดึงข้อมูลจำนวนสัญญาณ Double Top ที่ยืนยันแล้ว แยกตามปี
yearsignal_countmedian_depth_pct
201577.65
201678
2017118.04
2018157.9
2019213.36
202078.07
202168.33
2022119.92
202388.02
202497.8
202599.72
202658.68
SQL เบื้องหลังตัวเลขแต่ละตัว
WITH
px AS (
    SELECT ticker, date,
           toFloat64(argMax(high, _ingest_time))  AS h,
           toFloat64(argMax(low, _ingest_time))   AS l,
           toFloat64(argMax(close, _ingest_time)) AS c
    FROM global_markets.stocks_daily_aggs
    WHERE ticker IN ('AAPL','MSFT','NVDA','AMZN','GOOGL','META','JPM','JNJ','KO','XOM')
      AND date >= '2015-01-01' AND date < today()
    GROUP BY ticker, date),
splits AS (
    SELECT ticker, groupArray(execution_date) AS split_dates
    FROM global_markets.stocks_splits
    WHERE execution_date >= '2014-01-01'
    GROUP BY ticker),
pivots AS (
    SELECT ticker, date, h, l, c,
           toUInt8(h = max(h) OVER (PARTITION BY ticker ORDER BY date ROWS BETWEEN 10 PRECEDING AND 10 FOLLOWING)) AS is_peak
    FROM px),
framed AS (
    SELECT ticker, date, h, is_peak,
           groupArray(h)       OVER (PARTITION BY ticker ORDER BY date ROWS BETWEEN 60 PRECEDING AND CURRENT ROW) AS h_back,
           groupArray(l)       OVER (PARTITION BY ticker ORDER BY date ROWS BETWEEN 60 PRECEDING AND CURRENT ROW) AS l_back,
           groupArray(is_peak) OVER (PARTITION BY ticker ORDER BY date ROWS BETWEEN 60 PRECEDING AND CURRENT ROW) AS p_back,
           groupArray(c)       OVER (PARTITION BY ticker ORDER BY date ROWS BETWEEN CURRENT ROW AND 90 FOLLOWING) AS c_fwd,
           groupArray(date)    OVER (PARTITION BY ticker ORDER BY date ROWS BETWEEN CURRENT ROW AND 90 FOLLOWING) AS d_fwd
    FROM pivots),
paired AS (
    SELECT ticker, date AS peak2_date, h AS peak2_high, h_back, l_back, c_fwd, d_fwd,
           arrayFirst(g -> (p_back[61 - g] = 1)
                       AND (abs((h_back[61 - g] / h) - 1) <= 0.03)
                       AND (arrayMin(arraySlice(l_back, 61 - g, g + 1)) <= (0.95 * least(h_back[61 - g], h))),
                      range(15, 61)) AS gap
    FROM framed
    WHERE is_peak = 1 AND length(l_back) = 61 AND length(c_fwd) = 91),
necked AS (
    SELECT ticker, peak2_date, gap,
           greatest(h_back[61 - gap], peak2_high)          AS peak_high,
           arrayMin(arraySlice(l_back, 61 - gap, gap + 1)) AS neckline,
           c_fwd, d_fwd
    FROM (
        SELECT p.ticker AS ticker, p.peak2_date AS peak2_date, p.peak2_high AS peak2_high,
               p.h_back AS h_back, p.l_back AS l_back, p.c_fwd AS c_fwd, p.d_fwd AS d_fwd,
               p.gap AS gap, s.split_dates AS split_dates
        FROM paired AS p
        LEFT JOIN splits AS s ON p.ticker = s.ticker)
    WHERE gap > 0
      AND arrayCount(d -> (d >= (peak2_date - 150)) AND (d <= (peak2_date + 180)), split_dates) = 0),
confirmed AS (
    SELECT ticker,
           d_fwd[k_rel + 11]                                   AS confirm_date,
           round(100 * ((peak_high - neckline) / peak_high), 2) AS depth_pct
    FROM (SELECT *, arrayFirstIndex(x -> x < neckline, arraySlice(c_fwd, 12, 20)) AS k_rel FROM necked)
    WHERE k_rel > 0
    ORDER BY ticker, confirm_date
    LIMIT 1 BY ticker, confirm_date)
SELECT
    toYear(confirm_date)                    AS year,
    count()                                 AS signal_count,
    round(quantileExact(0.5)(depth_pct), 2) AS median_depth_pct
FROM confirmed
GROUP BY year
ORDER BY year
ลองรันด้วยตัวเอง

ตลอดช่วงที่วัด รูปแบบนี้ปรากฏใน 12 ปีปฏิทิน ตั้งแต่ปี 2015 ถึงปี 2026 จำนวนต่อปีไม่คงที่ บางปีเงียบ บางปีถี่ขึ้นชัดเจน คอลัมน์ความลึกคือตัวเลขที่ควรอ่านคู่กันเสมอ มันบอกว่าจากยอดลงมาถึงเนคไลน์ห่างกันกี่เปอร์เซ็นต์ ซึ่งเป็นระยะที่ราคาเดินลงมาเรียบร้อยแล้วก่อนที่สัญญาณจะเกิด คนที่รอเข้าไม้ตอนปิดต่ำกว่าเนคไลน์จึงเข้าหลังจากระยะนั้นผ่านไปแล้วทั้งหมด

หลังยืนยันแล้วราคาไปทางไหน และวันธรรมดาให้เท่าไร

ตัวเลขที่ทุกคนอยากรู้คือผลตอบแทนหลังยืนยัน แต่ตัวเลขนั้นอ่านเดี่ยวๆ ไม่ได้เลย สมมติค่ากลาง 20 วันทำการหลังสัญญาณออกมาติดลบ 1% มันดูเหมือนรูปแบบใช้ได้ จนกว่าจะรู้ว่าวันอื่นของหุ้นชุดเดียวกันในช่วงเวลาเดียวกันให้เท่าไร แผงนี้จึงวางสองคอลัมน์ไว้ข้างกัน คอลัมน์แรกนับเฉพาะวันที่ยืนยันสัญญาณ คอลัมน์ที่สองคือวันอื่นทั้งหมดในหุ้นชุดเดิม

คำสั่งดึงข้อมูลค่ากลางผลตอบแทนหลังยืนยัน เทียบกับค่าฐานของวันที่ไม่มีรูปแบบ
horizon_labelafter_break_pctbaseline_pctsignal_count
5 วันทำการ0.010.4587
10 วันทำการ1.50.8387
20 วันทำการ0.981.6687
60 วันทำการ6.714.4687
SQL เบื้องหลังตัวเลขแต่ละตัว
WITH
px AS (
    SELECT ticker, date,
           toFloat64(argMax(high, _ingest_time))  AS h,
           toFloat64(argMax(low, _ingest_time))   AS l,
           toFloat64(argMax(close, _ingest_time)) AS c
    FROM global_markets.stocks_daily_aggs
    WHERE ticker IN ('AAPL','MSFT','NVDA','AMZN','GOOGL','META','JPM','JNJ','KO','XOM')
      AND date >= '2015-01-01' AND date < today()
    GROUP BY ticker, date),
splits AS (
    SELECT ticker, groupArray(execution_date) AS split_dates
    FROM global_markets.stocks_splits
    WHERE execution_date >= '2014-01-01'
    GROUP BY ticker),
pivots AS (
    SELECT ticker, date, h, l, c,
           toUInt8(h = max(h) OVER (PARTITION BY ticker ORDER BY date ROWS BETWEEN 10 PRECEDING AND 10 FOLLOWING)) AS is_peak
    FROM px),
framed AS (
    SELECT ticker, date, h, is_peak,
           groupArray(h)       OVER (PARTITION BY ticker ORDER BY date ROWS BETWEEN 60 PRECEDING AND CURRENT ROW) AS h_back,
           groupArray(l)       OVER (PARTITION BY ticker ORDER BY date ROWS BETWEEN 60 PRECEDING AND CURRENT ROW) AS l_back,
           groupArray(is_peak) OVER (PARTITION BY ticker ORDER BY date ROWS BETWEEN 60 PRECEDING AND CURRENT ROW) AS p_back,
           groupArray(c)       OVER (PARTITION BY ticker ORDER BY date ROWS BETWEEN CURRENT ROW AND 90 FOLLOWING) AS c_fwd,
           groupArray(date)    OVER (PARTITION BY ticker ORDER BY date ROWS BETWEEN CURRENT ROW AND 90 FOLLOWING) AS d_fwd
    FROM pivots),
paired AS (
    SELECT ticker, date AS peak2_date, h AS peak2_high, h_back, l_back, c_fwd, d_fwd,
           arrayFirst(g -> (p_back[61 - g] = 1)
                       AND (abs((h_back[61 - g] / h) - 1) <= 0.03)
                       AND (arrayMin(arraySlice(l_back, 61 - g, g + 1)) <= (0.95 * least(h_back[61 - g], h))),
                      range(15, 61)) AS gap
    FROM framed
    WHERE is_peak = 1 AND length(l_back) = 61 AND length(c_fwd) = 91),
necked AS (
    SELECT ticker, peak2_date, gap,
           arrayMin(arraySlice(l_back, 61 - gap, gap + 1)) AS neckline,
           c_fwd, d_fwd
    FROM (
        SELECT p.ticker AS ticker, p.peak2_date AS peak2_date,
               p.l_back AS l_back, p.c_fwd AS c_fwd, p.d_fwd AS d_fwd,
               p.gap AS gap, s.split_dates AS split_dates
        FROM paired AS p
        LEFT JOIN splits AS s ON p.ticker = s.ticker)
    WHERE gap > 0
      AND arrayCount(d -> (d >= (peak2_date - 150)) AND (d <= (peak2_date + 180)), split_dates) = 0),
confirmed AS (
    SELECT ticker, d_fwd[k_rel + 11] AS confirm_date
    FROM (SELECT *, arrayFirstIndex(x -> x < neckline, arraySlice(c_fwd, 12, 20)) AS k_rel FROM necked)
    WHERE k_rel > 0
    ORDER BY ticker, confirm_date
    LIMIT 1 BY ticker, confirm_date),
universe AS (
    SELECT f.c_fwd AS c_fwd, s.hit AS is_signal
    FROM framed AS f
    LEFT JOIN (SELECT ticker, confirm_date, toUInt8(1) AS hit FROM confirmed GROUP BY ticker, confirm_date) AS s
           ON f.ticker = s.ticker AND f.date = s.confirm_date
    WHERE length(f.c_fwd) = 91)
SELECT
    concat(toString(hz), ' วันทำการ')                      AS horizon_label,
    round(quantileExactIf(0.5)(ret_pct, is_signal = 1), 2) AS after_break_pct,
    round(quantileExactIf(0.5)(ret_pct, is_signal = 0), 2) AS baseline_pct,
    countIf(is_signal = 1)                                 AS signal_count
FROM (
    SELECT hz, is_signal, 100 * ((c_fwd[hz + 1] / c_fwd[1]) - 1) AS ret_pct
    FROM (SELECT c_fwd, is_signal, arrayJoin([5, 10, 20, 60]) AS hz FROM universe))
GROUP BY hz
HAVING countIf(is_signal = 1) > 0
ORDER BY hz
ลองรันด้วยตัวเอง

ชุดข้อมูลนี้มีวันยืนยันทั้งหมด 87 วัน ที่ระยะ 20 วันทำการ ค่ากลางหลังยืนยันอยู่ที่ 0.98% ขณะที่ค่าฐานของวันอื่นอยู่ที่ 1.66% พอยืดออกไปเป็น 60 วันทำการ ตัวเลขคู่เดียวกันคือ 6.71% กับ 4.46%

ส่วนต่างระหว่างสองคอลัมน์คือสิ่งที่รูปแบบนี้ให้จริง อ่านคอลัมน์แรกลำพังจะได้ข้อสรุปที่ผิดทางเสมอ ไม่ว่าตัวเลขจะออกมาหน้าตาแบบไหน เพราะหุ้นใหญ่สหรัฐตลอดสิบกว่าปีที่ผ่านมามีค่าฐานที่ไม่ใช่ศูนย์อยู่แล้ว อีกเรื่องที่ต้องเตือนตัวเองคือค่ากลางไม่ใช่สิ่งที่จะเกิดกับไม้ถัดไปของคุณ ครึ่งหนึ่งของตัวอย่างอยู่ต่ำกว่าเส้นนั้น อีกครึ่งอยู่สูงกว่า และช่วงการกระจายตัวกว้างกว่าที่ตัวเลขตัวเดียวจะบอกได้

ราคาไปถึงเป้า measured move บ่อยแค่ไหน

คำถามที่ตรงกว่าเรื่องผลตอบแทนเฉลี่ยคือคำถามแบบแข่งกันสองทาง หลังยืนยันแล้ว ภายใน 60 วันทำการถัดไป ราคาลงไปแตะเป้า measured move ก่อน หรือกลับขึ้นไปปิดเหนือเนคไลน์ก่อน แผงนี้แบ่งสัญญาณทุกครั้งออกเป็นสามกอง โดยดูว่าเหตุการณ์ไหนเกิดก่อนกัน

คำสั่งดึงข้อมูลผลที่เกิดก่อนภายใน 60 วันทำการหลังยืนยัน
outcome_labelsignal_countshare_pct
ถึงเป้า measured move ก่อน2124.1
ปิดกลับเหนือเนคไลน์ก่อน6574.7
ไม่เกิดทั้งสองอย่าง11.1
SQL เบื้องหลังตัวเลขแต่ละตัว
WITH
px AS (
    SELECT ticker, date,
           toFloat64(argMax(high, _ingest_time))  AS h,
           toFloat64(argMax(low, _ingest_time))   AS l,
           toFloat64(argMax(close, _ingest_time)) AS c
    FROM global_markets.stocks_daily_aggs
    WHERE ticker IN ('AAPL','MSFT','NVDA','AMZN','GOOGL','META','JPM','JNJ','KO','XOM')
      AND date >= '2015-01-01' AND date < today()
    GROUP BY ticker, date),
splits AS (
    SELECT ticker, groupArray(execution_date) AS split_dates
    FROM global_markets.stocks_splits
    WHERE execution_date >= '2014-01-01'
    GROUP BY ticker),
pivots AS (
    SELECT ticker, date, h, l, c,
           toUInt8(h = max(h) OVER (PARTITION BY ticker ORDER BY date ROWS BETWEEN 10 PRECEDING AND 10 FOLLOWING)) AS is_peak
    FROM px),
framed AS (
    SELECT ticker, date, h, is_peak,
           groupArray(h)       OVER (PARTITION BY ticker ORDER BY date ROWS BETWEEN 60 PRECEDING AND CURRENT ROW) AS h_back,
           groupArray(l)       OVER (PARTITION BY ticker ORDER BY date ROWS BETWEEN 60 PRECEDING AND CURRENT ROW) AS l_back,
           groupArray(is_peak) OVER (PARTITION BY ticker ORDER BY date ROWS BETWEEN 60 PRECEDING AND CURRENT ROW) AS p_back,
           groupArray(c)       OVER (PARTITION BY ticker ORDER BY date ROWS BETWEEN CURRENT ROW AND 90 FOLLOWING) AS c_fwd,
           groupArray(l)       OVER (PARTITION BY ticker ORDER BY date ROWS BETWEEN CURRENT ROW AND 90 FOLLOWING) AS l_fwd,
           groupArray(date)    OVER (PARTITION BY ticker ORDER BY date ROWS BETWEEN CURRENT ROW AND 90 FOLLOWING) AS d_fwd
    FROM pivots),
paired AS (
    SELECT ticker, date AS peak2_date, h AS peak2_high, h_back, l_back, c_fwd, l_fwd, d_fwd,
           arrayFirst(g -> (p_back[61 - g] = 1)
                       AND (abs((h_back[61 - g] / h) - 1) <= 0.03)
                       AND (arrayMin(arraySlice(l_back, 61 - g, g + 1)) <= (0.95 * least(h_back[61 - g], h))),
                      range(15, 61)) AS gap
    FROM framed
    WHERE is_peak = 1 AND length(l_back) = 61 AND length(c_fwd) = 91),
necked AS (
    SELECT ticker, peak2_date, gap,
           greatest(h_back[61 - gap], peak2_high)          AS peak_high,
           arrayMin(arraySlice(l_back, 61 - gap, gap + 1)) AS neckline,
           c_fwd, l_fwd, d_fwd
    FROM (
        SELECT p.ticker AS ticker, p.peak2_date AS peak2_date, p.peak2_high AS peak2_high,
               p.h_back AS h_back, p.l_back AS l_back, p.c_fwd AS c_fwd, p.l_fwd AS l_fwd,
               p.d_fwd AS d_fwd, p.gap AS gap, s.split_dates AS split_dates
        FROM paired AS p
        LEFT JOIN splits AS s ON p.ticker = s.ticker)
    WHERE gap > 0
      AND arrayCount(d -> (d >= (peak2_date - 150)) AND (d <= (peak2_date + 180)), split_dates) = 0),
confirmed AS (
    SELECT ticker,
           d_fwd[k_rel + 11] AS confirm_date,
           arrayFirstIndex(x -> x <= ((2 * neckline) - peak_high), arraySlice(l_fwd, k_rel + 12, 60)) AS target_idx,
           arrayFirstIndex(x -> x > neckline, arraySlice(c_fwd, k_rel + 12, 60))                      AS recover_idx
    FROM (SELECT *, arrayFirstIndex(x -> x < neckline, arraySlice(c_fwd, 12, 20)) AS k_rel FROM necked)
    WHERE k_rel > 0
    ORDER BY ticker, confirm_date
    LIMIT 1 BY ticker, confirm_date)
SELECT
    tup.1                                   AS outcome_label,
    tup.2                                   AS signal_count,
    round(100 * (tup.2 / total_signals), 1) AS share_pct
FROM (
    SELECT count() AS total_signals,
           countIf((target_idx > 0) AND ((recover_idx = 0) OR (target_idx <= recover_idx))) AS n_target,
           countIf((NOT ((target_idx > 0) AND ((recover_idx = 0) OR (target_idx <= recover_idx)))) AND (recover_idx > 0)) AS n_recover,
           countIf((target_idx = 0) AND (recover_idx = 0)) AS n_stall
    FROM confirmed)
ARRAY JOIN [('ถึงเป้า measured move ก่อน', n_target), ('ปิดกลับเหนือเนคไลน์ก่อน', n_recover), ('ไม่เกิดทั้งสองอย่าง', n_stall)] AS tup
ลองรันด้วยตัวเอง

กอง ถึงเป้า measured move ก่อน คิดเป็น 24.1% ของสัญญาณทั้งหมด กอง ปิดกลับเหนือเนคไลน์ก่อน อยู่ที่ 74.7% และที่เหลืออีก 1.1% จบ 60 วันทำการโดยราคาไม่ลงไปแตะเป้าและไม่ปิดกลับขึ้นเหนือเนคไลน์ภายในกรอบเวลาที่วัด

กองที่สามคือกองที่คนวางแผนล่วงหน้ามักลืมนึกถึง มันคือกรณีที่ราคาค้างอยู่ใต้เนคไลน์แบบไม่ไปไหน ซึ่งกินทั้งเวลาและกินทั้งความอดทนของคนถือสถานะ การตั้งกรอบเวลาไว้ล่วงหน้าว่าจะให้สัญญาณหนึ่งครั้งมีอายุกี่วันทำการ จึงเป็นส่วนหนึ่งของกฎ ไม่ใช่เรื่องที่ค่อยไปตัดสินใจเอาตอนอยู่ในสถานะ

ตัวเลขในกฎขยับได้ และข้อสรุปก็ขยับตาม

กฎสี่ข้อข้างบนมีเกณฑ์ที่เราตั้งขึ้นเองอยู่หลายตัว 3% ของความห่างระหว่างยอด 5% ของความลึก 15 ถึง 60 วันทำการของระยะห่าง ไม่มีตัวไหนศักดิ์สิทธิ์ ถ้าขยายเกณฑ์ความห่างของยอดให้กว้างขึ้น จำนวนสัญญาณจะเพิ่มขึ้นตามนิยาม เพราะชุดใหม่ครอบชุดเดิมไว้ทั้งหมด และค่าสถิติที่ได้ก็จะเป็นคนละค่ากับที่แสดงไว้ในหน้านี้

นี่คือเหตุผลที่ตัวเลขความแม่นยำของรูปแบบกราฟที่เห็นตามอินเทอร์เน็ตไม่เคยตรงกันสักที่ ใครก็ตามที่โชว์ hit rate ของ Double Top โดยไม่บอกเกณฑ์ที่ใช้นับ ไม่บอกชุดหุ้น ไม่บอกช่วงเวลา และไม่วางค่าฐานไว้ข้างกัน กำลังโชว์ตัวเลขที่เลือกได้ตามใจ วิธีอ่านงานวัดแบบนี้จึงเริ่มจากการอ่านกฎก่อนอ่านผลเสมอ

ข้อสังเกตเรื่องข้อมูลและขอบเขตการวัด

หุ้นที่ใช้วัดคือหุ้นขนาดใหญ่สหรัฐสิบตัว ซึ่งมีสภาพคล่องสูงและราคาไม่กระโดดจากการขาดคนซื้อขาย ผลที่ได้จึงอ่านได้เฉพาะกับหุ้นลักษณะนี้ หุ้นเล็กที่สเปรดกว้างมีพฤติกรรมคนละแบบ และรูปแบบเดียวกันบนกราฟรายนาทีหรือรายสัปดาห์ก็นับเป็นคนละงานวัด

ราคาที่ใช้เป็นราคาเปิดสูงต่ำปิดรายวัน หากมีแถวซ้ำของวันเดียวกัน จะเลือกแถวที่บันทึกล่าสุดเสมอ เพื่อให้การคำนวณซ้ำได้ค่าเดิม

ช่วงที่มีการแตกพาร์ถูกตัดออกทั้งหมด โดยไม่นับสัญญาณของหุ้นตัวใดที่มีวันแตกพาร์อยู่ภายใน 150 วันก่อน หรือ 180 วันหลังยอดที่สอง การแตกพาร์ทำให้ระดับราคาในบัญชีเปลี่ยนทันที ซึ่งถ้าไม่ตัดออกจะถูกนับเป็นการหลุดเนคไลน์แบบผิดๆ

การวัดเป็นแบบ point in time ข้อมูลที่ใช้ตัดสินว่าเกิดรูปแบบหรือไม่ มีอยู่แล้วในวันที่ยืนยัน ต้นทุนของเงื่อนไขนี้คือสัญญาณที่ราคาหลุดเนคไลน์ภายใน 10 วันทำการแรกหลังยอดที่สองจะไม่ถูกนับเลย ตัวเลขทั้งหน้าจึงอธิบายเฉพาะรูปแบบที่ค่อยเป็นค่อยไปพอที่คนดูกราฟจะเห็นทัน

ทุกสัญญาณต้องมีข้อมูลข้างหน้าอย่างน้อย 60 วันทำการจึงจะถูกนับ รูปแบบที่เพิ่งเกิดในไม่กี่เดือนล่าสุดจึงยังไม่ปรากฏในตาราง และตัวเลขทั้งหมดในหน้านี้คำนวณใหม่ทุกครั้งที่หน้าถูกอัปเดต

FAQ

Double Top คืออะไร

Double Top คือรูปแบบราคาที่ขึ้นไปทำจุดสูงสองครั้งในระดับใกล้เคียงกัน โดยมีการย่อคั่นกลางหนึ่งรอบ คนไทยเรียกกันว่ารูปแบบสองยอดหรือรูปแบบ M นิยามที่วัดได้ต้องระบุให้ครบว่ายอดสองยอดต่างกันได้กี่เปอร์เซ็นต์ ห่างกันกี่วัน และย่อกลางต้องลึกเท่าไร

เนคไลน์ของ Double Top อยู่ตรงไหน

เนคไลน์คือแนวราคาที่จุดต่ำสุดของการย่อระหว่างสองยอด ในหน้านี้ใช้ราคาต่ำสุดของวันที่ต่ำที่สุดในช่วงนั้นเป็นเนคไลน์ เพื่อให้เป็นตัวเลขเดียวที่ทุกคนนับแล้วได้ค่าเท่ากัน

รูปแบบสองยอดถือว่ายืนยันเมื่อไร

เมื่อมีราคาปิดรายวันต่ำกว่าเนคไลน์ ราคาที่แกว่งลงไปใต้เนคไลน์ระหว่างวันแล้วปิดกลับขึ้นมาไม่นับ และในงานวัดชุดนี้ยังกำหนดเพิ่มว่าการปิดนั้นต้องเกิดในวันทำการที่ 11 ถึง 30 นับจากยอดที่สอง เพื่อไม่ให้ใช้ข้อมูลที่ยังไม่มีทางรู้ในวันนั้น

Double Top แม่นกี่เปอร์เซ็นต์

ไม่มีตัวเลขเดียวที่ตอบได้ ความแม่นขึ้นกับเกณฑ์ที่ใช้นิยามรูปแบบ ชุดหุ้น ช่วงเวลา และนิยามของคำว่าสำเร็จ ตัวเลขที่มีความหมายคือส่วนต่างระหว่างผลหลังยืนยันกับค่าฐานของวันธรรมดาในหุ้นชุดเดียวกัน ซึ่งเป็นสิ่งที่แผงข้างบนวางไว้ให้เทียบตรงๆ

ต่างจาก Double Bottom อย่างไร

Double Bottom คือภาพกลับด้านของ Double Top มีจุดต่ำสองจุดในระดับใกล้เคียงกัน คั่นด้วยการเด้งหนึ่งรอบ และยืนยันเมื่อปิดสูงกว่าแนวของจุดสูงตรงกลาง กฎการวัดก็ต้องกลับด้านตามกันทั้งหมด ผลของรูปแบบหนึ่งใช้อนุมานอีกรูปแบบหนึ่งไม่ได้


ทุกแผงข้างบนมีโค้ด SQL เต็มซ่อนอยู่ใต้ตาราง กดเปิดดูได้ว่าตัวเลขแต่ละตัวนับมาอย่างไร และถ้าอยากเปลี่ยนเกณฑ์เป็นของตัวเองแล้วนับใหม่ ถามเป็นภาษาไทยได้เลยบน Strasmore terminal

#chart patterns#double top#technical analysis#base rates#risk management