Пересадка:https://github.com/richox/okcoin-leeks-reaper
Я просто сделал трансплантацию, не тестировался на диске, заинтересован в изучении. Изобретатели количественного Tick-уровневого ретроспективного воспроизведения поддерживают воспроизведение Deepth и Trades, что позволяет непосредственно ретроспективно изучать стратегическую логику.
Ниже приведены оригинальные описания
Это высокочастотный торговый робот на криптовалютной торговой платформе OKCoin, который с июня 2016 года был продемонстрирован, а к середине января 2017 года был успешно очищен от первоначального вложения 6000 до 250000. В результате недавней политики высокого давления на биткоин со стороны центрального банка, основные платформы прекратили финансирование и начали взимать сборы за транзакции. Эта стратегия фактически не сработала.
Эта робот-программа основана на двух основных стратегиях:
Эта процедура требует сбалансированной позиции, т.е. (капитал + финансирование = денежные средства), чтобы при позиции 50% чистые активы не колебались с ценой, а также гарантировали, что в случае возникновения тенденционных колебаний.Взрыв.。
Мы хотим поблагодарить вас за следующие два проекта:
Спасибо OKCoin:
BTC: 3QFn1qfZMhMQ4FhgENR7fha3T8ZVw1bEeU
/*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) } }
Король хип-хапаЭта стратегия не сработала, и прибыль была получена за счет высокочастотного дохода с нулевой оплатой.
Кунгбай979 self.vol到底是个啥?是一个ticker期间内所有交易量的总和吗?
деньTrader2018for (var i = 0; i < 15; i++) { self.prices[i] = trades[trades.length - 1].Price }; Есть ли здесь какая-то проблема, так что каждый элемент в массиве prices является последней ценой сделки?
Коую 7035У меня есть несколько обменных пунктов, где я могу работать без оплаты. Можно попробовать эту стратегию?
БиджасуоОчень круто, к сожалению, не работает.
СкайффайрПримечание: продажа: 2000 экземпляров, неофициальный, имеется связь
РаджаякКто-нибудь из тех, кто пробовал, вышел и обсудил результаты?
ВаленнКогда появится аннотация?
УцзяньминКак можно работать на биржах без поддержки botvs, где можно торговать бесплатно, как написать API биржи?
JСпасибо, что поделились такой хорошей стратегией! exchange.CancelOrder ((orders[i].Id) код отмены здесь немного проблемен, постоянно отменяется при проверке. Посмотрев на исходную версию кода, вы должны были отменить заявку через 10 секунд. В общем-то, все остальное в принципе нормально, и после того, как я его изменил, я начал работать на бирже, которая не платит за обслуживание, и это хорошо.
Киль-студия 66行prices需加.length
снежный горошекКакой это язык?
Нуль 平衡那里下单忘加上Price属性了。。已更正,有发现bug请及时提交.
ВодолеиПо-видимому, есть тактики, чтобы заработать деньги, или не продавать, и оставить себе деньги.
1213761768Не выпускать раньше.
Чан НихиНет, цена предложения должна быть меньше, чем цена спроса, одна из которых - цена покупки, одна - цена продажи.
БвксяокПожалуйста, когда вы рассчитываете bidprice и askprice, вы делаете заказ так, как если бы не судили, что bidprice больше askprice, так что если купить или продать очень близко, вы вычисляете, что это скорее всего, что вы покупаете или продаете, будет ли это проблема?
Я люблю луковицу.Я написал аннотацию, в которой говорится, что все должны иметь возможность добавлять свой твит Hoo_tongxue, и самое главное - бесплатно.
Я люблю луковицу.На самом деле, кожа достаточно толстая, чтобы быть одетой.
Маленький угольный шарКакие биржи?
НульЭто должно быть инициировано как последняя цена, за которой следует операция Shift.
Перезагрузка - чудоЭто уже давно провалилось. Сейчас все боевые роботы.
сускиДа, да, я думаю, что это будет лучше.
СкайффайрПусть продавец продает, и пусть покупатель покупает, и не спорят с тобой.
И невесты тоже.Все выпустили исходный код, а вы комментируете, продать 2000?
Аккк 请问zaif.jp现在还是免手续费吗?怎么通过认证呢
Хиаохуань001Посмотрите на ID.
J 在Zaif.jp上测试,买一卖一间经常就没有空间,用这个策略有什么问题吗?
JЭто правда? Выходите и дайте им урок.
Хиаохуань001Удивительный автор
JХорошо, есть еще вопросы, пожалуйста, и есть еще одна статья: https://www.botvs.com/bbs-topic/677
НульЕсли у вас есть какие-либо вопросы или пожелания по поводу этой стратегии, пожалуйста, разместите их на форуме.
НульСпасибо за предложение, я добавил параметр, балансировать время ожидания ордера, если вы хотите одновременную обработку, вы можете записать ID каждого ордера с временем размещения ордера, а затем избирательно отменить, что уменьшит задержку, но логически, должен быть балансировать снова открыть первым, поскольку не все биржи поддерживают свойство времени получения ордера, поэтому платформа не добавляет это свойство в ордера, требуя собственных статистических данных.
Хиаохуань001Мне кажется, эта стратегия странная, мне нравится ((*^__^*)
НульЯ никогда не пытался это сделать, но вам нужно будет изучить это сами.
Орион 1708Очень сложно перенести Z. Пожалуйста, изменить параметры политики по умолчанию, что может сильно повлиять на политику?
НульХа-ха, спасибо, добавлено.
НульJavaScript
НульВысокая частота сделок
Изобретатели количественного измерения - мечтыАвтор также был опубликован только в те дни, когда он взимал плату за регистрацию.
Хиаохуань001Почему трендовые стратеги боятся ударных затрат?