Transplante OKCoin para a colheita de cenoura

Autora:Zero., Data: 30 de janeiro de 2017
Tags:Alta frequência

Transplante de:https://github.com/richox/okcoin-leeks-reaper

O autor original disse que não funcionaria depois da cobrança, eu só fiz o transplante, sem testes em disco real, interessado em aprender. Inventor de retorno de nível Tick quantificado, com suporte à reprodução de Depth e Trades, que permite retomar diretamente a lógica estratégica de aprendizagem

Aqui está a descrição original:

A OKCoin é uma máquina de colheita.

Este é um programa de robô de negociação de alta frequência na plataforma de negociação de Bitcoin OKCoin, que foi desenvolvido a partir de um modelo básico de estratégia em junho de 2016 até meados de janeiro de 2017. A estratégia foi bem-sucedida em limpar o investimento inicial de 6.000 para 250.000.

image

O programa de robótica baseia-se em duas estratégias principais:

  1. Estratégia de tendência: fazer um pedido em tempo hábil e seguir quando os preços estão em tendência, ou seja, como diz o ditado.Perseguição e queda
  2. Estratégia de equilíbrio: quando o posicionamento se desvia 50%, liberar folhetos faz com que o posicionamento volte para 50% gradualmente, evitando que a reversão do final da tendência cause um recuo, ou seja,O lucro vai para o saco, não para a cauda do peixe

Este procedimento requer o equilíbrio dos posicionamentos, isto é, (capital + financiamento = moeda), para que os posicionamentos sejam de 50%, o que garante que os ativos líquidos não flutuem com os preços, mas também quando ocorrem flutuações de tendência.O que é que se passa?

A intenção do blogueiro é mostrar a sua gratidão por dois projetos:

A OKCoin também está presente.

O BCE deve apresentar ao BCE um relatório sobre as operações de reestruturação e de reestruturação.


/*backtest
start: 2019-09-05 00:00:00
end: 2019-09-05 22:00:00
period: 1h
exchanges: [{"eid":"Binance","currency":"BTC_USDT","fee":[0,0]}]
mode: 1
*/

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.p = 0.5
    self.account = null
    self.preCalc = 0
    self.preNet = 0

    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.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.35 +
            (orderBook.Bids[1].Price + orderBook.Asks[1].Price) * 0.1 +
            (orderBook.Bids[2].Price + orderBook.Asks[2].Price) * 0.05))
    }
    self.balanceAccount = function() {
        var account = exchange.GetAccount()
        if (!account) {
            return
        }
        self.account = account
        var now = new Date().getTime()
        if (self.orderBook.Bids.length > 0 && now - self.preCalc > (CalcNetInterval * 1000)) {
            self.preCalc = now
            var net = _N(account.Balance + account.FrozenBalance + self.orderBook.Bids[0].Price * (account.Stocks + account.FrozenStocks))
            if (net != self.preNet) {
                self.preNet = net
                LogProfit(net)
            }
        }
        self.btc = account.Stocks
        self.cny = account.Balance
        self.p = self.btc * self.prices[self.prices.length-1] / (self.btc * self.prices[self.prices.length-1] + self.cny)
        var balanced = false
        
        if (self.p < 0.48) {
            Log("开始平衡", self.p)
            self.cny -= 300
            if (self.orderBook.Bids.length >0) {
                exchange.Buy(self.orderBook.Bids[0].Price + 0.00, 0.01)
                exchange.Buy(self.orderBook.Bids[0].Price + 0.01, 0.01)
                exchange.Buy(self.orderBook.Bids[0].Price + 0.02, 0.01)
            }
        } else if (self.p > 0.52) {
            Log("开始平衡", self.p)
            self.btc -= 0.03
            if (self.orderBook.Asks.length >0) {
                exchange.Sell(self.orderBook.Asks[0].Price - 0.00, 0.01)
                exchange.Sell(self.orderBook.Asks[0].Price - 0.01, 0.01)
                exchange.Sell(self.orderBook.Asks[0].Price - 0.02, 0.01)
            }
        }
        Sleep(BalanceTimeout)
        var orders = exchange.GetOrders()
        if (orders) {
            for (var i = 0; i < orders.length; i++) {
                if (orders[i].Id != self.tradeOrderId) {
                    exchange.CancelOrder(orders[i].Id)
                }
            }
        }
    }

    self.poll = function() {
        self.numTick++
        self.updateTrades()
        self.updateOrderBook()
        self.balanceAccount()
        
        var burstPrice = self.prices[self.prices.length-1] * BurstThresholdPct
        var bull = false
        var bear = false
        var tradeAmount = 0
        if (self.account) {
            LogStatus(self.account, 'Tick:', self.numTick, ', 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
            tradeAmount = self.cny / self.bidPrice * 0.99
        } 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
            tradeAmount = self.btc
        }
        if (self.vol < BurstThresholdVol) {
            tradeAmount *= self.vol / BurstThresholdVol
        }
        
        if (self.numTick < 5) {
            tradeAmount *= 0.8
        }
        
        if (self.numTick < 10) {
            tradeAmount *= 0.8
        }
        
        if ((!bull && !bear) || tradeAmount < MinStock) {
            return
        }
        var tradePrice = bull ? self.bidPrice : self.askPrice
        while (tradeAmount >= MinStock) {
            var orderId = bull ? exchange.Buy(self.bidPrice, tradeAmount) : exchange.Sell(self.askPrice, tradeAmount)
            Sleep(200)
            if (orderId) {
                self.tradeOrderId = orderId
                var order = null
                while (true) {
                    order = exchange.GetOrder(orderId)
                    if (order) {
                        if (order.Status == ORDER_STATE_PENDING) {
                            exchange.CancelOrder(orderId)
                            Sleep(200)
                        } else {
                            break
                        }
                    }
                }
                self.tradeOrderId = 0
                tradeAmount -= order.DealAmount
                tradeAmount *= 0.9
                if (order.Status == ORDER_STATE_CANCELED) {
                    self.updateOrderBook()
                    while (bull && self.bidPrice - tradePrice > 0.1) {
                        tradeAmount *= 0.99
                        tradePrice += 0.1
                    }
                    while (bear && self.askPrice - tradePrice < -0.1) {
                        tradeAmount *= 0.99
                        tradePrice -= 0.1
                    }
                }
            }
        }
        self.numTick = 0
    }
    return self
}

function main() {
    var reaper = LeeksReaper()
    while (true) {
        reaper.poll()
        Sleep(TickInterval)
    }
}

Relacionados

Mais.

O Grande Rei do Hip-HopA estratégia falhou e os lucros vieram de uma renda de baixa diferença de alta frequência com zero taxas de processamento.

Kongbai979 self.vol到底是个啥?是一个ticker期间内所有交易量的总和吗?

diaTrader2018para (var i = 0; i < 15; i++) { self.prices[i] = trades[trades.length - 1].Price Não é um pouco de um problema, então não é que cada elemento na matriz de preços é o preço mais recente transação?

ouyou7035Eu tenho várias bolsas de câmbio sem taxas de processamento e com uma boa profundidade de negociação. Posso tentar essa estratégia?

BijiasuoIsso é ótimo, mas não vai funcionar.

SkyfffireNota de venda: 2000 exemplares, não oficial, com intenção de ligação

RajajackQuem já fez o teste, saiu e discutiu os benefícios?

ValennnQuando é que vem a versão de notas?

WuqianmingComo é que é possível executar uma troca gratuita sem o suporte do botvs, como é que é necessário escrever um API de troca?

JObrigado por compartilhar uma estratégia tão boa! exchange.CancelOrder ((orders[i].Id) O código de cancelamento aqui é um pouco problemático, o que significa que a verificação continua a ser feita. A partir da versão original do código, o pedido deve ter sido retirado depois de 10 segundos. O resto é praticamente normal, e depois de alterá-lo e colocá-lo em uma bolsa gratuita, sinto-me bem.

Kmstudio 66行prices需加.length

Ervilhas de neveQue língua é essa?

Zero. 平衡那里下单忘加上Price属性了。。已更正,有发现bug请及时提交.

AquárioO que parece ser uma estratégia para ganhar dinheiro, ou não vender e ficar com o seu dinheiro.

1213761768Não o deixei sair.

Zhang não se importaNão, o preço da oferta deve ser menor do que o preço da oferta, um é o preço da compra, um é o preço da venda.

BvxiaokPor favor, no cálculo do bidprice e do askprice, o pedido é feito como se o bidprice não fosse maior do que o askprice, então se o buy/sell estiver muito próximo, é provável que o preço seja mais alto ou mais baixo.

Eu adoro pelúcia.Eu escrevi um comentário e todos precisam de poder adicionar o meu WeChat Hoo_tongxue, e o mais importante é que é grátis.

Eu adoro pelúcia.A pele real é grossa o suficiente para vestir.

Esferas de carvãoQual é o mercado?

Zero.Este deve ser initializado para o preço mais recente, com a operação de mudança por trás.

Reabastecimento milagrosoA guerra dos robôs é uma guerra de robôs.

sucoSim, pode ser, esta cenoura é melhor.

SkyfffireQue o vendedor venda e que o comprador compre, e não discuta contigo.

A noiva também.O código-fonte é público, você pode comentar, vender 2000?

- Não. 请问zaif.jp现在还是免手续费吗?怎么通过认证呢

Xiahaohuan001Veja a identificação

J 在Zaif.jp上测试,买一卖一间经常就没有空间,用这个策略有什么问题吗?

JNão é verdade? Venha dar uma lição.

Xiahaohuan001Autor surpreso

JBom, ainda há algumas perguntas, por favor, e um outro post: https://www.botvs.com/bbs-topic/677

Zero.Se você tem alguma dúvida sobre esta estratégia, por favor, faça um post no fórum.

Zero.Obrigado pela sugestão, eu adicionei um parâmetro, tempo de espera do balanço do pedido, se quiser processar em simultâneo, você pode registrar a ID de cada ordem com o tempo de envio do pedido, e cancelar seletivamente, o que reduz o atraso, mas, logicamente, deve ser o primeiro a reabrir o balanço, porque nem todas as exchanges suportam o atributo de tempo de obtenção do pedido.

Xiahaohuan001Eu acho essa estratégia estranha, eu gosto disso.

Zero.Eu não tentei isso.

Orion1708Por favor, a mudança no valor padrão do parâmetro da política tem um grande impacto na política?

Zero.Ha ha, obrigado, já adicionado.

Zero.JavaScript

Zero.Frequência alta de transações

Sonhos pequenosO autor original também foi divulgado nos dias em que cobrou a taxa de inscrição.

Xiahaohuan001Por que os estrategistas de tendências têm medo dos custos de choque?