Benjamin Graham, le mentor de Warren Buffett, a mentionné un mode de négociation dynamique des actions et des obligations dans le livre
Le mode de négociation est très simple: - investir 50% des fonds dans des fonds d'actions et les 50% restants dans des fonds d'obligations. - en fonction de l'intervalle fixe ou des variations du marché, procéder à un rééquilibrage des actifs pour ramener la proportion des actifs boursiers et des actifs obligataires à l'original de 1:1. C'est la logique de toute la stratégie, y compris quand acheter et vendre et combien acheter et vendre.
Dans cette méthode, la volatilité des fonds obligataires est en fait très faible, bien inférieure à la volatilité des stocks, de sorte que les obligations sont utilisées ici comme "ancres de référence", c'est-à-dire pour mesurer si les stocks ont augmenté trop ou trop peu par les obligations. Si le prix des actions augmente, la valeur marchande des actions sera supérieure à la valeur marchande des obligations. Lorsque le ratio de valeur marchande des deux dépasse le seuil fixé, la position totale sera réajustée, les actions seront vendues et les obligations achetées, de sorte que le ratio de valeur marchande des actions et des obligations reviendra à l'original de 1:1. Au contraire, si le prix des actions diminue, la valeur marchande de l'action sera inférieure à la valeur marchande des obligations. Lorsque le ratio de valeur marchande des deux dépasse le seuil fixé, la position totale sera réajustée, les actions seront achetées et les obligations seront vendues, de sorte que le ratio de valeur marchande des actions et des obligations reviendra à l'original de 1:1. De cette façon, nous pouvons profiter des fruits de la croissance des actions et réduire la volatilité des actifs en équilibrant dynamiquement la proportion entre les actions et les obligations.
Stratégie de balance dynamique dans l'actif blockchain BTC
La logique de la stratégie
De cette façon, peu importe si BTC s'apprécie ou s'amortit, nous gardons toujours le solde du compte et la valeur marchande de BTC
Alors, comment l'implémenter dans le code? Nous prenons la plateforme de trading FMZ Quant comme exemple, jetons un coup d'œil au cadre stratégique d'abord:
// function to cancel orders
function CancelPendingOrders() {}
// function to place an order
function onTick() {}
// main function
function main() {
// filter non-important information
SetErrorFilter("GetRecords:|GetOrders:|GetDepth:|GetAccount|:Buy|Sell|timeout");
while (true) { // polling mode
if (onTick()) { // execute onTick function
CancelPendingOrders(); // cancel the outstanding pending orders
Log(_C(exchange.GetAccount)); // print the current account information
}
Sleep(LoopInterval * 1000); // sleep
}
}
L'ensemble du cadre de stratégie est très simple en fait, y compris une fonction principale, une fonction de commande onTick, une fonction CancelPendingOrders et les paramètres nécessaires.
// order-placing function
function onTick() {
var acc = _C(exchange.GetAccount); // obtain account information
var ticker = _C(exchange.GetTicker); // obtain Tick data
var spread = ticker.Sell - ticker.Buy; // obtain bid ask spread of Tick data
// 0.5 times of the difference between the account balance and the current position value
var diffAsset = (acc.Balance - (acc.Stocks * ticker.Sell)) / 2;
var ratio = diffAsset / acc.Balance; // diffAsset / account balance
LogStatus('ratio:', ratio, _D()); // Print ratio and current time
if (Math.abs(ratio) < threshold) { // If the absolute value of the ratio is less than the specified threshold
return false; // return false
}
if (ratio > 0) { // if ratio > 0
var buyPrice = _N(ticker.Sell + spread, ZPrecision); // Calculate the price of an order
var buyAmount = _N(diffAsset / buyPrice, XPrecision); // Calculate the order quantity
if (buyAmount < MinStock) { // If the order quantity is less than the minimum transaction quantity
return false; // return false
}
exchange.Buy(buyPrice, buyAmount, diffAsset, ratio); // Purchase order
} else {
var sellPrice = _N(ticker.Buy - spread, ZPrecision); // Calculate the price of an order
var sellAmount = _N(-diffAsset / sellPrice, XPrecision); // Calculate the order quantity
if (sellAmount < MinStock) { // If the order quantity is less than the minimum transaction quantity
return false; // return false
}
exchange.Sell(sellPrice, sellAmount, diffAsset, ratio); // Sell and place an order
}
return true; // return true
}
La logique de négociation des ordres est bien organisée, et tous les commentaires ont été écrits dans le code.
Le processus principal est le suivant:
// Withdrawal function
function CancelPendingOrders() {
Sleep(1000); // Sleep for 1 second
var ret = false;
while (true) {
var orders = null;
// Obtain the unsettled order array continuously. If an exception is returned, continue to obtain
while (!(orders = exchange.GetOrders())) {
Sleep(1000); // Sleep for 1 second
}
if (orders.length == 0) { // If the order array is empty
return ret; // Return to order withdrawal status
}
for (var j = 0; j < orders.length; j++) { // Iterate through the array of unfilled orders
exchange.CancelOrder(orders[j].Id); // Cancel unfilled orders in sequence
ret = true;
if (j < (orders.length - 1)) {
Sleep(1000); // Sleep for 1 second
}
}
}
}
Le module de retrait est plus simple: les étapes sont les suivantes:
// Backtest environment
/*backtest
start: 2018-01-01 00:00:00
end: 2018-08-01 11:00:00
period: 1m
exchanges: [{"eid":"Bitfinex","currency":"BTC_USD"}]
*/
// Order withdrawal function
function CancelPendingOrders() {
Sleep(1000); // Sleep for 1 second
var ret = false;
while (true) {
var orders = null;
// Obtain the unsettled order array continuously. If an exception is returned, continue to obtain
while (!(orders = exchange.GetOrders())) {
Sleep(1000); // Sleep for 1 second
}
if (orders.length == 0) { // If the order array is empty
return ret; // Return to order withdrawal status
}
for (var j = 0; j < orders.length; j++) { // Iterate through the array of unfilled orders
exchange.CancelOrder(orders[j].Id); // Cancel unfilled orders in sequence
ret = true;
if (j < (orders.length - 1)) {
Sleep(1000); // Sleep for 1 second
}
}
}
}
// Order function
function onTick() {
var acc = _C(exchange.GetAccount); // obtain account information
var ticker = _C(exchange.GetTicker); // obtain Tick data
var spread = ticker.Sell - ticker.Buy; // obtain bid ask spread of Tick data
// 0.5 times of the difference between the account balance and the current position value
var diffAsset = (acc.Balance - (acc.Stocks * ticker.Sell)) / 2;
var ratio = diffAsset / acc.Balance; // diffAsset / account balance
LogStatus('ratio:', ratio, _D()); // Print ratio and current time
if (Math.abs(ratio) < threshold) { // If the absolute value of ratio is less than the specified threshold
return false; // return false
}
if (ratio > 0) { // if ratio > 0
var buyPrice = _N(ticker.Sell + spread, ZPrecision); // Calculate the order price
var buyAmount = _N(diffAsset / buyPrice, XPrecision); // Calculate the order quantity
if (buyAmount < MinStock) { // If the order quantity is less than the minimum trading quantity
return false; // return false
}
exchange.Buy(buyPrice, buyAmount, diffAsset, ratio); // buy order
} else {
var sellPrice = _N(ticker.Buy - spread, ZPrecision); // Calculate the order price
var sellAmount = _N(-diffAsset / sellPrice, XPrecision); // Calculate the order quantity
if (sellAmount < MinStock) { // If the order quantity is less than the minimum trading quantity
return false; // return false
}
exchange.Sell(sellPrice, sellAmount, diffAsset, ratio); // sell order
}
return true; // return true
}
// main function
function main() {
// Filter non-important information
SetErrorFilter("GetRecords:|GetOrders:|GetDepth:|GetAccount|:Buy|Sell|timeout");
while (true) { // Polling mode
if (onTick()) { // Execute onTick function
CancelPendingOrders(); // Cancel pending orders
Log(_C(exchange.GetAccount)); // Print current account information
}
Sleep(LoopInterval * 1000); // sleep
}
}
Paramètres extérieurs
Ensuite, testons cette stratégie d'équilibrage dynamique simple pour voir si elle fonctionne.
Environnement de contre-test
Performance des tests de retour
courbe de rétro-test
Au cours de la période de backtest, le BTC a continué à baisser jusqu'à 8 mois, même avec une baisse maximale de plus de 70%, ce qui a fait perdre confiance à de nombreux investisseurs dans les actifs blockchain. Le rendement cumulé de cette stratégie est jusqu'à 160%, et le ratio de risque de rendement annualisé dépasse 5.
Le code source de la stratégie a été publié sur le site officiel de FMZ Quant:https://www.fmz.com/strategy/110545Il n'y a pas besoin de configurer, vous pouvez backtesting en ligne directement.
La stratégie d'équilibre dynamique dans cet article n'a qu'un seul paramètre de base ( seuil), qui est une méthode d'investissement très simple. Ce qu'elle poursuit n'est pas un rendement excédentaire, mais un rendement régulier. Contrairement à la stratégie de tendance, la stratégie d'équilibre dynamique est contre la tendance. Mais la stratégie d'équilibre dynamique est tout le contraire. Lorsque le marché est populaire, réduire la position, tandis que lorsque le marché est impopulaire, élargir la position, ce qui est similaire à la régulation macroéconomique.
En fait, la stratégie de balance dynamique est un métier qui hérite du concept de prix imprévisibles et capture en même temps les fluctuations de prix. Le noyau de la stratégie de balance dynamique est de définir et d'ajuster le ratio d'allocation des actifs, ainsi que le seuil de déclenchement. Compte tenu de la longueur, un article ne peut pas être complet. Vous devez savoir qu'au-delà des mots, il y a un cœur. La partie la plus importante de la stratégie de balance dynamique est l'idée d'investissement. Vous pouvez même remplacer les actifs BTC individuels dans cet article par un panier de portefeuilles d'actifs blockchain.
Enfin, terminons cet article avec les célèbres mots de Benjamin Graham dans le livre The Intelligent Investor: Le marché boursier n'est pas une machine à peser qui peut mesurer la valeur avec précision, mais plutôt une machine à voter. Les décisions prises par d'innombrables personnes sont un mélange de rationalité et de sensibilité.