Использование функции __Thread в дизайне JavaScript-политики

Автор:Маленькие мечты, Создано: 2023-07-04 16:35:42, Обновлено: 2023-09-18 19:32:51

img

Использование функции __Thread в дизайне JavaScript-политики

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

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

1, простой параллельный дизайн

Если мы хотим, чтобы главный строк стратегии работал одновременно с выполнением одной из подстрок для выполнения настройки, которую мы написали, мы можем использовать дизайн, похожий на следующий код.GetTickerAsync(), чтобы написать конкретную функцию этой функции. Эта функция выполняет мертвый цикл, в которомwhileAPI-интерфейс FMZ, постоянно вызывающий в цикле:GetTicker()Посмотрите, что происходит в этом районе.

А затем использовать.__threadSetData(0, "ticker", t)Эта фраза записывается в основную строку с данными, называемымиticker, значение данногоtТо естьGetTicker()В результате, мы получаем обратное значение.

__threadSetData(0, "ticker", t)

После того, как мы разработаем настраиваемые функции, которые выполняются одновременно, мы можем написатьmain()И мы можем сделать это, если мы используем код в функции.main()Для начала мы используем:

__Thread(GetTickerAsync, 0)   // GetTickerAsync为需要并发执行的自定义函数,0为这个传入GetTickerAsync函数的参数

Мы создаем параллельную нить, которая начинает выполнятьGetTickerAsync()Функция. Далее.main()Функция начинает выполнять свою работу.whileЦикл, получающий в циклеGetTickerAsync()Функция обновляет данные и печатает:

var t = __threadGetData(0, "ticker")
Log(t)

Полный пример кода:

function GetTickerAsync(index) {
    while (true) {
        var t = exchanges[index].GetTicker()
        __threadSetData(0, "ticker", t)
        Sleep(500)
    }
}

function main() {
    __Thread(GetTickerAsync, 0)

    while(true) {
        var t = __threadGetData(0, "ticker")
        Log(t)
        Sleep(1000)
    }
}

Проверка на диске:

img

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

2, совместное проектирование

Можно спроектировать одну функцию, чтобы создать 10 потоков одновременно, каждый из которых выполняет одну подчиненную операционную функцию.main()И мы можем сделать это.whileВ этом случае, если вы хотите, чтобы ваш сайт был доступен для пользователей, вы можете использовать его для поиска информации о ваших пользователях.placeMultipleOrdersИ мы должны сделать это, чтобы вызвать эту функцию.testPlaceMultipleOrders()

if (cmd == "placeMultipleOrders") {
    // ...
}

Добавить интерактивный дизайн политики на странице редактирования политики, установить кнопку и команду: placeMultipleOrders

img

Полный пример кода:

function placeOrder(exIndex, type, price, amount) {
    var id = null 
    if (type == "Buy") {
        id = exchanges[exIndex].Buy(price, amount)
    } else if (type == "Sell") {
        id = exchanges[exIndex].Sell(price, amount)
    } else {
        throw "type error! type:" + type
    }
}

function testPlaceMultipleOrders(index, beginPrice, endPrice, step, type, amount) {
    Log("beginPrice:", beginPrice, ", endPrice:", endPrice, ", step:", step, ", type:", type, ", amount:", amount)
    var tids = []
    for (var p = beginPrice; p <= endPrice; p += step) {
        var tid = __Thread(placeOrder, index, type, p, amount)
        tids.push(tid)
        Sleep(10)
    }
    Sleep(1000)
    for (var i = 0; i < tids.length; i++) {
        __threadTerminate(tids[i])
    }
}

function main() {
    while(true) {
        LogStatus(_D())
        var cmd = GetCommand()
        if (cmd) {
            if (cmd == "placeMultipleOrders") {
                var t = _C(exchange.GetTicker)
                var beginPrice = t.Last * 0.8
                var endPrice = t.Last * 0.9
                var step = t.Last * 0.01
                testPlaceMultipleOrders(0, beginPrice, endPrice, step, "Buy", 0.01)
                var orders = exchange.GetOrders()
                for (var i = 0; i < orders.length; i++) {
                    Log(orders[i])
                }
            }
        }
        Sleep(1000)
    }
}
  • Тестирование с использованием подвешенного списка, с наращиванием от 80% до 90% от текущей цены, с использованием дискового средного тестирования, нажатие интерактивной кнопки запускает тестовый список:

    img

  • После нажатия кнопки "PlaceMultipleOrders" вы получаете сообщение:

    img

  • В журнале стратегии отображаются следующие действия:

    img

3, Создание соединения WebSocket в одновременном выполнении функций

Это требование было предъявлено пользователем FMZ, который хотел бы иметь простой пример демонстрации использования в параллельных потоках.Веб-сокетМы создали систему, которая позволяет нам подключаться и проектировать, как передавать данные на основные провода.main()Функция.

На самом деле это очень просто, и создание параллельных строк в этом примере почти то же самое, что и в предыдущем.__threadPeekMessage()Функции и__threadPostMessage()Функция. В качестве примера вызова интерфейса WebSocket API на бирже Bitcoin мы также должны обратить внимание на действие закрытия соединения WebSocket в дизайне. В следующем примере также показано, как дать уведомление о том, что одновременная нить должна быть остановлена.

Полный пример кода:

var tid = null 

function createWS() {
    // wss://stream.binance.com:9443/ws/<streamName> , <symbol>@ticker
    
    var stream = "wss://stream.binance.com:9443/ws/btcusdt@ticker"    
    var ws = Dial(stream)
    Log("创建WS连接:", stream)
    
    while (true) {
        var data = ws.read()
        if (data) {            
            __threadPostMessage(0, data)
        }
        Log("接收到WS链接推送的数据,data:", data)
        
        // __threadPeekMessage 超时参数设置-1,不阻塞
        var msg = __threadPeekMessage(-1)
        if (msg) {
            if (msg == "stop") {
                Log("并发线程Id:", __threadId(), "接收到stop指令")
                break
            }
        }
    }

    Log("并发线程执行完毕,关闭ws连接")
    ws.close()
}

function main() {
    tid = __Thread(createWS)
    Log("创建并发线程,线程Id:", tid)

    while(true) {
        // __threadPeekMessage 的超时参数设置为0,阻塞等待数据
        var data = __threadPeekMessage(0)
        Log("接收到并发线程", ", Id:", tid, ", 发送的数据,data:", data, "#FF0000")
        
        var tbl = {
            type : "table", 
            title : "<symbol>@ticker频道推送消息",
            cols : ["事件类型", "事件时间", "交易对", "24小时价格变化", "24小时价格变化百分比", "平均价格", "最新成交价格", "24小时内成交量", "24小时内成交额"],
            rows : []
        }

        try {
            data = JSON.parse(data)
            tbl.rows.push([data.e, _D(data.E), data.s, data.p, data.P, data.w, data.c, data.v, data.q])
        } catch (e) {
            Log("e.name:", e.name, "e.stack:", e.stack, "e.message:", e.message)
        }
        LogStatus(_D(), "\n`" + JSON.stringify(tbl) + "`")
    }
}

function onexit() {
    Log("扫尾函数,向Id为", tid, "的并发线程发送stop指令")
    __threadPostMessage(tid, "stop")
    Log("等待Id为", tid, "的并发线程停止")
    __threadJoin(tid)
    Log("扫尾函数执行完毕")
}

Проверка на диске:

img

Вы можете видетьmain()Функция непрерывно получает трафикные данные, полученные от соединения WebSocket, созданного одновременно с проводами.

При остановке реального диска политика запускает функцию стереотипа:

img


Связанные

Больше

Спарта играет в количественном режимеИ последний пример, если у вас много ws-потоков, и вы подписаны на несколько тем, то что лучше для общения между потоками, как получить/установить или посмотреть/положить?

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

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