Dans les articles précédents, nous avons analysé les idées et la mise en œuvre du code de la version spontanée originale de la stratégie de récolte de profit à haute fréquence.
Analyse des bénéfices réalisés par le moissonneur (1) Analyse des bénéfices réalisés par le moissonneur (2)
Beaucoup d'utilisateurs dans le cercle de crypto-monnaie quantitative sont très préoccupés par la stratégie développée par un maître appeléimprimer de l'argentLa stratégie deimprimer de l'argentLa stratégie à haute fréquence est similaire au principe de la moissonneuse de bénéfices (le maître Xiaocao a également dit que le principe de la stratégie à haute fréquence est similaire à celui de la moissonneuse de bénéfices).
Par conséquent, j'étais tellement excité que je ne pouvais m'empêcher de vouloir modifier magiquement la stratégie, même le résultat et l'effet de la stratégie magiquement modifiée n'étaient rien face aux stratégies développées par les maîtres. Mais c'est aussi une pratique d'apprentissage pour la stratégie à haute fréquence. Les FMZ intéressés peuvent discuter et en apprendre ensemble.
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)
}
}
La stratégie est prévue pour le commerce sur le marché des contrats Binance USDT, qui prend en charge les positions unidirectionnelles. Par conséquent, la stratégie est modifiée et conçue en fonction des caractéristiques des positions unidirectionnelles (les positions unidirectionnelles sont plus pratiques pour la modification de la stratégie), et vous n'avez qu'à envisager d'acheter et de vendre, pas besoin de penser à la fermeture des positions. Cette façon de penser est également plus proche de la version au comptant de la moissonneuse de bénéfices.
La stratégie maintient essentiellement le critère de rupture de tendance des prix à court terme d'origine et la fourchette de rupture des prix à court terme est contrôlée par le paramètreburstThresholdPct
. Selon le critère de détermination du prix à court termebull
oubear
.
La stratégie supprime certains modules de l'original, tels que le module de solde. Une modification assez importante consiste à changer la mise en place des ordres à des ordres en attente dans le carnet de commandes et en attente d'exécution. Il est prévu qu'il ouvre des positions à un coût relativement faible sur un marché chaotique avec un jeu long-short féroce, suit la tendance à court terme et ferme des positions lorsque la tendance à court terme s'inverse, puis continue à inverser les ordres en attente et les positions ouvertes.
Bien que la stratégie soit une stratégie peu rentable, même avec des pertes, c'est un modèle très facile et utile pour un FMZer d'apprendre des stratégies à haute fréquence, d'observer les actions des stratégies à haute fréquence, d'observer les règles microscopiques du marché, etc. Le trading programmé et quantitatif doit être basé sur beaucoup de pratique, d'expérience et de théories.
On constate qu'il est plus difficile d'ouvrir et de fermer des positions lorsque la situation du marché n'est pas active.
À l'heure actuelle, aucune bonne orientation d'optimisation n'a été trouvée. Les élèves intéressés peuvent s'exprimer et en discuter ensemble.
Adresse stratégique:https://www.fmz.com/strategy/260806
La stratégie est seulement pour l'étude; quand le marché est plat, l'exécuter dans le bot pourrait faire des pertes.