리소스 로딩... 로딩...

데리비트 옵션 델타 동적 헤딩 전략

저자:발명가들의 수량화 - 작은 꿈, 2021-03-26 11:18:53로 제작, 2024-12-05 21:55:32로 업데이트

img

데리비트 옵션 델타 동적 헤딩 전략

이 FMZ의 전략은데리비트 옵션 델타 동적 헤딩 전략이 전략은 동적 델타 헤딩 (DDH) 이라고도 불린다.

옵션 거래에 대한 학습은 일반적으로 다음과 같은 몇 가지 개념을 습득해야합니다.

  • 옵션 가격 모델, B-S 모델, 옵션 가격은 표지표에 따른 물품 가격 오차, 유통권 가격 오차, 만료 남은 시간 오차, 유동률 오차, 무관한 금리 오차 등에 따라 가격을 결정한다.

  • 이 모든 것은 우리가 할 수 있는 일입니다.

    • 델타 옵션의 방향 위험. 만약 델타가 +0.50이라면, 이 옵션은 지표 가격의 하락에 따른 이익/손실 성과를 0.50 현금으로 간주할 수 있다.
    • 감마 방향의 위험의 가속화. 예를 들어, 감마의 작용으로 인해 지표가격이 주행권 가격에 위치하기 시작하여, 가격이 상승하는 과정에서 델타는 +0.50에서 +1.00로 점차적으로 상승한다.
    • 테타 시간 (Theta time) ─ 당신이 옵션을 구매할 때, 지표 가격이 움직이지 않는다면, 매일, 당신은 테타 금액의 표시된 수수료를 지불할 것이다 (USD로 계산된 데리비트) ─ 만약 지표값이 변하지 않는다면, 당신이 옵션을 팔 때, 당신은 하루가 지나면 테타 금액에 표시된 수수료를 받게 된다.
    • 베가 변동률 . 당신이 옵션을 구매할 때 베가는 긍정적, 즉 더 많은 변동률을 한다. 함축 변동률이 증가하면 베가 에서 수익을 얻는다. 반대로, 당신이 옵션을 판매할 때 함축 변동률이 감소하면 수익을 얻는다.

DDH의 전략은 다음과 같습니다:

  • DDH의 원리 설명 옵션과 선물의 델타를 평준화함으로써 거래 방향의 위험 중립성을 달성한다. 옵션의 델타는 지표의 물가 변화를 따라 변하기 때문에, 선물과 현금의 델타는 변하지 않는다. 옵션 계약 포지션을 보유한 후, 선물 헤지핑으로 델타를 평준화한 후, 지표의 물가 변동에 따라 전체 델타는 다시 불균형 상태에 놓이게 된다. 옵션 포지션과 선물 포지션과 같은 조합에 대해서는 지속적인 동적 헤지핑 평준화가 델타가 필요하다.

    예를 들어: 우리가 파일옵션을 구매할 때, 우리는 다방향 파일옵션을 보유하고 있다. 이 때, 전체 델타 중립 (<0 또는 0에 가까운) 을 달성하기 위해 옵션의 델타를 헤지하기 위해 빈 퓨처스를 할 필요가 있다. 우리는 옵션 계약의 남은 기간, 변동률 등의 요소를 고려하지 않습니다. 상황 1: 지표 물가가 상승하고, 옵션 부분의 델타가 증가하고, 전체 델타가 긍정으로 이동하여, 선물이 다시 헤딩이 필요하며, 일부 빈 헤드 포션을 열어 빈 선물로 계속하여 전체 델타를 다시 균형을 이루게합니다. (다시 평준화되기 전에, 이 기간 권리의 델타는 크고, 선물의 델타는 상대적으로 작으며, 유가 옵션의 마진 이득이 계약 공백의 마진 손실을 초과하고, 전체 포트폴리오는 이익이 나타납니다.)

    두 번째 사례: 지표 물가 하락, 옵션 부분의 델타가 감소, 전체 델타가 마이너스 방향으로 이동, 평형 부분의 빈 헤드 선물 보유가 전체 델타를 다시 균형을 이루고 있다. (다시 평준화되기 전에, 이 기간 동안 권리의 델타는 작고, 선물의 델타는 상대적으로 크며, 유가 옵션의 변수 손실은 계약 공백의 변수 이익보다 작고, 전체 포트폴리오는 여전히 이익을 얻을 수 있습니다.)

    그래서 이상적으로, 가격 상승은 시장의 변동이 있을 때에도 수익을 가져올 수 있습니다.

    그러나 고려해야 할 다른 요소도 있습니다. 시간 가치, 거래 비용 등.

    그래서 소를 아는 사람의 설명을 인용합니다:

    Gamma Scalping 的关注点并不是delta,dynamic delta hedging 只是过程中规避underlying价格风险的一种做法而已。
    Gamma Scalping 关注的是Alpha,此Alpha不是选股的Alpha,这里的Alpha = Gamma/Theta也就是单位Theta的时间损耗换来多少Gamma,
    这个是关注的点。可以构建出上涨和下跌都浮盈的组合,但一定伴随时间损耗,那问题就在于性价比了。
    
    作者:许哲
    链接:https://www.zhihu.com/question/51630805/answer/128096385
    

DDH 전략 설계 설명

  • 융합 시장 인터페이스 포장, 프레임 디자인
  • 전략 UI 디자인
  • 전략적 인터랙션 디자인
  • 자동 헤지킹 기능 설계

이 글의 소스:

// 构造函数
function createManager(e, subscribeList, msg) {
	var self = {}
    self.supportList = ["Futures_Binance", "Huobi", "Futures_Deribit"]  // 支持的交易所的

    // 对象属性
    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 = []                    // 接口获取的所有行情数据,定义数据格式:{bid1: 123, ask1: 123, symbol: "xxx"}}
    self.subscribeTickers = []           // 需要的行情数据,定义数据格式:{bid1: 123, ask1: 123, symbol: "xxx"}}
    self.accData = null 
    self.pos = null 

    // 初始化函数
    self.init = function() { 
    	// 判断是否支持该交易所
        if (!_.contains(self.supportList, self.name)) {        	
        	throw "not support"
        }
    }

    self.setBase = function(base) {
        // 切换基地址,用于切换为模拟盘
        self.e.SetBase(base)
        Log(self.name, self.label, "切换为模拟盘:", base)
    }

    // 判断数据精度
    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
    }

    // 更新资产
    self.updateAcc = function(callBackFuncGetAcc) {
        var ret = callBackFuncGetAcc(self)
        if (!ret) {
        	return false 
        }
        self.accData = ret 
        return true 
    }

    // 更新持仓
    self.updatePos = function(httpMethod, url, params) {
        var pos = self.e.IO("api", httpMethod, url, params)
        var ret = []
        if (!pos) {
            return false 
        } else {
            // 整理数据
            // {"jsonrpc":"2.0","result":[],"usIn":1616484238870404,"usOut":1616484238870970,"usDiff":566,"testnet":true}
            try {
                _.each(pos.result, function(ele) {
                    ret.push(ele)
                })
            } catch(err) {
                Log("错误:", err)
                return false 
            }
            self.pos = ret
        }
        return true 
    }

    // 更新行情数据
    self.updateTicker = function(url, callBackFuncGetArr, callBackFuncGetTicker) {
    	var tickers = []
    	var subscribeTickers = []
    	var ret = self.httpQuery(url)
    	if (!ret) {
    		return false 
    	}
    	// Log("测试", ret)// 测试
    	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("错误:", 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("错误:", 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
    }
    
    // 返回持仓表格
    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 : []
        }
        /* 接口返回的持仓数据格式
        {
            "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])
                }
                // 遍历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 
    }

    // 初始化
    self.init()
	return self 
}


function main() {
    // 初始化,清空日志
    if(isResetLog) {
    	LogReset(1)
    }

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

    // 切换为模拟盘
    var base = "https://www.deribit.com"
    if (isTestNet) {    
        m1.setBase(testNetBase)    
        m2.setBase(testNetBase)
        base = testNetBase
    }

    while(true) {
        // 期权
        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}}) 
        
        // 永续期货
        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
        }

        // 更新持仓
        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
        }

        // 交互
        var cmd = GetCommand()
        if(cmd) {
            // 处理交互
            Log("交互命令:", cmd)
            var arr = cmd.split(":")
            // cmdClearLog 
            if(arr[0] == "setContractType") {
                // parseFloat(arr[1])
                m1.e.SetContractType(arr[1])
                Log("exchanges[0]交易所对象设置合约:", 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("执行价格:", price, "执行数量:", amount, "执行方向:", 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("执行价格:", price, "执行数量:", amount, "执行方向:", arr[0])
            } else if (arr[0] == "setHedgeDeltaStep") {
                hedgeDeltaStep = parseFloat(arr[1])
                Log("设置参数hedgeDeltaStep:", hedgeDeltaStep)
            } 
        }
        
        // 获取期货合约价格
        var perpetualTicker = m2.getTicker("BTC-PERPETUAL")
        var hedgeMsg = " PERPETUAL:" + JSON.stringify(perpetualTicker)

        // 从账户数据中获取delta总值        
        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 大于0 对冲期货做空                
                var amount = _N(Math.abs(sumDelta) * perpetualTicker.ask1, -1)                
                if (amount > 10) {
                    Log("超过对冲阈值,当前总delta:", sumDelta, "买入期货")
                    m2.e.SetContractType("BTC-PERPETUAL")                    
                    m2.e.SetDirection("buy")
                    m2.e.Buy(-1, amount)
                } else {
                	hedgeMsg += ", 对冲下单量小于10"
                }
            } else {
                // delta 小于0 对冲期货做多
                var amount = _N(Math.abs(sumDelta) * perpetualTicker.bid1, -1)
                if (amount > 10) {
                    Log("超过对冲阈值,当前总delta:", sumDelta, "卖出期货")
                    m2.e.SetContractType("BTC-PERPETUAL")
                    m2.e.SetDirection("sell")
                    m2.e.Sell(-1, amount)
                } else {
                	hedgeMsg += ", 对冲下单量小于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)
    }
}


전략 파라미터:img

그라운드:https://www.fmz.com/strategy/265090

전략 실행:

img

img

이 전략은 교육 전략, 학습을 기본으로 하며, 실제 사용에 주의를 기울여야 합니다.


관련

더 많은

환상상이것은 실제 디스크에 사용할 수 있습니까?

궤도 생물이 지표는 이 지표에 대한 모든 정보를 담고 있습니다.

발명가들의 수량화 - 작은 꿈이런 식으로 설계하면 전략 코드를 구체적으로 변경할 수 있습니다.

환상상예를 들어, 어떤 가격 이상으로 ddh를 실행할 수 있는지

발명가들의 수량화 - 작은 꿈안녕하세요, 전략은 교육, 테스트, 실제 디스크에 직접 수정 할 수 있습니다.

발명가들의 수량화 - 작은 꿈예, 블록체인 자산 파생 거래소, 동전계에서 가장 전문적인 옵션 거래소.