
En respuesta a muchas demandas de los usuarios, la plataforma FMZ respaldó recientemente el intercambio descentralizado dYdX. Los amigos con estrategias pueden minar felizmente dYdX. Dio la casualidad de que hacía tiempo que quería escribir una estrategia de trading aleatoria. No importaba si ganaba o perdía dinero. El objetivo era practicar y enseñar el diseño de estrategias al mismo tiempo. Diseñemos juntos una estrategia de intercambio aleatorio. No se preocupe por el rendimiento de la estrategia. Aprendamos sobre el diseño de estrategias.
Captura de pantalla de minería estratégica en este artículo.

¡Los amigos que tengan buenas ideas sobre estrategias mineras también son bienvenidos a dejar un mensaje!
¡Pensemos salvajemente! Planeo diseñar una estrategia que coloque órdenes al azar sin mirar indicadores ni precios. Las órdenes no son más que ir en largo o en corto, y todo lo que hay que hacer es predecir probabilidades. Luego usamos números aleatorios del 1 al 100 para determinar largo y corto.
Condiciones largas: números aleatorios 1 ~ 50. Condiciones de venta corta: números aleatorios 51 ~ 100.
Los números para las posiciones largas y cortas son 50. A continuación, pensemos en cómo cerrar la posición. Como se trata de una apuesta, debe haber un estándar para ganar y perder. Luego, en la transacción, establecemos un take-profit y un stop-loss fijos como estándar para ganar o perder. Si dejas de obtener ganancias, ganas; si dejas de obtener pérdidas, pierdes. En cuanto a las configuraciones adecuadas de take-profit y stop-loss, esto en realidad afecta la relación de ganancias y pérdidas, ¡oh sí! ¡También afecta la probabilidad de ganar! (¿Es efectiva esta estrategia de diseño? ¿Puede garantizar una expectativa matemática positiva? ¡Hagámoslo primero! Después de todo, ¡es para aprender e investigar!)
El trading no es gratuito. Factores como el deslizamiento y las tarifas de gestión son suficientes para reducir nuestra tasa de éxito en operaciones aleatorias a menos del 50 %. ¿Cómo debo continuar diseñando con esto en mente? Es mejor diseñar un aumento de posiciones múltiples. Como se trata de una apuesta, la probabilidad de perder 8 transacciones aleatorias de 10 seguidas no debería ser muy alta. Entonces quiero diseñar la primera transacción para que tenga un tamaño de pedido muy pequeño, lo más pequeño posible. Luego, si pierde la apuesta, aumente la cantidad del pedido y continúe realizando pedidos aleatorios.
Bien, el diseño de la estrategia es así de simple.
Código fuente del diseño:
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("重置所有数据", "#FF0000")
}
exchange.SetContractType(ct)
var initPos = _C(exchange.GetPosition)
if (initPos.length != 0) {
throw "策略启动时有持仓!"
}
exchange.SetPrecision(pricePrecision, amountPrecision)
Log("设置精度", 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 "获取初始权益失败"
}
} else {
totalEq = recoverTotalEq
}
} else {
totalEq = _C(exchange.GetAccount).Balance
}
while (1) {
if (openPrice == 0) {
// 更新账户信息,计算收益
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("下", direction > 50 ? "买单" : "卖单", ",价格:", 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
}
// 平仓检测
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
// 画线
$.PlotLine("bid", depth.Bids[0].Price)
$.PlotLine("ask", depth.Asks[0].Price)
// 止损
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
}
// 止盈
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
}
// 检测挂单
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 {
// 撤销挂单
cancelAll()
Sleep(2000)
pos = _C(exchange.GetPosition)
// 撤销后更新持仓,需要再次检查
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 {
// 撤销挂单
// 重置openPrice
cancelAll()
openPrice = 0
}
Sleep(1000)
}
}
Parámetros de la estrategia:

¡Oh sí! La estrategia necesita un nombre, llamémoslo “Adivina el tamaño (versión dYdX)”.
Las pruebas retrospectivas son sólo para referencia._<! El objetivo principal es verificar si hay errores en la estrategia y utilizar el backtesting de futuros de Binance.




La prueba retrospectiva está completa y no hay errores. Pero siento que quizás he sobreajustado el sistema de backtest… T_T, déjame probarlo en tiempo real.



Esta estrategia es sólo para aprendizaje y referencia.10 millones~10 millones¡No lo uses de verdad! !