Дизайн синхронной системы управления заказами на базе FMZ (1)

Автор:Маленькие мечты, Создано: 2022-02-14 19:46:30, Обновлено: 2023-09-15 20:44:11

img

Дизайн синхронной системы управления заказами на базе FMZ (1)

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

Сегодня мы попробуем немного иной дизайн, основанный на мощном расширенном API-интерфейсе для квантовой торговой платформы FMZ, и мы разработаем синхронизированную систему управления заказами.

Идеи дизайна

В первую очередь, нам нужны хорошие рекомендации, нужды.

  • 1, Исполнитель синхронной стратегии на реальном рынке должен иметь API KEY на счету ссылки, API KEY на счету с синхронным счетом. Проблема с использованием сценария заключается в следующем: вполне нормально, что другие учетные записи на бирже следуют за своим; но это может быть проблематично для ссылочных счетов и синхронных счетов, не имеющих одного владельца; владельцы синхронных счетов иногда не хотят предоставлять API KEY для своих учетных записей на бирже по соображениям безопасности; но как синхронизировать транзакции без API KEY?

    Решение: Используя расширенный API-интерфейс FMZ, владельцам синхронизированных учетных записей (подписчикам) достаточно зарегистрироваться на КТП FMZ, а затем запустить одну из стратегий (в системе, разработанной для данной статьи):订单同步管理系统(Synchronous Server)Политика диска); затем можно предоставить FMZ расширение API KEY (примечание, не API KEY для учетных записей биржи) и синхронный сервер диска для владельцев ссылочных учетных записей. В системе, разработанной для использования в данной статье, имеется реферальный диск владельца аккаунта (участника).订单同步管理系统类库(Single Server)В случае, если вы не хотите, чтобы ваш аккаунт был закрыт, вы должны выслать сигнал, и ваш аккаунт будет автоматически закрыт.

  • 2, многие разработчики имеют более совершенные стратегии, которые не могут использовать два описанных выше просроченных ордера, держать синхронизированные стратегии; потому что это требует совмещения их с этими синхронизированными стратегиями, которые могут потребовать больших изменений и усилий. Есть ли хороший способ, чтобы некоторые из своих устоявшихся стратегий были напрямую модернизированы для синхронизации заказов? Решение: Можно создать заказную синхронную библиотеку шаблонов (в системе, разработанной в данной статье)订单同步管理系统类库(Single Server)Политика), чтобы владелец ссылочного аккаунта (ссылочный пользователь) напрямую встраивал эту библиотеку шаблонов в свою политику для реализации функций синхронизации заказов, хранения.

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

Таким образом, система состоит из двух частей: 1, Классификация систем синхронного управления заказами (Single Server) 2, Система синхронного управления заказами (Synchronous Server)

Если у вас есть определенные потребности, начните их разрабатывать.

Дизайн 1: Классификация систем синхронного управления заказами (Single Server)

Обратите внимание, что это не стратегия. Это шаблонная библиотека FMZ. Концепция библиотеки шаблонов может быть поискана в документации FMZ API.

Код класса шаблона:

// 全局变量
var keyName_label = "label"
var keyName_robotId = "robotId"
var keyName_extendAccessKey = "extendAccessKey"
var keyName_extendSecretKey = "extendSecretKey"
var fmzExtendApis = parseConfigs([config1, config2, config3, config4, config5])
var mapInitRefPosAmount = {}

function parseConfigs(configs) {
    var arr = []
    _.each(configs, function(config) {
        if (config == "") {
            return 
        }
        var strArr = config.split(",")
        if (strArr.length != 4) {
            throw "configs error!"
        }
        var obj = {}
        obj[keyName_label] = strArr[0]
        obj[keyName_robotId] = strArr[1]
        obj[keyName_extendAccessKey] = strArr[2]
        obj[keyName_extendSecretKey] = strArr[3]
        arr.push(obj)
    })
    return arr 
}

function getPosAmount(pos, ct) {
    var longPosAmount = 0
    var shortPosAmount = 0
    _.each(pos, function(ele) {
        if (ele.ContractType == ct && ele.Type == PD_LONG) {
            longPosAmount = ele.Amount
        } else if (ele.ContractType == ct && ele.Type == PD_SHORT) {
            shortPosAmount = ele.Amount
        }
    })
    var timestamp = new Date().getTime()
    return {ts: timestamp, long: longPosAmount, short: shortPosAmount}
}

function sendCommandRobotMsg (robotId, accessKey, secretKey, msg) {
    // https://www.fmz.com/api/v1?access_key=xxx&secret_key=yyyy&method=CommandRobot&args=[186515,"ok12345"]
    var url = "https://www.fmz.com/api/v1?access_key=" + accessKey + "&secret_key=" + secretKey + "&method=CommandRobot&args=[" + robotId + ',"' + msg + '"]'
    Log(url)
    var ret = HttpQuery(url)
    return ret 
}

function follow(nowPosAmount, symbol, ct, type, delta) {
    var msg = ""
    var nowAmount = type == PD_LONG ? nowPosAmount.long : nowPosAmount.short
    if (delta > 0) {
        // 开仓
        var tradeDirection = type == PD_LONG ? "buy" : "sell"
        // 发送信号
        msg = symbol + "," + ct + "," + tradeDirection + "," + Math.abs(delta)        
    } else if (delta < 0) {
        // 平仓
        var tradeDirection = type == PD_LONG ? "closebuy" : "closesell"
        if (nowAmount <= 0) {
            Log("未检测到持仓")
            return 
        }
        // 发送信号
        msg = symbol + "," + ct + "," + tradeDirection + "," + Math.abs(delta)
    } else {
        throw "错误"
    }
    if (msg) {
        _.each(fmzExtendApis, function(extendApiConfig) {
            var ret = sendCommandRobotMsg(extendApiConfig[keyName_robotId], extendApiConfig[keyName_extendAccessKey], extendApiConfig[keyName_extendSecretKey], msg)
            Log("调用CommandRobot接口,", "label:", extendApiConfig[keyName_label], ", msg:", msg, ", ret:", ret)
            Sleep(1000)
        })
    }
}

$.PosMonitor = function(exIndex, symbol, ct) {    
    var ts = new Date().getTime()
    var ex = exchanges[exIndex]
    // 判断ex类型
    var exName = ex.GetName()
    var isFutures = exName.includes("Futures_")
    var exType = isFutures ? "futures" : "spot"
    if (!isFutures) {
        throw "仅支持期货跟单"
    }

    if (exType == "futures") {
        // 缓存 symbol ct
        var buffSymbol = ex.GetCurrency()
        var buffCt = ex.GetContractType()

        // 切换到对应的交易对、合约代码
        ex.SetCurrency(symbol)
        if (!ex.SetContractType(ct)) {
            throw "SetContractType failed"
        }

        // 监控持仓
        var keyInitRefPosAmount = "refPos-" + exIndex + "-" + symbol + "-" + ct    // refPos-exIndex-symbol-contractType
        var initRefPosAmount = mapInitRefPosAmount[keyInitRefPosAmount]
        if (!initRefPosAmount) {
            // 没有初始化数据,初始化          
            mapInitRefPosAmount[keyInitRefPosAmount] = getPosAmount(_C(ex.GetPosition), ct)
            initRefPosAmount = mapInitRefPosAmount[keyInitRefPosAmount]
        }

        // 监控
        var nowRefPosAmount = getPosAmount(_C(ex.GetPosition), ct)
        // 计算仓位变动
        var longPosDelta = nowRefPosAmount.long - initRefPosAmount.long
        var shortPosDelta = nowRefPosAmount.short - initRefPosAmount.short

        // 检测变动
        if (!(longPosDelta == 0 && shortPosDelta == 0)) {
            // 执行多头动作
            if (longPosDelta != 0) {
                Log(ex.GetName(), ex.GetLabel(), symbol, ct, "执行多头跟单,变动量:", longPosDelta)
                follow(nowRefPosAmount, symbol, ct, PD_LONG, longPosDelta)
            }
            // 执行空头动作
            if (shortPosDelta != 0) {
                Log(ex.GetName(), ex.GetLabel(), symbol, ct, "执行空头跟单,变动量:", shortPosDelta)
                follow(nowRefPosAmount, symbol, ct, PD_SHORT, shortPosDelta)
            }

            // 执行跟单操作后,更新
            mapInitRefPosAmount[keyInitRefPosAmount] = nowRefPosAmount
        }

        // 恢复 symbol ct
        ex.SetCurrency(buffSymbol)
        ex.SetContractType(buffCt)
    } else if (exType == "spot") {
        // 现货
    }
}

$.getTbl = function() {
    var tbl = {
        "type" : "table", 
        "title" : "同步数据", 
        "cols" : [], 
        "rows" : []
    }
    // 构造表头
    tbl.cols.push("监控账户:refPos-exIndex-symbol-contractType")
    tbl.cols.push(`监控持仓:{"时间戳":xxx,"多头持仓量":xxx,"空头持仓量":xxx}`)
    _.each(fmzExtendApis, function(extendApiData, index) {
        tbl.cols.push(keyName_robotId + "-" + index)
    })
    
    // 写入数据
    _.each(mapInitRefPosAmount, function(initRefPosAmount, key) {
        var arr = [key, JSON.stringify(initRefPosAmount)]
        _.each(fmzExtendApis, function(extendApiData) {
            arr.push(extendApiData[keyName_robotId])
        })
        tbl.rows.push(arr)
    })

    return tbl
}

// 引用该模板类库的策略调用范例
function main() {
    // 清除所有日志
    LogReset(1)

    // 切换到OKEX 模拟盘测试
    exchanges[0].IO("simulate", true)

    // 设置合约
    exchanges[0].SetCurrency("ETH_USDT")
    exchanges[0].SetContractType("swap")

    // 定时交易时间间隔
    var tradeInterval = 1000 * 60 * 3        // 三分钟交易一次,用于观察跟单信号
    var lastTradeTS = new Date().getTime()
    
    while (true) {
        // 策略其它逻辑...

        // 用于测试的模拟交易触发
        var ts = new Date().getTime()
        if (ts - lastTradeTS > tradeInterval) {
            Log("模拟带单策略发生交易,持仓变化", "#FF0000")
            exchanges[0].SetDirection("buy")
            exchanges[0].Buy(-1, 1)
            lastTradeTS = ts
        }

        // 使用模板的接口函数
        $.PosMonitor(0, "ETH_USDT", "swap")    // 可以设置多个监控,监控带单策略上的不同的exchange对象  
        var tbl = $.getTbl()
        
        // 显示状态栏
        LogStatus(_D(), "\n" + "`" + JSON.stringify(tbl) + "`")
        Sleep(1000)
    }
}

Эта библиотека имеет две функциональные функции. Когда одна из программных стратегий торговли на платформе FMZ ссылается на订单同步管理系统类库(Single Server)После библиотеки классов шаблонов. Эта стратегия может использоваться с помощью следующей функции.

  • $.PosMonitor Функция выполняет функцию мониторинга изменения состояния объекта биржи в стратегии, а затем отправляет торговые сигналы на реальный диск, установленный в параметрах шаблона: Order Synchronization Management System (Single Server).

  • $$.getTbl Он возвращает синхронизированные данные от мониторинга.

Пример использования: Классификация систем синхронного управления заказами ("Single Server")mainФункция:

// 引用该模板类库的策略调用范例
function main() {
    // 清除所有日志
    LogReset(1)

    // 切换到OKEX 模拟盘测试
    exchanges[0].IO("simulate", true)

    // 设置合约
    exchanges[0].SetCurrency("ETH_USDT")
    exchanges[0].SetContractType("swap")

    // 定时交易时间间隔
    var tradeInterval = 1000 * 60 * 3        // 三分钟交易一次,用于观察跟单信号
    var lastTradeTS = new Date().getTime()
    
    while (true) {
        // 策略其它逻辑...

        // 用于测试的模拟交易触发
        var ts = new Date().getTime()
        if (ts - lastTradeTS > tradeInterval) {
            Log("模拟带单策略发生交易,持仓变化", "#FF0000")
            exchanges[0].SetDirection("buy")
            exchanges[0].Buy(-1, 1)
            lastTradeTS = ts
        }

        // 使用模板的接口函数
        $.PosMonitor(0, "ETH_USDT", "swap")    // 可以设置多个监控,监控带单策略上的不同的exchange对象  
        var tbl = $.getTbl()
        
        // 显示状态栏
        LogStatus(_D(), "\n" + "`" + JSON.stringify(tbl) + "`")
        Sleep(1000)
    }
}

Сам шаблонный кластер также может создавать политические диски, которые обычно используются для тестирования кластеров шаблонов.mainФункция - это ваша стратегия.mainФункция.

Испытательный код написан для тестирования с использованием диска OKEX, требует настройки на FMZ API KEY диска OKEX в качестве ссылки на учетную запись (связь), начинает переключаться на диск в основной функции. Затем пара транзакций устанавливается на ETH_USDT, контракт устанавливается на постоянный (свап). Затем входит в цикл while.$.PosMonitor(0, "ETH_USDT", "swap")Первый параметр, который вызывается этой функцией, передается в 0, что означает, что обменный объект, контролирующий обменную пару ETH_USDT, является обменным контрактом.$.getTbl()Получить информацию о графике, использоватьLogStatus(_D(), "\n" + "`" + JSON.stringify(tbl) + "`")Укажите данные графика на панели состояния.

Так что, вы видите, если вы используете это в какой-то стратегии, которая ссылается на шаблон,$.PosMonitor(0, "ETH_USDT", "swap")В этом случае можно сделать так, чтобы стратегия имела функцию мониторинга хранения определенной разновидности, изменения хранения для продвижения сообщения.

Расскажите, пожалуйста, до того, как мы проверим это.订单同步管理系统类库(Single Server)Параметры разработки стратегии: Мы только что говорили о том, как использовать интерфейсную функцию шаблона, чтобы улучшить какую-то политику с ленточной функцией. Вопрос о том, кому это отправить, решается самим автором.订单同步管理系统类库(Single Server)Параметры настраиваются.

img

Вы можете видеть, что параметры имеют 5 параметров, поддерживающих до 5 push (необходимо добавить самостоятельно расширяемые), параметры по умолчанию являются пустыми строками, то есть не обрабатываются.

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

  • Идентификатор робота Идентификатор диска, созданный владельцем синхронизированной учетной записи订单同步管理系统(Synchronous Server)Идентификатор реального диска.

  • accessKey AccessKey для расширения API FMZ

  • Секретный ключ Секретный ключ для расширения API FMZ

В следующий раз мы проведем простые тесты.

Заказы синхронной системы управления классами (Single Server) работают:

img

Диск синхронной системы управления заказами (Synchronous Server) получил сигнал: Мы пока не закончили разработку синхронного сервера, но сначала мы реализуем его с помощью простого кода, не делая транзакций, просто печатая сигналы:

Временный код системы синхронного управления заказами (Synchronous Server):

function main() {
    LogReset(1)
    while (true) {
        var cmd = GetCommand()
        if (cmd) {
            // cmd: ETH_USDT,swap,buy,1
            Log("cmd: ", cmd)
        }
        Sleep(1000)
    }
}

img

На диске владельца синхронной учетной записи появилась запись:ETH_USDT,swap,buy,1Я не знаю. Таким образом, следующий шаг - это автоматическое отслеживание своих сделок в зависимости от пары, кода контракта, направления и количества сделок в информации.

В настоящее время订单同步管理系统(Synchronous Server)Это временный код, и мы продолжим обсуждать его дизайн в следующем номере.


Связанные

Больше

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

Мингси1005Учебное пособие, показывает ошибку в настройке

Аль-АльКакие параметры нужно изменить в обратном списке

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

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

Маленькие мечтыВы можете посмотреть на статью, информацию о конфигурации: теги, ID реального диска, accesskey, secretkey.

Мингси1005Ошибка configs error!, в базе данных системы синхронного управления заказами (Single Server) заполняется диск заказчика и 2 КЕЙ, а затем в базе данных упоминается база данных системы синхронного управления заказами (Single Server), возвращается ошибка, ошибка configs error!

Мингси1005Ошибка в конфигурации!

Маленькие мечтыПосмотрите, какие именно ошибки были сообщены.

Маленькие мечтыНеобходимо изменить стратегию.

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