Type/to search
8
Follow
1364
Followers
लंबित ऑर्डर वायदा हेजिंग रणनीति के डिजाइन पर अनुसंधान और उदाहरण
Discussions
Created 2021-11-26 14:15:31  Updated 2023-09-20 09:24:03
 3
 2446

img

लंबित ऑर्डर वायदा हेजिंग रणनीति के डिजाइन पर अनुसंधान और उदाहरण

वायदा और हाजिर हेजिंग को हमेशा मूल्य अंतर का पता लगाने और मूल्य अंतर पूरा होने पर हेजिंग के लिए आदेश लेने के लिए डिज़ाइन किया गया है। क्या इसे लंबित ऑर्डर हेजिंग के रूप में डिज़ाइन किया जा सकता है? उत्तर है, हाँ। आज मैं पाठकों को पेंडिंग ऑर्डर हेजिंग के लिए एक डिज़ाइन आइडिया और कोड प्रोटोटाइप से परिचित कराऊंगा।

लंबित ऑर्डर हेजिंग विचार

जब विभिन्न बाजारों में एक ही या एक ही प्रकार की अंतर्निहित परिसंपत्ति के खरीद और बिक्री आदेशों में बड़ा अंतर होता है, तो हेजिंग का अवसर होता है। आम तौर पर, हम मूल्य अंतर को पूरा करने वाले बाजार आदेश लेंगे और एक बचाव स्थिति बनाए रखेंगे। इसलिए, हेजिंग के दो उद्देश्य हैं। पहला है ऑर्डर की स्थिति को हेज करना, और दूसरा यह सुनिश्चित करना कि खरीद और बिक्री की कीमतों के बीच का अंतर हमारी अपेक्षाओं को यथासंभव अधिकतम सीमा तक पूरा करे। इस संबंध में लंबित ऑर्डर ट्रेडिंग का लाभ यह है कि लेनदेन शुल्क दर कम है। इसका नुकसान यह है कि इसमें सौदा करना आसान नहीं है और एक पैर पर खड़े होकर सौदा करना आसान है।

फिर हम बाजार ए की ऑर्डर बुक के खरीद ऑर्डर में खरीद ऑर्डर रखने के लिए ट्रेडिंग आइडिया को डिजाइन करते हैं, और बाजार बी की ऑर्डर बुक के विक्रय ऑर्डर में विक्रय ऑर्डर रखते हैं। फिर हम अपने खाते के लंबित ऑर्डरों की जांच करते हैं और पाए गए लंबित ऑर्डरों के प्रसंस्करण में अगला कदम उठाते हैं। उदाहरण के लिए, जब लंबित ऑर्डरों में परिवर्तन का पता चलता है, तो वायदा और हाजिर हेजिंग स्थितियों को तुरंत संतुलित कर दिया जाता है, तथा वायदा और हाजिर स्थितियों में अतिप्रवाह वाली स्थितियों को कवर या बंद कर दिया जाता है। हेज्ड पोजीशन में वृद्धि के अनुसार, अगले लंबित ऑर्डर और बाजार के पहले स्तर के बीच की दूरी को धीरे-धीरे हेज करने और बड़ा मूल्य अंतर प्राप्त करने के लिए समायोजित किया जाता है।

हेजिंग लॉजिक img

कोड डिजाइन

टिप्पणियाँ सीधे कोड में लिखी जाती हैं। यह उदाहरण केवल संदर्भ डिज़ाइन के लिए उपयोग किया जाता है और इसे केवल OKEX V5 सिमुलेशन डिस्क पर संक्षिप्त रूप से परीक्षण किया गया है। यह उदाहरण पूर्ण रणनीति नहीं है और केवल संदर्भ के लिए है।

javascript
// 临时参数 var fuContractType = "quarter" // 期货合约 var fuSymbol = "ETH_USDT" // 期货交易对 var spSymbol = "ETH_USDT" // 现货交易对 var minAmount = 0.1 // 每次交易量、最小交易量,币数 var step = 40 // 差价步长 var buff = 5 // 缓冲差价 var balanceType = "open" // 对于单腿成交平衡时, open 补仓 close 平仓 var depthManager = function(fuEx, spEx, fuCt, fuSymbol, spSymbol) { var self = {} self.fuExDepth = null self.spExDepth = null self.plusPrice = null self.minusPrice = null self.update = function() { spEx.SetCurrency(spSymbol) if (!IsVirtual()) { fuEx.SetCurrency(fuSymbol) } fuEx.SetContractType(fuCt) var fuRoutine = fuEx.Go("GetDepth") var spRoutine = spEx.Go("GetDepth") var fuDepth = fuRoutine.wait() var spDepth = spRoutine.wait() if (!fuDepth || !spDepth) { return false } self.fuExDepth = fuDepth self.spExDepth = spDepth if (fuDepth.Bids.length == 0 || fuDepth.Asks.length == 0 || spDepth.Bids.length == 0 || spDepth.Asks.length == 0) { return false } self.plusPrice = fuDepth.Bids[0].Price - spDepth.Asks[0].Price // futures Bid - spot Ask self.minusPrice = fuDepth.Asks[0].Price - spDepth.Bids[0].Price // futures Ask - spot Bid return true } self.getData = function() { return { "fuExDepth" : self.fuExDepth, "spExDepth" : self.spExDepth, "plusPrice" : self.plusPrice, "minusPrice" : self.minusPrice } } return self } var positionManager = function(fuEx, spEx, fuCt, fuSymbol, spSymbol, step, buffDiff, balanceType, initSpAcc) { var self = {} self.balanceType = balanceType self.depth = null self.level = 1 self.lastUpdateTs = 0 self.fuPos = [] self.spPos = [] self.initSpAcc = initSpAcc self.spAcc = null self.hedgePos = null self.hedgePosPrice = 0 self.minAmount = 0.01 self.offset = ["", 0] self.update = function() { spEx.SetCurrency(spSymbol) if (!IsVirtual()) { fuEx.SetCurrency(fuSymbol) } fuEx.SetContractType(fuCt) self.offset = ["", 0] var fuRoutine = fuEx.Go("GetPosition") var spRoutine = spEx.Go("GetAccount") var fuPos = fuRoutine.wait() var spAcc = spRoutine.wait() if (!fuPos || !spAcc) { return false } self.fuPos = fuPos self.spAcc = spAcc if (!self.initSpAcc) { return false } self.spPos = (spAcc.Stocks + spAcc.FrozenStocks) - (self.initSpAcc.Stocks + self.initSpAcc.FrozenStocks) // 当前减去最初,正数为做多 // 检测fuPos if (fuPos.length > 1) { return false } fuPosAmount = fuPos.length == 0 ? 0 : (fuPos[0].Type == PD_LONG ? fuPos[0].Amount : -fuPos[0].Amount) if ((fuPosAmount > 0 && self.spPos > 0) || (fuPosAmount < 0 && self.spPos < 0)) { return false } fuPosAmount = self.piece2Coin(fuPosAmount) self.hedgePos = (fuPosAmount == 0 || self.spPos == 0) ? 0 : (fuPosAmount < 0 && self.spPos > 0 ? Math.min(Math.abs(fuPosAmount), Math.abs(self.spPos)) : -Math.min(Math.abs(fuPosAmount), Math.abs(self.spPos))) var diffBalance = (spAcc.Balance + spAcc.FrozenBalance) - (self.initSpAcc.Balance + self.initSpAcc.FrozenBalance) if (self.hedgePos == 0) { self.hedgePosPrice = 0 } else { self.hedgePosPrice = fuPos[0].Price - (Math.abs(diffBalance) / Math.abs(self.spPos)) } self.offset[1] = fuPosAmount + self.spPos // 正数多头持仓溢出,负数空头持仓溢出 if (fuPosAmount > 0 && self.spPos < 0) { // 反套 self.offset[0] = "minus" } else if (fuPosAmount < 0 && self.spPos > 0) { self.offset[0] = "plus" } else if (fuPosAmount == 0 && self.spPos < 0) { self.offset[0] = "minus" } else if (fuPosAmount > 0 && self.spPos == 0) { self.offset[0] = "minus" } else if (fuPosAmount == 0 && self.spPos > 0) { self.offset[0] = "plus" } else if (fuPosAmount < 0 && self.spPos == 0) { self.offset[0] = "plus" } return true } self.getData = function() { return { "fuPos" : self.fuPos, "spPos" : self.spPos, "initSpAcc" : self.initSpAcc, "spAcc" : self.spAcc, "hedgePos" : self.hedgePos, "hedgePosPrice" : self.hedgePosPrice, } } self.keepBalance = function(depth) { var fuDepth = depth.fuExDepth var spDepth = depth.spExDepth if (self.offset[0] == "plus") { if (self.offset[1] >= self.minAmount) { if (self.balanceType == "close") { // 现货多头持仓多了,平现货多仓 spEx.Sell(-1, self.offset[1]) } else if (self.balanceType == "open") { // 现货多头持仓多了,开期货空头持仓 fuEx.SetDirection("sell") fuEx.Sell(-1, self.coin2Piece(Math.abs(self.offset[1]))) } } else if (self.offset[1] <= -self.minAmount) { if (self.balanceType == "close") { // 期货空头持仓多了,平期货空仓 fuEx.SetDirection("closesell") fuEx.Buy(-1, self.coin2Piece(Math.abs(self.offset[1]))) } else if (self.balanceType == "open") { // 期货空头持仓多了,开现货多头持仓 spEx.Buy(-1, spDepth.Asks[0].Price * Math.abs(self.offset[1])) } } return false } else if (self.offset[0] == "minus") { if (self.offset[1] >= self.minAmount) { if (self.balanceType == "close") { // 期货多头持仓多了,平期货多仓 fuEx.SetDirection("closebuy") fuEx.Sell(-1, self.coin2Piece(self.offset[1])) } else if (self.balanceType == "open") { // 期货多头持仓多了,开现货空头持仓 spEx.Sell(-1, self.offset[1]) } } else if (self.offset[1] <= -self.minAmount) { if (self.balanceType == "close") { // 现货空头持仓多了,平现货空仓 spEx.Buy(-1, spDepth.Asks[0].Price * Math.abs(self.offset[1])) } else if (self.balanceType == "open") { // 现货空头持仓多了,开期货多头持仓 fuEx.SetDirection("buy") fuEx.Buy(-1, self.coin2Piece(Math.abs(self.offset[1]))) } } return false } return true } self.process = function(depthManager) { var ts = new Date().getTime() var depth = depthManager.getData() var orders = self.getOrders() if (!orders) { return } self.depth = depth var fuOrders = orders[0] var spOrders = orders[1] if (fuOrders.length == 0 && spOrders.length == 0) { // 重置level if (self.hedgePos == 0) { self.level = 1 } else { self.level = Math.max(1, _N(self.hedgePos / self.minAmount, 0)) } // 限制最大持仓量 if (Math.abs(self.hedgePos) > 1) { return } // 挂单 var fuDepth = depth.fuExDepth var spDepth = depth.spExDepth self.update() if (self.hedgePos >= 0 && fuDepth.Bids[0].Price - spDepth.Asks[0].Price > 0) { // 正套 var distance = (step * self.level - (fuDepth.Asks[0].Price - spDepth.Bids[0].Price)) / 2 fuEx.SetDirection("sell") fuEx.Sell(fuDepth.Asks[0].Price + distance, self.coin2Piece(self.minAmount), fuDepth.Asks[0].Price, "挂单差价:", fuDepth.Asks[0].Price + distance - (spDepth.Bids[0].Price - distance)) spEx.Buy(spDepth.Bids[0].Price - distance, self.minAmount, spDepth.Bids[0].Price) } else if (self.hedgePos <= 0 && spDepth.Bids[0].Price - fuDepth.Asks[0].Price > 0) { // 反套 var distance = (step * self.level - (spDepth.Asks[0].Price - fuDepth.Bids[0].Price)) / 2 fuEx.SetDirection("buy") fuEx.Buy(fuDepth.Bids[0].Price - distance, self.coin2Piece(self.minAmount), fuDepth.Bids[0].Price, "挂单差价:", spDepth.Asks[0].Price + distance - (fuDepth.Bids[0].Price - distance)) spEx.Sell(spDepth.Asks[0].Price + distance, self.minAmount, spDepth.Asks[0].Price) } } else if (fuOrders.length == 1 && spOrders.length == 1) { var fuDepth = depth.fuExDepth var spDepth = depth.spExDepth // 判断位置 var isCancelAll = false if (self.hedgePos >= 0 && fuDepth.Bids[0].Price - spDepth.Asks[0].Price > 0) { // 正套 var distance = (step * self.level - (fuDepth.Asks[0].Price - spDepth.Bids[0].Price)) / 2 if (Math.abs(fuOrders[0].Price - (fuDepth.Asks[0].Price + distance)) > buffDiff || Math.abs(spOrders[0].Price - (spDepth.Bids[0].Price - distance)) > buffDiff) { isCancelAll = true } } else if (self.hedgePos <= 0 && spDepth.Bids[0].Price - fuDepth.Asks[0].Price > 0) { // 反套 var distance = (step * self.level - (spDepth.Asks[0].Price - fuDepth.Bids[0].Price)) / 2 if (Math.abs(spOrders[0].Price - (spDepth.Asks[0].Price + distance)) > buffDiff || Math.abs(fuOrders[0].Price - (fuDepth.Bids[0].Price - distance)) > buffDiff) { isCancelAll = true } } else { isCancelAll = true } if (isCancelAll) { self.cancelAll(fuEx, fuOrders) self.cancelAll(spEx, spOrders) self.lastUpdateTs = 0 } } else { self.cancelAll(fuEx, fuOrders) self.cancelAll(spEx, spOrders) self.lastUpdateTs = 0 } if (ts - self.lastUpdateTs > 1000 * 60 * 2) { self.update() self.keepBalance(depth) self.update() self.lastUpdateTs = ts } LogStatus(_D()) // 状态栏可以设计输出需要观察的数据、信息 } self.getOrders = function() { spEx.SetCurrency(spSymbol) if (!IsVirtual()) { fuEx.SetCurrency(fuSymbol) } fuEx.SetContractType(fuCt) var fuRoutine = fuEx.Go("GetOrders") var spRoutine = spEx.Go("GetOrders") var fuOrders = fuRoutine.wait() var spOrders = spRoutine.wait() if (!fuOrders || !spOrders) { return false } return [fuOrders, spOrders] } // 币转合约张数 self.coin2Piece = function(amount) { if (IsVirtual()) { if (fuEx.GetName() == "Futures_Binance") { return amount } else if (fuEx.GetName() == "Futures_OKCoin") { var price = (self.depth.fuExDepth.Bids[0].Price + self.depth.fuExDepth.Asks[0].Price) / 2 return _N(amount / (100 / price), 0) } else { throw "not support" } } if (fuEx.GetName() == "Futures_OKCoin") { if (fuEx.GetQuoteCurrency() == "USDT") { return _N(amount * 10, 0) } else if (fuEx.GetQuoteCurrency() == "USD") { var price = (self.depth.fuExDepth.Bids[0].Price + self.depth.fuExDepth.Asks[0].Price) / 2 return _N(amount / (100 / price), 0) } else { throw "not support" } } else { throw "not support" } } // 合约张数转币 self.piece2Coin = function(amount) { if (IsVirtual()) { if (fuEx.GetName() == "Futures_Binance") { return amount } else if (fuEx.GetName() == "Futures_OKCoin") { var price = (self.depth.fuExDepth.Bids[0].Price + self.depth.fuExDepth.Asks[0].Price) / 2 return amount * 100 / price } else { throw "not support" } } if (fuEx.GetName() == "Futures_OKCoin") { if (fuEx.GetQuoteCurrency() == "USDT") { return amount * 0.1 } else if (fuEx.GetQuoteCurrency() == "USD") { var price = (self.depth.fuExDepth.Bids[0].Price + self.depth.fuExDepth.Asks[0].Price) / 2 return amount * 100 / price } else { throw "not support" } } else { throw "not support" } } self.cancelAll = function(e, orders) { var isFirst = true while (true) { Sleep(500) if (orders && isFirst) { isFirst = false } else { orders = e.GetOrders() } if (!orders) { continue } else { for (var i = 0 ; i < orders.length ; i++) { e.CancelOrder(orders[i].Id, orders[i]) } } if (orders.length == 0) { break } } } self.CoverAll = function() { // 全部平仓 // 这里可以实现一个,一键平仓的功能 } self.setMinAmount = function(minAmount) { self.minAmount = minAmount } self.init = function() { while(!self.spAcc) { self.update() Sleep(1000) } if (!self.initSpAcc) { var positionManager_initSpAcc = _G("positionManager_initSpAcc") if (!positionManager_initSpAcc) { self.initSpAcc = self.spAcc _G("positionManager_initSpAcc", self.initSpAcc) } else { self.initSpAcc = positionManager_initSpAcc } } else { _G("positionManager_initSpAcc", self.initSpAcc) } // 打印初始信息 Log("self.initSpAcc:", self.initSpAcc.Balance, self.initSpAcc.FrozenBalance, self.initSpAcc.Stocks, self.initSpAcc.FrozenStocks) } self.init() return self } function main() { _G(null) // 清空持久化数据 LogReset(1) // 重置日志 // 以下代码可以切换OKEX模拟盘 // exchanges[0].IO("simulate", true) // exchanges[1].IO("simulate", true) var dm = depthManager(exchanges[0], exchanges[1], fuContractType, fuSymbol, spSymbol) var pm = positionManager(exchanges[0], exchanges[1], fuContractType, fuSymbol, spSymbol, step, buff, balanceType) pm.setMinAmount(minAmount) while (true) { if (!dm.update()) { Sleep(3000) continue } var cmd = GetCommand() if (cmd) { // 处理交互 Log("交互命令:", cmd) var arr = cmd.split(":") if (arr[0] == "") { pm.CoverAll() } } pm.process(dm) Sleep(5000) } }

बैकटेस्ट विश्लेषण

img

img

यह देखा जा सकता है कि ऑर्डर बहुत बार दिए जाते हैं और रद्द कर दिए जाते हैं। बैकटेस्टिंग सिस्टम द्वारा गणना किए गए मुनाफे से देखते हुए, वायदा एक्सचेंज खाते में -0.01666 ETH का नुकसान हुआ, और स्पॉट एक्सचेंज ने 842.23758 USDT का लाभ कमाया। बैकटेस्ट के अंत में, ETH स्पॉट मूल्य 4252USDT था।-0.01666 * 4252 = -70.83832000000001. हाजिर मुनाफे के साथ मिलाकर, कुल मिलाकर स्थिति लाभदायक है।

हालाँकि, यह सिर्फ एक बैकटेस्ट है, और अधिक विवरण वास्तविक ट्रेडिंग में हल किए जाने चाहिए।

Related Recommendations
Comment
All comments (3)

    梦总,支持okex统一账户模式不 现货买入ETH 期货直接当保证金做空

    4 years ago

    您好, 支持OKEX V5接口的,支持这个模式。

    4 years ago

    4 years ago
  • 1
iPhone Download
Forums
PINE Language
© 2015 - ∞ INVENTOR PTE LTD (SG)