TGB (Все сообщения пользователя)

Выбрать дату в календареВыбрать дату в календаре

Страницы: 1 2 3 4 5 6 7 8 9 10 11 ... 17 След.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
 
Цитата
VPM написал:
То остальное зачем?
   Согласен. В вашем конкретном случае достаточно первого варианта.
Если бы я был архитектором QUIK, Что стоило бы изменить в QUIK по-крупному
 
Вариант ТЗ на модификацию интерфейса QLua c QUIK
1. Вместо существующей схемы запуска коллбеков создаются циклические очереди (соответствующие коллбекам).
2. В очереди пишет данные событий служебный поток QUIK, а читают эти очереди и выполняют функции их обработки потоки main скриптов пользователя в теле  модифицированной функции sleep.
3. В меню, добавленное в окно запуска пользовательских скриптов, обеспечить возможность изменения пользователем умолчания параметров очередей, а также функций фильтрации данных, записываемых в очереди .
4. У читающих потоков должны быть свои указатели чтения циклических очередей и битовые шкалы непустых очередей, хранящиеся в объекте доступа к их очередям.
5. Читающие потоки циклически, выполнив свои коды переходят в состояние ожидания сигнала появления данных в их очередях или истечения заданного интервала времени.
6. При записи в любую очередь пишущий поток меняет состояние битовых шкал непустых очередей и активирует все читающие потоки.
7. Каждый читающий поток при чтении очереди, выбираемой на основании своей битовой шкалы непустых очередей, получает признак: состояние прочитанных очередей в виде размера непрочитанных данных.
8. Добавить в код динамическое управление количеством очередей и реализовать полностью Lock-Free механизм уведомления без использования std::mutex.
9. Добавить логику удаления очередей «на лету» (dynamic removal) с использованием механизма безопасного освобождения памяти, такого как Hazard Pointers.
10. Реализовать идиому Hazard Pointers с очередью на удаление (retire list).
11. Реализовать пользовательскую функцию запроса свойств очередей.
12. Подключать в QUIKе коды Lua без внесения изменений в его исходники.
13. Перенести все необходимые функции (с внесением изменений, учитывающих п.1 - 12), реализованные в текущей версии QUIK в исходниках Lua, в пакет dll.
-------
  Что в написанном выше не понятно? В моих сообщениях 91 и 92 приведены "сырые", но работающие прототипы, частично реализующие это ТЗ.
 На возражения, замечания и предложения по улучшению ТЗ, постараюсь ответить.
Если бы я был архитектором QUIK, Что стоило бы изменить в QUIK по-крупному
 
Мне стало интересно, а более продвинутый вариант циклических очередей ИИ сможет реализовать?
                                     Промт для ИИ
 Написать программу на C++, в которой:
   1) Создаются несколько циклических очередей с разными типами данных.
   2) В очереди пишет данные один поток, а читают эти очереди несколько потоков.
   3) У читающих потов должны быть свои указатели чтения циклических очередей и битовые шкалы непустых очередей, хранящиеся в объекте доступа к их очередям.
   4) При записи в любую очередь пишущий поток меняет состояние битовых шкал непустых очередей и активирует все читающие потоки.
   5) Каждый читающий поток при чтении очереди, выбираемой на основании своей битовой шкалы непустых очередей, получает признак: состояние прочитанных очередей в виде размера непрочитанных данных.
   6) Добавить в код динамическое управление количеством очередей и реализовать полностью Lock-Free механизм уведомления без использования std::mutex.

Смог  (все комментарии ИИ):
Код
// Это сложная задача, требующая использования атомарных операций (std::atomic) и барьеров памяти для реализации Lock-Free взаимодействия.
// Для выполнения условия динамического управления очередями и уведомления без мьютексов, мы будем использовать std::atomic_flag или
// std::atomic<bool> для сигнализации (busy-wait или wait/notify в C++20) и атомарные указатели.
// Ниже представлен концептуальный код, реализующий эту логику:
//    C++20   ----
#include <iostream>
#include <vector>
#include <atomic>
#include <thread>
#include <memory>
#include <optional>

// Шаблонная циклическая очередь (Lock-Free для одного писателя и нескольких читателей со своими индексами)
template<typename T, size_t Capacity>
class CircularQueue {
    T buffer[Capacity];
    std::atomic<size_t> head{0}; // Указатель записи

public:
    void push(T item) {
        size_t h = head.load(std::memory_order_relaxed);
        buffer[h % Capacity] = item;
        head.store(h + 1, std::memory_order_release);
    }

    bool try_pop(size_t& reader_idx, T& out_item, size_t& pending_count) {
        size_t current_head = head.load(std::memory_order_acquire);
        if (reader_idx < current_head) {
            out_item = buffer[reader_idx % Capacity];
            reader_idx++;
            pending_count = current_head - reader_idx;
            return true;
        }
        pending_count = 0;
        return false;
    }
};

// Объект доступа для каждого читающего потока
struct ReaderContext {
    std::atomic<uint64_t> bitmask{0}; // Битовая шкала непустых очередей
    std::vector<size_t> read_indices;  // Свои указатели чтения
    std::atomic<bool> data_ready{false};

    void update_mask(size_t queue_idx) {
        bitmask.fetch_or(1ULL << queue_idx, std::memory_order_release);
        data_ready.store(true, std::memory_order_release);
        data_ready.notify_all(); // C++20 Lock-free уведомление
    }
};

class QueueManager {
    CircularQueue<int, 1024> int_queue;
    CircularQueue<float, 1024> float_queue;
    std::vector<std::shared_ptr<ReaderContext>> readers;

public:
    void add_reader(std::shared_ptr<ReaderContext> ctx) {
        ctx->read_indices.resize(2, 0); // 0 для int, 1 для float
        readers.push_back(ctx);
    }

    void write_int(int val) {
        int_queue.push(val);
        for (auto& r : readers) r->update_mask(0);
    }

    void write_float(float val) {
        float_queue.push(val);
        for (auto& r : readers) r->update_mask(1);
    }

    void reader_thread_func(std::shared_ptr<ReaderContext> ctx, int id) {
        while (true) {
            // Ожидание данных (Lock-free wait)
            ctx->data_ready.wait(false, std::memory_order_acquire);
            
            uint64_t mask = ctx->bitmask.load(std::memory_order_acquire);
            for (size_t i = 0; i < 2; ++i) {
                if (mask & (1ULL << i)) {
                    size_t pending = 0;
                    if (i == 0) {
                        int val;
                        while (int_queue.try_pop(ctx->read_indices[0], val, pending)) {
                            printf("[Reader %d] Int: %d (Pending: %zu)\n", id, val, pending);
                        }
                    } else {
                        float val;
                        while (float_queue.try_pop(ctx->read_indices[1], val, pending)) {
                            printf("[Reader %d] Float: %.2f (Pending: %zu)\n", id, val, pending);
                        }
                    }
                    // Сбрасываем бит, если данных больше нет
                    if (pending == 0) ctx->bitmask.fetch_and(~(1ULL << i));
                }
            }
            ctx->data_ready.store(false, std::memory_order_relaxed);
        }
    }
};

int main() {
    QueueManager manager;
    auto r1 = std::make_shared<ReaderContext>();
    auto r2 = std::make_shared<ReaderContext>();

    manager.add_reader(r1);
    manager.add_reader(r2);

    std::thread t1(&QueueManager::reader_thread_func, &manager, r1, 1);
    std::thread t2(&QueueManager::reader_thread_func, &manager, r2, 2);

    // Пишущий поток
    std::thread writer([&]() {
        for (int i = 0; i < 5; ++i) {
            std::this_thread::sleep_for(std::chrono::milliseconds(100));
            manager.write_int(100 + i);
            manager.write_float(1.5f * i);
        }
    });

    writer.join();
    t1.detach(); 
    t2.detach();

    return 0;
}
// Ключевые моменты реализации :
// Индивидуальные индексы : Каждый читатель хранит свои read_indices, что позволяет им двигаться по одной и 
// той же очереди независимо.
// Битовая шкала : Используется std::atomic<uint64_t>, где каждый бит соответствует ID очереди.Это позволяет 
// мгновенно проверить, где появились данные.
// Lock - Free Notify : Использован метод atomic::wait / notify_all(доступен с C++20).Он работает эффективнее 
// обычного yield, так как позволяет потоку "заснуть" без использования мьютекса в пользовательском 
// коде(на уровне ОС это может использовать фьютексы).
// Pending Count : Метод try_pop возвращает разницу между указателем записи и текущим индексом чтения, 
// выполняя условие получения "размера непрочитанных данных".
Если бы я был архитектором QUIK, Что стоило бы изменить в QUIK по-крупному
 
Цитата
Oleg Kuzembaev написал:
необходимо достичь понимания, какая именно доработка требуется.Если у вас уже есть такая наготове, то просьба предметно описать ее: что именно стоит добавить? Как это будет выглядеть в вашем представлении?
Промт для ИИ
 Написать программу на C++, в которой:
   1) Создаются несколько циклических очередей с разными типами данных.
   2) В очереди пишет данные один поток, а читают эти очереди несколько потоков.
   3) У читающих потов должны быть свои указатели чтения циклических очередей.
   4) При записи в любую очередь пишущий поток активирует все читающие потоки.
   5) Каждый читающий поток при чтении получает признак: состояние прочитанных очередей в виде размера
      непрочитанных данных.
--------
Результат от ИИ, полученный в течении 5 сек.(компилируемый, код-основа для разработки очередей событий):
Код
#include <iostream>
#include <vector>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <atomic>

template <typename T, size_t Size>
class CircularQueue {
public:
    void push(T item) {
        buffer[head % Size] = item;
        head.fetch_add(1, std::memory_order_release);
    }

    // Каждый читатель передает свой локальный индекс
    bool try_read(size_t& reader_idx, T& out_item, size_t& pending_count) {
        size_t current_head = head.load(std::memory_order_acquire);
        if (reader_idx < current_head) {
            out_item = buffer[reader_idx % Size];
            reader_idx++;
            pending_count = current_head - reader_idx;
            return true;
        }
        pending_count = 0;
        return false;
    }

private:
    T buffer[Size];
    std::atomic<size_t> head{0};
};

// Контейнер для очередей разных типов
struct SharedData {
    CircularQueue<int, 100> int_queue;
    CircularQueue<double, 100> double_queue;
    std::mutex mtx;
    std::condition_variable cv;
    bool stop = false;
};

void writer(SharedData& data) {
    for (int i = 1; i <= 5; ++i) {
        {
            std::lock_guard<std::mutex> lock(data.mtx);
            data.int_queue.push(i * 10);
            data.double_queue.push(i * 1.1);
            std::cout << "[Writer] Pushed data set " << i << std::endl;
        }
        data.cv.notify_all(); // Активируем всех читателей
        std::this_thread::sleep_for(std::chrono::milliseconds(100));
    }
    data.stop = true;
    data.cv.notify_all();
}

void reader(int id, SharedData& data) {
    size_t my_int_ptr = 0;
    size_t my_dbl_ptr = 0;
    
    while (true) {
        std::unique_lock<std::mutex> lock(data.mtx);
        data.cv.wait(lock, [&] { return data.stop || true; }); // Упрощенно: просыпаемся по сигналу

        int val;
        double dval;
        size_t pending;

        // Читаем из инт-очереди
        while (data.int_queue.try_read(my_int_ptr, val, pending)) {
            std::cout << "Reader " << id << " got INT: " << val << " (Left: " << pending << ")\n";
        }
        // Читаем из дабл-очереди
        while (data.double_queue.try_read(my_dbl_ptr, dval, pending)) {
            std::cout << "Reader " << id << " got DBL: " << dval << " (Left: " << pending << ")\n";
        }

        if (data.stop) break;
    }
}

int main() {
    SharedData data;
    std::thread w(writer, std::ref(data));
    std::thread r1(reader, 1, std::ref(data));
    std::thread r2(reader, 2, std::ref(data));

    w.join();
    r1.join();
    r2.join();
    return 0;
}

// Основные моменты реализации (от ИИ):
// Индивидуальные указатели: Переменные my_int_ptr и my_dbl_ptr находятся в стеке каждого читающего потока. Они отслеживают прогресс конкретного 
// читателя относительно общей «головы» (head) очереди.
// Шаблон очереди: Позволяет создавать экземпляры для int, double или любых других типов в одном контейнере SharedData.
// Синхронизация: std::condition_variable используется для мгновенной активации читателей пишущим потоком.
// Статус очереди: Метод try_read возвращает pending_count, что позволяет читателю знать, сколько данных еще осталось в буфере именно для него.

Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
 
Цитата
VPM написал:
Да, спасибо за вариант, про собственный флаг, даже не задумывался, взял на вооружение!
   Этот вариант наглядный, но не самый эффективный и гибкий. Сам я использую для управления, всего двумя нужными мне коллбеками: OnCleanUp и OnTransReply их переопределение, то есть присвоение переменным коллбеков тех функций, которые мне нужны для обработки соответствующих событий.
   Например, если я не хочу (по как то причине) обрабатывать события OnTransReply, то выполняется  OnTransRe ply = function()  end
   Для продолжения обработки значение переменной OnTransReply  заменяется на нужную мне функцию обработки (запись в очередь параметров событий).
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
 
Цитата
Йцукен написал:
Это теоритическое предположение или есть исследования на эту тему?
   Это не предположение. Вы это можете проверить эмпирически в своих скриптах. Это будет тем заметнее, чем больше скриптов работает одновременно и чем большая работа выполняется при инициализации скриптов.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
 
Цитата
VPM написал:
То есть это полноценная модульная система. Так?
 Да.

И еще существенное замечание:
Цитата
Nikolay написал:
Приход колбека должен быть не прерыванием, а добавлением события в очередь. Когда завершите всю работу с инициализацией, то разберете колбеки что пришли, если пришли. А порядок инициализации не испортится, если это сделать не в OnInit.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
 
Цитата
VPM написал:
1. Не понял в чем разница?
    Nikolay, в сообщении #738 эту разницу описал.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
 
Цитата
VPM написал:
Что я делаю не так?
  Выполняйте инициализацию в main (при отключенных коллбеках) и используйте, как написал  Nikolay, вместо dofile, require.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
 
1.
Цитата
VPM написал:
Ну хорошо, давайте по порядку. Вот вариант от  TGB , Так?
  Не так.   Прочитайте  мое сообщение  #737.

2.
Цитата
VPM написал:
Именно здесь, ни кто не по беспокоит, ни какие колбеки не прилетят, пока зависимости в модулях не установлены.
 Тогда почему бы вам не сделать управление коллбеками, хотя бы так?:
Код
-- В самом начале вашего текста скрипта ---
is_Callback = false   --- Коллбеки вас не беспокоят --
 --- Во всех ваших коллбеках первая строка:
if not is_Callback then return end

--- В любом месте вашего скрипта.
--  Включить обработку коллбеков:
is_Callback = true
--  Выключить обработку коллбеков:
is_Callback = false
 

 И пока вы в своем скрипте не выполните;
is_Callback = true
 коллбеки вас не будут беспокоить.
  Если вам в скрипте, по какой то надобности, потребуется отключить обработку коллбеков, то:
is_Callback = false.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
 
Цитата
VPM написал:
TGB , Ну так огромная! А именно в локализации глобальных переменных для данного проекта. Да медленнее но Гарантированно!
     А так быстро и гарантированно (с локализацией глобальных переменных для данного проекта):
Код
function OnInit_VPM()
    -- Логирование (ваш код)
    Logger.init(log_file)
    Logger.log("INIT", "", "Starting robot")
  ----    Весь остальной ваш код ---


end

function main()
      --- Инициализация (в начале main)--
      OnInit_VPM()
     
      --- Дальше ваш код ---

end

   
    Зачем вам "медленно но Гарантированно!", когда можно быстро и  гарантированно?
    Что из написанного мной вам непонятно?
Более того, как я отмечал:
Цитата
TGB написал:
в рассмотренном варианте при запуске нескольких скриптов сразу они начинают выполняться быстрее, чем с кодами в OnInit и  body.
   Это означает, что перезапуск QUIK, при инициализации в main, выполняется быстрее по сравнению с инициализацией в OnInit.
Зачем вам долгий перезапуск?
------
    Вы какой то Сусанин :smile: . Из возможных решений все время выбираете и рекламируете самые сложные и неэффективные.
    Вы хотите пользователей завести в болото :smile:
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
 
Цитата
VPM написал:
Ваши заключения абсолютно верны, и подход с использованием main для инициализации и работы в многозадачной среде действительно более эффективен в случае с QUIK, где важна производительность и отсутствие блокировок. Ну все этим пользуются, и я не исключение.
и
   А тогда зачем вы хотите использовать OnInit, выполняемый в служебном потоке?
   Где вы видите разницу между функцией OnInit, выполняемой перед запуском main и точно такой же функцией, но с другим именем, выполняемой сразу вначале main (кроме того что в первом случае загружается служебный поток)?
Функция getDepoEx может приводить к зависаниям терминала
 
Цитата
Йцукен написал:
потому что getDepoEx, getSecurityInfo, в случае ошибки не возвращают ничего (процедуры, другими словами).
     В синтаксисе Lua есть понятия: результат функции (отсутствие/одно или несколько значений) и выражение. Функция может не возвращать результата, но есть синтаксические конструкции, которые рассматриваются как выражения (это можно посмотреть в описании языка). Например, присвоение:  local v = f (). В этом случае вызов функции справа от равенства считается выражением. В выражении функция, не возвращающая результат, заменяется на nil.  Результатом выражения может быть только одно значение. Явным способом привести к выражению можно синтаксическую конструкцию, заключив ее в круглые скобки. Например: message(type((getSecurityInfo("", "")))), результат печати: nil
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
 
Цитата
TGB написал:
можно разместить в начале main в виде функции
  Уточнение: если очень хотите, определение этой функции в переменной с именем отличным от OnInit можно разместить в области body, но вызвать только в начале main.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
 
Цитата
VPM написал:
OnInit, или просто прозрение, которым хочется поделиться.
   Я бы не стал это комментировать, но ведь кто то может это воспринять как открытие :smile:  и руководство к действию.
 Попробую объяснить ваше заблуждение (очередное).
Я в своих скриптах не использую ни OnInit ни кода в body по следующим причинам:
1) Код OnInit и код body будут исполняться в основном служебном единственном потоке, который обслуживает:
  - запуск всех Lua-скриптов пользователя;
  - запуск коллбеков всех Lua-скриптов пользователя;
  - обработка всех коллбеков таблиц QUIK (это не таблицы Lua);
  - обработка всех индикаторов пользователя.
 Это значит, что пока он будет "возиться" с кодами OnInit и  body другого он ничего делать не будет.
  На всякий случай попробуйте в начале OnInit написать строку: sleep(30000) и посмотрите что получится :smile: .
2) Всю необходимую инициализацию (включая пакеты) можно разместить в начале main в виде функции, вызываемой сразу после ее определения и это будет выполняться в отдельном созданном потоке main, а основной служебный поток продолжит параллельно (если у ПК несколько ядер) выполнять свою перечисленную ранее работу.
3) в рассмотренном варианте при запуске нескольких скриптов сразу они начинают выполняться быстрее, чем с кодами в OnInit и  body.
Функция getDepoEx может приводить к зависаниям терминала
 
1.
Цитата
Йцукен написал:
Предлагаю заинтересованным подтвердить или опровергнуть это.
   Подтверждаю. В выложенном экземпляре QUIK у меня ошибка проявляется.

2.
Цитата
Nikolay написал:
Да, любое зависание основного окна приложения - это ошибка, баг.
  Согласен. Локализована типичная ошибка синхронизации. В моей песочнице эта ошибка не проявляется.

3.  
Цитата
Йцукен написал:
Но когда посреди торгов, у вас неожиданно всё зависнет, - прибежите на форум.
  Согласен. Такие нетривиальные ошибки надо выкладывать и исправлять (разработчику), а пользователей, сумевших их локализовать, поощрять :smile: .

4. Вообще то, многие ошибки, обнаруженные в QUIK, по моему мнению, во многом, следствие существующей дефектной (сложной) его архитектуры , о чем я написал в своей ветке "Что стоило бы изменить в QUIK по-крупному" два года назад.
Если бы я был архитектором QUIK, Что стоило бы изменить в QUIK по-крупному
 
Цитата
TGB написал:
предложение можно сформулировать следующим образом:     функциональность обработки событий QUIK расширить, добавив в API пользователя функцию задания свойств служебных очередей событий
  Оформить это, наверное, лучше в виде меню задания свойств служебных очередей событий QLua, вызываемое в окне запуска скриптов пользователя, при отсутствии запущенных скриптов.
  Промежуточный итог обсуждения интерфейса QUIK со скриптами QLua, при реализации предложений этой ветки следующий:
пользователям, при этом, вносить изменения в их существующие скрипты не требуется.
Если бы я был архитектором QUIK, Что стоило бы изменить в QUIK по-крупному
 
У меня было предложение, которое стоит повторить:
Цитата
TGB написал:
 На форумах ARQA для комментирующих пользователей ввести месячный лимит трафика, после которого не будет возможность вводить комментарии.   Значением этого лимита могло быть: Годовой трафик nikolz / 12 / 10. Но, конечно, насчет значения лимита, решать ARQA.
 Наличие такого лимита, обеспечило бы:    
  - экономию дискового пространства баз форумов;    
 - автоматическое модерирование форумов за счет принуждения думать о краткости и четкости текстов, пишущих комментаторами;       -     - удобство для читающих комментарии, в которых будет меньше флуда.
  Это может показаться неактуальным из-за снижения активности пишущих, но могло бы улучшить качество форумов в перспективе.
Если бы я был архитектором QUIK, Что стоило бы изменить в QUIK по-крупному
 
Цитата
Йцукен написал:
Логичней было бы, чтобы терминал не дублировал пропущенные колбэки, по которым скрипт не получит новых данных.
  Это хорошее ваше предложение можно сформулировать следующим образом:
    функциональность обработки событий QUIK расширить, добавив в API пользователя функцию задания свойств служебных очередей событий:
 1) длин очередей;
 2) функций фильтрации событий перед их записью в соответствующие очереди;
 3) приоритетов обработки очередей;
 4) может быть что то еще..
 Все свойства имеют значение по умолчанию.
Если бы я был архитектором QUIK, Что стоило бы изменить в QUIK по-крупному
 
Цитата
nikolz написал:
Я специально выложил для начинающих писателей не псевдокод, а скрипт на Lua с очередью. Да и в документации на QLua есть еще один пример.
  Какой же вы непонятливый. До сих пор не поняли, что обсуждаются не существующие реализации, а вариант изменения этих реализаций.
  Все таки, похоже, что вы полуинтеллектуальный робот-спамер устаревшей версии, без способности учета контекста обсуждаемой темы при генерации спама.
Если бы я был архитектором QUIK, Что стоило бы изменить в QUIK по-крупному
 
Цитата
nikolz написал:
все что делается внутри sleep - это передается ядру время на которое надо остановить поток.
  Вы, как дятел :smile: , про свое, не относящееся к обсуждаемому.
  Вы это читали ?:
Цитата
TGB написал:
-- Отличие только в реализации функции sleep.
-- При  ее вызове с заданным интервалом внутри нее выполняется (код на C++):
   WaitForSingleObject( ,  ); // здесь ожидание истечения   или выдачи сигнала QUIK (неблокирующей функцией Pulse в служебном потоке) о записи в очереди новых событий.
 -- Когда sleep "срывается" с  , то в ней анализируются очереди (это  можно сделать эффективно, используя битовую шкалу непустых очередей скрипта) и выполняются соответствующие   с параметрами считанными из очередей.
 -- Функционально это не отличается от того, что реализовано сейчас, но выполняется в потоке пользователя main.
Если бы я был архитектором QUIK, Что стоило бы изменить в QUIK по-крупному
 
Цитата
nikolz написал:
Sleep останавливает поток main, а функции колбеков вызываются в другом потоке, на который sleep не действует.
   Вы опять только пишите не читая.
   Мы же с Йцукен обсуждаем не системный Sleep и даже sleep QLua, а предложенный мной запускающий коллбеки.
Вам опять надо проложиться между комментариев :smile: ?
Если бы я был архитектором QUIK, Что стоило бы изменить в QUIK по-крупному
 
Цитата
Йцукен написал:
А как вы узнаете, что это повторы, пока не обработаете их?
   Вы сначала создаете таблицу фильтрации со значениями полей фильтрации заведомо не совпадающими с ожидаемыми данными.
Если бы я был архитектором QUIK, Что стоило бы изменить в QUIK по-крупному
 
Цитата
Йцукен написал:
А смысл несколько раз подряд обрабатывать, например OnQuote, если каждый раз мы будем обрабатывать одни и те же данные?Или вы предлагаете хранить данные для каждого колбэка?
 Если вы не хотите повторно обрабатывать данные, то фильтруйте их. Для фильтрации данных можно создать, для соответствующего вида коллбека, таблицу с фильтруемыми полями, обновляемыми при поступлении новых данных и использовать эту таблицу в начале коллбека с тем. чтобы не обрабатывать ненужные вам повторы.
Если бы я был архитектором QUIK, Что стоило бы изменить в QUIK по-крупному
 
Цитата
Йцукен написал:
а что делать, если между слипами данные поступили по инструменту несколько раз?
  При "просыпании" sleep, функции чтения очередей (коллбеки) будут выполняться (последовательно, без пропусков) столько раз сколько необработанных записей в очередях. Если очереди не переполняются, а это можно контролировать и не допускать, то события не теряются, но возможны задержки в их отработке.
  Как было указано ранее, sleep "просыпается" либо по времени, либо по записи в очереди данных из QUIK. Но при этом в в sleep всегда анализируются и при необходимости обрабатываются непустые служебные очереди скрипта.
Если бы я был архитектором QUIK, Что стоило бы изменить в QUIK по-крупному
 
Цитата
Йцукен написал:
колбэки внутри sleep должны вызываться или как?
  Да, так называемые коллбеки, должны вызываться внутри sleep (выполняемой в потоке main) с данными из очередей.
Если бы я был архитектором QUIK, Что стоило бы изменить в QUIK по-крупному
 
Цитата
Йцукен написал:
можете написать прсевдокод, как по-вашему, использовать очередь событий?
   Я так понимаю, в случае реализации предложенного.

У пользователя никаких изменений:
Код
  <Определение функций обработки событий ровно так, как это сейчас>

---  Весь код скрипта без изменений, в том числе sleep(<Интервал>) --
-- Отличие только в реализации функции sleep.
-- При  ее вызове с заданным интервалом внутри нее выполняется (код на C++):
    WaitForSingleObject(<ОбъектОжидания>, <Интервал>); // здесь ожидание истечения <Интервала> или выдачи сигнала QUIK (неблокирующей функцией Pulse в служебном потоке) о записи в очереди новых событий.
  -- Когда sleep "срывается" с <ОбъектаОжидания>, то в ней анализируются очереди (это  можно сделать эффективно, используя битовую шкалу непустых очередей скрипта) и выполняются соответствующие <Функций обработки событий> с параметрами считанными из очередей.
  -- Функционально это не отличается от того, что реализовано сейчас, но выполняется в потоке пользователя main.
-- Тому, кому интересны детали выполнения sleep, может изменить в своем скрипте формат вызова sleep: вместо sleep(<Интервал>) строка
     local <Количество обработанных элементов очереди>, <Данные о потерях событий в очередях>  = sleep(<Интервал>) 
Если бы я был архитектором QUIK, Что стоило бы изменить в QUIK по-крупному
 
Цитата
Oleg Kuzembaev написал:
В данном случае, нам видится возможность зарегистрировать пожелание на доработку будущих версий ПО. Однако необходимо достичь понимания, какая именно доработка требуется.Если у вас уже есть такая наготове, то просьба предметно описать ее: что именно стоит добавить? Как это будет выглядеть в вашем представлении?

      1. Я исхожу из того, что среди пользователей QUIK могут быть квалифицированные IT-разработчики, которые могут улучшить мои предложения и поэтому выкладываю их в публичку.
      2. Сохранение существующего API QLua, с тем, чтобы обеспечить совместимость с существующими разработками пользователей, является основным ограничением на предлагаемое.
-------------------
I.  В текущей версии QUIK в одном основном потоке обслуживаются:
- запуск всех Lua-скриптов пользователя;
- запуск коллбеков всех Lua-скриптов пользователя;
- обработка всех коллбеков таблиц QUIK (это не таблицы Lua);
- обработка всех индикаторов пользователя.
  Притом, что в текущий момент у подавляющего количества ПК много ядер ЦП, написанное выше явный перебор. Наверное, нет проблем перечисленное выше обрабатывать в отдельных потоках, так как перечисленные выше функции, в моем представлении, не сильно связаны друг с другом и, на первый взгляд, между ними не требуется синхронизация.

II. Интерфейс  взаимодействия QUIK c Lua-скриптом пользователя, реализованный в виде коллбеков, предполагает многопоточный режим использования Lua, порождающий неприятные проблемы параллельного программирования (для решения которых сами же разработчики предлагают использовать потокобезопасную очередь между коллбеками и потоком main). Мне представляется, что имеет смысл вместо коллбеков использовать активную очередь событий, При этом не требуется использовать Lua в многопоточном, редко используемом и не очень стабильном режиме. При этом не будет проблем с подключением новых версий Lua. Более того, скрипты пользователя будут выполняться несколько быстрее из-за отсутствия синхронизации, требуемой в многопоточном варианте использования  Lua.
  Конкретные предложения:
 1) Lua подключать в однопоточном режиме, нативном варианте, без внесения изменений в исходники. Все необходимые коды QLua перенести в dll-пакет.
 2) Для взаимодействия со скриптами пользователя использовать общие для них служебные циклические очереди (в соответствии с существующими функциями обратного вызова). Длины очередей задавать по умолчанию с возможностью их изменения пользователем. Для каждого запускаемого скрипта пользователя создавать блоки доступа (с соответствующими указателями, обеспечивающими чтение очередей без блокировки) к общим циклически очередям.
 3) Функции чтения очередей регистрировать под теми же именами и так же, как это делается для существующих коллбеков.
 4) Выполнять функции чтения очередей в модифицированной следующим образом sleep:
     - sleep выполняется по истечению заданного в ней интервала времени или при получения сигнала поступления данных в одну из циклических очередей (в пропуске сигналов нет проблем, так есть запуск по времени);
     - выполнение функции начинается с анализа появления новых данных в циклических очередях скрипта (конкретного) и запуска зарегистрированных его функций с теми параметрами из очередей, как это делается в существующей версии QUIK;
     - в качестве результата в модифицированной sleep выдавать значения: количество считанных записей в очередях, признак отсутствия потерь данных в очередях из-за их переполнения (с указанием очередей, в которых это возникло), и, возможно, еще что-то.
 Предложенное:
 1) устраняет зависимость служебного потока от пользовательского, когда (служебный) в существующей версии QUIK может быть блокирован пользовательским, а пользовательский служебным;
 2) устраняет необходимость внесения правок в исходники Lua; при этом скрипты пользователя будут выполняться несколько быстрее из-за отсутствия синхронизации, требуемой в многопоточном варианте использования Lua;
 3) обеспечивает контроль потерь данных в очередях, а также возможность исключения этих потерь за счет увеличения длин очередей пользователем или уменьшения времени ожидания в sleep;
 4) убирает проблемы синхронизации внутри скрипта пользователя.

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

IV. Пожелание: сократить время восстановления взаимодействия QUIK с сервером при перезапуске хотя бы до 10 сек.
Если бы я был архитектором QUIK, Что стоило бы изменить в QUIK по-крупному
 
Цитата
Oleg Kuzembaev написал:
В указанный период на сервере проводились технические работы, которые и стали причиной невозможности снятия заявки
  Здравствуйте! Спасибо за ответ.
  У меня просьба к вам: донести до разработчиков мои комментарии 1, 51.
Если бы я был архитектором QUIK, Что стоило бы изменить в QUIK по-крупному
 
В песочнице QUIK 12.8.3.4 была создана заявка с номером 10256702148.
Она не удаляется ни вручную ни из скрипта.
 Выдается сообщение: "Не удалось снять заявку с номером 10256702148"
 Распечатка заявки из таблицы orders:
<code>
{--таблица: 18.02.26 13:04:52:795 - время создания.
  ['lseccode'] = [=[]=]
, ['qty'] = 7.0
, ['activation_time'] = 0
, ['accepted_uid'] = 0
, ['revision_number'] = 0
, ['sec_code'] = [=[YDEX]=]
, ['investment_decision_maker_short_code'] = 0
, ['visible_repo_value'] = 0.0
, ['accruedint'] = 0.0
, ['executing_trader_qualifier'] = 0
, ['trading_session'] = 0
, ['account'] = [=[NL0011100043]=]
, ['client_qualifier'] = 0
, ['operation_type'] = 0
, ['min_qty'] = 0.0
, ['ext_order_flags'] = 0
, ['client_code'] = [=[10379]=]
, ['price'] = 4917.0
, ['exchange_code'] = [=[]=]
, ['order_num'] = 10256702148
, ['passive_only_order'] = 0
, ['reject_reason'] = [=[]=]
, ['withdraw_datetime'] = { -- table: 00000171D1A2F9A0
 ['min'] = 0
, ['week_day'] = 1
, ['sec'] = 0
, ['ms'] = 0
, ['day'] = 1
, ['year'] = 1601
, ['mcs'] = 0
, ['month'] = 1
, ['hour'] = 0
 }
, ['visible'] = 0.0
, ['yield'] = 0.0
, ['settle_date2'] = 0
, ['price_currency'] = [=[]=]
, ['on_behalf_of_uid'] = 0
, ['awg_price'] = 0.0
, ['linkedorder'] = 0
, ['trans_id'] = 105007541
, ['start_date'] = 0
, ['firmid'] = [=[NC0011100000]=]
, ['value2'] = 0.0
, ['executing_trader_short_code'] = 0
, ['exec_type'] = 0
, ['extref'] = [=[]=]
, ['value'] = 34419.0
, ['repo_value_balance'] = 0.0
, ['repovalue'] = 0.0
, ['datetime'] = { -- table: 00000171D1A2FB20
 ['min'] = 36
, ['week_day'] = 3
, ['sec'] = 57
, ['ms'] = 0
, ['day'] = 18
, ['year'] = 2026
, ['mcs'] = 0
, ['month'] = 2
, ['hour'] = 6
 }
, ['class_code'] = [=[QJSIM]=]
, ['value_entry_type'] = 0
, ['settle_date'] = 0
, ['acnt_type'] = 0
, ['brokerref'] = [=[10379//1]=]
, ['start_discount'] = 0
, ['balance'] = 7.0
, ['side_qualifier'] = 0
, ['seccode'] = [=[YDEX]=]
, ['external_qty'] = 0.0
, ['benchmark'] = [=[]=]
, ['qty2'] = 0.0
, ['client_short_code'] = 0
, ['repoterm'] = 0
, ['price_entry_type'] = 0
, ['visibility_factor'] = 0.0
, ['ext_order_status'] = 0
, ['flags'] = 29
, ['settlecode'] = [=[]=]
, ['uid'] = 228221
, ['expiry'] = -1
, ['bank_acc_id'] = [=[]=]
, ['repo2value'] = 0.0
, ['capacity'] = 0
, ['ordernum'] = 10256702148
, ['price2'] = 0.0
, ['investment_decision_maker_qualifier'] = 0
, ['userid'] = [=[NC0011100000]=]
, ['expiry_time'] = -1
, ['canceled_uid'] = 0
, ['settle_currency'] = [=[]=]
, ['filled_value'] = 0.0
}--таблица: 18.02.26 13:04:52:795
<code>
----
Архив песочницы для анализа поддержкой: https://cloud.mail.ru/public/LTv3/NMDsG3SZD
Не приходит полная версия OnTrade
 
Цитата
VPM написал:
За ссылку спасибо, но там столько не понятных для меня слов, что не хватает моей компетенции разобраться.
   Если вы не понимаете то, что написано вами, то бесполезно вам что то объяснять. Все равно не поймете.
Не приходит полная версия OnTrade
 
Цитата
VPM написал:
А что тут комментировать, ЧУШЬ полная!
  Это ваше добровольное признание :smile: :
Цитата
VPM написал:
Не ну ладно, я "несу  всякую ахинею",  разбирая свои идеи по винтикам и полочкам на примерах.
   На всякий случай ссылка: https://forum.quik.ru/messages/forum10/message78413/topic9090/#message78413
Не приходит полная версия OnTrade
 
Цитата
VPM написал:
архитектура с чёткими инвариантами и детерминированными компонентами позволяет предсказать поведение системы в любых ситуациях, включая сбои, и гарантировать, что она не совершит опасных действий (например, не превысит лимиты, не создаст дублирующий ордер).
  Это заклинания :smile:.   Вы думаете, что они работают?
Не приходит полная версия OnTrade
 
У вас много текста но нет простых вещей:
Цитата
TGB написал:
где доказательство безопасности счета?
Не приходит полная версия OnTrade
 
VPM
  Забыл добавить: где доказательство безопасности счета?
Не приходит полная версия OnTrade
 
VPM
Понятно, вас с "толку" не сбить :smile: .
Но интересно, что вы напишите на следующее.
   Обрабатывая коллбеки и восстанавливая их результат, вы, по сути, повторяете (но в условиях неопределенности) работу которая выполняется в QUIK при формировании его таблиц.
  1. Зачем повторять функциональность которую реализовали разработчики и которая отлажена, скорее всего лучше чем "призрачные" коллбеки (зависящие от кода main), так как это было давно (до появления QLua) и проще контролируется?
  2. Полагаете, что вы квалифицированнее разработчиков?
  3. Вы же вроде согласны с принципом "меньше дергаешься - реже падаешь". Вам нечем заняться и хочется поразвлечься с коллбеками?
Не приходит полная версия OnTrade
 
Цитата
VPM написал:
безопасность счёта можно доказать математически
   Определите что такое безопасность счета и приведите математическое доказательство (можете посоветоваться с ИИ).
Не приходит полная версия OnTrade
 
Цитата
VPM написал:
как она обрабатывает неопределённость!
   Мне, кажется, что обычно всем желательна определенность, особенно в сфере финансов, а вы жаждете приключений :smile: .Такое тоже бывает.
Не приходит полная версия OnTrade
 
Цитата
VPM написал:
которая должна быть математически корректной, отказоустойчивой и масштабируемой, без событийной модели и формальных инвариантов не обойтись.Потому что её поведение можно доказать на реальной торговле на любых объёмах и с любыми стратегиями, а не просто протестировать!
   Зачем вы используете, не первый раз громкие понятия. от которых, похоже, очень далеки? Вы сделали в математике открытие: "доказать на реальной торговле" :smile: . Вам это надо опубликовать в научном журнале.
Не приходит полная версия OnTrade
 
Цитата
Йцукен написал:
Это ваш выбор. Но я написал о другом.Ваш подход также не исключает получения "сырых", как вы выразились, колбэков по заявкам / сделкам.Просто вы получаете их гораздо реже в силу того, что, как правило, колбэки с заполненными параметрами идут сразу следом за частично заполненными.
  1. Читайте:
Цитата
TGB написал:
В моих роботах единственный обрабатываемый коллбек это OnTransReply
  2. Вы проверяли задержку между коллбэком с заполненными параметрами и появлением записи в таблице? Если нет, то проверьте.

Цитата
Йцукен написал:
Колбэки OnParam и OnQuote сообщают, когда произошло изменение. Как вы определяете эти изменения?
   1. Я OnQuote не пользуюсь. QUIK не предназначен для высокочастотной торговли. Из стакана вам приходит история с задержкой как минимум 2-3 сек. и ваша реакция, скорее всего, тоже > 2 сек. Хотелось увидеть реальные доходные стратегии в таких условиях.
   2. Если мне нужны какие то данные из текущей таблицы торгов, то я их читаю в цикле, с нужным мне периодом (у меня есть возможность создавать такие циклы, кроме основного) и фильтрую, чтобы не было повторов, по параметру VOLTODAY. Получается не хуже по результату и эффективности использования ПК, чем при использовании OnParam.
Не приходит полная версия OnTrade
 
1.
Цитата
VPM написал:
Ну или просто банально OnTransReply может потеряться. Вы ждёте 120 секунд — это огромный интервал.
  Кто вас заставляет ждать 120 сек.? Ждите 1 млс.  И, вообще, возитесь с коллбеками сколько хотите :smile: . Для вас чем сложнее, тем лучше.

2.
Цитата
VPM написал:
Для простых систем да.
  Я знаю как делать сложные системы не теоретически. И один из основных принципов их создания это не делать лишних движений. Несделанное, во-первых, не ломается, а во вторых, супер эффективно, так как не требует ресурсов.
  С тем подходом к созданию роботов, который использует Nikolay и я не видно проблем создания сложных роботов.
  Кстати, хотя я стараюсь находить и использовать простые решения, робот у меня не сильно простой. Во всяком случае он полностью автономный. Я, конечно, смотрю что он делает, но уже давно он работает месяцами без моего вмешательства.
Не приходит полная версия OnTrade
 
Цитата
Nikolay написал:
Правда такой подход уже сложнее реализовывать, если данные гоняются через socket в алгоритмы, написанные не на lua.
   У меня есть простая функциональность создания собственных событий в виде таблиц событий, в которые записываются функции с их параметрами при подписке на событие.  Если надо, то при наступлении в скрипте события, например, появления каких то данных выполняется запуск всех функций таблицы соответствующей такому событию.
Не приходит полная версия OnTrade
 
Цитата
Йцукен написал:
Но вы так-то тоже  обрабатываете  "сырые" колбэки и получаете соответствующие проблемы, которые потом закрываете "костылями".
    В моих роботах единственный обрабатываемый коллбек это OnTransReply по той причине, что в нем есть информация о возможных причинах отказа в выставлении заявки. При этом я предполагаю, что он может теряться и отслеживаю в таймере выставление заявки по  времени, проверяя таблицу заявок (orders соответственно stop_orders). Если заявка не появилась в соответствующей таблице в течении 120 секунд, то это ошибка в выставлении и есть ветка отработки этой ошибки.
    Все остальное, включая случаи необходимости получения текущих данных таблиц текущих торгов и тд. я беру из таблиц QUIK, кешируя для быстрого доступа индексы используемых таблиц.
    Признаком изменения состояния таблиц (исключая orders, stop_orders) является изменение длины, которую можно получать функцией getNumberOf.  Признаком возможных изменений в существующих записях orders и stop_orders является изменение длины таблицы сделок.
    Вообще, для торговли надо знать состояние своего счета и какую то картину рынка. Все это можно получить из таблиц QUIK и я не вижу смысла возни с коллбеками.
Если бы я был архитектором QUIK, Что стоило бы изменить в QUIK по-крупному
 
Цитата
nikolz написал:
Что именно по-вашему блокируется  "пока в потоке main не выполнится sleep"  Напишите конкретно от какого до какого момента исполнения кода в функции Main блокируется
    Вы опять не читаете или ничего не соображаете.  У меня же написано конкретно то, что давно известно:
Цитата
TGB написал:
В существующей версии QUIK выполнение коллбека блокируется до тех пор пока в потоке main не выполнится sleep или сишная функция.
   Выполните в main строку: for i = 0, 10000000000 do  end
  и вы заблокируете секунд на 30 не только коллбеки, но и диалог QUIK.
  -----
Цитата
nikolz написал:
Вы сказали буквально следующее:  Колбеки всегда остановлены если в main нет функции sleep или параметр у нее равен нулю.
   Вы опять меня "передергиваете".  Где я это писал буквально?  Читайте мою приведенную выше цитату. Вы понимаете что означает слово буквально?
 Зачем вы меня "передергиваете" и пытаетесь приписать свои фантазии?
 Вы продолжаете работать прокладкой между комментариями :smile: ?
Если бы я был архитектором QUIK, Что стоило бы изменить в QUIK по-крупному
 
Цитата
nikolz написал:
Поэтому ничего не блокируется для исполнения sleep.
    Когда же вы научитесь читать :smile: ? Вы читаете тексты перед тем как писать?
  Ведь написано:
Цитата
TGB написал:
блокируется до тех пор пока в потоке main не выполнится sleep или сишная функция
 Где вы видите у меня фразу: "для исполнения"?  
 У вас какое то недержание ваших текстов.
Если бы я был архитектором QUIK, Что стоило бы изменить в QUIK по-крупному
 
Вопрос к поддержке:
   В QUIKе много различных коллбеков. Где гарантии, что они не пропускают события, по которым должны выполняться?
Пропуск событий в заявленных коллбеках, даже если это происходит нечасто, это ошибка QUIK.
   В существующей версии QUIK коллбеки выполняются в единственном служебном потоке.  Что происходит в QUIKе если возникает очередное новое событие, по которому должен выполниться коллбек и при этом не был обработан предыдущий? Есть служебные очереди необработанных событий?
   В существующей версии QUIK выполнение коллбека блокируется до тех пор пока в потоке main не выполнится sleep или сишная функция.
   Выше написанное означает полную зависимость служебного потока от пользовательского. Зачем это сделано в QUIKe?
   В этой ветке были изложены предложения, которые, по моему мнению, могли бы устранить описанные выше проблемы. Что в этих предложениях не понятно или вызывает сомнения?
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
 
Цитата
Nikolay написал:
Квик банально встанет, что не говорит в его пользу и организацию работы с потоками.
  В ветке "Что стоило бы изменить в QUIK по-крупному" (от 15.03.2024) предложены изменения схемы встраивания Lua в QUIK (с сохранением существующего API пользователя) устраняющие некоторые существующие его дефекты, но реакция разработчик QUIK нулевая. Нет даже возражений.
Не приходит полная версия OnTrade
 
Вопрос задан User12501.
Не приходит полная версия OnTrade
 
И все таки:
Цитата
TGB написал:
2. Если вам нужны данные по сделкам, то их можно получать готовыми из таблицы QUIK trade с помощью функции getItem. Зачем вы отрабатываете "сырые" коллбеки OnTrade?
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
 
Цитата
Nikolay написал:
Когда я говорил о двойной очереди, я говорил именно о двух очередях.
    Из написанного вами о двойной очереди (по сути реализующей одну) я не понял между какими функциональностями робота они могут использоваться и что при этом не обеспечивается в QLua, выложенным мной давно известным вариантом?
Страницы: 1 2 3 4 5 6 7 8 9 10 11 ... 17 След.
Наверх