La stratégie de négociation du réseau
(www.fmz.com)
L'idée de base du trading en grille est très simple. Au lieu de placer une transaction, nous plaçons plusieurs transactions formant un modèle de grille. Habituellement, celles-ci sont entrées sous forme d'ordres
Qu'est-ce que le trading de réseau et comment fonctionne-t-il? Le trading par grille est un jeu sur la volatilité du marché. Il y a deux raisons pour lesquelles il est préféré par les traders. La première est qu'il ne vous oblige pas à avoir une prédiction définitive sur la direction du marché.
La seconde est qu'il fonctionne bien sur les marchés volatils, où il n'y a pas de tendance claire
Le trading par grille est un type de trading d'analyse technique basé sur le mouvement dans des modèles de grille spécifiques. Le trading par grille est populaire dans le trading de devises.
La grille peut personnaliser la direction
Opération commerciale de base: acheter d'abord et ensuite vendre.
La grille commencera à envoyer un ordre d'achat au prix inférieur au premier prix, qui est le prix suivi du premier prix (deuxième dernier prix d'achat, troisième dernier prix d'achat...et ainsi de suite).
Après tout ordre d'achat est terminé, le programme sera sur la base du prix d'achat, ajouter le prix de la
Vendre à découvert d'abord et acheter ensuite pour couvrir: l'opération est tout le contraire
Le plus grand risque de cette stratégie est lorsque la tendance du marché est unilatérale et que les fluctuations des prix dépassent la grille.
Le code suivant a fait la grille avec une fonction d'arrêt automatique et de mouvement.
Commentaires:
La stratégie utilise une conception d'ordre en attente virtuelle, qui fournit une grande quantité de traitement pour l'échange afin de limiter le nombre d'ordres en attente, et résout le problème de manière flexible.
La grille logique est flexible dans sa conception et intelligente dans sa structure.
Calcul des profits et pertes, chaque algorithme statistique numérique peut être utilisé à titre de référence, et chaque conception de détection de condition est rigoureuse. (pour minimiser la possibilité de BUG)
Le code source vaut la peine d'être appris.
Pour plus d'informations, veuillez consulter:
https://www.fmz.com/strategy/112633
Code source:
// Code source: /* Paramètres d'interface (indiqués sous forme de variables globales dans le code) OpType Grille Direction Boîte déroulante (sélectionnée) Acheter d'abord, puis vendre. Le prix initial automatique automatique (vrai/faux) Le prix initial automatique numérique (numéro) 100 Nombre total numérique (nombre) 10 PriceGrid Intervalle numérique (numéro) 1 Différence de prix numérique (nombre) 2 QuantitéTypes de commande Taille boîte déroulante (sélectionnée) acheter et vendre le même montant Quantité numérique (nombre) de la transaction unique BAmountOnce@AmountType==1 Taille de commande numérique (nombre) 0.1 SAmountOnce@AmountType==1 Taille numérique (numéro) de l'ordre de vente 0.1 QuantitéCoefficient@AmountType==0 Différence de quantité Chaîne (chaîne) *1 AmountDot Le point décimal numérique (nombre) 3 ActiverProtectDiff Activer la protection contre les écarts Booléen (vrai/faux) faux ProtégerDiff@EnableProtectDiff Différence d'entrée de l'écart de protection des prix numérique (numéro) 20 CancelAllWS stop annule tous les ordres en attente Booléen (vrai/faux) vrai CheckInterval Numéro numérique de l'intervalle de vote (numéro) 2000 Intervalle d'échec de la réessai Numérique (numéro) 1300 RestoreProfit rétablit le dernier bénéfice Booléen (vrai/faux) faux Dernier bénéfice@RestoreProfit Dernier bénéfice numérique (nombre) 0 ProfitAsOrg@RestoreProfit Dernier bénéfice compté comme prix moyen Boole (vrai/faux) faux ActiverAccountCheck activer la vérification du solde Booléen (vrai/faux) vrai Définition de l'opération de démarrage de l'opération StopLoss@EnableStopLoss Perte flottante maximale numérique (nombre) 100 StopLossMode@EnableStopLoss Opération de perte post-stop Boîte déroulante (sélectionnée) Recycler et sortir Activation de l'option de prise de bénéfices en mode booléen (vrai/faux) StopWin@EnableStopWin Profit variable maximal Type de numéro (numéro) 120 StopWinMode@EnableStopWin boîte déroulante d'opération après prise de profit (sélectionnée) Recycler et sortir. Automove@EnableAccountVérifier le déplacement automatiqueBooléen (vrai/faux) faux MaxDistance@AutoMove distance maximale numérique (nombre) 20 MaxIdle@AutoMove temps d'arrêt maximal (secondes) numérique (nombre) 7200 Activation dynamique Tourne sur les commandes en attente dynamiques Booléen (vrai/faux) faux DynamicMax@EnableDynamic Distance d'expiration de l'ordre Numéro (nombre) 30 ResetData efface toutes les données au démarrage Boolean (vrai/faux) vrai Prix de précision longueur décimale numérique (numéro) 5 */
fonction hasOrder ((ordres, orderId) { // Vérifiez s'il existe une commande avec l'ID de commande dans les commandes de paramètres pour (var i = 0; i < orders.length; i++) { // Traverser des ordres pour vérifier s'il y a les mêmes id, s'il y en a alors retourner vrai si (ordres[i].Id == ordreId) { retourner true; Je ne sais pas. Je ne sais pas. retourner false; // Tout traversé, pas de déclencheur si signifie n'ont pas trouvé l'ordre avec l'ordre ID, retourner false Je ne sais pas.
fonction annulerPending() { // Annuler toutes les fonctions de commande en attente Var ret = faux; // Retourner la variable de la balise de réussite pendant (true) { // pendant boucle si (ret) { // Si ret est vrai alors Dormez pendant un certain temps Le sommeil (intervalle); Je ne sais pas. var commandes = _C(exchange.GetOrders); // Appeler l'API pour obtenir les informations d'ordre que l'échange n'a pas exécuté. si (ordres.length == 0) { // Si un tableau vide est renvoyé, l'échange n'a pas d'ordres non exécutés. pause; // Sauter hors de la boucle pendant Je ne sais pas.
for (var j = 0; j < orders.length; j++) { // Traverse the unfinished order array and use orders[j].Id one by one to cancel the order based on the index j.
exchange.CancelOrder(orders[j].Id, orders[j]);
ret = true; // Once there is a cancel operation, ret is assigned a value of true. Used to trigger above Sleep, wait for re-exchange.GetOrders detection
}
}
return ret; // return ret
}
fonction valuesToString(values, pos) { // Valeur convertie en une chaîne
Var résultat =
fonction Trader() { // fonction Trader, utilisant des fermetures.
Var vId = 0; // Identifiant de l'incrément de commande
Var orderBooks = []; // Livre de commandes
Var hisBooks = []; // Livre d'ordre historique
Var orderBooksLen = 0; // La longueur du carnet de commandes
this.Buy = fonction ((prix, montant, supplément) { // Fonction d'achat, paramètres: prix, quantité, informations détaillées
si (typeof(extra) ===
si (ordres[i].Id == order.Id) { // Lorsque vous trouvez un ordre avec le même id d'ordre dans orderBooks, attribuer une valeur de vrai à trouver, ce qui signifie trouver.
trouvé = vrai;
pause; // Sauter hors de la boucle actuelle
Je ne sais pas.
Je ne sais pas.
si (!found) { // Si ce n'est pas le cas, appuyez sur orderBooks[orderId] pour les commandes.
commandes.push ((orderBooks[orderId]); // Pourquoi voulez-vous pousser comme ça?
Je ne sais pas.
Je ne sais pas.
commandes de retour;
Je ne sais pas.
Cette.GetOrder = fonction ((orderId) { // Obtenez l'ordre
si (typeof(orderId) ===
var pfn = order.Type == ORDER_TYPE_BUY ? exchange.Buy : exchange.Sell; // Assign the corresponding API function reference to pfn according to the type of the order.
// That is, if the order type is a buy order, pfn is a reference to the exchange.Buy function, the same as the sell order.
if (order.Id == 0 && diff <= priceDiff) { // If the order order in the order book is not activated (ie Id is equal to 0) and the current price is less than or
// equal to the order plan price, the priceDiff passed in the parameter.
var realId = pfn(order.Price, order.Amount, order.Extra + "(distance: " + diff + (order.Type == ORDER_TYPE_BUY ? (" ask price: " + ticker.Buy) : (" bid price: " + ticker.Sell))+")");
// Execute order function, parameter passing price, quantity, order extension information + pending order distance + market data (ask price or bid price), return exchange order id
if (typeof(realId) === 'number') { // If the returned realId is a numeric type
order.Id = realId; // Assign the Id attribute of the current order order to the order book.
}
} else if (order.Id > 0 && diff > (priceDiff + 1)) { // If the order is active and the current distance is greater than the distance passed in by the parameter
var ok = true; // Declare a variable for tagging Initially set true
do { // Execute "do" first and then judge while
ok = true; // Ok assign true
exchange.CancelOrder(order.Id, "unnecessary" + (order.Type == ORDER_TYPE_BUY ? "buying" : "selling"), "placed order price:", order.Price, "volume:", order.Amount, ", distance:",
diff, order.Type == ORDER_TYPE_BUY ? ("ask price: " + ticker.Buy) : ("bid price: " + ticker.Sell));
// Cancel the pending order that is out of range. After canceling the order, print the current order information and the current distance diff.
Sleep(200); // Wait 200 milliseconds
orders = _C(exchange.GetOrders); // Call the API to get an uncompleted order in the exchange.
for (var i = 0; i < orders.length; i++) { // Traverse these unfinished orders.
if (orders[i].Id == order.Id) { // If the cancelled order is found in the list of orders that have not been completed by the exchange
ok = false; // Assign ok this variable to false, that is, no cancellation is successful.
}
}
} while (!ok); // If ok is false, then !ok is true and while will continue to repeat the loop, continue to cancel the order,
// and check if the cancellation is successful.
order.Id = 0; // Assigning a value of 0 to order.Id means that the current order is inactive.
}
}
};
}
fonction balanceAccount ((orgAccount, initAccount) { // Balance Account Function Parameter Initial account information when the strategy is started La fonction init est la suivante:
CALL the custom function cancelPending ((() pour annuler toutes les commandes en attente.
Var nowAccount = _C ((exchange.GetAccount); // Déclarer une variable nowAccount pour enregistrer les dernières informations sur le compte à l'heure actuelle.
Var slidePrice = 0.2; // Set the slip price when placing the order as 0.2 Il est possible de modifier le prix de la commande en fonction de la valeur de la commande
var ok = true; // Tag variable initialement défini comme vrai
pendant (true) { // pendant boucle
Var diff = _N ((nowAccount.Stocks - initAccount.Stocks); // Calculer la différence entre le compte courant et le compte initial
Si la valeur absolue de la différence de devise est inférieure au volume de transaction minimum de l'échange,
// le break saute hors de la boucle et n'effectue pas d'opérations d'équilibrage.
Je ne sais pas.
Je ne sais pas.
Var depth = _C ((exchange.GetDepth); // Obtenez l'information de profondeur d'échange Assignez à la variable de profondeur déclarée
Var books = diff > 0? depth.Bids : depth.Asks; // According the difference of the currency is greater than 0 or less than 0, extract the buy order array or
// sell order array in depth (equal to 0 will not be processed, it is break when it is judged to be less than GetMinStock) // vends l'ordre de vente en profondeur (équivalent à 0 ne sera pas traité, il est brisé quand il est jugé être inférieur à GetMinStock)
// La différence entre les pièces est supérieure à 0 pour vendre le solde, alors regardez le tableau des ordres d'achat
// la différence entre les pièces est inférieure à 0 est l'inverse.
Var n = 0; // Statement n initial est 0
Var prix = 0; // Statement prix initial 0
pour (var i = 0; i < books.length; i++) { // Traversant le tableau des ordres de vente ou de vente
n += books[i].Amount; // Accumuler le montant (la quantité de commande) pour chaque commande basée sur l'index traversé
si (n >= Math.abs ((diff)) { // Si la quantité d'ordre cumulative n est supérieure ou égale à la différence de monnaie, alors:
Le prix de l'ordre indexé actuel, assigner à prix
break; // Jump out of the current for traversal cycle (Sauvez le courant pour le cycle de traversation)
Je ne sais pas.
Je ne sais pas.
Var pfn = diff > 0? Sell: exchange.Buy; // Pass the sell order API (exchange.Sell) or the next buy order API (exchange.Buy) reference to the declared pfn (Exchange.Buy) est une référence à l'ordre de vente de l'API (exchange.Buy)
// basé sur la différence de devise supérieure ou inférieure à 0
Var amount = Math.abs ((diff); // Le montant de l'ordre à équilibrer est diff, la différence dans la monnaie, assignée à la variable de montant déclaré.
var price = diff > 0? (prix - slidePrice) : (prix + slidePrice); // The direction of buying and selling according to the difference in the currency, increase or decrease the
// prix de glissement basé sur le prix (le prix de glissement est de le rendre plus facile à négocier), et puis l'assigner au prix
Log ((
var STATE_WAIT_OPEN = 0; // Utilisé pour l' état de chaque nœud dans le fishTable le nombre de fois où le système est désactivé. le nombre de fois où le système est désactivé. Var ProfitCount = 0; // Compte des résultats Var BuyFirst = vrai; // Paramètres d'interface initiaux var IsSupportGetOrder = true; // déterminer le support d'échange de la fonction GetOrder API, une variable globale, utilisée pour déterminer le début de la fonction principale var LastBusy = 0; // Enregistrer le dernier objet de temps traité
fonction setBusy() { // Définir le temps d'occupation LastBusy = new Date(); // Assigner LastBusy à l'objet de l'heure en cours Je ne sais pas.
la fonction isTimeout() { // Détermine si elle est à temps si (MaxIdle <= 0) { // Temps d'inactivité maximal (en fonction du déplacement automatique de la grille), // si le temps d'arrêt maximal MaxIdle est inférieur ou égal à 0 retourner false; // retourne false, ne juge pas le temps d'arrêt. c'est-à-dire toujours retourner false sans temps d'arrêt. Je ne sais pas. var now = new Date ((); // Obtenir l'objet de l'heure actuelle si (((now.getTime() - LastBusy.getTime()) / 1000) >= MaxIdle) { // Utilisez la fonction getTime de l'objet temps en cours pour obtenir l'horodatage et l'horodatage de LastBusy pour calculer la différence, // Divisez par 1000 pour calculer le nombre de secondes entre les deux objets de temps. // Détermine si elle est supérieure au temps d'inactivité maximal MaxIdle LastBusy = maintenant; // Si elle est supérieure à, mettre à jour LastBusy à l'objet de temps actuel maintenant retourner true; // retourne true, qui est un temps mort. Je ne sais pas. retourner false; // retourner false sans délai d'attente Je ne sais pas.
fonction onexit() { // La fonction de fermeture lorsque le programme sort.
si (CancelAllWS) { // Pour annuler toutes les commandes en attente lors de l'arrêt, appelez cancelPending() pour annuler toutes les commandes en attente.
Log ((
fonction pêche ((orgCompte, poissonCompte) { // Paramètres de la mise en mer: informations sur le compte, nombre de prises en mer
setBusy(); // Réglez LastBuys à l'horodatage actuel
var compte = _C(exchange.GetAccount); // Déclarer une variable de compte pour obtenir les informations du compte courant et l'assigner.
Log ((account); // Sortie des informations du compte au début de l'appel à la fonction de pêche.
Var InitAccount = compte; // Déclarer une variable InitAccount et l'assigner avec compte.
// cette coulée, utilisée pour calculer les bénéfices et pertes flottants.
var ticker = _C(exchange.GetTicker); // Obtenez la valeur de cotation attribuée à la variable ticker déclarée
var amount = _N(AmountOnce); // Selon le nombre de paramètres d'interface, utilisez _N pour traiter les décimales (_N par défaut à 2 bits) et les attribuer à amount.
var amountB = [amount]; // Déclarer une variable appelée amountB est un tableau, initialiser un élément avec amount
Var amountS = [amount]; // Déclarer une variable appelée amountS...
si (typeof(AmountType)!==
Je ne sais pas.
// Initialisez la table des poissons
Var fishTable = {}; // Déclarer un objet de grille
Var uuidTable = {}; // Objet de la table de code d'identification
Var needStocks = 0; // Variable des pièces requises
Var needMoney = 0; // Variable de l'argent requis
Var actuelNeedMoney = 0; // En fait besoin d'argent
var actualNeedStocks = 0; // Les pièces réellement nécessaires
var notEnough = false; // Variante de balise sous-financée, initialement définie sur false
Var canNum = 0; // Grille disponible
pour (var idx = 0; idx < AllNum; idx++) { // La structure est traversée selon le nombre de grille AllNum.
Var prix = _N((BuyFirst? FirstPrice - (idx * PriceGrid) : FirstPrice + (idx * PriceGrid)), Précision);
// Lors de la traversée de la construction, le prix idx de l'indice actuel est défini selon BuyFirst.
needStocks += amountS[idx]; // Le nombre de pièces vendues s'accumule progressivement avec le cycle. (accumulé par le tableau de quantité des ordres de vente à needStocks un par un)
needMoney += prix * quantitéB[idx]; // La quantité d'argent nécessaire à l'achat est progressivement accumulée avec le cycle.
si (BuyFirst) { // Traitement de l' achat en premier
si (_N(needMoney) <= _N ((account.Balance)) { // Si la grille nécessite moins d'argent que le montant disponible sur le compte
actualNeedMondy = needMoney; // Assigné au montant réel de l'argent requis
actualisNeedStocks = needStocks; // Assignation au nombre réel de pièces requises.
canNum++; // Nombre cumulé de grilles disponibles
} else { // _N(needMoney) <= _N(account.Balance) Si cette condition n'est pas remplie, régler la variable de la balise sous-financée sur vrai
notEnough = vrai;
Je ne sais pas.
{ \ pos (192,230) } autre { \ pos (192,230) } Traitement de la vente en premier
si (_N(needStocks) <= _N(account.Stocks)) { // Vérifiez si le nombre de pièces requis est inférieur au nombre de pièces disponibles sur le compte
ActuelNeedMondy = besoin d'argent; // affectation
Les stocks actuels de besoins = stocks de besoins;
canNum++; // Nombre cumulé de grilles disponibles
{ \ pos (192,230) } autre
notEnough = true; // S'il n'est pas satisfait aux conditions de financement
Je ne sais pas.
Je ne sais pas.
fishTable[idx] = STATE_WAIT_OPEN; // Selon l'index idx actuel, définir l'état du membre idx (nœud de la grille) de l'objet de la grille,
// initialement STATE_WAIT_OPEN (attendant d'ouvrir la position)
uuidTable[idx] = -1; // L'objet numéroté initie également sa propre valeur idx (le nœud correspondant au fishTable) à -1 en fonction de l'idx actuel.
Je ne sais pas.
si (!EnableAccountCheck && (canNum < AllNum)) { // Si la vérification des fonds n'est pas activée, et le nombre de grilles (le nombre total de nœuds) où le nœud est plus petit
// que le paramètre d'interface peut être ouvert.
Log ((
lancer
var trader = new Trader(); // Constructs a Trader object, assigning it to the trader variable declared here.
var OpenFunc = BuyFirst ? exchange.Buy : exchange.Sell; // According to whether to buy and sell first, set the open function OpenFunc to refer to exchange.Buy or exchange.Sell
var CoverFunc = BuyFirst ? exchange.Sell : exchange.Buy; // same as above
if (EnableDynamic) { // Set OpenFunc/CoverFunc again according to whether the interface parameter EnableDynamic is enabled.
OpenFunc = BuyFirst ? trader.Buy : trader.Sell; // The member function Buy that references the trader object is used for dynamic pending orders (mainly because
// some exchanges limit the number of pending orders, so virtual dynamic pending orders are required)
CoverFunc = BuyFirst ? trader.Sell : trader.Buy; // same as above
}
var ts = new Date(); // Create a time object at this time (assigned to ts) to record the time at the moment.
var preMsg = ""; // Declare a variable to record the last message, the initial set to empty string
var profitMax = 0; // Maximum return
while (true) { // The main logic after the grid is casted
var now = new Date(); // Record the time when the current cycle started
var table = null; // Declare a variable
if (now.getTime() - ts.getTime() > 5000) { // Calculate whether the difference between the current time now and the recorded time ts is greater than 5000 milliseconds
if (typeof(GetCommand) == 'function' && GetCommand() == "Receiving grid") { // Check if the strategy interaction control command "receives the grid" is received,
// stops and balances to the initial state.
Log("Start executing commands to perform grid operations"); // Output information
balanceAccount(orgAccount, InitAccount); // Perform a balancing function to balance the number of coins to the initial state
return false; // This time the grid function is fishing and return false
}
ts = now; // Update ts with current time now for next comparison time
var nowAccount = _C(exchange.GetAccount); // Declare the nowAccount variable and initially been set as the current account information.
var ticker = _C(exchange.GetTicker); // Declare the ticker variable and initially been set as the current market information.
if (EnableDynamic) { // If you enable dynamic pending orders
trader.Poll(ticker, DynamicMax); // Call the Poll function of the trader object to detect and process all orders based on the
// current ticker market and the interface parameter DynamicMax.
}
var amount_diff = (nowAccount.Stocks + nowAccount.FrozenStocks) - (InitAccount.Stocks + InitAccount.FrozenStocks); // Calculate the current coin difference
var money_diff = (nowAccount.Balance + nowAccount.FrozenBalance) - (InitAccount.Balance + InitAccount.FrozenBalance); // Calculate the current money difference
var floatProfit = _N(money_diff + (amount_diff * ticker.Last)); // Calculate the current floating profit and loss of this time of casting grid
var floatProfitAll = _N((nowAccount.Balance + nowAccount.FrozenBalance - orgAccount.Balance - orgAccount.FrozenBalance) + ((nowAccount.Stocks + nowAccount.FrozenStocks
- orgAccount.Stocks - orgAccount.FrozenStocks) * ticker.Last));
// Calculate the overall floating profit and loss
var isHold = Math.abs(amount_diff) >= exchange.GetMinStock(); // If the absolute value of the coin difference at this moment is greater than the minimum trading
// volume of the exchange, it means that the position has been held.
if (isHold) { // If you have already held a position, execute the setBusy() function, which will update the LastBusy time.
setBusy(); // That is, after opening the position, the opening of the opening mechanism is started.
}
profitMax = Math.max(floatProfit, profitMax); // Refresh the maximum floating profit and loss
if (EnableAccountCheck && EnableStopLoss) { // If you initiate account detection and start a stop loss
if ((profitMax - floatProfit) >= StopLoss) { // If the maximum floating profit or loss minus the current floating profit or loss is greater than or equal to
// the maximum floating loss value, execute the code inside the curly braces
Log("Current floating profit a