1. Mô tả Dynamic Swing Anchored VWAP Strategy
Tự động neo một đường VWAP vào điểm đảo chiều (swing) gần nhất, vẽ lại toàn bộ đường từ điểm neo mỗi khi cấu trúc thị trường đổi hướng, kèm nhãn cấu trúc HH / HL / LH / LL.
1.1 Concept của chỉ báo
VWAP (giá trung bình theo khối lượng) truyền thống luôn được neo vào một mốc thời gian cố định: đầu phiên, đầu tuần, đầu tháng. Chỉ báo này đặt ra một câu hỏi khác: mốc neo có ý nghĩa nhất với trader không phải là "0 giờ", mà là điểm mà nhịp giá hiện tại thực sự bắt đầu — tức đáy đảo chiều gần nhất khi thị trường đang đi lên, hoặc đỉnh đảo chiều gần nhất khi thị trường đang đi xuống.
- Vì sao neo vào swing: đường VWAP tính từ đúng cái đáy đó chính là "giá vốn trung bình" của những người đã mua vào trong nhịp tăng này. Khi giá quay về chạm đường đó, đám đông đang lời chuyển về hoà vốn — nên đó là vùng mà phản ứng (mua thêm / cắt lỗ) thường xảy ra mạnh nhất.
- Điểm khác biệt thứ hai — không dùng phép cộng dồn: VWAP cổ điển cộng dồn toàn bộ giá×khối lượng từ mốc neo, nên nhịp càng kéo dài đường càng "ì", gần như không nhúc nhích. Chỉ báo này thay phép cộng dồn bằng trung bình động hàm mũ (EWMA) cho cả tử số (giá×khối lượng) lẫn mẫu số (khối lượng), với một tham số "nửa đời" gọi là APT — Adaptive Price Tracking. Kết quả là một đường vẫn có trọng số khối lượng nhưng luôn bám sát giá, không bị đông cứng.
- Điểm khác biệt thứ ba (tuỳ chọn) — tự co giãn theo biến động: khi bật, APT sẽ tự rút ngắn lúc thị trường biến động mạnh (đường phản ứng nhanh hơn) và tự kéo dài lúc thị trường êm (đường mượt hơn), dựa trên tỉ lệ giữa ATR hiện tại và ATR trung bình.
1.2 Chức năng của chỉ báo
-
Hiển thị:
- Đường VWAP đang chạy (active): một đường gấp khúc (polyline) bắt đầu đúng tại điểm swing neo và kéo dài tới nến hiện tại, mỗi nến được nối thêm một điểm mới. Đây là đường bạn giao dịch theo.
- Các đường VWAP đã "đóng băng": mỗi khi cấu trúc đổi hướng, đường của nhịp vừa kết thúc được giữ nguyên tại chỗ trên chart như một kỷ lục lịch sử, còn một đường mới bắt đầu từ điểm neo mới. Chart vì vậy dần tích tụ một chuỗi các đoạn VWAP nối tiếp nhau theo từng nhịp sóng.
- Nhãn cấu trúc HH / HL / LH / LL: mỗi khi đổi hướng, một nhãn được đặt lùi về đúng nến chứa điểm swing neo — nhãn xanh lá chỉ lên đặt ở đáy, nhãn đỏ chỉ xuống đặt ở đỉnh (theo màu mặc định). Chữ trong nhãn cho biết đáy/đỉnh này cao hay thấp hơn đáy/đỉnh cùng loại trước đó: HH đỉnh cao hơn, LH đỉnh thấp hơn, HL đáy cao hơn, LL đáy thấp hơn.
- Alert: Chỉ báo KHÔNG khai báo alertcondition() nào — thuần hiển thị trực quan, không có cảnh báo tự động.
1.3 Cách dùng chỉ báo
- Lấy đường VWAP đang chạy làm ranh giới phe mua / phe bán trong nhịp hiện tại: giá đóng cửa nằm trên đường (và đường đang neo tại một đáy) nghĩa là người mua của nhịp này đang có lời — ưu tiên phía mua. Ngược lại, giá dưới đường neo tại một đỉnh thì ưu tiên phía bán.
- Vào lệnh khi giá hồi về chạm đường rồi bật ra: đây là cách dùng phổ biến nhất của mọi VWAP neo — chờ giá pullback về vùng "giá vốn trung bình" và xuất hiện nến từ chối (bóng nến dài, nến đảo chiều) rồi vào theo hướng nhịp đang chạy.
- Đọc chuỗi nhãn để xác nhận xu hướng: HH kèm HL liên tiếp = xu hướng tăng còn khoẻ; LH kèm LL liên tiếp = xu hướng giảm. Khi xuất hiện một LH ngay sau chuỗi HH, hoặc một HL ngay sau chuỗi LL, đó là dấu hiệu sớm cấu trúc đang gãy.
- Dùng các đường đã đóng băng của những nhịp trước như mức tham chiếu: phần kéo dài về phía phải của chúng thường trùng với những vùng giá mà thị trường còn "nhớ".
- Chỉnh Swing Period theo khung thời gian: giá trị lớn (50 mặc định) cho ít điểm neo hơn nhưng mỗi điểm quan trọng hơn — hợp với swing trade. Giá trị nhỏ (10–20) cho nhiều điểm neo hơn, đường bị reset liên tục — hợp với scalping nhưng nhiễu hơn nhiều.
- Chỉnh APT theo kiểu bám giá bạn muốn: APT nhỏ (5–10) khiến đường gần như dính vào giá, ít khi bị chạm nên ít tín hiệu retest; APT lớn (50–100) khiến đường phẳng và xa giá, giống VWAP cổ điển hơn, cho vùng retest rộng hơn.
1.4 Cách hoạt động của chỉ báo
Đầu vào & vai trò
- prd ("Swing Period", số nguyên, mặc định 50, tối thiểu 2): số nến dùng để xác định một đỉnh/đáy có đáng kể hay không. Một nến được ghi nhận là đỉnh mới khi giá cao nhất của nó là cao nhất trong prd nến gần nhất. Ví dụ: trên khung M5 với prd=50, chỉ báo chỉ quan tâm những đỉnh/đáy vượt trội trong khoảng 4 giờ giao dịch gần nhất. Nếu giảm xuống 20, cửa sổ chỉ còn ~1 giờ 40 phút — đỉnh/đáy xuất hiện dày hơn nhiều, đường VWAP bị neo lại (reset) liên tục và gần như không kịp hình thành một đoạn dài có ý nghĩa.
- baseAPT ("Adaptive Price Tracking", số thập phân, mặc định 20, tối thiểu 1): chính là nửa đời (half-life) tính bằng số nến của trung bình hàm mũ. Hiểu đơn giản: sau đúng baseAPT nến, ảnh hưởng của một nến cũ lên đường VWAP chỉ còn một nửa. Con số này được quy đổi thành trọng số alpha dành cho nến mới nhất theo công thức alpha = 1 − e^(−ln2 / APT). Ví dụ cụ thể: APT=20 → alpha ≈ 0,0341 (mỗi nến mới chỉ chiếm 3,4% giá trị đường); APT=5 → alpha ≈ 0,1294 (12,9% — đường bám rất sát giá, hầu như không còn tác dụng làm mượt); APT=100 → alpha ≈ 0,0069 (0,69% — đường gần như nằm ngang, giống VWAP cộng dồn).
- useAdapt ("Adapt APT by ATR ratio", tick bật/tắt, mặc định TẮT): khi tắt, APT là hằng số đúng bằng baseAPT suốt mọi nến. Khi bật, APT được tính lại từng nến theo biến động thị trường (xem Luồng 4). Bật hay tắt không đổi vị trí điểm neo — chỉ đổi độ cong / độ bám giá của đường.
- volBias ("Volatility Bias", số thập phân, mặc định 10,0, tối thiểu 0,1, bước 0,1): số mũ quyết định biến động ảnh hưởng mạnh tới đâu — chỉ có tác dụng khi useAdapt đang BẬT. Công thức: APT = baseAPT ÷ (tỉ lệ ATR)^volBias. Ví dụ với mặc định volBias=10: ATR hiện tại chỉ cần cao hơn trung bình 20% (tỉ lệ 1,2) thì mẫu số đã là 1,2¹⁰ ≈ 6,2 → APT tụt từ 20 xuống 3,2 và bị chặn lại ở mức sàn 5. Ngược lại ATR thấp hơn 20% (tỉ lệ 0,8) → 0,8¹⁰ ≈ 0,107 → APT vọt lên 186. Nếu để volBias=1, cùng tỉ lệ 1,2 chỉ đưa APT về 16,7 — êm hơn rất nhiều.
- highS / lowS ("Swing Labels", 2 ô màu cùng dòng, mặc định lime / đỏ): màu nền của nhãn cấu trúc. Ô thứ nhất được dùng cho nhãn đặt tại ĐÁY, ô thứ hai cho nhãn đặt tại ĐỈNH (xem lưu ý kỹ thuật — cách đặt tên tooltip trong code dễ gây hiểu ngược). Màu nhãn luôn được làm mờ 20% và chữ luôn màu trắng.
- S / R ("VWAP Lines", 2 ô màu cùng dòng, mặc định lime / đỏ): màu của các đường VWAP. Xem lưu ý kỹ thuật: trên thực tế nhịp TĂNG lại được vẽ bằng ô R (đỏ) và nhịp GIẢM bằng ô S (lime) — ngược với mô tả trong tooltip gốc.
- xx (ô số cuối dòng "VWAP Lines", số nguyên, mặc định 2, tối thiểu 1): độ dày nét vẽ của mọi đường VWAP, tính bằng pixel. Tăng lên 3–4 giúp đường nổi bật trên nền nến nhưng che mất chi tiết bóng nến ở những nơi đường đi xuyên qua giá.
Các khối logic chính
🏷️ Luồng 1 — Phát hiện swing và xác định nhịp hiện tại (chạy mọi nến)
- Chỉ báo giữ 4 biến "nhớ dai" (giá trị được mang qua các nến, chỉ thay khi có sự kiện mới): ph = giá đỉnh gần nhất, phL = số thứ tự nến của đỉnh đó, pl / plL tương tự cho đáy.
- Mỗi nến, chỉ báo hỏi: "giá cao nhất của nến này có phải là cao nhất trong prd nến gần nhất không?" (trong code là ta.highestbars(high, prd) == 0). Nếu đúng → cập nhật ph và phL về nến hiện tại. Câu hỏi đối xứng cho đáy với ta.lowestbars(low, prd) == 0.
- Hướng nhịp dir được quyết định chỉ bằng việc sự kiện nào xảy ra gần đây hơn: dir = phL > plL ? 1 : −1. Nếu lần lập đỉnh mới gần đây hơn lần lập đáy mới → dir = +1 → thị trường đang trong nhịp TĂNG, và điểm khởi phát của nhịp này chính là cái ĐÁY cũ. Ngược lại dir = −1 → nhịp GIẢM, khởi phát từ cái ĐỈNH cũ.
- Ví dụ: giá rơi liên tục, mỗi nến đều phá đáy 50 nến → plL cập nhật liên tục, dir = −1. Giá tạo đáy tại nến #1000 rồi bật lên; tới nến #1042 giá vượt qua đỉnh cao nhất của 50 nến trước đó → phL = 1042 > plL = 1000 → dir lật thành +1. Đây chính là nến đổi hướng, và điểm neo được chọn là nến #1000 — lùi về quá khứ 42 nến.
📍 Luồng 2 — Xử lý nến đổi hướng: đặt nhãn cấu trúc
- Toàn bộ khối này chỉ chạy đúng những nến mà dir khác với nến trước (dir != dir[1]).
- Chọn điểm neo: nếu dir vừa thành +1 → lấy toạ độ đáy (x = plL, y = pl), nhãn dạng mũi chỉ lên đặt bên dưới đáy, màu highS. Nếu dir vừa thành −1 → lấy toạ độ đỉnh (x = phL, y = ph), nhãn chỉ xuống đặt phía trên đỉnh, màu lowS.
- Chữ trong nhãn được chọn bằng cách so sánh điểm swing vừa chốt với biến prev — vốn đang lưu điểm swing cùng loại của lần đổi hướng trước: đang neo đáy và đáy mới thấp hơn → LL, cao hơn → HL; đang neo đỉnh và đỉnh mới thấp hơn → LH, cao hơn → HH.
- Ngay sau khi vẽ nhãn, prev được nạp giá trị cho lần đổi hướng kế tiếp: prev := dir > 0 ? ph[1] : pl[1]. Nhờ cách xen kẽ này, lần so sánh sau luôn là đáy-với-đáy hoặc đỉnh-với-đỉnh, không bao giờ so lệch loại.
🌱 Luồng 3 — Gieo hạt (seed) lại đường VWAP tại điểm neo
- Tính khoảng lùi: barsback = bar_index − x (trong ví dụ trên là 42 nến).
- Hai bộ tích luỹ của EWMA được nạp lại từ đầu bằng đúng dữ liệu tại nến neo: p := y × volume[barsback] (tử số) và vol := volume[barsback] (mẫu số). Chia hai số này cho nhau ra đúng y — nghĩa là điểm đầu tiên của đường VWAP luôn nằm chính xác trên đỉnh/đáy neo, không lệch.
- Đường VWAP của nhịp cũ được "đóng băng": code tạo một polyline mới từ đúng danh sách điểm cũ nhưng không gán vào biến nào — nó trở thành một hình vẽ không còn ai quản lý, nằm lại vĩnh viễn trên chart. Sau đó danh sách điểm được xoá sạch để bắt đầu nhịp mới.
⚡ Luồng 4 — Quy đổi APT thành trọng số alpha (và chế độ thích ứng)
- Đo biến động: atr = ATR(50), atrAvg = RMA(atr, 50) (trung bình của chính ATR), ratio = atr / atrAvg. ratio > 1 nghĩa là thị trường đang động hơn bình thường.
- Nếu useAdapt TẮT: aptRaw = baseAPT. Nếu BẬT: aptRaw = baseAPT / ratio^volBias.
- Kết quả luôn bị chặn trong khoảng [5 ; 300] rồi làm tròn về số nguyên — đây là lý do vì sao với volBias mặc định quá lớn, APT phần lớn thời gian chỉ nằm ở đúng hai đầu chặn.
- Cuối cùng quy đổi sang trọng số: alpha = 1 − e^(−ln2 / APT). alpha càng lớn thì nến mới càng lấn át, đường càng dính giá.
🔁 Luồng 5 — Dựng lại toàn bộ đường từ điểm neo (chỉ tại nến đổi hướng)
- Code chạy một vòng lặp lùi từ nến neo về nến hiện tại (i = barsback → 0). Tại mỗi bước i, nó đọc lại dữ liệu lịch sử của đúng nến đó: aptSeries[i], hlc3[i], volume[i] — nghĩa là APT thích ứng được áp dụng đúng theo biến động của từng nến trong quá khứ, chứ không dùng một giá trị APT duy nhất cho cả đoạn.
- Mỗi bước cập nhật hai tích luỹ theo công thức EWMA: p := (1−alpha)×p + alpha×(hlc3[i]×volume[i]) và vol := (1−alpha)×vol + alpha×volume[i]. Giá trị VWAP tại nến đó là p / vol, được đẩy vào danh sách điểm.
- Ví dụ số: APT=20 → alpha=0,0341. Tại nến neo đường bằng đúng giá đáy, giả sử 2600. Nến kế tiếp có hlc3=2610 → đường mới ≈ 2600 + 0,0341×(2610−2600) ≈ 2600,34 (nếu khối lượng hai nến tương đương). Phải mất khoảng 20 nến đi cùng hướng thì đường mới đuổi kịp một nửa quãng đường tới giá.
- Sau vòng lặp, một polyline mới được tạo từ toàn bộ danh sách điểm và được gán vào vwap.poly — đây là đường "đang chạy", cái duy nhất chỉ báo còn quyền xoá / vẽ lại ở các nến sau.
➕ Luồng 6 — Nối dài đường ở các nến bình thường (không đổi hướng)
- Chỉ một bước EWMA duy nhất với dữ liệu nến hiện tại: p := (1−alpha)×p + alpha×(hlc3×volume), vol := (1−alpha)×vol + alpha×volume, vap = p / vol.
- Polyline đang chạy bị xoá, điểm mới được thêm vào cuối danh sách, rồi polyline được vẽ lại từ danh sách đã dài thêm một điểm. Về mặt thị giác người dùng chỉ thấy đường "mọc" thêm một đoạn ở mũi phải.
- Vì mọi điểm cũ được giữ nguyên trong danh sách, phần đường phía sau không đổi — chỉ đoạn cuối cùng là mới.
Đầu ra & vai trò trong sử dụng
- Đường VWAP đang chạy: mức tham chiếu động để phân định phe mua/phe bán trong nhịp hiện tại và để canh điểm vào lệnh khi giá hồi về chạm.
- Các đường VWAP đã đóng băng: bản đồ lịch sử cho thấy trong từng nhịp trước, "giá vốn trung bình" nằm ở đâu — dùng như các mức hỗ trợ/kháng cự mềm.
- Nhãn HH / HL / LH / LL: tóm tắt cấu trúc thị trường bằng chữ, giúp xác nhận xu hướng hoặc bắt sớm tín hiệu gãy cấu trúc mà không cần tự vẽ tay.
- Không có đầu ra dạng số: chỉ báo không có plot() nào, nên không thể gọi giá trị VWAP này từ chỉ báo khác qua nguồn dữ liệu bên ngoài, cũng không có alert dựng sẵn.
- Màu đường VWAP bị ngược so với tooltip: tooltip ghi S là "màu cho xu hướng tăng" và R cho "xu hướng giảm". Nhưng ở nhánh chạy mỗi nến, code dùng dir > 0 ? R : S — nghĩa là nhịp TĂNG (dir=+1) được vẽ bằng R (mặc định đỏ) và nhịp GIẢM bằng S (mặc định lime). Muốn màu trực quan như tooltip mô tả, cách đơn giản nhất là hoán đổi hai ô màu trong bảng cài đặt.
- Nháy màu một nến tại mỗi lần đổi hướng: ngay tại nến đổi hướng, đường mới được tạo với điều kiện dir < 0 ? R : S — đúng ngược lại với nhánh chạy bình thường. Hệ quả: đường của nhịp mới xuất hiện với màu này đúng một nến rồi đổi sang màu kia từ nến kế tiếp. Đây gần như chắc chắn là lỗi sao chép trong code gốc, và là điểm cần sửa nếu chuyển sang strategy/MT5.
- Chỉ báo VẼ LẠI QUÁ KHỨ (repaint): tại nến đổi hướng, toàn bộ đoạn đường từ điểm neo tới hiện tại được tính và vẽ mới; nhãn cấu trúc cũng xuất hiện lùi về quá khứ hàng chục nến. Nghĩa là những gì bạn nhìn thấy trên lịch sử KHÔNG phải những gì đã thực sự hiển thị ở thời điểm đó. Mọi backtest thủ công bằng mắt trên chart đều sẽ lạc quan hơn thực tế — điểm neo chỉ được biết sau khi giá đã phá đỉnh/đáy prd nến.
- Các đường đóng băng là hình vẽ "mồ côi", không thể xoá: vì được tạo không gán biến, chỉ báo không còn tham chiếu tới chúng. Chúng chỉ biến mất khi vượt giới hạn max_polylines_count = 100 khai báo ở đầu code — lúc đó TradingView tự xoá cái cũ nhất. Trên chart nhiều lịch sử, bạn chỉ thấy được khoảng 100 nhịp gần nhất.
- Đây không phải VWAP theo đúng định nghĩa: VWAP thật là tổng cộng dồn (giá×khối lượng) chia tổng cộng dồn (khối lượng) kể từ mốc neo, mọi nến có trọng số như nhau. Ở đây cả tử và mẫu đều là trung bình hàm mũ, nến càng cũ trọng số càng suy giảm theo cấp số nhân. Gọi chính xác thì đây là một đường trung bình động có trọng số khối lượng, gieo hạt tại điểm swing. Đường vì vậy luôn bám sát giá hơn VWAP thật rất nhiều.
- volBias mặc định 10 là mức cực nhạy: vì biến động được nâng lên luỹ thừa 10, chỉ cần ATR lệch khoảng ±25% so với trung bình là APT đã chạm sàn 5 hoặc trần 300. Nếu muốn chế độ thích ứng hoạt động mượt mà thay vì nhảy giữa hai cực, hãy thử volBias trong khoảng 0,5–2,0. Lưu ý mặc định useAdapt đang TẮT nên mặc định ra chart, ô này chưa có tác dụng gì.
- Nhãn đầu tiên trên chart không có chữ: lần đổi hướng đầu tiên, biến prev vẫn rỗng (na) nên mọi phép so sánh đều sai và chuỗi ký tự rơi vào nhánh mặc định là rỗng. Bạn sẽ thấy một nhãn màu trống chữ ở đầu vùng lịch sử — đây là hành vi bình thường, không phải lỗi hiển thị.
- Ô màu "Swing Labels" dễ hiểu ngược: tooltip ghi ô thứ nhất (highS) là "màu nhãn swing high/low" và ô thứ hai (lowS) là "màu nhãn swing low". Thực tế trong code, highS được dùng khi neo vào ĐÁY (dir=+1) và lowS khi neo vào ĐỈNH — tức đúng theo nghĩa "xanh cho tín hiệu tăng, đỏ cho tín hiệu giảm", không phải theo loại pivot như tên biến gợi ý.
- Giới hạn lịch sử: vòng lặp dựng lại đường truy xuất dữ liệu lùi tới barsback nến, nên code khai báo max_bars_back = 5000. Nếu một nhịp kéo dài hơn 5000 nến mà không có điểm neo mới (rất hiếm, nhưng có thể xảy ra với prd lớn trên khung nhỏ có ít lịch sử), chỉ báo sẽ báo lỗi thay vì vẽ.
- Phụ thuộc hoàn toàn vào dữ liệu khối lượng: cả tử lẫn mẫu đều nhân với volume. Trên các mã không có volume (một số chỉ số, vài nguồn forex), mẫu số bằng 0 → chỉ báo trả về na và không vẽ được đường nào. Với forex/vàng, volume trên TradingView là tick volume (số lần giá thay đổi), không phải khối lượng thật — vẫn dùng được nhưng nên hiểu đúng bản chất.


