Untuk pemula dalam merancang strategi, strategi hedging adalah strategi yang sangat baik untuk dipraktekkan. Artikel ini mengimplementasikan strategi hedging tunai mata uang digital yang sederhana namun praktis.
Pertama-tama, jelaskan bahwa strategi yang akan dirancang adalah strategi hedging mata uang digital, dan kami telah merancang hedging yang paling sederhana, hanya antara dua bursa mata uang yang menjual dengan harga yang lebih tinggi dan membeli dengan harga yang lebih rendah untuk mendapatkan perbedaan. Ketika semua bursa dengan harga yang lebih tinggi adalah mata uang (karena semua koin yang lebih tinggi telah dijual), maka tidak ada hedging untuk bursa dengan harga yang lebih rendah adalah semua koin (karena semua koin yang lebih rendah telah dibeli).
Harga, jumlah, dan batas presisi transaksi saat melakukan hedging. Selain batas minimum, strategi out-of-limit untuk melakukan hedging juga mempertimbangkan jumlah pesanan maksimum yang dapat dilakukan dalam satu hari, dan jika jumlah pesanan terlalu besar maka tidak akan ada jumlah pesanan yang cukup. Juga perlu dipertimbangkan bagaimana menggunakan konversi nilai tukar jika dua mata uang yang diperdagangkan berbeda.
Dengan mempertimbangkan hal-hal ini, strategi perlu dirancang dengan beberapa parameter:
hedgeDiffPrice
, Ketika perbedaan melebihi nilai ini, pemicu operasi hedging.minHedgeAmount
, jumlah unit minimum yang dapat di-hedge (jumlah koin) ⇒maxHedgeAmount
, jumlah unit maksimum dari suatu hedging (jumlah koin) ‖.pricePrecisionA
, A adalah presisi harga pesanan (digit kecil) ⇒amountPrecisionA
Perhitungan persatuan (persentase kecil) di bursa A.pricePrecisionB
Harga yang tepat (digit kecil) di bursa B.amountPrecisionB
Perhitungan yang lebih akurat (digit kecil)rateA
, Konversi nilai tukar dari objek bursa pertama yang ditambahkan, default 1 tidak dikonversi.rateB
, Konversi nilai tukar objek bursa kedua yang ditambahkan, default 1 tidak dikonversi.Strategi hedging membutuhkan menjaga jumlah koin dari kedua akun selalu tidak berubah (yaitu tidak memegang posisi arah apa pun, tetap netral), sehingga diperlukan strategi yang memiliki logika keseimbangan yang selalu mendeteksi keseimbangan. Ketika mendeteksi keseimbangan, kita tidak dapat menghindari data aset dari dua bursa. Kita perlu menulis fungsi untuk menggunakannya.
function updateAccs(arrEx) {
var ret = []
for (var i = 0 ; i < arrEx.length ; i++) {
var acc = arrEx[i].GetAccount()
if (!acc) {
return null
}
ret.push(acc)
}
return ret
}
Jika tidak ada pesanan yang ditransfer setelah pesanan tersebut, kita perlu membatalkannya tepat waktu, tidak bisa membiarkan pesanan itu tetap tergantung. Operasi ini baik dalam modul keseimbangan maupun dalam logika perlindungannya harus diproses, jadi kita juga perlu merancang fungsi pencabutan penuh pesanan.
function cancelAll() {
_.each(exchanges, function(ex) {
while (true) {
var orders = _C(ex.GetOrders)
if (orders.length == 0) {
break
}
for (var i = 0 ; i < orders.length ; i++) {
ex.CancelOrder(orders[i].Id, orders[i])
Sleep(500)
}
}
})
}
Dalam mengimbangi jumlah koin, kita perlu mencari harga yang akumulasi ke jumlah koin tertentu dalam data kedalaman tertentu, jadi kita membutuhkan fungsi seperti ini untuk mengolahnya.
function getDepthPrice(depth, side, amount) {
var arr = depth[side]
var sum = 0
var price = null
for (var i = 0 ; i < arr.length ; i++) {
var ele = arr[i]
sum += ele.Amount
if (sum >= amount) {
price = ele.Price
break
}
}
return price
}
Kemudian kita perlu merancang dan menulis operasi suborder untuk hedging tertentu, yang harus dirancang sebagai suborder paralel:
function hedge(buyEx, sellEx, price, amount) {
var buyRoutine = buyEx.Go("Buy", price, amount)
var sellRoutine = sellEx.Go("Sell", price, amount)
Sleep(500)
buyRoutine.wait()
sellRoutine.wait()
}
Akhirnya, kita akan menyelesaikan desain fungsi keseimbangan, yang agak rumit.
function keepBalance(initAccs, nowAccs, depths) {
var initSumStocks = 0
var nowSumStocks = 0
_.each(initAccs, function(acc) {
initSumStocks += acc.Stocks + acc.FrozenStocks
})
_.each(nowAccs, function(acc) {
nowSumStocks += acc.Stocks + acc.FrozenStocks
})
var diff = nowSumStocks - initSumStocks
// 计算币差
if (Math.abs(diff) > minHedgeAmount && initAccs.length == nowAccs.length && nowAccs.length == depths.length) {
var index = -1
var available = []
var side = diff > 0 ? "Bids" : "Asks"
for (var i = 0 ; i < nowAccs.length ; i++) {
var price = getDepthPrice(depths[i], side, Math.abs(diff))
if (side == "Bids" && nowAccs[i].Stocks > Math.abs(diff)) {
available.push(i)
} else if (price && nowAccs[i].Balance / price > Math.abs(diff)) {
available.push(i)
}
}
for (var i = 0 ; i < available.length ; i++) {
if (index == -1) {
index = available[i]
} else {
var priceIndex = getDepthPrice(depths[index], side, Math.abs(diff))
var priceI = getDepthPrice(depths[available[i]], side, Math.abs(diff))
if (side == "Bids" && priceIndex && priceI && priceI > priceIndex) {
index = available[i]
} else if (priceIndex && priceI && priceI < priceIndex) {
index = available[i]
}
}
}
if (index == -1) {
Log("无法平衡")
} else {
// 平衡下单
var price = getDepthPrice(depths[index], side, Math.abs(diff))
if (price) {
var tradeFunc = side == "Bids" ? exchanges[index].Sell : exchanges[index].Buy
tradeFunc(price, Math.abs(diff))
} else {
Log("价格无效", price)
}
}
return false
} else if (!(initAccs.length == nowAccs.length && nowAccs.length == depths.length)) {
Log("错误:", "initAccs.length:", initAccs.length, "nowAccs.length:", nowAccs.length, "depths.length:", depths.length)
return true
} else {
return true
}
}
Fungsi-fungsi ini dirancang sesuai dengan kebutuhan kebijakan, dan berikut adalah fungsi utama yang dapat Anda mulai merancang kebijakan.
Strategi di FMZ adalah darimain
Fungsi dimulai pada.main
Pada bagian awal fungsi, kita akan melakukan initialization beberapa strategi.
Nama objek bursa Karena banyak operasi dalam strategi yang digunakan untuk objek bursa, seperti mendapatkan pasar, melakukan pesanan, dll. Jadi menggunakan nama yang lebih panjang setiap kali akan menjadi masalah, trik kecil adalah menggunakan nama sederhana sebagai gantinya, misalnya:
var exA = exchanges[0]
var exB = exchanges[1]
Dengan cara ini, Anda akan merasa nyaman menulis kode di belakang.
Rasio tukar, desain yang berkaitan dengan akurasi
// 精度,汇率设置
if (rateA != 1) {
// 设置汇率A
exA.SetRate(rateA)
Log("交易所A设置汇率:", rateA, "#FF0000")
}
if (rateB != 1) {
// 设置汇率B
exB.SetRate(rateB)
Log("交易所B设置汇率:", rateB, "#FF0000")
}
exA.SetPrecision(pricePrecisionA, amountPrecisionA)
exB.SetPrecision(pricePrecisionB, amountPrecisionB)
Jika parameter nilai tukarrateA
、rateB
Dengan pengaturan 1 (default adalah 1), yaiturateA != 1
ataurateB != 1
Tidak akan memicu, jadi tidak akan mengatur konversi nilai tukar.
Setel kembali semua data
Kadang-kadang kebijakan perlu menghapus semua data log, catatan kosong saat memulai. Anda dapat merancang parameter antarmuka kebijakan.isReset
, lalu desain ulang bagian kode yang di-initialize dalam kebijakan, misalnya:
if (isReset) { // 当isReset为真时重置数据
_G(null)
LogReset(1)
LogProfitReset()
LogVacuum()
Log("重置所有数据", "#FF0000")
}
Memulihkan data akun awal, memperbarui data akun saat ini
Untuk menilai keseimbangan, strategi membutuhkan catatan terus-menerus tentang kondisi aset akun awal yang digunakan dibandingkan dengan saat ini.nowAccs
Variabel ini digunakan untuk mencatat data akun saat ini, menggunakan fungsi yang baru saja kami desain.updateAccs
Mengakses data akun dari bursa saat ini.initAccs
Untuk mencatat status akun awal (data seperti jumlah mata uang di bursa A dan bursa B, jumlah mata uang yang ditagih)initAccs
Pertama kali digunakan_G()
Fungsi pemulihan ((_G) berfungsi untuk menyimpan data secara permanen, dan dapat mengembalikan data yang telah tercatat, lihat dokumentasi API:Tautan), jika Anda tidak dapat melakukan pencarian, atribut dan gunakan informasi akun saat ini_G
Fungsi mencatat.
Contoh kode berikut:
var nowAccs = _C(updateAccs, exchanges)
var initAccs = _G("initAccs")
if (!initAccs) {
initAccs = nowAccs
_G("initAccs", initAccs)
}
Kode dalam loop utama adalah proses yang dijalankan setiap putaran logika strategi, dan pelaksanaan berulang-ulang yang terus-menerus membentuk loop utama strategi. Mari kita lihat proses yang dilakukan setiap kali program dalam loop utama.
Dapatkan data pasar dan menilai efektivitas data pasar
var ts = new Date().getTime()
var depthARoutine = exA.Go("GetDepth")
var depthBRoutine = exB.Go("GetDepth")
var depthA = depthARoutine.wait()
var depthB = depthBRoutine.wait()
if (!depthA || !depthB || depthA.Asks.length == 0 || depthA.Bids.length == 0 || depthB.Asks.length == 0 || depthB.Bids.length == 0) {
Sleep(500)
continue
}
Di sini Anda dapat melihat fungsi paralel menggunakan platform FMZ.exchange.Go
Saya ingin membuat sebuah panggilan.GetDepth()
Objek paralel pada antarmukadepthARoutine
、depthBRoutine
❖ Ketika kedua objek paralel ini dibuat, panggilGetDepth()
Interface juga terjadi dengan cepat, saat kedua permintaan untuk mendapatkan data mendalam dikirim ke bursa.
Lalu panggildepthARoutine
、depthBRoutine
objekwait()
Metode untuk mendapatkan data mendalam.
Setelah mendapatkan data dalam, data dalam perlu diperiksa untuk menilai efektivitasnya.continue
Kata-kata yang dilakukan kembali dalam lingkaran utama.
Penggunaan价差值
Apakah parameternya差价比例
Parameternya?
var targetDiffPrice = hedgeDiffPrice
if (diffAsPercentage) {
targetDiffPrice = (depthA.Bids[0].Price + depthB.Asks[0].Price + depthB.Bids[0].Price + depthA.Asks[0].Price) / 4 * hedgeDiffPercentage
}
Di parameter kami telah melakukan desain seperti ini. Parameter FMZ dapat didasarkan pada suatu parameter.TampilkanAtauBerlindungJadi kita bisa membuat parameter untuk menentukan apakah kita akan menggunakannya.价格差
Atau,差价比例
。
Tambahkan parameter pada parameter antarmuka strategidiffAsPercentage
❖ Dua parameter lain yang bisa ditampilkan atau disembunyikan berdasarkan parameter ini adalah:hedgeDiffPrice@!diffAsPercentage
KetikadiffAsPercentage
Untuk menampilkan parameter tersebut.hedgeDiffPercentage@diffAsPercentage
KetikadiffAsPercentage
Untuk menunjukkan bahwa parameter tersebut benar.
Setelah desain ini, kami memilih.diffAsPercentage
Parameter, yaitu proporsi perbedaan harga sebagai kondisi pemicu hedging.diffAsPercentage
Parameter adalah perbedaan harga sebagai kondisi pemicu untuk hedging.
Memutuskan kondisi pemicu hedging
if (depthA.Bids[0].Price - depthB.Asks[0].Price > targetDiffPrice && Math.min(depthA.Bids[0].Amount, depthB.Asks[0].Amount) >= minHedgeAmount) { // A -> B 盘口条件满足
var price = (depthA.Bids[0].Price + depthB.Asks[0].Price) / 2
var amount = Math.min(depthA.Bids[0].Amount, depthB.Asks[0].Amount)
if (nowAccs[0].Stocks > minHedgeAmount && nowAccs[1].Balance / price > minHedgeAmount) {
amount = Math.min(amount, nowAccs[0].Stocks, nowAccs[1].Balance / price, maxHedgeAmount)
Log("触发A->B:", depthA.Bids[0].Price - depthB.Asks[0].Price, price, amount, nowAccs[1].Balance / price, nowAccs[0].Stocks) // 提示信息
hedge(exB, exA, price, amount)
cancelAll()
lastKeepBalanceTS = 0
isTrade = true
}
} else if (depthB.Bids[0].Price - depthA.Asks[0].Price > targetDiffPrice && Math.min(depthB.Bids[0].Amount, depthA.Asks[0].Amount) >= minHedgeAmount) { // B -> A 盘口条件满足
var price = (depthB.Bids[0].Price + depthA.Asks[0].Price) / 2
var amount = Math.min(depthB.Bids[0].Amount, depthA.Asks[0].Amount)
if (nowAccs[1].Stocks > minHedgeAmount && nowAccs[0].Balance / price > minHedgeAmount) {
amount = Math.min(amount, nowAccs[1].Stocks, nowAccs[0].Balance / price, maxHedgeAmount)
Log("触发B->A:", depthB.Bids[0].Price - depthA.Asks[0].Price, price, amount, nowAccs[0].Balance / price, nowAccs[1].Stocks) // 提示信息
hedge(exA, exB, price, amount)
cancelAll()
lastKeepBalanceTS = 0
isTrade = true
}
}
Di sini ada beberapa faktor yang memicu perhitungan.
1, pertama-tama memenuhi perbedaan hedging, dan hanya dapat di-hedge jika perbedaan dalam transaksi memenuhi parameter perbedaan yang ditetapkan.
2, margin yang dapat dieksekusi harus memenuhi margin minimum yang ditetapkan pada parameter, karena batas minimum yang mungkin dieksekusi oleh berbagai bursa berbeda, maka ambil yang terkecil dari keduanya.
3. Aset di bursa yang menjual operasi cukup untuk dijual, dan aset di bursa yang membeli operasi cukup untuk dibeli.
Ketika kondisi ini terpenuhi, fungsi hedging dijalankan untuk melakukan hedging. Sebelum fungsi utama, kita menyatakan variabel sebelumnya.isTrade
Untuk menandai apakah terjadi hedging, di sini variabel ditetapkan sebagaitrue
Anda dapat mengklik tombol "Memperbarui" dan "Memperbarui Variabel Global".lastKeepBalanceTS
Untuk 0 ((lastKeepBalanceTS digunakan untuk menandai timestamp dari operasi keseimbangan terakhir, yang diatur ke 0 akan langsung memicu operasi keseimbangan), dan kemudian membatalkan semua daftar gantungan.
Operasi keseimbangan
if (ts - lastKeepBalanceTS > keepBalanceCyc * 1000) {
nowAccs = _C(updateAccs, exchanges)
var isBalance = keepBalance(initAccs, nowAccs, [depthA, depthB])
cancelAll()
if (isBalance) {
lastKeepBalanceTS = ts
if (isTrade) {
var nowBalance = _.reduce(nowAccs, function(sumBalance, acc) {return sumBalance + acc.Balance}, 0)
var initBalance = _.reduce(initAccs, function(sumBalance, acc) {return sumBalance + acc.Balance}, 0)
LogProfit(nowBalance - initBalance, nowBalance, initBalance, nowAccs)
isTrade = false
}
}
}
Anda dapat melihat bahwa fungsi keseimbangan akan dijalankan secara berkala, tetapi jika operasi hedging telah dipicu, Anda dapat melihat bahwa fungsi ini tidak dapat dioperasikan secara teratur.lastKeepBalanceTS
Operasi rebalancing yang disetel kembali ke 0 akan segera dipicu. Hasil akan dihitung setelah rebalancing berhasil.
Informasi status
LogStatus(_D(), "A->B:", depthA.Bids[0].Price - depthB.Asks[0].Price, " B->A:", depthB.Bids[0].Price - depthA.Asks[0].Price, " targetDiffPrice:", targetDiffPrice, "\n",
"当前A,Stocks:", nowAccs[0].Stocks, "FrozenStocks:", nowAccs[0].FrozenStocks, "Balance:", nowAccs[0].Balance, "FrozenBalance", nowAccs[0].FrozenBalance, "\n",
"当前B,Stocks:", nowAccs[1].Stocks, "FrozenStocks:", nowAccs[1].FrozenStocks, "Balance:", nowAccs[1].Balance, "FrozenBalance", nowAccs[1].FrozenBalance, "\n",
"初始A,Stocks:", initAccs[0].Stocks, "FrozenStocks:", initAccs[0].FrozenStocks, "Balance:", initAccs[0].Balance, "FrozenBalance", initAccs[0].FrozenBalance, "\n",
"初始B,Stocks:", initAccs[1].Stocks, "FrozenStocks:", initAccs[1].FrozenStocks, "Balance:", initAccs[1].Balance, "FrozenBalance", initAccs[1].FrozenBalance)
Status bar tidak dirancang untuk menjadi sangat rumit, menunjukkan waktu saat ini, menunjukkan perbedaan antara bursa A ke bursa B dan perbedaan antara bursa B ke bursa A. Menampilkan perbedaan target lindung nilai saat ini. Menampilkan data aset akun bursa A, data aset akun B.
Pada parameter, kita merancang parameter untuk mengubah nilai tukar, dan pada awal strategi, kita membuat parameter untuk mengubah nilai tukar.main
Bagian dari operasi awal fungsi, kita juga merancang konversi nilai tukar.SetRate
Fungsi konversi nilai tukar harus dilakukan terlebih dahulu.
Karena fungsi ini mempengaruhi dua tingkatan:
BTC_USDT
Harga adalah:USDT
Anda juga dapat menggunakan mata uang dalam akun Anda.USDT
Jika saya ingin mengubah nilai CNY, saya akan mengaturnya dalam kode.exchange.SetRate(6.8)
Anda bisa mengambilnyaexchange
Semua data yang diperoleh oleh fungsi di bawah obyek bursa ini ditukarkan menjadi CNY.
Anda bisa mendapatkan uang tunai dari bank.SetRate
Fungsi masukNilai tukar mata uang saat ini ke mata uang target。Strategi lengkap:Strategi hedging mata uang yang berbeda (Pendidikan)
Squirrels adalah hewan yang sangat ramah.Sangat bagus.