Sebagai tindak balas kepada permintaan ramai pengguna, platform FMZ telah mengakses dYdX baru-baru ini, pertukaran terdesentralisasi. Seseorang yang mempunyai strategi boleh menikmati proses memperoleh mata wang digital dYdX. Saya hanya mahu menulis strategi perdagangan stokastik untuk masa yang lama, tidak kira sama ada ia membuat keuntungan. Jadi seterusnya kita datang bersama untuk merancang strategi pertukaran stokastik, tidak kira strategi berfungsi dengan baik atau tidak, kita hanya belajar reka bentuk strategi.
Mari kita bertukar fikiran! Ia dirancang untuk merancang strategi meletakkan pesanan secara rawak dengan penunjuk rawak dan harga. Menempatkan pesanan tidak lebih daripada pergi panjang atau pergi pendek, hanya bertaruh pada kebarangkalian. Kemudian kita akan menggunakan nombor rawak 1 ~ 100 untuk menentukan sama ada untuk pergi panjang atau pergi pendek.
Syarat untuk pergi panjang: nombor rawak 1 ~ 50. Syarat untuk pergi pendek: nombor rawak 51 ~ 100.
Oleh itu, kedua-dua pergi panjang dan pergi pendek adalah 50 nombor. Seterusnya, mari kita fikirkan bagaimana untuk menutup kedudukan, kerana ia adalah pertaruhan, maka mesti ada kriteria untuk menang atau kalah. Kami menetapkan kriteria untuk keuntungan berhenti tetap dan kerugian dalam urus niaga. Hentikan keuntungan untuk menang, hentikan kerugian untuk kehilangan. Mengenai jumlah keuntungan berhenti dan kerugian, ia sebenarnya kesan nisbah keuntungan dan kerugian, oh ya! Ia juga mempengaruhi kadar kemenangan! (Adakah reka bentuk strategi ini berkesan? Bolehkah ia dijamin sebagai jangkaan matematik positif? Lakukan terlebih dahulu! (Selepas itu, hanya untuk pembelajaran, penyelidikan!)
Perdagangan tidak bebas kos, terdapat cukup slippage, yuran, dan lain-lain untuk menarik kadar kemenangan perdagangan stokastik kami ke arah bahagian kurang daripada 50%. Jadi bagaimana untuk merancangnya secara berterusan? Bagaimana dengan merancang pengganda untuk meningkatkan kedudukan? Oleh kerana ia adalah pertaruhan, maka kebarangkalian kehilangan selama 8 ~ 10 kali dalam satu barisan perdagangan rawak harus rendah. Jadi transaksi pertama direka untuk meletakkan sejumlah kecil pesanan, sekecil mungkin. Kemudian jika saya kalah, saya akan meningkatkan jumlah pesanan dan terus meletakkan pesanan secara rawak.
OK, strategi ini direka dengan mudah.
Kod sumber direka:
var openPrice = 0
var ratio = 1
var totalEq = null
var nowEq = null
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(500)
}
Sleep(500)
}
}
function main() {
if (isReset) {
_G(null)
LogReset(1)
LogProfitReset()
LogVacuum()
Log("reset all data", "#FF0000")
}
exchange.SetContractType(ct)
var initPos = _C(exchange.GetPosition)
if (initPos.length != 0) {
throw "Strategy starts with a position!"
}
exchange.SetPrecision(pricePrecision, amountPrecision)
Log("set the pricePrecision", pricePrecision, amountPrecision)
if (!IsVirtual()) {
var recoverTotalEq = _G("totalEq")
if (!recoverTotalEq) {
var currTotalEq = _C(exchange.GetAccount).Balance // equity
if (currTotalEq) {
totalEq = currTotalEq
_G("totalEq", currTotalEq)
} else {
throw "failed to obtain initial interest"
}
} else {
totalEq = recoverTotalEq
}
} else {
totalEq = _C(exchange.GetAccount).Balance
}
while (1) {
if (openPrice == 0) {
// Update account information and calculate profits
var nowAcc = _C(exchange.GetAccount)
nowEq = IsVirtual() ? nowAcc.Balance : nowAcc.Balance // equity
LogProfit(nowEq - totalEq, nowAcc)
var direction = Math.floor((Math.random()*100)+1) // 1~50 , 51~100
var depth = _C(exchange.GetDepth)
if (depth.Asks.length <= 2 || depth.Bids.length <= 2) {
Sleep(1000)
continue
}
if (direction > 50) {
// long
openPrice = depth.Bids[1].Price
exchange.SetDirection("buy")
exchange.Buy(Math.abs(openPrice) + slidePrice, amount * ratio)
} else {
// short
openPrice = -depth.Asks[1].Price
exchange.SetDirection("sell")
exchange.Sell(Math.abs(openPrice) - slidePrice, amount * ratio)
}
Log("place", direction > 50 ? "buying order" : "selling order", ", price:", Math.abs(openPrice))
continue
}
var orders = _C(exchange.GetOrders)
if (orders.length == 0) {
var pos = _C(exchange.GetPosition)
if (pos.length == 0) {
openPrice = 0
continue
}
// Test for closing the position
while (1) {
var depth = _C(exchange.GetDepth)
if (depth.Asks.length <= 2 || depth.Bids.length <= 2) {
Sleep(1000)
continue
}
var stopLossPrice = openPrice > 0 ? Math.abs(openPrice) - stopLoss : Math.abs(openPrice) + stopLoss
var stopProfitPrice = openPrice > 0 ? Math.abs(openPrice) + stopProfit : Math.abs(openPrice) - stopProfit
var winOrLoss = 0 // 1 win , -1 loss
// drawing the line
$.PlotLine("bid", depth.Bids[0].Price)
$.PlotLine("ask", depth.Asks[0].Price)
// stop loss
if (openPrice > 0 && depth.Bids[0].Price < stopLossPrice) {
exchange.SetDirection("closebuy")
exchange.Sell(depth.Bids[0].Price - slidePrice, pos[0].Amount)
winOrLoss = -1
} else if (openPrice < 0 && depth.Asks[0].Price > stopLossPrice) {
exchange.SetDirection("closesell")
exchange.Buy(depth.Asks[0].Price + slidePrice, pos[0].Amount)
winOrLoss = -1
}
// stop profit
if (openPrice > 0 && depth.Bids[0].Price > stopProfitPrice) {
exchange.SetDirection("closebuy")
exchange.Sell(depth.Bids[0].Price - slidePrice, pos[0].Amount)
winOrLoss = 1
} else if (openPrice < 0 && depth.Asks[0].Price < stopProfitPrice) {
exchange.SetDirection("closesell")
exchange.Buy(depth.Asks[0].Price + slidePrice, pos[0].Amount)
winOrLoss = 1
}
// Test the pending orders
Sleep(2000)
var orders = _C(exchange.GetOrders)
if (orders.length == 0) {
pos = _C(exchange.GetPosition)
if (pos.length == 0) {
if (winOrLoss == -1) {
ratio++
} else if (winOrLoss == 1) {
ratio = 1
}
break
}
} else {
// cancel pending orders
cancelAll()
Sleep(2000)
pos = _C(exchange.GetPosition)
// update the position after cancellation, and check it again
if (pos.length == 0) {
if (winOrLoss == -1) {
ratio++
} else if (winOrLoss == 1) {
ratio = 1
}
break
}
}
var tbl = {
"type" : "table",
"title" : "info",
"cols" : ["totalEq", "nowEq", "openPrice", "bid1Price", "ask1Price", "ratio", "pos.length"],
"rows" : [],
}
tbl.rows.push([totalEq, nowEq, Math.abs(openPrice), depth.Bids[0].Price, depth.Asks[0].Price, ratio, pos.length])
tbl.rows.push(["pos", "type", "amount", "price", "--", "--", "--"])
for (var j = 0 ; j < pos.length ; j++) {
tbl.rows.push([j, pos[j].Type, pos[j].Amount, pos[j].Price, "--", "--", "--"])
}
LogStatus(_D(), "\n", "`" + JSON.stringify(tbl) + "`")
}
} else {
// cancel the pending orders
// reset openPrice
cancelAll()
openPrice = 0
}
Sleep(1000)
}
}
Parameter strategi:
Oh ya! Strategi ini memerlukan nama, mari kita panggil
Backtesting adalah untuk rujukan sahaja, >_
Ujian belakang telah selesai, tidak ada bug.
Strategi ini digunakan untuk pembelajaran dan rujukan sahaja, jangan menggunakannya dalam bot sebenar!