Система принятия решений и/или Нечеткая логика(FuzzyLogic)

Страницы: Пред. 1 ... 5 6 7 8 9
RSS
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
 
Цитата
Nikolay написал:
А значит выполняться она может тоже только через вызовы в основном цикле mian. И тоже частота вызовов регулируется задержкой цикла main.Собственно ваш любимый hacktrade так и работает.
Вы не поняли сути hacktrade, как раз он как пример такой асинхронности.

1. При первом в ходе создается корутина и мы работаем в ее цикле, а у нее никаких задержек, (кроме накладных), в ней идет вся торговая логика расчеты, вычисление и так далее. Останавливаем исполнение когда выполнены условия на отправку заявки и заявка отправлена (выполняется yield).

2. Структурно код стал на выполнение в цикле маин (с задержками sleep)  функционально идет работа с заявкой. Где тут последовательность?
Самая что не на есть асинхронность.

Выполнение кода структурно разделено на две составляющие:
А) Поиск условия выполнения заявки (в цикле корутины);
Б) Не посредственное исполнение заявки (взаимодействие с апи квик - в цикле маин).  
 
Нашел. Вот когда то я сохранял для себя понимание. Что то с родни Вашему подходу.

Lua предоставляет "лёгкие потоки" — coroutines (сопрограммы). Это кооперативные задачи, которые работают внутри одного потока исполнения, но могут приостанавливать и возобновлять выполнение, передавая управление.

--Ключевая идея лёгкого потока (coroutine)

local is_run = true
local threads = {}

function worker(name, delay)
   local i = 0
   while is_run do
       i = i + 1
       message(string.format("[%s] шаг %d", name, i))
       for _ = 1, delay do coroutine.yield() end
   end
end

function main()
   threads[1] = coroutine.create(function() worker("A", 2) end)
   threads[2] = coroutine.create(function() worker("B", 5) end)

   while is_run do
       for _, co in ipairs(threads) do
           if coroutine.status(co) ~= "dead" then
               coroutine.resume(co)
           end
       end
       sleep(200)
   end
end

function OnStop() is_run = false end

Это — мини-диспетчер потоков на чистом Lua.
Каждый "поток" (worker) — корутина с собственным ритмом, а цикл в main() играет роль планировщика.

* Корутину можно считать лёгким потоком Lua — она живёт, имеет собственный контекст и исполняется пошагово.

* А main() — просто планировщик, который возобновляет корутины.
 
Цитата
VPM написал:
Вы не поняли сути hacktrade, как раз он как пример такой асинхронности.
Я на него смотрел еще в году так 16-ом. Как он работает предельно понятно. Подход далеко не новый, да и с чего ему быть новым если корутины в Lua появились в далеком 5.0 от 2003

Цитата
А main() — просто планировщик, который возобновляет корутины
Правильно. А значит с тем же успехом можно планировать и вызовы процедур, созданных иначе. Какая разница что вызывать - корутину или процедуру. Вызывается из одного и того же места, с тем же ритмом и скоростью. Отличия только в обертке одних в корутины, а другие нет.
 
Да но есть ключевое отличие. yield() - приостанавливает только задачу, не весь скрипт как sleep.

--- Ключевая идея лёгкого потока (coroutine - кооперативная задача). Этот код создаёт лёгкий поток (фактически, сопрограмму), который выполняется по шагам, каждый шаг — между yield() и resume().
Код
local co = coroutine.create(function()
    for i = 1, 5 do
        print("Работаю...", i)
        coroutine.yield() -- приостанавливаем "поток"
    end
end)

while coroutine.status(co) ~= "dead" do
    coroutine.resume(co) -- возобновляем
    sleep(100)
end
Код
--- Пример «лёгкого фонового потока» в QUIK

local is_run = true

-- "Лёгкий поток" для фоновой задачи
local function background_task()
    local count = 0
    while is_run do
        count = count + 1
        message("Фоновая задача: шаг " .. count)
        coroutine.yield()  -- уступаем управление
    end
end

function main()
    local co = coroutine.create(background_task)
    message("Запуск фонового лёгкого потока...")
    while is_run do
        coroutine.resume(co)  -- возобновляем поток
        sleep(1000)           -- имитация "асинхронного" поведения
    end
end

function OnStop()
    is_run = false
    message("Остановка фонового потока.")
end


-- * Корутину можно считать лёгким потоком Lua — она живёт, имеет собственный контекст и исполняется пошагово.
 
 
Тогда давайте еще раз, на пальцах. Берем этот пример и "брюки превращаются":

local is_run = true
-- "Лёгкий поток" для фоновой задачи
local function create_task()
   local count = 0
   return function()
       count = count + 1
       message("Фоновая задача: шаг " .. count)
       return  -- уступаем управление
   end
end
function main()
   local co = create_task()
   message("Запуск фонового лёгкого потока...")
   while is_run do
       co()                  -- возобновляем поток
       sleep(1000)           -- имитация "асинхронного" поведения
   end
end
function OnStop()
   is_run = false
   message("Остановка фонового потока.")
end



Как говорится - найдите десять отличий.
 
Отличие прежнее.

Вы в потоке маин вызываете псевдоним функции выше, после выполнения функции цикл  приостанавливается sleep(1000) .
В то время как в примере с корутиной  имеется свой легки поток без задержек, а   coroutine.yield()  -- уступаем управление (подвешивает задачу) не создавая ни каких задержек, но цикл то маин выполняется. И таких задач можно вешать сколько угодно, в то время как в Вашем варианте после каждой задачи задержка.
Код
-- "Лёгкий поток" для фоновой задачиlocal function background_task()
    local count = 0
    while is_run do
        count = count + 1
        message("Фоновая задача: шаг " .. count)
        coroutine.yield()  -- уступаем управление
    end
end
 
Нет такого. Я просто переделал Ваш пример. У Вас там есть задержка. Уберите, если хотите и не будет никаких задержек.
 
Цитата
VPM написал:
Отличие прежнее.

Вы в потоке маин вызываете псевдоним функции выше, после выполнения функции цикл  приостанавливается sleep(1000) .
В то время как в примере с корутиной  имеется свой легки поток без задержек, а   coroutine.yield()  -- уступаем управление (подвешивает задачу) не создавая ни каких задержек, но цикл то маин выполняется. И таких задач можно вешать сколько угодно, в то время как в Вашем варианте после каждой задачи задержка.
Код
   -- "Лёгкий поток" для фоновой задачиlocal function background_task() 
     local  count  =   0 
     while  is_run  do 
        count  =  count  +   1 
         message ( "Фоновая задача: шаг "   ..  count)
         coroutine.yield ()   -- уступаем управление 
     end 
 end   
У Вас тоже задержка в main() на 1 секунду, т.е. в общем потоке скрипта, будет точно также задерживаться. У Вас и у Nikolay абсолютно синхронно будут исполняться вызовы, только у него быстрее будет проходить сам вызов в десятки раз.
 
Ну хорошо вот другой пример:
Код
function main()
    threads[1] = coroutine.create(function() worker("A", 2) end)
    threads[2] = coroutine.create(function() worker("B", 5) end)

    while is_run do
        for _, co in ipairs(threads) do
            if coroutine.status(co) ~= "dead" then
                coroutine.resume(co)
            end
        end
        sleep(200)
    end
end
 
Подсобрался с мыслями. Можно некий итог подвести.

Различия двух подходов, про применение см. выше мнение не поменял.

1. Подход с замыканием.
Нет возможности приостанавливать сложные задачи на середине выполнения.
Сложно реализовать ожидание событий или таймеров внутри задачи без внешнего кода.
Каждая задача должна сама заботиться о том, как уступать управление (через sleep в основном цикле).

2. Подход с корутиной.
Внутри корутины можно писать сложные алгоритмы и «разбивать» их на шаги.
Более гибкая модель.
Можно приостанавливать задачу на любом шаге.
Можно легко комбинировать несколько фоновых задач в одном цикле.
Более похоже на настоящие асинхронные потоки.
Сложнее.
Немного больше накладных расходов на создание и управление корутиной (хотя для QUIK это не критично).
coroutine.yield() - приостанавливает выполнение задачи, позволяя основному циклу выполняться и управлять её запуском.

Пока разбирались на кидал лёгкий планировщик фоновых задач для QUIK. Всем пока хорошего кода.
 
Нет. Это все не так. Корутина точно также работает. Где в корутине yield, в процедуре return. Где коде coroutine.resume - просто вызов процедуры. Все с точностью до стоки кода. Никаких чудес.
Полная аналогия.
 
Цитата
Nikolay написал:
Полная аналогия.
  С довесочком:
 1. Программировать корутины сложнее.
 2.
Цитата
VPM написал:
1   1   29.10.2025   10:31:19   Скрипт запущен. Идёт фоновое измерение производительности...
2   1   29.10.2025   10:31:20   Фон: N=100000, coroutine=584.000 мс (c=100000), func=6.000 мс (f=100000), T1/T2=97.33
 По вашим же тестам накладные расходы на вызов корутин в 97.33 раз больше, чем на вызов функций (coroutine=584.000 мс , func=6.000 мс ). Чтобы для вас было наглядно, при всяком вызове корутины, прежде чем она начнет что-то делать, делается 97 пустых вызовов функций.
Страницы: Пред. 1 ... 5 6 7 8 9
Читают тему
Наверх