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

Chuyển từ Pine Script

Bạn đã quen viết chỉ báo bằng Pine Script trên TradingView? Trang này đối chiếu các khái niệm để bạn tự viết lại bằng FireAnt Script. FireAnt Terminal không chạy mã Pine; bạn viết lại theo bảng dưới, hoặc mô tả ý tưởng để Copilot viết giúp.

Khác biệt cốt lõi​

Pine ScriptFireAnt Script
Ngôn ngữNgôn ngữ riêngJavaScript + bộ hàm (ta, param, đầu ra)
Mô hình chạyCả script chạy lại ở mỗi nếnplot / signals chạy một lần, lắp phép trên cả chuỗi; logic theo nến viết riêng trong onBar
Phép trên chuỗiToán tử: close > open, a and bPhương thức: d.close.gt(d.open), a.and(b)
Lịch sử x[1]Cú pháp [ ]x.shift(1); trong onBar: ctx.bar(1).close, ctx.prev("x", 1), ctx.track("x").at(1)
Biến varGiữ qua các nếnstate: () => ({ … }) + onBar
naGiá trị đặc biệtNaN; điều kiện có 3 trạng thái (đúng / sai / chưa biết)
Nhìn trướcrequest.security(…, lookahead_on) có thể nhìn trướcKhông có cách nào đọc nến sau; khung lớn chỉ lấy nến đã đóng

Bảng đối chiếu nhanh​

PineFireAnt Script
indicator("Tên", overlay = true)indicator({ name: "Tên", pane: "price", plot: … })
strategy("Tên")strategy({ name: "Tên", signals: … })
input.int(14, "Chu kỳ", minval = 2)params: { len: param.int(14, { min: 2, label: "Chu kỳ" }) } → p.len
input.float, input.bool, input.string(options = …)param.num, param.bool, param.choice
input.source(close)param.choice("close", ["close", "open", "high", "low", "hl2", "hlc3", "ohlc4"]) + d.source(p.src)
input.price, input.timeparam.price(null), param.time(null) (chọn trên biểu đồ)
close, open, high, low, volume, hl2, hlc3, ohlc4d.close, d.open, …
bar_index, timed.index, d.time (ctx.i, ctx.time trong onBar)
a + b, a - b, a * b, a / ba.add(b), a.sub(b), a.mul(b), a.div(b)
a > b, a >= b, a == ba.gt(b), a.gte(b), a.eq(b)
a and b, a or b, not aa.and(b), a.or(b), a.fillna(0).not()
c ? x : yx.where(c, y); hằng: d.const(5).where(c)
nz(x, 0), na(x), fixnan(x)x.fillna(0), x.isNaN(), x.ffill()
ta.sma, ta.ema, ta.wma, ta.hma, ta.rma, ta.rsicùng tên: ta.sma(d.close, 20)
ta.macd(close, 12, 26, 9) → [m, s, h]ta.macd(d.close, 12, 26, 9) → { macd, signal, hist }
ta.bb(close, 20, 2)ta.bb(d.close, 20, 2) → { upper, mid, lower, pctB, width }
ta.atr(14), ta.supertrend(3, 10)ta.atr(d, 14), ta.supertrend(d, 10, 3) (thứ tự tham số khác; dir dương = tăng)
ta.stoch(close, high, low, 14)ta.stoch(d, 14, 3, 3).k
ta.highest(high, 20), ta.lowest(low, 20)d.high.highest(20), d.low.lowest(20)
ta.change(x, n), ta.roc(x, n)x.diff(n), ta.roc(x, n)
ta.crossover(a, b), ta.crossunder(a, b), ta.crossa.crossAbove(b), a.crossBelow(b), a.cross(b)
ta.barssince(c), ta.valuewhen(c, x, 0)c.barsSince(), x.valueWhen(c, 0)
ta.stdev(x, n), math.sum(x, n), ta.cum(x)x.rolling(n).std(), x.rolling(n).sum(), x.cumsum()
ta.vwma, ta.alma, ta.linreg, ta.cmo, ta.tsi…ta.run("vwma", …), ta.run("alma", …) — danh mục
plot(x, "Tên", color.blue, 2)"Tên": line(x, { color: "accent", width: 2 })
plot(…, style = plot.style_histogram / _columns / _area / _stepline / _circles)hist, columns, area, line(…, { step: true }), line(…, { points: "circles" })
plot(…, color = c ? color.green : color.red)line(x, { color: "down", colors: [{ when: c, color: "up" }] })
color.new(color.red, 70)"#F6465D4D" (hai số cuối là độ đục) hoặc opacity: 0.3
plotshape(c, style = shape.triangleup, location = location.belowbar)shape(c, { shape: "triangleUp", at: "below" })
plotchar(c, char = "★")shape(c, { char: "★" })
hline(70), fill(p1, p2)hline(70), fill("Tên 1", "Tên 2")
bgcolor(c ? color.green : na), barcolor(…)bgcolor(c, { color: "up" }), barcolor(c, { color: … })
plotcandle(o, h, l, c)candles({ open, high, low, close })
request.security(syminfo.tickerid, "W", close)d.tf("1W").close
alertcondition(c, "Tên", "Lời nhắn")alerts: (d, p) => ({ "Tên": { when: c, message: "Lời nhắn" } })
var x = 0 + x := x + 1state: () => ({ x: 0 }) + onBar: (ctx, s) => { s.x += 1; … }
label.new, line.new, box.new, table.newctx.draw.label, ctx.draw.line, ctx.draw.box, ctx.table (trong onBar)
log.info(…)ctx.log(…)
barstate.isconfirmed, barstate.isrealtimectx.closed, ctx.realtime
strategy.entry("L", strategy.long, when = c) / strategy.close("L", when = x)signals: (d) => ({ entry: c, exit: x })
strategy.exit(stop = …, limit = …, trail_percent = …)risk: { stopLoss, takeProfit, trailingStop } (tỷ lệ)
strategy(initial_capital, commission_value, pyramiding)portfolio: { capital, pyramiding }, costs: { fees }

Ví dụ 1 — đường trung bình và RSI​

//@version=5
indicator("RSI có mức", overlay = false)
len = input.int(14, "Chu kỳ", minval = 2)
r = ta.rsi(close, len)
plot(r, "RSI", color = r > 70 ? color.red : color.blue)
hline(70)
hline(30)

Ví dụ 2 — tín hiệu cắt nhau và cảnh báo​

//@version=5
indicator("EMA cắt", overlay = true)
f = ta.ema(close, 20)
s = ta.ema(close, 50)
plot(f)
plot(s)
up = ta.crossover(f, s)
plotshape(up, style = shape.triangleup, location = location.belowbar, color = color.green)
alertcondition(up, "EMA cắt lên", "EMA 20 cắt lên EMA 50")

Ví dụ 3 — biến var và đếm​

//@version=5
indicator("Đếm nến tăng")
var int dem = 0
dem := close > open ? dem + 1 : 0
plot(dem, style = plot.style_columns)

Riêng ví dụ này còn viết được không cần onBar: d.close.gt(d.open).fillna(0).not().barsSince() là số nến kể từ nến không tăng gần nhất.

Ví dụ 4 — dữ liệu khung tuần​

//@version=5
indicator("EMA tuần", overlay = true)
w = request.security(syminfo.tickerid, "W", ta.ema(close, 20))
plot(w)

d.tf("1W") chỉ lấy nến tuần đã đóng (như request.security tắt nhìn trước); trong tuần đang chạy, giá trị là của tuần trước. Muốn cả nến tuần đang chạy: d.tf("1W", { forming: true }).

Ví dụ 5 — chiến lược có dừng lỗ​

//@version=5
strategy("RSI 2", overlay = true, initial_capital = 100000000)
r = ta.rsi(close, 2)
if r < 10 and close > ta.sma(close, 200)
strategy.entry("L", strategy.long)
if r > 70
strategy.close("L")
strategy.exit("SL", "L", stop = strategy.position_avg_price * 0.92)

Kết quả kiểm thử sẽ khác TradingView vì FireAnt áp luật thị trường Việt Nam (T+2, lô 100, biên độ, trần / sàn, phí và thuế bán) và khớp lệnh ở giá mở cửa nến sau.

Những điểm hay vấp​

  • Quên đổi toán tử: close > open phải thành d.close.gt(d.open) — xem Lỗi thường gặp.
  • Mọi thứ không phải onBar: trong Pine dòng nào cũng chạy mỗi nến; trong FireAnt Script, code trong plot chạy một lần. if trong plot rẽ nhánh khi dựng (theo tham số), không theo từng nến — điều kiện theo nến viết bằng .where() hoặc trong onBar.
  • Thứ tự tham số khác: ta.supertrend(d, chuKy, heSo) (Pine: hệ số trước), ta.atr(d, n) nhận d.
  • Thang của một số chỉ báo khác: TSI của thư viện nhân 100; chiều Supertrend ngược dấu với Pine.
  • Mảng, kiểu tự định nghĩa, thư viện (import) không có — dùng mảng JavaScript trong state, hàm JavaScript.