Nos artigos anteriores, analisamos as ideias e implementação de código da versão spot original da estratégia de colheita de lucro de alta frequência.
Análise dos produtores de lucro (1) Análise dos produtores de lucros (2)
Muitos usuários no círculo de criptomoedas quantitativas estão muito preocupados com a estratégia desenvolvida por um mestre chamadoimprimir dinheiroA estratégia deimprimir dinheiroA partir da observação e análise de muitos seguidores, pode-se ver que a estratégia de alta frequência é semelhante ao princípio da colheita de lucro (o mestre Xiaocao também disse que o princípio da estratégia de alta frequência é semelhante ao da colheita de lucro). Mas deve haver alguma sutileza que permita que uma estratégia tenha uma taxa de ganho estável e uma proporção de lucro/perda adequada.
Portanto, eu estava tão animado que eu não podia deixar de querer modificar magicamente a estratégia, mesmo o resultado e efeito da estratégia magicamente modificada não era nada diante das estratégias desenvolvidas pelos mestres.
var TickInterval = 100
function LeeksReaper() {
var self = {}
self.numTick = 0
self.lastTradeId = 0
self.vol = 0
self.askPrice = 0
self.bidPrice = 0
self.orderBook = {
Asks: [],
Bids: []
}
self.prices = []
self.tradeOrderId = 0
self.account = null
self.buyPrice = 0
self.sellPrice = 0
self.state = 0
self.depth = null
self.updateTrades = function() {
var trades = _C(exchange.GetTrades)
if (self.prices.length == 0) {
while (trades.length == 0) {
trades = trades.concat(_C(exchange.GetTrades))
}
for (var i = 0; i < 15; i++) {
self.prices[i] = trades[trades.length - 1].Price
}
}
self.vol = 0.7 * self.vol + 0.3 * _.reduce(trades, function(mem, trade) {
// Huobi not support trade.Id
if ((trade.Id > self.lastTradeId) || (trade.Id == 0 && trade.Time > self.lastTradeId)) {
self.lastTradeId = Math.max(trade.Id == 0 ? trade.Time : trade.Id, self.lastTradeId)
mem += trade.Amount
}
return mem
}, 0)
}
self.updateOrderBook = function() {
var orderBook = _C(exchange.GetDepth)
self.depth = orderBook
self.buyPrice = orderBook.Bids[pendingLevel].Price
self.sellPrice = orderBook.Asks[pendingLevel].Price
self.orderBook = orderBook
if (orderBook.Bids.length < 3 || orderBook.Asks.length < 3) {
return
}
self.bidPrice = orderBook.Bids[0].Price * 0.618 + orderBook.Asks[0].Price * 0.382 + 0.01
self.askPrice = orderBook.Bids[0].Price * 0.382 + orderBook.Asks[0].Price * 0.618 - 0.01
self.prices.shift()
self.prices.push(_N((orderBook.Bids[0].Price + orderBook.Asks[0].Price) * 0.15 +
(orderBook.Bids[1].Price + orderBook.Asks[1].Price) * 0.1 +
(orderBook.Bids[2].Price + orderBook.Asks[2].Price) * 0.1 +
(orderBook.Bids[3].Price + orderBook.Asks[3].Price) * 0.075 +
(orderBook.Bids[4].Price + orderBook.Asks[4].Price) * 0.05 +
(orderBook.Bids[5].Price + orderBook.Asks[5].Price) * 0.025))
}
self.updateAccount = function() {
var account = exchange.GetAccount()
if (!account) {
return
}
self.account = account
LogProfit(parseFloat(account.Info.totalWalletBalance), account)
}
self.CancelAll = function() {
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)
}
Sleep(100)
}
}
self.poll = function() {
self.numTick++
self.updateTrades()
self.updateOrderBook()
var pos = _C(exchange.GetPosition)
var burstPrice = self.prices[self.prices.length - 1] * burstThresholdPct
var bull = false
var bear = false
LogStatus(_D(), "\n", 'Tick:', self.numTick, 'self.vol:', self.vol, ', lastPrice:', self.prices[self.prices.length - 1], ', burstPrice: ', burstPrice)
if (self.numTick > 2 && (
self.prices[self.prices.length - 1] - _.max(self.prices.slice(-6, -1)) > burstPrice ||
self.prices[self.prices.length - 1] - _.max(self.prices.slice(-6, -2)) > burstPrice && self.prices[self.prices.length - 1] > self.prices[self.prices.length - 2]
)) {
bull = true
} else if (self.numTick > 2 && (
self.prices[self.prices.length - 1] - _.min(self.prices.slice(-6, -1)) < -burstPrice ||
self.prices[self.prices.length - 1] - _.min(self.prices.slice(-6, -2)) < -burstPrice && self.prices[self.prices.length - 1] < self.prices[self.prices.length - 2]
)) {
bear = true
}
if (pos.length != 0) {
if (pos[0].Type == PD_LONG) {
self.state = 1
} else {
self.state = 2
}
} else {
self.state = 0
}
if ((!bull && !bear)) {
return
}
if (bull) {
var price = (self.state == 0 || self.state == 1) ? self.buyPrice : self.depth.Bids[coverPendingLevel].Price
var amount = (self.state == 0 || self.state == 1) ? pendingAmount : pos[0].Amount
exchange.SetDirection("buy")
exchange.Buy(price, amount)
} else if (bear) {
var price = (self.state == 0 || self.state == 2) ? self.sellPrice : self.depth.Asks[coverPendingLevel].Price
var amount = (self.state == 0 || self.state == 2) ? pendingAmount : pos[0].Amount
exchange.SetDirection("sell")
exchange.Sell(price, amount)
}
self.numTick = 0
Sleep(TickInterval)
self.CancelAll()
self.updateAccount()
}
while (!self.account) {
self.updateAccount()
Sleep(500)
}
Log("self.account:", self.account)
return self
}
function main() {
LogProfitReset()
exchange.SetPrecision(pricePrecision, amountPrecision)
exchange.SetContractType("swap")
var reaper = LeeksReaper()
while (true) {
reaper.poll()
Sleep(100)
}
}
A estratégia é planejada para negociar no mercado de contratos Binance USDT, que suporta posições unidirecionais. Portanto, a estratégia é modificada e projetada de acordo com as características das posições unidirecionais (posições unidirecionais são mais convenientes para modificação de estratégia), e você só precisa considerar a compra e venda, não precisa pensar em fechar posições.
A estratégia mantém basicamente o critério original de ruptura da tendência de preços a curto prazo e a faixa de ruptura de preços a curto prazo é controlada pelo parâmetroburstThresholdPct
. De acordo com o critério para determinar se o preço a curto prazo ébull
oubear
.
A estratégia remove alguns módulos do original, como o módulo de balanço. Uma modificação bastante grande é mudar a colocação de ordens para ordens pendentes na carteira de pedidos e aguardando execução. Espera-se que abra posições a um custo relativamente baixo no mercado caótico com um jogo longo e curto acirrado, siga a tendência de curto prazo e feche posições quando a tendência de curto prazo se inverter e, em seguida, continue a executar ordens pendentes e posições abertas de forma inversa.
A estratégia remove outro código inútil, por isso é muito curta e simples. Embora a estratégia seja uma estratégia não lucrativa, mesmo com perdas, é um modelo muito fácil e útil para um FMZer aprender estratégias de alta frequência, observar as ações de estratégias de alta frequência, observar as regras microscópicas do mercado, etc. A negociação programada e quantitativa precisa ser baseada em muita prática, experiência e teorias.
Pode-se observar que é mais difícil abrir e fechar posições quando a situação do mercado não é ativa.
No momento, não foi encontrada uma boa direcção de otimização. Os alunos, que estão interessados, podem falar ativamente e discutir juntos.
Endereço estratégico:https://www.fmz.com/strategy/260806
A estratégia é apenas para estudo; quando o mercado está plano, executá-lo no bot pode causar perdas.