1000 раз уже на форуме говорил "Не программист, и знания мои так себе". Это раз! Форум - это площадка для обсуждений, а не выставления амбиций. Это два!
Теперь что касается последней темы:
1. Не надо "Кусочничить". Я тему веду последовательно, и рассуждения читать нужно также. 2. А Вы то понимаете сами? Пока не создан подход, то и оптимизировать НЕ ЧЕГО, от слова совсем? 3. Ответ на Ваш вопрос. Оптимизация - это КОМПРОМИС. Поменяйте понимание и все встанет по местам. 4. Повторюсь мне не сложно: Подход - Инвестиционный (означает тф. месячный и больше, в квик их нет). Задача - возможность торговать и управлять 1 инструментом так и портфелем (универсальность). Структура - модульная, много разового использования. Интерфейс - наипростейший, понятный бабушке!
Про КПД, чего Вы рассуждаете? Все КПД моего старенького направленно на эффективность торговли = увеличению баланса счета. Тем более что подход описан, и можно воспользоваться функциями без корутин.
И последнее, Вы не сомневайтесь, сомнения нужны на стадии анализа, а когда решение принято, нужно действовать. Попробуйте. Ну или обосновано возражайте.
Пользователь
Сообщений: Регистрация: 30.01.2015
06.11.2025 10:25:03
Цитата
VPM написал: Попурри на тему "Три тополя на Плющихи" в исполнении ... . ::
Зацените на сколько удобен интерфейс конечного пользователя в этом подходе.
Код
Преимущества MARKETDATA_PRO v1.0:
Вы не учитываете тот факт, что только Вы знаете это .
Мне как пользователю непонятно зачем мне это. -------------------------- Слишком.сложно, много букв. Трудно выявлять ошибки. -------------------- Попробуйте не дублировать уже описанное. -------------------- Все общее разместите в начале. Например так:
Код
-- Примеры использования универсальной системы:
market = "TQBR"
ticker = "SBER"
-- Глобальный экземпляр
MDP = MarketData_Pro.Manager:new()
-- 1. УНИВЕРСАЛЬНЫЙ ТЕХНИЧЕСКИЙ АНАЛИЗ ДЛЯ ЛЮБЫХ ДАННЫХ
-- Анализ цены последней сделки
local price_analysis = MDP:getOrCreate{ interval = INTERVAL_H1, param = "last" }
print ( "Цена SMA20:" , price_analysis:sma( 20 ))
print ( "Цена RSI14:" , price_analysis:rsi( 14 ))
-- Анализ стакана (биды)
local bid_analysis = MDP:getOrCreate{ interval = INTERVAL_M5, param = "bid" }
print ( "Биды EMA10:" , bid_analysis:ema( 10 ))
print ( "Биды STDDEV20:" , bid_analysis:getIndicator( "STDDEV" , 20 ))
-- Анализ объема
local volume_analysis = MDP:getOrCreate{ interval = INTERVAL_M15, param = "volume" }
print ( "Объем SMA30:" , volume_analysis:sma( 30 ))
-- 2. КАСТОМНЫЕ ИНДИКАТОРЫ ДЛЯ ЛЮБЫХ ПАРАМЕТРОВ
-- Регистрация индикатора для спреда
MDP:registerIndicator( "SPREAD_EMA" , function (buffer, period)
if buffer.size < period then return nil end
local sum = 0
for i = 1 , period do sum = sum + buffer:last(i).value end
return round(sum / period, 4 )
end , "EMA for Spread" , {"numeric"})
-- Анализ спреда bid/offer
local spread_data = MDP:getOrCreate{ description = "Bid-Offer Spread" }
-- Здесь можно обновлять буфер вручную с вычисленным спредом
spread_data:updateBuffer( "value" , 0.15 ) -- пример спреда
print ( "Спред EMA10:" , spread_data:getIndicator( "SPREAD_EMA" , 10 ))
-- 3. УНИВЕРСАЛЬНЫЙ АНАЛИЗ РАЗНЫХ ТИПОВ ДАННЫХ
local analyses = {
{param = "last" , desc = "Price Analysis" },
{param = "bid" , desc = "Bid Analysis" },
{param = "volume" , desc = "Volume Analysis" },
{param = "value" , desc = "Value Analysis" }
}
for _, analysis in ipairs(analyses) do
local data = MDP:getOrCreate{ ticker = "GAZP" , interval = INTERVAL_D1, param = analysis.param }
local sma = dat a:sma( 20 )
local rsi = dat a:rsi( 14 )
print ( string.format ( "%s - SMA20: %.2f, RSI14: %.1f" , analysis.desc, sma or 0 , rsi or 0 ))
end
-- 4. COMPLEX MULTI-PARAMETER ANALYSIS
interval = INTERVAL_H1
-- Анализ нескольких параметров одновременно
local multi_analysis = function ()
local price = MDP:getOrCreate{ param = "last" }
local volume = MDP:getOrCreate{ param = "volume" }
local bids = MDP:getOrCreate{ param = "bid" }
local price_trend = price:ema( 10 ) > price:ema( 20 )
local volume_spike = volume:sma( 5 ) > volume:sma( 20 ) * 1.5
local bid_strength = bids:ema( 5 ) > bids:ema( 10 )
return price_trend and volume_spike and bid_strength
end
-- 5. DYNAMIC INDICATOR CREATION
-- Создание индикатора на лету
local dynamic_indicator = function ()
MDP:registerIndicator( "VOLUME_PRICE_RATIO" , function (buffer, priceBuffer, period)
if not priceBuffer or buffer.size < period then return nil end
local volume_avg = 0
local price_avg = 0
for i = 1 , period do
local vol_item = buffer:last(i)
local price_item = priceBuffer:last(i)
if vol_item and price_item then
volume_avg = volume_avg + vol_item.value
price_avg = price_avg + price_item.value
end
end
volume_avg = volume_avg / period
price_avg = price_avg / period
return volume_avg / math.max (price_avg, 0.001 )
end , "Volume-Price Ratio" , {"volume"})
end
Универсальная система - это такая система, разработчик которой не имеет представления где и как ее будут применять. ----------------------- Пользователь такой системы не в состоянии понять все, что включил в нее разработчик. ------------------------- В результате реально либо используется 10 процентов возможности такой системы, либо пользователь начинает делать свою - не универсальную.
Пользователь
Сообщений: Регистрация: 15.06.2023
06.11.2025 10:45:08
nikolz, На счет сложности, для меня очень сложно, здесь с Вами не поспоришь. Отсюда бывает и путаница.
Не могу согласиться: "Универсальная система - это такая система, разработчик которой не имеет представления где и как ее будут применять.". На все известно и источники и методы, а использование их на прямую зависит от сложности самой торговой системы. Изначально думал для удобства сделать единый интерфейс рыночных данных, как то само собой добавились индикаторы и вся остальная инфраструктура и все вылилось в целый фреймворк. Конечно нужно тестирование и оптимизация.
"Пользователь такой системы не в состоянии понять все, что включил в нее разработчик." Так ведь и задача стоит, не нужно пользователю начинка, подключил блок и пользуйся понятным простым интерфейсом. Меня "ушатала" постоянная переделка. Задача все таки, удобство получать в торговых подходах, а не упражнения в программировании. Удобно и то что есть алгоритмы которые использует большинство, ATR, StDev, средниеи.
Пользователь
Сообщений: Регистрация: 15.06.2023
06.11.2025 11:09:36
"Едем дальше, видим больше"! На мой взгляд данный подход, нужно распространить на получение "Серверных данных". Для понимания проблематики, архитектуру предлагается использовать общею для фондового и сросного рынков? Задача все та же.
Задача - возможность торговать и управлять 1 инструментом так и портфелем (универсальность), с учетом рисков (как квиковских, так и собственно ручных), ну и конечно одной из основных задач управление позицией. Структура - модульная, много разового использования. Интерфейс - наипростейший, понятный бабушке!
Обобщенно свести квиковские в функции в удобную оболочку:
Функции взаимодействия скрипта Lua и Рабочего места QUIK
getDepoEx - функция для получения позиций по инструментам указанного типа
getMoneyEx - функция для получения информации по денежным позициям указанного типа
getFuturesLimit - функция для получения информации по фьючерсным лимитам
getFuturesHolding - функция для получения информации по фьючерсным позициям
getSecurityInfo - функция для получения информации по инструменту?
getTradeDate - функция для получения даты торговой сессии
CalcBuySell - функция для расчета максимально возможного количества лотов в заявке? (скорее для контроля, уж больно тяжелая?)
getPortfolioInfoEx - функция для получения значений параметров таблицы «Клиентский портфель» с учетом срока расчётов
getBuySellInfoEx - функция для получения параметров (включая срок расчётов) таблицы «Купить/Продать» (Важная для маржинальной торговли!)
Пользователь
Сообщений: Регистрация: 15.06.2023
06.11.2025 14:16:24
Вариант реализации подхода, что скажите?
Код
QuickDataManager = {}
QuickDataManager.__index = QuickDataManager
-- Конструктор класса
function QuickDataManager:new(firmid, client_code)
local obj = setmetatable({}, self)
obj.firmid = firmid
obj.client_code = client_code
obj.data = {} -- Для хранения кэшированных данных
obj.loaded = {} -- Для отслеживания загруженных параметров
return obj
end
-- Функция для ленивой загрузки данных с учетом firmid и client_code
function QuickDataManager:_loadData(param, optional_params)
-- Формируем уникальный ключ для кэширования (с учетом параметров)
local cache_key = param .. "_" .. (optional_params or "")
if self.loaded[cache_key] then
return self.data[cache_key] -- Возвращаем из кэша
end
-- Если данных нет в кэше, загружаем их
local data
if param == "money" then
-- Вызов getMoneyEx для получения информации по деньгам
data = getMoneyEx(self.firmid, self.client_code, optional_params.tag or "", optional_params.currcode or "", optional_params.limit_kind or 0)
elseif param == "depo" then
-- Вызов getDepoEx для получения позиций по инструментам
data = getDepoEx(self.firmid, self.client_code, optional_params.sec_code or "", optional_params.trdaccid or "", optional_params.limit_kind or 0)
elseif param == "portfolio" then
-- Вызов getPortfolioInfoEx для получения информации по клиентскому портфелю
data = getPortfolioInfoEx(self.firmid, self.client_code, optional_params.limit_kind or 0, optional_params.board_tag or "", optional_params.currency or "")
elseif param == "buy_sell" then
-- Вызов getBuySellInfoEx для получения параметров по заявкам
data = getBuySellInfoEx(self.firmid, self.client_code, optional_params.class_code or "", optional_params.sec_code or "", optional_params.price or 0)
elseif param == "futures_limit" then
-- Вызов getFuturesLimit для получения фьючерсных лимитов
data = getFuturesLimit(self.firmid, optional_params.trdaccid or "", optional_params.limit_type or 0, optional_params.currcode or "")
elseif param == "futures_holding" then
-- Вызов getFuturesHolding для получения позиций по фьючерсным счетам
data = getFuturesHolding(self.firmid, optional_params.trdaccid or "", optional_params.sec_code or "", optional_params.type or 0)
end
-- Кэшируем загруженные данные
self.data[cache_key] = data
self.loaded[cache_key] = true
return data or {}
end
-- Доступ к данным с ленивой загрузкой
function QuickDataManager:__index(key)
if key == "money" then
return self:_loadData("money", {tag = "default", currcode = "USD", limit_kind = 0})
elseif key == "depo" then
return self:_loadData("depo", {sec_code = "SBER", trdaccid = "1234", limit_kind = 0})
elseif key == "portfolio" then
return self:_loadData("portfolio", {limit_kind = 0, board_tag = "TQBR", currency = "RUB"})
elseif key == "buy_sell" then
return self:_loadData("buy_sell", {class_code = "TQBR", sec_code = "SBER", price = 1000})
elseif key == "futures_limit" then
return self:_loadData("futures_limit", {trdaccid = "TQBR", limit_type = 0, currcode = "USD"})
elseif key == "futures_holding" then
return self:_loadData("futures_holding", {trdaccid = "1234", sec_code = "SBER", type = 0})
else
-- Загружать другие параметры по необходимости
return self:_loadData(key)
end
end
-- Пример использования
local manager = QuickDataManager:new("Firm1", "Client1")
-- Ленивое обращение к данным
local money = manager.money -- Получение информации по деньгам
local depo = manager.depo -- Получение позиций по инструментам
local portfolio = manager.portfolio -- Получение информации по портфелю
local buy_sell = manager.buy_sell -- Получение информации по заявкам на покупку/продажу