Tài nguyên đang được tải lên... tải...

Đảm bảo rủi ro theo hệ thống delta động của các tùy chọn deribit

Tác giả:Ninabadass, Tạo: 2022-04-24 11:32:48, Cập nhật: 2022-04-24 15:50:56

Đảm bảo rủi ro theo hệ thống delta động của các tùy chọn deribit

Lần này, chiến lược của FMZ Quant làĐảm bảo rủi ro theo hệ thống delta động của các tùy chọn deribit, viết tắt là DDH.

Để nghiên cứu giao dịch tùy chọn, chúng ta thường cần làm chủ các khái niệm trong một số khía cạnh:

  • Mô hình định giá tùy chọn; Mô hình B-S; Giá tùy chọn được xác định dựa trên giá suất cơ bản, giá suất thực hiện, ngày đến hết hạn, (đã ngụ ý) biến độnglãi suất không rủi ro.

  • Khả năng rủi ro tùy chọn:

    • Delta rủi ro theo hướng tùy chọn. Nếu giá trị delta là + 0,5, hiệu suất lợi nhuận và lỗ của tùy chọn khi giá cơ bản tăng và giảm có thể được coi là 0,50 điểm.
    • Gamma tốc độ tăng tốc của rủi ro theo hướng. Ví dụ, một lựa chọn mua. Do Gamma, từ nơi giá cơ bản ở mức giá thực hiện, Delta sẽ đến gần +1.00 từ +0.50, trong quá trình tăng giá.
    • Khi bạn mua các tùy chọn, nếu giá cơ bản vẫn không đổi, với mỗi ngày trôi qua, bạn sẽ trả một khoản phí được hiển thị bởi giá trị Theta (Deribit được định giá bằng USD). Khi bạn bán các tùy chọn, và giá cơ bản vẫn không đổi, với mỗi ngày trôi qua, bạn sẽ nhận được một khoản phí hiển thị bởi giá trị Theta.
    • Khi bạn mua các tùy chọn, Vega được thể hiện dưới dạng một giá trị tích cực, cụ thể là biến động ngụ ý dài. Khi biến động ngụ ý tăng lên, bạn có thể kiếm lợi nhuận bằng cách tiếp xúc với Vega. Tình huống ngược lại cũng giống như vậy. Khi bạn bán các tùy chọn, biến động ngụ ý giảm, và bạn sẽ có lợi nhuận.

Giải thích chiến lược DDH:

  • Giải thích nguyên tắc DDH Bằng cách cân bằng delta của các tùy chọn và tương lai, tính trung lập rủi ro của hướng giao dịch được đạt được. Sau khi nắm giữ một vị trí hợp đồng quyền chọn và sử dụng tương lai để bảo hiểm và cân bằng Delta, khi thay đổi giá cơ bản, tổng thể Delta sẽ xuất hiện không cân bằng một lần nữa.

    Ví dụ: Khi chúng ta mua một lựa chọn mua, chúng ta có một vị trí tăng. tại thời điểm này, nó là cần thiết để ngắn tương lai để bảo hiểm các tùy chọn Delta để đạt được trung tính tổng thể Delta (0 hoặc gần 0). Hãy bỏ qua các yếu tố, chẳng hạn như ngày đến hết hạn và sự biến động ngụ ý của hợp đồng quyền chọn. Kịch bản 1: Khi giá cơ bản tăng, tùy chọn Delta tăng, và tổng số Delta di chuyển đến một số tích cực. (Trước khi tái cân bằng, delta tùy chọn lớn, delta tương lai tương đối nhỏ, lợi nhuận biên của tùy chọn mua vượt quá lỗ biên của hợp đồng ngắn và toàn bộ danh mục đầu tư sẽ tạo ra lợi nhuận.) Kịch bản 2: Khi giá cơ bản giảm, delta tùy chọn giảm, và tổng số delta di chuyển đến một số âm, và một số vị trí tương lai ngắn được đóng để làm cho tổng số dư delta trở lại. (Trước khi tái cân bằng, delta tùy chọn nhỏ, delta tương lai tương đối lớn, lỗ biên của tùy chọn mua ít hơn lợi nhuận biên của hợp đồng ngắn và toàn bộ danh mục đầu tư vẫn sẽ có lợi nhuận.)

    Do đó, lý tưởng nhất, sự gia tăng và giảm của các cơ sở cả hai mang lại lợi nhuận, miễn là thị trường biến động.

    Tuy nhiên, có những yếu tố khác cần được xem xét: giá trị thời gian, chi phí giao dịch và những yếu tố khác.

    Vì vậy, tôi trích dẫn lời giải thích của một bậc thầy từ Zhihu:

    Sự tập trung của Gamma Scalping không phải là delta, bảo hiểm delta động chỉ là một cách để tránh rủi ro giá cơ bản trong quá trình này. Gamma Scalping tập trung vào Alpha. Alpha không phải là Alpha của việc lựa chọn cổ phiếu. Ở đây, Alpha = Gamma / Theta, tức là Gamma được trao đổi bằng thời gian suy giảm của đơn vị Theta. Đó là điểm. Có thể xây dựng một sự kết hợp của tăng và giảm cả hai với lợi nhuận nổi, chắc chắn đi kèm với sự suy giảm thời gian, và vấn đề là tỷ lệ hiệu suất chi phí. Tác giả: Xu Zhe; Liên kết bài viết gốc:https://www.zhihu.com/question/51630805/answer/128096385

Thiết kế chiến lược DDH

  • kết hợp giao diện thị trường tổng hợp, thiết kế cấu trúc;
  • thiết kế UI chiến lược;
  • thiết kế chiến lược tương tác;
  • Thiết kế chức năng phòng ngừa rủi ro tự động.

Mã nguồn:

// constructor 
function createManager(e, subscribeList, msg) {
	var self = {}
    self.supportList = ["Futures_Binance", "Huobi", "Futures_Deribit"]  // from the supported platforms

    // object attributes
    self.e = e
    self.msg = msg
    self.name = e.GetName()
    self.type = self.name.includes("Futures_") ? "Futures" : "Spot"
    self.label = e.GetLabel()
    self.quoteCurrency = ""  
    self.subscribeList = subscribeList   // subscribeList : [strSymbol1, strSymbol2, ...]
    self.tickers = []                    // all market data obtained by the interface; define the data format as: {bid1: 123, ask1: 123, symbol: "xxx"}}
    self.subscribeTickers = []           // the market data in need; define the data format as: {bid1: 123, ask1: 123, symbol: "xxx"}}
    self.accData = null 
    self.pos = null 

    // initialization function 
    self.init = function() { 
    	// judge whether the platform is supported 
        if (!_.contains(self.supportList, self.name)) {        	
        	throw "not support"
        }
    }

    self.setBase = function(base) {
        // switch base address, used to switch to the simulated bot 
        self.e.SetBase(base)
        Log(self.name, self.label, "switch to simulated bot:", base)
    }

    // judge the data precision 
    self.judgePrecision = function (p) {
        var arr = p.toString().split(".")
        if (arr.length != 2) {
            if (arr.length == 1) {
                return 0
            }
            throw "judgePrecision error, p:" + String(p)
        }
        
        return arr[1].length
    }

    // update assets 
    self.updateAcc = function(callBackFuncGetAcc) {
        var ret = callBackFuncGetAcc(self)
        if (!ret) {
        	return false 
        }
        self.accData = ret 
        return true 
    }

    // update positions 
    self.updatePos = function(httpMethod, url, params) {
        var pos = self.e.IO("api", httpMethod, url, params)
        var ret = []
        if (!pos) {
            return false 
        } else {
            // arrange data 
            // {"jsonrpc":"2.0","result":[],"usIn":1616484238870404,"usOut":1616484238870970,"usDiff":566,"testnet":true}
            try {
                _.each(pos.result, function(ele) {
                    ret.push(ele)
                })
            } catch(err) {
                Log("error:", err)
                return false 
            }
            self.pos = ret
        }
        return true 
    }

    // update the market data 
    self.updateTicker = function(url, callBackFuncGetArr, callBackFuncGetTicker) {
    	var tickers = []
    	var subscribeTickers = []
    	var ret = self.httpQuery(url)
    	if (!ret) {
    		return false 
    	}
    	// Log("test", ret)// test
    	try {
            _.each(callBackFuncGetArr(ret), function(ele) {
            	var ticker = callBackFuncGetTicker(ele)
            	tickers.push(ticker)
                if (self.subscribeList.length == 0) {
                    subscribeTickers.push(ticker)
                } else {
                	for (var i = 0 ; i < self.subscribeList.length ; i++) {                        
                    	if (self.subscribeList[i] == ticker.symbol) {
                    		subscribeTickers.push(ticker)
                    	}
                	}
                }
            })
        } catch(err) {
        	Log("error:", err)
        	return false 
        }

        self.tickers = tickers
        self.subscribeTickers = subscribeTickers
        return true 
    }

    self.getTicker = function(symbol) {
    	var ret = null 
    	_.each(self.subscribeTickers, function(ticker) {
    		if (ticker.symbol == symbol) {
    			ret = ticker
    		}
    	})
    	return ret 
    }

    self.httpQuery = function(url) {
    	var ret = null
        try {
            var retHttpQuery = HttpQuery(url)
            ret = JSON.parse(retHttpQuery)
        } catch (err) {
            // Log("error:", err)
            ret = null
        }
        return ret 
    }

    self.returnTickersTbl = function() {
        var tickersTbl = {
        	type : "table", 
        	title : "tickers",
        	cols : ["symbol", "ask1", "bid1"], 
        	rows : []
        }
        _.each(self.subscribeTickers, function(ticker) {        
        	tickersTbl.rows.push([ticker.symbol, ticker.ask1, ticker.bid1])
        })
        return tickersTbl
    }
    
    // return the positon table 
    self.returnPosTbl = function() {
        var posTbl = {
            type : "table", 
            title : "pos|" + self.msg,
            cols : ["instrument_name", "mark_price", "direction", "size", "delta", "index_price", "average_price", "settlement_price", "average_price_usd", "total_profit_loss"], 
            rows : []
        }
        /* the position data format returned by the interface 
        {
            "mark_price":0.1401105,"maintenance_margin":0,"instrument_name":"BTC-25JUN21-28000-P","direction":"buy",
            "vega":5.66031,"total_profit_loss":0.01226105,"size":0.1,"realized_profit_loss":0,"delta":-0.01166,"kind":"option",
            "initial_margin":0,"index_price":54151.77,"floating_profit_loss_usd":664,"floating_profit_loss":0.000035976,
            "average_price_usd":947.22,"average_price":0.0175,"theta":-7.39514,"settlement_price":0.13975074,"open_orders_margin":0,"gamma":0
        }
        */
        _.each(self.pos, function(ele) {
        	if(ele.direction != "zero") {
                posTbl.rows.push([ele.instrument_name, ele.mark_price, ele.direction, ele.size, ele.delta, ele.index_price, ele.average_price, ele.settlement_price, ele.average_price_usd, ele.total_profit_loss])
            }
        })
        return posTbl
    }

    self.returnOptionTickersTbls = function() {
        var arr = []
        var arrDeliveryDate = []
        _.each(self.subscribeTickers, function(ticker) {
            if (self.name == "Futures_Deribit") {
                var arrInstrument_name = ticker.symbol.split("-")
                var currency = arrInstrument_name[0]
                var deliveryDate = arrInstrument_name[1]
                var deliveryPrice = arrInstrument_name[2]
                var optionType = arrInstrument_name[3]

                if (!_.contains(arrDeliveryDate, deliveryDate)) {
                    arr.push({
                        type : "table", 
                        title : arrInstrument_name[1],
                        cols : ["PUT symbol", "ask1", "bid1", "mark_price", "underlying_price", "CALL symbol", "ask1", "bid1", "mark_price", "underlying_price"], 
                        rows : []
                    })
                    arrDeliveryDate.push(arrInstrument_name[1])
                }
                // traverse arr
                _.each(arr, function(tbl) {
                    if (tbl.title == deliveryDate) {
                        if (tbl.rows.length == 0 && optionType == "P") {
                            tbl.rows.push([ticker.symbol, ticker.ask1, ticker.bid1, ticker.mark_price, ticker.underlying_price, "", "", "", "", ""])
                            return 
                        } else if (tbl.rows.length == 0 && optionType == "C") {
                            tbl.rows.push(["", "", "", "", "", ticker.symbol, ticker.ask1, ticker.bid1, ticker.mark_price, ticker.underlying_price])
                            return 
                        }                        
                        for (var i = 0 ; i < tbl.rows.length ; i++) {
                            if (tbl.rows[i][0] == "" && optionType == "P") {
                                tbl.rows[i][0] = ticker.symbol
                                tbl.rows[i][1] = ticker.ask1
                                tbl.rows[i][2] = ticker.bid1
                                tbl.rows[i][3] = ticker.mark_price
                                tbl.rows[i][4] = ticker.underlying_price
                                return 
                            } else if(tbl.rows[i][5] == "" && optionType == "C") {
                                tbl.rows[i][5] = ticker.symbol
                                tbl.rows[i][6] = ticker.ask1
                                tbl.rows[i][7] = ticker.bid1
                                tbl.rows[i][8] = ticker.mark_price
                                tbl.rows[i][9] = ticker.underlying_price
                                return 
                            }
                        }
                        if (optionType == "P") {
                            tbl.rows.push([ticker.symbol, ticker.ask1, ticker.bid1, ticker.mark_price, ticker.underlying_price, "", "", "", "", ""])
                        } else if(optionType == "C") {
                            tbl.rows.push(["", "", "", "", "", ticker.symbol, ticker.ask1, ticker.bid1, ticker.mark_price, ticker.underlying_price])
                        }
                    }
                })
            }
        })
        return arr 
    }

    // initialize 
    self.init()
	return self 
}


function main() {
    // initialize, and vacuum logs
    if(isResetLog) {
    	LogReset(1)
    }

    var m1 = createManager(exchanges[0], [], "option")
    var m2 = createManager(exchanges[1], ["BTC-PERPETUAL"], "future")

    // switch to the simulated bot 
    var base = "https://www.deribit.com"
    if (isTestNet) {    
        m1.setBase(testNetBase)    
        m2.setBase(testNetBase)
        base = testNetBase
    }

    while(true) {
        // options 
        var ticker1GetSucc = m1.updateTicker(base + "/api/v2/public/get_book_summary_by_currency?currency=BTC&kind=option", 
            function(data) {return data.result}, 
            function(ele) {return {bid1: ele.bid_price, ask1: ele.ask_price, symbol: ele.instrument_name, underlying_price: ele.underlying_price, mark_price: ele.mark_price}}) 
        
        // perpetual futures 
        var ticker2GetSucc = m2.updateTicker(base + "/api/v2/public/get_book_summary_by_currency?currency=BTC&kind=future", 
            function(data) {return data.result}, 
            function(ele) {return {bid1: ele.bid_price, ask1: ele.ask_price, symbol: ele.instrument_name}})
        if (!ticker1GetSucc || !ticker2GetSucc) {
            Sleep(5000)
            continue
        }

        // update positions 
        var pos1GetSucc = m1.updatePos("GET", "/api/v2/private/get_positions", "currency=BTC&kind=option")
        var pos2GetSucc = m2.updatePos("GET", "/api/v2/private/get_positions", "currency=BTC&kind=future")

        if (!pos1GetSucc || !pos2GetSucc) {
            Sleep(5000)
            continue
        }

        // interaction 
        var cmd = GetCommand()
        if(cmd) {
            // process interaction 
            Log("interactive command:", cmd)
            var arr = cmd.split(":")
            // cmdClearLog 
            if(arr[0] == "setContractType") {
                // parseFloat(arr[1])
                m1.e.SetContractType(arr[1])
                Log("exchanges[0] sets contract:", arr[1])
            } else if (arr[0] == "buyOption") {
                var actionData = arr[1].split(",")
                var price = parseFloat(actionData[0])
                var amount = parseFloat(actionData[1])
                m1.e.SetDirection("buy")
                m1.e.Buy(price, amount)
                Log("executed price:", price, "executed amount:", amount, "executed direction:", arr[0])
            } else if (arr[0] == "sellOption") {
                var actionData = arr[1].split(",")
                var price = parseFloat(actionData[0])
                var amount = parseFloat(actionData[1])
                m1.e.SetDirection("sell")
                m1.e.Sell(price, amount)                
                Log("executed price:", price, "executed amount:", amount, "executed direction:", arr[0])
            } else if (arr[0] == "setHedgeDeltaStep") {
                hedgeDeltaStep = parseFloat(arr[1])
                Log("set hedgeDeltaStep:", hedgeDeltaStep)
            } 
        }
        
        // obtain futures contract price 
        var perpetualTicker = m2.getTicker("BTC-PERPETUAL")
        var hedgeMsg = " PERPETUAL:" + JSON.stringify(perpetualTicker)

        // obtain the total delta value from the account data        
        var acc1GetSucc = m1.updateAcc(function(self) {
        	self.e.SetCurrency("BTC_USD")        
        	return self.e.GetAccount()
        })
        if (!acc1GetSucc) {
        	Sleep(5000)
        	continue
        }
        var sumDelta = m1.accData.Info.result.delta_total

        if (Math.abs(sumDelta) > hedgeDeltaStep && perpetualTicker) {
            if (sumDelta < 0) {
                // delta value is more than 0, hedge futures and make short                   
                var amount = _N(Math.abs(sumDelta) * perpetualTicker.ask1, -1)                
                if (amount > 10) {
                    Log("exceeding the hedging threshold value, the current total delta:", sumDelta, "call futures")
                    m2.e.SetContractType("BTC-PERPETUAL")                    
                    m2.e.SetDirection("buy")
                    m2.e.Buy(-1, amount)
                } else {
                	hedgeMsg += ", hedging order amount is less than 10"
                }
            } else {
                // delta value is less than 0, hedge futures and make long
                var amount = _N(Math.abs(sumDelta) * perpetualTicker.bid1, -1)
                if (amount > 10) {
                    Log("exceeding the hedging threshold value, the current total delta:", sumDelta, "put futures")
                    m2.e.SetContractType("BTC-PERPETUAL")
                    m2.e.SetDirection("sell")
                    m2.e.Sell(-1, amount)
                } else {
                	hedgeMsg += ", hedging order amount is less than 0"
                }
            }
        }

        LogStatus(_D(), "sumDelta:", sumDelta, hedgeMsg, 
        	"\n`" + JSON.stringify([m1.returnPosTbl(), m2.returnPosTbl()]) + "`", "\n`" + JSON.stringify(m2.returnTickersTbl()) + "`", "\n`" + JSON.stringify(m1.returnOptionTickersTbls()) + "`")
        Sleep(10000)
    }
}


Các thông số chiến lược:img

Địa chỉ chiến lược:https://www.fmz.com/strategy/265090

Chiến lược hoạt động:

img

img

Chiến lược là một hướng dẫn, chủ yếu được sử dụng để nghiên cứu, vì vậy hãy cẩn thận khi sử dụng trong một bot.


Thêm nữa