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

Viết code (SDK)

Mỗi chiến lược, bộ lọc, phân tích trong Quant AI Studio là một đoạn JavaScript gọi bộ hàm của Studio (SDK). Bạn không cần biết lập trình để dùng Studio — mẫu có sẵn và trợ lý Quant viết code cho bạn — nhưng đọc được code giúp hiểu chính xác chiến lược mua bán thế nào, và sửa code là cách nhanh nhất để đổi một ngưỡng, một điều kiện mà không phải mô tả lại cho trợ lý.

Code chạy ngay trong trình duyệt của bạn, trong một vùng cách ly: không truy cập mạng, cookie hay dữ liệu của trang; dữ liệu chỉ đến qua tham số d hoặc data.bars(…) do Studio nạp.

Code nằm ở tab Mã của mỗi mục (chiến lược, bộ lọc, phân tích): khung soạn có tô màu cú pháp, gợi ý hàm, nút Tài liệu SDK (bảng tra hàm ngay trong Studio), Lưu, Chạy và Nhật ký chạy. Từng nút, phiên bản và So sánh được mô tả ở Xem và sửa mã; trang này và các trang con nói về cách viết code.

Ba loại: chiến lược, bộ lọc, phân tích​

strategy({
name: "RSI hồi phục · VN30",
universe: universe("VN30"),
period: { from: "2016-01-01" },
params: {
len: param.int(14, { min: 2, max: 30, label: "Chu kỳ RSI" }),
lower: param.num(30, { min: 10, max: 45, label: "Ngưỡng mua" }),
stop: param.pct(0.07, { min: 0.03, max: 0.2, label: "Cắt lỗ" }),
},
signals: (d, p) => {
const r = ta.rsi(d.close, p.len);
const trend = d.close.gt(ta.sma(d.close, 200));
return { entry: r.crossAbove(p.lower).and(trend), exit: r.gt(70), score: r.neg() };
},
portfolio: { maxPositions: 5 },
risk: (p) => ({ stopLoss: p.stop }),
});

Backtest: mua mã VN30 khi RSI(14) cắt lên 30 trong xu hướng tăng, bán khi RSI > 70 hoặc cắt lỗ 7%, tối đa 5 mã. Xem Chiến lược.

Cấu trúc một đoạn code​

  • JavaScript thuần (ES2022): không import, không TypeScript. Dòng export default (quen tay khi viết module) được bỏ qua.
  • Gọi đúng một lần strategy({…}), screen({…}) hoặc research(…). Phía trên lời gọi được khai báo hằng số, hàm phụ (ví dụ const lnst = (d, ago) => d.fin("ParentCompanyShareholderProfitAfterTax", { ago });).
  • Các tên có sẵn, không cần khai báo:
TênDùng để
strategy, screen, researchKhai báo chiến lược, bộ lọc, phân tích
universeChọn rổ mã: universe("HOSE").liquid(10e9).top(240)
paramKhai báo tham số thành thanh trượt, công tắc, ô chọn
taChỉ báo kỹ thuật: ta.rsi, ta.macd, ta.atr…
statsThống kê trên mảng số: trung bình, tương quan, hồi quy, sụt giảm…
datesĐổi qua lại ngày dạng chữ và số ngày
PanelTự dựng bảng dữ liệu mã × phiên
logIn giá trị ra Nhật ký chạy
byYearMonth, monthOfYearMeanDựng bảng năm × tháng, trung bình theo tháng trong năm
  • Đơn vị: giá theo nghìn đồng (57,3 = 57.300 đ); giá trị theo đồng (10 tỷ viết 10e9); tỷ lệ là số thập phân (0,07 = 7%).
  • Tính trên cả bảng, không lặp từng phiên. Mỗi trường dữ liệu là một Panel — bảng mã × phiên. Phép tính áp cho cả bảng cùng lúc (d.close.gt(ta.sma(d.close, 200))): nhanh hơn vòng lặp nhiều lần và không vô tình đọc dữ liệu tương lai.

Một lần chạy diễn ra thế nào​

  1. Biên dịch phần khai báo (tối đa 5 giây) → tên, tham số, rổ mã. Lỗi cú pháp dừng ở đây.
  2. Xác định rổ mã (dòng tiến độ Xác định rổ mã): danh sách mã, rổ theo thời điểm khi backtest, cắt theo giới hạn số mã của gói.
  3. Biết code cần dữ liệu gì. Với chiến lược, bộ lọc: Studio chạy thử các hàm trên dữ liệu giả để biết code đọc những trường nào (khối ngoại, BCTC…) rồi chỉ tải phần đó. Với phân tích: bạn khai báo trong data.bars(…, { fields }).
  4. Nạp dữ liệu (Tải dữ liệu, Đọc dữ liệu n/N tệp, Đọc BCTC, sự kiện, Đọc dữ liệu vĩ mô…) từ kho dữ liệu, căn theo lịch phiên.
  5. Tính toán: tín hiệu (Tính tín hiệu), cột của bộ lọc (Tính bộ lọc) hoặc chạy hàm phân tích.
  6. Chiến lược: Kiểm tra nhìn trước tương lai, Mô phỏng danh mục theo luật khớp lệnh, Tính chỉ số.
  7. Hiện kết quả, kèm Ghi chú dữ liệu (rổ bị cắt, có nến tạm…) và Nhật ký chạy (dòng log(…) của code và gợi ý cho người viết code: biểu đồ trống, chuỗi vĩ mô thiếu số…).

Mỗi lần chạy dùng một vùng chạy mới rồi huỷ, nên vòng lặp vô hạn không làm treo trang. Math.random() có hạt giống cố định và cách sắp xếp giống nhau trên mọi trình duyệt: cùng code, cùng dữ liệu luôn cho cùng kết quả.

Giới hạn​

Giới hạnMức
Thời gian một lần chạy2 phút (tối ưu tham số, kiểm định: 5 phút); quá thì dừng với lỗi Chạy quá thời gian
Số mã mỗi lần chạy250 (Thiết yếu), 2.000 (Chuyên nghiệp, Cao cấp) — xem Giới hạn số mã
Khối đầu ra của phân tích60 khối; bảng 500 dòng; biểu đồ 30 chuỗi, mỗi chuỗi tự rút gọn còn 3.000 điểm; văn bản 20.000 ký tự
Bộ lọcTối đa 500 dòng kết quả (mặc định 100)
Nhật ký chạy1.000 dòng, mỗi dòng 2.000 ký tự
Môi trườngKhông mạng, không fetch, không lưu trữ trình duyệt, không import

Sửa và chạy code​

Chuyên nghiệp Gói Thiết yếu xem được code (khung có dải Chỉ xem code), chạy mẫu và đổi tham số; sửa code, tự viết hay nhập mục từ tệp cần gói Chuyên nghiệp.

  1. Mở một mục (từ tab Của tôi của thanh bên, hoặc chạy một mẫu), chọn tab Mã.
  2. Sửa trực tiếp. Gõ ta., d., param., stats., chart.… để hiện gợi ý kèm cách dùng; lỗi cú pháp được gạch đỏ ngay khi gõ, rê chuột để xem Lỗi cú pháp: …. Ctrl+F (macOS Cmd+F) tìm trong code, Ctrl+Z (macOS Cmd+Z) hoàn tác.
  3. Ctrl+S (macOS Cmd+S) lưu thành phiên bản mới; Ctrl+Enter (macOS Cmd+Enter) lưu và chạy.
  4. Xem kết quả ở tab Báo cáo / Kết quả; giá trị trung gian in bằng log(…) hiện ở Nhật ký chạy.

Bản nháp, Bỏ thay đổi, thông báo Bản nháp dựa trên v… khi trợ lý vừa tạo phiên bản mới: xem Xem và sửa mã.

Đổi ngưỡng bằng tham số, không sửa số trong code

Ngưỡng nào bạn hay thử (chu kỳ RSI, mức cắt lỗ, số mã) hãy khai báo bằng param.*: thanh tham số đổi là chạy lại ngay, không tạo phiên bản mới, và tối ưu tham số dùng đúng khoảng min–max bạn khai báo.

Khi code lỗi​

Code lỗi thì kết quả hiện khung lỗi: loại lỗi, dòng, thông báo, vài dòng code quanh chỗ lỗi, nút Nhờ Copilot sửa và Xem dòng N (mở tab Mã đúng dòng lỗi). Các loại lỗi và cách xử lý chung: Lỗi khi chạy. Lỗi Dùng dữ liệu tương lai thường do shift với số âm hoặc thống kê trên cả chuỗi — xem Tránh nhìn trước tương lai.

Thông báo riêng của code hay gặp (thông báo về dữ liệu, máy chủ ở trang trên):

Thông báoNghĩa
Code chưa gọi strategy({...}), screen({...}) hay research(...)Thiếu lời gọi khai báo
Mỗi đoạn code chỉ khai báo một strategy / screen / researchGọi hai lần trong một đoạn code
strategy cần một trong: signals(d, p), rank(d, p) hoặc weights(d, p)Chiến lược thiếu cách chọn mã
signals(d, p) phải trả về Panel hoặc { entry, exit?, score? }Hàm tín hiệu trả sai kiểu (thường quên return)
Không có trường dữ liệu "…". Các trường: …Gõ sai tên trường của d
Chưa nạp "…" — trong research thêm fields: ["…"] vào data.bars(…)Phân tích dùng trường chưa khai báo trong fields
Không có chỉ tiêu BCTC "…". Gần giống: …Sai khoá của d.fin; xem danh sách khoá
Không ghép được panel 30×2500 với 25×2500Hai Panel khác số mã — thường do lấy từ hai lần data.bars khác nhau
shift(n) với n âm dùng dữ liệu tương lai — không được phépshift(-1)
Rổ có … mã — gói hiện tại chạy tối đa 250 mã mỗi lần…Danh sách mã tự chọn vượt giới hạn

Tự viết hay nhờ trợ lý?​

Nên tự sửa code khiNên nhờ trợ lý Quant khi
Đổi một ngưỡng, một điều kiện đã biết rõ vị tríBiến một ý tưởng mô tả bằng lời thành code mới
Thêm tham số để kéo thử, để tối ưuĐổi cấu trúc (từ tín hiệu sang xoay vòng, thêm dữ liệu BCTC, vĩ mô)
Muốn kiểm soát chính xác từng dòng, giữ lịch sử phiên bản gọnSửa lỗi khó hiểu, giải thích kết quả, gợi ý cải tiến
Không muốn dùng hạn mức AITối ưu tham số, kiểm định độ vững theo câu hỏi

Hai cách dùng chung một mục: trợ lý sửa thì tạo phiên bản mới, bạn sửa tay cũng vậy — So sánh cho thấy từng thay đổi.

Đọc tiếp​

  • Dữ liệu và Panel — Mọi trường của d (giá, khối ngoại, BCTC, vĩ mô…), đơn vị, d.fin, d.macro và phép tính trên Panel. — Dữ liệu và Panel
  • Chiến lược — strategy({…}): tín hiệu, xoay vòng, tỷ trọng; danh mục, cắt lỗ, khớp lệnh, chi phí; ví dụ đầy đủ. — Chiến lược
  • Bộ lọc và phân tích — screen({…}) và research(…): cột, điều kiện, nạp dữ liệu, số liệu, biểu đồ, bảng, văn bản. — Bộ lọc và phân tích
  • Tham chiếu hàm — Bảng tra ta.*, phép tính Panel, universe, param, stats, dates, đầu ra của phân tích. — Tham chiếu hàm