Đi tới nội dung chính
Chuyển tới nội dung chính

Bài 8 — Khung lớn hơn và dữ liệu khác

Bạn sẽ học: dùng nến tuần / tháng trên biểu đồ ngày, nến ngày trên biểu đồ phút, nến phút bên trong nến ngày, lịch phiên giao dịch, thông tin mã, nến của mã khác, dòng tiền chủ động; và biết dữ liệu nào có trên biểu đồ, dữ liệu nào chỉ có khi lọc rổ / trong Quant AI Studio.

8.1. Nến khung lớn: d.tf(...)​

d.tf("1W") là nến tuần của cùng mã, gióng về từng nến của biểu đồ. Nó có đủ open, high, low, close, volume… và dùng với mọi hàm như d:

indicator({
name: "EMA 20 tuần trên biểu đồ ngày",
pane: "price",
plot: (d) => {
const tuan = d.tf("1W");
return {
"EMA 20 tuần": line(ta.ema(tuan.close, 20), { color: "ai", width: 2, step: true }),
"Đỉnh tuần trước": line(tuan.high, { color: "up", dash: "dot", step: true }),
"Đáy tuần trước": line(tuan.low, { color: "down", dash: "dot", step: true }),
};
},
});

Chỉ nến khung lớn đã đóng. Giá trị của một tuần chỉ xuất hiện từ nến ngày cuối cùng của tuần đó (khi tuần đã đóng). Trong tuần đang diễn ra, tuan.high là đỉnh của tuần trước — không phải đỉnh "từ đầu tuần tới giờ" (vốn còn thay đổi). Nhờ vậy tín hiệu không vẽ lại.

Muốn thấy cả nến khung lớn đang hình thành (đỉnh từ đầu tuần tới nến hiện tại), thêm { forming: true }:

indicator({
name: "Đỉnh / đáy tuần đang chạy",
pane: "price",
plot: (d) => {
const tuan = d.tf("1W", { forming: true });
return {
"Đỉnh từ đầu tuần": line(tuan.high, { color: "up", step: true }),
"Đáy từ đầu tuần": line(tuan.low, { color: "down", step: true }),
};
},
});
KhungViết
Phút / giờ"1", "5", "15", "30", "60", "240"
Ngày, tuần, tháng, quý, năm"1D", "1W", "1M", "3M", "12M"

Khung trong d.tf phải lớn hơn và là bội số của khung biểu đồ: trên biểu đồ ngày dùng được "1W", "1M"; trên biểu đồ 15 phút dùng được "30", "60", "1D", "1W"… Khung nhỏ hơn báo lỗi d.tf("60") nhỏ hơn khung đang tính 1D — chưa hỗ trợ — muốn đọc nến nhỏ hơn bên trong mỗi nến, dùng d.ltf (8.5).

8.2. Lọc tín hiệu ngày theo xu hướng tuần​

Mẫu hay dùng: chỉ lấy tín hiệu của khung nhỏ khi khung lớn cùng chiều.

indicator({
name: "Tín hiệu ngày theo xu hướng tuần",
pane: "price",
plot: (d) => {
const tuan = d.tf("1W");
const tangTuan = tuan.close.gt(ta.ema(tuan.close, 10));
const nhanh = ta.ema(d.close, 10);
const cham = ta.ema(d.close, 30);
return {
"Xu hướng tuần tăng": bgcolor(tangTuan, { color: "up", opacity: 0.05 }),
"Mua (cùng xu hướng tuần)": shape(nhanh.crossAbove(cham).and(tangTuan), { at: "below", shape: "arrowUp", color: "up" }),
"Bỏ qua (ngược xu hướng)": shape(nhanh.crossAbove(cham).and(tangTuan.fillna(0).not()), { at: "below", shape: "circle", color: "textMuted", size: "s" }),
};
},
});

Nền xanh khi xu hướng tuần tăng; mũi tên chỉ ở tín hiệu cùng chiều

Chỉ báo của thư viện cũng tính được trên khung lớn: đối số thứ ba của ta.run là dữ liệu cần tính, ví dụ Supertrend tuần:

indicator({
name: "Supertrend tuần",
pane: "price",
plot: (d) => {
const st = ta.run("supertrend", { atr: 10, factor: 3 }, d.tf("1W"));
return {
"Supertrend tuần tăng": line(st.up, { color: "up", width: 2, step: true }),
"Supertrend tuần giảm": line(st.down, { color: "down", width: 2, step: true }),
};
},
});

8.3. Ghim khung tính của cả chỉ báo​

resolution: "1W" trong khai báo làm cả chỉ báo tính trên nến tuần dù biểu đồ đang ở khung nào (miễn khung biểu đồ nhỏ hơn):

indicator({
name: "RSI tuần",
resolution: "1W",
scale: { range: [0, 100], levels: [30, 70] },
plot: (d) => ({ "RSI tuần": line(ta.rsi(d.close, 14), { color: "ai", step: true }) }),
});

8.4. Biểu đồ trong ngày: mức của phiên trước, lịch phiên​

Trên biểu đồ phút / giờ, d.tf("1D") cho cao / thấp / đóng của phiên trước (phiên đã đóng):

// khung: 15 (script cho biểu đồ trong ngày)
indicator({
name: "Mức của phiên trước",
pane: "price",
plot: (d) => {
const ngay = d.tf("1D");
return {
"Cao phiên trước": line(ngay.high, { color: "up", dash: "dash", step: true }),
"Thấp phiên trước": line(ngay.low, { color: "down", dash: "dash", step: true }),
"Đóng phiên trước": line(ngay.close, { color: "ref", dash: "dot", step: true }),
};
},
});

d.session cho biết vị trí của nến trong phiên (giờ của sàn, UTC+7):

ChuỗiGiá trị
d.session.first1 ở nến đầu tiên của mỗi phiên
d.session.last1 ở nến cuối của phiên (nến ngày, nến 60 phút; khung nhỏ hơn dùng d.session.minute.gte(14 * 60 + 30))
d.session.minutePhút trong ngày: 9:15 → 555, 14:30 → 870
d.session.weekdayThứ trong tuần: 0 = Chủ nhật, 1 = thứ Hai … 6 = thứ Bảy
d.session.daySố ngày kể từ 01/01/1970

Ví dụ biên độ 30 phút đầu phiên (opening range): ghi nhớ cao / thấp của các nến trước 9:45 rồi kẻ hai mức tới hết phiên.

// khung: 15 (script cho biểu đồ trong ngày)
indicator({
name: "Biên độ 30 phút đầu phiên",
pane: "price",
series: (d) => ({ phut: d.session.minute, dau: d.session.first }),
state: () => ({ cao: NaN, thap: NaN }),
onBar: (ctx, s) => {
if (ctx.v.dau === 1) {
s.cao = ctx.high;
s.thap = ctx.low;
} else if (ctx.v.phut < 9 * 60 + 45) {
s.cao = Math.max(s.cao, ctx.high);
s.thap = Math.min(s.thap, ctx.low);
}
return { cao: s.cao, thap: s.thap };
},
plot: (d, p, o) => ({
"Cao 30 phút đầu": line(o.cao, { color: "up", step: true }),
"Thấp 30 phút đầu": line(o.thap, { color: "down", step: true }),
"Vượt lên": shape(d.close.crossAbove(o.cao).and(d.session.minute.gte(9 * 60 + 45)), { at: "below", shape: "triangleUp", color: "up" }),
}),
});

8.5. Nến nhỏ bên trong mỗi nến: d.ltf(...)​

d.ltf("1") là các nến 1 phút nằm trong từng nến của biểu đồ (như request.security_lower_tf của Pine). Chuỗi của nó tính theo từng nến phút; muốn đưa về nến của biểu đồ thì gộp: m.sum(x), m.mean(x), m.max(x), m.min(x), m.first(x), m.last(x), m.count()… Ví dụ trên biểu đồ ngày, phần khối lượng của các phút tăng giá trong phiên: m.sum(m.volume.where(m.close.gt(m.open), 0)).div(m.sum(m.volume)).

Biểu đồ tự nạp nến phút cho script, tối đa khoảng 150.000 nến (với nến 1 phút ≈ 555 phiên gần nhất); nến ngày cũ hơn không có nến phút — phép gộp ra NaN. Đủ phép gộp và cách dùng trong onBar: Tham chiếu › d.ltf.

8.6. Thông tin mã và khung​

Thuộc tínhNghĩa
d.info.symbolMã đang tính ("FPT")
d.info.exchange, d.info.typeSàn, loại mã ("stock", "index", "future"…) khi biểu đồ có thông tin này
d.resolutionKhung đang tính ("1D", "15"…)
ctx.symbol, ctx.resolutionNhư trên, trong onBar

Dùng để đặt tên đầu ra hoặc chọn tham số theo khung, ví dụ chu kỳ dài hơn khi xem nến phút:

indicator({
name: "MA theo khung",
pane: "price",
plot: (d) => {
const trongNgay = !["1D", "1W", "1M"].includes(d.resolution);
const n = trongNgay ? 60 : 20;
return { [`MA ${n} (${d.resolution})`]: line(ta.sma(d.close, n), { color: "accent" }) };
},
});

8.7. Mã khác, dòng tiền chủ động, dữ liệu Quant​

Ngôn ngữ có sẵn cách đọc dữ liệu ngoài nến giá của mã đang xem — cùng tên với Quant AI Studio. Không phải dữ liệu nào cũng có trên biểu đồ:

ViếtDữ liệuTrên biểu đồ
d.symbol("VNINDEX").close, d.bench.closeNến của mã khác (tối đa 4 mã mỗi script), VNINDEX — gióng theo nến đang xemCó — biểu đồ tự nạp nến của mã đó
d.flow().delta, d.flow().cvd, d.footprint().poc…Dòng tiền chủ động: mua / bán chủ động, delta, CVD, footprint từng nếnCó, Chuyên nghiệp
d.fin("ROE", { ttm: true })Chỉ tiêu báo cáo tài chính theo ngày công bốKhông
d.macro("cpi_yoy")Chuỗi vĩ mô theo ngày công bốKhông
d.foreignNet, d.propNet, d.pe, d.pb, d.roe…Trường dữ liệu của Quant (khối ngoại, tự doanh, định giá, BCTC…)Không

So mã đang xem với VNINDEX — hoặc với bất kỳ mã nào bạn chọn ở cột Tham số:

// dữ liệu Quant không cần: d.symbol, d.bench tự nạp nến trên biểu đồ
indicator({
name: "Sức mạnh so với mã khác",
params: { ma: param.symbol("VNINDEX", { label: "So với mã" }) },
plot: (d, p) => {
const rs = d.close.div(d.symbol(p.ma).close);
const rsTb = ta.sma(rs, 50);
return {
"Tỷ lệ giá / mã so sánh": line(rs, { color: "accent" }),
"TB 50 phiên": line(rsTb, { color: "ref", dash: "dash" }),
"Mạnh lên": shape(rs.crossAbove(rsTb), { at: "bottom", shape: "triangleUp", color: "up" }),
};
},
});

d.symbol(p.ma) lấy nến của mã trong ô So với mã; giá trị ở mỗi nến là giá trị đã biết gần nhất của mã đó (không nhìn trước). Đổi ô sang VN30, HPG… là script tính lại. Script dùng d.symbol chạy trên biểu đồ một mã, không dùng để lọc rổ (d.bench thì được).

Dòng tiền chủ động Chuyên nghiệp — khớp lệnh có chiều mua / bán, như chỉ báo Volume Delta, CVD và kiểu biểu đồ Footprint (Dòng tiền chủ động):

// dữ liệu Quant không cần: d.flow đọc khớp lệnh có chiều của biểu đồ (gói Chuyên nghiệp)
indicator({
name: "Mua bán chủ động",
plot: (d) => {
const f = d.flow();
return {
"Delta (mua − bán chủ động)": hist(f.delta, { up: "up", down: "down" }),
"CVD": line(f.cvd, { color: "accent", pane: "CVD" }),
};
},
});

Các trường: Tham chiếu › d.flow, d.footprint. Lịch sử khớp lệnh theo giá có từ ngày FireAnt bắt đầu lưu; nến cũ hơn là số ước lượng từ lệnh lớn (f.exact = 0). Thiếu gói thì các chuỗi này trống.

BCTC, vĩ mô, khối ngoại: chưa có trên biểu đồ

Đường dùng d.fin, d.macro hay trường Quant (khối ngoại, tự doanh, định giá…) trống trên biểu đồ (chú giải ghi —). Các dữ liệu này dùng được khi:

  • Lọc bằng script trên một rổ có tên (VN30, HOSE…) — chạy bằng dữ liệu của Quant AI Studio;
  • Mở trong Quant AI Studio — chiến lược / bộ lọc chạy trên cả rổ.

Ví dụ và cách viết ở Bài 12; danh sách trường ở Quant AI Studio › Dữ liệu và Panel. Trên biểu đồ, chỉ báo dựng sẵn trong thư viện chỉ báo (khối ngoại, P/E, ROE…) vẫn có các dữ liệu này — Chỉ báo dữ liệu FireAnt.

Bài tập​

Trên biểu đồ ngày, tô nền xanh khi RSI 14 của nến tuần trên 50 và RSI 14 ngày trên 50; đỏ khi cả hai dưới 50.

Lời giải
indicator({
name: "RSI ngày và tuần cùng chiều",
pane: "price",
plot: (d) => {
const rTuan = ta.rsi(d.tf("1W").close, 14);
const rNgay = ta.rsi(d.close, 14);
return {
"Cùng tăng": bgcolor(rTuan.gt(50).and(rNgay.gt(50)), { color: "up", opacity: 0.08 }),
"Cùng giảm": bgcolor(rTuan.lt(50).and(rNgay.lt(50)), { color: "down", opacity: 0.08 }),
};
},
});

Tiếp theo: Bài 9 — Chiến lược đầu tiên