Récemment, il y a beaucoup de stratégies Martingale discutées dans le groupe officiel de FMZ, et il n'y a pas beaucoup de stratégies Martingale de contrats de crypto-monnaie sur la plate-forme. Par conséquent, j'ai profité de l'occasion pour concevoir une stratégie Martingale simple pour les contrats à terme de crypto-monnaie. Pourquoi est-elle appelée stratégie Martingale? Parce que les risques potentiels de la stratégie Martin ne sont en effet pas petits, elle n'est pas conçue exactement selon la stratégie Martin. Cependant, ce type de stratégie comporte encore de nombreux risques, et les paramètres de la stratégie de type Martin sont étroitement liés au risque, et le risque ne doit pas être ignoré.
Cet article explique principalement et apprend de la conception de stratégies de type Martin.
L'équité totale est souvent utilisée lors de la conception de stratégies à terme de crypto-monnaie. C'est parce que les rendements doivent être calculés, en particulier lorsque vous devez calculer les rendements flottants. Puisque la position est occupée par la marge, l'ordre en attente est également occupé.exchange.GetAccount()
En fait, la plupart des bourses à terme de crypto-monnaie fournissent les données du capital total, mais cet attribut n'est pas uniformément regroupé sur FMZ.
Nous avons donc conçu des fonctions pour obtenir ces données selon différents échanges:
// OKEX V5 obtain total equity
function getTotalEquity_OKEX_V5() {
var totalEquity = null
var ret = exchange.IO("api", "GET", "/api/v5/account/balance", "ccy=USDT")
if (ret) {
try {
totalEquity = parseFloat(ret.data[0].details[0].eq)
} catch(e) {
Log("failed to obtain the total equity of the account!")
return null
}
}
return totalEquity
}
// Binance futures
function getTotalEquity_Binance() {
var totalEquity = null
var ret = exchange.GetAccount()
if (ret) {
try {
totalEquity = parseFloat(ret.Info.totalWalletBalance)
} catch(e) {
Log("failed to obtain the total equity of the account!")
return null
}
}
return totalEquity
}
LetotalEquity
dans le code est le capital total dont nous avons besoin. puis nous écrivons une fonction comme l'entrée d'appel, et appeler la fonction correspondante selon le nom de l'échange.
function getTotalEquity() {
var exName = exchange.GetName()
if (exName == "Futures_OKCoin") {
return getTotalEquity_OKEX_V5()
} else if (exName == "Futures_Binance") {
return getTotalEquity_Binance()
} else {
throw "This exchange is not supported"
}
}
Avant de concevoir la fonction principale et la logique principale, nous devons faire quelques préparatifs et concevoir quelques fonctions auxiliaires.
Annuler toutes les commandes en attente
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)
}
}
Cette fonction est familière à ceux qui lisent souvent le code d'exemple de stratégie sur le carré de stratégie FMZ, et de nombreuses stratégies ont utilisé des conceptions similaires.
Opérations de placement de contrats à terme
function trade(distance, price, amount) {
var tradeFunc = null
if (distance == "buy") {
tradeFunc = exchange.Buy
} else if (distance == "sell") {
tradeFunc = exchange.Sell
} else if (distance == "closebuy") {
tradeFunc = exchange.Sell
} else {
tradeFunc = exchange.Buy
}
exchange.SetDirection(distance)
return tradeFunc(price, amount)
}
function openLong(price, amount) {
return trade("buy", price, amount)
}
function openShort(price, amount) {
return trade("sell", price, amount)
}
function coverLong(price, amount) {
return trade("closebuy", price, amount)
}
function coverShort(price, amount) {
return trade("closesell", price, amount)
}
Il existe quatre directions pour le trading de contrats à terme: openLong, openShort, coverLong et coverShort. Nous avons donc conçu quatre fonctions d'ordre correspondant à ces opérations. Si vous considérez seulement l'ordre, alors il y a plusieurs facteurs nécessaires: direction, prix de l'ordre et volume de l'ordre.
Nous avons aussi conçu une fonction appelée:trade
pour gérer l'opération lorsquedistance
, price
, amount
sont spécifiées.
Les appels à la fonction openLong, openShort, coverLong et coverShort sont finalement complétés par letrade
fonction, c'est-à-dire la mise en place d'un ordre sur un marché à terme basé sur la distance, le prix et la quantité établis.
L'idée de la stratégie est très simple, prenez le prix actuel comme référence et placez des ordres de vente (short) et d'achat (long) à une certaine distance vers le haut ou vers le bas. Une fois la transaction terminée, tous les ordres restants seront annulés, puis un nouvel ordre de clôture sera placé à une certaine distance selon le prix de la position, et un ordre d'augmentation sera placé au prix actuel mis à jour, mais le volume de l'ordre ne sera pas doublé pour les positions supplémentaires.
Travaux initiaux En raison de l'ordre en attente, nous avons besoin de deux variables globales pour enregistrer l'identifiant de commande.
var buyOrderId = null
var sellOrderId = null
Ensuite, les paramètres d'interface de stratégie sont conçus pour utiliser l'option OKEX_V5 simulé bot, donc un certain traitement doit être fait dans le code:
var exName = exchange.GetName()
// Switch OKEX V5 simulated bot
if (isSimulate && exName == "Futures_OKCoin") {
exchange.IO("simulate", true)
}
Il y a aussi une option pour réinitialiser toutes les informations dans les paramètres d'interface, donc il devrait y avoir un traitement correspondant dans le code:
if (isReset) {
_G(null)
LogReset(1)
LogProfitReset()
LogVacuum()
Log("reset all data", "#FF0000")
}
Nous n'exécutons que des contrats perpétuels, donc l'écriture est fixée ici et réglée sur perpétuel seulement.
exchange.SetContractType("swap")
Ensuite, nous devons également considérer l'exactitude du prix de l'ordre et du montant de l'ordre. Si l'exactitude n'est pas correctement définie, l'exactitude sera perdue pendant le processus de calcul de la stratégie. Si les données ont un grand nombre de décimales, il est facile de faire rejeter l'ordre par l'interface d'échange.
exchange.SetPrecision(pricePrecision, amountPrecision)
Log("set precision", pricePrecision, amountPrecision)
Récupération de données simple par conception
if (totalEq == -1 && !IsVirtual()) {
var recoverTotalEq = _G("totalEq")
if (!recoverTotalEq) {
var currTotalEq = getTotalEquity()
if (currTotalEq) {
totalEq = currTotalEq
_G("totalEq", currTotalEq)
} else {
throw "failed to obtain initial equity"
}
} else {
totalEq = recoverTotalEq
}
}
Si vous voulez spécifier le capital initial total du compte lorsque la stratégie est en cours d'exécution, vous pouvez définir le paramètretotalEq
. Si ce paramètre est réglé sur -1, la stratégie lira les données de capital total stockées. S'il n'y a pas de données de capital total stockées, la valeur actuelle de capital total lu est utilisée comme le capital total initial de la stratégie en cours d'exécution. Après cela, une augmentation du capital total indique un profit et une diminution du capital total indique une perte. Si les données de capital total sont lues, la stratégie continuera à fonctionner avec ces données.
logique principale Après le travail initial, nous sommes finalement arrivés à la partie logique principale de la stratégie.
while (1) { // The main logic of the strategy is designed as an infinite loop
var ticker = _C(exchange.GetTicker) // Read the current market information first, mainly using the latest transaction price
var pos = _C(exchange.GetPosition) // Read current position data
if (pos.length > 1) { // Judging the position data, because of the logic of this strategy, it is unlikely that long and short positions will appear at the same time, so if there are long and short positions at the same time, an error will be thrown
Log(pos)
throw "Simultaneous long and short positions" // Throw an error to stop the strategy
}
//Depends on status
if (pos.length == 0) { // Make different operations according to the position status, when there is no position, pos.length == 0
// If you have not held a position, count the profit once
if (!IsVirtual()) {
var currTotalEq = getTotalEquity()
if (currTotalEq) {
LogProfit(currTotalEq - totalEq, "current total equity:", currTotalEq)
}
}
buyOrderId = openLong(ticker.Last - targetProfit, amount) // Open a buy order for a long position
sellOrderId = openShort(ticker.Last + targetProfit, amount) // Open a short sell order
} else if (pos[0].Type == PD_LONG) { // For long positions, the position and quantity of pending orders are different
var n = 1
var price = ticker.Last
buyOrderId = openLong(price - targetProfit * n, amount)
sellOrderId = coverLong(pos[0].Price + targetProfit, pos[0].Amount)
} else if (pos[0].Type == PD_SHORT) { // For short positions, the position and quantity of pending orders are different
var n = 1
var price = ticker.Last
buyOrderId = coverShort(pos[0].Price - targetProfit, pos[0].Amount)
sellOrderId = openShort(price + targetProfit * n, amount)
}
if (!sellOrderId || !buyOrderId) { // If one side of the pending order fails, cancel all pending orders and start over
cancelAll()
buyOrderId = null
sellOrderId = null
continue
}
while (1) { // The pending order is completed, start monitoring the order
var isFindBuyId = false
var isFindSellId = false
var orders = _C(exchange.GetOrders)
for (var i = 0 ; i < orders.length ; i++) {
if (buyOrderId == orders[i].Id) {
isFindBuyId = true
}
if (sellOrderId == orders[i].Id) {
isFindSellId = true
}
}
if (!isFindSellId && !isFindBuyId) { // Detected that both buy and sell orders have been filled
cancelAll()
break
} else if (!isFindBuyId) { // Detected buy order closing
Log("buy order closing")
cancelAll()
break
} else if (!isFindSellId) { // Detected sell order closing
Log("sell order closing")
cancelAll()
break
}
LogStatus(_D())
Sleep(3000)
}
Sleep(500)
}
Toute la logique et le design sont expliqués.
Laissez la stratégie passer par un marché du 19 mai.
On voit que la stratégie Martingale comporte encore certains risques.
Le vrai bot peut être exécuté avec le bot de simulation OKEX V5
Adresse stratégique:https://www.fmz.com/strategy/294957
Les stratégies sont principalement utilisées pour l'apprentissage, et l'argent réel doit être utilisé avec prudence~!