Система принятия решений и/или Нечеткая логика(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 пустых вызовов функций.
 
TGB,  Ну так это без тестов пoнятно конечно, чуть больше, т.к. стек корутины сохраняется.

Александр М, Да Вы правы, все так, по той же самой причине - стек корутины сохраняется! Данный пример с count, это простейшее действие, а корутину создаем для решения сложных, затратных задач, где нужно не зависимая от основного цикла обработка данных (фон). Так что довод не корректен, так как при решении сложной задачи будет нивелирован, а возможно и получен выигрыш (как в обсуждаемом примере с фреймворком).

Nikolay,  Ну как же нет? Смотрим на саму суть:

* Что делает замыкание? Создало локальную переменную.

* Что делает корутина? Создало независимы поток (без задержек и не блокирует QUIK с минимальной нагрузкой на CPU)

Преимущества очевидны:
1.  Не блокирует QUIK.
2.  Можно запустить много задач одновременно (мониторинг, логирование, анализ, обновление лимитов).
3.  Лёгкая расширяемая структура — можно добавлять задачи динамически.
4. Поддерживает интервалы выполнения (как cron).

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

По каким признакам это "лёгкий поток"?
1. Лёгкий по памяти. Корутине нужно всего несколько КБ стека.
2. Быстрый. Не создаёт системных потоков/контекстов.
3. Кооперативный. Поток сам решает, когда уступить управление.
4. Полный контекст исполнения. Сохраняются локальные переменные, состояние и позиция.
5. Пауза без блокировки QUIK. yield() приостанавливает только задачу, не весь скрипт.

* Каротину можно считать лёгким потоком Lua — она живёт, имеет собственный контекст и исполняется пошагово.
* А `main()` — просто планировщик, который возобновляет _ Ну так это без тестов пoнятно конечно, чуть больше, т.к. стек корутины сохраняется.

Резюме. В Lua корутины — это лёгкие, управляемые потоки. Они позволяют выполнять фоновую работу, не блокируя основной цикл QUIK. В QUIK это единственный безопасный способ организовать "многозадачность" без внешних библиотек.
 
Любая процедура, вызванная из main не блокирует QUIK. Любая. Хоть завернутая в корутину, хоть вызванная напрямую, хоть в замыкании.
Также любая процедура сама принимает решение когда выйти из неё. Для этого есть оператор return. В корутине для этого используется yield. return тоже просто возвращает управление в точку вызова процедуры, тоже не останавливая скрипт.

Любое действие через корутины может быть формализовано через процедуры, с точно такой же последовательностью выполнения и получения результатов. Любое.
 
Да, но в подходе с замыканиями - приходится вручную хранить состояние "этапа" в цикле "подожди, пока". А код постепенно превращается в "машину состояний". При добавлении новых этапов он становится всё громоздче и сложней. Отсюда и вывод для простых задач!

В подходе с корутинами. Никаких ручных "этапов" — код читается как обычный последовательный сценарий. Можно использовать yield где угодно, чтобы "заморозить" выполнение.  Можно легко добавить ожидание событий, сетевые операции и т.д. Логика выглядит линейно, но выполняется асинхронно.
 
1.  
Цитата
VPM написал:
чуть больше
  В ~100 раз.  Вы философ :smile: .
2. У вас есть понятие, что при использовании корутин надо синхронизироваться, если в них используются общие изменяемые данные? То есть следить за тем, чтобы данные недоделанные в одной корутине не использовались в другой. Вы когда-нибудь занимались параллельным программированием?
 
TGB,  А Вам это о чем то говорит: ОС > Терминал > Lua? У Вас мощная машина, а у меня старенький 13 летний? 2. Еще в позапрошлом ВЕКЕ придумали "семафор" и он прекрасно справляется с пропусками поездов до сих пор. А пользоваться или нет параллельным программированием - решает пользователь для себя сам. Что касается меня так я примитивный пользователь - СЕМАФОР!  :smile:  
 
Цитата
VPM написал:
а у меня старенький 13 летний
 Зачем же вы его мучаете тяжелыми корутинами :smile: ? Когда можно легко обойтись легкими функциями. Вам же Nikolay все объяснил.
 
TGB,  Вы в начале полностью прочитайте обсуждение, а затем рекомендации выдавайте. Если рассмотреть пример с фреймворком то он значительно легче, если подобную логику выстраивать подходом с замыканиями.

По образованию инженер тяжело расстаюсь с техникой. А мой еще хоть куда, даст фору некоторым что сегодня в продаже. Это лучшая пока машинка из всех что были у меня (Sony, Toshiba, Asus ..) хотя и 3 поколение i7 прекрасно справляется с 3 квиками 5 браузерами и еще всякой всячиной. Проблема есть с WiFi старое поколение ограничена скорость приема данных 200, а нужно 1000.  
 
Все о великом да о великом! А элементарные вещи: Как при торговле на маржинальном счете Акциями, получить "Свободный денежный остаток"? Во Задача!
Сколько лет уже пользуюсь QUIK но ответ на этот вопрос взывает смятение.
Элементарный вопрос для каждого, оценить капитал в распоряжении. Стоимость Активов в бумагах + Свободные денежные средства = Активы клиента.

Как получить Эти "Свободные денежные средства", без выкрутасов? Во Задача?
 
Цитата
VPM написал:
В подходе с корутинами. Никаких ручных "этапов" — код читается как обычный последовательный сценарий. Можно использовать yield где угодно, чтобы "заморозить" выполнение.  Можно легко добавить ожидание событий, сетевые операции и т.д. Логика выглядит линейно, но выполняется асинхронно.
Да нет ничего сложного писать такие же легкие функции и без корутин. Если под легкостью подразумевается "загнать в корутину длинную портянку с множественными yield", то это спорный вопрос, насколько это легко воспринимается.

Цитата
Да, но в подходе с замыканиями - приходится вручную хранить состояние "этапа" в цикле "подожди, пока".
Ничего хранить вне замыкания не надо, оно само хранит на стеке свое состояние. Просто вызываете метод и он помнит окружение. Это кстати один из базовых методов организации своих колбеков, помещенных в очередь исполнения. Создали окружение, запихнули в очередь. И выполняете. Когда закончится выполнение, он сам вызовет колбек, который помнит все, чтобы отработать. Никаких дополнительных действий.

Думаю, что спорить дальше не стоит. Как уже писал, я корутины использую только для своих итераторов (hack-trade, кстати, и есть бесконечный итератор) или если надо пробросить varargs ... на следующий уровень. Более нужды нет.
Любая длительная операция, требующую ожидания неопределенное время, выполняется через очередь задач, построенную на простых функциях, где-то замыканиях.  
 
Поле -* Свободно - Доступно для вывода средств при сохранении обеспеченности позиций либо открытия позиций по не маржинальным активам, с учетом заблокированных средств под активные заявки, с точностью валюты цены инструмента.

Соответствует значению параметра «НаПокупкуНеМаржин» в таблице «Клиентский портфель».

Для срочного рынка соответствует значению параметра «План. чист. поз.» в таблице «Ограничения по клиентским счетам».
параметр - lim_non_margin STRING Оценка денежных средств, доступных для покупки не маржинальных инструментов .

По факту - это средства доступные для торговли (для проведению торговых операций), А каково, как оформлено, судите сами?

Ну что тут скажешь, не в нашу копилочку талантов! Ну не специально же люди так старались?
 
Nikolay,  Я с Вами не спорю, и ни чего не утверждаю, просто пытаюсь разобраться в возможностях LUA, то что подразумевается под понятием оптимизация, когда какой метод применять? Для себя некую шпаргалку сделать, пределы использования подхода. Да, обсуждение полезно, не много по другому взглянул на подходы. Замыкание использовал в основном при написании индикаторов там это логично. Ну чтобы с Вами окончательно согласиться или нет, нужна собственная история, буду пробовать. Надеюсь что не только мне было интересно и познавательно, но и многим нашим коллегам. Вам большое спасибо за предметное обсуждение.
 
Ну так в индикаторах замыкания используются не зря. Это позволяет хранить стек между вызовами OnCalculate. Сделки смогут проходит раз в час. И вызовы будут помнить все, что было час назад. И не надо городить глобальных переменных, ничего передавать не надо (в этом плане примеры от ARQA некорректны, т.к. передают каждый раз настройки). Т.е. это конструктор некого алгоритма расчета. Да, это можно реализовать через корутины, а кто-то будет упорно доказывать, что это надо решать через классы, они ведь тоже помнят контекст. Тем более, что целое поколение всем вдалбливали, что ООП - это основа, основ. Но как все в истории повторяется, теперь уже не так активно стали это говорить, и даже больше, ООП - это не очень удачная затея в целом.
 
Да это ранее мы обсуждали, пока настройки передаю, не сильно затратно, но более надежно (ни куда не пропадают при "прыгании" по инструментам, тф.) .
ООП  в индикаторах тоже попробовал, мнения определенного пока не сложилось, понравилось что таблицы луа органично ложатся на этот подход, классная расширяемость модульность, такое в впечатление что он под луа и создавался (шучу), что не понравилось накладные больше, значительно сложней в отладке. Сейчас пишу небольшие задачи в двух вариантах подходов. Пытаюсь как мы с Вами сейчас разобраться, что для меня приемлемей.
Страницы: Пред. 1 ... 5 6 7 8 9
Читают тему
Наверх