Type/to search
8
Follow
1364
Followers
Nghiên cứu và ví dụ về thiết kế chiến lược phòng ngừa rủi ro tương lai lệnh chờ
Discussions
Created 2021-11-26 14:15:31  Updated 2023-09-20 09:24:03
 3
 2446

img

Nghiên cứu và ví dụ về thiết kế chiến lược phòng ngừa rủi ro tương lai lệnh chờ

Hợp đồng tương lai và hợp đồng giao ngay luôn được thiết kế để phát hiện chênh lệch giá và tiếp nhận lệnh phòng ngừa khi đạt đến mức chênh lệch giá đó. Có thể thiết kế nó như một biện pháp phòng ngừa lệnh chờ không? Câu trả lời là có. Hôm nay tôi sẽ giới thiệu đến bạn đọc ý tưởng thiết kế và nguyên mẫu mã cho hoạt động phòng ngừa lệnh chờ.

Ý tưởng phòng ngừa lệnh chờ

Khi có sự chênh lệch lớn giữa lệnh mua và lệnh bán cùng loại tài sản cơ bản hoặc cùng loại tài sản cơ bản ở các thị trường khác nhau, sẽ có cơ hội để phòng ngừa rủi ro. Nhìn chung, chúng tôi sẽ tiếp nhận các lệnh thị trường đáp ứng được mức chênh lệch giá và giữ vị thế phòng ngừa. Do đó, mục đích của việc phòng ngừa rủi ro có hai mặt. Đầu tiên là phòng ngừa các vị thế lệnh, và thứ hai là đảm bảo rằng chênh lệch giữa giá mua và giá bán đáp ứng kỳ vọng của chúng tôi ở mức độ lớn nhất có thể. Ưu điểm của giao dịch lệnh chờ trong trường hợp này là mức phí giao dịch thấp hơn. Nhược điểm là không dễ để chốt giao dịch và dễ chốt giao dịch trên một chân.

Sau đó, chúng ta thiết kế ý tưởng giao dịch để đặt lệnh mua vào lệnh mua trong sổ lệnh của thị trường A và đặt lệnh bán vào lệnh bán trong sổ lệnh của thị trường B. Sau đó, chúng tôi kiểm tra các lệnh đang chờ xử lý trong tài khoản và thực hiện bước tiếp theo để xử lý các lệnh đang chờ xử lý đã phát hiện. Ví dụ, khi phát hiện có sự thay đổi trong các lệnh chờ, các vị thế phòng ngừa tương lai và giao ngay sẽ được cân bằng ngay lập tức, và các vị thế tràn trong các vị thế tương lai và giao ngay sẽ được bảo hiểm hoặc đóng lại. Theo sự gia tăng của các vị thế được phòng ngừa, khoảng cách giữa lệnh chờ tiếp theo và bậc đầu tiên của thị trường được điều chỉnh để phòng ngừa dần dần và đạt được mức chênh lệch giá lớn hơn.

Logic phòng ngừa img

Thiết kế mã

Các bình luận được viết trực tiếp trong mã. Ví dụ này chỉ được sử dụng cho thiết kế tham khảo và chỉ được thử nghiệm ngắn gọn trên đĩa mô phỏng OKEX V5. Ví dụ này không phải là chiến lược hoàn chỉnh và chỉ mang tính chất tham khảo.

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) } }

Phân tích kiểm tra ngược

img

img

Có thể thấy rằng các đơn hàng được đặt và hủy rất thường xuyên. Theo lợi nhuận được tính toán bởi hệ thống kiểm tra ngược, tài khoản giao dịch tương lai đã lỗ -0,01666 ETH và sàn giao dịch giao ngay đã kiếm được lợi nhuận là 842,23758 USDT. Vào cuối đợt kiểm tra ngược, giá giao ngay của ETH là 4252USDT.-0.01666 * 4252 = -70.83832000000001. Kết hợp với lợi nhuận giao ngay, tình hình chung là có lợi nhuận.

Tuy nhiên, đây chỉ là thử nghiệm ngược và cần phải giải quyết thêm nhiều chi tiết hơn trong quá trình giao dịch thực tế.

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)