天天看點

基于數字貨币的動态平衡政策

一、摘要

沃倫 · 巴菲特的導師本傑明 · 格雷厄姆曾經在《聰明的投資者》一書中,曾經提到過一種股票債券動态平衡的交易模式。

基于數字貨币的動态平衡政策

這種交易模式非常簡單:

  • 把手中 50% 的資金投資于股票基金,剩下 50% 投資于債券基金。即股票和債券兩者各占一半。
  • 根據固定間隔時間或市場變化進行一次資産再平衡,使股票資産和債券資産的比例恢複到初始的 1:1。

    這就是整個政策的全部邏輯,包含了什麼時候買賣,以及買賣多少。夠簡單吧!

二、動态平衡原理

在這個方法中,債券基金的波動率其實很小,遠遠低于股票波動率,是以債券在這裡被當做『 參照錨 』,也就是說,用債券來衡量股票究竟是漲得太多了,還是漲得太少了。

如果,股票價格上漲,會使得股票的市值大于債券的市值,當兩者市值比率超過設定的門檻值時,則對總倉位進行重新調整,賣出股票,并且買入債券,使股債市值比例恢複至初始的 1:1。

反之,股票價格下跌,會使得股票的市值小于債券的市值,當兩者市值比率超過設定的門檻值時,則對總倉位進行重新調整,買入股票,并且賣出債券,使股債市值比例恢複至初始的 1:1。

基于數字貨币的動态平衡政策

就這樣,在動态平衡股票和債券之間的比例,就夠享受到股票成長的果實,并且減少了資産波動率。作為價值投資的先驅,格雷厄姆為我們提供了一個很好的思路。既然這是一個完整的政策,為何我們不把它用在數字貨币上呢?

三、政策邏輯

區塊鍊資産 BTC 中的動态平衡政策

政策邏輯

  • 按照目前的 BTC 的價值,賬戶餘額保留¥5000 現金和 0.1個 BTC,即現金和BTC 市值的初始比例是 1:1。
  • 如果 BTC 的價格上漲至¥6000,即 BTC 市值大于賬戶餘額,并且其之間的差超過設定的門檻值,就賣掉(6000-5000)/6000/2個币。說明 BTC 升值了,把錢兌換回來。
  • 如果 BTC 的價格下跌至¥4000,即 BTC市值小于賬戶餘額,并且其之間的差超過設定的門檻值,就買入(5000-4000)/4000/2個币。說明 BTC 貶值了,把 BTC 買回來。

就這樣,不管 BTC 是升值還是貶值,始終動态保持賬戶餘額和 BTC 的市值相等。如果 BTC 貶值了就買一些,等再漲回來,就再賣一些,就好像天平一樣。

四、政策架構

那麼,如何用代碼去實作呢?我們以發明者量化交易平台為例,首先讓我們看一下政策架構:

// 撤單函數
function CancelPendingOrders() {}

// 下單函數
function onTick() {}

// 主函數
function main() {
    // 過濾非重要資訊
    SetErrorFilter("GetRecords:|GetOrders:|GetDepth:|GetAccount|:Buy|Sell|timeout");
    while (true) { // 輪詢模式
        if (onTick()) { // 執行 onTick 函數
            CancelPendingOrders(); // 取消未成交的挂單
            Log(_C(exchange.GetAccount)); // 列印目前賬戶資訊
        }
        Sleep(LoopInterval * 1000); // 休眠
    }
}
           

整個政策架構其實很簡單,一個 main 主函數、一個 onTick 下單函數、一個 CancelPendingOrders 函數、以及必要參數。

五、下單子產品

// 下單函數
function onTick() {
    var acc = _C(exchange.GetAccount); // 擷取賬戶資訊
    var ticker = _C(exchange.GetTicker); // 擷取 Tick 資料
    var spread = ticker.Sell - ticker.Buy; // 擷取 Tick 資料的買賣價差
    // 賬戶餘額與目前持倉價值的內插補點的 0.5倍
    var diffAsset = (acc.Balance - (acc.Stocks * ticker.Sell)) / 2;
    var ratio = diffAsset / acc.Balance; // diffAsset / 賬戶餘額
    LogStatus('ratio:', ratio, _D()); // 列印 ratio和目前時間
    if (Math.abs(ratio) < threshold) { // 如果 ratio的絕對值小于指定門檻值
        return false; // 傳回 false
    }
    if (ratio > 0) { // 如果 ratio大于 0
        var buyPrice = _N(ticker.Sell + spread, ZPrecision); // 計算下單價格
        var buyAmount = _N(diffAsset / buyPrice, XPrecision); // 計算下單量
        if (buyAmount < MinStock) { // 如果下單量小于最小交易量
            return false; // 傳回 false
        }
        exchange.Buy(buyPrice, buyAmount, diffAsset, ratio); // 買入下單
    } else {
        var sellPrice = _N(ticker.Buy - spread, ZPrecision); // 計算下單價格
        var sellAmount = _N(-diffAsset / sellPrice, XPrecision); // 計算下單量
        if (sellAmount < MinStock) { // 如果下單量小于最小交易量
            return false; // 傳回 false
        }
        exchange.Sell(sellPrice, sellAmount, diffAsset, ratio); // 賣出下單
    }
    return true; // 傳回 true
}
           

下單交易邏輯條理清晰,所有的注釋都已經寫到代碼裡面了,可以點選圖檔放大檢視。

主要流程如下:

  • 擷取賬戶資訊。
  • 擷取 Tick 資料。
  • 計算 Tick 資料買賣價差。
  • 計算賬戶餘額和 BTC 市值價差。
  • 計算買賣條件、下單價格、下單量。
  • 下單,并傳回 true。

六、撤單子產品

// 撤單函數
function CancelPendingOrders() {
    Sleep(1000); // 休眠 1秒
    var ret = false;
    while (true) {
        var orders = null;
        // 持續擷取未成交訂單數組,如果傳回異常,則繼續擷取
        while (!(orders = exchange.GetOrders())) {
            Sleep(1000); // 休眠 1秒
        }
        if (orders.length == 0) { // 如果訂單數組為空
            return ret; // 傳回撤單狀态
        }
        for (var j = 0; j < orders.length; j++) { // 周遊未成交訂單數組
            exchange.CancelOrder(orders[j].Id); // 依次取消未成交訂單
            ret = true;
            if (j < (orders.length - 1)) {
                Sleep(1000); // 休眠 1秒
            }
        }
    }
}
           

撤單子產品就更簡單了,步驟如下:

  • 撤單前先等待 1 秒,個别交易所,你懂的。
  • 持續擷取未成交訂單數組,如果傳回異常,則繼續擷取。
  • 如果未成交訂單數組為空,即時傳回撤單狀态。
  • 如果有未成交的訂單,則周遊整個數組,并依次根據訂單号撤單。

七、完整政策源碼

// 回測環境
/*backtest
start: 2018-01-01 00:00:00
end: 2018-08-01 11:00:00
period: 1m
exchanges: [{"eid":"Bitfinex","currency":"BTC_USD"}]
*/



// 撤單函數
function CancelPendingOrders() {
    Sleep(1000); // 休眠 1秒
    var ret = false;
    while (true) {
        var orders = null;
        // 持續擷取未成交訂單數組,如果傳回異常,則繼續擷取
        while (!(orders = exchange.GetOrders())) {
            Sleep(1000); // 休眠 1秒
        }
        if (orders.length == 0) { // 如果訂單數組為空
            return ret; // 傳回撤單狀态
        }
        for (var j = 0; j < orders.length; j++) { // 周遊未成交訂單數組
            exchange.CancelOrder(orders[j].Id); // 依次取消未成交訂單
            ret = true;
            if (j < (orders.length - 1)) {
                Sleep(1000); // 休眠 1秒
            }
        }
    }
}

// 下單函數
function onTick() {
    var acc = _C(exchange.GetAccount); // 擷取賬戶資訊
    var ticker = _C(exchange.GetTicker); // 擷取 Tick 資料
    var spread = ticker.Sell - ticker.Buy; // 擷取 Tick 資料的買賣價差
    // 賬戶餘額與目前持倉價值的內插補點的 0.5倍
    var diffAsset = (acc.Balance - (acc.Stocks * ticker.Sell)) / 2;
    var ratio = diffAsset / acc.Balance; // diffAsset / 賬戶餘額
    LogStatus('ratio:', ratio, _D()); // 列印 ratio和目前時間
    if (Math.abs(ratio) < threshold) { // 如果 ratio的絕對值小于指定門檻值
        return false; // 傳回 false
    }
    if (ratio > 0) { // 如果 ratio大于 0
        var buyPrice = _N(ticker.Sell + spread, ZPrecision); // 計算下單價格
        var buyAmount = _N(diffAsset / buyPrice, XPrecision); // 計算下單量
        if (buyAmount < MinStock) { // 如果下單量小于最小交易量
            return false; // 傳回 false
        }
        exchange.Buy(buyPrice, buyAmount, diffAsset, ratio); // 買入下單
    } else {
        var sellPrice = _N(ticker.Buy - spread, ZPrecision); // 計算下單價格
        var sellAmount = _N(-diffAsset / sellPrice, XPrecision); // 計算下單量
        if (sellAmount < MinStock) { // 如果下單量小于最小交易量
            return false; // 傳回 false
        }
        exchange.Sell(sellPrice, sellAmount, diffAsset, ratio); // 賣出下單
    }
    return true; // 傳回 true
}

// 主函數
function main() {
    // 過濾非重要資訊
    SetErrorFilter("GetRecords:|GetOrders:|GetDepth:|GetAccount|:Buy|Sell|timeout");
    while (true) { // 輪詢模式
        if (onTick()) { // 執行 onTick 函數
            CancelPendingOrders(); // 取消未成交的挂單
            Log(_C(exchange.GetAccount)); // 列印目前賬戶資訊
        }
        Sleep(LoopInterval * 1000); // 休眠
    }
}
           

外部參數

基于數字貨币的動态平衡政策

八、政策回測

接下來,讓我們測試一下這個簡單的動态平衡政策,看看到底有沒有效果。以下是在 BTC 的曆史資料上的回測,僅供大家參考。

回測環境

基于數字貨币的動态平衡政策

回測績效

基于數字貨币的動态平衡政策

回測曲線

基于數字貨币的動态平衡政策

再來一張,同時期 BTC 價格走勢圖

基于數字貨币的動态平衡政策

在回測時間段,BTC 已經持續了長達 8 個月下跌,甚至最大跌幅超過70%,這造成很多投資者對區塊鍊資産失去信心。本篇政策累計收益高達 160%,年化收益風險比超過 5。對于一個這麼簡單的投資政策,這個投資回報率已經超過絕大多數梭哈的群衆了。

九、擷取政策源碼

政策源碼已經公開到發明者量化官網 https://www.fmz.com/strategy/110545 無需配置直接線上回測。

十、總結

本篇動态平衡政策,隻有一個核心參數(threshold 門檻值),是一個很簡單的投資方法,追求的不是超額的收益,而是穩健的收益。與趨勢政策相反,動态平衡政策卻是逆勢而動。而動态平衡政策則恰好相反,市場熱的時候減倉降溫,市場冷清的時候加倉蟄伏,有點類似宏觀經濟調控。

其實,動态平衡政策正是秉承了價格不可預測的觀念,同時又捕捉價格波動的一門手藝。動态平衡政策的關鍵核心在設定和調整資産配置比例,還有觸發門檻值。鑒于篇幅原因,一篇文章沒辦法做到面面俱到,要知道文字之外,存乎一心。動态平衡政策最重要的是投資思想,你甚至可以把本篇中的單個 BTC 資産換成一籃子區塊鍊資産組合。

最後,讓我們以本傑明 · 格雷厄姆在《聰明的投資者》一書中的名言來結束本篇:股票市場并非一個能精确衡量價值的『 稱重計 』,相反它是一個『 投票機 』,不計其數的人所做出的決定是一種理性和感性的摻雜物,有很多時候這些抉擇和理性的價值評判相去甚遠。投資的秘訣就是在價格遠遠低于内在價值時投資,并且相信市場趨勢會回升。

——本傑明 · 格雷厄姆《聰明的投資者》

繼續閱讀