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

Mẫu chiến lược

Chiến lược hoàn chỉnh viết bằng signals, chạy được trong bảng Kiểm thử chiến lược và mở được sang Quant AI Studio. Thêm vào biểu đồ, xem mũi tên ▲ / ▼, rồi kiểm thử trên nhiều mã, nhiều kỳ (Bài 10) trước khi tin kết quả.

Chỉ để học

Các chiến lược dưới là ví dụ minh hoạ cách viết, không phải khuyến nghị đầu tư. Kết quả quá khứ không bảo đảm kết quả tương lai.

EMA 20/50 + lọc MA200​

Mẫu EMA 20/50 + lọc MA200 của thư viện — theo xu hướng: mua khi EMA 20 cắt lên EMA 50 và giá trên MA200, bán khi cắt xuống.

strategy({
name: "EMA 20/50 + lọc MA200",
description: "Mua khi EMA 20 cắt lên EMA 50 và giá trên MA200; bán khi EMA 20 cắt xuống. Dừng lỗ 7 %, dừng lỗ kéo theo 10 %.",
params: {
fast: param.int(20, { min: 5, max: 100, label: "EMA nhanh" }),
slow: param.int(50, { min: 10, max: 300, label: "EMA chậm" }),
},
signals: (d, p) => {
const f = ta.ema(d.close, p.fast), s = ta.ema(d.close, p.slow);
return { entry: f.crossAbove(s).and(d.close.gt(ta.sma(d.close, 200))), exit: f.crossBelow(s) };
},
plot: (d, p) => ({
[`EMA ${p.fast}`]: line(ta.ema(d.close, p.fast), { color: "accent" }),
[`EMA ${p.slow}`]: line(ta.ema(d.close, p.slow), { color: "ref" }),
}),
risk: { stopLoss: 0.07, trailingStop: 0.1 },
});

RSI hồi về trung bình​

Mẫu RSI hồi về trung bình của thư viện — mua nhịp điều chỉnh ngắn trong xu hướng tăng dài.

strategy({
name: "RSI hồi về trung bình",
description: "Mua khi RSI 2 dưới 10 trong xu hướng tăng (giá trên MA200); bán khi RSI 2 trên 70.",
params: {
len: param.int(2, { min: 2, max: 14, label: "Chu kỳ RSI" }),
buy: param.int(10, { min: 1, max: 40, label: "Mua dưới" }),
sell: param.int(70, { min: 50, max: 99, label: "Bán trên" }),
},
signals: (d, p) => {
const r = ta.rsi(d.close, p.len);
return { entry: r.lt(p.buy).and(d.close.gt(ta.sma(d.close, 200))), exit: r.gt(p.sell) };
},
risk: { stopLoss: 0.08 },
});

Turtle: vượt đỉnh 55, thoát đáy 20​

Quy tắc kinh điển của "nhà giao dịch rùa": mua khi giá vượt đỉnh 55 nến, thoát khi thủng đáy 20 nến; dừng lỗ theo ATR được thay bằng dừng lỗ kéo theo %.

strategy({
name: "Turtle Donchian 55 / 20",
params: {
vao: param.int(55, { min: 20, max: 120, label: "Đỉnh n nến (vào)" }),
ra: param.int(20, { min: 5, max: 60, label: "Đáy n nến (ra)" }),
},
signals: (d, p) => ({
entry: d.close.gt(d.high.highest(p.vao).shift(1)),
exit: d.close.lt(d.low.lowest(p.ra).shift(1)),
}),
plot: (d, p) => ({
"Đỉnh vào": line(d.high.highest(p.vao).shift(1), { color: "up", step: true }),
"Đáy ra": line(d.low.lowest(p.ra).shift(1), { color: "down", step: true }),
}),
risk: { trailingStop: 0.15 },
});

Bollinger hồi về giữa dải​

Mua khi giá đóng cửa cắt lên dải dưới (bật lại sau khi thủng), bán khi chạm đường giữa; chỉ mua khi chưa có xu hướng giảm mạnh (ADX thấp).

strategy({
name: "Bollinger hồi về giữa dải",
params: {
n: param.int(20, { min: 10, max: 50, label: "Chu kỳ" }),
k: param.num(2, { min: 1.5, max: 3, step: 0.25, label: "Độ lệch chuẩn" }),
},
filter: (d) => ta.adx(d, 14).adx.lt(30),
signals: (d, p) => {
const bb = ta.bb(d.close, p.n, p.k);
return { entry: d.close.crossAbove(bb.lower), exit: d.close.crossAbove(bb.mid).or(d.close.lt(bb.lower.mul(0.95))) };
},
plot: (d, p) => {
const bb = ta.bb(d.close, p.n, p.k);
return { "Dải": band(bb.upper, bb.lower, { color: "accent", opacity: 0.08 }), "Giữa": line(bb.mid, { color: "accent", dash: "dash" }) };
},
risk: { stopLoss: 0.06, maxHoldBars: 20 },
});

MACD lọc theo xu hướng tuần​

Tín hiệu MACD ngày chỉ được lấy khi giá đóng cửa tuần đang trên trung bình 10 tuần (xu hướng tuần thuận).

strategy({
name: "MACD ngày, lọc xu hướng tuần",
signals: (d) => {
const m = ta.macd(d.close, 12, 26, 9);
const tuan = d.tf("1W");
const tuanTang = tuan.close.gt(ta.sma(tuan.close, 10));
return { entry: m.macd.crossAbove(m.signal).and(tuanTang), exit: m.macd.crossBelow(m.signal) };
},
risk: { stopLoss: 0.08, trailingStop: 0.12 },
});

Dùng SMA cho khung tuần thay vì EMA / MACD tuần: chỉ báo đệ quy (EMA, MACD, RSI) cần khởi động khoảng 20 × chu kỳ nến của khung đó — MACD tuần cần hơn 500 tuần (10 năm) lịch sử trước khi kiểm thử bắt đầu.

Supertrend theo xu hướng​

Mua khi Supertrend chuyển sang tăng, bán khi chuyển giảm. Đơn giản, ít tham số — điểm xuất phát tốt để tối ưu n và mult.

strategy({
name: "Supertrend theo xu hướng",
params: {
n: param.int(10, { min: 5, max: 30, label: "Chu kỳ ATR" }),
mult: param.num(3, { min: 1.5, max: 5, step: 0.5, label: "Hệ số ATR" }),
},
signals: (d, p) => {
const st = ta.supertrend(d, p.n, p.mult);
return { entry: st.dir.crossAbove(0), exit: st.dir.crossBelow(0) };
},
plot: (d, p) => {
const st = ta.supertrend(d, p.n, p.mult);
return { Supertrend: line(st.line, { width: 2, colors: [{ when: st.dir.gt(0), color: "up" }], color: "down" }) };
},
});

Bứt phá nền tích luỹ có khối lượng​

Nền tích luỹ: 30 nến gần nhất dao động hẹp (biên độ ≤ 15 %). Mua khi giá đóng cửa vượt đỉnh nền với khối lượng gấp 1,5 lần trung bình; bán khi thủng EMA 20.

strategy({
name: "Bứt phá nền tích luỹ",
params: {
n: param.int(30, { min: 10, max: 120, label: "Độ dài nền" }),
bienDo: param.pct(0.15, { min: 0.05, max: 0.3, label: "Biên độ nền tối đa" }),
kl: param.num(1.5, { min: 1, max: 4, step: 0.1, label: "KL gấp TB 20" }),
},
signals: (d, p) => {
const dinh = d.high.highest(p.n).shift(1);
const day = d.low.lowest(p.n).shift(1);
const nenHep = dinh.div(day).sub(1).lte(p.bienDo);
const klManh = d.volume.gt(ta.sma(d.volume, 20).shift(1).mul(p.kl));
return {
entry: nenHep.and(d.close.gt(dinh)).and(klManh),
exit: d.close.lt(ta.ema(d.close, 20)),
};
},
plot: (d, p) => ({
"Đỉnh nền": line(d.high.highest(p.n).shift(1), { color: "up", step: true, dash: "dash" }),
"Đáy nền": line(d.low.lowest(p.n).shift(1), { color: "down", step: true, dash: "dash" }),
}),
risk: { stopLoss: 0.07 },
});

Giao cắt vàng dài hạn​

MA 50 cắt lên MA 200 thì mua, cắt xuống thì bán. Ít giao dịch — kiểm thử nên dùng Toàn bộ lịch sử.

strategy({
name: "Giao cắt vàng MA 50 / 200",
signals: (d) => {
const f = ta.sma(d.close, 50);
const s = ta.sma(d.close, 200);
return { entry: f.crossAbove(s), exit: f.crossBelow(s) };
},
plot: (d) => ({ "MA 50": line(ta.sma(d.close, 50), { color: "ref" }), "MA 200": line(ta.sma(d.close, 200), { color: "ceil" }) }),
});

Bứt phá biến động (lệnh dừng)​

Đặt lệnh mua dừng ở giá đóng cửa + 0,5 ATR cho nến sau, chỉ khi xu hướng trung hạn tăng; lệnh không khớp thì hết hiệu lực sau 1 nến. Thoát khi giá thủng đáy 10 nến.

strategy({
name: "Bứt phá biến động bằng lệnh dừng",
params: { k: param.num(0.5, { min: 0.2, max: 1.5, step: 0.1, label: "Hệ số ATR" }) },
signals: (d, p) => ({
entry: d.close.gt(ta.ema(d.close, 50)),
stop: d.close.add(ta.atr(d, 14).mul(p.k)),
exit: d.close.lt(d.low.lowest(10).shift(1)),
}),
risk: { stopLoss: 0.05, maxHoldBars: 30 },
});

Hai đáy RSI (mua khi RSI tạo đáy cao hơn)​

Mua khi RSI vừa cắt lên 30 lần thứ hai trong 20 nến và đáy giá lần hai không thấp hơn đáy lần một quá 3 %; bán khi RSI trên 65.

strategy({
name: "Hai đáy RSI",
signals: (d) => {
const r = ta.rsi(d.close, 14);
const cat = r.crossAbove(30);
const lanTruoc = cat.shift(1).hold(20);
const dayTruoc = d.low.lowest(5).valueWhen(cat, 1);
const dayNay = d.low.lowest(5);
return {
entry: cat.and(lanTruoc).and(dayNay.gte(dayTruoc.mul(0.97))),
exit: r.gt(65),
};
},
risk: { stopLoss: 0.07, maxHoldBars: 25 },
});
  • cat.shift(1).hold(20) — đã có một lần cắt lên trong 21 nến trước nến này.
  • x.valueWhen(cat, 1) — giá trị của x ở lần cắt thứ hai gần nhất (0 là gần nhất, 1 là lần trước đó).