Mô hình cốc tay cầm: breakout có thật sự đi tiếp?
Mô hình cốc tay cầm có thực sự đi tiếp sau breakout? Luật vẽ được viết thành ngưỡng cụ thể, đo trên cổ phiếu Mỹ từ 2015, tách kết quả theo khối lượng ngày breakout.
Mô hình cốc tay cầm là mẫu hình giá được dạy nhiều nhất trong tài liệu kiểu CANSLIM, và câu hỏi đáng tiền duy nhất là sau khi giá vượt vành cốc thì nó có đi tiếp hay không. Trên 3632 tín hiệu ở cổ phiếu Mỹ kể từ 2015, dựng bằng một bộ luật cố định ghi rõ ngay bên dưới, 32.7% số breakout chạm mức +10% trước khi giá thủng đáy tay cầm trong 60 ngày tiếp theo. Toàn bộ ngưỡng đều công khai, nên bạn có thể sửa luật rồi đo lại theo cách của mình.
Viết mô hình cốc tay cầm thành luật đo được
Một mẫu hình chỉ kiểm chứng được khi nó có ngưỡng bằng số. Tài liệu phổ thông dạy cốc tay cầm bằng hình vẽ, mà hình vẽ thì mỗi người nhìn một kiểu, nên tỷ lệ thành công ai nói cũng khác. Đây là bộ luật đứng sau mọi con số trong trang này, đo trên giá ngày của cổ phiếu niêm yết tại Mỹ.
- Xu hướng tăng trước nền giá: giá đóng cửa ở phiên mở đầu nền cao hơn giá đóng cửa của 120 phiên trước đó ít nhất 10%.
- Thân cốc: cửa sổ 110 phiên, kết thúc 11 phiên trước ngày breakout. Vành cốc là mức giá cao nhất trong cửa sổ đó, đáy cốc là mức thấp nhất.
- Độ sâu cốc nằm trong khoảng 12% đến 50%, tính từ vành xuống đáy.
- Tay cầm: 10 phiên liền trước ngày breakout. Toàn bộ giá cao nhất của 10 phiên này nằm dưới vành, đáy tay cầm cao hơn đáy cốc, và mức lùi của tay cầm so với vành không quá một nửa độ sâu cốc.
- Ngày breakout: giá đóng cửa vượt hẳn vành cốc.
- Điều kiện thanh khoản, tính ngay tại thời điểm đó: giá trị giao dịch bình quân 50 phiên liền trước từ 100 triệu USD trở lên, giá đóng cửa từ 10 USD.
- Cách chấm điểm: theo dõi 60 ngày lịch sau breakout, tức khoảng 40 phiên. Tín hiệu được tính là đạt khi giá cao nhất chạm mục tiêu trước ngày giá thấp nhất chạm đáy tay cầm. Chạm cả hai trong cùng một phiên được tính là hỏng.
Vì tay cầm bắt buộc nằm dưới vành, một phiên chỉ được ghi nhận là breakout khi 10 phiên trước đó chưa có phiên nào đóng cửa trên vành. Các phiên tăng tiếp sau đó không bị đếm thành tín hiệu mới. Vành cốc theo luật này thường rơi vào vùng đỉnh 52 tuần của cổ phiếu, dù điều kiện ở đây chỉ nhìn lại 110 phiên, tức khoảng nửa năm.
Tỷ lệ đi tiếp sau breakout là bao nhiêu
Một mẫu hình không có tỷ lệ thành công duy nhất. Nó có một đường cong: mục tiêu càng xa thì tỷ lệ chạm tới càng thấp, trong khi mức dừng vẫn giữ nguyên là đáy tay cầm. Bảng dưới đo cùng một tập tín hiệu ở năm mốc mục tiêu.
| target_label | signal_count | hit_rate_pct | stopped_first_pct |
|---|---|---|---|
| +5% | 3632 | 58.2 | 31.2 |
| +10% | 3632 | 32.7 | 38.9 |
| +15% | 3632 | 17.7 | 40.6 |
| +20% | 3632 | 10.4 | 41.1 |
| +25% | 3632 | 6.4 | 41.2 |
Câu lệnh SQL chính xác đằng sau mỗi con số
WITH
universe AS
(
SELECT ticker
FROM global_markets.stocks_daily_aggs
WHERE date >= '2014-06-01'
AND ifNull(otc, 0) = 0
AND ticker NOT IN ('SPCX')
GROUP BY ticker
HAVING count() >= 250
AND avg(toFloat64(close) * volume) >= 2e7
),
daily AS
(
SELECT
ticker,
date,
toFloat64(close) AS close,
toFloat64(high) AS high,
toFloat64(low) AS low,
toFloat64(volume) AS volume
FROM global_markets.stocks_daily_aggs
WHERE date >= '2014-06-01'
AND ticker IN (SELECT ticker FROM universe)
),
featured AS
(
SELECT
ticker,
date,
close,
volume,
max(high) OVER cup AS rim,
min(low) OVER cup AS cup_low,
max(high) OVER handle AS handle_high,
min(low) OVER handle AS handle_low,
avg(volume) OVER vol50 AS adv50,
lagInFrame(close, 120) OVER trend AS base_start_close,
lagInFrame(close, 240) OVER trend AS trend_start_close,
count() OVER trend AS history_bars
FROM daily
WINDOW
cup AS (PARTITION BY ticker ORDER BY date ROWS BETWEEN 120 PRECEDING AND 11 PRECEDING),
handle AS (PARTITION BY ticker ORDER BY date ROWS BETWEEN 10 PRECEDING AND 1 PRECEDING),
vol50 AS (PARTITION BY ticker ORDER BY date ROWS BETWEEN 50 PRECEDING AND 1 PRECEDING),
trend AS (PARTITION BY ticker ORDER BY date ROWS BETWEEN 240 PRECEDING AND CURRENT ROW)
),
signals AS
(
SELECT
ticker,
date AS breakout_date,
close AS breakout_close,
handle_low AS handle_low
FROM featured
WHERE history_bars = 241
AND date >= '2015-01-01'
AND date <= today() - 65
AND rim > 0
AND adv50 > 0
AND close >= 10
AND adv50 * close >= 1e8
AND close > rim
AND handle_high <= rim
AND handle_low > cup_low
AND (1 - cup_low / rim) >= 0.12
AND (1 - cup_low / rim) <= 0.50
AND (rim - handle_low) / rim <= 0.5 * (1 - cup_low / rim)
AND base_start_close >= 1.10 * trend_start_close
),
paths AS
(
SELECT
min(if(b.low <= s.handle_low, b.date, toDate('2099-12-31'))) AS stop_date,
min(if(b.high >= s.breakout_close * 1.05, b.date, toDate('2099-12-31'))) AS hit_05,
min(if(b.high >= s.breakout_close * 1.10, b.date, toDate('2099-12-31'))) AS hit_10,
min(if(b.high >= s.breakout_close * 1.15, b.date, toDate('2099-12-31'))) AS hit_15,
min(if(b.high >= s.breakout_close * 1.20, b.date, toDate('2099-12-31'))) AS hit_20,
min(if(b.high >= s.breakout_close * 1.25, b.date, toDate('2099-12-31'))) AS hit_25
FROM daily AS b
INNER JOIN signals AS s ON s.ticker = b.ticker
WHERE b.date > s.breakout_date
AND b.date <= s.breakout_date + 60
GROUP BY
s.ticker,
s.breakout_date,
s.breakout_close,
s.handle_low
)
SELECT
concat('+', toString(goal.1), '%') AS target_label,
count() AS signal_count,
round(100 * countIf(goal.2 < stop_date) / count(), 1) AS hit_rate_pct,
round(100 * countIf(goal.2 >= stop_date
AND stop_date < toDate('2099-12-31')) / count(), 1) AS stopped_first_pct
FROM
(
SELECT
stop_date,
arrayJoin([(5, hit_05), (10, hit_10), (15, hit_15), (20, hit_20), (25, hit_25)]) AS goal
FROM paths
)
GROUP BY target_label
ORDER BY min(goal.1)Ở mốc gần nhất +5%, 58.2% số tín hiệu chạm đích trước khi giá quay về đáy tay cầm. Ở mốc +10% con số là 32.7%, còn ở mốc xa nhất +25% chỉ còn 6.4%. Cũng tại mốc +10%, 38.9% số tín hiệu thủng đáy tay cầm trước. Phần còn lại là những trường hợp lình xình, hết 60 ngày mà không chạm mốc nào trong hai mốc.
Đường cong này là thứ nên dùng thay cho câu "cốc tay cầm thắng khoảng 65%" mà bạn hay gặp. Một tỷ lệ chỉ có nghĩa khi gắn với một mục tiêu cụ thể và một mức dừng cụ thể.
Khối lượng ngày breakout có đổi kết quả không
Tài liệu CANSLIM nhấn mạnh khối lượng của phiên vượt vành. Điều kiện đó đo được trực tiếp: lấy khối lượng ngày breakout chia cho khối lượng bình quân 50 phiên trước đó, rồi tách tín hiệu thành từng nhóm. Mục tiêu giữ cố định ở +10%.
| volume_bucket | signal_count | hit_rate_pct | stopped_first_pct |
|---|---|---|---|
| Dưới 1x | 1329 | 31.3 | 39.9 |
| 1x đến 1,5x | 1230 | 33.8 | 41.1 |
| 1,5x đến 2x | 474 | 30.6 | 42.4 |
| 2x đến 3x | 357 | 35 | 34.2 |
| Trên 3x | 242 | 36 | 22.3 |
Câu lệnh SQL chính xác đằng sau mỗi con số
WITH
universe AS
(
SELECT ticker
FROM global_markets.stocks_daily_aggs
WHERE date >= '2014-06-01'
AND ifNull(otc, 0) = 0
AND ticker NOT IN ('SPCX')
GROUP BY ticker
HAVING count() >= 250
AND avg(toFloat64(close) * volume) >= 2e7
),
daily AS
(
SELECT
ticker,
date,
toFloat64(close) AS close,
toFloat64(high) AS high,
toFloat64(low) AS low,
toFloat64(volume) AS volume
FROM global_markets.stocks_daily_aggs
WHERE date >= '2014-06-01'
AND ticker IN (SELECT ticker FROM universe)
),
featured AS
(
SELECT
ticker,
date,
close,
volume,
max(high) OVER cup AS rim,
min(low) OVER cup AS cup_low,
max(high) OVER handle AS handle_high,
min(low) OVER handle AS handle_low,
avg(volume) OVER vol50 AS adv50,
lagInFrame(close, 120) OVER trend AS base_start_close,
lagInFrame(close, 240) OVER trend AS trend_start_close,
count() OVER trend AS history_bars
FROM daily
WINDOW
cup AS (PARTITION BY ticker ORDER BY date ROWS BETWEEN 120 PRECEDING AND 11 PRECEDING),
handle AS (PARTITION BY ticker ORDER BY date ROWS BETWEEN 10 PRECEDING AND 1 PRECEDING),
vol50 AS (PARTITION BY ticker ORDER BY date ROWS BETWEEN 50 PRECEDING AND 1 PRECEDING),
trend AS (PARTITION BY ticker ORDER BY date ROWS BETWEEN 240 PRECEDING AND CURRENT ROW)
),
signals AS
(
SELECT
ticker,
date AS breakout_date,
close AS breakout_close,
handle_low AS handle_low,
volume / adv50 AS rel_volume
FROM featured
WHERE history_bars = 241
AND date >= '2015-01-01'
AND date <= today() - 65
AND rim > 0
AND adv50 > 0
AND close >= 10
AND adv50 * close >= 1e8
AND close > rim
AND handle_high <= rim
AND handle_low > cup_low
AND (1 - cup_low / rim) >= 0.12
AND (1 - cup_low / rim) <= 0.50
AND (rim - handle_low) / rim <= 0.5 * (1 - cup_low / rim)
AND base_start_close >= 1.10 * trend_start_close
),
paths AS
(
SELECT
s.rel_volume AS rel_volume,
min(if(b.low <= s.handle_low, b.date, toDate('2099-12-31'))) AS stop_date,
min(if(b.high >= s.breakout_close * 1.10, b.date, toDate('2099-12-31'))) AS hit_date
FROM daily AS b
INNER JOIN signals AS s ON s.ticker = b.ticker
WHERE b.date > s.breakout_date
AND b.date <= s.breakout_date + 60
GROUP BY
s.ticker,
s.breakout_date,
s.breakout_close,
s.handle_low,
s.rel_volume
)
SELECT
multiIf(rel_volume < 1, 'Dưới 1x',
rel_volume < 1.5, '1x đến 1,5x',
rel_volume < 2, '1,5x đến 2x',
rel_volume < 3, '2x đến 3x',
'Trên 3x') AS volume_bucket,
count() AS signal_count,
round(100 * countIf(hit_date < stop_date) / count(), 1) AS hit_rate_pct,
round(100 * countIf(stop_date <= hit_date
AND stop_date < toDate('2099-12-31')) / count(), 1) AS stopped_first_pct
FROM paths
GROUP BY volume_bucket
ORDER BY min(rel_volume)Nhóm Dưới 1x đạt 31.3% trên 1329 tín hiệu. Nhóm Trên 3x đạt 36% trên 242 tín hiệu. Khoảng cách giữa hai đầu bảng chính là toàn bộ giá trị thực nghiệm của câu "breakout phải có khối lượng lớn", và bạn nên nhìn con số đó trước khi nhìn lời khuyên. Bài chỉ báo khối lượng có dự báo được gì không đi sâu hơn vào giới hạn của nhóm chỉ báo này, còn cách tính mẫu số nằm ở bài khối lượng giao dịch bình quân.
Một lưu ý khi đọc cột signal_count: các nhóm khối lượng cao luôn ít tín hiệu hơn hẳn. Tỷ lệ của một nhóm chỉ vài chục quan sát dao động mạnh, và không nên đặt ngang hàng với tỷ lệ của nhóm vài nghìn quan sát.
Con số có ổn định qua từng năm không
Một tỷ lệ gộp mười năm có thể che việc phần lớn kết quả đến từ vài năm thuận lợi. Tách theo năm breakout là cách kiểm tra rẻ nhất.
| year | signal_count | hit_rate_pct |
|---|---|---|
| 2015 | 99 | 15.2 |
| 2016 | 68 | 19.1 |
| 2017 | 369 | 28.2 |
| 2018 | 295 | 23.7 |
| 2019 | 255 | 31 |
| 2020 | 236 | 43.6 |
| 2021 | 674 | 30.3 |
| 2022 | 136 | 32.4 |
| 2023 | 200 | 39 |
| 2024 | 618 | 37.4 |
| 2025 | 408 | 33.8 |
| 2026 | 274 | 40.1 |
Câu lệnh SQL chính xác đằng sau mỗi con số
WITH
universe AS
(
SELECT ticker
FROM global_markets.stocks_daily_aggs
WHERE date >= '2014-06-01'
AND ifNull(otc, 0) = 0
AND ticker NOT IN ('SPCX')
GROUP BY ticker
HAVING count() >= 250
AND avg(toFloat64(close) * volume) >= 2e7
),
daily AS
(
SELECT
ticker,
date,
toFloat64(close) AS close,
toFloat64(high) AS high,
toFloat64(low) AS low,
toFloat64(volume) AS volume
FROM global_markets.stocks_daily_aggs
WHERE date >= '2014-06-01'
AND ticker IN (SELECT ticker FROM universe)
),
featured AS
(
SELECT
ticker,
date,
close,
volume,
max(high) OVER cup AS rim,
min(low) OVER cup AS cup_low,
max(high) OVER handle AS handle_high,
min(low) OVER handle AS handle_low,
avg(volume) OVER vol50 AS adv50,
lagInFrame(close, 120) OVER trend AS base_start_close,
lagInFrame(close, 240) OVER trend AS trend_start_close,
count() OVER trend AS history_bars
FROM daily
WINDOW
cup AS (PARTITION BY ticker ORDER BY date ROWS BETWEEN 120 PRECEDING AND 11 PRECEDING),
handle AS (PARTITION BY ticker ORDER BY date ROWS BETWEEN 10 PRECEDING AND 1 PRECEDING),
vol50 AS (PARTITION BY ticker ORDER BY date ROWS BETWEEN 50 PRECEDING AND 1 PRECEDING),
trend AS (PARTITION BY ticker ORDER BY date ROWS BETWEEN 240 PRECEDING AND CURRENT ROW)
),
signals AS
(
SELECT
ticker,
date AS breakout_date,
close AS breakout_close,
handle_low AS handle_low
FROM featured
WHERE history_bars = 241
AND date >= '2015-01-01'
AND date <= today() - 65
AND rim > 0
AND adv50 > 0
AND close >= 10
AND adv50 * close >= 1e8
AND close > rim
AND handle_high <= rim
AND handle_low > cup_low
AND (1 - cup_low / rim) >= 0.12
AND (1 - cup_low / rim) <= 0.50
AND (rim - handle_low) / rim <= 0.5 * (1 - cup_low / rim)
AND base_start_close >= 1.10 * trend_start_close
),
paths AS
(
SELECT
s.breakout_date AS breakout_date,
min(if(b.low <= s.handle_low, b.date, toDate('2099-12-31'))) AS stop_date,
min(if(b.high >= s.breakout_close * 1.10, b.date, toDate('2099-12-31'))) AS hit_date
FROM daily AS b
INNER JOIN signals AS s ON s.ticker = b.ticker
WHERE b.date > s.breakout_date
AND b.date <= s.breakout_date + 60
GROUP BY
s.ticker,
s.breakout_date,
s.breakout_close,
s.handle_low
)
SELECT
toYear(breakout_date) AS year,
count() AS signal_count,
round(100 * countIf(hit_date < stop_date) / count(), 1) AS hit_rate_pct
FROM paths
GROUP BY year
ORDER BY yearBảng trải từ 2015 đến 2026, tức 12 năm breakout. Riêng năm 2015 ghi nhận 99 tín hiệu với tỷ lệ đạt 15.2%. Hai cột đọc kèm nhau mới đủ: số tín hiệu mỗi năm dày lên trong các giai đoạn thị trường leo thang và mỏng đi trong các giai đoạn giá rơi, nên một năm có tỷ lệ cao mà chỉ vài chục tín hiệu không nói lên nhiều điều. Năm cuối bảng chỉ gồm các breakout đã đủ 60 ngày dữ liệu phía sau, vì vậy số tín hiệu của năm đó còn thiếu phần đuôi.
Cổ phiếu thanh khoản thấp hơn thì sao
Cùng một bộ luật, tách theo giá trị giao dịch bình quân 50 phiên trước breakout. Đây là cách nhìn gần nhất với câu hỏi "mẫu hình này có chạy ở hàng thanh khoản thấp không" mà dữ liệu cho phép trả lời.
| liquidity_bucket | signal_count | hit_rate_pct | stopped_first_pct |
|---|---|---|---|
| Dưới 300 triệu USD | 2185 | 32 | 38.9 |
| 300 triệu đến 1 tỷ USD | 1072 | 32.6 | 40.3 |
| 1 tỷ đến 5 tỷ USD | 312 | 36.9 | 35.6 |
| Trên 5 tỷ USD | 63 | 41.3 | 30.2 |
Câu lệnh SQL chính xác đằng sau mỗi con số
WITH
universe AS
(
SELECT ticker
FROM global_markets.stocks_daily_aggs
WHERE date >= '2014-06-01'
AND ifNull(otc, 0) = 0
AND ticker NOT IN ('SPCX')
GROUP BY ticker
HAVING count() >= 250
AND avg(toFloat64(close) * volume) >= 2e7
),
daily AS
(
SELECT
ticker,
date,
toFloat64(close) AS close,
toFloat64(high) AS high,
toFloat64(low) AS low,
toFloat64(volume) AS volume
FROM global_markets.stocks_daily_aggs
WHERE date >= '2014-06-01'
AND ticker IN (SELECT ticker FROM universe)
),
featured AS
(
SELECT
ticker,
date,
close,
volume,
max(high) OVER cup AS rim,
min(low) OVER cup AS cup_low,
max(high) OVER handle AS handle_high,
min(low) OVER handle AS handle_low,
avg(volume) OVER vol50 AS adv50,
lagInFrame(close, 120) OVER trend AS base_start_close,
lagInFrame(close, 240) OVER trend AS trend_start_close,
count() OVER trend AS history_bars
FROM daily
WINDOW
cup AS (PARTITION BY ticker ORDER BY date ROWS BETWEEN 120 PRECEDING AND 11 PRECEDING),
handle AS (PARTITION BY ticker ORDER BY date ROWS BETWEEN 10 PRECEDING AND 1 PRECEDING),
vol50 AS (PARTITION BY ticker ORDER BY date ROWS BETWEEN 50 PRECEDING AND 1 PRECEDING),
trend AS (PARTITION BY ticker ORDER BY date ROWS BETWEEN 240 PRECEDING AND CURRENT ROW)
),
signals AS
(
SELECT
ticker,
date AS breakout_date,
close AS breakout_close,
handle_low AS handle_low,
adv50 * close / 1e6 AS adv_usd_mn
FROM featured
WHERE history_bars = 241
AND date >= '2015-01-01'
AND date <= today() - 65
AND rim > 0
AND adv50 > 0
AND close >= 10
AND adv50 * close >= 1e8
AND close > rim
AND handle_high <= rim
AND handle_low > cup_low
AND (1 - cup_low / rim) >= 0.12
AND (1 - cup_low / rim) <= 0.50
AND (rim - handle_low) / rim <= 0.5 * (1 - cup_low / rim)
AND base_start_close >= 1.10 * trend_start_close
),
paths AS
(
SELECT
s.adv_usd_mn AS adv_usd_mn,
min(if(b.low <= s.handle_low, b.date, toDate('2099-12-31'))) AS stop_date,
min(if(b.high >= s.breakout_close * 1.10, b.date, toDate('2099-12-31'))) AS hit_date
FROM daily AS b
INNER JOIN signals AS s ON s.ticker = b.ticker
WHERE b.date > s.breakout_date
AND b.date <= s.breakout_date + 60
GROUP BY
s.ticker,
s.breakout_date,
s.breakout_close,
s.handle_low,
s.adv_usd_mn
)
SELECT
multiIf(adv_usd_mn < 300, 'Dưới 300 triệu USD',
adv_usd_mn < 1000, '300 triệu đến 1 tỷ USD',
adv_usd_mn < 5000, '1 tỷ đến 5 tỷ USD',
'Trên 5 tỷ USD') AS liquidity_bucket,
count() AS signal_count,
round(100 * countIf(hit_date < stop_date) / count(), 1) AS hit_rate_pct,
round(100 * countIf(stop_date <= hit_date
AND stop_date < toDate('2099-12-31')) / count(), 1) AS stopped_first_pct
FROM paths
GROUP BY liquidity_bucket
ORDER BY min(adv_usd_mn)Nhóm thấp nhất, Dưới 300 triệu USD, đạt 32% trên 2185 tín hiệu, trong khi nhóm Trên 5 tỷ USD đạt 41.3%. Cần nói thẳng một giới hạn: cả bốn nhóm đều từ 100 triệu USD mỗi phiên trở lên, nên bảng này không phải phép thử trên cổ phiếu thanh khoản mỏng thật sự. Với hàng thanh khoản thấp, chi phí vào lệnh và khoảng trượt giá còn chưa được tính vào bất kỳ con số nào ở trên.
Biên độ dao động của HOSE làm mẫu hình méo đi ra sao
Toàn bộ số liệu trên đo bằng cổ phiếu niêm yết tại Mỹ. Không có dữ liệu HOSE, HNX hay UPCoM ở đây, và cũng không nên suy diễn thẳng sang bảng điện trong nước, vì cơ chế giá khác nhau ở một điểm rất lớn.
HOSE áp biên độ 7% mỗi phiên, HNX 10%, UPCoM 15%. Thị trường Mỹ không có trần sàn theo phiên. Một phiên vượt vành cốc ở Mỹ có thể mở gap 8% rồi đóng cửa cách xa vành, và chính cú nhảy đó làm mẫu hình nhìn rõ trên biểu đồ. Trên HOSE, cùng lượng cầu ấy bị chia nhỏ thành chuỗi phiên trần nối tiếp, phần giá chưa kịp thể hiện sẽ dồn sang các phiên sau.
Hai hệ quả rất cụ thể cho người vẽ chart tại Việt Nam. Thứ nhất, điểm breakout không còn là một phiên dứt khoát, mà là một chuỗi phiên, nên luật "giá đóng cửa vượt vành" phải được định nghĩa lại trước khi đo. Thứ hai, cái trông như tay cầm nhiều khi chỉ là vài phiên đi ngang sau khi biên độ đã hết dư địa trong ngày, chứ không phải nhịp chốt lời nông mà lý thuyết mô tả. Vì vậy, tỷ lệ đo trên thị trường Mỹ nên được coi là trần trên cho VN-Index, chứ không phải con số kỳ vọng.
Hai lỗi làm con số đẹp hơn thực tế
Vẽ vành cốc sau khi đã biết kết quả. Khi nhìn lại biểu đồ, mắt người tự động chọn đúng cái vành mà giá đã vượt qua và đi tiếp. Đó là thiên lệch nhìn trước, và nó đủ sức đẩy tỷ lệ thành công của bất kỳ mẫu hình nào lên mức không ai lặp lại được khi giao dịch thật. Bộ luật ở trang này chỉ dùng dữ liệu có trước ngày breakout, kể cả điều kiện thanh khoản, nên không có thông tin tương lai nào lọt vào thời điểm ra tín hiệu. Bài thiên lệch nhìn trước trong backtest mô tả các kiểu rò rỉ thường gặp, còn quy trình backtest một chiến lược nói về cách cố định luật trước khi chạy số.
Breakout khối lượng mỏng ở cổ phiếu ít giao dịch. Ở một mã giao dịch vài tỷ đồng mỗi phiên, một lệnh mua vừa phải cũng đủ đẩy giá qua vành và tạo ra đúng hình dạng mà mẫu hình đòi hỏi. Tín hiệu trông giống hệt nhau trên biểu đồ, nhưng mức giá bạn khớp được lại khác xa mức giá hiển thị. Đó là lý do mọi con số ở trên đều gắn với một ngưỡng thanh khoản tối thiểu, và cũng là lý do bảng cuối cùng được tách theo giá trị giao dịch thay vì gộp chung.
Ghi chú dữ liệu và những giới hạn đã biết
- Mẫu quan sát gồm cổ phiếu và chứng chỉ quỹ niêm yết tại Mỹ đạt ngưỡng thanh khoản tại thời điểm breakout. Dữ liệu ngày không tách riêng quỹ ETF, nên nhóm này nằm chung trong mẫu.
- Có một bộ lọc sơ bộ nhằm giảm khối lượng tính toán: chỉ giữ các mã có ít nhất 250 phiên và giá trị giao dịch bình quân toàn giai đoạn từ 20 triệu USD. Điều kiện thực sự ràng buộc vẫn là điều kiện 100 triệu USD tính tại ngày breakout.
- Các mã đã hủy niêm yết vẫn được tính nếu đạt điều kiện tại thời điểm breakout, nhưng mẫu nghiêng về nhóm vốn hóa lớn còn tồn tại tới nay.
- Trần độ sâu 50% loại bỏ phần lớn trường hợp méo hình do chia tách cổ phiếu tỷ lệ lớn trong cửa sổ quan sát. Chia tách tỷ lệ nhỏ vẫn có thể lọt vào mẫu.
- Mọi kết quả đo trên giá ngày, không tính phí giao dịch, thuế hay trượt giá, và không giả định bất kỳ cách quản lý vị thế nào ngoài hai mốc đã nêu.
FAQ
Mô hình cốc tay cầm là gì?
Đó là mẫu hình giá gồm một nhịp giảm rồi hồi phục tạo thành đáy tròn giống lòng cốc, sau đó là một nhịp chỉnh nông hơn sát vành cốc gọi là tay cầm, và kết thúc bằng phiên giá vượt lên trên vành. Trang này quy mỗi phần của mô tả đó thành một ngưỡng bằng số để có thể đếm được.
Tỷ lệ thành công của mô hình cốc tay cầm là bao nhiêu?
Không có một con số duy nhất. Theo bộ luật ở đây, với mục tiêu +10% và mức dừng là đáy tay cầm trong 60 ngày, tỷ lệ đạt là 32.7% trên 3632 tín hiệu ở cổ phiếu Mỹ từ 2015. Đổi mục tiêu hoặc đổi khung thời gian thì con số đổi theo, như bảng đường cong mục tiêu cho thấy.
Tay cầm nên sâu bao nhiêu?
Trong bộ luật này, tay cầm bị giới hạn ở mức lùi không quá một nửa độ sâu của cốc, và đáy tay cầm phải nằm cao hơn đáy cốc. Đây là ngưỡng do chúng tôi đặt ra để đo được, không phải quy ước bắt buộc. Bạn có thể nới hoặc siết ngưỡng này rồi chạy lại để xem tỷ lệ dịch chuyển tới đâu.
Mẫu hình này áp dụng cho cổ phiếu Việt Nam được không?
Hình dạng thì vẫn vẽ được, nhưng con số thì không chuyển thẳng sang được. Biên độ 7% của HOSE cắt nhỏ các cú vượt vành vốn là phần dễ nhận biết nhất của mẫu hình ở thị trường Mỹ, nên tỷ lệ đo trên dữ liệu Mỹ chỉ nên dùng làm trần trên khi đọc biểu đồ trong nước.
Khối lượng ngày breakout quan trọng tới mức nào?
Bảng tách theo khối lượng ở trên trả lời trực tiếp: nhóm Dưới 1x đạt 31.3% còn nhóm Trên 3x đạt 36%. Hãy đọc kèm số lượng tín hiệu của từng nhóm, vì các nhóm khối lượng cao có cỡ mẫu nhỏ hơn nhiều.
Mỗi bảng ở trên đều kèm nguyên văn câu lệnh SQL ngay bên dưới. Bạn mở ra, đổi ngưỡng độ sâu cốc hoặc số phiên của tay cầm, rồi hỏi lại bằng tiếng Việt trên terminal Strasmore để xem con số dịch chuyển tới đâu.