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

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

Страницы: Пред. 1 2 3 4 5 6 7 8 9 10 11 ... 24 След.
Золотыми буквами выбить!
 
Andrey Golik QUIK clients support, своими высказываниями, Вы приоткрываете внутреннею сторону финансового бытия, а главное поясняете фундаментальный закон этого бытия, закон спроса и предложения, так как его понимает компания. Вы уже историческая личность, вошли в историю, конечно еще мало осознания от пользователей, но думаю все впереди! Нужно исправлять, или ....  Вот из другой темы некие  пояснения, автор nikolz, ничего не напоминает?
Цитата
Попробую объяснить почему это не будет сделано.
------------------------
Согласно ФЗ о рынке ЦБ сделки на бирже делает не клиент, а брокер.
QUIK лишь терминал для подачи заявок брокеру. .
Поэтому действительны лишь те сделки , которые есть в отчете брокера.
--------------------  
При этом, если Вы выключили QUIK, то историю сделок Вы не получите,
а брокер, вне зависимости от включения QUIK, обязательно Вам ее передаст согласно ГК РФ.
--------------------
В итоге то, что прислал брокер это и есть Ваши сделки.
------------------  
Если формат не устраивает, то конвертируйте в другой формат.
Это техническая задача на уровне студента.
история сделок, история сделок
 
Ирина Никонова,  Если Вас я правильно понял, Вам нужна история собственных сделок, формат csv наверняка подходит, вот код копируйте запускайте, он создаст историю по всем счетам и будет сохранять  собственные сделки, все что нужно запустить скрипт (утилиту) и забыть, остальное она сделает сама, Ваша задача выгружать в excel нужный файл и анализировать или еще чего. Если попали в точку, меня не нужно благодарить, благодарить нужно автора, возможно даже благотворительность проявлять, и здесь не важно сколько, важно как. От себя ни чего добавить не могу, так как запустил когда то и забыл, думаю что это тот самый вариант автора, судите сами. Взято https://quikluacsharp.ru/.
Код
local Run = nil; -- флаг работы цикла в main
local DataFolder = ''; -- Полный путь к папке "Данные(c)quikluacsharp.ru"
local TradesFiles = {};-- Массив дескрипторов файлов

-- Создает каталоги по всем найденным счетам
function CreateAccountsFolders()
   -- Перебирает все счета
   for i=0, getNumberOf("trade_accounts")-1 do
      -- Получает номер счета
      local Account = getItem("trade_accounts", i).trdaccid;
      -- Получает путь
      local Path = '"'..DataFolder..Account..'\\"';
      -- Если каталог не существует
      if os.execute('cd '..Path) == 1 then
         -- Создает каталог
         os.execute('mkdir '..Path); 
      end;
   end;
end;
-- Проверяет записана ли данная сделка в файл истории
function CheckTradeInFile(trade)
   -- Получает путь к файлу инструмента в папке торгового счета
   local PathAccountSec = DataFolder..trade.account..'\\'..trade.sec_code..'.csv';
   -- Пытается открыть файл текущего инструмента в режиме "чтения"
   local TradesFile = io.open(PathAccountSec,"r");
   -- Если файл не существует, то сделка не записана
   if TradesFile == nil then return false;
   else -- Если файл существует
      -- Получает индекс файла
      local FileIndex = trade.account..'_'..trade.sec_code;
      -- Если файл еще не открыт для дописывания
      if TradesFiles[FileIndex] == nil then
         -- Открывает файл текущего инструмента в режиме "дописывания"
         TradesFiles[FileIndex] = io.open(PathAccountSec,"a+");
      end;
      -- Перебирает строки файла
      local Count = 0; -- Счетчик строк
      for line in TradesFile:lines() do
         Count = Count + 1;
         if Count > 1 and line ~= "" then
            -- Если номера сделок совпадают, то сделка записана
            local i = 0;
            for str in line:gmatch("[^;^\n]+") do
               i = i + 1;
               if i == 3 and tonumber(str) == trade.trade_num then
                  TradesFile:close();
                  return true; 
               end;
            end;
         end;      
      end;
   end;
   TradesFile:close();
   return false;
end;
-- Записывает все ранее не записанные сделки из таблицы "Сделки" в файлы
function CheckAndSaveTerminalTrades()
   local trade = nil;
   -- Перебирает все сделки в таблице "Сделки"
   for i=0,getNumberOf("trades")-1,1 do      
      trade = getItem ("trades", i);
      -- Если данная сделка еще не записана в файл истории
      if not CheckTradeInFile(trade) then        
         -- Добавляет сделку в файл истории
         AddTradeInFile(trade);
      end;
   end;
end;
-- Добавляет новую сделку в файл истории
function AddTradeInFile(trade)
   local DateTime = trade and trade.datetime;
   local Date = tonumber(DateTime.year);
   local month = tostring(DateTime.month);
   if #month == 1 then Date = Date.."0"..month; else Date = Date..month; end;
   local day = tostring(DateTime.day);
   if #day == 1 then Date = Date.."0"..day; else Date = Date..day; end;
   Date = tonumber(Date);
   local Time = "";
   local hour = tostring(DateTime.hour);
   if #hour == 1 then Time = Time.."0"..hour; else Time = Time..hour; end;
   local minute = tostring(DateTime.min);
   if #minute == 1 then Time = Time.."0"..minute; else Time = Time..minute; end;
   local sec = tostring(DateTime.sec);
   if #sec == 1 then Time = Time.."0"..sec; else Time = Time..sec; end;
   Time = tonumber(Time);
   -- Если ночная сделка, смещает дату на 1 день вперед
   if Time < 90000 then
      local seconds = os.time(DateTime);
      seconds = seconds + 24*60*60;
      DateTime = os.date("*t",seconds);
      Date = tonumber(DateTime.year);
      month = tostring(DateTime.month);
      if #month == 1 then Date = Date.."0"..month; else Date = Date..month; end;
      day = tostring(DateTime.day);
      if #day == 1 then Date = Date.."0"..day; else Date = Date..day; end;
      Date = tonumber(Date);
   end;
   local Operation = "";
   if CheckBit(trade.flags, 2) == 1 then Operation = "S"; else Operation = "B"; end;
   
   -- Добавляет сделку в массив
   local Trade = {};
   Trade.Account = trade.account;
   Trade.Sec_code = trade.sec_code;
   Trade.Num = trade.trade_num;
   Trade.Date = Date;
   Trade.Time = Time;
   Trade.Operation = Operation;
   Trade.Qty = tonumber(trade.qty);
   Trade.Price = tonumber(trade.price);
   Trade.Hint = "Счет: "..Trade.Account.."_Номер: "..trade.trade_num.."_Дата: ";
   if #day == 1 then Trade.Hint = Trade.Hint.."0"..day.."/"; else Trade.Hint = Trade.Hint..day.."/"; end;
   if #month == 1 then Trade.Hint = Trade.Hint.."0"..month.."/"..DateTime.year; else Trade.Hint = Trade.Hint..month.."/"..DateTime.year; end;
   if #hour == 1 then Trade.Hint = Trade.Hint.."_Время: 0"..hour..":"; else Trade.Hint = Trade.Hint.."_Время: "..hour..":"; end;
   if #minute == 1 then Trade.Hint = Trade.Hint.."0"..minute..":"; else Trade.Hint = Trade.Hint..minute..":"; end;
   if #sec == 1 then Trade.Hint = Trade.Hint.."0"..sec; else Trade.Hint = Trade.Hint..sec; end;
   Trade.Hint = Trade.Hint.."_Количество: "..trade.qty;
   Trade.Hint = Trade.Hint.."_Цена: "..trade.price;
   
   -- Получает путь к файлу инструмента в папке торгового счета
   local PathAccountSec = DataFolder..Trade.Account..'\\'..Trade.Sec_code..'.csv';
   local FileIndex = Trade.Account..'_'..Trade.Sec_code;
   -- Если файл еще не открыт, или не существует
   if TradesFiles[FileIndex] == nil then
      -- Пытается открыть файл текущего инструмента в режиме "дописывания"
      TradesFiles[FileIndex] = io.open(PathAccountSec,"a+");
      -- Если файл не существует, то сделка не записана
      if TradesFiles[FileIndex] == nil then 
         -- Создает файл в режиме "записи"
         TradesFiles[FileIndex] = io.open(PathAccountSec,"w");
         -- Закрывает файл
         message('Закрывает файл: ' ..tostring(FileIndex))
         TradesFiles[FileIndex]:close();
         -- Открывает уже существующий файл в режиме "дописывания"
         TradesFiles[FileIndex] = io.open(PathAccountSec,"a+");
      end;
   end;
   -- Встает в начало файла
   TradesFiles[FileIndex]:seek("set",0);
   -- Если файл пустой
   if TradesFiles[FileIndex]:read() == nil then
      -- Добавляет строку заголовков
      TradesFiles[FileIndex]:write("Счет;Код бумаги;Номер сделки;Дата сделки;Время сделки;Операция;Количество;Цена;Текст подсказки", "\n");
   end;
   -- Встает в конец файла
   TradesFiles[FileIndex]:seek("end",0);
   -- Записывает сделку в файл
   TradesFiles[FileIndex]:write(Trade.Account..";"..Trade.Sec_code..";"..Trade.Num..";"..Trade.Date..";"..Trade.Time..";"..Trade.Operation..";"..Trade.Qty..";"..Trade.Price..";"..Trade.Hint, "\n");TradesFiles[FileIndex]:flush();
end;
-- Функция возвращает значение бита (число 0, или 1) под номером bit (начинаются с 0) в числе flags, если такого бита нет, возвращает nil
function CheckBit(flags, bit)
   -- Проверяет, что переданные аргументы являются числами
   if type(flags) ~= "number" then error("Ошибка!!! Checkbit: 1-й аргумент не число!"); end;
   if type(bit) ~= "number" then error("Ошибка!!! Checkbit: 2-й аргумент не число!"); end;
   local RevBitsStr  = ""; -- Перевернутое (задом наперед) строковое представление двоичного представления переданного десятичного числа (flags)
   local Fmod = 0; -- Остаток от деления 
   local Go = true; -- Флаг работы цикла
   while Go do
      Fmod = math.fmod(flags, 2); -- Остаток от деления
      flags = math.floor(flags/2); -- Оставляет для следующей итерации цикла только целую часть от деления           
      RevBitsStr = RevBitsStr ..tostring(Fmod); -- Добавляет справа остаток от деления
      if flags == 0 then Go = false; end; -- Если был последний бит, завершает цикл
   end;
   -- Возвращает значение бита
   local Result = RevBitsStr:sub(bit+1,bit+1);
   if Result == "0" then return 0;     
   elseif Result == "1" then return 1;
   else return nil;
   end;
end;
-- Функция возвращает значение бита (0 или 1) под номером bit в числе flags
function CheckBit1(flags, bit)
    -- Проверяет, что переданные аргументы являются числами
    if type(flags) ~= "number" or type(bit) ~= "number" then
        error("Ошибка!!! CheckBit: оба аргумента должны быть числами!")
    end

    -- Проверяет, что бит под номером bit существует в числе flags
    if bit < 0 or bit >= (8 * sizeof(flags)) then
        return nil
    end

    -- Извлекает значение бита с помощью побитовой операции
    local bitValue = (bit32.band(flags, bit32.lshift(1, bit)) > 0) and 1 or 0

    return bitValue
end

-----------------
function OnTrade(trade)
   -- Если данная сделка еще не записана в файл истории
   if not CheckTradeInFile(trade) then        
      -- Добавляет сделку в файл истории
      AddTradeInFile(trade);
   end;
end;
function OnStop()
   -- Закрывает все файлы
   for key,Handle in pairs(TradesFiles) do
      if Handle ~= nil then Handle:close(); end;
   end;
   Run = false;
end;
function OnInit()
   Run = true;
   -- Получает полный путь к папке "Данные(c)quikluacsharp.ru"
   DataFolder = getWorkingFolder()..'\\Данные(c)quikluacsharp.ru\\';
   -- Создает папки по всем найденным счетам
   CreateAccountsFolders();
   -- Записывает все ранее не записанные сделки из таблицы "Сделки" в файлы
   CheckAndSaveTerminalTrades();
end;
function main()
   while Run do
      sleep(1);
   end;   
end;
Модуль подключения индикаторов папки LuaIndicators с сайта ARQA (https://arqatech.com/ru/support/files/)
 
Цитата
TGB написал:
Цитата
VPM написал:
Какую задачу хотите решить?
      В заголовке ветки написано: подключение в скрипте индикаторов папки LuaIndicators с сайта ARQA
Но это не задача, это некий сервис. Повторюсь
Цитата
VPM написал:
Не знаю как последние алгоритмы разработчиков , не пробовал, а первые это транжирство памяти, и помнится Вы мне тоже помогали с этим вопросом разбираться. Из своего опыта нельзя на прямую использовать в алгоритмах эти индикаторы!
Модуль подключения индикаторов папки LuaIndicators с сайта ARQA (https://arqatech.com/ru/support/files/)
 
Ваш код это некий сервис, по подключению алгоритмов (ну по крайней мере я так понял) наверняка он хороший и правильный, вот тока зачем? Какую задачу хотите решить?
Я показал альтернативный подход через класс луа, хотите используете в алгоритмах программ в потоке маин, хотите в виде индикатора квика, все "по образу и подобию", с контролем памяти, и однообразной инициализацией.
Модуль подключения индикаторов папки LuaIndicators с сайта ARQA (https://arqatech.com/ru/support/files/)
 
А понял, если Вы про это, только на график как индикатор и очень осторожно, так ка это путь убить КВИК на повал. Не знаю как последние алгоритмы разработчиков , не пробовал, а первые это транжирство памяти, и помнится Вы мне тоже помогали с этим вопросом разбираться. Из своего опыта нельзя на прямую использовать в алгоритмах эти индикаторы!
Модуль подключения индикаторов папки LuaIndicators с сайта ARQA (https://arqatech.com/ru/support/files/)
 
Так возвращаю результат
local out = decycler[class_names[1]][symbol_names[n]][interval_values[1]]:calculate(I)
Модуль подключения индикаторов папки LuaIndicators с сайта ARQA (https://arqatech.com/ru/support/files/)
 
Вот пример создания

-- Инициализация стратегии Decycler
           --settings.dec = {period = 60, depth = 0, wid = 0, sigma = 1}
           decycler[class][symbol][interval] = DecyclerQueue.new( {
                                         period = 120,
                                         depth = 0, wid = 0, sigma = 1,
                                         scale = feed[1].sec_scale,
                                         step = feed[1].sec_price_step
                                         }
                                         , ds[n][i]--dataSource:getDataSource(class, symbol, interval)
                                         , class, symbol, interval
                                       )
Модуль подключения индикаторов папки LuaIndicators с сайта ARQA (https://arqatech.com/ru/support/files/)
 
TGB,  Ни как не использую, выше привел код подключения модулей, в том числе алгоритмов, которые ныне упаковываю в класс луа. Вот еще из рабочей программы и здесь уже алгоритмы есть индикаторов
Код
 local FractalAnalyzer = require("FractalAnalyzerClass") --setmetatable(FractalAnalyzer, __object_behaviour)
    local BalanceTracker = require("BalanceTrackerClass")
   --local Analytics = require("Analytics")
   --local Strategy = require("Strategy")
    --local Strategy1 = require("Strategy1") --setmetatable(Strategy1, __object_behaviour)
    --local Strategy2 = require("Strategy2") --setmetatable(Strategy2, __object_behaviour)
   local ChannelPDF = require('ChannelPDFQueueClass')
    local DecyclerQueue = require('DecyclerQueueClass')
    local DetrenderQueue = require('DetrenderQueueClass')
   --local HPR = require("hprsClass") setmetatable(HPR, __object_behaviour)
    local HPR = require("HPRsClassv1") --setmetatable(HPR, __object_behaviour)
    local Result = require("ResultClass")
    local Position = require("PositionClass")
    local Instruction = require("InstructionClass")
    local Signal = require("SignalClass")
    local TimeFrameSynchronizer = require("TimeFrameSynchronizer")
    local TradeManager = require("TradeManagerClass")
Модуль подключения индикаторов папки LuaIndicators с сайта ARQA (https://arqatech.com/ru/support/files/)
 
TGB,  Вся библиотека индикаторов от любезно предоставленная разработчиками копируется и вставляется в папку LuaIndicators. Что тут можно показать? :shock:

Я про другое, это луа, здесь создается таблица и вне вставляются элементы (пусть даже алгоритмы), и затем возвращаем и читаем все ТОЧКА. Для каких целей Ваш алгоритм не очень понятно?
Модуль подключения индикаторов папки LuaIndicators с сайта ARQA (https://arqatech.com/ru/support/files/)
 
TGB,  Код я скинул и указал параметры для того чтоб показать как реализуются модули, и только.
Цитата
TGB написал:
То есть, если вам в скрипте надо использовать уже существующий индикатор, то вам интересно его программировать  и отлаживать.
Да нет просто скопировать и вставить.
Цитата
TGB написал:
Действительно, нет проблем реализовать самому любой индикатор. Но вопрос зачем, когда есть готовые коды некоторых индикаторов?
Очень редко применяю готовый код, скорее в тестерах для проверки идеи. А вот хорошую идею это да.

Основная проблема этих старых алгоритмов - это их математика, которая плохо подходит для внутри дневной торговли.  
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
 
Эта страничка начиналась с примера нечеткой логики с использованием алгоритма, даже можно назвать программы ADX. Этот индикатор всегда нравился мне своими правильными смысла, мощью, если бы не одно но. В таком виде  "классическом" он подходит для инвестирования, то есть для использования на больших тайм фреймах, и виной тому заложенное отставание в расчетах этого алгоритма. Для примера вот так его реализовали разработчики
Код
[/CODE][SPOILER=][CODE]------------------------------------------------------------------
----Moving Average SMA, MMA, EMA, WMA, SMMA, VMA
------------------------------------------------------------------

local SMA,MMA,EMA,WMA,SMMA,VMA = "SMA","MMA","EMA","WMA","SMMA","VMA"
local OPEN,HIGH,LOW,CLOSE,VOLUME,MEDIAN,TYPICAL,WEIGHTED,DIFFERENCE,ANY = "O","H","L","C","V","M","T","W","D","A"

--[[Simple Moving Average (SMA)
SMA = sum(Pi) / n]]
local function F_SMA()
   local sum = {}
   local it = {p=0, l=0}
return function (I, P, VT, ds)
   if I == 1 then
      sum = {}
      it = {p=0, l=0}
   end
   if CandleExist(I,ds) then
      if I~=it.p then it={p=I, l=it.l+1} end
      local Ip,Ipp,Ippp = Squeeze(it.l,P),Squeeze(it.l-1,P),Squeeze(it.l-P,P)
      sum[Ip] = (sum[Ipp] or 0) + GetValueEX(it.p,VT,ds)
      if it.l >= P then
         return (sum[Ip] - (sum[Ippp] or 0)) / P
      end
   end
return nil
end
end
--[[Modified Moving Average (MMA)
MMA = (MMAi-1*(n-1) + Pi) / n]]
local function F_MMA() 
   local sum = {}
   local tmp = {pp=nil, p=nil}
   local it = {p=0, l=0}
return function(I, P, VT, ds)
   if I == 1 then
      sum = {}
      tmp = {pp=nil, p=nil}
      it = {p=0, l=0}
   end
   if CandleExist(I,ds) then
      if I~=it.p then 
         it = {p=I, l=it.l+1} 
         tmp.pp = tmp.p
      end
      local Ip,Ipp,Ippp = Squeeze(it.l,P),Squeeze(it.l-1,P),Squeeze(it.l-P,P)
      if it.l <= P + 1 then
         sum[Ip] = (sum[Ipp] or 0) + GetValueEX(it.p,VT,ds)
         if (it.l == P) or (it.l == P + 1) then
            tmp.p = (sum[Ip] - (sum[Ippp] or 0)) / P
         end
      else
         tmp.p = (tmp.pp*(P-1) + GetValueEX(it.p,VT,ds)) / P
      end
      if it.l >= P then
         return tmp.p
      end
   end
return nil
end
end
--[[Exponential Moving Average (EMA)
EMAi = (EMAi-1*(n-1)+2*Pi) / (n+1)]]
local function F_EMA() 
   local tmp = {pp=nil, p=nil}
   local it = {p=0, l=0}
return function(I, P, VT, ds)
   if I == 1 then
      tmp = {pp=nil, p=nil}
      it = {p=0, l=0}
   end
   if CandleExist(I,ds) then
      if I~=it.p then 
         it = {p=I, l=it.l+1} 
         tmp.pp = tmp.p
      end
      if it.l == 1 then
         tmp.p = GetValueEX(it.p,VT,ds)
      else
         tmp.p = (tmp.pp*(P-1) + 2*GetValueEX(it.p,VT,ds)) / (P+1)
      end
      if it.l >= P then
         return tmp.p
      end
   end
return nil
end
end
--[[William Moving Average (WMA)
( Previous WILLMA * ( Period - 1 ) + Data ) / Period]]
local function F_WMA()
   local tmp = {pp=nil, p=nil}
   local it = {p=0, l=0}
return function(I, P, VT, ds)
   if I == 1 then
      tmp = {pp=nil, p=nil}
      it = {p=0, l=0}
   end
   if CandleExist(I,ds) then
      if I~=it.p then 
         it={p=I, l=it.l+1}
         tmp.pp = tmp.p
      end
      if it.l == 1 then
         tmp.p = GetValueEX(it.p,VT,ds)
      else
         tmp.p = (tmp.pp * (P-1) + GetValueEX(it.p,VT,ds)) / P
      end
      if it.l >= P then
         return tmp.p
      end
   end
return nil
end
end
--[[Volume Adjusted Moving Average (VMA)
VMA = sum(Pi*Vi) / sum(Vi)]]
local function F_VMA()
   local sum = {}
   local sum2 = {}
   local it = {p=0, l=0}
return function(I, P, VT, ds)
   if I == 1 then
      sum = {}
      sum2 = {}
      it = {p=0, l=0}
   end
   if CandleExist(I,ds) then
      if I~=it.p then it={p=I, l=it.l+1} end
      local Ip,Ipp,Ippp = Squeeze(it.l,P),Squeeze(it.l-1,P),Squeeze(it.l-P,P)
      sum[Ip] = (sum[Ipp] or 0) + GetValueEX(it.p,VT,ds) * GetValueEX(it.p,VOLUME,ds)
      sum2[Ip] = (sum2[Ipp] or 0) + GetValueEX(it.p,VOLUME,ds)
      if it.l >= P then
         return (sum[Ip] - (sum[Ippp] or 0)) / (sum2[Ip] - (sum2[Ippp] or 0))
      end
   end
return nil
end
end
--[[Smoothed Moving Average (SMMA)
SMMAi = (sum(Pi) - SMMAi-1 + Pi) / n]]
local function F_SMMA()
   local sum = {}
   local sum2 = {}
   local it = {p=0, l=0}
return function(I, P, VT, ds)
   if I == 1 then
      sum = {}
      sum2 = {}
      it = {p=0, l=0}
   end
   if CandleExist(I,ds) then
      if I~=it.p then it={p=I, l=it.l+1} end
      local Ip,Ipp,Ippp = Squeeze(it.l,P),Squeeze(it.l-1,P),Squeeze(it.l-P,P)
      sum[Ip] = (sum[Ipp] or 0) + GetValueEX(it.p,VT,ds)
      if it.l >= P then
         if it.l == P then
            sum2[Ip] = (sum[Ip] - (sum[Ippp] or 0)) / P
         else
            sum2[Ip] = ((sum[Ip] - (sum[Ippp] or 0)) - (sum2[Ipp] or 0)+ GetValueEX(it.p,VT,ds)) / P
         end
         return sum2[Ip]
      end
   end
return nil
end
end

local function CandleExist(I,ds)
return (type(C)=="function" and C(I)~=nil) or
   (type(ds)=="table" and (ds[I]~=nil or (type(ds.Size)=="function" and (I>0) and (I<=ds:Size()))))
end
local function Squeeze(I,P)
   return math.fmod(I-1,P+1)
end
local function ConvertValue(T,...)
local function r(V, R) 
   if R and string.upper(R)== "ON" then R=0 end
   if V and tonumber(R) then
      if V >= 0 then return math.floor(V * 10^R + 0.5) / 10^R
      else return math.ceil(V * 10^R - 0.5) / 10^R end
   else return V end
end
local arg = {...}
arg.n = select('#', ...)
   if arg.n > 0 then
      for i = 1, arg.n do
         arg[i]=arg[i] and r(arg[i] * ((T and T.Multiply) or 1), (T and T.Round) or "off")
      end
      return unpack(arg)
   else return nil end
end
local function GetValueEX(I,VT,ds) 
VT=(VT and string.upper(string.sub(VT,1,1))) or ANY
   if VT == OPEN then         --Open
      return (O and O(I)) or (ds and ds:O(I))
   elseif VT == HIGH then       --High
      return (H and H(I)) or (ds and ds:H(I))
   elseif VT == LOW then      --Low
      return (L and L(I)) or (ds and ds:L(I))
   elseif VT == CLOSE then      --Close
      return (C and C(I)) or (ds and ds:C(I))
   elseif VT == VOLUME then      --Volume
      return (V and V(I)) or (ds and ds:V(I)) 
   elseif VT == MEDIAN then      --Median
      return ((GetValueEX(I,HIGH,ds) + GetValueEX(I,LOW,ds)) / 2)
   elseif VT == TYPICAL then   --Typical
      return ((GetValueEX(I,MEDIAN,ds) * 2 + GetValueEX(I,CLOSE,ds))/3)
   elseif VT == WEIGHTED then   --Weighted
      return ((GetValueEX(I,TYPICAL,ds) * 3 + GetValueEX(I,OPEN,ds))/4) 
   elseif VT == DIFFERENCE then   --Difference
      return (GetValueEX(I,HIGH,ds) - GetValueEX(I,LOW,ds))
   else                     --Any
      return (ds and ds[I])
   end
return nil
end
local function MA() --Moving Average ("MA")
   local T_MA = {[SMA]=F_SMA(),[MMA]=F_MMA(),[EMA]=F_EMA(),[VMA]=F_VMA(),[SMMA]=F_SMMA(),[WMA]=F_WMA()}
return function (I, Fsettings, ds)
   local Fsettings=(Fsettings or {})
   local P = (Fsettings.Period or 14)
   if (P > 0) then
      return T_MA[string.upper(Fsettings.Metod or EMA)](I, P, (Fsettings.VType or CLOSE), ds)
   end
return nil
end
end

local function TR() --True Range ("TR")
   local it = {pp=0, p=0, l=0}
return function (I, ds)
   if I == 1 then
      it = {pp=0, p=0, l=0}
   end
   if CandleExist(I,ds) then
      if I~=it.p then it={pp=it.p, p=I, l=it.l+1} end
      if it.l == 1 then
         return math.abs(GetValueEX(it.p,DIFFERENCE, ds))
      else
         return math.max(math.abs(GetValueEX(it.p,DIFFERENCE, ds)), 
            math.abs(GetValueEX(it.p,HIGH,ds) - GetValueEX(it.pp,CLOSE,ds)), 
            math.abs(GetValueEX(it.pp,CLOSE,ds)-GetValueEX(it.p,LOW,ds)))
      end
   end
return nil
end
end
function ADX() --Average Directional Movement Index ("ADX")
   local pDI_MA=MA()
   local mDI_MA=MA()
   local ADX_MA=MA()
   local f_TR=TR()
   local it = {pp=0, p=0, l=0}
return function (I, Fsettings, ds)
local Fsettings=(Fsettings or {})
local P = (Fsettings.Period or 14)
local M = (Fsettings.Metod or EMA)
if (P>0) then
   if I == 1 then
      if (M==VMA) then M=SMA end
      it = {pp=0, p=0, l=0}
   end
   local i_TR = f_TR(I,ds)
   if CandleExist(I,ds) then
      if I~=it.p then it={pp=it.p, p=I, l=it.l+1} end
      if it.l > 1 then
         if GetValueEX(it.p,HIGH,ds) > GetValueEX(it.pp,HIGH,ds) then
            pDM = math.abs(GetValueEX(it.p,HIGH,ds)-GetValueEX(it.pp,HIGH,ds))
         else pDM = 0 end
         if GetValueEX(it.p,LOW,ds) < GetValueEX(it.pp,LOW,ds) then
            mDM = math.abs(GetValueEX(it.pp,LOW,ds)-GetValueEX(it.p,LOW,ds))
         else mDM = 0 end
         if pDM > mDM then mDM=0 end
         if mDM > pDM then pDM=0 end
         if pDM == mDM then pDM=0 mDM = 0 end
         if i_TR~=0 then pSDI = pDM / i_TR * 100 else pSDI = 0 end
         if i_TR~=0 then mSDI = mDM / i_TR * 100 else mSDI = 0 end
         local pDI = pDI_MA(it.l-1, {Period=P, Metod=M, VType=ANY}, {[it.l-1] = pSDI})
         
         local mDI = mDI_MA(it.l-1, {Period=P, Metod=M, VType=ANY}, {[it.l-1] = mSDI})
         
         if it.l>P and pDI and mDI then
            return ADX_MA(it.l-P, {Period=P, Metod=M, VType=ANY}, {[it.l-P]=math.abs(pDI-mDI)/(pDI+mDI)*100}),pDI,mDI
         else
            return nil,pDI,mDI
         end
      end
   end
end
return nil,nil,nil
end
end

Settings = {
Name = "*ADX (Average Directional Movement Index)", 
Period = 14, 
Metod = "EMA", --(SMA, MMA, EMA, WMA, SMMA, VMA)
line = {{
      Name = "Horizontal line",
      Type = TYPE_LINE, 
      Color = RGB(140, 140, 140)
      },
      {
      Name = "ADX", 
      Type = TYPE_LINE, 
      Color = RGB(0, 162, 232)
      },
      {
      Name = "ADX +DI",
      Type = TYPE_LINE, 
      Color = RGB(0, 206, 0)
      },
      {
      Name = "ADX -DI",
      Type = TYPE_LINE,
      Color = RGB(221, 44, 44)
      }
      },
Round = "off",
Multiply = 1,
Horizontal_line="off"
}
   local func      
function Init() 
   func = ADX()
   return #Settings.line
end
function OnCalculate(Index) 
   return tonumber(Settings.Horizontal_line),ConvertValue(Settings,func(Index, Settings))
end

[/SPOILER]Вот так переписываюlocal ADX = {}
ADX.__index = ADX


function ADX:new(settings)
   local instance = setmetatable({}, ADX)
   instance.settings = settings or {
       Name = "*ADX (Average Directional Movement Index)",
       Period = 14,
       Method = "EMA",
       line = {
           {Name = "Horizontal line", Type = TYPE_LINE, Color = RGB(140, 140, 140)},
           {Name = "ADX", Type = TYPE_LINE, Color = RGB(0, 162, 232)},
           {Name = "ADX +DI", Type = TYPE_LINE, Color = RGB(0, 206, 0)},
           {Name = "ADX -DI", Type = TYPE_LINE, Color = RGB(221, 44, 44)}
       },
       Round = "off",
       Multiply = 1,
       Horizontal_line = "off"
   }
   instance:initialize()
   return instance
end


function ADX:initialize()
   self.pDI_MA = self:createMovingAverage()
   self.mDI_MA = self:createMovingAverage()
   self.ADX_MA = self:createMovingAverage()
   self.f_TR = self:createTrueRange()
   self.it = {pp = 0, p = 0, l = 0}
end
function ADX:createMovingAverage()
   local T_MA = {
       [SMA] = self.F_SMA(),
       [MMA] = self.F_MMA(),
       [EMA] = self.F_EMA(),
       [VMA] = self.F_VMA(),
       [SMMA] = self.F_SMMA(),
       [WMA] = self.F_WMA()
   }
   return function(I, settings, ds)
       local settings = settings or {}
       local P = settings.Period or 14
       if P > 0 then
           return T_MA[string.upper(settings.Method or EMA)](I, P, settings.VType or CLOSE, ds)
       end
       return nil
   end
end
function ADX:createTrueRange()
   local it = {pp = 0, p = 0, l = 0}
   return function(I, ds)
       if I == 1 then
           it = {pp = 0, p = 0, l = 0}
       end
       if self:CandleExist(I, ds) then
           if I ~= it.p then it = {pp = it.p, p = I, l = it.l + 1} end
           if it.l == 1 then
               return math.abs(self:GetValueEX(it.p, DIFFERENCE, ds))
           else
               return math.max(math.abs(self:GetValueEX(it.p, DIFFERENCE, ds)),
                   math.abs(self:GetValueEX(it.p, HIGH, ds) - self:GetValueEX(it.pp, CLOSE, ds)),
                   math.abs(self:GetValueEX(it.pp, CLOSE, ds) - self:GetValueEX(it.p, LOW, ds)))
           end
       end
       return nil
   end
end
function ADX:calculate(I, settings, ds)
   local P = settings.Period or 14
   local M = settings.Method or EMA
   if P > 0 then
       if I == 1 then
           if M == VMA then M = SMA end
           self.it = {pp = 0, p = 0, l = 0}
       end
       local i_TR = self.f_TR(I, ds)
       if self:CandleExist(I, ds) then
           if I ~= self.it.p then self.it = {pp = self.it.p, p = I, l = self.it.l + 1} end
           if self.it.l > 1 then
               local pDM, mDM
               if self:GetValueEX(self.it.p, HIGH, ds) > self:GetValueEX(self.it.pp, HIGH, ds) then
                   pDM = math.abs(self:GetValueEX(self.it.p, HIGH, ds) - self:GetValueEX(self.it.pp, HIGH, ds))
               else pDM = 0 end
               if self:GetValueEX(self.it.p, LOW, ds) < self:GetValueEX(self.it.pp, LOW, ds) then
                   mDM = math.abs(self:GetValueEX(self.it.pp, LOW, ds) - self:GetValueEX(self.it.p, LOW, ds))
               else mDM = 0 end
               if pDM > mDM then mDM = 0 end
               if mDM > pDM then pDM = 0 end
               if pDM == mDM then pDM = 0 mDM = 0 end
               local pSDI = (i_TR ~= 0) and (pDM / i_TR * 100) or 0
               local mSDI = (i_TR ~= 0) and (mDM / i_TR * 100) or 0
               local pDI = self.pDI_MA(self.it.l - 1, {Period = P, Method = M, VType = ANY}, {[self.it.l - 1] = pSDI})
               local mDI = self.mDI_MA(self.it.l - 1, {Period = P, Method = M, VType = ANY}, {[self.it.l - 1] = mSDI})
               if self.it.l > P and pDI and mDI then
                   return self.ADX_MA(self.it.l - P, {Period = P, Method = M, VType = ANY}, {[self.it.l - P] = math.abs(pDI - mDI) / (pDI + mDI) * 100}), pDI, mDI
               else
                   return nil, pDI, mDI
               end
           end
       end
   end
   return nil, nil, nil
end


-- Methods for different Moving Averages (SMA, MMA, EMA, WMA, SMMA, VMA)
function ADX:F_SMA()
   local sum = {}
   local it = {p = 0, l = 0}
   return function(I, P, VT, ds)
       if I == 1 then
           sum = {}
           it = {p = 0, l = 0}
       end
       if self:CandleExist(I, ds) then
           if I ~= it.p then it = {p = I, l = it.l + 1} end
           local Ip, Ipp, Ippp = self:Squeeze(it.l, P), self:Squeeze(it.l - 1, P), self:Squeeze(it.l - P, P)
           sum[Ip] = (sum[Ipp] or 0) + self:GetValueEX(it.p, VT, ds)
           if it.l >= P then
               return (sum[Ip] - (sum[Ippp] or 0)) / P
           end
       end
       return nil
   end
end
function ADX:F_MMA()
   local sum = {}
   local tmp = {pp = nil, p = nil}
   local it = {p = 0, l = 0}
   return function(I, P, VT, ds)
       if I == 1 then
           sum = {}
           tmp = {pp = nil, p = nil}
           it = {p = 0, l = 0}
       end
       if self:CandleExist(I, ds) then
           if I ~= it.p then
               it = {p = I, l = it.l + 1}
               tmp.pp = tmp.p
           end
           local Ip, Ipp, Ippp = self:Squeeze(it.l, P), self:Squeeze(it.l - 1, P), self:Squeeze(it.l - P, P)
           if it.l <= P + 1 then
               sum[Ip] = (sum[Ipp] or 0) + self:GetValueEX(it.p, VT, ds)
               if (it.l == P) or (it.l == P + 1) then
                   tmp.p = (sum[Ip] - (sum[Ippp] or 0)) / P
               end
           else
               tmp.p = (tmp.pp * (P - 1) + self:GetValueEX(it.p, VT, ds)) / P
           end
           if it.l >= P then
               return tmp.p
           end
       end
       return nil
   end
end
function ADX:F_EMA()
   local tmp = {pp = nil, p = nil}
   local it = {p = 0, l = 0}
   return function(I, P, VT, ds)
       if I == 1 then
           tmp = {pp = nil, p = nil}
           it = {p = 0, l = 0}
       end
       if self:CandleExist(I, ds) then
           if I ~= it.p then
               it = {p = I, l = it.l + 1}
               tmp.pp = tmp.p
           end
           if it.l == 1 then
               tmp.p = self:GetValueEX(it.p, VT, ds)
           else
               tmp.p = (tmp.pp * (P - 1) + 2 * self:GetValueEX(it.p, VT, ds)) / (P + 1)
           end
           if it.l >= 1 then
               return tmp.p
           end
       end
       return nil
   end
end
function ADX:F_VMA()
   local sum = {}
   local tmp = {pp = nil, p = nil}
   local it = {p = 0, l = 0}
   return function(I, P, VT, ds)
       if I == 1 then
           sum = {}
           tmp = {pp = nil, p = nil}
           it = {p = 0, l = 0}
       end
       if self:CandleExist(I, ds) then
           if I ~= it.p then
               it = {p = I, l = it.l + 1}
               tmp.pp = tmp.p
           end
           local Ip, Ipp, Ippp = self:Squeeze(it.l, P), self:Squeeze(it.l - 1, P), self:Squeeze(it.l - P, P)
           sum[Ip] = (sum[Ipp] or 0) + self:GetValueEX(it.p, VT, ds)
           if it.l >= P then
               tmp.p = (sum[Ip] - (sum[Ippp] or 0)) / P
               return tmp.p
           end
       end
       return nil
   end
end
function ADX:F_SMMA()
   local sum = {}
   local tmp = {pp = nil, p = nil}
   local it = {p = 0, l = 0}
   return function(I, P, VT, ds)
       if I == 1 then
           sum = {}
           tmp = {pp = nil, p = nil}
           it = {p = 0, l = 0}
       end
       if self:CandleExist(I, ds) then
           if I ~= it.p then
               it = {p = I, l = it.l + 1}
               tmp.pp = tmp.p
           end
           if it.l == P then
               sum[P] = sum[P - 1] + self:GetValueEX(it.p, VT, ds)
               tmp.p = sum[P] / P
           elseif it.l < P then
               sum[it.l] = (sum[it.l - 1] or 0) + self:GetValueEX(it.p, VT, ds)
           else
               tmp.p = (tmp.pp * (P - 1) + self:GetValueEX(it.p, VT, ds)) / P
           end
           if it.l >= P then
               return tmp.p
           end
       end
       return nil
   end
end
function ADX:F_WMA()
   local sum = {}
   local weight_sum = 0
   local it = {p = 0, l = 0}
   return function(I, P, VT, ds)
       if I == 1 then
           sum = {}
           weight_sum = 0
           it = {p = 0, l = 0}
           for i = 1, P do
               weight_sum = weight_sum + i
           end
       end
       if self:CandleExist(I, ds) then
           if I ~= it.p then it = {p = I, l = it.l + 1} end
           local sum_weights = 0
           for i = 1, P do
               if self:CandleExist(it.p - i + 1, ds) then
                   sum_weights = sum_weights + self:GetValueEX(it.p - i + 1, VT, ds) * (P - i + 1)
               end
           end
           if it.l >= P then
               return sum_weights / weight_sum
           end
       end
       return nil
   end
end


-- Helper functions
function ADX:CandleExist(I, ds)
   return ds:C(I) ~= nil
end
function ADX:GetValueEX(I, VT, ds)
   return ds[VT](ds, I)
end
function ADX:Squeeze(I, P)
   return (I - 1) % P + 1
end
return ADX
Модуль подключения индикаторов папки LuaIndicators с сайта ARQA (https://arqatech.com/ru/support/files/)
 
Цитата
TGB написал:
Интересно: нет ни вопросов, ни замечаний. То ли все ясно, то ли не понятно ничего.
Скорее не понятно, зачем? Ведь таблица луа это уже модуль. Ну к примеру моя любая программа сейчас выглядит так,
и это не все классы.
При этом память на один инструмент не более 1000 кб, быстродействие алгоритма ограничиваю чтобы не перегружать процессор. Но это только мое мнение.
Код
-- Установите путь к вашему каталогу с модулями
   local path = '...\\modules';
    package.path = path.."\\?.lua;".. package.path
   
    -- Проверка и подключение необходимых модулей
    local function safeRequire(moduleName)
        local success, result = pcall(require, moduleName)
        if not success then
          error("Failed to load module: " .. moduleName .. "\n" .. result)
        end
        return result
    end
    
    -- Модули
    --local Log = require("LogClass")
    
    local Utility = require("Utility")
    
    local Queue = require("QueueClass") -- Реализация класса `Queue` двусвязной очереди
    local Color = require("ColorClass")
    local Label = require("LabelClass")
    local WindowCoordinates = require("WindowCoordinatesClass")
    local TableSaverLoader = require("TableSaverLoader")
    
    local TimeHandler = require("TimesClass")
    local Checker = require("Checker") --setmetatable(Checker, __object_behaviour)
    local Event = require("EventClass")
    --local VersionManager = require("VersionManager")
    local StateMachine = require("StateMachine") --  Управляет состояниями и переходами между ними.
    local StateManager = require("StateManager") -- Отвечает за сохранение и загрузку состояния из файла.
     
    local DS = require("DSClass") --setmetatable(DS, __object_behaviour)
    local RiskManagement = require("rmClass") --setmetatable(rm, __object_behaviour)
    local MoneyManagement = require("mmClass") --setmetatable(mm, __object_behaviour)
    local CapitalManagement = require("cmClass") --setmetatable(CapitalManagement, __object_behaviour)
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
 
Переписал Все! и продолжаю переписывать! Добрался до индикаторов, написанных ранее используя принцип замыкания, все перевожу в класс луа. а иногда и OPP,  в чем суть ниже покажу пример. А если в двух словах, всему основа структура языка луа - таблица. Таблица - это объект, то есть для примера как бы описывали автомобиль, начали бы  перечислять его  свойствами (цвет = красный, мотор = бензиновый и так далее), возможную скорость, расход топлива, уже не описать свойствами нужны методы = функции. Так и при описании позиции, бара, тренда ...  Если еще проще говорить, таблица позволяет оперировать (говорить) смыслами, создавать паттерны. Это позволяет перейти, от элементарной арифметике к векторному счислению и управлению объектами. "Аз. Буки , Ведай, Глаголь, Добро, ..." - это  остатки от языка на котором все создавалось и описывалось - это смыслы. Луа нас возвращает к возможности этим оперировать, об этом автор языка нам рассказывает.  
Хочу заказать скрипт., Хочу заказать скрипт по поиску роботов, которые покупают или продают рыночными заявками.
 
Цитата
nikolz написал:
Написал первый вариант такого скрипта.Пускаю его на тест сервере.Он обрабатывает всю таблицу  это 330 инструментов и 1 млн 100 тысяч записейДля каждого инструмента и каждой записи он ищет по истории нужных роботов.Примерно так.
Поделитесь своими чудесами?
Золотыми буквами выбить!
 
Сейчас поясню вот ссылка, https://forum.quik.ru/forum1/topic8572/  
Золотыми буквами выбить!
 
Нужно Золотыми буквами выбить подход А ПРИЧЕМ ТУТ РЫНОК?
Andrey Golik написал:
Данные манипуляции по редактированию данных для построения графиков выполняются брокером на стороне сервера. Рекомендуем по данному вопросу обратиться к Вашему обслуживающему брокеру.
Доработка индикаторов при принудительном изменении цены акции., Необходимо доработать алгоритмы расчета индикаторов при принудительном изменении цены акции.
 
Цитата
Andrey Golik написал:

Данные манипуляции по редактированию данных для построения графиков выполняются брокером на стороне сервера. Рекомендуем по данному вопросу обратиться к Вашему обслуживающему брокеру.
Данный подход нужно оформить в названии комплекса Ваших программ.  
Хочу заказать скрипт., Хочу заказать скрипт по поиску роботов, которые покупают или продают рыночными заявками.
 
Цитата
nikolz написал:
Написал первый вариант такого скрипта.
Пускаю его на тест сервере.
Он обрабатывает всю таблицу  это 330 инструментов и 1 млн 100 тысяч записей
Для каждого инструмента и каждой записи он ищет по истории нужных роботов.
Примерно так.
Ну даете, nikolz,  Вы не перестаёте меня удивлять :smile:  
Хочу заказать скрипт., Хочу заказать скрипт по поиску роботов, которые покупают или продают рыночными заявками.
 
Это небольшая но рабочая утилита, которая умеет управляться с таблицей всех сделок, то есть тиками.
Конечно это не то что Вы хотите получить, но этот не большой скрипт легко превращается в поиск необходимых Вам данных и многое еще чего, достаточно дописать фильтры.
Что делает данный скрипт, он предназначен для использования в торговой платформе QUIK, создает таблицу, отображающую баланс покупок и продаж за последние 5 минут, и обновляет ее при поступлении новых обезличенных сделок, в окно выводится баланс полученный за каждую 1 минуту.
Это "классический" вариант, алгоритм и идея которого взяты от сюда QuikLuaCSharp.ru, за что автору отдельное "большое человеческое спасибо!",
все что я сделал это превратил его в класс - модуль луа, для удобства использования в своих программах. В общем удачи.
Код
 -- Класс для отслеживания баланса покупок/продаж
local BalanceTracker = {}
BalanceTracker.__index = BalanceTracker
-- Конструктор
function BalanceTracker:new()
    local obj = setmetatable({}, BalanceTracker)
    obj.isRunning = true
    obj.array5Min = {}
    obj.lastBarSeconds = 0
    obj.t_id = nil
    obj:createTable()
    return obj
end
-- Создание таблицы
function BalanceTracker:createTable()
    self.t_id = AllocTable()
    if self.t_id == nil then
        error("Failed to allocate table")
    end

    AddColumn(self.t_id, 0, "1", true, QTABLE_INT_TYPE, 15)
    AddColumn(self.t_id, 1, "2", true, QTABLE_INT_TYPE, 15)
    AddColumn(self.t_id, 2, "3", true, QTABLE_INT_TYPE, 15)
    AddColumn(self.t_id, 3, "4", true, QTABLE_INT_TYPE, 15)
    AddColumn(self.t_id, 4, "5", true, QTABLE_INT_TYPE, 15)
    CreateWindow(self.t_id)
    SetWindowCaption(self.t_id, "Баланс покупок/продаж")
    InsertRow(self.t_id, -1)
end
-- Установка цвета
function BalanceTracker:setColor(col, color)
    SetColor(self.t_id, 1, col, color, RGB(0,0,0), color, RGB(0,0,0))
end
function BalanceTracker:red(col)
    self:setColor(col, RGB(255,128,128))
end
function BalanceTracker:yellow(col)
    self:setColor(col, RGB(240,240,0))
end
function BalanceTracker:green(col)
    self:setColor(col, RGB(128,255,128))
end
-- Добавление нового бара в массив
function BalanceTracker:addNewBarToArray5Min()
    table.insert(self.array5Min, 0)
    if #self.array5Min > 5 then
        table.remove(self.array5Min, 1)
    end
    local offset = 5 - #self.array5Min
    for i = 1, #self.array5Min do
        self:setBalance(self.array5Min[i], i + offset - 1)
    end
end
-- Установка баланса и цвет ячейки
function BalanceTracker:setBalance(newBalance, numCol)
    SetCell(self.t_id, 1, numCol, tostring(newBalance))
    if numCol == 4 then
        self.array5Min[#self.array5Min] = newBalance
    end
    if newBalance < 0 then
        self:red(numCol)
    elseif newBalance == 0 then
        self:yellow(numCol)
    else
        self:green(numCol)
    end
end
-- Проверка на новую минуту
function BalanceTracker:checkNewMin(dealDateTime)
    dealDateTime.sec = 0
    dealDateTime.mcs = 0
    local seconds = os.time(dealDateTime)
    if seconds > self.lastBarSeconds then
        self.lastBarSeconds = seconds
        return true
    else
        return false
    end
end
-- Обработка сделки
function BalanceTracker:onAllTrade(alltrade)
    if alltrade.sec_code == SEC_CODE then
        local newMinute = self:checkNewMin(alltrade.datetime)
        if newMinute then
            self:addNewBarToArray5Min()
        end

        if bit.test(alltrade.flags, 0) then
            self:setBalance(self.array5Min[#self.array5Min] - alltrade.qty, 4)
        else
            self:setBalance(self.array5Min[#self.array5Min] + alltrade.qty, 4)
        end
    end
end
-- Остановка скрипта
function BalanceTracker:onStop()
    self.isRunning = false
end
-- Главный цикл
function BalanceTracker:main()
    while self.isRunning do
        sleep(100) -- Уменьшить частоту вызова
    end
end
--return BalanceTracker

local CLASS_CODE     = "SPBFUT"     -- Класс бумаги
local SEC_CODE       = "NGN4"       -- Код бумаги

-- Создание объекта класса и функции обратного вызова
local balanceTracker = BalanceTracker:new()
function main()
    balanceTracker:main()
end
function OnAllTrade(alltrade)
    balanceTracker:onAllTrade(alltrade)
end
function OnStop()
    balanceTracker:onStop()
end
Куда все подевались?
 
funduk, Не уверен что по этому, а что же тогда будет являться обсуждением? Но в одном Вы правы.
И прежде чем продолжить, должен принести свои извинения, за излишнею грубость и хамство. nikolz,  извините.

Касаемо предмета обсуждения, фактически представлена реализация 3 вариантов кольцевого буфера с разными методами исполнения,
не смотря на то что изменения не значительны, но они сильно влияют на производительность алгоритма. Не вооруженным глазом видно что вариант1 быстрее варианта2.
Здесь рассуждение простые, вариант1 это всегда вставка(1 элемент), в то время как вариант2 это вставка(n элемент буфера).
Видимо фактор производительности, явился решающим для включения разработчиками данного подхода в свои индикаторы, но для меня оно интуитивно смущало из-за не прозрачного расчета индексов. Решил проверить вариант с двухсвязной очередью, дописал вариант для проверки на производительность.
И каково было мое удивление, ну в общем судите сами, вот варианты.
Код
local size = 100000 -- 3
 
do ---- 1.
--local F = {0, 0, 0}
local F = {}
for i = 1, size do
    F[i] = 0
end

local start_time = os.clock()
local function shiftArray(x)
    -- Сдвигаем элементы массива
    F[3] = F[2]
    F[2] = F[1]
    F[1] = x -- Записываем новый элемент в конец массива
    return F -- Возвращаем массив целиком (или можете возвращать только F[3], если нужно)
end
for I=1,size do
--print( shiftArray(I), F[1], F[2], F[3] )
shiftArray(I)
end
local end_time = os.clock()
print("1. Время выполнения для варианта 1:", end_time - start_time, "секунд")
end
do --local F = {0, 0, 0}
local F = {}
for i = 1, size do
    F[i] = 0
end

local start_time = os.clock()
local index = 0
local function addElement(x)
    index = (index % 3) + 1
    F[index] = x
   return F
end
for I=1,size do
--print(addElement(I), F[1], F[2], F[3] )
addElement(I)
end
local end_time = os.clock()
print("2. Время выполнения для варианта 1a:", end_time - start_time, "секунд")
end
do ---- 2.
--local F = {0, 0, 0}
local F = {}
for i = 1, size do
    F[i] = 0
end

local start_time = os.clock()
local index = 0
local function addElement(x)
    -- Обновляем текущий индекс с учетом кольцевого буфера
    index = (index % 3) + 1
    -- Вставляем новый элемент в текущий индекс
    F[index] = x
    
    -- Для наглядности выводим текущий массив
    local result = {}
    for i = 1, 3 do
        result[i] = F[(index - i + 3) % 3 + 1]
    end
    return result
end
for I=1,size do
--print('*',addElement(I), F[1], F[2], F[3] )
addElement(I)
end
local end_time = os.clock()
print("3. Время выполнения для варианта 2:", end_time - start_time, "секунд")
end
do ---- 3. Простой вариант с переменной currentIndex
local F = {}
for i = 1, 1000 do
    F[i] = 0
end

local start_time = os.clock()
local currentIndex = 1
local function addElement(x)
    F[currentIndex] = x
    currentIndex = currentIndex + 1
    if currentIndex > 1000 then
        currentIndex = 1
    end
    return F
end

for i = 1, 100000 do -- Повторяем операцию добавления 100000 раз
    addElement(i)
end

local end_time = os.clock()
print("4. Время выполнения для варианта 3:", end_time - start_time, "секунд")
end
А вот ответы:
1. Время выполнения для варианта 1:   0.009   секунд
2. Время выполнения для варианта 1a:   0.006   секунд
3. Время выполнения для варианта 2:   1.185   секунд
4. Время выполнения для варианта 3:   0.0050000000000001   секунд
>Exit code: 0    Time: 1.768
Куда все подевались?
 
nikolz,  Извините за банальность, но так сравнивают только "Х" с пальцем. Если Вы хотите провести сравнительные тесты, то нужно определим критерии по которым будут сравнивать. А сравнивать нужно хотя бы эти варианты.
Код
1. Pешение с использованием кольцевого буфера

local F = {0, 0, 0}
local index = 0
local function addElement(x)
    index = (index % 3) + 1
    F[index] = x
   return F
end
for I=1,10 do
print(addElement(I), F[1], F[2], F[3] )
end

2. Вариант. Альтернативное решение
local F = {0, 0, 0}
local function shiftArray(x)
    -- Сдвигаем элементы массива
    F[3] = F[2]
    F[2] = F[1]
    F[1] = x -- Записываем новый элемент в конец массива
    return F -- Возвращаем массив целиком (или можете возвращать только F[1], если нужно)
end

for I=1,10 do
print(shiftArray(I), F[1], F[2], F[3] )
end
А может подскажите, где я сказал, что какой то вариант лучше?
Куда все подевались?
 
nikolz,  Когда Вы голову подымите чуть выше, заметите что я поправил Ваш вариант, и для сравнения выложил альтернативное решение с использованием кольцевого буфера, даже попробовал разный порядок хранения данных.  Что лучше, почему лучше, когда какой применять, решает пользователь под свои задачи. А я лишь привожу пример про универсальный способ, и показываю его преимущества, относительно других. Но в любом случае их нужно погонять в условиях когда пропадают свечи, когда вызывается по нескольку раз на одном индексе алгоритмы и прочие радости жизни алгоритмов в квике.  
Куда все подевались?
 
Вот в этом варианте вроде работает, ну как то все сложно и сиюминутно
Код
local F = {0, 0, 0}
local index = 0
local function addElement(x)
    -- Обновляем текущий индекс с учетом кольцевого буфера
    index = (index % 3) + 1
    -- Вставляем новый элемент в текущий индекс
    F[index] = x
    
    -- Для наглядности выводим текущий массив
    local result = {}
    for i = 1, 3 do
        result[i] = F[(index - i + 3) % 3 + 1]
    end
    return result
end
Куда все подевались?
 
Nikolay,  Ну смотрите на моем примере выше при использовании двусвязной очереди, все Вами описанные задачи по сути сводятся к одному задать длину и метод извлечения, то есть ввести входные данные, которые можно менять динамически ведя дополнительные расчеты, или жестко установить. А вот что у меня получилось из примера nikolz, я в кольцевом буфере попытался поменять порядок хранения данных. Ну в общем то и не получается поменять.
Код
Куда все подевались?
 
Цитата
Nikolay написал:
Так и нет ответа, зачем сдвиги, если самое быстрое решение это перезапись элемента и расчет очередного корректного индекса.
А я не уверен что есть сдвиги, алгоритм помнит индексы, обновляет эти индексы.
Сам пример FilterSmooth(), подразумевает что можно менять длину и веса простыми способами.

Ну хорошо если знаете алгоритм, приведите пример алгоритма "самое быстрое решение это перезапись элемента и расчет очередного корректного индекса" динамически меняющего индекс, длину и веса?  
Куда все подевались?
 
nikolz,  Вот так работает
Код
local F = {0, 0, 0}
local function shiftArray(x)
    -- Сдвигаем элементы массива
    F[3] = F[2]
    F[2] = F[1]
    F[1] = x -- Записываем новый элемент в конец массива
    return F -- Возвращаем массив целиком (или можете возвращать только F[1], если нужно)
end

for I=1,10 do
print(shiftArray(I), F[1], F[2], F[3] )
end

table: 0000000002710d50   1   0   0
table: 0000000002710d50   2   1   0
table: 0000000002710d50   3   2   1
table: 0000000002710d50   4   3   2
table: 0000000002710d50   5   4   3
table: 0000000002710d50   6   5   4
table: 0000000002710d50   7   6   5
table: 0000000002710d50   8   7   6
table: 0000000002710d50   9   8   7
table: 0000000002710d50   10   9   8
>Exit code: 0    Time: 0.3958

2. Альтернативное решение с использованием кольцевого буфера

local F = {0, 0, 0}
local index = 0
local function addElement(x)
    index = (index % 3) + 1
    F[index] = x
   return F
end
for I=1,10 do
print(addElement(I), F[1], F[2], F[3] )
end

table: 00000000025a1150   1   0   0
table: 00000000025a1150   1   2   0
table: 00000000025a1150   1   2   3
table: 00000000025a1150   4   2   3
table: 00000000025a1150   4   5   3
table: 00000000025a1150   4   5   6
table: 00000000025a1150   7   5   6
table: 00000000025a1150   7   8   6
table: 00000000025a1150   7   8   9
table: 00000000025a1150   10   8   9
Куда все подевались?
 
Цитата
nikolz написал:
Мне непонятно, в чем его выгода и что же он делает. ------------------Полагаю, что есть другие вариант решения.
Цитата
VPM написал:
Классический кольцевой буфер, также известный как циклический буфер или кольцевая очередь, используется для хранения фиксированного количества последних значений в массиве.
Наверняка есть, Айдар,  выложил свой, я могу в виде класса выложить.
Цитата
nikolz написал:
Если я правильно Вас понял, то вот элементарное альтернативное решение:Кодlocal F={0,0,0}
local function shiftArray(x) local x=F[1] F[1]=F[2] F[2]=F[3] F[3]=x  return x end

Массив F имеет размер как у Вас. В нем хранится последние 3 элемента. При записи нового , первый выталкивается. Что не так? И в чем преимущество Вашего решения?  
Если Вы загрузите в SciTe это пример он не будет работать. Вот я уже попробовал
Код
local F={0,0,0} 
local function shiftArray(x) local x=F[1] F[1]=F[2] F[2]=F[3] F[3]=x  return x end
for I=1,10 do
print(shiftArray(I), F[1], F[2], F[3] )
end
ответы:
0   0   0   0
0   0   0   0
0   0   0   0
0   0   0   0
0   0   0   0
0   0   0   0
0   0   0   0
0   0   0   0
0   0   0   0
0   0   0   0
>Exit code: 0    Time: 0.4064
Куда все подевались?
 
Цитата
Nikolay написал:
Прежде чем кидать примеры, необходимо понимать зачем и как это будет использоваться.
Так именно это я и отношу в не достаток такого подхода
Цитата
VPM написал:
Я привел пример, с указанием на недостатки - для кольцевого буфера, извлечение данных зависит от конкретного сценария использования и потребностей, и указал на лучший подход
По сложности не намного сложней описанного Вами подхода, класс удобен, в моем примере (посчитал) аж 5 экземпляров очередей, различного размера, размер легко меняется, как и направление то есть динамичен структуру можно менять в процессе эксплуатации , универсальность (действует принцип по образу и подобию создаются экземпляры)
Динамичность позволяет менять структуру в процессе эксплуатации, например при поиске оптимальных параметров. Универсальность один раз разобрался и забыл.
Да и потом я не настаиваю что это единственный подход, я говорю что это удобно.
Куда все подевались?
 
Судите сами вот тот же пример. Изменение класса Ehlers.ChannelPDF, чтобы использовать двусвязную очередь для кольцевого буфера.
Код
local Queue = require("QueueClass")  -- класс Queue сохранен в файле QueueClass.lua

Ehlers.ChannelPDF = {}
Ehlers.ChannelPDF.__index = Ehlers.ChannelPDF
function Ehlers.ChannelPDF.new(FSettings, ds)
    local self = setmetatable({}, Ehlers.ChannelPDF)
    
    self.FSettings = FSettings or {}
    self.ds = ds
    self.P = FSettings.period or 4
    self.up = FSettings.up or 1.0
    self.dw = FSettings.dw or -1.0
    
    self.I1 = 0
    self.hh, self.ll = 0, 0
    
    self.Lead = Queue.new()
    
    self:initialize()
    
    return self
end
function Ehlers.ChannelPDF:initialize()
    self.fTransformFisher = self:TransformFisher()
    self.fTransformIFisher = self:TransformIFisher()
    
    self.fFilterSmooth = self:FilterSmooth()
    self.fFilterLead = self:FilterLead()
    
    self.I1 = 0
    self.Lead = Queue.new()
end

function Ehlers.ChannelPDF:FilterSmooth()
    local F = Queue.new()
    return function(I, x)
        if I == 1 then
            F = Queue.new()
            for _ = 1, 3 do F:push_right(0) end
        end
        F:pop_left()
        F:push_right(x)
        local y = 2 * F[1] + F[2] - F[3]
        y = y and (y >= 1 and 0.999 or y <= -1 and -0.999 or x) or y
        return y
    end
end

Называть наверно следует, кольцевая очередь, используется для хранения фиксированного количества последних значений в массиве
Куда все подевались?
 
nikolz,  Ну Вы в своем амплуа, целую повесть я тут написал
Цитата
VPM написал:
Расписал подробно для общего понимания вопроса
Это моя реализация (частный случай но показательный) как можно использовать
Цитата
VPM написал:
Классический кольцевой буфер, также известный как циклический буфер или кольцевая очередь, используется для хранения фиксированного количества последних значений в массиве.
Айдар,  попросил мой вариант
Цитата
Айдар написал:
Выложи пожалуйста свой вариант кольцевого буфера, мне тоже он был нужен, вот что через gpt получилось (может кому-то нужно):
Я привел пример, с указанием на недостатки - для кольцевого буфера, извлечение данных зависит от конкретного сценария использования и потребностей, и указал на лучший подход
Цитата
VPM написал:
Но есть подход лучше - использовать двусвязную очередь для реализации кольцевого буфера!
двусвязную очередь мы ранее обсуждали этому вопросу посвящалась целая ветка. Могу сказать как использую, у меня это модуль - класс, подгрузил в начале алгоритма
local Queue = require("QueueClass") и делаешь необходимое количество экземпляров определенной длины, определённой направленности, такие как FIFO, LIFO, или извлечение по произвольному условию. В моем примере local ChannelPDF={} это три экземпляра разной длины массивы. И это удобно! А что нужно доказывать я не понимаю. Здесь на мой взгляд просто нужно пользуетесь, не нужно не пользуетесь. Повторюсь вот модуль
Код
-- класс двусвязной очереди:

local Queue = {}
Queue.__index = Queue
function Queue.new()
    return setmetatable({first = 0, last = -1}, Queue)
end
function Queue:push_left(value)
    local first = self.first - 1
    self.first = first
    self[first] = value
end
function Queue:pop_left()
    local first = self.first
    if first > self.last then error("queue is empty") end
    local value = self[first]
    self[first] = nil  -- to allow garbage collection
    self.first = first + 1
    return value
end
function Queue:push_right(value)
    local last = self.last + 1
    self.last = last
    self[last] = value
end
function Queue:pop_right()
    local last = self.last
    if self.first > last then error("queue is empty") end
    local value = self[last]
    self[last] = nil  -- to allow garbage collection
    self.last = last - 1
    return value
end
return Queue
Куда все подевались?
 
Классический кольцевой буфер, также известный как циклический буфер или кольцевая очередь, используется для хранения фиксированного количества последних значений в массиве.
Кольцевой буфер реализован в виде массива фиксированного размера (в данном случае из трех элементов) и индекса, который отслеживает текущее положение для записи нового значения. Когда индекс достигает конца массива, он обнуляется, что позволяет использовать массив циклически.
Инициализация: В начале работы буфер заполняется нулями, и индекс указывается на первый элемент.
Обновление:
  - При каждом вызове функции новое значение записывается в текущий индекс буфера.
  - После записи индекс обновляется. Если индекс достигает конца массива, он обнуляется (возвращается к началу массива)
Обработка данных: Для выполнения вычислений используются значения из буфера.
Именно здесь появляются не удобство применения классического кольцевого буфера!
То есть, значения записываются 1,2,3, и снова 1,2,3, ...

Пример реализации методов с использованием кольцевого буфера:
Кольцевой буфер в классе `Ehlers.ChannelPDF` используется для хранения последних трех значений, которые обновляются при каждом новом баре.
Буфер работает по принципу FIFO, где новое значение заменяет самое старое значение, и обеспечивается циклический доступ к элементам массива
Код
-- Метод FilterSmooth
local ChannelPDF={}
function ChannelPDF:FilterSmooth()
    local F = {0, 0, 0}  -- кольцевой буфер на 3 элемента
    local index = 1
    local start = true
    return function(I, x)
        if I == 1 or start then
            F = {0, 0, 0} -- Инициализация значений
            index = 1 -- Инициализация индекса
            start = false
        end
        F[index] = x -- Обновление (новое значение)
        local y = F[index] + 2 * F[(index - 1 - 1) % 3 + 1] + F[(index - 2 - 1) % 3 + 1]
        y = y and (y >= 1 and 0.999 or y <= -1 and -0.999 or x) or y
        index = index % 3 + 1 -- Обновление индекса
        return y
    end
end
Циклическая запись данных и последовательная индексация свечей, приводит к сложностям (по крайней мере для меня) при получении данных из буфера и их последующей обработкой в формулах.
Для небольших задач пойдет. Но есть подход лучше - использовать двусвязную очередь для реализации кольцевого буфера!
Расписал подробно для общего понимания вопроса.  
Куда все подевались?
 
Ну господа, на Вас не угодить!  :smile:
Форум конечно не про Марс и не про жизнь на МОЕХ, форум про глюки, которыми радуют разработчики.
Данная веточка же про возможности организации алгоритмической торговли, не смотря ни на какие глюки, с помощью языка луа, по крайней мере так ее воспринимаю.
Позволю себе не согласиться, что все уже обсудили, у меня вопросов больше, чем ответов начиная от технологических, и заканчивая стратегиями.
Согласен gpt простые вопросы помогает решать. Но сколько копий сломано, пока разобрался с кольцевым буфером, возможно для кого то просто и понятно,
но у меня это заняло "вагон и маленькую тележку" времени. А ведь прием классный для работы с памятью. Возможно снова велосипед, но вспомнил, про двухфакторную очередь (которую выкладывал), на ее основе реализовал буфер (надо наверно выложить, может кому с экономит то самое время, которое сможет потратить на зарабатывание своих миллионов).
Лето, отпуска конечно ликвидность упала, протолкнуть объемы сложно, тут и самое время обсудить стратегии капитал менеджмента.
Индикатор insidebar, Написать индикатор
 
Посмотрите внимательней вы пропустили строку

local string_upper,string_sub=string.upper,string.sub;

поставьте перед функцией function Value(I,VType,ds)
Индикатор insidebar, Написать индикатор
 
Цитата
Skyrider50 написал:
VPM, все так, но нет. lua 5.4.1
В квике: система - настройки - основные - луа скрипты, вообще то хотя я и пишу в среде 5.4 но тут нет ничего такого что не воспроизвёл бы даже луа 5.1
Индикатор insidebar, Написать индикатор
 
Что в списке было удобно и быстро находить измените имя индикатора например так
Settings.Name = "1Structure";
это будет самописные блокировать в группу а Ваш поиск будет всегда с одного знака начинаться, просто удобно.
Индикатор insidebar, Написать индикатор
 
В блокноте это ANSI
Индикатор insidebar, Написать индикатор
 
Нужен формат 1251, воспользуйтесь стандартным блокнотом, скопируйте и сохраните в этом формате, проверь настройки квик там поставьте lua 5.4  
Индикатор insidebar, Написать индикатор
 
Да действительно, вот исправленный проверил у себя, пробуйте
local string_upper,string_sub=string.upper,string.sub;
function Value(I,VType,ds)
   
   local Out = nil
   local VType=(VType and string_upper(string_sub(VType,1,1))) or "A"
if VType == "O" then --Open
Out = (O and O(I)) or (ds and ds:O(I))
elseif VType == "H" then --High
Out = (H and H(I)) or (ds and ds:H(I))
elseif VType == "L" then --Low
Out = (L and L(I)) or (ds and ds:L(I))
elseif VType == "C" then --Close
Out = (C and C(I)) or (ds and ds:C(I))
elseif VType == "V" then --Volume
Out = (V and V(I)) or (ds and ds:V(I))
elseif VType == "X" then --DateTime
Out = (T and T(I)) or (ds and ds:T(I))
elseif VType == "A" then --Any
if ds then Out = ds[I] end
end
return Out
end
function Structure()
   local I1 = 0
   local Structura = 0

   return function(I, FS, ds)
       I = I or 1
       ds = ds or nil
       FS = FS or {}
       local p = FS.persent or 4 -- %
       local wid = FS.wid or 0

       local o0 = Value(I, 'O', ds) or 0
       local c0 = Value(I, 'C', ds) or o0
       local h0 = Value(I, 'H', ds) or c0
       local l0 = Value(I, 'L', ds) or c0

       if I == 1 then
           I1 = 0
           Structura = 0
       end

       local flag = h0 and l0 and c0 and o0 or false

       local o1 = I > 1 and Value(I-1, 'O', ds) or o0
       local c1 = I > 1 and Value(I-1, 'C', ds) or c0
       local h1 = I > 1 and Value(I-1, 'H', ds) or h0
       local l1 = I > 1 and Value(I-1, 'L', ds) or l0
       local flag1 = I > 1 and flag and h1 and l1 or false

       local h2 = I > 2 and Value(I-2, 'H', ds) or h1
       local l2 = I > 2 and Value(I-2, 'L', ds) or l1
       local flag2 = I > 2 and h2 and l2 and flag1 and flag or false

       local newbar = I > I1

       -- Определение типов баров
       local up_bar1 = flag2 and h1 > h2 and l1 >= l2 or false
       local down_bar1 = flag2 and l1 < l2 and h1 <= h2 or false
       local inbar1 = flag2 and h1 <= h2 and l1 >= l2 or false
       local outbar1 = flag2 and h1 > h2 and l1 < l2 or false
       local outbar_up1 = outbar1 and c1 > o1 or false
       local outbar_down1 = outbar1 and c1 <= o1 or false

       local outbar0 = flag1 and h0 > h1 and l0 < l1 or false
       local outbar_up0 = outbar0 and c0 > o0 or false
       local outbar_down0 = outbar0 and c0 < o0 or false
       local up_bar0 = flag1 and h0 > h1 and l0 >= l1 or false
       local down_bar0 = flag1 and l0 < l1 and h0 <= h1 or false
       local inbar0 = flag1 and h0 < h1 and l0 > l1 or false

       local event = newbar and (outbar0 or up_bar0 or down_bar0) or false

       local struc = (outbar_up0 or up_bar0) and 1 or (outbar_down0 or down_bar0) and -1 or 0
       local structura = Structura
       Structura = (newbar or event) and Structura + struc or structura

       I1 = I
if newbar and inbar1 then SetValue(I-1,1,l1 ) end
if newbar and outbar1 then SetValue(I-1,2,h1 ) end
       --return newbar and inbar1 and li or nil, newbar and outbar1 and h1 or nil
  end
end

Settings={};
Settings.Name = "Structure";

local f;
function Init()

f=Structure();
Settings.line = {
{Name = "InBar",Color = RGB(0, 0, 255), Type = TYPE_POINT, Width = 3},
{Name = "OutBar",Color = RGB(255, 0, 255), Type = TYPE_POINT, Width = 3},
};
return #Settings.line;
end
function OnCalculate(index)
return f( index,Settings )
end
Индикатор insidebar, Написать индикатор
 
Все таки напутал, нужно заменить строку
return newbar and inbar1 or nil, newbar and outbar1 or nil
на
return newbar and inbar1 and l1 or nil, newbar and outbar1 and h1 or nil

Должен выводить точки в момент появления новой свечи
Индикатор insidebar, Написать индикатор
 
Код
Попробуйте так, должен выводить внутренний бар и внешний бар поглощения. надеюсь ничего не напутал, давно не пользуюсь, но это самый простой и понятный вариант.

function Structure()
    local I1 = 0
    local Structura = 0

    return function(I, FS, ds)
        I = I or 1
        ds = ds or nil
        FS = FS or {}
        local p = FS.persent or 4 -- %
        local wid = FS.wid or 0

        local o0 = Value(I, 'O', ds) or 0
        local c0 = Value(I, 'C', ds) or o0
        local h0 = Value(I, 'H', ds) or c0
        local l0 = Value(I, 'L', ds) or c0

        if I == 1 then
            I1 = 0
            Structura = 0
        end

        local flag = h0 and l0 and c0 and o0 or false

        local o1 = I > 1 and Value(I-1, 'O', ds) or o0
        local c1 = I > 1 and Value(I-1, 'C', ds) or c0
        local h1 = I > 1 and Value(I-1, 'H', ds) or h0
        local l1 = I > 1 and Value(I-1, 'L', ds) or l0
        local flag1 = I > 1 and flag and h1 and l1 or false

        local h2 = I > 2 and Value(I-2, 'H', ds) or h1
        local l2 = I > 2 and Value(I-2, 'L', ds) or l1
        local flag2 = I > 2 and h2 and l2 and flag1 and flag or false

        local newbar = I > I1

        -- Определение типов баров
        local up_bar1 = flag2 and h1 > h2 and l1 >= l2 or false
        local down_bar1 = flag2 and l1 < l2 and h1 <= h2 or false
        local inbar1 = flag2 and h1 <= h2 and l1 >= l2 or false
        local outbar1 = flag2 and h1 > h2 and l1 < l2 or false
        local outbar_up1 = outbar1 and c1 > o1 or false
        local outbar_down1 = outbar1 and c1 <= o1 or false

        local outbar0 = flag1 and h0 > h1 and l0 < l1 or false
        local outbar_up0 = outbar0 and c0 > o0 or false
        local outbar_down0 = outbar0 and c0 < o0 or false
        local up_bar0 = flag1 and h0 > h1 and l0 >= l1 or false
        local down_bar0 = flag1 and l0 < l1 and h0 <= h1 or false
        local inbar0 = flag1 and h0 < h1 and l0 > l1 or false

        local event = newbar and (outbar0 or up_bar0 or down_bar0) or false

        local struc = (outbar_up0 or up_bar0) and 1 or (outbar_down0 or down_bar0) and -1 or 0
        local structura = Structura
        Structura = (newbar or event) and Structura + struc or structura

        I1 = I

        return newbar and inbar1 or nil, newbar and outbar1 or nil
   end
end

Settings={};
Settings.Name = "Structure";

local f;
function Init()

f=Structure();
Settings.line = {
{Name = "InBar",Color = RGB(0, 0, 255), Type = TYPE_POINT, Width = 2},
{Name = "OutBar",Color = RGB(255, 0, 255), Type = TYPE_HISTOGRAM, Width = 2},
};
return #Settings.line;

end
function OnCalculate(index)
return f( index,Settings )
end
   
Индикатор insidebar, Написать индикатор
 
Попробуйте такой
Код
function Cached.Structure()
    local I1 = 0
    local Structura = 0

    return function(I, FS, ds)
        I = I or 1
        ds = ds or nil
        FS = FS or {}
        local p = FS.persent or 4 -- %
        local wid = FS.wid or 0

        local o0 = Value(I, 'O', ds) or 0
        local c0 = Value(I, 'C', ds) or o0
        local h0 = Value(I, 'H', ds) or c0
        local l0 = Value(I, 'L', ds) or c0

        if I == 1 then
            I1 = 0
            Structura = 0
        end

        local flag = h0 and l0 and c0 and o0 or false

        local o1 = I > 1 and Value(I-1, 'O', ds) or o0
        local c1 = I > 1 and Value(I-1, 'C', ds) or c0
        local h1 = I > 1 and Value(I-1, 'H', ds) or h0
        local l1 = I > 1 and Value(I-1, 'L', ds) or l0
        local flag1 = I > 1 and flag and h1 and l1 or false

        local h2 = I > 2 and Value(I-2, 'H', ds) or h1
        local l2 = I > 2 and Value(I-2, 'L', ds) or l1
        local flag2 = I > 2 and h2 and l2 and flag1 and flag or false

        local newbar = I > I1

        -- Определение типов баров
        local up_bar1 = flag2 and h1 > h2 and l1 >= l2 or false
        local down_bar1 = flag2 and l1 < l2 and h1 <= h2 or false
        local inbar1 = flag2 and h1 <= h2 and l1 >= l2 or false
        local outbar1 = flag2 and h1 > h2 and l1 < l2 or false
        local outbar_up1 = outbar1 and c1 > o1 or false
        local outbar_down1 = outbar1 and c1 <= o1 or false

        local outbar0 = flag1 and h0 > h1 and l0 < l1 or false
        local outbar_up0 = outbar0 and c0 > o0 or false
        local outbar_down0 = outbar0 and c0 < o0 or false
        local up_bar0 = flag1 and h0 > h1 and l0 >= l1 or false
        local down_bar0 = flag1 and l0 < l1 and h0 <= h1 or false
        local inbar0 = flag1 and h0 < h1 and l0 > l1 or false

        local event = newbar and (outbar0 or up_bar0 or down_bar0) or false

        local struc = (outbar_up0 or up_bar0) and 1 or (outbar_down0 or down_bar0) and -1 or 0
        local structura = Structura
        Structura = (newbar or event) and Structura + struc or structura

        I1 = I

        if wid == 0 then
            return Structura
        end
        return struc
    end
end
Тикер в индикаторе.
 
Kolossi,  Насчет родственных связей Вы со своей бабушкой пообщайтесь.
Код
function BALVAN() 
       
          local Price={}
 
 return function (I, FSettings, ds)

    local ds=ds
    local FSettings=(FSettings or {})
    local P=(FSettings.period or 9)
    local v_t=(FSettings.v_t or 'C')  
    --------------------------------

    if I == 1 then 

       Price={};  

       local info=getDataSourceInfo(); 

       if info then
               interval,symbol,class = info.interval,info.sec_code,info.class_code
               local sec_info = getSecurityInfo(class_code, sec_code)
       end
    end
 end 
end

Вернули коды и получайте что нужно, не понятно в чем проблема! В примере выше возвращает short_name - короткое имя.
Тикер в индикаторе.
 
Цитата
Kolossi написал:
Споткнулся тут о проблему: в скрипте индикатора нужно обрабатывать свечи для бумаги прошедшей сплит по правилам, отличным от правил обработки других инструментов. Как в скрипте индикатора можно получить наименование тикера обрабатываемой свечи?
Разве существуют универсальные правила обработки сплитов? Причины сплитов могут быть различны: Увеличение ликвидности, Улучшение имиджа, Изменение структуры капитала.
Я столкнулся с неоходимость приведения к общему массштабу.
Цитата
Kolossi написал:
Как в скрипте индикатора можно получить наименование тикера обрабатываемой свечи?
Нужно использовать функцию getSecurityInfo для получения информации о тикере. Вот пример:

local function getTicker(class_code, sec_code)
   local sec_info = getSecurityInfo(class_code, sec_code)
   if sec_info ~= nil then
       return sec_info.short_name
   else
       return nil
   end
end
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
 
Вроде нашел, Логнормальное распределение приращений цен. Предполагается, что приращения логарифмических цен (логарифмические доходности) распределены нормально. Это означает, что если цены актива P(t) следуют логнормальному распределению, то логарифм цен ln(P(t)) следует нормальному распределению. Это предположение основано на наблюдениях, что логарифмы цен часто лучше подходят для нормального распределения  и что цены акций и других финансовых активов не могут быть отрицательными. И здесь нужно вспомнить, не столь далекие события ценообразованию нефти, когда к товару добавляли премию.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
 
Цитата
Nikolay написал:
Логарифм применяют не просто так, а в связи с концепцией непрерывно начисляемой доходностью и логнормальным распределением приращений цен.
Наверняка при моделировании будет удобней пользовать концепцией непрерывно начисляемой доходностей, не совсем уверен что нужно применять при анализе работы торговой системы, и уж точно не стоит отражать в финансовых отчетах?
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
 
nikolz,  Подобные аргументы слышны на этом форуме, чуть ли не через пост. Вы напрасно обижаетесь, назвать подобное ахиней, согласитесь относительно мягко, здесь ни статьи не помогут ни Шекспир.
Цитата
nikolz написал:
'Математически логарифмирование заменяет умножение сложением"
--------
тогда исходя из этого правила
получается, что  2*2=2*log(2)
Круто!
1) Одно из основных фундаментальных свойств логарифмов заключается в том, что они заменяют умножение сложением, нет здесь ни какого моего правила - это свойство логарифмов, возможно забыли?
                           ln(a⋅b)=ln(a)+ln(b)
Это свойство позволяет заменить умножение сложением, что особенно удобно при  анализе временных рядов.
2) Где в Вашем примере хоть что то напоминает операцию сложения  2*2=2*log(2) , вообще что этим хотели сказать???
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
 
Цитата
Nikolay написал:
Цитата
VPM написал:
Отсутствие  строгой терминологии привносит свою лепту и путаницу.
Т.к. это не точная наука, то есть некая девиация. Но все же зарубежные термины уже давно устоялись, рынок там давно живет. Вот когда начинают творческим переводом заниматься, то и возникает путаница.
Справедливости ради, почти все приходит не из русскоязычного сегмента, так что и не стоит пытаться что-то искать по-русски - это будет творческое переосмысление. Правда всегда можно уйти в область обработки сигналов, мат. теории. рядов. Там уже достаточно отечественных материалов по теме.
Но ведь и слег не добавляет точности, волатильность широко вошла в обиход, и под этим названием скрываются несколько смыслов, так как расчеты различны. Один из способов это расчет стандартного отклонения,  если  вместо волатильности произнесли стандартное отклонение, то ту появляется смыслы, сигма, нулевая средняя, нормальное распределение с вероятностями исходов. Родной язык позволяет эти смыслы поддерживать, ну к примеру русский язык строится от корня, корень несет смысл, что уже по себе существенно (отклонился, уклонился приклонился...). В то время как применяя термин на иностранном, он превращается в некую новую переменную, теряя или привнося новые смыслы. Так что и переосмысление бывает полезным. Но лучше с оригинала самому.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
 
Посмотрел внимательней. Нет все таки есть существенная неточность в моих суждениях. В своих расчетах (использую абсолютные значения), расчеты в статье (применяют натуральный логарифм цены), а это более чем существенное отличие. Хотя даже не знаю что лучше использовать, ведь в стать тоже делается допущение "Когда доходность мала, например, всего несколько процентов, мы имеем: г ≈ Ln (1 + г)", когда делаешь расчет с горизонтом год и один день?
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
 
Nikolay,  Спасибо, пробежал бегло, ну в общем тоже известный подход, расчет исторической волатильности, терминология несколько отличается а смысл один, у себя я так и считаю терминология другая, 1) в случае моделирования сделки; 2) при оценки результатов торговой стратегии если достаточно статистики. Отсутствие  строгой терминологии привносит свою лепту и путаницу. Для себя, установил как бы два термина, Доходность - это % приращения, а HPR - когда средняя = 1, это удобно, позволяет переходить из одно системы в другую измеряю по сути одно и тоже используя разные размерности.
HPR = Р2/Р1; относительная доходность = Р2 / Р1 - 1; доходность% = ( Р2 / Р1 - 1) * 100
Сейчас поясню, минмаксная нормировка дает нам размерность [0,1] , где 0 предел (самое маленькое значение), 1 предел (самое большое значение), умножая на 100 уже в процентах, делая перевод [-1,0,1] средняя = 0, получили осциллятор с нормальным распределением. Надеюсь ни кого не запутал?  
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
 
Цитата
Nikolay написал:
Достаточно вспомнить любой расчет волатильности.
Не понял, о каком расчете Вы говорите?
Страницы: Пред. 1 2 3 4 5 6 7 8 9 10 11 ... 24 След.
Наверх