[TOC]

Dengan perkembangan pesat teknologi kecerdasan buatan (AI), ia telah menunjukkan kecekapan dan kreativiti yang sangat tinggi dalam banyak bidang. Sebagai bidang yang sangat teknikal, perdagangan kuantitatif secara semula jadi juga aktif meneroka aplikasi AI. Walau bagaimanapun, dalam amalan, kami akan mendapati bahawa masih terdapat cabaran besar dalam bergantung sepenuhnya kepada AI untuk terus menjana strategi dagangan yang lengkap, stabil dan menguntungkan secara mampan.
Terutama untuk pengguna baharu di platform, disebabkan kemahiran pengaturcaraan mereka yang lemah, sukar untuk melaksanakan idea dagangan mereka ke dalam kod strategi. Walaupun pada masa ini kami boleh memberitahu AI idea kami dan membiarkannya mengeluarkan strategi. Walau bagaimanapun, kesan pelaksanaan tidak cukup memenuhi jangkaan. Saya sering menemui pengguna yang datang untuk bertanya soalan dengan kod yang dijana AI, dan kadangkala saya dapat melihat strategi yang dijana AI sepintas lalu. Kerana masih terdapat banyak masalah dengan kod strategi yang dihasilkan oleh AI pada peringkat ini, menggunakan AI dengan cara ini bukan sahaja tidak menyelesaikan sebarang masalah, tetapi juga membawa lebih banyak kekeliruan dan masalah kepada orang baru. Semakin saya belajar, semakin keliru saya, dan akhirnya saya “berputus asa daripada bermula”.
Saya secara peribadi berpendapat bahawa terdapat dua sebab utama masalah semasa dengan strategi keluaran langsung AI:
Jadi, adakah kaedah aplikasi lain yang lebih cekap? Artikel ini ingin berkongsi cara pemikiran baharu: benarkan AI membantu kami mempelajari strategi sedia ada, memahami reka bentuk strategi, mengekstrak butiran dan teknik utama serta menganalisis keberkesanan dan ruang untuk penambahbaikan. Kaedah ini bukan sahaja dapat membantu kami memahami intipati reka bentuk strategi dengan lebih cepat, tetapi juga secara sistematik meningkatkan tahap dagangan kuantitatif kami.
Mengambil kesempatan daripada AI, AI boleh mempunyai pemahaman yang agak tepat tentang analisis kod tertentu, kerana untuk AI, data kod ialah “1 ialah 1, 2 ialah 2” dan tidak akan ada kekeliruan logik, kekaburan atau masalah lain yang disebabkan oleh keperluan perihalan bahasa semula jadi. Jadi mengapa tidak menggunakan kelebihan AI untuk mengurangkan beban kerja manual dan memberikan permainan sepenuhnya kepada kelebihan buruh manual.
Ia boleh dibahagikan kepada langkah-langkah berikut:
Pilih strategi sedia ada Ia boleh ditulis sendiri, sumber terbuka atau sampel strategi yang sangat baik pada platform kuantitatif pencipta.
Biar AI membantu kami menerangkan strategi
Fahami idea keseluruhan
Susun modul berfungsi setiap bahagian
Jelaskan penunjuk, parameter dan logik dagangan yang digunakan
Di bawah keadaan pasaran apakah strategi menunjukkan prestasi yang lebih baik?
Apakah mata risiko yang mungkin?
Apakah bidang yang boleh dioptimumkan dan dipertingkatkan?
Ujian belakang pada produk dan tempoh yang berbeza
Tambahkan penapis tambahan atau langkah kawalan risiko
Perhatikan perubahan prestasi dan bentuk cerapan anda sendiri
Mari biarkan AI mempelajari strategi dan menerangkannya kepada kami untuk melihat sama ada ia memenuhi jangkaan kami. Ia boleh membantu kita mempelajari kuantifikasi.
Reka bentuk dan pelaksanaan strategi perdagangan meningkatkan kedudukan langkah demi langkah berdasarkan penapisan arah aliran EMA Alamat strategi: 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()
}
Bagi pelajar baharu platform FMZ, melihat timbunan kod sedemikian mungkin membuatkan anda berasa rugi. Daripada mempelajari kod baris demi baris, kami mungkin juga (malas) dan membuangnya kepada AI, biarkan AI menerangkannya kepada kami dan meningkatkan kecekapan pembelajaran.
Saya menggunakan GPT di sini, dan kandungan berikut dijelaskan oleh AI:
Gambaran ringkas Artikel ini akan memperkenalkan strategi perdagangan meningkatkan kedudukan langkah demi langkah berdasarkan penapisan arah aliran EMA (purata bergerak eksponen). Strategi ini digunakan terutamanya pada Binance Futures (Futures_Binance), menyokong ujian belakang 1 jam dan berdasarkan pengagregatan data K-line selama 1 minit. Dengan pemantauan masa nyata sisihan antara harga dan EMA, strategi menukar mod dagangan secara dinamik (dagangan biasa/dagangan yang digantung), secara beransur-ansur meningkatkan kedudukan dalam pasaran yang stabil dan secara automatik menggantung kedudukan dalam turun naik yang tidak normal untuk mengelakkan risiko.
flowchart TD
开始 --> 初始化参数
初始化参数 --> 账户余额检查
账户余额检查 --> 计算EMA
计算EMA --> 判断是否锁仓
判断是否锁仓 -->|是| 暂停交易
判断是否锁仓 -->|否| 正常交易
正常交易 --> 是否有持仓
是否有持仓 -->|无| 首次挂单
是否有持仓 -->|有| 按持仓方向加仓与止盈挂单
首次挂单 --> 等待成交
按持仓方向加仓与止盈挂单 --> 等待成交
等待成交 --> 挂单成交检测
挂单成交检测 --> 成交后调整
成交后调整 --> 更新加仓次数
更新加仓次数 --> 是否超出最大加仓次数
是否超出最大加仓次数 -->|是| 平仓
是否超出最大加仓次数 -->|否| 继续交易
Mengenai soalan GPT:

Kandungan berikut dijelaskan oleh AI:
Dalam strategi ini, penapisan arah aliran dicapai dengan:
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
}
Kunci arah aliran dan lepaskan: Dengan membandingkan perbezaan antara harga semasa (ticker.Last) dan nilai EMA jam sebelumnya, peratusan yang mana harga menyimpang daripada EMA dikira. Math.abs(ticker.Last - ema[ema.length - 2]) / ema[ema.length - 2] mengira peratusan sisihan harga semasa daripada EMA jam sebelumnya. Jika sisihan melebihi 3% (> 0.03), arah aliran pasaran dianggap telah berubah dengan ketara, dan fungsi cancelAll() dipanggil untuk membatalkan semua pesanan belum selesai, dan isLock ditetapkan kepada benar, iaitu kedudukan dikunci, menghalang dagangan selanjutnya. Jika harga menyimpang daripada EMA kurang daripada 2% (< 0.02), keadaan kunci dilepaskan dan isLock ditetapkan kepada palsu.
Penggantungan dagangan: Jika isLock adalah benar (menunjukkan bahawa kedudukan sedang dikunci), tiada operasi dagangan selanjutnya akan dilakukan. Program ini akan mengeluarkan rekod log dan memanggil plotRecords() untuk melukis carta untuk menunjukkan trend semasa dan status kedudukan. Gunakan Tidur(selang) untuk menjeda untuk tempoh masa tertentu dan kemudian teruskan gelung.

Nampaknya beberapa trend boleh ditapis. Dengan membaca kod itu sendiri, saya mendapati bahawa penjelasan AI adalah sangat jelas, malah lebih jelas daripada jika saya telah menerangkannya sendiri.
Dengan membiarkan AI menganalisis dan menerangkan strategi keseluruhan, dan kemudian berdasarkan penjelasan AI tentang strategi keseluruhan, menganalisis secara beransur-ansur, membuka dan menerangkan butiran tempatan strategi dan menerangkan idea reka bentuk. Penjelasan yang kami terima agak tepat. AI menyenaraikan hampir semua butiran yang direka dalam strategi tanpa ketinggalan, dan menjalankan analisis terperinci melalui penyoalan lanjut. Cara mempelajari keseluruhan pemikiran strategi, butiran reka bentuk kod dan meningkatkan pengalaman reka bentuk strategi ini semuanya sangat membantu.
Dalam perjalanan perdagangan kuantitatif, AI boleh menjadi rakan kongsi pembelajaran dan pertumbuhan yang sangat berkuasa untuk kami. Daripada bergantung pada AI untuk menjana strategi siap dengan satu klik, AI boleh:
Hanya laluan ini benar-benar boleh meningkatkan keupayaan perdagangan kuantitatif kami dan mewujudkan sistem perdagangan sistematik kami sendiri. Pada Platform Dagangan Kuantitatif Inventor, kami boleh menggunakan sepenuhnya kuasa AI dan menggabungkannya dengan amalan kami sendiri untuk pergi lebih jauh dan terbang lebih tinggi.