[TOC]

Với sự phát triển nhanh chóng của công nghệ trí tuệ nhân tạo (AI), nó đã chứng minh được hiệu quả và khả năng sáng tạo cực kỳ cao trong nhiều lĩnh vực. Là một lĩnh vực có tính kỹ thuật cao, giao dịch định lượng đương nhiên cũng đang tích cực khám phá ứng dụng của AI. Tuy nhiên, trên thực tế, chúng ta sẽ thấy rằng vẫn còn những thách thức lớn khi chỉ dựa vào AI để trực tiếp tạo ra các chiến lược giao dịch hoàn chỉnh, ổn định và có lợi nhuận bền vững.
Đặc biệt đối với người dùng mới trên nền tảng, do kỹ năng lập trình còn yếu nên họ khó có thể triển khai ý tưởng giao dịch của mình vào mã chiến lược. Mặc dù hiện tại chúng ta có thể nói với AI những ý tưởng của mình và để nó đưa ra các chiến lược. Tuy nhiên, hiệu quả thực hiện chưa thực sự như mong đợi. Tôi thường gặp những người dùng đến đặt câu hỏi với các mã do AI tạo ra và đôi khi tôi có thể nhìn thoáng qua các chiến lược do AI tạo ra. Vì vẫn còn nhiều vấn đề với các mã chiến lược do AI tạo ra ở giai đoạn này, nên việc sử dụng AI theo cách này không những không giải quyết được vấn đề nào mà còn gây thêm nhiều bối rối và vấn đề cho người mới bắt đầu. Càng tìm hiểu, tôi càng thấy bối rối và cuối cùng tôi đã “bỏ cuộc không muốn bắt đầu”.
Cá nhân tôi nghĩ rằng có hai lý do chính dẫn đến các vấn đề hiện tại với các chiến lược đầu ra trực tiếp của AI:
Vậy, có phương pháp ứng dụng nào hiệu quả hơn không? Bài viết này muốn chia sẻ một cách suy nghĩ mới: hãy để AI giúp chúng ta tìm hiểu các chiến lược hiện có, hiểu thiết kế chiến lược, trích xuất các chi tiết và kỹ thuật quan trọng, đồng thời phân tích sâu hơn về hiệu quả của chúng và khả năng cải thiện. Phương pháp này không chỉ giúp chúng ta nắm bắt được bản chất của thiết kế chiến lược nhanh hơn mà còn cải thiện trình độ giao dịch định lượng của chúng ta một cách có hệ thống.
Tận dụng AI, AI có thể hiểu tương đối chính xác về phân tích mã cụ thể, vì đối với AI, dữ liệu mã là “1 là 1, 2 là 2” và sẽ không có sự nhầm lẫn về mặt logic, mơ hồ hoặc các vấn đề khác do yêu cầu mô tả ngôn ngữ tự nhiên gây ra. Vậy tại sao không sử dụng những lợi thế của AI để giảm khối lượng công việc thủ công và phát huy tối đa những lợi thế của lao động thủ công.
Có thể chia thành các bước sau:
Chọn một chiến lược hiện có Có thể là tự viết, mã nguồn mở hoặc là mẫu chiến lược tuyệt vời trên nền tảng định lượng của nhà phát minh.
Hãy để AI giúp chúng ta giải thích chiến lược
Hiểu được ý tưởng chung
Sắp xếp các mô-đun chức năng của từng bộ phận
Làm rõ các chỉ số, thông số và logic giao dịch được sử dụng
Chiến lược này sẽ hoạt động tốt hơn trong điều kiện thị trường nào?
Những điểm rủi ro có thể xảy ra là gì?
Những lĩnh vực nào có thể được tối ưu hóa và cải thiện?
Kiểm tra ngược trên các sản phẩm khác nhau và các giai đoạn khác nhau
Thêm bộ lọc bổ sung hoặc biện pháp kiểm soát rủi ro
Quan sát những thay đổi về hiệu suất và hình thành hiểu biết của riêng bạn
Hãy để AI học một chiến lược và giải thích cho chúng ta để xem nó có đáp ứng được kỳ vọng của chúng ta hay không. Nó có thể giúp chúng ta học cách định lượng.
Thiết kế và triển khai chiến lược giao dịch tăng vị thế từng bước dựa trên lọc xu hướng EMA Địa chỉ chiến lược: https://www.fmz.com/strategy/492116
/*backtest
start: 2024-10-01 00:00:00
end: 2025-04-23 00:00:00
period: 1h
basePeriod: 1m
exchanges: [{"eid":"Futures_Binance","currency":"ETH_USDT"}]
args: [["targetProfit",20],["amount",20],["amountPrecision",3],["isAmountForUSDT",true]]
*/
function getTotalEquity_OKEX_V5() {
var totalEquity = null
var ret = exchange.IO("api", "GET", "/api/v5/account/balance", "ccy=USDT")
if (ret) {
try {
totalEquity = parseFloat(ret.data[0].details[0].eq)
} catch(e) {
Log("获取账户总权益失败!")
return null
}
}
return totalEquity
}
function getTotalEquity_Binance() {
var totalEquity = null
var ret = exchange.GetAccount()
if (ret) {
try {
totalEquity = parseFloat(ret.Info.totalWalletBalance)
} catch(e) {
Log("获取账户总权益失败!")
return null
}
}
return totalEquity
}
function getTotalEquity() {
var exName = exchange.GetName()
if (exName == "Futures_OKCoin") {
return getTotalEquity_OKEX_V5()
} else if (exName == "Futures_Binance") {
return getTotalEquity_Binance()
} else {
throw "不支持该交易所"
}
}
function ceilToDecimals(value, decimals) {
const factor = Math.pow(10, decimals);
return Math.ceil(value * factor) / factor;
}
function cancelAll() {
while (1) {
var orders = _C(exchange.GetOrders)
if (orders.length == 0) {
break
}
for (var i = 0 ; i < orders.length ; i++) {
exchange.CancelOrder(orders[i].Id, orders[i])
Sleep(interval)
}
Sleep(interval)
}
}
function trade(distance, price, amount) {
var tradeFunc = null
if (distance == "buy") {
tradeFunc = exchange.Buy
} else if (distance == "sell") {
tradeFunc = exchange.Sell
} else if (distance == "closebuy") {
tradeFunc = exchange.Sell
} else {
tradeFunc = exchange.Buy
}
exchange.SetDirection(distance)
return tradeFunc(price, amount)
}
function openLong(price, amount) {
return trade("buy", price, amount)
}
function openShort(price, amount) {
return trade("sell", price, amount)
}
function coverLong(price, amount) {
return trade("closebuy", price, amount)
}
function coverShort(price, amount) {
return trade("closesell", price, amount)
}
function plotRecords(c, buyOrder, sellOrder, pos) {
var bars = _C(exchange.GetRecords)
if (bars.length == 0) {
return
}
bars.forEach(function(bar, index) {
c.begin(bar)
if (index == bars.length - 1) {
if (buyOrder) {
c.hline(buyOrder.Price, "buy", "rgba(255, 0, 0, 0.2)", "dotted")
}
if (sellOrder) {
c.hline(sellOrder.Price, "sell", "rgba(0, 255, 0, 0.2)", "dotted")
}
if (pos && pos.length == 1) {
c.hline(pos[0].Price, "pos", "rgba(0, 0, 255, 0.2)", "dashed")
}
}
c.close()
})
}
var buyOrderId = null
var sellOrderId = null
var logStatusMsgBuff = ""
function main() {
var exName = exchange.GetName()
if (isSimulate && exName == "Futures_OKCoin") {
exchange.IO("simulate", true)
}
if (isReset) {
_G(null)
LogReset(1)
LogProfitReset()
LogVacuum()
Log("重置所有数据", "#FF0000")
}
exchange.SetContractType(contractType)
exchange.SetPrecision(pricePrecision, amountPrecision)
Log("设置精度", pricePrecision, amountPrecision)
exchange.SetMarginLevel(marginLevel)
if (totalEq == -1 && !IsVirtual()) {
var recoverTotalEq = _G("totalEq")
if (!recoverTotalEq) {
var currTotalEq = getTotalEquity()
if (currTotalEq) {
totalEq = currTotalEq
_G("totalEq", currTotalEq)
} else {
throw "获取初始权益失败"
}
} else {
totalEq = recoverTotalEq
}
}
var addCounter = _G("addCounter")
if (!addCounter) {
addCounter = 1
if (setAddCounter != -1) {
addCounter = setAddCounter
}
_G("addCounter", addCounter)
} else {
addCounter -= 1
}
let c = KLineChart({
overlay: true
})
var isLock = false
while (true) {
var ticker = _C(exchange.GetTicker)
var pos = _C(exchange.GetPosition)
if (pos.length > 1) {
Log(pos)
throw "同时有多空持仓"
}
var r = _C(exchange.GetRecords, 60 * 60)
var ema = TA.EMA(r, 60)
if (Math.abs(ticker.Last - ema[ema.length - 2]) / ema[ema.length - 2] > 0.03) {
cancelAll()
isLock = true
}
if (Math.abs(ticker.Last - ema[ema.length - 2]) / ema[ema.length - 2] < 0.02) {
isLock = false
}
if (isLock) {
LogStatus(_D(), "暂停, 检测阈值:", _N(Math.abs(ticker.Last - ema[ema.length - 2]) / ema[ema.length - 2], 3), logStatusMsgBuff)
plotRecords(c, null, null, pos)
Sleep(interval)
continue
}
var currentAcc = _C(exchange.GetAccount)
if (currentAcc.Balance < totalEq * reserve) {
throw "no money, stop"
}
if (addCounter > maxAddCounter) {
LogStatus(_D(), "加仓已达到上限", logStatusMsgBuff)
if (isMaxAddCounterClear && pos.length >= 1) {
Log("加仓已达到上限,撤单,清仓")
cancelAll()
if (pos[0].Type == PD_LONG) {
var coverId = coverLong(-1, pos[0].Amount)
} else if (pos[0].Type == PD_SHORT) {
var coverId = coverShort(-1, pos[0].Amount)
}
addCounter = 1
}
continue
}
if (pos.length == 0) {
if (!IsVirtual()) {
var currTotalEq = getTotalEquity()
if (currTotalEq) {
LogProfit(currTotalEq - totalEq, "当前总权益:", currTotalEq)
}
}
var tradeAmountLong = amount
var tradeAmountShort = amount
if (isAmountForUSDT) {
tradeAmountLong = ceilToDecimals(tradeAmountLong * 1.01 / (ticker.Last - targetProfit / 5) / oneCtValue, amountPrecision)
tradeAmountShort = ceilToDecimals(tradeAmountShort * 1.01 / (ticker.Last + targetProfit / 5) / oneCtValue, amountPrecision)
}
buyOrderId = openLong(ticker.Last - targetProfit / 5, tradeAmountLong)
sellOrderId = openShort(ticker.Last + targetProfit / 5, tradeAmountShort)
addCounter = 1
_G("addCounter", addCounter)
} else if (pos[0].Type == PD_LONG) {
var n = ratio
var price = ticker.Last
var addAmount = isDoubling ? pos[0].Amount : (isAmountForUSDT ? (ceilToDecimals(amount * 1.01 / (price - targetProfit * n) / oneCtValue, amountPrecision)) : amount)
buyOrderId = openLong(price - targetProfit * n, addAmount)
sellOrderId = coverLong(pos[0].Price + targetProfit, pos[0].Amount)
addCounter++
_G("addCounter", addCounter)
} else if (pos[0].Type == PD_SHORT) {
var n = ratio
var price = ticker.Last
var addAmount = isDoubling ? pos[0].Amount : (isAmountForUSDT ? (ceilToDecimals(amount * 1.01 / (price + targetProfit * n) / oneCtValue, amountPrecision)) : amount)
buyOrderId = coverShort(pos[0].Price - targetProfit, pos[0].Amount)
sellOrderId = openShort(price + targetProfit * n, addAmount)
addCounter++
_G("addCounter", addCounter)
}
if (!sellOrderId || !buyOrderId) {
cancelAll()
buyOrderId = null
sellOrderId = null
continue
}
while (1) {
var isFindBuyId = false
var isFindSellId = false
var orders = _C(exchange.GetOrders)
var buyOrder = null
var sellOrder = null
for (var i = 0 ; i < orders.length ; i++) {
if (buyOrderId == orders[i].Id) {
isFindBuyId = true
buyOrder = orders[i]
}
if (sellOrderId == orders[i].Id) {
isFindSellId = true
sellOrder = orders[i]
}
}
if (!isFindSellId && !isFindBuyId) {
cancelAll()
break
} else if (!isFindBuyId) {
Log("买单成交")
cancelAll()
break
} else if (!isFindSellId) {
Log("卖单成交")
cancelAll()
break
}
var acc = _C(exchange.GetAccount)
var tbl = {"type": "table", "title": "data", "cols": ["data", "symbol", "type", "price", "amount"], "rows": []}
if (buyOrder) {
tbl.rows.push(["订单", buyOrder.Symbol, buyOrder.Type == ORDER_TYPE_BUY ? "买入" : "卖出", buyOrder.Price, buyOrder.Amount])
}
if (sellOrder) {
tbl.rows.push(["订单", sellOrder.Symbol, sellOrder.Type == ORDER_TYPE_BUY ? "买入" : "卖出", sellOrder.Price, sellOrder.Amount])
}
if (pos && pos.length == 1) {
tbl.rows.push(["持仓", pos[0].Symbol, pos[0].Type == PD_LONG ? "多" : "空", pos[0].Price, pos[0].Amount])
}
logStatusMsgBuff = "当前权益:" + acc.Equity + ", 初始权益:" + totalEq + (!IsVirtual() ? ", 浮动盈亏:" + (acc.Equity - totalEq) : "") + ", 加仓次数:" + addCounter + "\n`" + JSON.stringify(tbl) + "`"
LogStatus(_D(), "当前权益:", acc.Equity, ", 初始权益:", totalEq, !IsVirtual() ? ", 浮动盈亏:" + (acc.Equity - totalEq) : "", ", 加仓次数:" + addCounter, "\n`" + JSON.stringify(tbl) + "`")
plotRecords(c, buyOrder, sellOrder, pos)
Sleep(interval)
}
Sleep(interval)
}
}
function onexit() {
Log("扫尾,撤销所有挂单")
cancelAll()
}
Đối với những người mới học nền tảng FMZ, việc nhìn thấy một đống mã như vậy có thể khiến bạn cảm thấy bối rối. Thay vì nghiên cứu từng dòng mã, chúng ta cũng có thể (lười biếng) và giao nó cho AI, để AI giải thích cho chúng ta và cải thiện hiệu quả học tập.
Tôi đang sử dụng GPT ở đây và nội dung sau đây được giải thích bằng AI:
A. Ghi chú Bài viết này sẽ giới thiệu chiến lược giao dịch tăng vị thế từng bước dựa trên phương pháp lọc xu hướng EMA (đường trung bình động theo cấp số nhân). Chiến lược này chủ yếu được sử dụng trên Binance Futures (Futures_Binance), hỗ trợ kiểm tra ngược 1 giờ và dựa trên tổng hợp dữ liệu K-line 1 phút. Bằng cách theo dõi thời gian thực độ lệch giữa giá và EMA, chiến lược này sẽ chuyển đổi chế độ giao dịch (giao dịch bình thường/giao dịch tạm dừng), tăng dần vị thế trong thị trường ổn định và tự động tạm dừng vị thế trong những biến động bất thường để tránh rủi ro.
flowchart TD
开始 --> 初始化参数
初始化参数 --> 账户余额检查
账户余额检查 --> 计算EMA
计算EMA --> 判断是否锁仓
判断是否锁仓 -->|是| 暂停交易
判断是否锁仓 -->|否| 正常交易
正常交易 --> 是否有持仓
是否有持仓 -->|无| 首次挂单
是否有持仓 -->|有| 按持仓方向加仓与止盈挂单
首次挂单 --> 等待成交
按持仓方向加仓与止盈挂单 --> 等待成交
等待成交 --> 挂单成交检测
挂单成交检测 --> 成交后调整
成交后调整 --> 更新加仓次数
更新加仓次数 --> 是否超出最大加仓次数
是否超出最大加仓次数 -->|是| 平仓
是否超出最大加仓次数 -->|否| 继续交易
Về các câu hỏi GPT:

Nội dung sau đây được giải thích bằng AI:
Trong chiến lược này, việc lọc xu hướng được thực hiện bằng cách:
var ema = TA.EMA(r, 60)
if (Math.abs(ticker.Last - ema[ema.length - 2]) / ema[ema.length - 2] > 0.03) {
cancelAll()
isLock = true
}
if (Math.abs(ticker.Last - ema[ema.length - 2]) / ema[ema.length - 2] < 0.02) {
isLock = false
}
if (isLock) {
LogStatus(_D(), "暂停, 检测阈值:", _N(Math.abs(ticker.Last - ema[ema.length - 2]) / ema[ema.length - 2], 3), logStatusMsgBuff)
plotRecords(c, null, null, pos)
Sleep(interval)
continue
}
Khóa và nhả xu hướng: Bằng cách so sánh sự khác biệt giữa giá hiện tại (ticker.Last) và giá trị EMA của giờ trước, tỷ lệ phần trăm giá lệch khỏi EMA sẽ được tính toán. Math.abs(ticker.Last - ema[ema.length - 2]) / ema[ema.length - 2] tính toán độ lệch phần trăm của giá hiện tại so với EMA của giờ trước. Nếu độ lệch vượt quá 3% (> 0,03), xu hướng thị trường được coi là đã thay đổi đáng kể và hàm cancelAll() được gọi để hủy tất cả các lệnh đang chờ xử lý và isLock được đặt thành true, tức là vị thế bị khóa, ngăn chặn giao dịch tiếp theo. Nếu giá lệch khỏi EMA nhỏ hơn 2% (< 0,02), trạng thái khóa sẽ được giải phóng và isLock được đặt thành false.
Tạm dừng giao dịch: Nếu isLock là đúng (cho biết vị thế hiện đang bị khóa), sẽ không có hoạt động giao dịch nào nữa được thực hiện. Chương trình sẽ xuất ra các bản ghi nhật ký và gọi plotRecords() để vẽ biểu đồ hiển thị xu hướng hiện tại và trạng thái vị trí. Sử dụng Sleep(interval) để tạm dừng trong một khoảng thời gian nhất định rồi tiếp tục vòng lặp.

Có vẻ như một số xu hướng có thể được lọc ra. Khi tự đọc mã, tôi thấy lời giải thích của AI rất rõ ràng, thậm chí còn rõ ràng hơn so với khi tôi tự giải thích.
Bằng cách để AI phân tích và giải thích chiến lược tổng thể, sau đó dựa trên lời giải thích của AI về chiến lược tổng thể, dần dần phân tích, phân tích và giải thích các chi tiết cục bộ của chiến lược và giải thích các ý tưởng thiết kế. Giải thích chúng tôi nhận được tương đối chính xác. AI đã liệt kê hầu như toàn bộ các chi tiết được thiết kế trong chiến lược mà không bỏ sót bất kỳ chi tiết nào và tiến hành phân tích chi tiết thông qua việc đặt thêm câu hỏi. Cách học toàn bộ tư duy chiến lược, chi tiết thiết kế mã và tăng cường kinh nghiệm thiết kế chiến lược này đều rất hữu ích.
Trên con đường giao dịch định lượng, AI có thể trở thành đối tác học tập và phát triển cực kỳ mạnh mẽ của chúng ta. Thay vì dựa vào AI để tạo ra các chiến lược hoàn thiện chỉ bằng một cú nhấp chuột, AI có thể:
Chỉ có con đường này mới có thể thực sự nâng cao khả năng giao dịch định lượng của chúng ta và thiết lập hệ thống giao dịch có hệ thống của riêng chúng ta. Trên Nền tảng giao dịch định lượng Inventor, chúng ta có thể tận dụng tối đa sức mạnh của AI và kết hợp nó với hoạt động thực tiễn của mình để tiến xa hơn và bay cao hơn.