Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 15.06.2023
20.01.2026 16:17:17
Цитата
VPM написал: Конечно невозможно поучить во встроенных индикаторах
Упёрся ровно в ключевое ограничение QUIK, и если решить его правильно — дальше всё встанет на свои места, очень чисто. Продлема: -> QUIK НЕ даёт напрямую получить параметры class_code и sec_code из легенды графика. -> Легенда — это "UI-строка", не идентификатор инструмента. Но не обходное решение нашлось, и оно рабочее. Задача. Нужна универсальная функция (алгоритм) утверждающая "это мой инструмент", должна быть безопасна при переключении графиков.
Это как раз типичный "quik-овский" момент, отвечающий принципу их "Ни чего не знаю, ни за что не отвечаю". Но все же он решается, довольно аккуратно и надёжно, "без костылей".
Важно. Нельзя здесь конечно ни чего утверждать однозначно. Так как строится данный алгоритм на гипотезе утверждающей: "Легенда графика всегда содержит short_name, но с хвостом вида: " [Price]" / " [Volume]" / " [ATR]" и т.п.". Есть просто надежда, что еще какое то время, она просуществует, но ведь существовала же до сих пор. Возможно это очередной "велосипед", и кто то решал уже подобную задачу, но я ни чего не нашел, поэтому будет "Трехколесный".
Ниже — по порядку.
Что у нас есть? SecurityInfo.short_name = "Сургнфгз-п" legenda = "Сургнфгз-п [Price]"
Правильная логика сравнения. Нужно убрать всё после '[' и сравнить "чистые" строки.
if short_name == legend_clean then -- это нужный график end
Это единственный надёжный путь. Стратегия - обратное сопоставление: legend -> short_name -> sec_code + class_code То есть: 1. Берём legend 2. Извлекаем short_name 3. Ищем инструмент, у которого SecurityInfo.short_name совпадает 4. Запоминаем class_code + sec_code
ВАЖНО: коллизии short_name. Это реальная проблема: * GAZP (акции) * GAZP-12.25 (фьючерс) Как защититься (думаю), хранить список, а не один элемент.
Это значит, что мы можем построить полностью автоматическую библиотеку инструментов:
getClassesList() v getClassInfo(class) v getClassSecurities(class) v getSecurityInfo(class, sec)
И уже по легенде графика восстанавливать: legend > short_name > sec_code + class_code.
Извечный вопрос: повторные вызовы OnTrade, Даже при заявке на одну акцию
Какие скоростные алгоритмы? Когда есть ограничение архитектуры QUIK. Факторами возможных задержек в нем являются <Реализация скрипта> -> <Реализация QUIK> -> <Используемая аппаратура ПК> -> <Канал связи с брокером> -> <Сервер брокера> -> -> <Канал связи брокера с биржей> -> <Биржа>.
Я не очень понимаю, что Вы хотите донести, и о чем спорите? И при этой архитектуре можно строить торговлю спредом, с выставление огромного количества ордеров, а следовательно нужна обработка как ордеров так и сделок. Например, мой алгоритм оставленный мной без присмотра, поймал какую то ошибку (уже и не припомню причину) наделал столько заявок, что брокер заблокировал канал, а затем выставил штраф. Это я к тому что все возможно!
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 15.06.2023
10.01.2026 15:12:17
"А ларчик просто открывался!"
При описанным выше подходе "разделения ответственности", элегантно решаемся еще одна наедающая покоя задача. А именно передача параметра sec_coda из индикатора в луа скрипт. Конечно невозможно поучить во встроенных индикаторах, но всегда можно повторить его в луа, получить параметр и передать, как показано выше в моем примере.
Извечный вопрос: повторные вызовы OnTrade, Даже при заявке на одну акцию
Пользователь
Сообщений: Регистрация: 15.06.2023
10.01.2026 13:45:20
Добрый день TGB, то что Вы описываете в определённых стратегиях конечно надежней, но задача далеко не тривиальна, особенно в скоростных алгоритмах. Да и автор вопроса применяет событийный подход. А вопрос звучит так:
Цитата
User12501 написал: Речь о том, как проигнорировать бесполезный вызов и не посчитать дважды то, что нужно? Например если в момент OnTrade мне нужно знать общее количество оставшихся акций, стандартные get-функции не работают (спрашивал об этом вот здесь: ). Значит нужно вводить отдельную переменную - количество акций, и при каждом OnTrade обновлять. Но тогда при повторном OnTrade происходит повторное обновление, и пожалуйста - ошибка.
Плюс учет различных комиссий в принятии решений, насколько помню точность в учете QUIK до шестого знака. Как же тут не сверять свою вторую бухгалтерию?
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 15.06.2023
09.01.2026 19:12:45
Концептуально, такую архитектуру можно свести к последовательным шагам взросления системы, в стиле боевого QUIK-safe. Важных, самостоятельных 4 - логических слоя, как в профессиональных торговых платформах:
ШАГ 1. Цель QUIK-safe. Приведение индикатора к QUIK-safe стилю, для QUIK это будет означать: 1. никаких глобальных переменных; 2. никаких "висящих" состояний; 3. чёткий lifecycle: "init -> bar -> return"; 4. "индикатор не знает про торговлю, только сигналы".
1.1. Новая контрактация индикатора (правильный подход). "Индикатор = детектор структуры рынка, не стратегии". Он должен: * принимать index, settings, datasourсe; * хранить локальный state; * возвращать расчетные значения (для индикатора только линии).
ШАГ 2. Встраивание в SignalEngine. Теперь "SignalEngine — мозг, индикатор — сенсор".
2.2. Использование данных от индикатора (и это уже по взрослому).
Код
function SignalEngine:updateFromBreakout(buy, sell, support, resistance, volRatio)
local factor = {}
-- Фактор направления
factor.breakout =
buy and 1 or
sell and -1 or
0
-- Фактор структуры
factor.structure =
support and 0.5 or
resistance and -0.5 or
0
-- Фактор волатильности
factor.volatility = clamp((volRatio or 0) - 1, -1, 1)
self.factors.breakout = factor
end
ШАГ 3. Indicator / TradingCore (разделение ответственности). Правило №1. "Индикатор не принимает решений".
local Trader = {}
function Trader:process(signalScore, regime)
if regime == "flat" then return end
if signalScore > 0.7 then
self:buy()
elseif signalScore < -0.7 then
self:sell()
end
end
ШАГ 4. Auto-Regime + фильтры.
4.1. Определение режима.
Код
function SignalEngine:detectRegime(vol, adx)
if vol < 0.7 and adx < 15 then
return "flat"
elseif adx > 25 then
return "trend"
else
return "transition"
end
end
function SignalEngine:filterFactorsByRegime(regime)
if regime == "flat" then
self.factors.breakout.breakout = 0
elseif regime == "transition" then
self.factors.breakout.breakout = 0.5
end
end
-- 4.3. Финальный Score
Код
function SignalEngine:calcScore()
local score = 0
for _, f in pairs(self.factors) do
score = score + (f.breakout or 0) + (f.structure or 0)
end
self.score = clamp(score, -1, 1)
return self.score
end
И ни какой магии, типа машинного обучения или нейросетей! А главное безопасное изменение и замена модулей. Хочется думать так, а жизнь покажет, что опять не учитываю.
Извечный вопрос: повторные вызовы OnTrade, Даже при заявке на одну акцию
Пользователь
Сообщений: Регистрация: 15.06.2023
09.01.2026 15:55:59
Привел Вам просто базовую свою заготовку, в качестве примера не более. Если вы пишите на луа 5.4, то нужно отказаться от bit.band в пользу продвинутого метода. Что там точно за комиссии, подсказать тоже не могу так как на каждом рынке есть особенности. Для Фондового API QUIK предлагает предварительный расчет через стандартную функцию. Для оценки можно ее воспользоваться. На срочном есть зависимость от гарантийного обеспечения и курсов ... Что касается моего подхода, то я применяю подход Ральфа Винса, а именно, торговый капитал делю изначально на две части: пассивный и активный. Так как в процессе торговле всегда присутствует пассивная часть, нет необходимости вести четкий учет комиссий, сверяю по клирингу. Здесь более важен учет количества и цены, так как на прямую влияют на управление позицией.
Извечный вопрос: повторные вызовы OnTrade, Даже при заявке на одну акцию
Пользователь
Сообщений: Регистрация: 15.06.2023
09.01.2026 15:29:03
User12501, И это еще не вся проблематика, ведь нужно данные периодически синхронизировать с данными QUIK.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 15.06.2023
09.01.2026 14:50:56
Nikolay, Вы подняли очень важную проблему "вопрос консистентности данных", все мы сталкиваемся, так как повлиять на ситуацию целиком мы не можем, но должны учитывать эти особенности, должны применять какие то инженерные подходы в обеспечении безопасности. На мой взгляд проблема слишком большая, и требует отдельного обсуждения, может даже выноса в отдельную ветку (если еще не вынесена).
Но давайте по порядку.
Цитата
Nikolay написал: Вы забыли данные из других источников.
Я их умышленно обошел, и задачу свел к получению исторических данных из QUIK, предполагая что они уже есть, и показу единообразия в подходах. Запись в файл и чтения из него, здесь сводится к единой структуре данных. По сути заданию некоего индекса.
Расчет local breakout = f( index, Settings ) , если не нежны графики? выводим в скрипте f( index, Settings, ds ). По сути сменили источник с сохранением архитектуры, ровно то что Вы описали выше. Давно уже задался задачей сохранения архитектуры при изменяемых модулях.
Извечный вопрос: повторные вызовы OnTrade, Даже при заявке на одну акцию
Пользователь
Сообщений: Регистрация: 15.06.2023
09.01.2026 14:25:26
Цитата
User12501 написал: Например если в момент OnTrade мне нужно знать общее количество оставшихся акций, стандартные get-функции не работают
Вы подняли очень важный вопрос. Он касается широкого круга пользователей, и широко обсуждался на форуме и приводились различные боевые подходы. На Ваш вопрос выше, ответ нужно организовывать внутренний учет, не только количества но и других параметров зависящих от конкретной сделки сделки (допустим усреднялись). Вот пример подхода которым, часто пользуюсь на скоростных скриптах:
Код
function OnTrade(trade)
if not WORKING_FLAG then return end
local key = trade.trans_id
local i = tonumber(sdelka[0]);
if working
and key and key>0
and (i==0 and key~=sdelka.id) or (i>0 and sdelka[i][1]~=key)
--and trade.sec_code==symbol --and trade.class_code==class
then
i=i+1;
sdelka[0]=i;
sdelka[i]={};
sdelka[i][0]=sdelka[0];
sdelka[i][1]=trade.trans_id;
sdelka[i][2]=get_date(trade.datetime)
sdelka[i][3]=get_time(trade.datetime)
sdelka[i][4]="B"; if bit.band(trade.flags,4)~=0 then sdelka[i][4]="S"; end;
local dir = sdelka[i][4]=="B" and 1 or sdelka[i][4]=="S" and -1 or 0;
sdelka[i][5]=trade.qty*dir;
sdelka[i][6]=trade.price;
----- comission
sdelka[i][7]=trade.clearing_comission+trade.exchange_comission+trade.tech_center_comission;
sdelka[i][8]=trade.order_num;
sdelka[i][9]=trade.trade_num;
sdelka[i][10]=trade.sec_code;
sdelka.id=trade.trans_id;
Log:info("OnTrade! sdelka "..i .."; "
.."; trans_id="..sdelka[i][1]
.."; "..sdelka[i][2]
.."; "..sdelka[i][3]
.."; "..sdelka[i][4]
.."; "..sdelka[i][5]
.."; "..sdelka[i][6]
.."; comission="..sdelka[i][7]
.."; onum="..sdelka[i][8]
.."; tnum="..sdelka[i][9]
.."; "..sdelka[i][10]
.."\n"
);
--local a,v; for a,v in pairs(sdelka[i) do Log:trace( 'OnTrade! sdelka['..i..']['..tostring(a)..'] = '.. tostring(v) ) end;
end
end;
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 15.06.2023
09.01.2026 12:25:30
Разделение ответственности, на примере создания индикатора. Единый принцип архитектуры торговой системы в QUIK.
Что общего в получении исторической информации в QUIK разными способами. Ответ очевиден - хранение информации в массивах данных и извлечения ее с помощью параметра "index".
1. OnCalculate. Задается на прямую QUIK. 2. getCandlesByIndex. Получаем количество свечей "==" local index = getNumCandles(CFG.tags.price), индекс текущей свечи. 3. CreateDataSource. По факту тоже самое, получаем уже размер массива Size() "== index". Зачем введены разные смыслы, остается загадкой?
Понимание этого, приводит к пониманию принципа построения единой архитектуры для разных источников данных. Принципиальная ИТОГОВАЯ АРХИТЕКТУРА: [ QUIK Chart ] -> [ Indicator/ CandlesByIndex/DataSource] -> [ SignalEngine ] -> [ Regime Filter ] -> [ Trading Core ].
Коротко почему это наиболее правильный подход: * безопасно для QUIK; * расширяемо; * легко диагностировать; * нет переобучения внутри источника (индикатора); * можно менять стратегию без переписывания индикаторов. Пример, индикатор источник данных, перенос ответственности.
Код
local path = getWorkingFolder()
local f;
local save = {
position = 0,
d = 0,
t = 0
}
Settings={}
Settings.Name = "*BreakoutIndicator"
Settings.period = 5
Settings.k = 1
Settings.wid = 0
function Init()
local Cached = dofile(path .. "\\cached.lua");
f = BreakoutIndicator()
Cached=nil
Settings.line = {
{Name = "BUY", Type = TYPE_TRIANGLE_UP, Width = 1, Color = RGB(0, 0, 255) },
{Name = "SELL", Type = TYPE_TRIANGLE_DOWN, Width = 1, Color = RGB(255, 0, 128) },
{Name = "save.upper", Type = TYPE_BAR , Width = 1, Color = RGB(0, 128, 255) },
{Name = "save.lower", Type = TYPE_BAR, Width = 1, Color = RGB(255, 0, 128) },
{Name = "SL", Type =TYPE_DASH, Width = 1, Color = RGB(255, 0, 0) }
}
return #Settings.line
end
function OnCalculate(index)
-- ====== ТЕКУЩИИ ЗНАЧЕНИЯ ======
local position1 = save.position
local d1 = save.d
local t1 = save.t
-- ====== Расчет ЗНАЧЕНИЙ ======
local breakout = f( index, Settings )
-- ====== Обработка ======
local newbar = (breakout and d1 ~= breakout.d or breakout.t ~= t1)
save.position = breakout and breakout.position
save.d = breakout and breakout.d
save.t = breakout and breakout.t
--====== RETURN LINES ======
if Settings.wid == 2 then
return nil,nil,nil,nil, breakout and breakout.volatilityRatio > 1 and breakout.volatilityRatio or nil
end
return breakout and (d1 ~= breakout.d or breakout.t ~= t1) and breakout.position == 1 and breakout.entryLevel or nil, -- BUY
breakout and (d1 ~= breakout.d or breakout.t ~= t1) and breakout.position == -1 and breakout.entryLevel or nil, -- SELL
breakout and breakout.position == 1 and breakout.upperPivot or nil,
breakout and breakout.position == -1 and breakout.lowerPivot or nil,
breakout and breakout.position ~= 0 and breakout.slLevel or nil
end
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 15.06.2023
03.01.2026 16:44:20
Цитата
Nikolay написал: А для получения результата сейчас лучше пойти намного более простым путем.
А чем же он проще? Все модули нужны везде?
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 15.06.2023
03.01.2026 16:31:58
Согласен, картину страшную описали для авто торговли. Думал заменить подход, теперь верну.
Код
----- Получаем цену последней сделки с графика цены
local I = getNumCandles(tag.price)
while I==nil or I==0 do
sleep (100)
I = getNumCandles(tag.price)
end
if I<=4 then toLog(log, 'Недостаточно бар для продолжения работы ' .. tostring(I) ) return end
Вывод. Получение данных сводится к отдельной задаче. Корректность данных можно свести к общим подходам так как данные сводим в таблицы. Так? В реализации подхода рассмотренного мною, без машины состояний вообще не вариант. State Machine - система состояний (FSM), будет отслеживать состояние робота — в состоянии ли он торгов, или ждёт обновлений данных или ждёт сигналов и т.д.
Итог. правильная модель (минимальный фундамент): -> рынок — это функция времени (ввести понятие дискретности "квант времени"), -> стратегия — функция состояния (снимок, срез в заданный момент).
Принципы. 1. Источник истины — время 2. Минимальный ТФ > двигатель времени 3. Остальные ТФ > состояния мира 4. Стратегия никогда не входит в источники данных 5. Индикаторы — просто ещё один Source.
Каркас - итоговый поток:
DataSource v TimeEngine (tick - "квант времени") v WorldState (snapshot - снимок) v Strategy (signal) v SignalFilter v PositionManager v FSM v TradeAdapter v Equity
Каждый слой делает только своё. Попробую реализовать. Не могу сказать что упростил, но "руки чешутся" по пробовать.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 15.06.2023
03.01.2026 15:09:31
Код
-- Безопасное получение значения с графика
function Utils.getGraphValue(tag, line, index, field)
local candles = getCandlesByIndex(tag, line, index, 1)
if not candles or not candles[0] then
return nil
end
return candles[0][field]
end
-- ===============================
-- ДАННЫЕ (DATA LAYER)
-- ===============================
local Data = {}
function Data:init()
self.context = {}
self.history = {}
self.current_index = 0
end
function Data:update()
-- Получаем количество свечей
local num_candles = getNumCandles(CFG.tags.price)
if num_candles < 20 then
Utils.log("WARN", "Недостаточно свечей: " .. num_candles)
return false
end
-- Текущая свеча
local candle = Utils.getGraphValue(CFG.tags.price, 0, num_candles - 1, "close")
if not candle then return false end
self.context = {
-- Цены
bar_index = num_candles - 1,
datetime = Utils.getGraphValue(CFG.tags.price, 0, num_candles - 1, "datetime"),
open = Utils.getGraphValue(CFG.tags.price, 0, num_candles - 1, "open"),
high = Utils.getGraphValue(CFG.tags.price, 0, num_candles - 1, "high"),
low = Utils.getGraphValue(CFG.tags.price, 0, num_candles - 1, "low"),
close = Utils.getGraphValue(CFG.tags.price, 0, num_candles - 1, "close"),
volume = Utils.getGraphValue(CFG.tags.price, 0, num_candles - 1, "volume"),
-- Price Channel
resistance = Utils.getGraphValue(CFG.tags.channel, 0, num_candles - 1, "close"),
middle = Utils.getGraphValue(CFG.tags.channel, 1, num_candles - 1, "close"),
support = Utils.getGraphValue(CFG.tags.channel, 2, num_candles - 1, "close"),
-- Decycler
decycler_high = Utils.getGraphValue(CFG.tags.decycler, 0, num_candles - 1, "close"),
decycler_low = Utils.getGraphValue(CFG.tags.decycler, 1, num_candles - 1, "close"),
decycler_high_prev = Utils.getGraphValue(CFG.tags.decycler, 0, num_candles - 2, "close"),
-- RSI
rsi = Utils.getGraphValue(CFG.tags.rsi, 0, num_candles - 1, "close"),
-- ADX
adx = Utils.getGraphValue(CFG.tags.adx, 0, num_candles - 1, "close"),
plus_di = Utils.getGraphValue(CFG.tags.adx, 1, num_candles - 1, "close"),
minus_di = Utils.getGraphValue(CFG.tags.adx, 2, num_candles - 1, "close"),
-- ATR
atr = Utils.getGraphValue(CFG.tags.atr, 0, num_candles - 1, "close")
}
-- Проверка данных
if not self.context.resistance or not self.context.middle or not self.context.support then
Utils.log("ERROR", "Не удалось получить данные Price Channel")
return false
end
-- Расчет процента ATR
if self.context.atr and self.context.close then
self.context.atr_pct = (self.context.atr / self.context.close) * 100
else
self.context.atr_pct = 0
end
-- Сохраняем в историю
table.insert(self.history, {
index = self.context.bar_index,
datetime = self.context.datetime,
open = self.context.open,
high = self.context.high,
low = self.context.low,
close = self.context.close,
data = {
resistance = self.context.resistance,
middle = self.context.middle,
support = self.context.support,
decycler_high = self.context.decycler_high,
decycler_low = self.context.decycler_low,
rsi = self.context.rsi,
adx = self.context.adx,
plus_di = self.context.plus_di,
minus_di = self.context.minus_di,
atr = self.context.atr
}
})
return true
end
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 15.06.2023
03.01.2026 14:59:51
Синхронизация же нужна для режима бэк теста.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 15.06.2023
03.01.2026 14:56:59
Цитата
Nikolay написал: Здесь вопрос в излишней сложности.
Вопрос получения данных обособленный процесс. Если рассматривать 2 способа. getCandlesByIndex возвращает таблицу луа, DataSource возвращает методы получения данных. Два подхода таблица и функция. Мне представляется во втором больше проверок, так как если график отрисован -> таблица уже есть.
Цитата
Nikolay написал: В режиме чтения с графика необходимо реализовать все те же методы синхронизации, заказа и ожидания данных
Появление данных проверяем в первом проверяем с getNumCandles по факту индекс. Обновилась таблица пересчет все остальных индикаторов. Возможно и здесь коме события нужны состояния и переходы?
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 15.06.2023
03.01.2026 13:44:16
Цитата
Nikolay написал: Легенда - это просто подпись под данными.
Так вот я и подумал, что если со сменой Легенды (или вместо) возвращать параметры class_code, sec_code, решается много задач автоматизации. Или как то их привязать друг к другу.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 15.06.2023
03.01.2026 13:36:27
Цитата
Nikolay написал: Ну если обмен информацией еще не кажется на данном этапе "стоп-сигналом для использования данной "технологии"
Я не вижу здесь противоречий. Заменяя способ получения данных, делаешь все тоже самое в луа, возникает необходимость дописывать алгоритмы уже в самом луа, в место получения их графика. А здесь уже компетенции играют роль. За частую наделаю ошибок и всю хорошею (ну как минимум не проверенную) заброшу.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 15.06.2023
03.01.2026 13:26:35
Цитата
Nikolay написал: Но т.к. Вы решили пойти сложным путем, и использовать зачем-то связанные окна
Идея проста. Инвестиционный портфель (МЕСЯЧНЫЙ ТАЙМ ФРЕЙМ) , Среднесрочный портфель (НЕДЕЛЬНЫЙ ТАЙМ ФРЕЙМ) . На них удобен этот подход. Редкие запросы.
Цитата
VPM написал: QUIK сам делает тяжёлую работу. Lua только читает результат.
Получаем всю картинку в виде метрик по инструменту в таблице луа + визуализации на графике, видно весь контекст. Для ручного управления подходит. А вот дальнейшия автоматизация требует дополнительных параметров. Если рассуждать про торговый робот то и событийная модель не проходит, нужно в водить машину состояний. Да и Вами ранее описанный асинхронный подход (Dispatch) не будет лишним, а красиво ляжет. При этом получаем робот на один инструмент, с просты переходом на любой другой. Делая различные контуры управления, можно достигать любой необходимой сложности?
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 15.06.2023
03.01.2026 13:06:40
Не совсем понял:
Цитата
Nikolay написал: Но тут же возникает вопрос - а может еще сложнее сделать... И это при существующем решении полностью независящим от графиков, интерфейса, случайных действий пользователя с графиком, особенностей запуска Квика и т.д.
Мои рассуждения просты. Одним из параметров возвращаемых ф. getCandlesByIndex является легенда (подпись) графика. Что это за подпись в справке умалчивается? По ней фиксирую смену инструмента. Здесь возникает вопрос, а можно ли по ней восстанавливать параметры class_code, sec_code? Так как они ключ к получению остальной информации по инструменту. Вариант 2. На графике в режиме индикатор можем получить, но возникает вопрос как простым способом передать в луа?
Цитата
nikolz написал: local t=getDataSourceInfo(); int=t.interval; clas=t.class_code; sec=t.sec_code;
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 15.06.2023
03.01.2026 11:24:27
С Новым годом!
Цитата
nikolz написал: Если это не то, то расскажите на примере, что Вы хотите.
Так выше все описано. Раньше здесь предлагались dll от разных авторов, но дума и на чистом луа должно быть решение.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 15.06.2023
30.12.2025 18:21:36
nikolz, Да я умею читать справку. Речь идет о передаче из графика в луа? Есть график где исполняются в QUIK разные индикаторы и формируются свечи, но чтобы привести цену к необходимому формату нужны class_code и sec_code, а с графика получаем легенду графика, если б приходил sec_code, то все остальные торговые параметры можно было бы восстанавливать (получать) по нему. А по факту задал tag графику получил все остальные метрики в том числе и торговые.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 15.06.2023
30.12.2025 14:41:42
Определенное не удобство в этом подходе, вызывает от факт что нельзя вернуть с class_code и sec_code? То факт что возвращается легенда графика, мало чем помогает в автоматизации подхода.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 15.06.2023
30.12.2025 13:41:22
Цитата
Nikolay написал: Все же мне сложно понять зачем выбирать чтение с медленного графика, когда есть инструмент для получения данных без каких либо ручных манипуляций.
Все дело в компетенции. Подход с запахом "нафталина", напомнил времена, когда информация передавалась на дискетах, а вместо монитора зачастую использовали телевизор. А под DOS за несколько минут можно было собрать не большое приложение, да еще работающее.
Вот и это подход позволяет за не большой промежуток времени собрать целые стратегии. Да он отправляет к истокам самого QUIK, но мне представилось, что его не забросили разработчики и что то подкрутили. По крайней мере у меня такое чувство сложилось от применения. Если отбросить мой контур управления из луа кода в виде модулей, то подход с правилами описанными выше стоит 100 - 300 кБ. Но главное это время от идеи до воплощения в терминале!
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 15.06.2023
30.12.2025 12:55:41
Цитата
nikolz написал: В таком случае можно сделать просто бесконечный цикл и выход по break
Этот мой пример вообще на "помойку" нужно выбросить, что и сделаем.
Получить номер свечи-фрактала
Пользователь
Сообщений: Регистрация: 15.06.2023
28.12.2025 21:14:09
Сергей, Если Вы про скрипт выше FRACTALS, то он написан для использования в 2 подходах: main и OnCalculate. Для использования в OnCalculate ds не нужен. Для варианта с main его нужно определить и передать в расчеты. Этот подход реализован функцией Value, а именно строками: Out = (O and O(I)) or (ds and ds:O(I)), так как O(I) определенна в OnCalculate следовательно будет возвращать значение. В случае с main нужно определять ds и получать значения через метод. Здесь много примеров как это делается для обоих вариантов.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 15.06.2023
28.12.2025 19:50:11
Оказывается, QUIK гарантирует, если время последней свечи изменилось — свеча закрыта! Тогда определяется ключевой элемент "детектор НОВОЙ СВЕЧИ". Важно, торговые решения применяем, только после закрытия свечи, торговля внутри незакрытой свечи Запрещена! Следящее правило, работать с 2–3 последними свечами, отсчет ведется от текущей не закрытой свечи. Еще одно правило, так как QUIK не гарантирует синхронность и свеча может закрыться с задержкой, правильно: сравнение datetime свечи. Правило уже озвучено зафиксируем, график = результат, Lua только читает.
local Graph = {}
function Graph.new(tag, line)
local o = {}
o.tag = tag
o.line = line or 0
function o:last()
for i = 0, 50000 do
local _, n = getCandlesByIndex(o.tag, o.line, i, 1)
if n == 0 then
local t = getCandlesByIndex(o.tag, o.line, i - 1, 1)
return t and t[1] or nil
end
end
end
return o
end
return Graph
Ну и пример того что получилось:
Код
local Graph = require("Graph")
local NewBar = require("NewBar")
local Trade = require("Trade")
local is_run = true
function main()
local price = Graph.new("graph_SBER", 0)
local ma20 = Graph.new("graph_SBER", 1)
local ma50 = Graph.new("graph_SBER", 2)
local bar = NewBar.new("graph_SBER")
while is_run do
if bar:check() then
local p = price:last()
local m20 = ma20:last()
local m50 = ma50:last()
if p and m20 and m50 then
if p.close > m20.close and m20.close > m50.close then
Trade.buy()
elseif p.close < m20.close and m20.close < m50.close then
Trade.sell()
end
end
end
sleep(200)
end
end
function OnStop()
is_run = false
end
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 15.06.2023
28.12.2025 19:11:00
Обоснуем подход не как “универсальный”, а как узкоспециализированный адаптер под индикаторный график. Если сделать его правильно, getCandlesByIndex —оказывается очень удобный и надёжный источник для робота, торгующего одним инструментом на одном графике. Когда getCandlesByIndex — правильный выбор. Подходит ИДЕАЛЬНО, если:
индикаторы уже построены в QUIK,
сигналы зависят от: пользовательских индикаторов,
стратегия реагирует на закрытие свечи.
То есть: график = источник истины! Подход реально надёжен и это важно понимать, понимая что делает QUIK:
индикаторы считаются C++-кодом QUIK,
график уже агрегирован
все пересчёты завершены ДО вызова Lua
Следовательно, нет рассинхронизации, нет “ещё не досчиталось”, нет гонок. Скрипт читает готовый результат, а не поток данных. QUIK сам делает тяжёлую работу. Lua только читает результат.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 15.06.2023
28.12.2025 18:19:41
О чудеса чудесные! Вот какой вывод могу сделать, после всех моих изысканий. Формула QUIK - нативного кода. Если свести всё к одному правилу:
"Пиши Lua так, как будто это C-обёртка над QUIK API"
явные функции.
минимум таблиц.
минимум косвенности.
предсказуемый жизненный цикл.
Поэтому версия без метатаблиц — QUIK - нативная! Да уж, до экспериментировал. Где то это уже видел?
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 15.06.2023
28.12.2025 17:53:11
Цитата
Nikolay написал: Более важен вопрос - а надо ли это делать.
С моей точки зрения "универсальность" - это прагматичный подход даёт нам гибкость, когда она нужна, и не мешает, когда не нужна. Один раз создав модуль, забываем про него, и пользуемся повсеместно. То что Вы описываете, получается подход не "универсальный источник", а универсальный такой контейнер-декоратор, и это ключевое отличие. Нет таймеров, подписок, событий — всё по запросу? В QUIK это будет снижать риск зависаний и утечек?
Главным критерием достоинством подхода, должен быть лозунг "не бороться с QUIK, а работаешь в рамках его реальности".
На сколько оправдано, пока для меня не понятно, много лишнего кода, пробую упростить без лишней магии и версия без метатаблиц вообще?
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 15.06.2023
28.12.2025 16:17:03
nikolz, Выше описанному мной подходу, ну так с десяток лет! Код просто поднял, накидал нужных мне индикаторов и все работает. Работает в режиме советника, тестирования, торговли. Попробуйте проделать с Вашим решение все это? Что касается меня, не применяю ни чего кроме луа и квик, даже dll отметаю. Причина здесь банально, в мире где все изменяется стремительно, а время выступает основным фактором, сторонние приложении требуют отдельной поддержки и затрат времени на их поддержание и разбирательство с ними. Вторым фактором, является достижение надежности в автоматических системах.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 15.06.2023
28.12.2025 15:58:01
Идея объединить все эти источники под единый интерфейс на первый взгляд очень хороша и удобна, поскольку позволяет работать с данными с разных источников одинаково. Но, учитывая особенности Квик, а именно отсутствие синхронизации данных, не известно что и когда получишь, страшно выкладывать получившийся класс.
Посмотрим асинхронный подход ранее здесь обсуждаемый, может там что то по проще проявится?
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 15.06.2023
28.12.2025 15:28:54
Подход, разделяем получение данных и их обработку.
Задача на получение данных создает источник и регистрирует его в менеджере.
Задачи на обработку данных берут источник из менеджера и работают с ним через единый интерфейс.
За основу таблицы-прототипа для представления данных в едином виде, напрашивается подход реализованный CreateDataSource - "Функция предназначена для создания таблицы Lua и позволяет работать со свечками". То есть по индексу свечи возвращать соответствующее значение?
Получить номер свечи-фрактала
Пользователь
Сообщений: Регистрация: 15.06.2023
28.12.2025 15:06:06
Сергей, Смотрите в справке функцию CreateDataSource - Функция предназначена для создания таблицы Lua и позволяет работать со свечками, полученными с сервера QUIK, а также реагировать на их изменение.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 15.06.2023
28.12.2025 13:26:48
Следовательно задачу: "Логика Обработки Данных из Интерфейса"?
Создадим класс (в Lua — таблицу-прототип) для представления данных в едином виде.
Логика обработки данных будет работать с этим единым классом, независимо от источника.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 15.06.2023
28.12.2025 13:04:28
Nikolay, про существующие недостатки данного подхода получения данных (getCandlesByIndex), Вы все правильно говорите. К Вашим замечаниям лишь добавлю, что ошибки в коде при использовании этого подхода, часто приводят к вылету (падению) самого терминала. Для меня это была основная причина по которой его не применял.
Но у метода есть и положительные стороны для его использования, часть из которых уже назвали, просто зафиксируем:
1. Простота реализации идей. 2. Быстрота реализации целых стратегий и идей. 3. Наглядность, легкая отрисовка результатов на графике, поддержка множественности линий. 4. Легко тестировать стратегии, легко менять целиком парадигмы (1 ТФ так вообще без вопросов). 5. Минимальная подготовка в знаниях языка, при этом можно строить целые торговые роботы.
Минимум времени затраченного от идеи до ее реализации и получению результатов! Это пожалуй ключевые моменты для применения подхода в своих скриптах.
О применении подхода: 1 инструмент, к нему графики необходимых тайм фреймов + режим связанных окон, не нужно хранить 30 графиков. Да не немного инженерии требуется, при определении смены инструмента, но это совсем просто, и это, все та же техническая задача получения данных.
Почему портфель причем. Этим же подходом, проходим по портфелю, переключаемся в терминале на режим связанных окон от таблицы "Состояния Портфеля", и проверяем идеи на портфеле. Да это полуавтомат, так ведь и нежено на этом этапе целиком автоматизировать процесс, достаточно устанавливать в скрипте режим работы.
Согласен, логика обработки данных из интерфейса должна быть единой, но еще нужна надежность, нужна простота получения данных. А у нас то "дырка", то "нил" получаем? Если сюда добавить что сервер отдан на откуп брокеру, с их "специалистами".
Тогда получается что можно этот единый подход? Подход "Логика Обработки Данных из Интерфейса"?
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Да собственно это и есть у меня основное затруднение. Все работает в предварительных версиях, но как гляну на код данного подхода, руки опускаются. Все работает, но как правильно сделать не понимаю?
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 15.06.2023
27.12.2025 11:19:14
Цитата
Nikolay написал: А т.к один график - один инструмент, то, спрашивается, где же взять данные.
График для каждого ТФ. (свой tag) для одного тикера. Так как я не представляю портфель с 1000 тикеров, такой просто будет ломать мой риск менеджмент (а он еще участвует в расчёте количества в удерживаемой позиции). То задачу сканирования 1000 тикеров вижу только для предварительного отбора инструментов. Ну или как ранее здесь предлагалось, ждать какой "стрельнет". Но это все не про эффективность использования капитала. Вывод, только ликвидные, фундаментально подтвержденные инструменты. А их на нашем рынке раз два и обчёлся. А пробежаться глазами раз в недельку по рынку и портфелю, очень полезно, мне так просто необходимо.
Дело здесь вот еще в чем, подход Score - позволяет оценивать качество самого сигнала, это уже не просто данные индикаторов, это класс сигнала, определяющий качество + количество принятия торгового решения. Что позволяет перейти от подхода написания "торгового робота", к уровню проп-деск-алгоритма, а не просто сканирования розничных индикаторов, и полной автоматизации самого процесса торговли. Также это один из путей быстрого бек теста в квик, правда здесь возникает другая проблема, синхронизации данных.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 15.06.2023
27.12.2025 09:55:56
Цитата
Nikolay написал: Если думаете, что getCandlesByIndex не требует ожидания и проверки, что данные есть, то ошибаетесь. Точно также требует. Да, если скрипт запускается уже после того как терминал загрузился и "прогрелся", то можно ожидать, что данные уже есть. Но полностью исключает вариант работы скрипта "не выключаясь". А с таким числом требуемых графиков, терминал будет стартовать долго.
Делаю так:
Код
----- Получаем цену последней сделки с графика цены
local I = getNumCandles(tag.price)
while I==nil or I==0 do
sleep (100)
I = getNumCandles(tag.price)
end
if I<=4 then toLog(log, 'Недостаточно бар для продолжения работы ' .. tostring(I) ) return end
local newber = I > I1 I1=I
local I = getNumCandles(tag.price) - это ведь по сути индекс, но и количество полученных свечей.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 15.06.2023
27.12.2025 09:48:58
Цитата
Nikolay написал: Плюс удобство работы вызывает сомнения, т.к. чтобы эта конструкция работала необходимо держать открытыми графики. У меня скрипты могут сканировать до 1000 инструментов на разных ТФ - предлагаете все это открывать, наносить индикаторы. Терминал умрет первым.
Конечно нет ни какой необходимости открывать 1000 графиков. Для одного инструмента создаются графики нужных нам ТФ. Удобство использования достигается с помощью режима "связанных окон". Такой режим можно установить для таблицы 1. Таблица Текущих Торгов (ТТТ) 2. Состояния счета. * В варианте 1. отвечает на вопрос, что происходит на рынке? * В варианте 2. что происходит в собственном портфеле? +Такого подхода, высокая визуализация мульти ТФ. Если для ТФ Месячный, Недельный нужны только свечные паттерны, то для внутри дневных использую индикаторы и фильтры. И все это сразу видно как в целом для рынка так и для портфеля. Задача основная стояла рефакторинг портфеля ИНВЕСТИЦИОНОГО, и среднесрочная торговля акциями. И такой подход оказался очень удобным и наглядным для принятия решений. Для роботизации применил расчеты (детектор сигналов), которые пока вывожу в таблицу, а можно и на график:
Код
Эталонная структура сигнала
Signal = {
dir = "BUY" | "SELL" | "NONE",
score = 0..100,
class = "A" | "B" | "C" | "NONE",
regime = "TREND" | "RANGE" | "TRANSITION" | "VOLATILE",
rr = number,
}
-- Принцип:
1. Определяем Regime;
2. Считаем SignalScore;
3. Проверяем Risk/Reward;
4. Только потом -> торговое решение.
Принцип здесь такой: 1. Определяем Regime в котором будем торговать (принимать решения) 2. Считаем SignalScore 3. Проверяем Risk/Reward 4. Только потом > торговое решение.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 15.06.2023
26.12.2025 16:40:26
А насчет
Цитата
Nikolay написал: Это потенциально бесконечный цикл. Достаточно ошибиться в таге источника.
Он просто не войдет в цикл проверки. Да и в коде их наличие необходимо проверять: "if tag.decycler then", так как без них вообще все бессмысленно.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 15.06.2023
26.12.2025 16:33:23
Но ведь есть принципиальное отличие, и оно накладывает свой отпечаток на проверки. Если в CreateDataSource получаем только интерфейс на получение данных и ждем загрузку с сервера тех самых данных. То в этом подходе можем допустить даже return. В варианте с getCandlesByIndex читаем свечи уже загруженные в терминал, и все что беспокоит это "дыры" в данных?
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 15.06.2023
26.12.2025 15:09:15
Добрый день Nikolay, но в моем варианте думаю отрисовка меток, вариант еще проблематичной. А этот в режиме ADVISER такой эксперт, в режиме связанных окон корректно переходит с с инструмента на инструмент. Да с задержками но в мое случае приемлемо. Начинаю читать с месячного тф. и заканчивает или 15 или 5 минутными свечами. Смущает Вот такая запись?
Код
local bar_cur1 = getCandlesByIndex(tag.price,0,I-1,1)[0]
while not bar_cur1 or bar_cur1==nil do
sleep (100);
I = getNumCandles(tag.price);
bar_cur1 = getCandlesByIndex(tag.price,0,I-1,1)[0];
end
А именно цикл проверки и ожидания?
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 15.06.2023
26.12.2025 14:13:58
«Всё новое — хорошо забытое старое».
Вопросы нормализации, нормировки, калибровки данных, в системах автоматической поддержки принятия решений, далеко не тривиальны, и заслуживают отдельного обстоятельного обсуждения. А подход самонормировки, вообще уникален.
Разбираясь с рядом вопросов мне потребовалось визуализировать проверку своих идей. Для проверки этих идей, нужен скрипт легко переписываемый и способный обрисовывать множество линий на графике. В моем случае 76 линий и получение данных в режиме мультитаймфрема.
Из за сложности редактирования кода, все мои скрипты не подходили. Вспомнил про старые сохранённые работы, от группы "Универ". Основная идея у ребят, была делать простые торговые роботы, доступные для понимания с минимальной подготовкой в области программирования и знаний луа.
Один из таких я взял за основу. Источником рыночных данных выступает функция getCandlesByIndex. Здесь все вроде бы просто, определяем идентификатор графику и читаем любые данные с графиков. Таким подходом давно не пользовался, более того избегал его, а причина заключалась в способности скрипта обрушить целиком весь терминал. Квик просто падал.
Каково же было мое удивление, когда набросав с десяток индикаторов (в том числе и самописных), получив с них данные и еще с десяток тайфреймов получив свечи, что это все это аккуратно работает!
Здесь нужно помнить что такой подход - это работа в потоке самого терминала, и минимальная нагрузка на него сильно удивила? Вторая особенность этого подхода, в полученных данных могут быть "дыры", это накладывает особую аккуратность на обработку данных. В моем варианте кода терминал падал лишь при новых загрузках. Проблема решилась добавлением циклов ожидания получения данных. Но вопросики остались!
Основной из них, функция getCandlesByIndex предоставляет возможность, получить массив из таблиц данных из свечей, либо таблицу одной свечи, что здесь оптимальной и надежей? * Первый уменьшает количество обращений к терминалу, следовательно уменьшает нагрузку. * Второй безопасней исключает "дыры".
Ну и главное как корректно ожидать получение свечей, возможно вообще пропускать "дыры"? Я выбрал как предложили ребята из "Универ", пока работает корректно. Но вопросики остались?
Состояние счета, Таблица Состояние счета
Пользователь
Сообщений: Регистрация: 15.06.2023
28.11.2025 10:43:41
Извините ввел в заблуждение. Сам путаюсь, это один из шедевров, уж не знаю от разработчиков или с биржи, им делить лавры.
Руководство пользователя. -> Раздел 3. Просмотр информации -> Состояние счета -> Позиции: "
Свободно
Доступно для вывода средств при сохранении обеспеченности позиций либо открытия позиций по немаржинальным активам, с учетом заблокированных средств под активные заявки, с точностью валюты цены инструмента. Соответствует значению параметра «НаПокупкуНеМаржин» в таблице «Клиентский портфель». Для срочного рынка соответствует значению параметра «План. чист. поз.» в таблице «Ограничения по клиентским счетам»
"
Состояние счета, Таблица Состояние счета
Пользователь
Сообщений: Регистрация: 15.06.2023
28.11.2025 10:22:14
Ни как! Надо рассчитывать, в справке есть формула.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 15.06.2023
28.11.2025 09:49:00
Конечно это не рабочий скрипт, это просто проверка идеи, идеи возможной адаптации. Инженерия кода страдает, но каково, за пол часа от идеи до первых тестов. В SciTe запускаем, подставляем разные массивы и проверяем (просто и дешево), методы все широко описаны. Кстати ранее для проверок идей подключал "gnuplot" к рыночным данным, наглядно получается, давно не пользовался. Поисковики сегодня свели для задач раздачи рекламы. Использую несколько браузеров, а Яндекс (гордость отечества) обхожу стороной. Хотя сам тоже предпочитаю поиск.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 15.06.2023
27.11.2025 21:07:17
Для луа 5.3 и 5.4 нужно добавить:
local unpack = table.unpack or unpack;
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 15.06.2023
27.11.2025 21:01:31
Сказал - сделал. Предлагаю вниманию (сам не проверял, если есть ошибки пишите). Код в комментариях, думаю и так все понятно, так же там есть ссылка на книгу с примерами на луа, мне в свое время помогла рекомендую. Код немного большой для форума, но не судите строго, выкладываю как есть:
Код
--[[ Как выбораем метод (Памятка)?
Кто уже или еще? не очень дружен со 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), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 15.06.2023
23.11.2025 12:36:13
Безусловно, замечание от 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), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 15.06.2023
22.11.2025 13:19:25
Пару слов про сам код. Вот эта конструкция:
local x = (FSettings.x or nil) local p0 = x or Value(I, v_t, ds) or 0;
Позволяет через таблицу FSettings задавать и передавать любой ранее полученный параметр на обработку (Не только цены).
Например получили массив значений RSI, не понятно что происходит, можно нормализовать, используя AGC и посмотреть что происходит.
Моей же задачей, была нормализация единичного вектора в гиперкубе состояний (мой морской навигатор). Это позволило сглаживать волны и применить аппарат нечеткой логики, на стадии получения вывода. Как лингвистическую переменную (для пользователя), так и математическую (цифровую для алгоритма).