Strategi Hedging Dinamis Opsi Deribit Delta

Penulis:Lydia, Dibuat: 2022-11-01 17:49:07, Diperbarui: 2023-09-15 20:49:52

img

Strategi yang dibawa FMZ Quant adalah strategi Deribit Options Delta Dynamic Hedging atau singkatnya DDH (dynamic delta hedging).

Untuk mempelajari perdagangan opsi, kita biasanya harus menguasai konsep-konsep ini:

· Model penetapan harga opsi, model B-S, harga opsi ditentukan berdasarkan [harga subjek], [harga power-wield], [waktu yang tersisa hingga kedaluwarsa], [[implikasi] volatilitas], dan [tingkat bebas risiko].

· Eksposur opsi:

Jika Delta adalah +0,50, maka opsi, yang menghasilkan keuntungan atau kerugian ketika harga subjek naik atau turun, dapat dianggap sebagai spot 0,50. -Gamma Percepatan risiko arah. Misalnya, dalam kasus opsi pembelian, karena Gamma, Delta secara bertahap akan bergerak dari +0,50 menjadi +1,00 karena harga terus meningkat dari saat harga subjek berada pada harga power-wield. - Theta Eksposur Waktu Ketika Anda membeli opsi, jika harga subjek tidak berubah, untuk setiap hari yang berlalu, Anda membayar biaya yang ditunjukkan dalam jumlah Theta (Deribit dinyatakan dalam USD). Ketika Anda menjual opsi, jika harga subjek tidak berubah, Anda akan menerima biaya yang ditunjukkan dalam jumlah Theta setiap hari. -Vega Volatility Exposure. ketika Anda membeli opsi, Vega positif, yaitu volatilitas jangka panjang. ketika volatilitas tersirat meningkat, Anda mendapatkan eksposur Vega. dan sebaliknya, ketika Anda menjual opsi, Anda mendapatkan volatilitas tersirat menurun.

Penjelasan strategi DDH:

· Penjelasan prinsip DDH Arah perdagangan netral risiko dicapai dengan mencocokkan Delta opsi dan berjangka. Setelah mengambil posisi dalam kontrak opsi dan menyeimbangkan Delta dengan lindung nilai berjangka, keseluruhan Delta akan menjadi tidak seimbang lagi ketika harga subjek bergerak. Kombinasi opsi dan posisi berjangka seperti itu membutuhkan lindung nilai dinamis yang berkelanjutan untuk menyamakan Delta.

· Misalnya: Ketika kita membeli opsi panggilan, kita memegang posisi dalam arah panjang pada saat ini. pada saat ini, perlu untuk pergi pendek berjangka untuk lindung nilai Delta opsi, mencapai keseluruhan Delta netral (0 atau dekat dengan 0). Mari kita abaikan waktu yang tersisa untuk berakhirnya kontrak opsi, volatilitas dan faktor lainnya. Skenario 1: Ketika harga subjek naik, Delta opsi meningkat, dan keseluruhan Delta bergerak ke angka positif, dan berjangka perlu lindung nilai lagi. (Sebelum rebalancing, Delta opsi besar, sedangkan yang berjangka relatif kecil. keuntungan marginal opsi panggilan melebihi kerugian marginal posisi kontrak pendek, dan seluruh portofolio akan menghasilkan.)

Skenario 2: Ketika harga subjek jatuh, bagian opsi dari Delta menurun dan keseluruhan Delta bergerak ke angka negatif, menutup sebagian dari posisi berjangka pendek dan membawa keseluruhan Delta kembali seimbang. (Sebelum menyeimbangkan kembali, pada saat ini, Delta opsi kecil, sedangkan opsi berjangka relatif besar. kerugian marginal opsi panggilan kurang dari keuntungan marginal posisi kontrak pendek, dan seluruh portofolio masih akan menghasilkan keuntungan.)

Oleh karena itu, dalam keadaan ideal, peningkatan dan penurunan subjek akan membawa manfaat selama pasar berfluktuasi.

Namun, ada juga faktor-faktor yang perlu dipertimbangkan: nilai waktu, biaya transaksi, dan faktor-faktor lainnya.

Oleh karena itu penjelasan hotshot di Zhihu dikutip:

The focus of Gamma Scalping is not on delta, dynamic delta hedging is just a way to avoid underlying price risk in the process.
Gamma Scaling focuses on alpha, which is not the alpha of stock selection. Here, alpha=gamma/theta, that is, how much gamma is exchanged for the time loss of unit Theta.
This is the point of concern. It is possible to construct a portfolio that floats both up and down, but it must be accompanied by time loss, and then the problem lies in the cost effectiveness.

Author: Xu Zhe
URL: https://www.zhihu.com/question/51630805/answer/128096385

Penjelasan desain strategi DDH

· Pengelompokan antarmuka pasar agregat, desain kerangka kerja · Desain UI Strategi · Desain interaksi strategis · Desain fungsi lindung nilai otomatis Kode sumber:

// Construct functions
function createManager(e, subscribeList, msg) {
	var self = {}
    self.supportList = ["Futures_Binance", "Huobi", "Futures_Deribit"]  // of the supported exchanges

    // 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: {bid1: 123, ask1: 123, symbol: "xxx"}}
    self.subscribeTickers = []           // The required market data, define the data format: {bid1: 123, ask1: 123, symbol: "xxx"}}
    self.accData = null 
    self.pos = null 

    // Initialize the function
    self.init = function() { 
    	// Judge if the exchange is supported
        if (!_.contains(self.supportList, self.name)) {        	
        	throw "not support"
        }
    }

    self.setBase = function(base) {
        // Switching base address for switching to analog bot
        self.e.SetBase(base)
        Log(self.name, self.label, "switch to analog bot:", base)
    }

    // Judging 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 {
            // Organize 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
    }
    
    // Back to the position 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 : []
        }
        /* Format of the position data 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])
                }
                // Iterate through 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 
    }

    // Initialization
    self.init()
	return self 
}


function main() {
    // Initialization, clear logs
    if(isResetLog) {
    	LogReset(1)
    }

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

    // Switch to analog 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
        }

        // Interactions
        var cmd = GetCommand()
        if(cmd) {
            // Handle interactions
            Log("Interaction commands", cmd)
            var arr = cmd.split(":")
            // cmdClearLog 
            if(arr[0] == "setContractType") {
                // parseFloat(arr[1])
                m1.e.SetContractType(arr[1])
                Log("exchanges[0] contract set by exchange object.", 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("execution price: ", price, "execution amount: ", amount, "execution 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("execution price: ", price, "execution amount: ", amount, "execution direction: ", arr[0])
            } else if (arr[0] == "setHedgeDeltaStep") {
                hedgeDeltaStep = parseFloat(arr[1])
                Log("set the parameter hedgeDeltaStep:", hedgeDeltaStep)
            } 
        }
        
        // Obtain the future contract prices
        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) {
                // Hedging futures go short if delta is greater than 0                 
                var amount = _N(Math.abs(sumDelta) * perpetualTicker.ask1, -1)                
                if (amount > 10) {
                    Log("Exceed the hedging threshold, current total delta:", sumDelta, "Buy futures")
                    m2.e.SetContractType("BTC-PERPETUAL")                    
                    m2.e.SetDirection("buy")
                    m2.e.Buy(-1, amount)
                } else {
                	hedgeMsg += ", hedging order volume less than 10"
                }
            } else {
                // Hedging futures go long if delta is less than 0
                var amount = _N(Math.abs(sumDelta) * perpetualTicker.bid1, -1)
                if (amount > 10) {
                    Log("Exceed the hedging threshold, current total delta:", sumDelta, "Sell futures")
                    m2.e.SetContractType("BTC-PERPETUAL")
                    m2.e.SetDirection("sell")
                    m2.e.Sell(-1, amount)
                } else {
                	hedgeMsg += ", hedging order volume less than 10"
                }
            }
        }

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

Alamat Strategi:https://www.fmz.com/strategy/265090

Operasi strategi:

img

Strategi ini adalah tutorial strategi, belajar berorientasi, silahkan gunakan dengan hati-hati di bot nyata.


Berkaitan

Lebih banyak