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

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

Страницы: 1 2 3 4 5 6 7 8 9 10 11 ... 27 След.
Состояние счета, Таблица Состояние счета
 
Извините ввел в заблуждение. Сам путаюсь, это один из шедевров, уж не знаю от разработчиков или с биржи, им делить лавры.

Руководство пользователя. -> Раздел 3. Просмотр информации -> Состояние счета -> Позиции:
"
СвободноДоступно для вывода средств при сохранении обеспеченности позиций либо  открытия позиций по немаржинальным активам, с учетом заблокированных средств под  активные заявки, с точностью валюты цены инструмента. Соответствует значению  параметра «НаПокупкуНеМаржин» в таблице «Клиентский портфель».
Для срочного  рынка соответствует значению параметра «План. чист. поз.» в таблице «Ограничения  по клиентским счетам»
"
Состояние счета, Таблица Состояние счета
 
Ни как! Надо рассчитывать, в справке есть формула.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
 
Конечно это не рабочий скрипт, это просто проверка идеи, идеи возможной адаптации. Инженерия кода страдает, но каково, за пол часа от идеи до первых тестов. В SciTe запускаем, подставляем разные массивы и проверяем (просто и дешево), методы все широко описаны. Кстати ранее для проверок идей подключал "gnuplot" к рыночным данным, наглядно получается, давно не пользовался.
Поисковики сегодня свели для задач раздачи рекламы. Использую несколько браузеров, а Яндекс (гордость отечества) обхожу стороной. Хотя сам тоже предпочитаю поиск.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
 
Для луа 5.3 и 5.4  нужно добавить:

local unpack = table.unpack or unpack;
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
 
Сказал - сделал. Предлагаю вниманию (сам не проверял, если есть ошибки пишите). Код в комментариях, думаю и так все понятно, так же там есть ссылка на книгу с примерами на луа, мне в свое время помогла рекомендую. Код немного большой для форума, но не судите строго, выкладываю как есть:
Код
--[[ Как выбораем метод (Памятка)?
Кто уже или еще? не очень дружен со cтатистикой и методами анализа, могу порекомендовать (в сваободном достепе Эл. с примерами на lua 5.1): 
John R. Hauser "Numerical Methods for Nonlinear Engineering Models"

1. Используйте AGC когда. Нужно сохранить форму волны для визуального анализа. Работаете с осцилляторами в реальном времени. Важна минимальная задержка.
2. Используйте Z-score когда. Данные приблизительно нормально распределены. Нужны статистически значимые пороги. Работаете с mean-reverting стратегиями.
3. Используйте Robust scaling когда. Есть выбросы и тяжелые хвосты. Данные не нормально распределены. Нужна устойчивость к экстремальным движениям.
4. Используйте Percentile когда. Важны ранги и относительное положение. Работаете с непараметрическими статистиками. Нужна полная независимость от распределения.

Вывод. Не существует универсального лучшего метода. AGC прекрасен для своей ниши (осцилляторы, визуализация), но для машинного обучения и статистических решений нужен более тонкий подход. Реализуйте адаптивную систему, которая для каждой метрики анализирует распределение и автоматически выбирает оптимальный метод нормализации. Это даст преимущества каждого подхода без их недостатков.
--]]
-------------------------------
-- АДАПТИВНАЯ СИСТЕМА НОРМАЛИЗАЦИИ
-------------------------------
function CandleManager:adaptiveNormalize(data, method, parameters)
    parameters = parameters or {}
    
    -- Анализ характеристик временного ряда
    local stats = self:calculateTimeSeriesStats(data)
    
    -- Автоматический выбор метода если не указан явно
    if not method then
        method = self:selectNormalizationMethod(stats)
    end
    
    if method == "AGC" then
        return self:AGC(data, parameters.alpha or 0.991)
    elseif method == "ZSCORE" then
        return self:ZScoreNormalize(data, parameters)
    elseif method == "ROBUST" then
        return self:robustScale(data, parameters)
    elseif method == "PERCENTILE" then
        return self:percentileNormalize(data, parameters)
    elseif method == "ADAPTIVE" then
        return self:adaptiveHybridNormalize(data, stats, parameters)
    else
        return self:minMaxScale(data)
    end
end

-------------------------------
-- АНАЛИЗ СТАТИСТИК ВРЕМЕННОГО РЯДА
-------------------------------
function CandleManager:calculateTimeSeriesStats(data)
    local stats = {}
    
    -- Базовые статистики
    stats.mean = self:mean(data)
    stats.std = self:stdDev(data)
    stats.min = math.min(unpack(data))
    stats.max = math.max(unpack(data))
    
    -- Анализ выбросов (outliers)
    stats.skewness = self:skewness(data)
    stats.kurtosis = self:kurtosis(data)
    
    -- Анализ волатильности (кластеризация)
    stats.volatility_clustering = self:detectVolatilityClustering(data)
    
    -- Тест на нормальность (приблизительный)
    stats.is_normal = math.abs(stats.skewness) < 1 and stats.kurtosis < 3.5
    
    -- Коэффициент вариации
    stats.coefficient_of_variation = stats.std / math.abs(stats.mean)
    
    return stats
end

-------------------------------
-- АВТОМАТИЧЕСКИЙ ВЫБОР МЕТОДА НОРМАЛИЗАЦИИ
-------------------------------
function CandleManager:selectNormalizationMethod(stats)
    -- Если данные приблизительно нормальны
    if stats.is_normal and stats.coefficient_of_variation < 2 then
        return "ZSCORE"
    
    -- Если есть выбросы (тяжелые хвосты)
    elseif math.abs(stats.skewness) > 1 or stats.kurtosis > 4 then
        return "ROBUST"
    
    -- Сильная кластеризация волатильности
    elseif stats.volatility_clustering then
        return "ADAPTIVE"
    
    -- Стабильный диапазон, мало выбросов
    else
        return "AGC"
    end
end

-- Специализированные методы нормализации:

-- 1. Robust Scaling (устойчивый к выбросам)
function CandleManager:robustScale(data, parameters)
    local median = self:median(data)
    local q75 = self:quantile(data, 0.75)
    local q25 = self:quantile(data, 0.25)
    local iqr = q75 - q25
    
    local normalized = {}
    for i = 1, #data do
        if iqr ~= 0 then
            normalized[i] = (data[i] - median) / iqr
        else
            normalized[i] = 0
        end
    end
    
    return normalized
end

-- 2. Percentile Normalization
function CandleManager:percentileNormalize(data, parameters)
    local sorted = {}
    for i, v in ipairs(data) do sorted[i] = v end
    table.sort(sorted)
    
    local normalized = {}
    for i = 1, #data do
        local rank = 0
        for j = 1, #sorted do
            if sorted[j] <= data[i] then rank = rank + 1 end
        end
        normalized[i] = (rank / #sorted) * 2 - 1  -- [-1, 1]
    end
    
    return normalized
end

-- 3. Adaptive Hybrid Normalization
function CandleManager:adaptiveHybridNormalize(data, stats, parameters)
    -- Разделяем данные на режимы: тренд и шум
    local trend = self:EMA(data, parameters.trend_period or 20)
    local noise = {}
    
    for i = 1, #data do
        noise[i] = data[i] - (trend[i] or data[i])
    end
    
    -- К тренду применяем AGC, к шуму - Robust scaling
    local normalized_trend = self:AGC(trend, 0.995)
    local normalized_noise = self:robustScale(noise)
    
    -- Комбинируем с весами
    local combined = {}
    local trend_weight = parameters.trend_weight or 0.7
    
    for i = 1, #data do
        combined[i] = trend_weight * (normalized_trend[i] or 0) + 
                     (1 - trend_weight) * (normalized_noise[i] or 0)
    end
    
    return combined
end

-- Пример применения в вашем Navigator
function Navigator:enhancedNormalizeMetrics(
                                            EMA20, 
                                            EMA50, 
                                            ATR, 
                                            RSI, 
                                            Vol, 
                                            SMA_Vol, 
                                            sentiment
                                            )

    -- Собираем метрики
    local raw_metrics = {
        (EMA20-EMA50)/ATR,     -- Нормализованный тренд
        (RSI-50)/25,           -- Моментум
        (ATR/close-0.01)/0.05, -- Волатильность
        (Vol/SMA_Vol-1),       -- Объем
        sentiment              -- Настроения
    }

    -- Анализируем каждую метрику и применяем оптимальную нормализацию
    local normalized_metrics = {}
    local method_per_metric = {}
    
    for i, metric in ipairs(raw_metrics) do
        local metric_data = {metric} -- В реальности это будет история метрики
        
        local stats = CandleManager:calculateTimeSeriesStats(metric_data)
        local best_method = CandleManager:selectNormalizationMethod(stats)
        
        normalized_metrics[i] = CandleManager:adaptiveNormalize(
                                                                metric_data, best_method
                                                                )[1] -- Берем последнее значение
        
        method_per_metric[i] = best_method
    end
    
    -- Логируем выбранные методы для отладки (обращаем внимание на точность)
    log_write("Normalization methods: " .. table.concat(method_per_metric, ", "))
    
    return normalized_metrics
end

Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
 
Безусловно, замечание от Nikolay, очень важны, их нужно учитывать при выборе методов нормализации!

AGC — не универсален. Да, он подходит для, осцилляторов (RSI, ROC), для normalized momentum или normalized (DI+ / DI-) или как в моем случае. Но совершенно не пригоден, на абсолютных трендовых показателях (EMA, MACD), когда важны уровни, а не форма сигнала, когда рынок входит в высокий волатильный режим (AGC будет как бы "сплющивать" тренд) или при анализе прорывных ATR моделей (AGC уничтожает ATR-информацию).

Посмотрим ограничения, почему и какие особенности в алгоритме расчета зашиты.

-- ПРОБЛЕМА 1: "ПАМЯТЬ" О ПРОШЛЫХ ЭКСТРЕМУМАХ. local peak = 0.991 * peak1  
Старые экстремумы медленно "забываются", но в момент резкого движения рынка это создает запаздывание.

-- ПРОБЛЕМА 2: НЕ УЧИТЫВАЕТ РАСПРЕДЕЛЕНИЕ ДАННЫХ.
AGC нормализует только по абсолютному максимуму, игнорируя:
* Статистическое распределение,
* Кластеризацию волатильности,
* Тяжелые хвосты (fat tails).

Прислушался и буду реализовать модуль - комплексную адаптивную систему нормализации для трейдинга, которая выбирает метод на основе характеристик данных.

Задача модуля "Комплексная система нормализации для трейдинга". Адаптивная система, которая должна для каждой метрики анализировать распределение и автоматически выбирает оптимальный метод нормализации. Это даст преимущества каждого подхода без их недостатков.

Сформулирую методы Методы Модуля:

* Используем AGC когда? Нужно сохранить форму волны для визуального анализа, Работаем с осцилляторами в реальном времени, Важна минимальная задержка.
* Используем Z-score когда? Данные приблизительно нормально распределены, Нужны статистически значимые пороги. Работаем с стратегиями возврат к среднему.
* Используем масштабирование (Robust scaling) когда? Есть выбросы и тяжелые хвосты, Данные не нормально распределены, Нужна устойчивость к экстремальным движениям.
* Используем Percentile когда? Важны ранги и относительное положение, Работаем с непараметрическими статистиками, Нужна полная независимость от распределения.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
 
Пару слов про сам код. Вот эта конструкция:

local x = (FSettings.x or nil)
local p0 = x or Value(I, v_t, ds) or 0;

Позволяет через таблицу FSettings задавать и передавать любой ранее полученный параметр на обработку (Не только цены).

Например получили массив значений RSI, не понятно что происходит, можно нормализовать,  используя AGC и посмотреть что происходит.

Моей же задачей, была нормализация единичного вектора в гиперкубе состояний (мой морской навигатор). Это позволило сглаживать волны и применить аппарат нечеткой логики, на стадии получения вывода. Как лингвистическую переменную (для пользователя), так и математическую (цифровую для алгоритма).

Всем хорошего кода.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
 

Применение метода Automatic Gain Control (AGC) для нормализации данных в торговых стратегиях может быть весьма эффективным, особенно когда цель — уменьшить влияние изменений волатильности и стандартизировать сигнал, чтобы он имел постоянную амплитуду. Такой подход помогает избежать ситуаций, когда более высокие колебания цены и рыночная волатильность могут вводить в заблуждение или искажать анализ.

Основная идея AGC:
  1. AGC (Автоматическая Регулировка Усиления) — это метод нормализации, который делит текущую цену на абсолютное значение недавнего максимального колебания, обеспечивая, что значения всегда находятся в пределах диапазона от -1 до 1.

  2. Важно, что AGC минимизирует эффект от колебаний цен, снижая значение «шумных» колебаний, а также помогает выявить тренды или сигналы на основе более «чистых» данных.

Как это работает:
  1. peak1: Это переменная для хранения максимума недавнего колебания.

  2. out: Это нормализованное значение, которое делится на максимум из прошлых значений, гарантируя, что его амплитуда не превысит 1 или не опустится ниже -1.

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

Преимущества применения AGC:
  • Нормализация амплитуды сигналов: Преобразует колебания в диапазон от -1 до 1, тем самым делая сигналы более «равномерными» и независимыми от величины самой волатильности.

  • Уменьшение влияния экстремальных колебаний: С помощью AGC устраняется искажение от больших колебаний, что может быть полезно для долгосрочных стратегий.

  • Упрощение сравнения сигналов: Сигналы становятся более «чистыми» и проще для анализа.

AGC действительно может значительно улучшить нашу систему нормализации, особенно в условиях меняющейся волатильности рынка. Это профессиональный подход, используемый в DSP (Digital Signal Processing) для трейдинга.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
 
Код
--[[Automatic Gain Control (AGC) Автоматическая регулировка усиления
Цель AGC - обеспечить единообразный внешний вид индикатора независимо от диапазона колебаний цены. 
Процесс AGC делит текущую цену на абсолютное значение недавнего максимального колебания, 
так что нормализованная форма волны имеет максимум 1 или минимум -1.
--]]
function Cached.AGC() -- Automatic Gain Control (Oscillator © 2013 John F. Ehler)
    
    local abs=math.abs
    
    local Peak={},{}
    local Out={}

    return function( I,FSettings,ds )
        local I = (I or 1)
        local ds = (ds or nil)
        local FSettings = (FSettings or {})
        local v_t = (FSettings.v_t or 'C')
        local x = (FSettings.x or nil)
        --------------------------------------
        local p0 = x or Value(I, v_t, ds) or 0;
        if I == 1 then
            Peak={}; Peak[I]=0;
            Out={}; Out[I]=0;
        end
        
        ----------------------------------------
        -- Automatic Gain Control (AGC) Автоматическая регулировка усиления
        local peak1 = I > 1 and Peak[I-1] or p0;
        local peak = 0.991 * peak1;
        if abs( p0 ) > peak then peak = abs( p0 ) end
        local out1 = I>1 and Out[I-1] or p0;
        local out=0; if peak~=0 then out=p0/peak end
        ----------------------------------------
        
        Peak[I] = peak
        Out[I] = out
        ----------------------------------------
        return out,out1
    end
end
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
 
О чудеса чудесные!!!  :unamused:

Цитата
nikolz написал:
А колбек Onparam как и все другие лишь отсылает событие в очередь.----------------------Я не стал приводить этот вариант, так как я использую механизм событий, а его посетители этого сайта не поймут и не реализуют .

Не только посетители этого сайта не пойму, боюсь что Ваш код ни кто не поймет.

Цитата
nikolz написал:
Поэтому привел этот вариант ему уже лет пятнадцать.  

Вы это серьезно ?  :shock:

Цитата
VPM написал:
param – необязательный параметр. Если параметр не задан, то заказываются данные на основании таблицы обезличенных сделок
Еще раз из таблицы обезличенных сделок! Причем тут "бабушкины калоши?"  ТТП?
Цитата
nikolz написал:
Прикольно, Но если ТТП у Вас часами не меняется по инструменту то что Вы будете считать?
В Вашем варианте: Вы получаете
Цитата
nikolz написал:
x=CreateDataSource(c,s, int[j]);  
То есть из таблицы обезличенных сделок. Причем тут ТТП и OnParam.- Функция вызывается терминалом QUIK при изменении текущих параметров?

Из Ваших сообщений следует, что  " привел этот вариант ему уже лет пятнадцать ", Вы в колбеке дергаете подписку, которую нужно получить один раз, да еще формируете очередь событий? А что ту да можно передать интерфейс получения данных.   О чудеса чудесные!!! :cry:  
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
 
"Ну что сказать, Ну что сказать, устроены так люди,
желают знать, желают знать, желают знать что будет..."
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
 
nikolz,  Да Вы просто из прошлого века. Выйдете на улицу и оглядитесь вокруг, все ли так?

То что читать не научилась, для меня не новость. А вот не разобраться, с одной из основных функций API QUIK, для программиста, коим Вы себе представляете - это перебор?

Да знак ? - это вопрос, вдруг забыли.

Вот справка терминал QUIK 12.6.0.53 (инклюзивно для nikolz, полный текст, ссылка выделена и подчеркнута):    "CreateDataSource

Функция предназначена для создания таблицы Lua и позволяет работать со  свечками, полученными с сервера QUIK, а также реагировать на их изменение.  

Формат вызова:  

TABLE data_source, STRING error_desc CreateDataSource (STRING  class_code, STRING sec_code, NUMBER interval, [, STRING param])

Параметры:  

  • class_code – код класса,
  • sec_code – код инструмента,
  • interval – интервал запрашиваемого графика,
  • param – необязательный параметр. Если параметр не задан,
    то заказываются данные на основании таблицы обезличенных сделок, если задан –
    данные по этому параметру.

Функция возвращает таблицу data_source в случае успешного  завершения. Если указан неверный код класса, код инструмента, интервал или  параметр, то возвращается «nil». При этом error_desc содержит  описание ошибки.  

Функцию CreateDataSource можно использовать только внутри функций main() и callback.

Список констант для передачи в параметр interval :  

ПараметрЗначение интервала
INTERVAL_TICKТиковые данные
INTERVAL_M11 минута
INTERVAL_M22 минуты
INTERVAL_M33 минуты
INTERVAL_M4

4 минуты

INTERVAL_M5

5 минут

INTERVAL_M6

6 минут

INTERVAL_M10

10 минут

INTERVAL_M15

15 минут

INTERVAL_M20

20 минут

INTERVAL_M30

30 минут

INTERVAL_H1

1 час

INTERVAL_H2

2 часа

INTERVAL_H4

4 часа

INTERVAL_D1

1 день

INTERVAL_W1

1 неделя

INTERVAL_MN1

1 месяц

Функция CreateDataSource возвращает таблицу Lua с параметрами:  

ПараметрТипОписание
SetUpdateCallbackfunctionПозволяет задать пользователю функцию обратного вызова для обработки  изменившихся свечек
O

function

Получить значение Open для указанной свечи
HfunctionПолучить значение High для указанной свечи
LfunctionПолучить значение Low для указанной свечи
Cfunction

Получить значение Close для указанной свечи

V

function

Получить значение Volume для указанной свечи
TfunctionПолучить значение Time для указанной свечи
SizefunctionВозвращает текущий размер (количество свечек в источнике данных)
Closefunction

Удаляет источник данных, отписывается от получения данных

SetEmptyCallbackfunction

Позволяет получать данные с сервера без указания функции обратного вызова  

Пример:

ds1 = CreateDataSource("SPBFUT", "RIU3", INTERVAL_M1, "last")
ds2 = CreateDataSource("SPBFUT", "RIU3", INTERVAL_M1)
ds3 = CreateDataSource("SPBFUT", "RIU3", INTERVAL_M1, "bid")

Руководство пользователя QUIK © ARQA Technologies / www.arqatech.com/ru/products/quik/"
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
 
Из справки: "Функцию CreateDataSource можно использовать только внутри функций main() и callback."

Но по моему в OnInit (инициализация функции main ) она не работает? Или?
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
 
Не очень понятно зачем много разовая подписка, вот это место?
Цитата
nikolz написал:
while N>j do j=j+1;
         if ds[j]==nil then local x=CreateDataSource(c,s, int[j]);  
       if x:Size()>0  then    local ti=math.tointeger(1000*(os.clock()-tim)//1);
          ds[j]=x; nkLog:write("time(ms)="..tostring(ti)..","..c..","..s..",j="..j..",int="..int[j]..",size="..ds[j]:Size().."\n"); nkLog:flush();
        end
     end
Есть же SetEmptyCallback. Функция позволяет получать данные с сервера.  
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
 
Прежде чем представить, строго структурированную, элегантную, презентабельную, созданную с нуля, «Информационную Конституцию Рынка», хочу продемонстрировать еще одну уникальную концепцию, озвученную в выше приведенном подходе. Концепцию способную оценивать все и вся - Гиперкуб состояний (2^n), концепция широко известная и хорошо изученная, и не требует какой то отдельной презентации. Для всеобщего понимания покажу свой подход при ее использовании в системе принятия торговых решений.

Суть способа сводится. Вписываем куб состояний в единичный шар, таким образом все его вершины лежат на поверхности шара. Со школьной парты, известна теория цикла, описанная в единичной окружности, тригонометрическими функциями, а так же способы их решений. Куб = 2^3, его проекция на плоскость квадрат = 2^2.
В своей практике, когда становится сложно воспринимать объемные фигуры, прибегаю к способу проектирования их на плоскости. Хорошим примером такой демонстрации является концепт "Морской румб" — это единица измерения угла в навигации, равная 1/32 полной окружности. Таким образом, 1 румб = 360° / 32 = 11,25°.
Принцип работы румба основан на фундаментальном делении круга на 4 основные части (четверти), затем каждой четверти — еще на 8 частей. Исходная четверка: Север (N), Восток (E), Юг (S), Запад (W). Это первичная "монада" направлений, образуемая двумя осями (N-S и E-W). Каждая четверть делится пополам, получаются промежуточные направления (например, между North и East получается Northeast - NE). Этот процесс продолжается, деление следующих частей дает направления типа North-Northeast (NNE) и т.д.
Это наглядный пример "развёртывания" сложной системы из простой двойственности (север-юг, запад-восток) через последовательное применение принципа деления пополам.

В итоге получается 32 равноудаленных направления на компасе ("32-румбовая роза"). Это не просто числа, а именованные направления. Эта система создаёт "рычажные весы" для направления, любое движение судна можно описать как отклонение от одного основного румба к другому, находя баланс между ними.

Практическое использование.
1) Задание курса. Штурман мог задать курс судна, указывая просто румб. Например, "держать курс ONO" (Ost-Nord-Ost, то есть Восток-Север-Восток).
2) Определение направлений. По румбам определяли направление на ветер, на другой корабль, на ориентир.
3) Система счисления. В сочетании с лагом (измерителем пройденного расстояния), румбы позволяли вести графическую счисляемую прокладку пути на карте.

Принципы работы румба оказались интересны, они идеально иллюстрируют рассмотренные ранее идеи (Двойственное отношение, Развёртывание иерархии, Рычажные весы)
1. В основе системы лежат две перпендикулярные пары-монады: Север-Юг и Восток-Запад. Их взаимодействие и порождает всё многообразие направлений.
2. Процесс деления окружности — это классический пример эволюции "от общего к частному", от 4-х основных направлений к 32-м уточнённым. Каждый новый уровень иерархии (N -> NNE -> NEbN -> NE) сохраняет память о предыдущем (образ и подобие).
3. Любой курс корабля можно представить как "весы", где на одной чаше — стремление к одному румбу, на другой — к соседнему. Истинный курс находится в балансе между ними. Смена курса — это динамический процесс перехода через эти "весы".
4. Румбовая система представляет собой дискретное представление непрерывного круга. Это прямое отражение единства прерывного и непрерывного. Система румбов квантует непрерывное пространство направлений, делая его удобным для практического использования и навигационных расчётов.

Таким образом, морской румб — это воплощение фундаментального принципа структурирования пространства через последовательное деление двойственных отношений, что полностью согласуется с концепцией Единого Закона.

Навигации (2D), есть ни что иное, как прямая аналогия с навигацией для 3D (Куб в Сфере). Здесь в гиперпространстве состояний,
* Эволюция системы = движение в пространстве состояний,
*  Каждое состояние = точка внутри единичного шара,
* "Курс" задаётся направлением в пространстве параметров.

Обе системы демонстрируют принцип дополнительности:
- Дискретное представление (румбы/вершины) — для точного ориентирования и классификации
- Непрерывное представление (окружность/шар) — для плавной эволюции и тонкой настройки
* Гиперкуб в шаре — это многомерное обобщение компаса, где Каждое "направление" = определённая конфигурация системы, "Курс" = траектория развития системы в пространстве возможных состояний, "Штурвал" = операторы, переводящие систему из одного состояния в другое.
От простого 2D-компаса к сложным N-мерным пространствам состояний сохраняется единый принцип баланса и преобразования двойственных отношений.

Ни чего не напоминает?
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
 
nikolz,  Я Вам уже отвечал на это вопрос, ни какой чат не может формировать идеи, их задача обработка данных. Вспомните 90, одной из тенденций была закрытие научно - исследовательских центров, без работными оказались тысячи их сотрудников. Закрытие этих институтов привело к тому что масса интеллектуальных, не шаблонно мыслящих людей  оказались "на вольных хлебах".  Именно тогда формировался ряд уникальных концепций способный по новому взглянуть на разные парадигмы. Во многом местом их публикаций был сайт "народ.ру". А я лишь проверяю прикладной характер не которых идей, затронувших меня. Рыночные данные отличное место для их реализации.

Человек и цивилизация в целом подчиняются информационным законам. Это объясняет:
  • повторяемость истории;
  • паттерны коллективного
        поведения;
  • инерцию обществ;
  • различие между индивидуальной и
        коллективной эволюцией.

Осознанный выбор меняет траекторию системы. Переход от автоматичности к свободе действия — и есть рост Меры Разума, который меняет:

  • будущее,
  • поведенческие паттерны,
и «генную память» цивилизации.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
 
Отдельно следует прокомментировать, уникальную концепцию понятия "Информация", примененную в подходе выше описанном. (Это очень важно и пожалуй главное!).
Основная идея: "Всё — это Танец Двух Начал".

Здесь Информация рассматривается ни как, некая база данных, а как Мера — универсальная категория. Информация — универсальная мера сложности. Её природа — в способности систем:
* хранить;
* передавать;
* преобразовывать;
шаблоны взаимодействий.

Здесь исходим из того, что в основе любых изменений в мире лежат два взаимодополняющих потока. Это наблюдаемый принцип, в физике:
*   Электрическое поле (E) не может существовать без Магнитного поля (H).
*   Изменение одного порождает другое.
*   Вместе они создают электромагнитную волну (свет, радиоволны) — фундаментальное явление природы.

Здесь предлагается, применить эту же логику ко всем процессам изменения, включая мышление, общество, биологию, ну и конечно рыночные процессы взаимодействий.
Это и есть "Инфодинамика" — наука о динамике между двумя универсальными началами.

Здесь уместна следующая метафора отражающая смысл, мы говорим "Дождь идет, Хорошая погода стоит".

Ключевые понятия (простым языком):
1. Событие (структурная компонента).
*   Что это? "Замороженный" факт, объект, структура. То, что уже произошло и стало частью реальности. Это "снимок" системы в конкретный момент.
Аналогия. Кирпичи. Дом, книга, произошедшее вчера собрание, записанная мысль — это события. Они имеют форму, структуру, их можно "пощупать" (физически или ментально).

2. Перемена (функциональная компонента).
*   Что это? Сам процесс изменения, поток, энергия, действие. Это то, что превращает одно событие в другое.
Аналогия. Строительство и перестройка. Процесс чтения книги, обсуждение на собрании, ход наших мыслей прямо сейчас — это перемены. Они динамичны и не имеют постоянной формы.

3. Информация (мера гармонии).
*   Что это? Это не просто данные или биты. Это мера того, насколько слаженно "танцуют" Событие и Перемена.
Аналогия. Качество связи между замыслом и исполнением. Представим танец пары:
   *   Событие — это позиции танцоров.
   *   Перемена — это их движение между позициями.
Тогда Информация — это не сами движения и не сами позиции, а та самая красота и слаженность танца, которая рождается из их идеального соответствия.
Если движения резкие и не попадают в ритм (дисгармония) — информации мало.
Если танец идеален (гармония) — информация максимальна.

Почему концепция уникальна и важно ее понимать?

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

2. Универсальность. Эта модель применима к чему угодно:
*   Физика: Частица (событие) и Поле (перемена).
*   Биология: Ген (событие) и Процесс его выражения (перемена).
*   Обучение: Знание (событие) и Процесс понимания (перемена).
*   Коммуникация: Сообщение (событие) и Диалог (перемена).

3. Новое определение Информации. Это, пожалуй, самое главное. Здесь убирается из информации мистика и технократизм. Информация — это не "знание", не "биты в компьютере". Это фундаментальная характеристика любого гармоничного процесса.

Тогда понятие Хаос, получает свою оценку (например, горящий газ) — это бурная перемена, но в нём тоже мало "информации", потому что нет устойчивых структур. Максимум информации возникает на границе между порядком и хаосом, где структура и процесс находятся в идеальном балансе.

Подведу итог. Предлагается не просто новая теория, а новый уникальный язык для описания реальности. Язык, который объединяет разные науки и сознание через единый принцип — динамическую двойственность События и Перемены, а мерой гармонии которых является Информация.

Это тот "электромагнитный закон" для всех сложных систем, который объясняет, как из взаимодействия двух простейших начал рождается всё многообразие и сложность системы (мира).
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
 
Структура проверяемых идей, и адаптация их под философскую концепцию Инь/Ян, информационную динамику и Единое Самосогласованное Поле,  дало удивительные результаты.

Вопрос стоял так: можно ли рассматривать рынок как систему двух анти-компонент, подобную Ян/Инь, и связать это с "инфодинамикой", двойственностью и электромагнетизмом?
Ответ: да — концептуально это корректно, если это используется как модель, как некая аналогия.

1. Почему Ян / Инь можно трактовать как "анти-компоненты"?  Инь и Ян — это две взаимно дополнительные формы одного процесса, где:
* Ян — активное, импульсное, направленное, динамическое поле
* Инь — пассивное, принимающее, инерционное, емкостное поле

В финансах это напрямую соответствует:

| Ян (актив, импульс)     | Инь (реакция, емкость)    |
| --------------------------------| ------------------------- ----------|
| Cпрос, агрессор           | Предложение, абсорбер  |
| Импульс цены              | Волатильность                  |
| Тренд                            | Флейт/консолидация        |
| Импульс ликвидности | Дисперсия ликвидности   |
| Risk-on                          | Risk-off                              |

То есть, рынок уже строится как взаимодействие двух ортогональных потоков Спрос / Предложение. Это очень похоже на двойственность:
* частица - античастица
* заряд - противозаряд
* поток E - поток H в электромагнитном поле
* спрос - предложение

2. Почему 2 компоненты + 2 анти-компоненты = 4-компонентная рыночная модель (аналог 4-компонентного спинора Дирака). В уравнении Дирака 4 компоненты возникают потому что:
1. спин 1/2 > 2 состояния (вверх/вниз);
2. релятивизм > частица/античастица > ещё 2 компоненты.

В рынке можно провести корректную, не-физическую, но математическую аналогию:

1. Два направления динамики (спин):
 * тренд вверх
 * тренд вниз
 
2. Два типа потоков (анти-компоненты):
 * поток агрессора (покупатель или продавец => импульс);
 * поток абсорбера (ликвидность, которая принимает удар => пассивная сторона).
Получаем рыночный "спинор". Это концептуально корректное обобщение, не нарушающее физики.

3. Где здесь "анти"? Не в смысле зло или антипод, а как взаимодополнение через отрицание (с позиции ортогональности компонент). То есть:
• Спрос — анти-предложение
• Импульс — анти-инерция
• Ян — анти-Инь
• Тренд — анти-волатильность
• Цена — анти-объем (в смысле ортогональности)

Следовательно две компоненты системы:
* Активная сила (Ян): движет рынок => импульс => смена цены.
* Пассивная сила (Инь): принимает импульс => распределяет его= > создаёт структуру волатильности.
Это и есть рыночная анти-компонента.

4. Электромагнитная аналогия. F = E * H. Векторное произведение даёт спиральную структуру, аналог двойной спирали. В рыночной интерпретации:
* E — активный импульс рынка (тренд).
* H — пассивная емкость рынка (ликвидность, волатильность).
* F — результирующее рыночное движение / сила тренда.
Это корректно в форме математической аналогии, а не физического тождества.

5. "Инфодинамика" как обобщенная динамика двойственности. Вывод, который можно сделать без мистики: => "Информация — это мера гармонии между двумя взаимодополняющими потоками". Тогда:
* Событие = структурная компонента изменений.
* Перемена = функциональная компонента изменений.

Динамика между ними — это "инфодинамика", аналог динамики поля между:
* электрическим (E)
* магнитным (H)
полями.

6. Как это построить в математическую модель и затем — преобразовать в торговую систему? Данное направление полностью совместимо с классикой финансовой математикой:
* HPR > мультипликативная механика.
* ln(W) > критерий оптимального роста.
* E/H > ортогональные компоненты рынка.
* Инь/Ян > две взаимодополняющие рыночные моды.
* Единый закон > стационарность + потоковая структура.

Что в свою очередь, позволяет построить:
* формальную стохастическую модель.
* аналог уравнения Дирака.
* рабочую торговую систему в QUIK.
* презентацию для инвесторов

Итог. Рынок можно моделировать как Инь/Ян-поле! Это:
* математически корректно.
* концептуально красиво.
* логически непротиворечиво.
* соответствует теории двойственности и оптимальному управлению.

И все это можем превратиться в:
1.  Сформировать Единое стохастическое уравнение рынка, выглядящее как уравнение Дирака.
2.  Реализовать код Lua* для QUIK, который использует эту модель.

СИСТЕМА перестала быть просто торговой, а СТАЛА: Живым воплощением принципа «ВСЕ ЕСТЬ ЧИСЛО» — от математических абстракций до практического трейдинга, отражая единые законы мироздания в финансовых рынках.

---
Проверка концепции Пифагора "ВСЕ ЕСТЬ ЧИСЛО". Применение принципа "По Образу и Подобию" для построения иерархической структуры рынка. Привело к созданию завершенной онтологической системы. В которой:
Рынок - это живой организм с собственной душой и духом
Цена - это материализованная информация о мере отношений
Управление - это осознанный выбор между прошлыми шаблонами и творением будущего
Прибыль - это мера гармонии между Объектом и Субъектом рынка

Система способна:
Воспринимать рынок как целостный информационный организм.
Анализировать через призму онтологических принципов.
Выбирать осознанно, преодолевая генную память прошлого.
Творить будущее, а не следовать готовым шаблонам.
Измерять успех через полноту понимания и гармонию отношений.

Это не просто уже торговая система - это инструмент эволюции, где каждый выбор становится актом творения, а каждая сделка - мерой понимания гармонии.

Здесь роль Архитектора, таких Онтологических Систем, сводится к задачам:
Проектировщик - создание онтологической архитектуры.
Философ - обеспечение смысловой целостности.
Инженер - практическая реализация принципов.
Наставник - обучение системы осознанному выбору.
Ну что то вроде этого.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
 
Ведь особенность такого заказа local ds, err = _G.CreateDataSource(ctx.class_code, ctx.sec_code, ctx.interval) "Если параметр не задан, то заказываются данные на основании таблицы обезличенных сделок". Следовательно если сделок нет по инструменту то и нет подписки, ну или ds:Size() = 0, как это было в моем примере?

Кстати не понятно почему, откуда взялся 0, почему не nil?
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
 
Цитата
nikolz написал:
А если поставить колбек то и тыкать не надо. Тратим время лишь когда приди данные. Что не так?
Только то что могут ни когда не прийти! Или на низко ликвидных завтра подойти!
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
 
С этим разобрались, идея классная и правильная! Но мой эксперимент сводился к получению данных с использованием 4  необязательного параметра, задача получить ("LAST", "NUMCONTRACTS", "NUMBIDS", "NUMOFFERS", "BIDDEPTHT", "OFFERDEPTHT")  в виде свечей и применить к ним технический анализ?

Ни ужели не кто ни использует?  
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
 
Не, не Вы правы это я невнимателен, не сразу рассмотрел идею. "Доходит до утки, на третьи сутки" из этой области.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
 
Кажется я уловил идею, цикл до основного потока это отдельная не блокирующая основной цикл задача! Супер.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
 
Так и в нашем упрощённом варианте предусмотрен выход из цикла подписки.  Либо передача управления в основной цикл (поток луа), либо вообще остановка скрипта, так как данных нет, обрабатывать дальше не чего. Но это уже на усмотрение архитектуры решаемых задач.

Переписал с помощью корутин, здесь их применение наиболее показательно.
Код
local is_run = true

if _G.message then
    print = function(...) _G.message(table.concat({...}, ", ")) end
end

-- Таблица для управления корутинами
local coroutines = {}
local coroutine_queue = {}

-- Функция для добавления корутины в очередь
local function create_task(process_func, description, done_callback, err_callback, ctx)
    local task = {
        coroutine = coroutine.create(process_func),
        description = description,
        done_callback = done_callback,
        err_callback = err_callback,
        ctx = ctx,
        done = false,
        error = false
    }
    
    table.insert(coroutine_queue, task)
    return task
end

-- Функция для выполнения корутин (аналог Dispatch)
local function ProcessCoroutines()
    if #coroutine_queue == 0 then
        return
    end

    local i = 1
    while i <= #coroutine_queue do
        local task = coroutine_queue[i]
        
        if task.done or task.error then
            -- Задача завершена, удаляем из очереди
            if not task.silent then
                if task.done then
                    print('Задача выполнена успешно: '..tostring(task.description))
                elseif task.error then
                    print('Задача не выполнена: '..tostring(task.description))
                end
                if task.response_mes and task.response_mes ~= '' then
                    print('\t'..task.response_mes)
                end
            end
            
            if task.done and task.done_callback then
                task.done_callback(task.ctx, task.response_mes)
            elseif task.error and task.err_callback then
                task.err_callback(task.ctx, task.response_mes)
            end
            
            table.remove(coroutine_queue, i)
        else
            -- Выполняем корутину
            local status = coroutine.status(task.coroutine)
            if status == 'dead' then
                task.done = true
            elseif status == 'suspended' then
                local success, result = coroutine.resume(task.coroutine)
                if not success then
                    task.error = true
                    task.response_mes = tostring(result)
                elseif coroutine.status(task.coroutine) == 'dead' then
                    task.done = true
                    task.response_mes = tostring(result)
                end
            end
            i = i + 1
        end
    end
    
    if #coroutine_queue == 0 then
        print('Очередь корутин пуста')
    end
end

-- Асинхронная версия создания источника данных
local function create_ds(ctx, done_callback, err_callback, wait_time)
    if not ctx then return end

    wait_time = wait_time or 60
    local start_time = os.time()

    local process = function()
        local ds, err = _G.CreateDataSource(ctx.class_code, ctx.sec_code, ctx.interval)
        if not ds then
            error(err)
        end

        ds.interval = ctx.interval
        ds.class_code = ctx.class_code
        ds.sec_code = ctx.sec_code
        ds.description = ctx.class_code..'|'..ctx.sec_code..', интервал '..tostring(ds.interval)
        ds.done_request = false
        ctx.ds = ds

        print('Заказ данных '..ds.description)

        while os.time() - start_time < wait_time do
            local size = ds:Size()
            if size > 0 then
                ds.done_request = true
                coroutine.yield(true, false, 'Получены бары '..ds.description..', размер: '..tostring(size))
                return
            end
            coroutine.yield(false, false, 'Ожидание данных...')
        end
        
        error('Не удалось инициализировать инструменты за время '..tostring(wait_time)..' сек.')
    end

    create_task(
        process,
        'Заказ данных '..ctx.class_code..'|'..ctx.sec_code,
        done_callback,
        err_callback,
        ctx
    )
end

-- Асинхронная версия счетчика
local function counter(i, limit)
    local x = 0
    local process = function()
        while x < limit do
            x = x + 1
            if x >= limit then
                coroutine.yield(true, false, string.format('%i: Счетчик до %i завершен', i, limit))
                return
            else
                coroutine.yield(false, false, string.format('%i: Счетчик на %i из %i', i, x, limit))
            end
        end
    end

    create_task(process, 'Счетчик до '..tostring(limit))
end

local sec_list = {
    {class_code = 'TQBR', sec_code = 'SBER', interval = 1},
    {class_code = 'TQBR', sec_code = 'SBER', interval = 2},
    {class_code = 'TQBR', sec_code = 'SBER', interval = 5},
    {class_code = 'TQBR', sec_code = 'SBER', interval = 10},
    {class_code = 'TQBR', sec_code = 'SBER', interval = 20},
    {class_code = 'TQBR', sec_code = 'GAZP', interval = 10},
    {class_code = 'TQBR', sec_code = 'GAZP', interval = 2},
    {class_code = 'TQBR', sec_code = 'GAZP', interval = 5},
    {class_code = 'TQBR', sec_code = 'LKOH', interval = 5},
    {class_code = 'TQBR', sec_code = 'FEES', interval = 5},
    {class_code = 'SPBFUT', sec_code = 'SiZ5', interval = 5},
    {class_code = 'SPBFUT', sec_code = 'RIZ5', interval = 5},
    {class_code = 'SPBFUT', sec_code = 'RIZ5', interval = 15},
    {class_code = 'SPBFUT', sec_code = 'SRZ5', interval = 30},
}

function main()
    for i = 1, #sec_list do
        counter(i, i*2)
        create_ds(sec_list[i])
    end
    
    -- Основной цикл выполнения
    while is_run do
        ProcessCoroutines()  -- Обрабатываем корутины вместо задач
        sleep(100)
    end
end

function OnStop()
    is_run = false
end
 
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
 
Теперь я ничего не понял? Вот это место:  
Код
    for i = 1, #sec_list do
        counter(i, i*2)
        create_ds(sec_list[i])
    end
Пока цикл for i = 1, #sec_list do не завершен, подвешен не исполняется основной цикл  while is_run do Так?


    while is_run do
        Dispatch()
        sleep(100)
    end
 
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
 
Запустил у себя, лог:
Код
   Тип   Дата   Время   Сообщение
1      18.11.2025   15:26:30   Заказ данных TQBR|SBER, интервал 1
2      18.11.2025   15:26:30   Заказ данных TQBR|SBER, интервал 2
3      18.11.2025   15:26:30   Заказ данных TQBR|SBER, интервал 5
4      18.11.2025   15:26:30   Заказ данных TQBR|SBER, интервал 10
5      18.11.2025   15:26:30   Заказ данных TQBR|SBER, интервал 20
6      18.11.2025   15:26:30   Заказ данных TQBR|GAZP, интервал 10
7      18.11.2025   15:26:30   Заказ данных TQBR|GAZP, интервал 2
8      18.11.2025   15:26:30   Заказ данных TQBR|GAZP, интервал 5
9      18.11.2025   15:26:30   Заказ данных TQBR|LKOH, интервал 5
10      18.11.2025   15:26:30   Заказ данных TQBR|FEES, интервал 5
11      18.11.2025   15:26:30   Заказ данных SPBFUT|SiZ5, интервал 5
12      18.11.2025   15:26:30   Заказ данных SPBFUT|RIZ5, интервал 5
13      18.11.2025   15:26:30   Заказ данных SPBFUT|RIZ5, интервал 15
14      18.11.2025   15:26:30   Заказ данных SPBFUT|SRZ5, интервал 30
15      18.11.2025   15:26:30   Задача выполнена успешно: Заказ данных SPBFUT|SiZ5, интервал 5
16      18.11.2025   15:26:30    Получены бары SPBFUT|SiZ5, интервал 5, размер: 23300
17      18.11.2025   15:26:30   Задача выполнена успешно: Заказ данных SPBFUT|RIZ5, интервал 5
18      18.11.2025   15:26:30    Получены бары SPBFUT|RIZ5, интервал 5, размер: 33461
19      18.11.2025   15:26:30   Задача выполнена успешно: Заказ данных SPBFUT|RIZ5, интервал 15
20      18.11.2025   15:26:30    Получены бары SPBFUT|RIZ5, интервал 15, размер: 12794
21      18.11.2025   15:26:30   Задача выполнена успешно: Счетчик до 2
22      18.11.2025   15:26:30    1: Счетчик до 2 завершен
23      18.11.2025   15:26:30   Задача выполнена успешно: Заказ данных TQBR|SBER, интервал 1
24      18.11.2025   15:26:30    Получены бары TQBR|SBER, интервал 1, размер: 10499
25      18.11.2025   15:26:30   Задача выполнена успешно: Заказ данных TQBR|SBER, интервал 2
26      18.11.2025   15:26:30    Получены бары TQBR|SBER, интервал 2, размер: 3255
27      18.11.2025   15:26:30   Задача выполнена успешно: Заказ данных TQBR|SBER, интервал 5
28      18.11.2025   15:26:30    Получены бары TQBR|SBER, интервал 5, размер: 6302
29      18.11.2025   15:26:30   Задача выполнена успешно: Заказ данных TQBR|SBER, интервал 10
30      18.11.2025   15:26:30    Получены бары TQBR|SBER, интервал 10, размер: 3052
31      18.11.2025   15:26:30   Задача выполнена успешно: Заказ данных TQBR|SBER, интервал 20
32      18.11.2025   15:26:30    Получены бары TQBR|SBER, интервал 20, размер: 3027
33      18.11.2025   15:26:30   Задача выполнена успешно: Заказ данных TQBR|GAZP, интервал 10
34      18.11.2025   15:26:30    Получены бары TQBR|GAZP, интервал 10, размер: 3052
35      18.11.2025   15:26:30   Задача выполнена успешно: Заказ данных TQBR|GAZP, интервал 2
36      18.11.2025   15:26:30    Получены бары TQBR|GAZP, интервал 2, размер: 3255
37      18.11.2025   15:26:30   Задача выполнена успешно: Заказ данных TQBR|GAZP, интервал 5
38      18.11.2025   15:26:30    Получены бары TQBR|GAZP, интервал 5, размер: 6302
39      18.11.2025   15:26:30   Задача выполнена успешно: Заказ данных TQBR|LKOH, интервал 5
40      18.11.2025   15:26:30    Получены бары TQBR|LKOH, интервал 5, размер: 3103
41      18.11.2025   15:26:30   Задача выполнена успешно: Заказ данных TQBR|FEES, интервал 5
42      18.11.2025   15:26:30    Получены бары TQBR|FEES, интервал 5, размер: 3101
43      18.11.2025   15:26:30   Задача выполнена успешно: Счетчик до 4
44      18.11.2025   15:26:30    2: Счетчик до 4 завершен
45      18.11.2025   15:26:30   Задача выполнена успешно: Счетчик до 6
46      18.11.2025   15:26:30    3: Счетчик до 6 завершен
47      18.11.2025   15:26:30   Задача выполнена успешно: Счетчик до 8
48      18.11.2025   15:26:30    4: Счетчик до 8 завершен
49      18.11.2025   15:26:31   Задача выполнена успешно: Счетчик до 10
50      18.11.2025   15:26:31    5: Счетчик до 10 завершен
51      18.11.2025   15:26:31   Задача выполнена успешно: Счетчик до 12
52      18.11.2025   15:26:31    6: Счетчик до 12 завершен
53      18.11.2025   15:26:31   Задача выполнена успешно: Счетчик до 14
54      18.11.2025   15:26:31    7: Счетчик до 14 завершен
55      18.11.2025   15:26:31   Задача выполнена успешно: Счетчик до 16
56      18.11.2025   15:26:31    8: Счетчик до 16 завершен
57      18.11.2025   15:26:31   Задача выполнена успешно: Счетчик до 18
58      18.11.2025   15:26:31    9: Счетчик до 18 завершен
59      18.11.2025   15:26:32   Задача выполнена успешно: Счетчик до 20
60      18.11.2025   15:26:32    10: Счетчик до 20 завершен
61      18.11.2025   15:26:32   Задача выполнена успешно: Счетчик до 22
62      18.11.2025   15:26:32    11: Счетчик до 22 завершен
63      18.11.2025   15:26:32   Задача выполнена успешно: Счетчик до 24
64      18.11.2025   15:26:32    12: Счетчик до 24 завершен
65      18.11.2025   15:26:32   Задача выполнена успешно: Счетчик до 26
66      18.11.2025   15:26:32    13: Счетчик до 26 завершен
67      18.11.2025   15:26:32   Задача выполнена успешно: Счетчик до 28
68      18.11.2025   15:26:32    14: Счетчик до 28 завершен
69      18.11.2025   15:26:33   Задача выполнена успешно: Заказ данных SPBFUT|SRZ5, интервал 30
70      18.11.2025   15:26:33    Получены бары SPBFUT|SRZ5, интервал 30, размер: 3013
71      18.11.2025   15:26:33   Очередь задач пуста

Все задачи Выполнены.
Но ведь это тот же самый вариант? Отличие Ваш скрипт ждет подписки (скорее подписка чем получение), а наш блокирует исполнение, привлекая внимание пользователя, передавая ему управление. (Смысл - Допустим, заблокируй не рабочий тикер, и запусти по новой).
В Вашем подходе будет все висеть пока все тикеры не подпишутся. Допустим сменился тикер у фьючерса, пользователь в надежде  что все работает в автомате? (Это просто частный случай, Вы сами утверждаете, что ситуация мало прогнозируема). А основной поток луа (цикл) остается не рабочем? Тогда уж, все исполнять нужно в основном цикле, с фиксацией состояния подписки, чтоб не повторять запросы?
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
 
Цитата
Nikolay написал:
Т.е. кидаем запросы атомарно, создаем задачу для проверки ответа
Поясните?

Подпиской создали таблицу интерфейса для получения данных, а дальше в потоке луа получаем ds:O(I).
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
 
VPM, А чему Вы удивляетесь? Это не я придумал? Таланты в стране, ни чего не поделаешь.
Цитата
nikolz написал:
"А, ты за большевиков, али за коммунистов?"
Я за индивидуальных ТРЕЙДЕРОВ, которым нужны простые рабочие варианты. По сути если обобщить получение данных из квик, есть 2 основных варианта:
1. с помощью параметров (class_code, sec_code)
2. firmid, client_code.

А есть особые случаи!!!
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
 
nikolz,  Это подписка на тиковые данные согласно документации Руководство пользователя QUIK © ARQA Technologies
Цитата
VPM написал:
"param – необязательный параметр. Если параметр не задан, то заказываются данные на основании таблицы обезличенных сделок, если задан – данные по этому параметру.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
 
nikolz,  И в примере выше подписка сделана один раз, перед созданием потока луа, более того подписка то прошла, ответ true? А индекс = 0? Речь идет о тиковых данных. А количество инструментов тут не причем, разве только все усугубить нужно, но проблематика прекрасна видна на одном инструменте.  Я ведь ни чего не придумал, нет тут от "себятины":

"param – необязательный параметр. Если параметр не задан, то заказываются данные на основании таблицы обезличенных сделок, если задан – данные по этому параметру.

Функция возвращает таблицу data_source в случае успешного  завершения. Если указан неверный код класса, код инструмента, интервал или  параметр, то возвращается «nil». При этом error_desc содержит  описание ошибки.  

Функцию CreateDataSource можно использовать только внутри функций main() и callback."
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
 
Минимально безопасный вариант;
Код
function createDS(class, symbol, interval)
    for i = 1, 20 do
        local ds, err = CreateDataSource(class, symbol, interval)
        if ds then return ds end
        sleep(100)
    end
    return nil
end
Почему это безопасно?
  • Повтор не бесконечный;

  • Максимальная задержка – ~2 секунды, QUIK не убьёт скрипт;

  • Если DS не создалась — ошибка обработана, без падений;

  • Лаконично и безопасно.

Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
 
TGB,  Спасибо, да но этот случай для получения данных из таблицы обезличенных сделок, я использую так, если не получены то и делать дальше нечего (нечего обрабатывать):
Код
  local ds, Error = nil, ''
        local count = 0
        repeat

            ds, Error = CreateDataSource(class, symbol, interval)
            if ds == nil then
                count = count + 1
                sleep(100)
            end

        until (ds or count == 1000)
А что делать когда получаем из таблицы TTT как в примере выше? И задача стоит получить "LAST", "NUMCONTRACTS", "NUMBIDS", "NUMOFFERS", "BIDDEPTHT", "OFFERDEPTHT"? Один не пришел заблокировал все?
Цитата
VPM написал:
Моя идея была получать разные параметры единообразным способом, в формате свечей, что в свою очередь позволило обрабатывать их едиными способами. Использовать единые фильтры, индикаторы, паттерны. Следовательно формировать единую логику, не только для цены, но и для OI, количества на покупку / продажу и так далее.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
 
Следовательно  ds:Size() = 0, есть показатель того что брокер не отдает данные?  
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
 
Но все же осталось не понимание:      
Код
-- Создаем источник данных свечей
    local error_desc = ''
    ds, error_desc  = CreateDataSource(class_code, sec_code, 60 ) -- ,"last"
    message( tostring(error_desc) ..' '.. type(ds))
    if ds then
        --sleep(1000)
        local result = ds:SetEmptyCallback() -- SetUpdateCallback(onCandleUpdate) --
        message("Источник свечей создан, размер: " .. ds:Size() ..' '..tostring(result) )
    else
        message("ОШИБКА: Не удалось создать источник свечей " .. tostring(error_desc))
        return
    end

Цитата
VPM написал:
То подписка на свечи не работает, от слова совсем (17.11.2025   7:51:28   Источник свечей создан, размер: true 0). Не падёт, ошибок не выводит, И НИ ЧЕГО не отдает ds:Size() =0?  Настройки: Умный заказ, терминал 12+ проверил на разных.
А как же проверить? Убедиться что все работает?
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
 
Цитата
Nikolay написал:
И стоит ли это вообще делать, т.к. обычно такие скорости нужны для HFT где нужны объемы, которые очень редко доступны для физ. лиц.
Моя идея была получать разные параметры единообразным способом, в формате свечей, что в свою очередь позволило обрабатывать их едиными способами. Использовать единые фильтры, индикаторы, паттерны. Следовательно формировать единую логику, не только для цены, но и для OI, количества на покупку / продажу и так далее.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
 
Проверил. Без доп. параметра работает. Даже задержка уменьшилась на получение из ТТТ.
Код
   TYPE   DATE   TIME   MESSAGE
1   1   17.11.2025   12:05:06   Скрипт инициализирован
2   1   17.11.2025   12:05:06   === ПРОСТОЙ РОБОТ ЗАПУЩЕН ===
3   1   17.11.2025   12:05:06   1. bid true boolean
4   1   17.11.2025   12:05:06   2. offer true boolean
5   1   17.11.2025   12:05:06   3. last true boolean
6   1   17.11.2025   12:05:06   1. Level_II true boolean
7   1   17.11.2025   12:05:06   nil table
8   1   17.11.2025   12:05:06   Источник свечей создан, размер: 6950 true
9   1   17.11.2025   12:05:36   Статус: 31 итераций, Bid=97970.000000, Offer=97980.000000
10   1   17.11.2025   12:05:36   получать данные с сервера, размер: 6950 true
11   1   17.11.2025   12:05:36   Свеча: O=295.1 H=296.0 L=295.1 C=295.6
12   1   17.11.2025   12:06:06   Статус: 61 итераций, Bid=97960.000000, Offer=97980.000000
13   1   17.11.2025   12:06:06   получать данные с сервера, размер: 6950 true
14   1   17.11.2025   12:06:06   Свеча: O=295.1 H=296.0 L=295.1 C=295.6
15   1   17.11.2025   12:06:34   Робот остановлен по команде
16   1   17.11.2025   12:06:35   Робот остановлен
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
 
Nikolay,  А подскажите такая практика:
ds1, error_desc  = CreateDataSource(class_code, sec_code, 60  ,"last")
ds2, error_desc  = CreateDataSource(class_code, sec_code, 60  ,"bid")
ds3, error_desc  = CreateDataSource(class_code, sec_code, 60  ,"offer")
dsn, error_desc  = CreateDataSource(class_code, sec_code, 60  ,"...")
Она "никудышняя"? Если допустим со стаканом сравнить, или опять же просто напрямую получить из ТТТ?
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
 
Nikolay,  Спасибо Уразумел! Задумался на д тем что получая данные о свечах из таблицы обезличенных сделок, не понятно как обрабатывать свечи на низко ликвидных инструментах?
Цитата
Nikolay написал:
тиковые данные только по запросу
А что брокер под каждого клиента подстраивает сервер? Или как?
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
 
nikolz,  Весь скрип перед Вами, ниже лог его исполнения. На одном инструменте, подписывается на получение данных с сервера, ну а как выводит видно из лога. Если из ТТТ начинает получать (17.11.2025   7:42:28   Статус: 331 итераций, Bid=98610.000000, Offer=98650.000000) хотя и пол века прошло? То подписка на свечи не работает, от слова совсем (17.11.2025   7:51:28   Источник свечей создан, размер: true 0). Не падёт, ошибок не выводит, И НИ ЧЕГО не отдает ds:Size() =0?  Настройки: Умный заказ, терминал 12+ проверил на разных.

Вопрос что делаю не так?  
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
 
Один простой ВОПРОС "Для кого все это???" . Ни покладая рук разработчики трудятся, а для кого все это? Или я что то делаю ни так?
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
 
Код
Минимальный рабочий Скрипт для QUIK

local WORKING_FLAG = true
local class_code, sec_code = "TQBR", "SBER"--"SPBFUT", "RIZ5"

-- Простые переменные для данных
local last_bid = "N/A"
local last_offer = "N/A" 
local last_candle = nil
local ds = nil

-- Прямые callback функции без сложных систем
function OnParam(class_code, sec_code)
    if class_code == "SPBFUT" and sec_code == "RIZ5" then
        last_bid = getParamEx(class_code, sec_code, "bid").param_value or "N/A"
        last_offer = getParamEx(class_code, sec_code, "offer").param_value or "N/A"
    end
end

function OnQuote(class_code, sec_code)
    -- Просто получаем стакан, но не обрабатываем чтобы не нагружать
end

-- Callback для свечей
local function onCandleUpdate(index)
    if ds and index <= ds:Size() then
        last_candle = {
            open = ds:O(index),
            high = ds:H(index),
            low = ds:L(index),
            close = ds:C(index),
            volume = ds:V(index)
        }
        
        if index == 1 then  -- Новая свеча
            message(string.format("НОВАЯ СВЕЧА %s O=%.1f C=%.1f", 
                sec_code, last_candle.open, last_candle.close))
        end
    end
end

function main()
    message("=== ПРОСТОЙ РОБОТ ЗАПУЩЕН ===")
    
    -- Простые подписки
    local result = ParamRequest(class_code, sec_code, "bid")
    message( '1. bid '.. tostring(result) ..' '.. type(result))
    local result = ParamRequest(class_code, sec_code, "offer") 
    message( '2. offer '.. tostring(result) ..' '.. type(result))
    local result = ParamRequest(class_code, sec_code, "last")
    message( '3. last '.. tostring(result) ..' '.. type(result))
    
    local result = Subscribe_Level_II_Quotes(class_code, sec_code)
    message( '1. Level_II '.. tostring(result) ..' '.. type(result))
    
    -- Создаем источник данных свечей
    local error_desc = ''
    
    ds, error_desc  = CreateDataSource(class_code, sec_code, 60, "last")
    message( tostring(error_desc) ..' '.. type(ds))
    if ds then
        --sleep(1000)
        local result = ds:SetEmptyCallback() -- SetUpdateCallback(onCandleUpdate) --
        message("Источник свечей создан, размер: " .. ds:Size() ..' '..tostring(result) )
    else
        message("ОШИБКА: Не удалось создать источник свечей " .. tostring(error_desc))
        return
    end
    
    -- ОСНОВНОЙ ЦИКЛ - ПРОСТОЙ И ЧИСТЫЙ
    local iteration = 0
    local last_print_time = os.time()
    
    while WORKING_FLAG do
        iteration = iteration + 1
        
        -- Печатаем статус раз в 30 секунд
        local current_time = os.time()
        if current_time - last_print_time >= 30 then
            message(string.format("Статус: %d итераций, Bid=%s, Offer=%s", 
                iteration, last_bid, last_offer))
            
            local result = ds:SetEmptyCallback() -- SetUpdateCallback(onCandleUpdate) --
            message("получать данные с сервера, размер: " .. ds:Size() ..' '..tostring(result) )
            if ds:Size() and ds:Size()>0  then
                message(string.format("Свеча: O=%.1f H=%.1f L=%.1f C=%.1f", 
                    ds:O(ds:Size()), ds:H(ds:Size()), 
                    ds:L(ds:Size()), ds:C(ds:Size())
                    ))
            end
            
            last_print_time = current_time
        end
        
        -- ВАЖНО: Даем время QUIK обработать события
        sleep(1000)  -- 1 СЕКУНДА - достаточно для избежания "Превышения времени"
    end
    
    message("Робот остановлен")
end

-- Простые обработчики остановки
function OnStop()
    WORKING_FLAG = false
    if ds then ds:Close() end
    message("Робот остановлен по команде")
end
function OnClose()
    WORKING_FLAG = false  
    if ds then ds:Close() end
end
function OnInit()
    message("Скрипт инициализирован")
end
Код
   TYPE   DATE   TIME   MESSAGE
1   1   17.11.2025   7:36:58   Скрипт инициализирован
2   1   17.11.2025   7:36:58   === ПРОСТОЙ РОБОТ ЗАПУЩЕН ===
3   1   17.11.2025   7:36:58   1. bid true boolean
4   1   17.11.2025   7:36:58   2. offer true boolean
5   1   17.11.2025   7:36:58   3. last true boolean
6   1   17.11.2025   7:36:58   1. Level_II true boolean
7   1   17.11.2025   7:36:58   nil table
8   1   17.11.2025   7:36:58   Источник свечей создан, размер: true 0
9   1   17.11.2025   7:37:28   Статус: 31 итераций, Bid=N/A, Offer=N/A
10   1   17.11.2025   7:37:28   Источник свечей создан, размер: true 0
11   1   17.11.2025   7:37:58   Статус: 61 итераций, Bid=N/A, Offer=N/A
12   1   17.11.2025   7:37:58   Источник свечей создан, размер: true 0
13   1   17.11.2025   7:38:28   Статус: 91 итераций, Bid=N/A, Offer=N/A
14   1   17.11.2025   7:38:28   Источник свечей создан, размер: true 0
15   1   17.11.2025   7:38:58   Статус: 121 итераций, Bid=N/A, Offer=N/A
16   1   17.11.2025   7:38:58   Источник свечей создан, размер: true 0
17   1   17.11.2025   7:39:28   Статус: 151 итераций, Bid=N/A, Offer=N/A
18   1   17.11.2025   7:39:28   Источник свечей создан, размер: true 0
19   1   17.11.2025   7:39:58   Статус: 181 итераций, Bid=N/A, Offer=N/A
20   1   17.11.2025   7:39:58   Источник свечей создан, размер: true 0
21   1   17.11.2025   7:40:28   Статус: 211 итераций, Bid=N/A, Offer=N/A
22   1   17.11.2025   7:40:28   Источник свечей создан, размер: true 0
23   1   17.11.2025   7:40:58   Статус: 241 итераций, Bid=N/A, Offer=N/A
24   1   17.11.2025   7:40:58   Источник свечей создан, размер: true 0
25   1   17.11.2025   7:41:28   Статус: 271 итераций, Bid=N/A, Offer=N/A
26   1   17.11.2025   7:41:28   Источник свечей создан, размер: true 0
27   1   17.11.2025   7:41:58   Статус: 301 итераций, Bid=N/A, Offer=N/A
28   1   17.11.2025   7:41:58   Источник свечей создан, размер: true 0
29   1   17.11.2025   7:42:28   Статус: 331 итераций, Bid=98610.000000, Offer=98650.000000
30   1   17.11.2025   7:42:28   Источник свечей создан, размер: true 0
31   1   17.11.2025   7:42:58   Статус: 360 итераций, Bid=98610.000000, Offer=98650.000000
32   1   17.11.2025   7:42:58   Источник свечей создан, размер: true 0
33   1   17.11.2025   7:43:28   Статус: 390 итераций, Bid=98610.000000, Offer=98650.000000
34   1   17.11.2025   7:43:28   Источник свечей создан, размер: true 0
35   1   17.11.2025   7:43:58   Статус: 420 итераций, Bid=98610.000000, Offer=98650.000000
36   1   17.11.2025   7:43:58   Источник свечей создан, размер: true 0
37   1   17.11.2025   7:44:28   Статус: 450 итераций, Bid=98610.000000, Offer=98650.000000
38   1   17.11.2025   7:44:28   Источник свечей создан, размер: true 0
39   1   17.11.2025   7:44:58   Статус: 480 итераций, Bid=98610.000000, Offer=98650.000000
40   1   17.11.2025   7:44:58   Источник свечей создан, размер: true 0
41   1   17.11.2025   7:45:28   Статус: 510 итераций, Bid=98610.000000, Offer=98650.000000
42   1   17.11.2025   7:45:28   Источник свечей создан, размер: true 0
43   1   17.11.2025   7:45:58   Статус: 540 итераций, Bid=98610.000000, Offer=98650.000000
44   1   17.11.2025   7:45:58   Источник свечей создан, размер: true 0
45   1   17.11.2025   7:46:28   Статус: 570 итераций, Bid=98610.000000, Offer=98650.000000
46   1   17.11.2025   7:46:28   Источник свечей создан, размер: true 0
47   1   17.11.2025   7:46:58   Статус: 600 итераций, Bid=98610.000000, Offer=98650.000000
48   1   17.11.2025   7:46:58   Источник свечей создан, размер: true 0
49   1   17.11.2025   7:47:28   Статус: 630 итераций, Bid=98610.000000, Offer=98650.000000
50   1   17.11.2025   7:47:28   Источник свечей создан, размер: true 0
51   1   17.11.2025   7:47:58   Статус: 660 итераций, Bid=98610.000000, Offer=98650.000000
52   1   17.11.2025   7:47:58   Источник свечей создан, размер: true 0
53   1   17.11.2025   7:48:28   Статус: 690 итераций, Bid=98610.000000, Offer=98650.000000
54   1   17.11.2025   7:48:28   Источник свечей создан, размер: true 0
55   1   17.11.2025   7:48:58   Статус: 720 итераций, Bid=98610.000000, Offer=98650.000000
56   1   17.11.2025   7:48:58   Источник свечей создан, размер: true 0
57   1   17.11.2025   7:49:28   Статус: 750 итераций, Bid=98610.000000, Offer=98650.000000
58   1   17.11.2025   7:49:28   Источник свечей создан, размер: true 0
59   1   17.11.2025   7:49:58   Статус: 780 итераций, Bid=98610.000000, Offer=98650.000000
60   1   17.11.2025   7:49:58   Источник свечей создан, размер: true 0
61   1   17.11.2025   7:50:28   Статус: 810 итераций, Bid=98610.000000, Offer=98650.000000
62   1   17.11.2025   7:50:28   Источник свечей создан, размер: true 0
63   1   17.11.2025   7:50:58   Статус: 840 итераций, Bid=98610.000000, Offer=98650.000000
64   1   17.11.2025   7:50:58   Источник свечей создан, размер: true 0
65   1   17.11.2025   7:51:28   Статус: 870 итераций, Bid=98610.000000, Offer=98650.000000
66   1   17.11.2025   7:51:28   Источник свечей создан, размер: true 0
67   1   17.11.2025   7:51:58   Статус: 900 итераций, Bid=98610.000000, Offer=98650.000000
68   1   17.11.2025   7:51:58   Источник свечей создан, размер: true 0
69   1   17.11.2025   7:52:15   Робот остановлен по команде
70   1   17.11.2025   7:52:15   Робот остановлен
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
 
2. Создание объектов в Lua (OOП-подход). Lua не имеет полноценного OOP, но таблицы + метатаблицы позволяют достаточно просто строить объекты.

Когда удобно использовать объект?
* Когда объект “знает о себе всё”, например, инструмент/портфель содержит всю информацию о классе, счёте, лоте, цене, позиции, статусе торгов.
* Когда нужно хранить состояние и методы, которые его изменяют.
* Когда удобно группировать методы вокруг данных, чтобы не передавать их постоянно в функции.

Когда объект может быть лишним?
* Если скрипт простой и все данные можно хранить в таблицах без методов.
* Если входные параметры минимальны, и основной сценарий — «инициализировал и забыл».

Итог.
*  ООП полезно для сложных инструментов, портфелей и роботов.
*  Но для конечного пользователя упрощённый интерфейс (модуль + таблицы данных) удобнее, просто и наглядно.

3. Удобство конечного пользователя. Ну здесь собственно и комментарии излишни, просто зафиксируем.

* Минимум входных параметров, тикер + счёт + субсчёт. Всё остальное берётся автоматически из QUIK.
* Автоопределение параметров, класс инструмента, шаг цены, масштаб, доступные позиции, счета.
* Модули как библиотека, пользователь не меняет код робота, а лишь занимается его конфигурацией.
* Принцип “Написал и Забыл”, всё сложное внутри библиотеки, робот только управляет потоком и вызывает нужные функции.

Ну как то так. Хорошего кода.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
 
Сформулирую подход — Разделение кода на модули. Критерии разделения кода в Lua для QUIK:

а) Функциональная логика – каждый модуль отвечает за конкретную задачу:

* qlib_core.lua — системные и сервисные функции (isConnected, sleep, getTradeDate, логирование).
* qlib_data.lua — получение рыночной информации (getQuotes, getParamEx, getSecurityInfo).
* qlib_portfolio.lua — управление портфелем (initPortfolio, autoRebalancePortfolio, позиции).
* qlib_utils.lua — общие утилиты (tableKeys, форматирование, вспомогательные функции).

б) Повторное использование — если какая-то функция используется в разных местах, выносим её в отдельный модуль.
с) Лёгкость замены/обновления — чтобы исправления коснулись только конкретного функционала, без изменения всего робота.
д) Простота конечного пользователя — модули скрывают все сложности и предоставляют простой интерфейс: входные параметры минимальны (например, только тикер, счёт, субсчёт).

Итог. Модули разделяем
* по смыслу
* и повторяемости функций.
Цель - пользователь получает простую точку входа — скрипт робота.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
 
Прислушаюсь к советам и замечания профи:
Цитата
Nikolay написал:
И да, делать для этого объекты - так себе затея. Входящие параметры для скрипта - это код инструмента, торговый счет, субсчет (код клиента) если их несколько. Все. Остальное получается из терминала. Впрочем даже счет и субсчет можно подставить из данных для класса инструмента. Зачастую они и нужны. Если Вы пишите скрипты для себя, то, конечно, делайте как хотите. Но если уже для других, то всегда отталкивайтесь, что максимум что может сделать пользователь - это изменить файл настроек, где все максимально просто и понятно. Не надо искать информацию в служебных окнах терминала. Либо делать интерфейс, через который тоже просто задаются параметры.
Разберусь с чем имеем дело.

1. Сила и мощь при  использовании луа - это его основная структура данных - таблица. Именно они позволяют нам структурировать код, так как нам нужно, создавать модули. Что в свою очередь приводит к многоразовому использованию этих модулей (принцип "Написал и Забыл") . Согласитесь - это просто удобно, если возникает необходимость что то исправить, мы просто работаем с этим модулем. И здесь возникает основной вопрос  по каким критериям, необходимо делить код на модули?

2. Луа позволяет легко создавать так называемый "Объект", создавая его необходимо понимать, а для чего и когда это удобно? Я не очень разобрался со всеми возможностями ООП, для меня важную роль играет фактор "таблица знает о себе все", то есть удобство управления, хранения и  получения данных. Именно здесь возникают профессиональные сложности.

3. Удобство конечного пользователя, просто необходимая. Автоматизация получения данных, утилиты, сервисные вещи и все прочее в библиотеку. Много  разовое модульное использования превращает нас из конструктора деталей и узлов в Главного конструктора нашего проекта "Робот". Один раз отладили, и используем в проверке наших торговых идей. Так что взялись за библиотеку, а идей еще очень много и не терпится их проверить!  :smile:  
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
 
Если добавить к этим модулям вспомогательную оболочку типа DataHub, которая объединит QuickDataManager и мой MarketData в одну унифицированную архитектуру (единый интерфейс “данные QUIK” и “данные с рынка”), то получим идеальную базу для торгового ядра?
Но в этом варианте в разы уваливается сложность, и требуется более профессиональный подход, в распределении ресурсов и нагрузок CPU, то о чем  нас постоянно предупреждают опытные разработчики.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
 
Разбор полета.

Грамотная архитектура, для идеи "ленивого дата-менеджера" и улучшения её в духе реального продакшн-решения. Разберу вариант подробней, чтобы подтвердить, где попал в точку и что нужно отполировать.

1. Нормализация ключа кэша.
Сортировка ключей — идея для стабильности (иначе "a,b" и "b,a" могли бы быть разными), нужно ещё добавить firmid и client_code в начало ключа: local key_parts = {self.firmid, self.client_code, param}
Так один менеджер может обслуживать несколько клиентов без пересечений в кэше, теперь комбинация sec_code=SBER и sec_code=GAZP не будет путаться.

2. Кэш с TTL и проверкой актуальности.
self.cache_ttl = 5
self.cache_timestamps[cache_key] = os.time()

Это минимальный, но практичный шаг, QUIK не всегда требует мгновенной актуализации, но важно не держать stale-данные применим подход "time-based invalidation".
Также можно улучшить, если добавить опциональный параметр TTL при вызове?
function QuickDataManager:new(firmid, client_code, cache_ttl)
   obj.cache_ttl = cache_ttl or 5
end

3. Безопасная загрузка через pcall: local success, err = pcall(function()
QUIK-функции часто возвращают nil или бросают ошибки при нестабильных данных. Это гарантия, что менеджер не уронит основной поток.

4. Методы вместо __index. Переход от хардкода (manager.depo) к явным методам (manager:get_depo()) — это повышает читаемость и контроль над параметрами.

5. Управление кэшем.
QuickDataManager:clear_cache()
QuickDataManager:refresh()
QuickDataManager:get_cache_stats()

Просто и функционально — всё, что нужно для отладки и тонкой настройки. get_cache_stats() — инструмент для мониторинга эффективности.

Что можно слегка отшлифовать.

1. Унификация вызова QUIK-функций. сделано логично:
if param == "money" then
   data = getMoneyEx(...)

Но чтобы не плодить if-ветки, можно вынести маппинг функций в таблицу:
QuickDataManager.functions = {
   money = getMoneyEx,
   depo = getDepoEx,
   portfolio = getPortfolioInfoEx,
   buy_sell = getBuySellInfoEx,
   futures_limit = getFuturesLimit,
   futures_holding = getFuturesHolding
}

А потом универсально:
local func = self.functions[param]
if not func then error("Unknown data type: " .. param) end
data = func(table.unpack(args))

Чтобы args формировать автоматически — хранить шаблоны параметров?

2. Параметры по умолчанию.
Сейчас много or "", можно централизовать дефолты:
QuickDataManager.defaults = {
   money = { tag="", currcode="SUR", limit_kind=0 },
   depo = { sec_code="", trdaccid="", limit_kind=0 },
   portfolio = { limit_kind=0 },
   buy_sell = { class_code="", sec_code="", price=0 },
   futures_limit = { trdaccid="", limit_type=0, currcode="SUR" },
   futures_holding = { trdaccid="", sec_code="", type=0 }
}
Тогда метод _loadData может начинаться с: optional_params = table.merge(self.defaults[param] or {}, optional_params or {})

3. Асинхронность или очередь обновлений. Если  добавить корутину-обновление (например, периодическое refresh), то эта структура идеально готова — просто запускаешь фоновые обновления без блокировки QUIK.

4. Универсальный интерфейс доступа. Чтобы сохранить удобство "ленивого доступа", можно вернуть синтаксическую обёртку:

setmetatable(QuickDataManager, {
   __index = function(self, key)
       if self["get_" .. key] then
           return self["get_" .. key](self)
       end
   end
})
Тогда снова можно писать:
local depo = manager.depo  -- ленивый вызов get_depo()
но при этом параметры будут управляться методами?

 Финальный вариант (сбалансированный).

function QuickDataManager:new(firmid, client_code, cache_ttl)
   local obj = setmetatable({}, self)
   obj.firmid = firmid
   obj.client_code = client_code
   obj.cache = {}
   obj.cache_timestamps = {}
   obj.cache_ttl = cache_ttl or 5
   return obj
end

function QuickDataManager:_build_cache_key(param, optional_params)
   local key_parts = {self.firmid, self.client_code, param}
   if optional_params then
       local sorted = {}
       for k in pairs(optional_params) do table.insert(sorted, k) end
       table.sort(sorted)
       for _, k in ipairs(sorted) do
           table.insert(key_parts, k .. "=" .. tostring(optional_params[k]))
       end
   end
   return table.concat(key_parts, "|")
end
Просто добавить централизованные defaults и маппинг функций.

ИТОГ. Такая версия — уже достаточно зрелая. Она:
* Решает проблему дублирования и нагрева QUIK-API;
* Гибко масштабируется под любые источники данных;
* Предусматривает отказоустойчивость;
* Простая для использования в сценариях (ленивая инициализация).

К этому обновленному, менеджеру если добавить, автоматическое обновление данных через coroutine с учётом TTL и нагрузки (чтобы QUIK не тормозил). Это позволит, например, держать кэш свежим без прямых вызовов refresh().
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
 
В концептуальном примере выше, используется ленивый подход (lazy loading) для получения данных, когда они действительно необходимы, а не заранее.

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

Производительность, хотя ленивый подход помогает избежать лишних запросов, важно следить за тем, чтобы не было слишком частых запросов к серверу, если объем данных большой.
Оптимизация, кэширование данных, чтобы не запрашивать данные каждый раз при обращении к параметрам, добавить кэширование результатов запросов через self.cache для параметров, чтобы избежать лишних вызовов.

Некоторые моменты, которые нужно улучшить для большей гибкости и упрощения, и настройки стабильной работы.

1. Обработчик ленивой загрузки для разных параметров. Вместо жесткого кода для каждого параметра, можно обрабатывать ленивую загрузку более универсально, используя механизм, который будет определять, какой тип данных нужно загружать, в зависимости от имени параметра.

2. Модификация функции __index. Нужно немного улучшить проверку, чтобы все параметры, можно было бы загружать лениво, а не только жестко прописанные. Например, можно динамически извлекать значения для всех типов данных через getParamEx.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
 
Цитата
nikolz написал:
В своем скрипте все параметры типа firmid, client  получаю из QUIK. Т е их не надо вводить пользователю.
Не очень понимаю этот подход, ну если с firmid все еще понятно, зависит в чей терминал скипт загружен. То с client не все очевидно, все равно приходится в водить,  
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
 
nikolz,  Это не инструкция, это описные одного из вариантов подхода, если хотите мое виденье, выложено на обсуждение сообществу.  

"ленивая" загрузка - описание есть выше, такую возможность предоставляет ООП, если не очень понятно можно посмотреть фреймворк на который  я ссылаюсь.

Подход уже тоже устарел так как нашлись более удобные решения, например кэширует результаты и имеет авто обновление через корутину (с ограничением нагрузки),
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
 
Что делает:

QuickDataManager:new(firmid, client_code). Конструктор создаёт экземпляр менеджера с обязательными параметрами firmid и client_code.
Это основные параметры для работы с системой QUIK. Все остальные параметры передаются как опциональные в виде таблицы в функции.

QuickDataManager:_loadData(param, optional_params). Это основная функция для ленивой загрузки данных. В зависимости от параметра (например, "money", "depo", "portfolio", и т.д.), она делает запросы к соответствующим функциям QUIK. Функция также проверяет, есть ли уже кэшированные данные для этого параметра, и если они есть — возвращает их. Если данных нет, выполняется запрос и кэшируются результаты? Здесь основной вопрос как правильно организовать работу?

QuickDataManager:__index(key). Метатаблица __index отвечает за доступ к данным через ключи, такие как money, depo, portfolio и другие. Для каждого ключа вызывается соответствующая функция ленивой загрузки, которая получает необходимые данные и кэширует их.

Параметры (например, tag, currcode, limit_kind, sec_code и другие) передаются через опциональные параметры, что позволяет адаптировать запросы под различные нужды и сохранить гибкость подхода.

Пример использования. При первом обращении к данным (manager.money, manager.depo, manager.portfolio, и т.д.) данные будут загружены, затем они будут кэшироваться для последующего использования без лишних запросов к системе. Что позволяет уменьшить нагрузку на систему и ускорить последующие операции. Как альтернатива. Если нужно избежать повторного получения одинаковых данных, можно добавить механизм для "очистки" кэша по истечении времени или по запросу.
Страницы: 1 2 3 4 5 6 7 8 9 10 11 ... 27 След.
Наверх