
Tujuan artikel ini adalah untuk berbagi beberapa pengalaman dan kiat dalam pengembangan strategi, yang dapat memungkinkan pembaca untuk dengan cepat memahami pengalaman dalam pengembangan strategi perdagangan. Ketika menemui masalah terperinci serupa dalam desain strategi, solusi yang masuk akal dapat segera disusun. Platform Perdagangan Kuantitatif Inventor digunakan sebagai platform untuk penjelasan, pengujian, dan praktik. Bahasa pemrograman kebijakan: JavaScript Pasar perdagangan: pasar aset blockchain (BTC, ETH, dll.)
Biasanya, tergantung pada logika strategi, dimungkinkan untuk menggunakan antarmuka berbeda berikut untuk mendapatkan data pasar, karena logika perdagangan strategi biasanya didorong oleh data pasar (tentu saja, ada beberapa strategi yang tidak melihat pasar). , seperti strategi investasi tetap).
GetTicker: Dapatkan informasi tick secara real-time. Umumnya digunakan untuk mendapatkan harga terkini, harga beli, dan harga jual dengan cepat.
GetDepth: Dapatkan kutipan kedalaman buku pesanan. Umumnya digunakan untuk mendapatkan harga setiap level dan ukuran pesanan. Digunakan untuk strategi lindung nilai, strategi pembuatan pasar, dll.
GetTrade: Dapatkan catatan transaksi terbaru di pasar. Umumnya digunakan untuk menganalisis perilaku pasar dalam waktu singkat dan menganalisis perubahan mikro pasar. Biasanya digunakan dalam strategi frekuensi tinggi dan strategi algoritmik.
GetRecords: Dapatkan data K-line pasar. Sering digunakan dalam strategi mengikuti tren. Digunakan untuk menghitung indikator.
Saat merancang strategi, pemula biasanya mengabaikan berbagai situasi kesalahan dan secara intuitif percaya bahwa hasil setiap tautan dalam strategi telah ditentukan sebelumnya. Namun pada kenyataannya, hal ini tidak terjadi. Ketika meminta data pasar selama pengoperasian program strategi, berbagai situasi yang tidak terduga akan ditemui. Misalnya, beberapa antarmuka pasar mengembalikan data abnormal:
var depth = exchange.GetDepth()
// depth.Asks[0].Price < depth.Bids[0].Price 卖一价格低于了买一价格,这种情况不可能存在于盘面上,
// 因为卖出的价格低于买入的价格,必定已经成交了。
// depth.Bids[n].Amount = 0 订单薄买入列表第n档,订单量为0
// depth.Asks[m].Price = 0 订单薄卖出列表第m档,订单价格为0
Atau exchange.GetDepth() langsung mengembalikan nilai null.
Ada banyak situasi aneh seperti itu. Oleh karena itu, pemrosesan yang sesuai harus dilakukan untuk masalah-masalah yang dapat diperkirakan sebelumnya, dan jenis solusi pemrosesan ini disebut pemrosesan yang toleran terhadap kesalahan.
Pendekatan toleransi kesalahan yang umum adalah membuang data dan mengambilnya kembali.
Misalnya:
function main () {
while (true) {
onTick()
Sleep(500)
}
}
function GetTicker () {
while (true) {
var ticker = exchange.GetTicker()
if (ticker.Sell > ticker.Buy) { // 以 检测卖一价格是不是小于买一价这个错误的容错处理为例,
// 排除这个错误,当前函数返回 ticker 。
return ticker
}
Sleep(500)
}
}
function onTick () {
var ticker = GetTicker() // 确保获取到的 ticker 不会存在 卖一价格小于买一价格这种数据错误的情况。
// ... 具体的策略逻辑
}
Proses toleransi kesalahan lain yang dapat diperkirakan dapat ditangani dengan cara serupa. Prinsip desainnya adalah bahwa data yang salah tidak boleh digunakan untuk menggerakkan logika strategi.
Akuisisi data K-line, panggilan:
var r = exchange.GetRecords()
Data K-line yang diperoleh adalah sebuah array seperti ini:
[
{"Time":1562068800000,"Open":10000.7,"High":10208.9,"Low":9942.4,"Close":10058.8,"Volume":6281.887000000001},
{"Time":1562072400000,"Open":10058.6,"High":10154.4,"Low":9914.5,"Close":9990.7,"Volume":4322.099},
...
{"Time":1562079600000,"Open":10535.1,"High":10654.6,"Low":10383.6,"Close":10630.7,"Volume":5163.484000000004}
]
Anda dapat melihat bahwa setiap kurung kurawal{}Termasuk waktu, harga pembukaan (buka), harga tertinggi (tinggi), harga terendah (rendah), harga penutupan (tutup), dan volume perdagangan (volume).
Ini adalah tempat lilin. Secara umum, data K-line digunakan untuk menghitung indikator, seperti MA moving average, MACD, dan lain-lain.
Masukkan data K-line sebagai parameter (data bahan baku), lalu atur parameter indikator dan hitung fungsi data indikator, yang kami sebut fungsi indikator.
Ada banyak fungsi indikator pada Platform Perdagangan Kuantitatif Inventor.
Misalnya, saat kita menghitung indikator rata-rata bergerak, berdasarkan periode berbeda dari data garis K yang kita masukkan, kita menghitung rata-rata bergerak pada periode terkait. Misalnya, jika data garis K harian dilewatkan (satu batang garis K mewakili satu hari), indikator yang dihitung adalah rata-rata bergerak harian. Demikian pula, jika data garis K yang dilewatkan ke fungsi indikator rata-rata bergerak adalah periode 1 jam, maka indikator yang dihitung adalah rata-rata pergerakan 1 jam.
Biasanya ketika kita menghitung indikator, kita sering mengabaikan suatu masalah. Jika saya ingin menghitung indikator moving average 5 hari, maka pertama-tama kita siapkan data K-line harian:
var r = exchange.GetRecords(PERIOD_D1) // 给GetRecords 函数传入参数 PERIOD_D1就是指定获取日K线,
// 具体函数使用可以参看:https://www.fmz.com/api#GetRecords
Dengan data K-line harian, kita dapat menghitung indikator moving average. Jika kita ingin menghitung moving average 5 hari, kita perlu mengatur parameter indikator fungsi indikator ke 5.
var ma = TA.MA(r, 5) // TA.MA() 就是指标函数,用来计算均线指标,第一个参数设置刚才获取的日K线数据r,
// 第二个参数设置5,计算出来的就是5日均线,其它指标函数同理。
Kita telah mengabaikan masalah potensial. Bagaimana jika jumlah batang garis K dalam data garis K r-hari kurang dari 5? Dapatkah kita menghitung indikator rata-rata pergerakan 5 hari yang valid? Jawabannya tentu saja tidak. Karena indikator rata-rata bergerak adalah untuk menemukan rata-rata harga penutupan sejumlah batang garis K tertentu.

Oleh karena itu, sebelum menggunakan data K-line dan fungsi indikator untuk menghitung data indikator, perlu ditentukan apakah jumlah kolom K-line pada data K-line memenuhi persyaratan perhitungan indikator (parameter indikator).
Oleh karena itu, sebelum menghitung rata-rata pergerakan 5 hari, perlu dilakukan penilaian. Kode lengkapnya adalah sebagai berikut:
function CalcMA () {
var r = _C(exchange.GetRecords, PERIOD_D1) // _C() 是容错函数,目的就是避免 r 为 null , 具体可以查询文档:https://www.fmz.com/api#_C
if (r.length > 5) {
return TA.MA(r, 5) // 用均线指标函数 TA.MA 计算出均线数据,做为函数返回值,返回。
}
return false
}
function main () {
var ma = CalcMA()
Log(ma)
}

Pengujian ulang menunjukkan: [null,null,null,null,4228.7,4402.9400000000005, … ]
Dapat dilihat bahwa empat indikator rata-rata pergerakan 5 hari pertama yang dihitung adalah nol, karena jumlah kolom K-line kurang dari 5 dan rata-ratanya tidak dapat dihitung. Pada kandil ke 5, hal itu dapat dihitung.
Saat kita menulis beberapa strategi, sering kali terdapat skenario yang mengharuskan kita memproses beberapa operasi atau mencetak beberapa log saat setiap siklus K-line selesai. Bagaimana kita mencapai fungsi ini? Bagi pemula yang belum punya pengalaman pemrograman, mungkin mereka tidak bisa memikirkan mekanisme apa yang harus digunakan untuk mengatasinya. Berikut ini kami akan langsung memberikan beberapa tips.
Kita dapat menilai bahwa siklus kolom K-line telah selesai dengan memulai dengan atribut waktu pada data K-line. Setiap kali kita memperoleh data K-line, kita menilai atribut Waktu pada data kolom K-line terakhir. data K-line ini. Apakah nilai atribut ini telah berubah. Jika telah berubah, berarti kolom K-line baru telah dibuat (membuktikan bahwa siklus kolom K-line sebelumnya dari kolom K-line yang baru dibuat telah telah selesai). Jika belum berubah, berarti belum ada Candlestick baru dibuat (siklus candlestick terakhir saat ini belum selesai).
Jadi kita perlu variabel untuk mencatat waktu kolom kandil terakhir dari data kandil.
var r = exchange.GetRecords()
var lastTime = r[r.length - 1].Time // lastTime 用来记录最后一根K线柱的时间。
Dalam aplikasi praktis, strukturnya biasanya seperti ini:
function main () {
var lastTime = 0
while (true) {
var r = _C(exchange.GetRecords)
if (r[r.length - 1].Time != lastTime) {
Log("新K线柱产生")
lastTime = r[r.length - 1].Time // 一定要更新 lastTime ,这个至关重要。
// ... 其它处理逻辑
// ...
}
Sleep(500)
}
}

Dapat dilihat bahwa dalam backtest, periode K-line ditetapkan ke hari (fungsi exchange.GetRecords dipanggil tanpa menentukan parameter, dan periode K-line yang ditetapkan sesuai dengan backtest adalah parameter default). Setiap kali kolom K-line baru muncul, dicetaklah log A.
Jika Anda ingin menampilkan atau mengontrol waktu yang dibutuhkan suatu strategi untuk mengakses antarmuka bursa, Anda dapat menggunakan kode berikut:
function main () {
while (true) {
var beginTime = new Date().getTime()
var ticker = exchange.GetTicker()
var endTime = new Date().getTime()
LogStatus(_D(), "GetTicker() 函数耗时:", endTime - beginTime, "毫秒")
Sleep(1000)
}
}
Sederhananya, stempel waktu yang direkam setelah memanggil fungsi GetTicker dikurangi dari stempel waktu sebelum panggilan untuk menghitung jumlah milidetik yang telah berlalu, yaitu waktu yang dibutuhkan fungsi GetTicker untuk mengeksekusi dan mengembalikan hasilnya.
Jika Anda menginginkan batas atas numerik, Anda biasanya menggunakan Math.min untuk membatasi
Misalnya, saat menempatkan perintah jual, jumlah pesanan tidak boleh lebih besar dari jumlah koin di akun. Karena jika lebih besar dari jumlah koin yang tersedia di akun, akan terjadi kesalahan saat melakukan pemesanan.
Biasanya dikontrol seperti ini: Misalnya, Anda berencana untuk menempatkan pesanan jual sebesar 0,2 koin.
var planAmount = 0.2
var account = _C(exchange.GetAccount)
var amount = Math.min(account.Stocks, planAmount)
Ini memastikan bahwa jumlah pesanan yang akan dilakukan tidak melebihi jumlah koin yang tersedia di akun.
Demikian pula, Math.max digunakan untuk memastikan batas bawah suatu nilai. Biasanya hal ini berlaku pada skenario seperti apa? Umumnya, bursa memiliki batas jumlah pesanan minimum untuk pasangan perdagangan tertentu. Jika jumlah pesanan lebih rendah dari jumlah pesanan minimum ini, pesanan akan ditolak. Pesanan ini akan gagal. Asumsikan jumlah pesanan minimum untuk BTC biasanya 0,01. Terkadang strategi perdagangan mungkin menghitung bahwa jumlah pesanan kurang dari 0,01, jadi kita dapat menggunakan Math.max untuk memastikan jumlah pesanan minimum.
Bisa digunakan_Fungsi N() atau fungsi SetPrecision untuk mengontrol presisi.
Fungsi SetPrecision() hanya perlu ditetapkan satu kali, dan sistem akan secara otomatis memotong tempat desimal berlebih pada nilai kuantitas pesanan dan harga.
_Fungsi N() digunakan untuk memotong nilai ke sejumlah tempat desimal tertentu (kontrol presisi)
Misalnya:
var pi = _N(3.141592653, 2)
Log(pi)
Nilai pi dipotong menjadi 2 tempat desimal, yaitu: 3,14
Lihat dokumentasi API untuk detailnya.
Anda dapat menggunakan mekanisme ini untuk menggunakan metode deteksi cap waktu guna menentukan cap waktu saat ini dikurangi cap waktu terakhir tugas terjadwal diselesaikan, dan menghitung waktu yang telah berlalu secara real time. Ketika waktu yang telah berlalu melebihi durasi waktu tertentu yang ditetapkan Setelah itu , operasi baru dieksekusi.
Misalnya, dapat digunakan dalam strategi investasi tetap.
var lastActTime = 0
var waitTime = 1000 * 60 * 60 * 12 // 一天的毫秒数
function main () {
while (true) {
var nowTime = new Date().getTime()
if (nowTime - lastActTime > waitTime) {
Log("执行定投")
// ... 具体的定投操作,买入操作。
lastActTime = nowTime
}
Sleep(500)
}
}
Ini adalah contoh sederhana.
Dengan menggunakan fungsi _G() terkuantisasi milik penemu dan fungsi simpan keluar, sangatlah mudah untuk merancang strategi untuk keluar dan menyimpan kemajuan, dan memulai kembali untuk memulihkan status secara otomatis.
var hold = {
price : 0,
amount : 0,
}
function main () {
if (_G("hold")) {
var ret = _G("hold")
hold.price = ret.price
hold.amount = ret.amount
Log("恢复 hold:", hold)
}
var count = 1
while (true) {
// ... 策略逻辑
// ... 策略运行中,可能开仓,交易,把开仓的持仓价格赋值给 hold.price ,开仓的数量赋值给 hold.amount,用以记录持仓信息。
hold.price = count++ // 模拟一些数值
hold.amount = count/10 // 模拟一些数值
Sleep(500)
}
}
function onexit () { // 点击机器人上的停止按钮,会触发执行这个函数,执行完毕机器人停止。
_G("hold", hold)
Log("保存 hold:", JSON.stringify(hold))
}

Dapat dilihat bahwa setiap kali robot dihentikan, data dalam objek penahan disimpan. Setiap kali robot dihidupkan ulang, data dibaca dan nilai penahan dikembalikan ke keadaan saat robot berhenti sebelumnya. Tentu saja, contoh di atas adalah contoh sederhana. Jika digunakan dalam strategi yang sebenarnya, maka harus dirancang sesuai dengan data utama yang perlu dikembalikan dalam strategi (umumnya informasi akun, posisi, nilai keuntungan, arah perdagangan, dll.) .). Tentu saja, Anda juga dapat menetapkan beberapa kondisi untuk menentukan apakah akan memulihkan.
Di atas adalah beberapa kiat untuk mengembangkan strategi. Semoga bermanfaat bagi pemula dan pengembang strategi! Cara tercepat untuk berkembang adalah berlatih! Saya berharap Anda semua terus untung.