Фьючерсный класс цифровой валюты

Автор:Маленькие мечты, Создано: 2021-07-02 14:35:34, Обновлено: 2023-09-21 21:09:56

img

Фьючерсный класс цифровой валюты

В последнее время в официальных группах FMZ обсуждается больше стратегий мартинского типа, а на платформе относительно контрактов на цифровые валюты не так много стратегий мартинского типа. Поэтому, воспользовавшись случаем, разработан простой стратегию мартинского типа цифровых валютных фьючерсов. Почему называют стратегию мартинского типа, поскольку потенциальный риск мартинской стратегии действительно не мал, и не разработан полностью в соответствии с стратегией мартинской; однако эта стратегия по-прежнему имеет немалый риск, и параметры стратегии мартинского типа, связанные с установкой параметров и процентов риска, не могут быть игнорированы.

В этой статье мы расскажем о том, как мы учимся на основе дизайна стратегии типа Мартина, и мы, как пользователи FMZ, больше думаем о стратегическом дизайне.

Доступ к общему праву

При разработке стратегии фьючерсов на цифровые валюты часто используются данные общий доход. Потому что для расчета дохода, особенно для расчета плавающего дохода, необходимы данные об общем доходе.exchange.GetAccount()Доступны доступные активы и замороженные активы. Фактически, большинство цифровых валютных фьючерсных бирж предоставляют данные об общем правоприменении, но FMZ не имеет единой упаковки этого свойства.

Так что мы получаем эти данные в зависимости от того, какую функцию мы разрабатываем на разных биржах:

// OKEX V5 获取总权益
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("获取账户总权益失败!")
            return null
        }
    }
    return totalEquity
}

// 币安期货
function getTotalEquity_Binance() {
    var totalEquity = null 
    var ret = exchange.GetAccount()
    if (ret) {
        try {
            totalEquity = parseFloat(ret.Info.totalWalletBalance)
        } catch(e) {
            Log("获取账户总权益失败!")
            return null
        }
    }
    return totalEquity
}

В кодеtotalEquityЭто то, что нам нужно. Затем мы пишем функцию, которая называет вход, и мы называем соответствующую функцию в соответствии с названием биржи.

function getTotalEquity() {
    var exName = exchange.GetName()
    if (exName == "Futures_OKCoin") {
        return getTotalEquity_OKEX_V5()
    } else if (exName == "Futures_Binance") {
        return getTotalEquity_Binance()
    } else {
        throw "不支持该交易所"
    }
}

Проектировать некоторые вспомогательные функции

Перед тем, как разработать основную функцию, основную логику. Мы также должны сделать некоторые приготовления, чтобы разработать некоторые вспомогательные функции.

  • Удалить все текущие объявления

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

    Эта функция, как мне кажется, хорошо знакома тем, кто часто читает примерный код стратегии на FMZ Strategy Square, и многие стратегии использовали аналогичную конструкцию.

  • Операция по заказу фьючерса

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

    Фьючерсные сделки имеют четыре направления: открытые длинные, открытые короткие, простые длинные и простые короткие, поэтому мы разработали четыре функции для подсчета, которые соответствуют этим операциям. Если рассматривать только подсчет, то есть несколько необходимых факторов: направление, цена подсчета, количество подсчета. Также мы разработали проект под названием:tradeФункции, которые обрабатывают方向(distance)下单价格(price)下单量(amount)Все эти действия были совершенно ясными. Вызовы к функциям openLong, openShort, coverLong и coverShort в конечном итоге выполняются с помощьюtradeФункция выполняет фактическую функцию, то есть размещает заказы на фьючерсных биржах в соответствии с установленным направлением, ценой и количеством.

Главная функция

Стратегическая идея проста: продать (сделайте) или купить (сделайте больше) за определенное расстояние ниже текущей цены на базовой линии. В то время как сделка завершается, все оставшиеся заказы аннулируются, а затем, в соответствии с ценой, находящейся в наличии, на определенном расстоянии вывешиваются новые ордера на баланс, после обновления заказы накладываются на текущую цену, но добавление заказов не удваивает количество заказов.

  • Первоначальная работа Поскольку мы хотим привязать заказы, нам нужны две глобальные переменные для записи ID заказа.

    var buyOrderId = null
    var sellOrderId = null
    

    Затем в параметрах интерфейса стратегии был разработан вариант использования OKEX_V5, поэтому в коде нужно сделать несколько обработок:

    var exName = exchange.GetName()    
    // 切换OKEX V5模拟盘
    if (isSimulate && exName == "Futures_OKCoin") {
        exchange.IO("simulate", true)
    }
    

    Также в параметрах интерфейса разработаны параметры для перестановки всей информации, поэтому в коде также должна быть соответствующая обработка:

    if (isReset) {
        _G(null)
        LogReset(1)
        LogProfitReset()
        LogVacuum()
        Log("重置所有数据", "#FF0000")
    }
    

    Мы бежим только по вечному договору, так что здесь написано, что мы умерли, и мы только настроились на вечный договор.

    exchange.SetContractType("swap")
    

    Затем мы также должны учитывать вопросы точности цены заказа, точности заказа, если точность не установлена правильно, то точность теряется в процессе стратегического расчета, много дробных цифр данных легко вызывает отказ интерфейса биржи при заказе.

    exchange.SetPrecision(pricePrecision, amountPrecision)
    Log("设置精度", pricePrecision, amountPrecision)
    

    Простые в разработке функции восстановления данных

    if (totalEq == -1 && !IsVirtual()) {
        var recoverTotalEq = _G("totalEq")
        if (!recoverTotalEq) {
            var currTotalEq = getTotalEquity()
            if (currTotalEq) {
                totalEq = currTotalEq
                _G("totalEq", currTotalEq)
            } else {
                throw "获取初始权益失败"
            }
        } else {
            totalEq = recoverTotalEq
        }
    }
    

    Параметры могут быть установлены, если вы хотите указать первоначальный общий аккаунт при выполнении политики.totalEqЕсли этот параметр установлен на -1, политика будет читать сохраненные данные общих прав и интересов, если нет сохраненных данных общих прав и интересов, то это первоначальные общие интересы, с учетом текущего чтения общих прав и интересов в качестве прогресса в работе стратегии, после чего увеличение общих прав и интересов означает потерю, а уменьшение общих прав и интересов - потерю. Если читается данные общих прав и интересов, использование данных продолжается.

  • Основная логика После того, как начальная работа была завершена, наконец, пришла часть основной логики стратегии, и для удобства объяснения я написал ее прямо в кодовых примечаниях.

      while (1) {                                  // 策略主要逻辑设计为一个死循环
          var ticker = _C(exchange.GetTicker)      // 首先读取当前行情信息,主要用到最新成交价
          var pos = _C(exchange.GetPosition)       // 读取当前持仓数据
          if (pos.length > 1) {                    // 判断持仓数据,由于这个策略的逻辑,是不太可能同时出现多空持仓的,所以发现同时出现多空持仓就抛出错误
              Log(pos)
              throw "同时有多空持仓"                  // 抛出错误,让策略停止
          }
          // 根据状态而定
          if (pos.length == 0) {                    // 根据持仓状态做出不同操作,pos.length == 0是当没有持仓时
              // 未持仓了,统计一次收益
              if (!IsVirtual()) {
                  var currTotalEq = getTotalEquity()
                  if (currTotalEq) {
                      LogProfit(currTotalEq - totalEq, "当前总权益:", currTotalEq)
                  }
              }
    
              buyOrderId = openLong(ticker.Last - targetProfit, amount)       // 挂开多仓的买单
              sellOrderId = openShort(ticker.Last + targetProfit, amount)     // 挂开空仓的卖单
          } else if (pos[0].Type == PD_LONG) {   // 有多头持仓,挂单位置、数量有所不同
              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) {   // 有空头持仓,挂单位置、数量有所不同
              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) {   // 如果有一边挂单失败就取消所有挂单,重来
              cancelAll()
              buyOrderId = null 
              sellOrderId = null
              continue
          } 
    
          while (1) {  // 挂单完成,开始监控订单
              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) {    // 检测到买卖单都成交了
                  cancelAll()
                  break
              } else if (!isFindBuyId) {   // 检测到买单成交
                  Log("买单成交")
                  cancelAll()
                  break
              } else if (!isFindSellId) {  // 检测到卖单成交
                  Log("卖单成交")
                  cancelAll()
                  break
              }
              LogStatus(_D())
              Sleep(3000)
          }
          Sleep(500)
      }
    

Все логика и дизайн были объяснены.

Проверка

Позвольте стратегии пережить 19 мая.

img

img

Как видно, тактика Мартина по-прежнему сопряжена с определенными рисками.

На диске можно играть в OKEX V5 Simulator

img

Политический адрес:https://www.fmz.com/strategy/294957

Строгие стратегии - это обучение, а золото и серебро - это осторожность ~!


Связанные

Больше

Лиза20231Дун Да, я хочу спросить тебя об этом. if (!isFindSellId &&!isFindBuyId) { // обнаруживает, что все заказы выполнены Если в процессе обнаружения заказа быстро поднимать и опускать разъем, а затем совершать покупку и продажу, может ли это вызвать ошибку?

Neo1898Второй вопрос, который возникает, это вопрос о том, что будет с контрактом, как он будет настроен - полный или частичный?

Neo1898Если договор был открыт, почему не был установлен двойной договор? Сколько раз продать?

Легкие облака.Спасибо, Джим, я наконец-то могу понять все, что я говорю. Затем я научился следить за списками, и написал двусторонний Мартин. Два дня, 580 строк. Спасибо, Джимми.

количество hk/upload/asset/1a9ebf427c4e2cbf1c327.png В обмен на false true?

Восемь цифр для мечты.Если

Восемь цифр для мечты.Совокупность прав собственников

нулевойНеобходимо ли остановить ущерб?

btcrobotМартин, пересчитай, нуль.

ВкйЕсли вы не понимаете, что n всегда равен 1.

ИвдалейЕсть ли у вас несколько открытых пространств или только один?

Маленькие мечтыНе бросает ошибки. Все равно отменяет все заказы, выходит из текущего цикла и продолжает логику.

Маленькие мечтыОбычно используйте полный склад.

Маленькие мечтыЛеверидж может быть определен на бирже в зависимости от собственных рисковых предпочтений.

Маленькие мечтыВсего 666!

Маленькие мечтыЕсли эта переменная называется isFindBuyId, то она не подходит. Она должна быть isNotFindBuyId.

Маленькие мечтыЭта стратегия не предназначена для остановки убытков.

Маленькие мечтыХа-ха, это место Мартина. В этой статье, в основном, речь идет о разработке учебной стратегии, не обращая особого внимания на ее результаты.

Маленькие мечтыЭтот N используется для последующих изменений, например, если мы думаем, что n раз расстояния вкладываются, то временно можно установить 1 ≠ 1.

Маленькие мечтыВ этом случае мы не будем делать никаких ошибок.