4
Подписаться
1271
Подписчики

Новички в количественной торговле в криптовалютных кругах, пожалуйста, ознакомьтесь с этим - Приближаемся к количественной торговле в криптовалютных кругах (VI)

Создано: 2021-06-04 10:08:48, Обновлено: 2024-12-04 21:14:15
comments   6
hits   2596

Новички в количественной торговле в криптовалютных кругах, пожалуйста, ознакомьтесь с этим - Приближаемся к количественной торговле в криптовалютных кругах (VI)

Новички в количественной торговле в криптовалютных кругах, пожалуйста, ознакомьтесь с этим - Приближаемся к количественной торговле в криптовалютных кругах (VI)

В предыдущей статье мы работали вместе над созданием простой стратегии сетки. В этой статье мы улучшим и расширим эту стратегию до многовариантной стратегии сетки точек и испытаем ее в реальном бою. Цель состоит не в том, чтобы найти «святой Грааль», а в том, чтобы исследовать различные проблемы и решения при разработке стратегий. В этой статье я расскажу о некоторых своих опытах в разработке этой стратегии. Содержание этой статьи немного сложное и требует определенных основ в программировании.

Проектирование мышления на основе стратегических потребностей

В этой статье, как и в предыдущей, по-прежнему обсуждается конструкция на основе Inventor Quantization (FMZ.COM).

  • Множество разновидностей Говоря прямо, я думаю, что эта стратегия сетки не толькоBTC_USDT, также может сделатьLTC_USDT/EOS_USDT/DOGE_USDT/ETC_USDT/ETH_USDT. В любом случае, для пар спотовой торговли все продукты, которыми вы хотите торговать, могут торговаться в сетке одновременно.

Эм~~Приятно иметь возможность охватить волатильный рынок множества разновидностей. Требования кажутся простыми, но при проектировании возникают проблемы.

    1. Сначала получите рыночную информацию о нескольких разновидностях. Это первая проблема, которую необходимо решить. Изучив документацию API биржи, я обнаружил, что большинство бирж предоставляют интерфейс агрегированной рыночной информации. Хорошо, используйте интерфейс агрегированных рыночных данных для получения данных.
    1. Вторая возникшая проблема – это активы на счете. Поскольку мы хотим реализовать многовариантную стратегию, нам необходимо рассмотреть возможность отдельного управления активами для каждой транзакции. И получить данные и записи по всем активам одновременно. Зачем нам нужно получать данные об активах счета? Нужно ли нам вести отдельные записи для каждой пары транзакций? Поскольку при размещении заказа вам необходимо оценить доступные активы, нужно ли вам получить их, прежде чем принимать решение? И вам нужно рассчитать доход. Вам также нужно сначала записать начальные данные по активам счета, а затем получить текущие данные по активам счета и сравнить их с начальными, чтобы рассчитать прибыль и убыток? К счастью, интерфейс счета активов биржи обычно возвращает данные активов всех валют. Нам нужно получить их только один раз, а затем обработать данные.
    1. Разработка параметров стратегии. Параметры дизайна нескольких сортов существенно отличаются от параметров дизайна одного сорта, поскольку, хотя торговая логика каждого сорта одинакова, параметры во время торговли могут отличаться. Например, в стратегии сетки вы можете захотеть торговать 0,01 BTC каждый раз при торговле парами BTC_USDT. Однако, если вы все еще используете этот параметр (торговля 0,01 монеты) при торговле DOGE_USDT, это, очевидно, нецелесообразно. Конечно, вы можете также обработайте его в соответствии с суммой USDT. Но проблемы все равно будут. А что если вы просто хотите торговать 1000U с BTC_USDT и 10U с DOGE_USDT? Спрос никогда не будет удовлетворен. Некоторые студенты могут задуматься над этим вопросом и затем сказать: «Я могу установить несколько групп параметров, чтобы отдельно контролировать параметры разных торговых пар». Это все еще не может гибко удовлетворить потребности. Сколько групп параметров следует задать? Задано три набора параметров. Что делать, если я хочу торговать 4 сортами? Можно ли изменить стратегию и добавить параметры… Поэтому при проектировании параметров многовариантной стратегии мы должны полностью учитывать спрос на дифференцированные параметры. Одним из решений является проектирование параметров как обычных строк или строк JSON. Например:
    ETHUSDT:100:0.002|LTCUSDT:20:0.1
    

    Знак «|» разделяет данные каждого сорта, что означаетETHUSDT:100:0.002Он контролирует торговую пару ETH_USDT.LTCUSDT:20:0.1Он контролирует торговую пару LTC_USDT. Знак «|» в середине служит разделителем. ETHUSDT:100:0.002, где ETHUSDT указывает торговую пару, которой вы хотите торговать, 100 — это шаг сетки, 0,002 — это количество монет ETH, торгуемых в каждой сетке, а знак «:» используется для разделения этих данных (конечно, эти правила параметров (устанавливается разработчиком стратегии). Вы можете разработать ее в соответствии со своими потребностями). Эти строки содержат информацию о параметрах каждого продукта, которым вы хотите торговать. Проанализируйте эти строки в стратегии и присвойте определенные значения переменным стратегии, чтобы контролировать логику торговли каждого продукта. Так как же его проанализировать? Давайте снова воспользуемся приведенным выше примером.

    function main() {
        var net = []  // 记录的网格参数,具体运行到网格交易逻辑时,使用这里面的数据
        var params = "ETHUSDT:100:0.002|LTCUSDT:20:0.1"
        var arrPair = params.split("|")
        _.each(arrPair, function(pair) {
            var arr = pair.split(":")
            var symbol = arr[0]              // 交易对名称
            var diff = parseFloat(arr[1])    // 网格间距
            var amount = parseFloat(arr[2])  // 网格下单量
            net.push({symbol : symbol, diff : diff, amount : amount})
        })
        Log("网格参数数据:", net)
    }
    

    Новички в количественной торговле в криптовалютных кругах, пожалуйста, ознакомьтесь с этим - Приближаемся к количественной торговле в криптовалютных кругах (VI)

    Вы можете видеть, что параметры анализируются таким образом. Конечно, вы также можете использовать строки JSON напрямую, что проще.

    function main() {        
        var params = '[{"symbol":"ETHUSDT","diff":100,"amount":0.002},{"symbol":"LTCUSDT","diff":20,"amount":0.1}]'
        var net = JSON.parse(params)  // 记录的网格参数,具体运行到网格交易逻辑时,使用这里面的数据        
        _.each(net, function(pair) {
            Log("交易对:", pair.symbol, pair)
        })
    }
    

    Новички в количественной торговле в криптовалютных кругах, пожалуйста, ознакомьтесь с этим - Приближаемся к количественной торговле в криптовалютных кругах (VI)

    1. Сохранение данных Также существует большая разница между стратегиями, которые можно применить на практике, и стратегиями обучения. Стратегия обучения в предыдущей статье — это лишь предварительный тест логики и дизайна стратегии. На практике есть еще вопросы, которые следует рассмотреть. Во время реальной торговли вы можете начинать и прекращать реальную торговлю. В это время все данные, полученные в ходе операции в реальном времени, будут утеряны. Так как же нам остановить реальный диск, а затем перезапустить его, чтобы он продолжил работу в предыдущем состоянии? Здесь необходимо сохранять ключевые данные во время работы в реальном времени, чтобы данные можно было считать и продолжить работу при перезапуске системы. Его можно использовать на платформе количественной торговли Inventor._G()Функция или использование функции работы с базой данныхDBExec()Подробную информацию можно найти в документации FMZ API.

    Например, мы проектируем функцию развертки, используя_G()Функция сохранения данных сетки.

    var net = null 
    function main() {  // 策略主函数
        // 首先读取储存的net
        net = _G("net")
    
    
        // ...
    }
    
    
    function onExit() {
        _G("net", net)
        Log("执行扫尾处理,保存数据", "#FF0000")
    }
    
    
    function onexit() {    // 平台系统定义的退出扫尾函数,在点击实盘停止时触发执行
        onExit()
    }
    
    
    function onerror() {   // 平台系统定义的异常退出函数,在程序发生异常时触发执行
        onExit()
    }
    
    1. Ограничения по точности количества заказа, точности цены заказа, минимального количества заказа, минимальной суммы заказа и т. д.

    Система бэктестинга не накладывает столь строгих ограничений на количество и точность ордеров, но в реальной торговле каждая биржа может иметь строгие стандарты на цену и количество ордеров, и эти стандарты для каждой торговой пары также очень строгие. Ограничения не одинаковый. Поэтому новички часто тестируют систему бэктеста и видят всевозможные проблемы при запуске транзакций на реальном рынке. Затем они даже не читают сообщение об ошибке и испытывают всевозможные безумные проблемы [собачья голова].

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

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

    1. Адаптация к различным биржам Почему этот вопрос поставлен в конце? Потому что решения проблем, о которых мы говорили выше, приведут к этой последней проблеме, поскольку наша стратегия планирует использовать агрегированный рыночный интерфейс, получать доступ к точности торговых пар на бирже и другим данным по адаптации, получать доступ к информации о счете и обрабатывать каждую торговую пару отдельно и т. д. . Эти решения будут Существуют огромные различия между биржами. Существуют различия в вызовах интерфейсов и различия в механизмах. Для спотовых бирж разница будет меньше, если эту стратегию сетки расширить до фьючерсной версии. Различия в механизмах различных обменов еще больше. Одним из решений является разработка библиотеки шаблонов FMZ. Напишите и спроектируйте эти дифференцированные реализации в библиотеке классов. Уменьшите связь между самой стратегией и биржей. Недостатком этого способа является необходимость написания библиотеки шаблонов и ее реализации для каждого обмена в этом шаблоне.

Разработать библиотеку шаблонов

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

Мы можем разработать эту библиотеку шаблонных классов следующим образом (некоторые коды опущены):

function createBaseEx(e, funcConfigure) {
    var self = {}
    self.e = e 
    
    self.funcConfigure = funcConfigure
    self.name = e.GetName()
    self.type = self.name.includes("Futures_") ? "Futures" : "Spot"
    self.label = e.GetLabel()
    
    // 需要实现的接口
    self.interfaceGetTickers = null   // 创建异步获取聚合行情数据线程的函数
    self.interfaceGetAcc = null       // 创建异步获取账户数据线程的函数
    self.interfaceGetPos = null       // 获取持仓
    self.interfaceTrade = null        // 创建并发下单
    self.waitTickers = null           // 等待并发行情数据 
    self.waitAcc = null               // 等待账户并发数据
    self.waitTrade = null             // 等待下单并发数据
    self.calcAmount = null            // 根据交易对精度等数据计算下单量
    self.init = null                  // 初始化工作,获取精度等数据
    
    // 执行配置函数,给对象配置
    funcConfigure(self)

    // 检测configList约定的接口是否都实现
    _.each(configList, function(funcName) {
        if (!self[funcName]) {
            throw "接口" + funcName + "未实现"
        }
    })
    
    return self
}

$.createBaseEx = createBaseEx
$.getConfigureFunc = function(exName) {
    dicRegister = {
        "Futures_OKCoin" : funcConfigure_Futures_OKCoin,    // OK期货的实现
        "Huobi" : funcConfigure_Huobi,
        "Futures_Binance" : funcConfigure_Futures_Binance,
        "Binance" : funcConfigure_Binance,
        "WexApp" : funcConfigure_WexApp,                    // wexApp的实现
    }
    return dicRegister
}

В шаблоне напишите его для конкретной реализации обмена, например, возьмите в качестве примера диск моделирования FMZ WexApp:

function funcConfigure_WexApp(self) {
    var formatSymbol = function(originalSymbol) {
        // BTC_USDT
        var arr = originalSymbol.split("_")
        var baseCurrency = arr[0]
        var quoteCurrency = arr[1]
        return [originalSymbol, baseCurrency, quoteCurrency]
    }

    self.interfaceGetTickers = function interfaceGetTickers() {
        self.routineGetTicker = HttpQuery_Go("https://api.wex.app/api/v1/public/tickers")
    }

    self.waitTickers = function waitTickers() {
        var ret = []
        var arr = JSON.parse(self.routineGetTicker.wait()).data
        _.each(arr, function(ele) {
            ret.push({
                bid1: parseFloat(ele.buy), 
                bid1Vol: parseFloat(-1),
                ask1: parseFloat(ele.sell), 
                ask1Vol: parseFloat(-1),
                symbol: formatSymbol(ele.market)[0],
                type: "Spot", 
                originalSymbol: ele.market
            })
        })
        return ret 
    }

    self.interfaceGetAcc = function interfaceGetAcc(symbol, updateTS) {
        if (self.updateAccsTS != updateTS) {
            self.routineGetAcc = self.e.Go("GetAccount")
        }
    }

    self.waitAcc = function waitAcc(symbol, updateTS) {
        var arr = formatSymbol(symbol)
        var ret = null 
        if (self.updateAccsTS != updateTS) {
            ret = self.routineGetAcc.wait().Info
            self.bufferGetAccRet = ret 
        } else {
            ret = self.bufferGetAccRet
        }
        if (!ret) {
            return null 
        }        
        var acc = {symbol: symbol, Stocks: 0, FrozenStocks: 0, Balance: 0, FrozenBalance: 0, originalInfo: ret}
        _.each(ret.exchange, function(ele) {
            if (ele.currency == arr[1]) {
                // baseCurrency
                acc.Stocks = parseFloat(ele.free)
                acc.FrozenStocks = parseFloat(ele.frozen)
            } else if (ele.currency == arr[2]) {
                // quoteCurrency
                acc.Balance = parseFloat(ele.free)
                acc.FrozenBalance = parseFloat(ele.frozen)
            }
        })
        return acc
    }

    self.interfaceGetPos = function interfaceGetPos(symbol, price, initSpAcc, nowSpAcc) {
        var symbolInfo = self.getSymbolInfo(symbol)
        var sumInitStocks = initSpAcc.Stocks + initSpAcc.FrozenStocks
        var sumNowStocks = nowSpAcc.Stocks + nowSpAcc.FrozenStocks
        var diffStocks = _N(sumNowStocks - sumInitStocks, symbolInfo.amountPrecision)
        if (Math.abs(diffStocks) < symbolInfo.min / price) {
            return []
        }
        return [{symbol: symbol, amount: diffStocks, price: null, originalInfo: {}}]
    }

    self.interfaceTrade = function interfaceTrade(symbol, type, price, amount) {
        var tradeType = ""
        if (type == self.OPEN_LONG || type == self.COVER_SHORT) {
            tradeType = "bid"
        } else {
            tradeType = "ask"
        }
        var params = {
            "market": symbol,
            "side": tradeType,
            "amount": String(amount),
            "price" : String(-1),
            "type" : "market"
        }
        self.routineTrade = self.e.Go("IO", "api", "POST", "/api/v1/private/order", self.encodeParams(params))
    }

    self.waitTrade = function waitTrade() {
        return self.routineTrade.wait()
    }

    self.calcAmount = function calcAmount(symbol, type, price, amount) {
        // 获取交易对信息
        var symbolInfo = self.getSymbolInfo(symbol)
        if (!symbol) {
            throw symbol + ",交易对信息查询不到"
        }
        var tradeAmount = null 
        var equalAmount = null  // 记录币数
        if (type == self.OPEN_LONG || type == self.COVER_SHORT) {
            tradeAmount = _N(amount * price, parseFloat(symbolInfo.pricePrecision))
            // 检查最小交易量
            if (tradeAmount < symbolInfo.min) {
                Log(self.name, " tradeAmount:", tradeAmount, "小于", symbolInfo.min)
                return false 
            }
            equalAmount = tradeAmount / price
        } else {
            tradeAmount = _N(amount, parseFloat(symbolInfo.amountPrecision))
            // 检查最小交易量
            if (tradeAmount < symbolInfo.min / price) {
                Log(self.name, " tradeAmount:", tradeAmount, "小于", symbolInfo.min / price)
                return false 
            }
            equalAmount = tradeAmount
        }
        return [tradeAmount, equalAmount]
    }

    self.init = function init() {   // 自动处理精度等条件的函数
        var ret = JSON.parse(HttpQuery("https://api.wex.app/api/v1/public/markets"))
        _.each(ret.data, function(symbolInfo) {
            self.symbolsInfo.push({
                symbol: symbolInfo.pair,
                amountPrecision: parseFloat(symbolInfo.basePrecision),
                pricePrecision: parseFloat(symbolInfo.quotePrecision),
                multiplier: 1,
                min: parseFloat(symbolInfo.minQty),
                originalInfo: symbolInfo
            })
        })        
    }
}

Тогда использовать этот шаблон в стратегии просто:

function main() {
    var fuExName = exchange.GetName()
    var fuConfigureFunc = $.getConfigureFunc()[fuExName]
    var ex = $.createBaseEx(exchange, fuConfigureFunc)

    var arrTestSymbol = ["LTC_USDT", "ETH_USDT", "EOS_USDT"]
    var ts = new Date().getTime()
    
    // 测试获取行情
    ex.goGetTickers()
    var tickers = ex.getTickers()
    Log("tickers:", tickers)
    
    // 测试获取账户信息
    ex.goGetAcc(symbol, ts)
    
    _.each(arrTestSymbol, function(symbol) {        
        _.each(tickers, function(ticker) {
            if (symbol == ticker.originalSymbol) {
                // 打印行情数据
                Log(symbol, ticker)
            }
        })

        // 打印资产数据
        var acc = ex.getAcc(symbol, ts)
        Log("acc:", acc.symbol, acc)
    })
}

Стратегия реального рынка

Очень просто разработать и написать стратегию на основе приведенного выше шаблона. Вся стратегия состоит из более чем 300 строк, которые реализуют стратегию сетки спот-цифровой валюты с несколькими вариантами.

Новички в количественной торговле в криптовалютных кругах, пожалуйста, ознакомьтесь с этим - Приближаемся к количественной торговле в криптовалютных кругах (VI)

Новички в количественной торговле в криптовалютных кругах, пожалуйста, ознакомьтесь с этим - Приближаемся к количественной торговле в криптовалютных кругах (VI)

В настоящее время теряю деньгиT_T, исходный код пока не будет опубликован.

Вот несколько регистрационных кодов. Если вам интересно, вы можете попробовать это на wexApp:

购买地址: https://www.fmz.com/m/s/284507
注册码: 
adc7a2e0a2cfde542e3ace405d216731
f5db29d05f57266165ce92dc18fd0a30
1735dca92794943ddaf277828ee04c27
0281ea107935015491cda2b372a0997d
1d0d8ef1ea0ea1415eeee40404ed09cc

Нас было чуть более 200, и как только он начал работать, он столкнулся с большим односторонним рынком и медленно восстановился. Самое большое преимущество точечной сетки: «Вы можете хорошо выспаться!» Стабильность в порядке. Не трогал с 27 мая. Фьючерсную сетку пока не решаюсь пробовать.