Phản ứng với nhu cầu của nhiều người dùng, nền tảng FMZ gần đây đã hỗ trợ nền tảng phi tập trung dYdX. Bạn bè có chiến lược có thể khai thác trên dYdX một cách hạnh phúc. Cách đây rất lâu, tôi muốn viết một chiến lược giao dịch ngẫu nhiên. Không quan trọng là tôi kiếm được lợi nhuận hay không. Mục đích là thực hành kỹ thuật của tôi và dạy thiết kế chiến lược. Vì vậy, tiếp theo, hãy cùng nhau thiết kế một chiến lược nền tảng ngẫu nhiên. Đừng lo lắng về hiệu suất của chiến lược, và chỉ cần học thiết kế chiến lược.
Ảnh chụp màn hình của chiến lược khai thác trong bài báo.
Chào mừng bạn bè có ý tưởng chiến lược khai thác tốt để chia sẻ!
Chúng ta hãy suy nghĩ! Chúng ta có kế hoạch thiết kế một chiến lược để đặt đơn đặt hàng ngẫu nhiên mà không cần nhìn vào các chỉ số hoặc giá cả. Đặt đơn đặt hàng không gì khác ngoài việc đặt mua và mua, đó là đặt cược vào xác suất. Sau đó chúng ta sử dụng các số ngẫu nhiên từ 1 đến 100 để xác định xem mua mua hay mua.
Điều kiện làm dài: số ngẫu nhiên từ 1 đến 50. Điều kiện làm ngắn: số ngẫu nhiên từ 51 đến 100.
Làm dài và ngắn đều cần 50 số. Tiếp theo, chúng ta hãy suy nghĩ về cách đóng các vị trí. Vì nó là một cược, phải có một tiêu chuẩn thắng hoặc thua. Sau đó, chúng ta hãy thiết lập một stopProfit cố định và stopLoss như tiêu chuẩn thắng hoặc thua. Hãy lấy stopProfit là thắng, và stopLoss là thua. Về sự phù hợp của stopProfit và stopLoss, nó thực sự ảnh hưởng đến tỷ lệ lợi nhuận và lỗ, và tỷ lệ thắng! (Có hiệu quả khi thiết kế một chiến lược theo cách này? Có thể đảm bảo nó là một kỳ vọng toán học tích cực không? Dù sao đi nữa, hãy làm điều đó trước! Bởi vì nó là để học và nghiên cứu!)
Giao dịch không phải là miễn phí, và có những yếu tố như điểm trượt và phí đủ để kéo tỷ lệ chiến thắng giao dịch ngẫu nhiên của chúng tôi xuống dưới 50%. Vì vậy, tôi muốn thiết kế đặt một số lượng đơn đặt hàng nhỏ trong giao dịch đầu tiên, càng nhỏ càng tốt. sau đó nếu tôi thua cược, tăng số lượng đơn đặt hàng và tiếp tục đặt các đơn đặt hàng ngẫu nhiên.
Chiến lược đơn giản như thế này.
Mã nguồn của thiết kế:
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 "Position detected when starting the strategy!"
}
exchange.SetPrecision(pricePrecision, amountPrecision)
Log("setPrecision", 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 "fail to obtain the initial equity"
}
} else {
totalEq = recoverTotalEq
}
} else {
totalEq = _C(exchange.GetAccount).Balance
}
while (1) {
if (openPrice == 0) {
// update account information, and calculate the profit
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 ? "buy order" : "sell 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
}
// detect close positions
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
// plot
$.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
}
// detect 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)
// after canceling, update positions, which needs to be detected 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 pending orders
// reset openPrice
cancelAll()
openPrice = 0
}
Sleep(1000)
}
}
Các thông số chiến lược:
Được rồi! Chiến lược cần một cái tên, và hãy gọi nó là "Đánh đoán cái nào lớn hơn (phiên bản dYdX).
Kiểm tra lại chỉ để tham khảo thôi! Nó chủ yếu là để kiểm tra xem có bất kỳ lỗi nào trong chiến lược; backtest với Binance Futures.
Nhưng tôi cảm thấy như hệ thống backtest đã phù hợp... hãy chạy nó trong một robot thực sự để quan sát.
Chiến lược này chỉ để học và tham khảo.Đừng!! Đừngsử dụng nó trong một robot thực sự!