В ответ на спрос многих пользователей, платформа FMZ недавно получила доступ к dYdX, децентрализованной бирже. Кто-то, у кого есть стратегии, может насладиться процессом приобретения цифровой валюты dYdX. Я просто хотел написать стохастическую торговую стратегию давно, неважно, приносит ли она прибыль.
Давайте проведем мозговой штурм! Планируется разработать стратегию размещения заказов случайным образом с случайными показателями и ценами. Размещение заказов - это не что иное, как длинный или короткий ход, просто ставки на вероятность. Затем мы будем использовать случайное число 1 ~ 100 для определения длинного или короткого.
Условие для покупки: случайное число от 1 до 50. Условие для короткого расписания: случайный номер 51~100.
Таким образом, и длинный, и короткий ход - это 50 цифр. Далее, давайте подумаем о том, как закрыть позицию, поскольку это ставка, то должны быть критерии для выигрыша или проигрыша. Мы устанавливаем критерии для фиксированной остановки прибыли и убытка в сделке. Остановить прибыль для выигрыша, остановить убыток для проигрыша. Что касается суммы остановки прибыли и убытка, на самом деле это влияние соотношения прибыли и убытка, о да! Это также влияет на коэффициент выигрыша! (Это дизайн стратегии эффективен? Можно ли гарантировать как положительные математические ожидания? Сделайте это сначала! (После, это просто для обучения, исследования!)
Торговля не является бесплатной, есть достаточно скольжения, сборов и т.д., чтобы вытащить наш стохастический процент выигрыша торговли к стороне менее 50%. Как насчет разработки мультипликатора для увеличения позиции? Поскольку это ставка, то вероятность проигрыша в течение 8 ~ 10 раз в ряд случайных сделок должна быть низкой. Так что первая транзакция была разработана для размещения небольшого количества заказов, как можно меньше.
Хорошо, стратегия спроектирована просто.
Исходный код разработан:
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)
}
}
Параметры стратегии:
О да! Стратегия нуждается в названии, давайте назовем его "Угадай размер (версия dYdX) ".
Обратное тестирование только для справки, >_
Бактэст завершен, нет ошибок.
Эта стратегия используется только для обучения и справки, не используйте ее в реальном боте!