
Tujuan artikel ini adalah untuk berkongsi beberapa pengalaman dan petua dalam pembangunan strategi, yang membolehkan pembaca memahami dengan cepat pengalaman dalam pembangunan strategi perdagangan. Apabila menghadapi masalah terperinci yang serupa dalam reka bentuk strategi, penyelesaian yang munasabah boleh segera difikirkan. Platform Dagangan Kuantitatif Inventor digunakan sebagai platform untuk penjelasan, ujian dan amalan. Bahasa pengaturcaraan dasar: JavaScript Pasaran dagangan: pasaran aset blockchain (BTC, ETH, dll.)
Biasanya, bergantung pada logik strategi, adalah mungkin untuk menggunakan antara muka yang berbeza berikut untuk mendapatkan data pasaran, kerana logik perdagangan strategi biasanya didorong oleh data pasaran (sudah tentu, terdapat beberapa strategi yang tidak melihat pasaran , seperti strategi pelaburan tetap).
GetTicker: Dapatkan maklumat tanda masa nyata. Ia biasanya digunakan untuk mendapatkan harga terkini semasa, harga beli dan harga jual dengan cepat.
GetDepth: Dapatkan petikan kedalaman buku pesanan. Ia biasanya digunakan untuk mendapatkan harga setiap peringkat dan saiz pesanan. Digunakan untuk strategi lindung nilai, strategi membuat pasaran, dsb.
GetTrade: Dapatkan rekod transaksi terkini dalam pasaran. Ia biasanya digunakan untuk menganalisis gelagat pasaran dalam tempoh masa yang singkat dan menganalisis perubahan mikro pasaran. Biasanya digunakan dalam strategi frekuensi tinggi dan strategi algoritma.
GetRecords: Dapatkan data K-line pasaran. Selalunya digunakan dalam strategi mengikuti trend. Digunakan untuk mengira penunjuk.
Apabila mereka bentuk strategi, orang baru biasanya mengabaikan pelbagai situasi ralat dan secara intuitif percaya bahawa keputusan setiap pautan dalam strategi telah ditentukan terlebih dahulu. Tetapi sebenarnya, ini tidak berlaku Apabila meminta data pasaran semasa operasi program strategi, pelbagai situasi yang tidak dijangka akan dihadapi. Contohnya, sesetengah antara muka pasaran mengembalikan data yang tidak normal:
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() terus mengembalikan nilai nol.
Terdapat banyak situasi pelik seperti itu. Oleh itu, pemprosesan yang sepadan mesti dilakukan untuk masalah yang boleh dijangka ini, dan penyelesaian pemprosesan jenis ini dipanggil pemprosesan toleran kesalahan.
Pendekatan toleransi kesalahan yang biasa adalah membuang data dan mendapatkannya semula.
Contohnya:
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 boleh diramal boleh dikendalikan dengan cara yang sama. Prinsip reka bentuk ialah data yang salah tidak boleh digunakan untuk memacu logik strategi.
Pemerolehan data K-line, hubungi:
var r = exchange.GetRecords()
Data K-line yang diperoleh ialah tatasusunan, 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 boleh melihat bahawa setiap pendakap kerinting{}Ia termasuk masa, harga pembukaan (terbuka), harga tertinggi (tinggi), harga terendah (rendah), harga tutup (tutup), dan volum dagangan (volume).
Ini adalah batang lilin. Secara amnya, data K-line digunakan untuk mengira penunjuk, seperti purata bergerak MA, MACD, dsb.
Masukkan data K-line sebagai parameter (data bahan mentah), kemudian tetapkan parameter penunjuk dan hitung fungsi data penunjuk, yang kita panggil fungsi penunjuk.
Terdapat banyak fungsi penunjuk pada Platform Dagangan Kuantitatif Pencipta.
Sebagai contoh, apabila kami mengira penunjuk purata bergerak, berdasarkan tempoh berbeza bagi data garis K yang kami lalui, kami mengira purata bergerak bagi tempoh yang sepadan. Sebagai contoh, jika data K-line harian dihantar (satu bar K-line mewakili satu hari), penunjuk yang dikira ialah purata bergerak harian Begitu juga, jika data garis K dihantar ke fungsi penunjuk purata bergerak tempoh 1 jam, maka penunjuk yang dikira ialah purata bergerak 1 jam .
Biasanya apabila kita mengira penunjuk, kita sering terlepas pandang jika saya ingin mengira penunjuk purata bergerak 5 hari, maka kita sediakan 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 boleh mengira penunjuk purata bergerak Jika kita ingin mengira purata bergerak 5 hari, kita perlu menetapkan parameter penunjuk fungsi penunjuk kepada 5.
var ma = TA.MA(r, 5) // TA.MA() 就是指标函数,用来计算均线指标,第一个参数设置刚才获取的日K线数据r,
// 第二个参数设置5,计算出来的就是5日均线,其它指标函数同理。
Kami telah terlepas pandang masalah yang berpotensi Bagaimana jika bilangan bar K-line dalam data K-line r-hari adalah kurang daripada 5 Bolehkah kita mengira penunjuk purata bergerak 5 hari? Jawapannya pasti tidak. Kerana penunjuk purata bergerak adalah untuk mencari purata harga penutupan sebilangan bar K-line tertentu.

Oleh itu, sebelum menggunakan data K-line dan fungsi penunjuk untuk mengira data penunjuk, adalah perlu untuk menentukan sama ada bilangan lajur K-line dalam data K-line memenuhi syarat untuk pengiraan penunjuk (parameter penunjuk)
Oleh itu, sebelum mengira purata bergerak 5 hari, adalah perlu untuk membuat pertimbangan Kod lengkap adalah seperti 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)
}

Pertunjukan ujian belakang: [null,null,null,null,4228.7,4402.9400000000005, … ]
Dapat dilihat bahawa empat yang pertama daripada penunjuk purata bergerak 5 hari yang dikira adalah batal, kerana bilangan lajur garis K kurang daripada 5 dan purata tidak boleh dikira. Dengan batang lilin ke-5, ia boleh dikira.
Apabila kita menulis beberapa strategi, selalunya terdapat senario sedemikian yang kita perlu memproses beberapa operasi atau mencetak beberapa log apabila setiap kitaran K-line selesai. Bagaimanakah kita mencapai fungsi ini? Bagi pemula yang tidak mempunyai pengalaman pengaturcaraan, mereka mungkin tidak dapat memikirkan mekanisme yang akan digunakan untuk menanganinya Di sini kami akan memberikan anda beberapa petua.
Kita boleh menilai bahawa kitaran lajur K-line dilengkapkan dengan bermula dengan atribut masa dalam data K-line Setiap kali kami memperoleh data K-line, kami menilai atribut Time dalam data lajur K-line yang terakhir daripada data K-line ini sama ada nilai atribut ini telah berubah Jika ia telah berubah, ini bermakna lajur K-line baharu telah dijana (membuktikan bahawa kitaran lajur K-line sebelumnya bagi lajur K-line yang baru dijana. telah selesai). Jika ia tidak berubah, ini bermakna tiada A candlestick baru dijana (kitaran candlestick terakhir semasa masih belum selesai).
Jadi kita memerlukan pembolehubah untuk merekodkan masa lajur batang lilin terakhir data batang lilin.
var r = exchange.GetRecords()
var lastTime = r[r.length - 1].Time // lastTime 用来记录最后一根K线柱的时间。
Dalam aplikasi praktikal, struktur 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)
}
}

Ia boleh dilihat bahawa dalam ujian belakang, tempoh K-line ditetapkan kepada hari (fungsi pertukaran.GetRecords dipanggil tanpa menentukan parameter, dan tempoh K-line yang ditetapkan mengikut ujian belakang ialah parameter lalai lajur K-line baharu muncul, ia dicetak A log.
Jika anda ingin memaparkan atau mengawal masa yang diambil untuk strategi mengakses antara muka pertukaran, anda boleh menggunakan kod 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)
}
}
Ringkasnya, cap masa yang direkodkan selepas memanggil fungsi GetTicker ditolak daripada cap masa sebelum panggilan untuk mengira bilangan milisaat yang telah berlalu, iaitu masa yang diperlukan untuk fungsi GetTicker untuk melaksanakan dan mengembalikan hasilnya.
Jika anda mahukan had atas berangka, anda biasanya menggunakan Math.min untuk mengehadkan
Contohnya, apabila membuat pesanan jual, jumlah pesanan mestilah tidak lebih besar daripada bilangan syiling dalam akaun. Kerana jika ia lebih besar daripada bilangan syiling yang tersedia dalam akaun, ralat akan dilaporkan semasa membuat pesanan.
Biasanya dikawal seperti ini: Sebagai contoh, anda bercadang untuk membuat pesanan jual untuk 0.2 syiling.
var planAmount = 0.2
var account = _C(exchange.GetAccount)
var amount = Math.min(account.Stocks, planAmount)
Ini memastikan jumlah itu, jumlah pesanan yang akan dibuat, tidak melebihi bilangan syiling yang tersedia dalam akaun.
Begitu juga, Math.max digunakan untuk memastikan had yang lebih rendah untuk sesuatu nilai. Apakah jenis senario yang biasanya digunakan untuk ini? Secara amnya, bursa mempunyai had kuantiti pesanan minimum untuk pasangan dagangan tertentu Jika kuantiti pesanan lebih rendah daripada kuantiti pesanan minimum ini, pesanan akan ditolak. Dengan cara ini pesanan akan gagal. Anggapkan bahawa kuantiti pesanan minimum untuk BTC biasanya 0.01. Kadangkala strategi dagangan mungkin mengira bahawa kuantiti pesanan adalah kurang daripada 0.01, jadi kami boleh menggunakan Math.max untuk memastikan kuantiti pesanan minimum.
Boleh digunakan_Fungsi N() atau fungsi SetPrecision untuk mengawal ketepatan.
Fungsi SetPrecision() hanya perlu ditetapkan sekali, dan sistem akan memotong lebihan tempat perpuluhan secara automatik dalam kuantiti pesanan dan nilai harga.
_Fungsi N() digunakan untuk memotong nilai kepada bilangan tempat perpuluhan tertentu (kawalan ketepatan)
Contohnya:
var pi = _N(3.141592653, 2)
Log(pi)
Nilai pi dipotong kepada 2 tempat perpuluhan, iaitu: 3.14
Lihat dokumentasi API untuk butiran.
Anda boleh menggunakan mekanisme ini untuk menggunakan kaedah pengesanan cap masa untuk menentukan cap masa semasa tolak cap masa kali terakhir tugas yang dijadualkan selesai, dan mengira masa berlalu dalam masa nyata Apabila masa berlalu melebihi tempoh masa yang ditetapkan , operasi baharu dilaksanakan.
Sebagai contoh, ia boleh digunakan dalam strategi pelaburan 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 mudah.
Menggunakan fungsi _G() terkuantisasi pencipta dan fungsi simpan keluar, adalah sangat mudah untuk mereka bentuk strategi untuk keluar dan menyimpan kemajuan, dan mulakan semula untuk memulihkan status secara automatik.
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))
}

Ia boleh dilihat bahawa setiap kali robot dihentikan, data dalam objek tahan disimpan Setiap kali ia dimulakan semula, data dibaca dan nilai tahan dipulihkan kepada keadaan pada hentian sebelumnya. Sudah tentu, di atas adalah contoh mudah Jika ia digunakan dalam strategi sebenar, ia harus direka mengikut data utama yang perlu dipulihkan dalam strategi (umumnya maklumat akaun, kedudukan, nilai keuntungan, arahan perdagangan, dll. .). Sudah tentu, anda juga boleh menetapkan beberapa syarat untuk menentukan sama ada untuk memulihkan.
Di atas ialah beberapa petua untuk membangunkan strategi, saya harap ia akan membantu pemula dan pembangun strategi. Cara terpantas untuk menambah baik adalah dengan berlatih! Saya doakan anda semua terus mendapat keuntungan.