En respuesta a la demanda de muchos usuarios, la plataforma FMZ ha accedido recientemente a dYdX, un intercambio descentralizado. Alguien que tenga estrategias puede disfrutar del proceso de adquisición de moneda digital dYdX. Solo quería escribir una estrategia de negociación estocástica hace mucho tiempo, no importa si obtiene ganancias. Así que a continuación nos reunimos para diseñar una estrategia de intercambio estocástica, sin importar si la estrategia funciona bien o no, solo aprendemos el diseño de la estrategia.
Vamos a tener una lluvia de ideas! Se planea diseñar una estrategia de colocar órdenes al azar con indicadores y precios aleatorios. Poner órdenes no es más que ir largo o ir corto, sólo apostando a la probabilidad. Luego usaremos el número aleatorio 1 ~ 100 para determinar si ir largo o ir corto.
Condición para hacer el largo: número aleatorio 1~50. Condición para el cortocircuito: número aleatorio 51~100.
Por lo tanto, tanto ir largo como ir corto son 50 números. A continuación, pensemos en cómo cerrar la posición, ya que es una apuesta, entonces debe haber un criterio para ganar o perder. Establecemos un criterio para stop de ganancia y pérdida fijos en la transacción. Stop de ganancia para ganar, stop de pérdida para perder. En cuanto a la cantidad de stop de ganancia y pérdida, en realidad es el impacto de la relación de ganancia y pérdida, oh sí!
El comercio no es libre de costos, hay suficiente deslizamiento, comisiones, etc. para tirar nuestra tasa de ganancia de comercio estocástico hacia el lado de menos del 50%. Así que, ¿cómo diseñar continuamente? ¿Qué tal diseñar un multiplicador para aumentar la posición? ya que es una apuesta, entonces la probabilidad de perder por 8 ~ 10 veces en una fila de operaciones aleatorias debe ser baja. Así que la primera transacción fue diseñada para colocar una pequeña cantidad de órdenes, lo más pequeño posible. Luego, si pierdo, voy a aumentar la cantidad de órdenes y seguir colocando órdenes al azar.
Está bien, la estrategia está diseñada de manera simple.
Código fuente diseñado:
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)
}
}
Parámetros de la estrategia:
La estrategia necesita un nombre, vamos a llamarlo
Las pruebas de retroceso son sólo para referencia, >_
La prueba de retroceso ha terminado, no hay ningún error.
Esta estrategia se utiliza para el aprendizaje y la referencia sólo, no lo use en el bot real!