Thiết kế chiến lược tương lai tiền điện tử kiểu Martingale

Tác giả:Ninabadass, Tạo: 2022-04-12 17:50:07, Cập nhật: 2022-04-12 18:06:07

Thiết kế chiến lược tương lai tiền điện tử kiểu Martingale

Gần đây, có rất nhiều chiến lược kiểu Martingale được thảo luận trong nhóm chính thức FMZ, và không có nhiều chiến lược kiểu Martingale của các hợp đồng tiền điện tử trên nền tảng của chúng tôi. Do đó, tôi đã tận dụng cơ hội này để thiết kế một chiến lược kiểu Martingale tương lai tiền điện tử đơn giản. Tại sao nó được gọi là chiến lược kiểu Martingale? Bởi vì rủi ro tiềm năng của chiến lược Martingale thực sự không nhỏ, không cần thiết phải thiết kế theo chiến lược Martingale. Tuy nhiên, loại chiến lược này vẫn có rất nhiều rủi ro, và cài đặt tham số của chiến lược kiểu Martingale có liên quan chặt chẽ đến rủi ro, và rủi ro không được bỏ qua.

Trong bài viết này, chúng tôi chủ yếu giải thích và học hỏi từ việc thiết kế các chiến lược kiểu Martingale.

Có được toàn bộ vốn chủ sở hữu

Tổng vốn chủ sở hữu thường được sử dụng khi thiết kế một chiến lược tương lai tiền điện tử, vì chúng ta muốn tính toán lợi nhuận, đặc biệt là khi chúng ta cần tính toán lợi nhuận nổi.exchange.GetAccount()Trong thực tế, hầu hết các nền tảng tương lai tiền điện tử cung cấp dữ liệu tổng vốn chủ sở hữu, nhưng tài sản này không được đóng gói đồng nhất trên FMZ.

Do đó, chúng tôi thiết kế riêng các chức năng để lấy dữ liệu theo các nền tảng khác nhau:

// OKEX V5 obtains the total equity 
function getTotalEquity_OKEX_V5() {
    var totalEquity = null 
    var ret = exchange.IO("api", "GET", "/api/v5/account/balance", "ccy=USDT")
    if (ret) {
        try {
            totalEquity = parseFloat(ret.data[0].details[0].eq)
        } catch(e) {
            Log("Fail to obtain the total equity of the account!")
            return null
        }
    }
    return totalEquity
}

// Binance Ftures 
function getTotalEquity_Binance() {
    var totalEquity = null 
    var ret = exchange.GetAccount()
    if (ret) {
        try {
            totalEquity = parseFloat(ret.Info.totalWalletBalance)
        } catch(e) {
            Log("Fail to obtain the total equity!")
            return null
        }
    }
    return totalEquity
}

CáctotalEquitySau đó chúng ta viết một hàm như là mục gọi, và gọi hàm tương ứng theo tên nền tảng.

function getTotalEquity() {
    var exName = exchange.GetName()
    if (exName == "Futures_OKCoin") {
        return getTotalEquity_OKEX_V5()
    } else if (exName == "Futures_Binance") {
        return getTotalEquity_Binance()
    } else {
        throw "Do not support the platform"
    }
}

Thiết kế một số chức năng phụ trợ

Trước khi thiết kế chức năng chính và logic chính, chúng ta cũng cần thiết kế một số chức năng phụ trợ để chuẩn bị.

  • Hủy tất cả các đơn đặt hàng đang chờ

    function cancelAll() {
        while (1) {
            var orders = _C(exchange.GetOrders)
            if (orders.length == 0) {
                break
            }
            for (var i = 0 ; i < orders.length ; i++) {
                exchange.CancelOrder(orders[i].Id, orders[i])
                Sleep(500)
            }
            Sleep(500)
        }
    }
    

    Chức năng này được cho là quen thuộc với những người thường đọc mã ví dụ chiến lược trên hình vuông chiến lược FMZ, và nhiều chiến lược đã sử dụng thiết kế tương tự.

  • Hoạt động đặt lệnh tương lai

    function trade(distance, price, amount) {
        var tradeFunc = null 
        if (distance == "buy") {
            tradeFunc = exchange.Buy
        } else if (distance == "sell") {
            tradeFunc = exchange.Sell
        } else if (distance == "closebuy") {
            tradeFunc = exchange.Sell
        } else {
            tradeFunc = exchange.Buy
        }
        exchange.SetDirection(distance)
        return tradeFunc(price, amount)
    }
    
    function openLong(price, amount) {
        return trade("buy", price, amount)
    }
    
    function openShort(price, amount) {
        return trade("sell", price, amount)
    }
    
    function coverLong(price, amount) {
        return trade("closebuy", price, amount)
    }
    
    function coverShort(price, amount) {
        return trade("closesell", price, amount)
    }
    

    Có bốn hướng giao dịch tương lai: mở vị trí dài (openLong), mở vị trí ngắn (openShort), đóng vị trí dài (coverLong), và đóng vị trí ngắn (coverShort). Do đó, chúng tôi đã thiết kế bốn chức năng lệnh để tương ứng với các hoạt động này. Nếu bạn chỉ xem xét đặt lệnh, thì có một số yếu tố cần thiết: hướng, giá lệnh và số tiền lệnh.

    Chúng tôi cũng thiết kế một chức năng có tên:tradeđể xử lý hoạt động khidirection (distance), order price (price)order amount (amount)được xác định.

    Các cuộc gọi chức năng của các vị trí mở dài (openLong), các vị trí mở ngắn (openShort), đóng các vị trí dài (coverLong), và đóng các vị trí ngắn (coverShort) cuối cùng được hoàn thành bởitradechức năng, đó là, theo hướng, giá và số tiền được chỉ định, đặt lệnh trong các nền tảng tương lai.

Chức năng chính

Ý tưởng chiến lược rất đơn giản; lấy giá hiện tại làm đường cơ sở, và từ một khoảng cách nhất định trên và dưới đường cơ sở để đặt lệnh bán (short) và mua lệnh (long). Nếu lệnh của một bên được thực hiện, hủy tất cả các lệnh còn lại, và sau đó các lệnh đóng mới sẽ được đặt ở một khoảng cách nhất định theo giá vị trí, và các lệnh mua sẽ được đặt ở mức giá hiện tại được cập nhật, nhưng các lệnh mua sẽ không tăng gấp đôi số tiền đặt hàng.

  • Công việc ban đầu Vì chúng ta muốn chờ đặt hàng, chúng ta cần hai biến để ghi lại ID đặt hàng.

    var buyOrderId = null
    var sellOrderId = null
    

    Sau đó, tùy chọn sử dụng OKEX_V5 mô phỏng bot được thiết kế trong các thông số giao diện chiến lược, vì vậy một số xử lý cần phải được thực hiện trong mã:

    var exName = exchange.GetName()    
    // switch to OKEX V5 simulated bot 
    if (isSimulate && exName == "Futures_OKCoin") {
        exchange.IO("simulate", true)
    }
    

    Tùy chọn để thiết lập lại tất cả thông tin cũng được thiết kế trong các thông số chiến lược, vì vậy một số xử lý cần phải được thực hiện trong mã:

    if (isReset) {
        _G(null)
        LogReset(1)
        LogProfitReset()
        LogVacuum()
        Log("Reset all data", "#FF0000")
    }
    

    Chúng ta chỉ chạy các hợp đồng vĩnh viễn, vì vậy ở đây chúng ta viết nó trong một vòng lặp vô hạn, và chúng ta chỉ đặt nó vào hợp đồng vĩnh viễn.

    exchange.SetContractType("swap")
    

    Ngoài ra, chúng ta cần phải xem xét các vấn đề chính xác của giá lệnh và số tiền đặt hàng. Nếu chính xác không được đặt đúng, nó sẽ bị mất trong quá trình tính toán chiến lược. Nếu dữ liệu có số lượng lớn số thập phân, rất dễ gây ra lệnh bị từ chối bởi giao diện nền tảng.

    exchange.SetPrecision(pricePrecision, amountPrecision)
    Log("set percision", pricePrecision, amountPrecision)
    

    Chức năng khôi phục dữ liệu đơn giản trong thiết kế

    if (totalEq == -1 && !IsVirtual()) {
        var recoverTotalEq = _G("totalEq")
        if (!recoverTotalEq) {
            var currTotalEq = getTotalEquity()
            if (currTotalEq) {
                totalEq = currTotalEq
                _G("totalEq", currTotalEq)
            } else {
                throw "Fail to obtain the initial equity"
            }
        } else {
            totalEq = recoverTotalEq
        }
    }
    

    Nếu bạn muốn chỉ định vốn chủ sở hữu ban đầu của tài khoản khi chạy chiến lược, bạn có thể đặt tham sốtotalEq. Nếu tham số này được đặt thành -1, chiến lược sẽ đọc dữ liệu tổng vốn chủ sở hữu được lưu trữ. Nếu không có dữ liệu tổng vốn chủ sở hữu được lưu trữ, tổng vốn chủ sở hữu hiện đang được đọc được sử dụng làm tổng vốn chủ sở hữu ban đầu trong chiến lược đang tiến hành. Sau đó, nếu tổng vốn chủ sở hữu tăng, điều đó có nghĩa là nó đã kiếm được lợi nhuận; nếu tổng vốn chủ sở hữu giảm, điều đó có nghĩa là có lỗ. Nếu dữ liệu tổng vốn chủ sở hữu được đọc, hãy sử dụng dữ liệu để tiếp tục chạy.

  • Lý thuyết chính Sau khi hoàn thành công việc ban đầu, cuối cùng chúng tôi đã đến với phần logic chính của chiến lược.

      while (1) {                                  // the main logic of the strategy is designed as an infinite loop
          var ticker = _C(exchange.GetTicker)      // read the current market information first, in which we mainly use the latest trading price
          var pos = _C(exchange.GetPosition)       // read the current position data 
          if (pos.length > 1) {                    // judge the position data; due to the strategy logic, it is unlikely to have long and short positions at the same time, so if there are long and short positions at the same time, an error will be thrown
              Log(pos)
              throw "concurrently with long and short positions"                  // raise an error, and stop the strategy 
          }
          // according to the status 
          if (pos.length == 0) {                    // according to the position status, make different operations; if pos.length == 0, it means currently no position
              // when there is no position yet, calculate the equity 
              if (!IsVirtual()) {
                  var currTotalEq = getTotalEquity()
                  if (currTotalEq) {
                      LogProfit(currTotalEq - totalEq, "Current total equity:", currTotalEq)
                  }
              }
    
              buyOrderId = openLong(ticker.Last - targetProfit, amount)       // pend buy order of open long position 
              sellOrderId = openShort(ticker.Last + targetProfit, amount)     // pend sell order of open short position
          } else if (pos[0].Type == PD_LONG) {   // there are long positions; pending position and amount are 
              var n = 1
              var price = ticker.Last
              buyOrderId = openLong(price - targetProfit * n, amount)
              sellOrderId = coverLong(pos[0].Price + targetProfit, pos[0].Amount)
          } else if (pos[0].Type == PD_SHORT) {   // there are short positions; pending position and amount are different 
              var n = 1
              var price = ticker.Last
              buyOrderId = coverShort(pos[0].Price - targetProfit, pos[0].Amount)
              sellOrderId = openShort(price + targetProfit * n, amount)
          }
    
          if (!sellOrderId || !buyOrderId) {   // if opending orders of one side fails, cancel all pending orders and try again 
              cancelAll()
              buyOrderId = null 
              sellOrderId = null
              continue
          } 
    
          while (1) {  // finish pending the order, and start to monitor the order
              var isFindBuyId = false 
              var isFindSellId = false
              var orders = _C(exchange.GetOrders)
              for (var i = 0 ; i < orders.length ; i++) {
                  if (buyOrderId == orders[i].Id) {
                      isFindBuyId = true 
                  }
                  if (sellOrderId == orders[i].Id) {
                      isFindSellId = true 
                  }               
              }
              if (!isFindSellId && !isFindBuyId) {    // both buy order and sell order are detected to be executed 
                  cancelAll()
                  break
              } else if (!isFindBuyId) {   // a buy order execution is detected 
                  Log("buy order executed")
                  cancelAll()
                  break
              } else if (!isFindSellId) {  // a sell order execution is detected 
                  Log("sell order executed")
                  cancelAll()
                  break
              }
              LogStatus(_D())
              Sleep(3000)
          }
          Sleep(500)
      }
    

Toàn bộ logic và thiết kế được giải thích hoàn toàn sau đó.

Kiểm tra hậu quả

Hãy để chiến lược vượt qua báo giá thị trường vào ngày 19 tháng 5 năm 2021.

img

img

Như chúng ta có thể thấy, chiến lược tương tự như chiến lược Martingale vẫn có một số rủi ro.

Bot thử nghiệm có thể sử dụng OKEX V5 mô phỏng bot để chạy

img

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

Chiến lược chủ yếu được sử dụng để nghiên cứu, vì vậy không vận hành chiến lược trong một bot thực sự!


Thêm nữa