Бенджамин Грэхем, наставник Уоррена Баффета, упомянул динамический баланс режима торговли акций и облигаций в книге "Умный инвестор".
Торговый режим очень прост: - инвестировать 50% средств в фондовые фонды и оставшиеся 50% в облигационные фонды. то есть, акции и облигации составляют половину друг друга. - в соответствии с фиксированным интервалом или изменениями на рынке, провести ребалансировку активов, чтобы восстановить соотношение акций и облигаций к первоначальному 1:1. Это логика всей стратегии, включая время покупки и продажи и сумму покупки и продажи.
В этом методе волатильность облигационных фондов очень мала, на самом деле, намного ниже, чем волатильность акций, поэтому облигации используются здесь как "справочные якори", то есть для измерения того, выросли ли запасы слишком сильно или слишком мало. Если цена акций повышается, рыночная стоимость акций будет больше рыночной стоимости облигаций. Когда соотношение рыночной стоимости двух превысит установленный порог, общая позиция будет скорректирована, акции будут проданы, а облигации будут куплены, так что соотношение рыночной стоимости акций и облигаций вернется к первоначальному 1:1. Напротив, если цена акций снижается, рыночная стоимость акций будет меньше рыночной стоимости облигаций. Когда соотношение рыночной стоимости двух превышает установленный порог, общая позиция будет скорректирована, акции будут куплены и облигации будут проданы, так что соотношение рыночной стоимости акций и облигаций вернется к первоначальному 1:1. Таким образом, мы можем наслаждаться плодами роста акций и снижать волатильность активов, динамично балансируя соотношение между акциями и облигациями.
Динамическая стратегия баланса в блокчейн-активе BTC
Логика стратегии
Таким образом, независимо от того, ценится BTC или обесценивается, мы всегда держим баланс счета и рыночную стоимость BTC
Итак, как это реализовать в коде? мы берем FMZ Quant Trading Platform в качестве примера, давайте сначала посмотрим на стратегическую основу:
// 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
}
}
Вся структура стратегии очень проста, включая основную функцию, функцию размещения заказов onTick, функцию CancelPendingOrders и необходимые параметры.
// 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
}
Логика торговли ордера хорошо организована, и все комментарии были записаны в код.
Основной процесс следующий:
// 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
}
}
}
}
Модуль снятия средств проще.
// 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
}
}
Внешние параметры
Далее, давайте проверим эту простую стратегию динамического балансирования, чтобы увидеть, работает ли она.
Окружающая среда для обратного тестирования
Производительность обратного тестирования
Кривая обратного тестирования
В течение периода обратного теста BTC продолжала снижаться до 8 месяцев, даже с максимальным снижением более 70%, что заставило многих инвесторов потерять доверие к активам блокчейна.
Исходный код стратегии опубликован на официальном сайте FMZ Quant:https://www.fmz.com/strategy/110545. Нет необходимости настраивать, вы можете backtesting онлайн непосредственно.
Стратегия динамического баланса в этой статье имеет только один ключевой параметр (порог), который является очень простым инвестиционным методом. Она преследует не избыточную доходность, а устойчивую доходность. В отличие от стратегии тренда, стратегия динамического баланса является против тренда. Но стратегия динамического баланса является прямо противоположной. Когда рынок популярен, сокращение позиции, а когда рынок непопулярен, масштабирование позиции, что похоже на макроэкономическое регулирование.
По сути, стратегия динамического баланса - это искусство, которое наследует концепцию непредсказуемых цен и одновременно улавливает колебания цен. Ядро стратегии динамического баланса заключается в установке и корректировке коэффициента распределения активов, а также порога запуска. Ввиду длины статья не может быть всеобъемлющей. Вы должны знать, что за словами есть сердце. Самой важной частью стратегии динамического баланса является инвестиционная идея. Вы даже можете заменить отдельные активы BTC в этой статье корзиной портфелей активов блокчейна.
Наконец, давайте закончим эту статью с известными словами Бенджамина Грэхема в книге "Интеллигентный инвестор": фондовый рынок - это не "вешалка", которая может точно измерить стоимость, а скорее "машина для голосования". Решения, принимаемые бесчисленными людьми, представляют собой смесь рациональности и чувствительности.