Để đáp ứng nhu cầu của nhiều người dùng, nền tảng FMZ gần đây đã truy cập dYdX, một sàn giao dịch phi tập trung. Bất cứ ai có chiến lược có thể thưởng thức quá trình mua tiền kỹ thuật số dYdX. Tôi chỉ muốn viết một chiến lược giao dịch chứng khoán từ lâu, không quan trọng nó có kiếm lợi nhuận hay không. Vì vậy, tiếp theo chúng ta cùng nhau thiết kế một chiến lược giao dịch chứng khoán, cho dù chiến lược có hiệu quả tốt hay không, chúng ta chỉ cần học thiết kế chiến lược.
Chúng ta hãy suy nghĩ! Nó được lên kế hoạch để thiết kế một chiến lược đặt đơn đặt hàng ngẫu nhiên với các chỉ số ngẫu nhiên và giá cả. Đặt đơn đặt hàng là không gì khác hơn là đi dài hoặc đi ngắn, chỉ đặt cược vào xác suất. Sau đó chúng ta sẽ sử dụng số ngẫu nhiên 1 ~ 100 để xác định xem nên mua dài hay mua ngắn.
Điều kiện để mua dài: số ngẫu nhiên 1 ~ 50. Điều kiện để đi ngắn: số ngẫu nhiên 51 ~ 100.
Do đó, cả đi dài và đi ngắn đều là 50 con số. Tiếp theo, chúng ta hãy suy nghĩ về cách đóng vị trí, vì đó là một cược, sau đó phải có một tiêu chí để thắng hoặc thua. Chúng ta thiết lập một tiêu chí để dừng lợi nhuận và lỗ cố định trong giao dịch. Dừng lợi nhuận cho chiến thắng, dừng lỗ cho thua. Về số lượng dừng lợi nhuận và lỗ, nó thực sự ảnh hưởng đến tỷ lệ lợi nhuận và lỗ, ôi vâng! Nó cũng ảnh hưởng đến tỷ lệ thắng! (Mục đích thiết kế chiến lược này có hiệu quả không? Có thể đảm bảo như một kỳ vọng toán học tích cực không? Làm điều đó trước! (Sau đó, chỉ để học, nghiên cứu!)
Giao dịch không phải là miễn phí, có đủ trượt, phí, vv để kéo tỷ lệ chiến thắng giao dịch ngẫu nhiên của chúng tôi về phía dưới 50%. Vì vậy, làm thế nào để thiết kế nó liên tục? Nếu chúng ta có thể tạo ra một số lượng lớn hơn, thì chúng ta có thể tạo ra một số lượng lớn hơn. Nếu chúng ta có thể tạo ra một số lượng lớn hơn, chúng ta có thể tạo ra một số lượng lớn hơn. Nếu chúng ta có thể tạo ra một số lượng lớn hơn, chúng ta có thể tạo ra một số lượng lớn hơn.
Được rồi, chiến lược được thiết kế đơn giản.
Mã nguồn được 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 "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)
}
}
Các thông số chiến lược:
Ồ vâng! Chiến lược cần một cái tên, hãy gọi nó là
Backtesting chỉ để tham khảo, >_
Kiểm tra đã hoàn tất, không có lỗi.
Chiến lược này chỉ được sử dụng để học và tham khảo, đừng sử dụng nó trong bot thực sự!