Le trading à haute fréquence est un domaine difficile et compétitif qui repose sur une exécution rapide des transactions et des connaissances sensibles sur la microstructure du marché. Une stratégie notable est le Penny Jump, qui se concentre sur l'exploitation des "éléphants" sur le marché pour obtenir de petits profits mais fréquents.
Dans le marché boursier, les "éléphants" désignent généralement les investisseurs institutionnels qui souhaitent acheter ou vendre un grand nombre d'actions, mais qui ne sont pas disposés à négocier au prix du marché.
Par exemple, supposons que la profondeur initiale d'un marché boursier était la suivante: 200 ∙ $1.01 x $1.03 ∙ 200. Puis un " éléphant " entre et place un ordre d'achat de 3000 actions à 1,01 $ chacune. À ce stade, la profondeur du marché changera à 3 200 ∙ $1.01 x $1.03 ∙ 200. Cette action est comme introduire un " éléphant ", qui devient le centre d'attention des autres participants au marché.
Marché concurrentiel Pour les traders à haute fréquence, leurs profits proviennent principalement de l'analyse de la microstructure du marché pour spéculer sur les intentions des autres traders.
Le dilemme de l'éléphant Bien que les éléphants puissent souhaiter opérer à grande échelle sur le marché, leurs actions révèlent également leurs intentions commerciales, ce qui les rend cibles pour les traders à haute fréquence.
La tromperie sur le marché En réalité, les grands investisseurs institutionnels ne placent généralement pas un grand nombre d'ordres d'achat ou de vente sur le marché de manière flagrante, car un tel comportement pourrait conduire d'autres participants au marché à prendre des contre-mesures ou même à manipuler le marché.
L'idée de base de la stratégie Penny Jump est qu'une fois qu'un
Non seulement cela, mais les traders à haute fréquence peuvent également réaliser des bénéfices après l'achat même si le prix ne monte pas, car ils savent que le grand acteur a soutenu le prix de base; ils peuvent donc rapidement vendre leurs actions à ce grand acteur et obtenir de minuscules bénéfices d'arbitrage.
Le code source de la stratégie:https://www.fmz.com/strategy/358
Le code de stratégie fourni ci-dessus est un exemple, utilisé pour implémenter la stratégie Penny Jump. Ci-dessous est une explication détaillée du code, permettant aux débutants de comprendre son fonctionnement:
var Counter = {
i: 0,
w: 0,
f: 0
};
// Variables
var InitAccount = null;
function CancelAll() {
while (true) {
var orders = _C(exchange.GetOrders);
if (orders.length == 0) {
break;
}
for (var i = 0; i < orders.length; i++) {
exchange.CancelOrder(orders[i].Id);
}
Sleep(Interval);
}
}
function updateStatus(msg) {
LogStatus("Number of debugging sessions:", Counter.i, "succeeded:", Counter.w, "failed:", Counter.f, "\n"+msg+"#0000ff\n"+new Date());
}
function main() {
if (DisableLog) {
EnableLog(false);
}
CancelAll();
InitAccount = _C(exchange.GetAccount);
Log(InitAccount);
var i = 0;
var locks = 0;
while (true) {
Sleep(Interval);
var depth = _C(exchange.GetDepth);
if (depth.Asks.length === 0 || depth.Bids.length === 0) {
continue;
}
updateStatus("Searching within the elephant... Buy one: " + depth.Bids[0].Price + ", Sell one:" + depth.Asks[0].Price + ", Lock times: " + locks);
var askPrice = 0;
for (i = 0; i < depth.Asks.length; i++) {
if (depth.Asks[i].Amount >= Lot) {
askPrice = depth.Asks[i].Price;
break;
}
}
if (askPrice === 0) {
continue;
}
var elephant = null;
// skip Bids[0]
for (i = 1; i < depth.Bids.length; i++) {
if ((askPrice - depth.Bids[i].Price) > ElephantSpace) {
break;
}
if (depth.Bids[i].Amount >= ElephantAmount) {
elephant = depth.Bids[i];
break;
}
}
if (!elephant) {
locks = 0;
continue;
}
locks++;
if (locks < LockCount) {
continue;
}
locks = 0;
updateStatus("Debug the elephant... The elephant is in gear " + i + ", " + JSON.stringify(elephant));
exchange.Buy(elephant.Price + PennyTick, Lot, "Bids[" + i + "]", elephant);
var ts = new Date().getTime();
while (true) {
Sleep(CheckInterval);
var orders = _C(exchange.GetOrders);
if (orders.length == 0) {
break;
}
if ((new Date().getTime() - ts) > WaitInterval) {
for (var i = 0; i < orders.length; i++) {
exchange.CancelOrder(orders[i].Id);
}
}
}
var account = _C(exchange.GetAccount);
var opAmount = _N(account.Stocks - InitAccount.Stocks);
if (opAmount < 0.001) {
Counter.f++;
Counter.i++;
continue;
}
updateStatus("Successful payment: " + opAmount +", Start taking action...");
exchange.Sell(elephant.Price + (PennyTick * ProfitTick), opAmount);
var success = true;
while (true) {
var depth = _C(exchange.GetDepth);
if (depth.Bids.length > 0 && depth.Bids[0].Price <= (elephant.Price-(STTick*PennyTick))) {
success = false;
updateStatus("Didn't get it, start to stop loss, currently buying one: " + depth.Bids[0].Price);
CancelAll();
account = _C(exchange.GetAccount);
var opAmount = _N(account.Stocks - InitAccount.Stocks);
if (opAmount < 0.001) {
break;
}
exchange.Sell(depth.Bids[0].Price, opAmount);
}
var orders = _C(exchange.GetOrders);
if (orders.length === 0) {
break;
}
Sleep(CheckInterval);
}
if (success) {
Counter.w++;
} else {
Counter.f++;
}
Counter.i++;
var account = _C(exchange.GetAccount);
LogProfit(account.Balance - InitAccount.Balance, account);
}
}
Je vais analyser votre code de stratégie ligne par ligne pour vous aider à comprendre son fonctionnement en détail.
var Counter = {
i: 0,
w: 0,
f: 0
};
Ce code initie un objet nommé Counter, qui est utilisé pour suivre les informations statistiques de trading d'une stratégie.
Ces attributs seront enregistrés et mis à jour au cours du processus d'exécution de la stratégie.
var InitAccount = null;
Cette ligne de code initie une variable appelée InitAccount, qui stocke les informations du compte lorsque la stratégie commence à s'exécuter.
function CancelAll() {
while (true) {
var orders = _C(exchange.GetOrders);
if (orders.length == 0) {
break;
}
for (var i = 0; i < orders.length; i++) {
exchange.CancelOrder(orders[i].Id);
}
Sleep(Interval);
}
}
C'est une fonction appeléeCancelAll()
L'objectif est d'annuler toutes les commandes non exécutées sur le marché.
while (true)
: C'est une boucle infinie, elle continuera à fonctionner jusqu'à ce qu'il n'y ait plus d'ordres inachevés.var orders = _C(exchange.GetOrders)
: Cette ligne de code utilise la fonction exchange.GetOrders pour récupérer tous les ordres en attente sur le compte courant et les stocker dans la variable des ordres.if (orders.length == 0)
: Cette ligne de code vérifie les commandes inachevées. Si la longueur du tableau des commandes est 0, cela signifie qu'il n'y a pas d'ordres inachevés et que la boucle sera interrompue (rupture).for (var i = 0; i < orders.length; i++)
: Il s'agit d'une boucle for qui itère à travers tous les ordres inachevés.exchange.CancelOrder(orders[i].Id)
: Cette ligne de code utilise la fonction exchange.CancelOrder() pour annuler chaque commande par son ID.Sleep(Interval)
: Cette ligne de code introduit une période d'attente, en faisant une pause pendant un certain temps (en millisecondes), afin de s'assurer que l'opération d'annulation des ordres ne soit pas trop fréquente.Cette ligne de code introduit une période d'attente, en faisant une pause pendant un certain temps (en millisecondes), afin de garantir que l'opération d'annulation des ordres ne soit pas trop fréquente.
function updateStatus(msg) {
LogStatus("Number of debugging sessions:", Counter.i, "succeeded:", Counter.w, "failed:", Counter.f, "\n" + msg + "#0000ff\n" + new Date());
}
C'est une fonction appeléeupdateStatus(msg)
, qui est utilisé pour mettre à jour et enregistrer les informations sur l'état des transactions. Il accepte un paramètre msg, qui contient généralement des informations sur l'état actuel du marché. Les opérations spécifiques de la fonction comprennent:
En utilisant leLogStatus()
fonction pour enregistrer les informations affichées dans la barre d'état pendant l'exécution de la stratégie.
Lemsg
Paramètre est joint, qui contient des informations sur l'état actuel du marché.
L'horodatage actuel (new Date()
) est ajoutée pour afficher les informations relatives à l'heure.
Cette fonction a pour but d'enregistrer et de mettre à jour les informations sur l'état des transactions pour le suivi et l'analyse lors de l'exécution de la stratégie.
function main() {
if (DisableLog) {
EnableLog(false);
}
CancelAll();
InitAccount = _C(exchange.GetAccount);
Log(InitAccount);
var i = 0;
var locks = 0;
while (true) {
Sleep(Interval);
var depth = _C(exchange.GetDepth);
if (depth.Asks.length === 0 || depth.Bids.length === 0) {
continue;
}
updateStatus("Searching within the elephant... Buy one: " + depth.Bids[0].Price + ", Sell one:" + depth.Asks[0].Price + ", Lock times: " + locks);
var askPrice = 0;
for (i = 0; i < depth.Asks.length; i++) {
if (depth.Asks[i].Amount >= Lot) {
askPrice = depth.Asks[i].Price;
break;
}
}
if (askPrice === 0) {
continue;
}
var elephant = null;
// skip Bids[0]
for (i = 1; i < depth.Bids.length; i++) {
if ((askPrice - depth.Bids[i].Price) > ElephantSpace) {
break;
}
if (depth.Bids[i].Amount >= ElephantAmount) {
elephant = depth.Bids[i];
break;
}
}
if (!elephant) {
locks = 0;
continue;
}
locks++;
if (locks < LockCount) {
continue;
}
locks = 0;
updateStatus("Debug the elephant... The elephant is in gear " + i + ", " + JSON.stringify(elephant));
exchange.Buy(elephant.Price + PennyTick, Lot, "Bids[" + i + "]", elephant);
var ts = new Date().getTime();
while (true) {
Sleep(CheckInterval);
var orders = _C(exchange.GetOrders);
if (orders.length == 0) {
break;
}
if ((new Date().getTime() - ts) > WaitInterval) {
for (var i = 0; i < orders.length; i++) {
exchange.CancelOrder(orders[i].Id);
}
}
}
var account = _C(exchange.GetAccount);
var opAmount = _N(account.Stocks - InitAccount.Stocks);
if (opAmount < 0.001) {
Counter.f++;
Counter.i++;
continue;
}
updateStatus("Successful payment: " + opAmount +", Start taking action...");
exchange.Sell(elephant.Price + (PennyTick * ProfitTick), opAmount);
var success = true;
while (true) {
var depth = _C(exchange.GetDepth);
if (depth.Bids.length > 0 && depth.Bids[0].Price <= (elephant.Price-(STTick*PennyTick))) {
success = false;
updateStatus("Didn't get it, start to stop loss, currently buying one: " + depth.Bids[0].Price);
CancelAll();
account = _C(exchange.GetAccount);
var opAmount = _N(account.Stocks - InitAccount.Stocks);
if (opAmount < 0.001) {
break;
}
exchange.Sell(depth.Bids[0].Price, opAmount);
}
var orders = _C(exchange.GetOrders);
if (orders.length === 0) {
break;
}
Sleep(CheckInterval);
}
if (success) {
Counter.w++;
} else {
Counter.f++;
}
Counter.i++;
var account = _C(exchange.GetAccount);
LogProfit(account.Balance - InitAccount.Balance, account);
}
}
C'est la fonction d'exécution principale.main()
La première partie de la stratégie, qui contient la logique de base de la stratégie, explique ses opérations ligne par ligne:
if (DisableLog)
: Cette ligne de code vérifie si la variable DisableLog est vraie, et si c'est le cas, elle désactivera l'enregistrement des journaux.
CancelAll()
: Appelez la fonction CancelAll( expliquée précédemment pour vous assurer qu'il n'y a pas de commandes inachevées.
InitAccount = _C(exchange.GetAccount)
: Cette ligne de code récupère les informations sur le compte courant et les stocke dans la variable InitAccount.
var i = 0;
etvar locks = 0;
: Initialiser deux variables, i et verrous, qui seront utilisées dans la logique de stratégie ultérieure.
while (true)
: Il s'agit d'une boucle infinie, principalement utilisée pour l'exécution continue de stratégies.
Ensuite, nous expliquerons la logique stratégique principale au sein de lawhile (true)
boucle ligne par ligne.
while (true) {
Sleep(Interval);
var depth = _C(exchange.GetDepth);
if (depth.Asks.length === 0 || depth.Bids.length === 0) {
continue;
}
updateStatus("Searching within the elephant... Buy one: " + depth.Bids[0].Price + ", Sell one:" + depth.Asks[0].Price + ", Lock times: " + locks);
Sleep(Interval)
: Cette ligne de code permet à la stratégie de dormir pendant une période de temps, afin de contrôler la fréquence d'exécution de la stratégie.
var depth = _C(exchange.GetDepth)
: Obtenir les informations actuelles sur la profondeur du marché, y compris les prix et les quantités des ordres de vente et d'achat.
if (depth.Asks.length === 0 || depth.Bids.length === 0)
: Cette ligne de code vérifie les informations de profondeur du marché, en s'assurant que les ordres de vente et d'achat existent.
updateStatus("Searching within the elephant... Buy one: " + depth.Bids[0].Price + ", Sell one:" + depth.Asks[0].Price + ", Lock times: " + locks)
: Cette ligne de code appelle la fonction updateStatus pour mettre à jour les informations d'état de la stratégie. Elle enregistre l'état actuel du marché, y compris le prix d'enchère le plus élevé, le prix d'enchère le plus bas et les temps de verrouillage précédents (verrouillage).
var askPrice = 0;
for (i = 0; i < depth.Asks.length; i++) {
if (depth.Asks[i].Amount >= Lot) {
askPrice = depth.Asks[i].Price;
break;
}
}
if (askPrice === 0) {
continue;
}
var elephant = null;
var askPrice = 0;
: Initialisez la variable askPrice, elle sera utilisée pour stocker le prix des ordres de vente qui répondent aux conditions.
for (i = 0; i < depth.Asks.length; i++)
: Il s'agit d'une boucle for utilisée pour traverser les informations sur le prix et la quantité des ordres de vente sur le marché.
if (depth.Asks[i].Amount >= Lot)
: Dans la boucle, vérifiez si la quantité de chaque ordre de vente est supérieure ou égale au lot spécifié (compte à main). Si oui, stockez le prix de cet ordre de vente dans askPrice et terminez la boucle.
if (askPrice === 0)
: Si aucun ordre de vente ne répond aux conditions (askPrice est toujours 0), la stratégie continuera d'attendre et de sauter les opérations suivantes.
var elephant = null;
: Initialisez la variable éléphant, elle sera utilisée pour stocker les informations d'ordre d'achat identifiées comme
for (i = 1; i < depth.Bids.length; i++) {
if ((askPrice - depth.Bids[i].Price) > ElephantSpace) {
break;
}
if (depth.Bids[i].Amount >= ElephantAmount) {
elephant = depth.Bids[i];
break;
}
}
if (!elephant) {
locks = 0;
continue;
}
locks++;
if (locks < LockCount) {
continue;
}
locks = 0;
Continuer à parcourir les informations sur le prix et la quantité des ordres d'achat sur le marché, en sautant le premier ordre d'achat (offres[0]).
if ((askPrice - depth.Bids[i].Price) > ElephantSpace)
: Vérifiez si l'écart entre le prix d'enchère actuel et le prix d'enchère est supérieur à ElephantSpace.
if (depth.Bids[i].Amount >= ElephantAmount)
: Vérifiez si la quantité de l'ordre d'achat actuel est supérieure ou égale à ElephantAmount. Si oui, stockez les informations de l'ordre d'achat dans la variable elephant.
if (!elephant)
: Si l'éléphant n'est pas trouvé, réinitialisez le nombre de verrouillage à 0 et continuez à attendre.
locks++
: Si l'éléphant est trouvé, augmentez le nombre de verrouillages. Ceci est pour s'assurer que la stratégie est exécutée seulement après avoir confirmé l'existence de l'éléphant plusieurs fois sur une période de temps.
if (locks < LockCount)
: Vérifiez si le nombre de temps de verrouillage satisfait à l'exigence (LockCount).
updateStatus("Debug the elephant... The elephant is in gear " + i + ", " + JSON.stringify(elephant));
exchange.Buy(elephant.Price + PennyTick, Lot, "Bids[" + i + "]", elephant);
var ts = new Date().getTime();
while (true) {
Sleep(CheckInterval);
var orders = _C(exchange.GetOrders);
if (orders.length == 0) {
break;
}
if ((new Date().getTime() - ts) > WaitInterval) {
for (var i = 0; i < orders.length; i++) {
exchange.CancelOrder(orders[i].Id);
}
}
}
updateStatus("Debug the elephant... The elephant is in gear " + i + ", " + JSON.stringify(elephant))
: Appelez la fonction updateStatus pour enregistrer l'état actuel de la stratégie, y compris la position de l'engrenage de l'éléphant trouvé et les informations connexes.
exchange.Buy(elephant.Price + PennyTick, Lot, "Bids[" + i + "]", elephant)
: Utilisez la fonction exchange.Buy pour acheter l'éléphant trouvé. Le prix d'achat est elephant.Price + PennyTick, la quantité d'achat est Lot, et décrivez l'opération d'achat comme
var ts = new Date().getTime()
: Obtenir l'horodatage de l'heure actuelle pour le calcul ultérieur des intervalles de temps.
while (true)
: Entrez une nouvelle boucle infinie, utilisée pour attendre l'exécution des ordres d'achat
Sleep(CheckInterval)
: La stratégie dort pendant un certain temps pour contrôler la fréquence de vérification de l'état des commandes.
var orders = _C(exchange.GetOrders)
Obtenir toutes les informations relatives aux commandes du compte courant.
if (orders.length == 0)
: Vérifiez s'il y a des commandes inachevées, sinon, coupez la boucle.
(new Date().getTime() - ts) > WaitInterval
: Calculer l'intervalle de temps entre l'heure actuelle et le moment où l'éléphant a été acheté.
for (var i = 0; i < orders.length; i++)
Traversez toutes les commandes inachevées.
exchange.CancelOrder(orders[i].Id)
: Utilisez la fonction exchange.CancelOrder pour annuler chaque commande inachevée.
var account = _C(exchange.GetAccount);
var opAmount = _N(account.Stocks - InitAccount.Stocks);
if (opAmount < 0.001) {
Counter.f++;
Counter.i++;
continue;
}
updateStatus("Successful payment: " + opAmount + ", Start taking action...");
exchange.Sell(elephant.Price + (PennyTick * ProfitTick), opAmount);
var success = true;
while (true) {
var depth = _C(exchange.GetDepth);
if (depth.Bids.length > 0 && depth.Bids[0].Price <= (elephant.Price - (STTick * PennyTick))) {
success = false;
updateStatus("Didn't get it, start to stop loss, currently buying one: " + depth.Bids[0].Price);
CancelAll();
account = _C(exchange.GetAccount);
var opAmount = _N(account.Stocks - InitAccount.Stocks);
if (opAmount < 0.001) {
break;
}
exchange.Sell(depth.Bids[0].Price, opAmount);
}
var orders = _C(exchange.GetOrders);
if (orders.length === 0) {
break;
}
Sleep(CheckInterval);
}
if (success) {
Counter.w++;
} else {
Counter.f++;
}
Counter.i++;
var account = _C(exchange.GetAccount);
LogProfit(account.Balance - InitAccount.Balance, account);
}
var account = _C(exchange.GetAccount)
Obtenez des informations sur les comptes courants.
var opAmount = _N(account.Stocks - InitAccount.Stocks)
: Calculer la variation des actifs du compte après l'achat de l'éléphant. Si la variation est inférieure à 0,001, cela indique que l'achat a échoué, augmenter le nombre d'échecs et continuer à la boucle suivante.
updateStatus("Successful payment: " + opAmount + ", Start taking action...")
: Enregistrer les informations relatives à l'achat réussi de
exchange.Sell(elephant.Price + (PennyTick * ProfitTick), opAmount)
: Utilisez la fonction exchange.Sell pour vendre l'éléphant acheté avec succès à but lucratif. Le prix de vente est elephant.Price + (PennyTick * ProfitTick).
Entrez une nouvelle boucle infinie, utilisée pour attendre l'exécution des ordres de vente.
var depth = _C(exchange.GetDepth)
Obtenir des informations approfondies sur le marché.
if (depth.Bids.length > 0 && depth.Bids[0].Price <= (elephant.Price - (STTick * PennyTick)))
: Vérifiez l'information sur la profondeur du marché, si le prix du marché est déjà tombé au niveau de stop-loss, puis exécutez l'opération stop-loss.
CancelAll()
: Appeler la fonction CancelAll() pour annuler toutes les commandes inachevées, afin d'éviter le risque de position.
if (opAmount < 0.001)
: Vérifiez à nouveau la quantité d'achat, si elle est inférieure à 0,001, cela indique que l'achat a échoué, quittez la boucle.
exchange.Sell(depth.Bids[0].Price, opAmount)
: Exécuter une opération stop-loss, vendre les actifs restants au prix le plus bas du marché actuel.
Enfin, mettre à jour le nombre de transactions réussies et infructueuses en fonction de la réussite ou non de la transaction et enregistrer les bénéfices commerciaux.
Il s'agit d'une explication ligne par ligne de l'ensemble de la stratégie. L'idée de base de cette stratégie est de trouver
En général, cette stratégie est une stratégie de trading à haute fréquence visant à utiliser les informations de profondeur du marché pour identifier les gros ordres d'achat et effectuer des transactions d'achat et de vente dans une courte période. Elle nécessite une surveillance constante du marché et l'exécution d'opérations d'achat et de vente pour obtenir rapidement de petits profits. Cependant, c'est aussi une stratégie à haut risque, car elle nécessite des réponses rapides aux fluctuations du marché tout en tenant compte de la gestion des risques et des mécanismes de stop-loss pour éviter des pertes importantes.
Veuillez noter que la stratégie est basée sur des marchés et des plateformes de négociation spécifiques. Pour différents marchés et bourses, des ajustements et des optimisations appropriés peuvent être nécessaires. Dans l'application pratique, les investisseurs doivent tester et évaluer soigneusement la performance de la stratégie pour s'assurer qu'elle correspond à leurs objectifs d'investissement et à leur tolérance au risque.
Au fur et à mesure que vous continuez à exécuter la stratégie, elle effectuera à plusieurs reprises les opérations suivantes:
Premièrement, la stratégie permettra de vérifier l'information approfondie du marché afin de comprendre la situation actuelle des ordres de vente et des ordres d'achat.
Ensuite, la stratégie tentera de trouver des ordres de vente qui répondent aux critères, en particulier des ordres de vente avec une quantité supérieure ou égale à Lot.
Ensuite, la stratégie continuera à rechercher
Si un nombre suffisant d'éléphants est trouvé consécutivement (contrôlé par le paramètre LockCount), la stratégie effectue ensuite les opérations suivantes:
L'ensemble de la stratégie effectue continuellement les opérations ci-dessus pour capturer autant d'éléphants que possible et obtenir de petits bénéfices. Il s'agit d'une stratégie de trading à haute fréquence qui nécessite des réponses rapides aux changements du marché, tout en tenant compte de la gestion des risques et des mécanismes de stop-loss pour protéger le capital. Les investisseurs devraient soigneusement envisager d'utiliser cette stratégie, en particulier sur les marchés très volatils.
La stratégie Penny Jump est un exemple typique du trading à haute fréquence, démontrant le jeu subtil et la concurrence entre les participants au marché. Cette stratégie est particulièrement importante sur le marché de la crypto-monnaie en raison de ses grandes fluctuations, où les investisseurs institutionnels et les traders à haute fréquence poursuivent tous des profits rapides. Cependant, cela rend également le marché plein de défis, nécessitant une adaptation et un ajustement constants des stratégies pour maintenir des avantages concurrentiels.