Benjamin Graham, mentor de Warren Buffett, mencionou um modo de negociação de balanço dinâmico de ações e títulos no livro
O modo de negociação é muito simples: - Inverter 50% dos fundos em fundos de acções e os restantes 50% em fundos de obrigações, ou seja, as acções e as obrigações representam metade uma da outra. - De acordo com o intervalo fixo ou as alterações do mercado, realizar um reequilíbrio de activos para restabelecer a proporção de activos de acções e activos de obrigações para a proporção original de 1:1. Esta é a lógica de toda a estratégia, incluindo quando comprar e vender e quanto comprar e vender.
Neste método, a volatilidade dos fundos de obrigações é muito pequena, na verdade, muito menor do que a volatilidade das ações, de modo que as obrigações são usadas como
Estratégia de equilíbrio dinâmico no ativo blockchain BTC
Estratégia lógica
Desta forma, não importa se o BTC se valoriza ou se deprecia, sempre mantemos o saldo da conta e o valor de mercado do BTC
Então, como implementá-lo em código? Tomamos a plataforma de negociação FMZ Quant como exemplo, vamos dar uma olhada no quadro de estratégia primeiro:
// 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
}
}
A estrutura da estratégia é realmente muito simples, incluindo uma função principal, uma função de colocação de ordens onTick, uma função CancelPendingOrders e os parâmetros necessários.
// 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
}
A lógica de negociação de ordens está bem organizada, e todos os comentários foram escritos no código.
O processo principal é o seguinte:
// 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
}
}
}
}
O módulo de retirada é mais simples.
// 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
}
}
Parâmetros externos
Em seguida, vamos testar esta simples estratégia de equilíbrio dinâmico para ver se funciona.
Ambiente de ensaio de retrocesso
Desempenho dos testes de retorno
Curva de ensaio de retrocesso
Durante o período de backtest, o BTC continuou a diminuir por até 8 meses, mesmo com um declínio máximo de mais de 70%, o que fez com que muitos investidores perdessem a confiança nos ativos blockchain.
O código fonte da estratégia foi publicado no site oficial da FMZ Quant:https://www.fmz.com/strategy/110545Não há necessidade de configurar, você pode backtesting online diretamente.
A estratégia de equilíbrio dinâmico neste artigo tem apenas um parâmetro central (limite), que é um método de investimento muito simples. O que ele busca não é um retorno em excesso, mas um retorno constante. Ao contrário da estratégia de tendência, a estratégia de equilíbrio dinâmico é contra a tendência. Mas a estratégia de equilíbrio dinâmico é exatamente o oposto.
Na verdade, a estratégia de balanço dinâmico é um ofício que herda o conceito de preços imprevisíveis e capta flutuações de preços ao mesmo tempo. O núcleo da estratégia de balanço dinâmico é definir e ajustar a taxa de alocação de ativos, bem como o limiar de gatilho. Em vista do comprimento, um artigo não pode ser abrangente. Você deve saber que além das palavras, há um coração. A parte mais importante da estratégia de balanço dinâmico é a ideia de investimento. Você pode até substituir os ativos individuais de BTC neste artigo por uma cesta de carteiras de ativos blockchain.
Finalmente, vamos encerrar este artigo com as famosas palavras de Benjamin Graham no livro