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

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

Страницы: 1 2 3 4 5 6 7 8 9 10 11 ... 21 След.
Имена параметров ТТП и других данных торгового сервера MOEX
 
Anton Belonogov,  Спасибо, за ссылку. Так я и утверждаю что "Тормоза в багажнике".  Ну хорошо, не хотите вести перечень имен таблицы текущих параметров, хотя бы ссылку на инструкцию их получения, закрепите на форуме в явном виде (Часто задаваемые вопросы). Интересно сколько раз пользователи читают инструкцию по использованию телевизора?
Имена параметров ТТП и других данных торгового сервера MOEX
 
Цитата
Anton Belonogov написал:
VPM, добрый день.

С чем с целом связан вопрос? Какая задача решается, для чего нужна эта информация?
Вы наверно пошутили, или не прочитали название данной ветки?
Имена параметров ТТП и других данных торгового сервера MOEX
 
Anton Belonogov,  Все дело в том, что есть права и есть обязанности! Не должен конечный пользователь, добывать информацию "под пытками". В чем сложность публиковать параметры транслируемые Квиком?
Имена параметров ТТП и других данных торгового сервера MOEX
 
Во чудеса! Достаточно странная ситуация?
Цитата
Anton Belonogov написал:
Станислав, добрый день.

Нет, точного соответствия между наименованиями параметров на торговых площадках и в QUIK нет.
Получается QUIK не проста транслирует данные с биржи, но изменяет имена параметров на собственные! При этом их не публикует, для конечного пользователя? О, Чудеса - чудесные! Это в финансовом мире принято что - то не договаривать, в этой ситуации разработчики выступают инженерами и технологами.  Здесь аналогия такая: "посадили за руль автомобиля, с педалью тормоза в багажнике"?
Новый период и время проведения торгов на бирже.
 
nikolz, СУПЕР!!! Еще бы  закрепить, в отдельную тему, для быстрого поиска. Чтобы на конец закрыть этот вопрос.
Новый период и время проведения торгов на бирже.
 
Скрытый текст
Очень долгое выключение терминала
 
Из собственного опыта, скачал у брокера еще одну версию, поставил ее параллельно не работающей, моментально все загрузилось!  :smile:  Вывод что произошло с сохранением данных в предыдущей версии. Давненько не было таких проблем, все работало стабильно, уже и забыл, как с этим справляться. Всем пока, хорошей торговли.  
Очень долгое выключение терминала
 
Ок, спасибо.
Очень долгое выключение терминала
 
Anton Belonogov,  а мне сейчас как быть? Переставлять квик?
Очень долгое выключение терминала
 
Цитата
VPM написал:
Проверил скорость интернета, сбросил лог., сбросил квик  несколько раз для загрузки предыдущих wnd, не помогло.
Да сохранятся, откатился уже к 05.02.25.
Очень долгое выключение терминала
 
Anton Belonogov, Да соединение проходит, пишет "чтение информации о расположении окон" и на этом зависает. Из диспетчера видно , загружает гигабайты, Вчера все норм было.  
Очень долгое выключение терминала
 
Добрый день,

"Ни когда не было и вот опять!". Все утро пытаюсь загрузить квик версия 11.4.1.3. Вернее не так сам квик грузится, но при входе по логину, часами зависает на "чтении информации об окнах", качает себе гигабайты и крутит колесико? Увлекательное зрелище! Проверил скорость интернета, сбросил лог., сбросил квик  несколько раз для загрузки предыдущих wnd, не помогло. Позвонил брокеру, "Сервера работают нормально, пере закажите данные". НЕ помогло?  
Новый период и время проведения торгов на бирже.
 
На моей памяти так, параметры устанавливает биржа, постоянно изменяются, разработчики предлагали выгружать таблицу всех параметров. По логике документацию должна биржа публиковать?
Нужна помощь . торговым алгоритмом
 
Сергей ВАТ,  Вам нужно подтянуть материальную часть. Это далеко не алгоритм, алгоритм - это прежде всего логика и последовательность действий, что совсем отсутствует в Вашем коде. Ниже выкладываю демонстрационный пример, как код должен выглядеть.  Это не торговый, это демонстрация возможностей!
Код
--stopped = false  -- Этот флаг здесь не нужен
function OnStop()
   --stopped = true
   return 5000
end

-- Установки
local Kod_klienta = "10800"; -- нужно поставить свое значение
local Torg_schet = "NL0011100043"; -- нужно поставить свое значение
local CLASS_CODE = "QJSIM" -- Код класса
local SEC_CODE = "SPBE" -- Код бумаги
local Kod_FirM = "NC0011100000" -- Код фирмы
local step_grid = 5

local run = true -- флаг работы скипта
function main()
    
   -- один раз получает шаг цены (так как величина постоянная)
    local step_price = getParamEx(CLASS_CODE, SEC_CODE, "SEC_PRICE_STEP").param_value

  while run do
    --в цикле каждые милисекунды (sleep(10000)) обновляем цену перед расчетом нового уровня
    local Sena = getParamEx(CLASS_CODE, SEC_CODE, "LAST").param_value
    -- Расчет 10 уровней с шагом сетки step_grid = 5
    for i = 1, 10 do
    
        -- расчет сдвига цены (сетка)
      Sena = Sena + i * step_price * step_grid 

      local podgot = {
                        ACCOUNT = Torg_schet,
                        CLIENT_CODE = Kod_klienta,
                        TYPE = "L",
                        TRANS_ID = "1",
                        CLASSCODE = CLASS_CODE,
                        SECCODE = SEC_CODE,
                        ACTION = "NEW_ORDER",
                        OPERATION = "B",
                        PRICE = tostring(Sena),
                        QUANTITY = "1"
                        }
      --Отпровляется транзакция
        --if -- Условия для выхода из расчета
          sendTransaction(podgot) 
      --then break; end;
    end
       
   sleep(10000)
  end
end
отправка заявки из скрипта Lua
 
__spb13__,  С кодом у Вас, все в порядке. Перед основным циклом, Вы задаете инструмент по которому хотите работать, он загружается один раз перед выполнением цикла, а дальше вся работа идет в цикле.
       sec_code = 'SU26219RMFS4'
       -- infinite loop to compensate for problems with getting the price
       while true do
Цитата
__spb13__ написал:
Но только если в окне "Текущая таблица параметров" выбрана вот та самая бумага - 'SU26219RMFS4'. Это ОФЗ.Выбираешь в окне другую и нужно менять код в скрипте.
У вас окна квика привязаны к  таблице текущих параметров, для того чтобы отключить эту функцию, нужно сбросить якоря(в верхнем углу стакана горит цветная кнопка, встаете на нее л.кнопка мыши "отключить"). Чтоб работал Этот код должен быть открыт стакан по данному инструменту. quoteLevel = getQuoteLevel2('TQOB', sec_code). в вашем случае,  sec_code = 'SU26219RMFS4'.
Если хотите добавить работу с портфелем бумаг вместо sec_code = 'SU26219RMFS4', создайте таблицу sec_codes = {'SU26219RMFS4', ...,} и в цикле перебирайте эту таблицу.

Код
 
local sec_codes = {'SU26219RMFS4', ...}

 -- infinite loop to compensate for problems with getting the price
        while true do

         for _, sec_code in ipairs(sec_codes) do

            quoteLevel = getQuoteLevel2('TQOB', sec_code)
            if quoteLevel.offer then
                pc = tonumber(quoteLevel.offer[1].price)
            end
            if pc == 0 or pc < 0 or pc == nil then
                co.toLog(sn, '    still nothing...')
                sleep(math.random(1000, 2000))
            else
                break
            end
         end
        end
       
отправка заявки из скрипта Lua
 
__spb13__,  С перового прочтения сформулированный Вами  вопрос, сильно смахивает на каламбур, рассмешил, извините еще раз.  Касаемо вопроса.
1) Квик действительно нужно настроить под себя, в открытом окне развернуть необходимые для работы таблицы. Зайти в настройки и установить умный заказ. Более подробно, на сайте есть от разработчиков, по моему первые посты.
2) цену в скрипте можно получать разными способами: с подпиской, с графика, из таблицы текущих параметров, стакана и так далее.
3) То что Вы описываете, поведение не совсем характерное, для понимания проблемы, лучше показать код, где получаете цену и как пытаетесь вывести ее в ордере.
отправка заявки из скрипта Lua
 
spb13 Это лучшей вопрос, за время которое я провел на сайте просто супер, только не обижайтесь "ради  бога"! :smile:  :smile:  :smile:  
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
 
Megafan,  Спасибо за уточнение. Не проверял, микро добавил по аналогии для демонстрации возможности, свою метку ограничиваю мили, что вполне хватает для моей задачи оценки актуальности.
nikolz,   то что данные приходят с некоторым лагом в программу, это и так понятно, это другая задача, моя же задача проверки актуальности данных, сводится к уже полученным и на копленным данным. И причина в необходимости проверки заключается, в асинхронности обработки двух разных быстрых таблиц в различных корутинах. Ведь дальше следует вывод и принятие решения. То есть, проверить данные полученные из стакана на соответствие данным полученным из т. всех сделок!
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
 

Про актуальность данных. nikolz,  поднял важную тему. Пришлось призадуматься,  ведь если при последовательной обработке таблиц не очень  и нужны временные метки.  В варианте с обработкой таблиц в разных сопрограмма уже не обойтись, без них. Есть вариант стакан и таблицу всех сделок обрабатывать последовательно в одной сопрограмме, но таблицы очень быстрые, да и легких путей не ищу. :smile:

Пересмотрев внимательней статью выложенную Nikolay,  обратил внимание, на запись данных книги ордеров, кроме стандартного времени, есть запись временной метки!

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

Код
-- Получаем дату и время
local sysdate = os.sysdate()
-- Создаем строку временной метки с точностью до микросекунд
local timestamp = string.format("%04d-%02d-%02d %02d:%02d:%02d.%03d.%03d", sysdate.year, sysdate.month, sysdate.day, sysdate.hour, sysdate.min, sysdate.sec, sysdate.ms, sysdate.mcs)
-- Выводим временную метку
print("Timestamp with microsecond precision:", timestamp)

Пример временной метки: 2025-02-11 14:12:52.123.456

Здесь:

  • 2025-02-11 — это дата (год, месяц, день).
  • 14:12:52 — это время (часы, минуты,
        секунды).
  • .123 — это миллисекунды.
  • .456 — это микросекунды.

Для чего все это? Как вызываются сопрограммы, пока им одним ведома? В моем варианте данные собираю в очереди, пришлось и их переделать, в одну универсальную, чтоб не привязываться конкретно к таблицам, добавил  метаданные, ну конечно и временной штамп.

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

2.    Все данные о времени в одном формате, что удобно для сортировки, фильтрации и анализа.

3.    Функция использует системные вызовы, что гарантирует реальное время, а не время процессора.

Если бы мне сказали, когда я начинал собирать свою программу, что она достигнет такой сложности,  я бы просто не поверил. А мне за букварь надо со всем этим разбираться!

Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
 
Да, спасибо, в переводном варианте есть ссылка на оригинал, перевел для себя, но все равно до конца все не понял. Кумулятивный спрос и предложения вывожу на график, а в алгоритме тоже нормирую, для понимания настроений. Мой же подход, краткосрочно забрать 10 пунктов, для этого, на какой стороне заходить и предлагаю алгоритм, оценки этой стороны. А логика простая, чтоб набрать крупную позицию, сегодня вынуждены двигать цены в стакане в сторону набора, в погоне за ликвидностью. Вернутся деньги в рынок, наверняка все будет по другому. Ну и конечно одного этого недостаточно.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
 
Nikolay, За информацию спасибо! Согласен с Вами, меня собственно подтолкнул, отчет моего брокера, который оценил участников на рынке, 70% частники, то есть крупному игроку негде разгуляться, отсюда следует что должны приспосабливаться и  приводит свои алгоритмы под текущую ситуацию. Обратил внимание на стакан, MM в обеспечение своих обязательств, приходится чаще набирать позиции на слабой стороне, таковы реалии сегодня. Второе, опробовал технологию асинхронности обработки таблиц (затолкал данные от колбэков в сопрограммы, с небольшими очередями), что позволяет выполнять описанный выше алгоритмы. Ну и последнее, задача стоит для общей торговой системы, сделать разные модули торговых стратегий, с авто переключением между ними, такие амбиции, пока не понятно что из этого выйдет? Но одновременная работа трендовой и реального времени вполне приемлема, по крайней мере вижу куда двигаться. Но и самое главное надеюсь что подход избавит от постоянной переделки системы, с использованием стратегий в модулях.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
 
nikolz, Собственно этот алгоритм продолжение этой темы https://forum.quik.ru/messages/forum10/message77319/topic8859/#message77319, корректирую архитектуру торговой системы и привожу структуру данных. Этот алгоритм один из модулей торговой стратегии стратегия "скальперской", задачей которого является оценка ликвидности в стакане, ответ на вопрос на чьей стороне. Формализация алгоритма необходима для применения в алгоритмической торговле. Что делает алгоритм, еще раз, нормируем, переводит в диапазон -1/+1, Фишер нужен для выделения хвостов (в диапазоне -0.5/+0.5 передается практически линейно, значения выше с лог. зависимостью, не создает задержек). Статистика в водится,  если можно так сказать, для оценки результатов и их стабилизации. Периоды накопления данных для такой оценки регулирую в зависимости от инструмента и необходимости. Ни какого прогноза, оцениваем что происходит, конечно с неким лагом. Метрики применяю обычные, тенденция, импульс ... Для чего для поддержки принятия решений в краткосрочных стратегиях. На счет актуальности, ну конечно, если даже данные пришли за вчера! На счет применения каждый решает сам, подход я озвучил, привел пример с нечеткой логикой, для сглаживания переходных процессов и задания зон принадлежности. Любой может взять и попробовать.  
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
 
Накидал небольшой пример для отладки, проверил вроде рабочий, прикручу посмотрим.
Код
---------------------------------
-- Константы для правила трех сигм
---------------------------------
local mean_bid = 0   -- Среднее значение ликвидности Bid (можно обновлять)
local std_bid = 0.3  -- Стандартное отклонение ликвидности Bid
local mean_ask = 0   -- Среднее значение ликвидности Ask (можно обновлять)
local std_ask = 0.3  -- Стандартное отклонение ликвидности Ask

local sigma_threshold = 3  -- Граница трех сигм

---------------------------------
-- Функция проверки трех сигм
---------------------------------
function check_three_sigma(bid_liq, ask_liq)
    local bid_outlier = (bid_liq > mean_bid + sigma_threshold * std_bid) or (bid_liq < mean_bid - sigma_threshold * std_bid)
    local ask_outlier = (ask_liq > mean_ask + sigma_threshold * std_ask) or (ask_liq < mean_ask - sigma_threshold * std_ask)

    return bid_outlier, ask_outlier
end

---------------------------------
-- Создаем нечеткую систему
---------------------------------
local fuzzy = luafuzzy()

---------------------------------
-- Входные переменные (нормализованная ликвидность)
---------------------------------
-- Ликвидность Bid
local bid_liq = fuzzy:addinp('bid_liq', -1, 1)
bid_liq:addlingvar('low', gaussmf, { 0.3, -1.0 })  
bid_liq:addlingvar('medium', gaussmf, { 0.3, 0.0 }) 
bid_liq:addlingvar('high', gaussmf, { 0.3, 1.0 })  

-- Ликвидность Ask
local ask_liq = fuzzy:addinp('ask_liq', -1, 1)
ask_liq:addlingvar('low', gaussmf, { 0.3, -1.0 })  
ask_liq:addlingvar('medium', gaussmf, { 0.3, 0.0 }) 
ask_liq:addlingvar('high', gaussmf, { 0.3, 1.0 })  

---------------------------------
-- Выходная переменная (решение)
---------------------------------
local decision = fuzzy:addout('decision', 0, 10)
decision:addlingvar('sell', trimf, { 0, 2, 4 })   
decision:addlingvar('hold', trimf, { 3, 5, 7 })  
decision:addlingvar('buy', trimf, { 6, 8, 10 })  

---------------------------------
-- Правила нечеткой логики
---------------------------------
-- 1. Если Bid высокий и Ask низкий > Покупка
local r1 = fuzzy:addrule(1, 'andmethod')
r1:addpremise(false, 'bid_liq', 'high')
r1:addpremise(false, 'ask_liq', 'low')
r1:addimplic(false, 'decision', 'buy')

-- 2. Если Bid низкий и Ask высокий > Продажа
local r2 = fuzzy:addrule(1, 'andmethod')
r2:addpremise(false, 'bid_liq', 'low')
r2:addpremise(false, 'ask_liq', 'high')
r2:addimplic(false, 'decision', 'sell')

-- 3. Если Bid и Ask средние > Удержание позиции
local r3 = fuzzy:addrule(1, 'andmethod')
r3:addpremise(false, 'bid_liq', 'medium')
r3:addpremise(false, 'ask_liq', 'medium')
r3:addimplic(false, 'decision', 'hold')

---------------------------------
-- Функция получения торгового решения с учетом трех сигм
---------------------------------
function get_trade_decision(bid_norm, ask_norm)
    -- Проверяем выбросы по правилу трех сигм
    local bid_outlier, ask_outlier = check_three_sigma(bid_norm, ask_norm)

    if bid_outlier and ask_outlier then
        if bid_norm > 0 and ask_norm < 0 then
            return "STRONG BUY (3-sigma)"
        elseif bid_norm < 0 and ask_norm > 0 then
            return "STRONG SELL (3-sigma)"
        end
    end

    -- Если выбросов нет, используем нечеткую логику
    local result = fuzzy:solve(bid_norm, ask_norm)

    if result < 4 then
        return "SELL"
    elseif result > 6 then
        return "BUY"
    else
        return "HOLD"
    end
end

---------------------------------
-- Пример использования в QUIK
---------------------------------
local bid_liq_value = 0.9  -- Пример нормализованной ликвидности Bid
local ask_liq_value = -0.9  -- Пример нормализованной ликвидности Ask

local decision = get_trade_decision(bid_liq_value, ask_liq_value)
print("Торговое решение: " .. decision)
Запустить скрипт Lua другим скриптом, Запустить скрипт Lua другим скриптом
 
nikolz, Да Вы совершено правы, я лишь хотел подчеркнуть особенность подключения
Цитата
VPM написал:
Функция dofile выполнит Lua-скрипт, и все переменные и функции, определённые в нём, будут доступны в текущем окружении. И смысл здесь в подключении новой задачи!
Ведь есть еще способ  local Utility = require("Utility").
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
 
nikolz, Не совсем понял Ваш вопрос? Применяя Вашу аллегорию, можно пояснить смысл. Если выпитый стакан вчера был с алкоголем, сев сегодня за руль, и подышав в трубочку представителю закона, результат выявлен.
Так и в нашем случае, данные какие получили такие и есть. А задача подхода оценить кто заправляет в стакане, деля резултат алгоритма на 3 категории покупатель, продавец или нейтрально.
Могу добавить что этот модуль, только часть большей задачи. Стакан это настроения, выставляя лимитки мы подменяем ММ и говорим о намерениях, рынок двигают рыночными ордерами это и оцениваем. В большой задаче, примерно также оцениваю Спрос/Предложение, и Настроение на рынке. Сейчас задача объединить анализ настроений с анализом сделок, в сделках уже есть время сделки.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
 
В стратегии реального времени, для автоматической торговли, в системы принятия торговых решений внес изменения, добавил  использование данных о ликвидности в стакане. Давно "руки чесались", алгоритм не сложный, но мест где наделать ошибки достаточно. Вкратце следующий,  получаем данные о ликвидности из стакана, проводится нормировка для преобразования к нормальному распределению, выделяем пиковые значения с помощью преобразования Фишера,  создаем правила на основе нечеткой логики . Думаю еще прикрутить правило 3 сигм для стабилизации результатов, но пока без сигм покручу нужно добиться стабильности. Пока хорошей торговли!
Запустить скрипт Lua другим скриптом, Запустить скрипт Lua другим скриптом
 
Цитата
nikolz написал:
И еще...Нет смысла запускать скрипты с помощью dofile (особенно как в приведенном VPM примере)Так как это лишь замедляет исполнение.---------------dofile имеет смысл применять для разделения большого скрипта на блоки, чтобы упростить чтение и отладку скрипта.
nikolz, Пример выше это просто демонстрация возможностей, ни на что не претендующая.
К примеру у себя использую следующий вариант (кусочек из рабочего код):  
Код
-- Пытаемся загрузить библиотеку
            local fuzzy;
            local success, err = pcall(dofile, path..'\\luafuzzy.lua')
            if not success then
                Log:error("Ошибка при загрузке файла luafuzzy: " .. err)
            else
                -- Если библиотека успешно загружена, используем её
                local fuzzy = luafuzzy()
                Log:info("Библиотека luafuzzy успешно загружена!")
            end

    while WORKING_FLAG do
Перед основным циклом while WORKING_FLAG do 1 раз вызываем "Пан или пропал!" :smile: , ни чего не замедляем, просто Функция dofile выполнит Lua-скрипт, и все переменные и функции, определённые в нём, будут доступны в текущем окружении. И смысл здесь в подключении новой задачи!
Новый период и время проведения торгов на бирже.
 
Станислав, Ok! Спасибо.
Новый период и время проведения торгов на бирже.
 
Подскажите по каким признакам, можно фильтровать время проведения торговых сессий? Ни как не возьму в толк, с новыми изменениями, где начало где конец сессии? Какие активы торгуются? На какой бирже?
Запустить скрипт Lua другим скриптом, Запустить скрипт Lua другим скриптом
 
Nikolay,  Согласен, вопрос составлен не четко, двусмысленно. Но ведь он звучит все таки так:
Цитата
Saturn написал:
То есть один Kua скрипт запущенный в цикле проверял бы если другой Lua скрипт не запущен - то запустить его.
Ответ: Да, это возможно. В Lua можно запустить другой Lua-скрипт с помощью функции dofile или loadfile. Вы можете создать основной скрипт, который будет проверять, запущен ли другой скрипт, и если нет, то запускать его.
Вот такого подхода пример:
Код
-- основной скрипт (main.lua)
local is_other_script_running = false
-- Функция для проверки, запущен ли другой скрипт
function check_if_other_script_running()
    -- Здесь можно реализовать проверку, например, через файл или глобальную переменную
    -- В данном примере просто используем переменную для демонстрации
    return is_other_script_running
end
-- Функция для запуска другого скрипта
function run_other_script()
    is_other_script_running = true
    dofile("other_script.lua")  -- Запуск другого скрипта
    is_other_script_running = false
end
-- Основной цикл
while true do
    if not check_if_other_script_running() then
        print("Другой скрипт не запущен, запускаю...")
        run_other_script()
    else
        print("Другой скрипт уже запущен.")
    end

    -- Пауза перед следующей проверкой
    os.execute("sleep 1")  -- Для Linux/MacOS
    -- os.execute("timeout /t 1")  -- Для Windows
end
Никаких принципиальных сложностей. В этом примере: Основной скрипт (main.lua) работает в бесконечном цикле. Он проверяет, запущен ли другой скрипт (other_script.lua), с помощью функции check_if_other_script_running. Если другой скрипт не запущен, он запускает его с помощью dofile("other_script.lua"). После завершения работы другого скрипта, флаг is_other_script_running сбрасывается.

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

Разбираясь в работе Quik и функциональных возможностях Lua, иногда можно запутаться, и тогда трезвый взгляд со стороны помогает всё расставить по местам. Для меня таким взглядом всегда был Nikolay. И сейчас я бы не стал вмешиваться в эту дискуссию, если бы не ответы!

Да, это возможно! В Lua действительно можно запустить другой Lua-скрипт с помощью функций dofile или loadfile. Вы можете создать основной скрипт, который будет проверять, запущен ли другой скрипт, и если нет — запускать его. Все это и так явно.

Но почему бы не пойти дальше? Хочу озвучить другой подход.

Давайте забудем про все языки (Си, C#, да и про Fortran с Basic я забыл ещё со студенческих времён). Что у нас есть?

  • API Quik: разработчики любезно предоставили нам возможность через Lua получать данные от брокера и отправлять приказы (заявки) брокеру.

  • Функционал Lua: вот здесь начинается самое интересное!

Представим, что поток main — это основной поток (другого ничего нет), в котором всё крутится (в этом легко убедиться, запустив его без задержек).
Функционал Lua предоставляет лёгкие потоки, которые работают внутри основного потока — они называются корутины.

Что они делают? Любые программы, блоки, модули, функции — всё это можно запускать в корутинах! Причём не только последовательно, но и асинхронно.

Таким образом, функция main(), будучи запущенной, превращается в сложнейшую программу, способную не только явно но и в фоновом режиме выполнять что угодно: получать данные, проводить расчёты, подключать и останавливать модули и многое другое.

К чему я так подробно рассказываю? Напишите в своей программе модуль на Lua (это та же таблица)  который хотите запустить, и используйте его где угодно.

Это открывает огромные возможности для создания гибких и мощных решений.

Дата и время позиции
 
Коллбек как источник данных, для асинхронной обработки данных.
Довел вариант до рабочего, в качестве источника данных OnAllTrade, получаем таблицу и переносим расчеты, не в маин, в сопрограмму. Такой подход не блокирует выполнение других операций программы, если количество сделок большое, или сделка обрабатывается долго, которые запущены в процессе. Производительность и нагрузки просто супер. Задание паузы между итерациями обработки позволяет контролировать частоту обработки данных, что полезно для предотвращения перегрузки системы, а также задает временные промежутки для накопления данных в очередь.    
Этот подход позволяет не только улучшить структуру кода, но и легко расширять систему с новыми метриками и функциональностью. Каждый компонент изолирован и отвечает только за свою часть. Легко добавлять или менять логику внутри каждого модуля, не влияя на другие части системы. А также, можно добавлять новые метрики или алгоритмы, расширяя существующие возможности самой программы. Собраны метрики и алгоритмы в отдельные модули. Каждый модуль может экспортировать только необходимые функции и данные, позволяя другим частям системы использовать их через интерфейсы, что должно помочь избежать излишней зависимости между компонентами. Метрики можно групировать по стратегиям. Система принятия решений будет интегрировать метрики, анализировать их с использованием различных стратегий и на основе результатов принимать решение о торговых действиях.
Основными компонентами такой системы принятия решений будут:
1. Метрики – используем различные метрики для анализа данных.
2. Стратегии – каждая стратегия (скальпинг, трендовая торговля, арбитраж) будет использовать различные метрики для принятия решений.
3. Алгоритм принятия решений – будет выбирать, какая стратегия должна быть использована в текущих условиях рынка и какое действие (купить/продать) должно быть выполнено.
4. Система обработки данных – будет собирать данные (например, цены и объемы), передавать их в соответствующие стратегии и использовать метрики для анализа.
В моем случае придется, переосмыслить архитектуру основной программы - добавить универсальности, но и наконец то, выхожу на однотипную структуру данных для такой программы, под гордым названием с большой буквы Робот.
Пока, Всем хорошей торговли!
Дата и время позиции
 
Не знаю почему не получается сворачивать окно у меня. Подскажите последовательность нажатия конок?
Хотел предложить на обсуждение еще один вариант, обработки сделок уже т. всех сделок с использованием очереди. По факту даже два варианта. 1) обрабатываем в маин. 2) асинхронный. Как раз перерабатываю, чтобы модуль добавить в программу.
Дата и время позиции
 
Касаемо обработки собственных сделок, была а возможно и есть программа написана на qpl, называется Калькулятор уровней позиции: (q_calc) автор Николай Морошкин. На ней учился переписывая на луа логику. Выкладываю как возможный пример обработки сделок, просто в нем есть четкая логика, на ошибки нужно проверять.
Код
function detect_position()

    --[[ Проверки статуса заявок (1-й и 2-й биты flags):
    "Активна": bit.band(order.flags, 1) > 0
    "Неактивна" (исполнена либо снята): bit.band(order.flags, 1) == 0
    "Исполнена": bit.band(order.flags, 1) == 0 и bit.band(order.flags, 2) == 0
    "Снята": bit.band(order.flags, 1) == 0 и bit.band(order.flags, 2) > 0

    Нас интересуют два флага:
    OF_ACTIVE = 0x01
    OF_KILL = 0x02
    --]]

    local ord = "orders"
    local max_numorder = getNumberOf("orders")
    
    -- Отслеживаем количество ордеров
    Log:trace('detect_position: отслеживаю размер массива ' 
              .. ' getNumberOf =' .. tostring(max_numorder) 
              .. ' index =' .. tostring(max_numorder-1)
              .. ' / o_index = ' .. tostring(o_index) 
              .. ' save_needed =' .. tostring(save_needed))

    -- Функция для поиска ордеров
    local function myFind(A, C, S, F)
        return (A == ACCOUNT and C == CLASSCODE and S == SECCODE 
                and bit.band(F, 0x2) == 0 and bit.band(F, 0x1) == 0)
    end
    
    -- Поиск ордеров с нужными фильтрами
    local iItems = SearchItems("orders", 0, max_numorder - 1, myFind, "account,class_code,sec_code,flags")

    -- Проверка на пустой результат
    if not iItems or #iItems == 0 then
        Log:trace('ERROR: SearchItems вернул пустой результат')
        return false
    end

    Log:trace('detect_position: всего элементов ' .. tostring(#iItems) .. ' последний ордер: ' .. tostring(iItems[#iItems]))

    -- Если еще не инициализировано
    if initialized == 0 then
        initialized = -1
        return
    end

    -- Обработка ордеров
    for i = o_index, #iItems do
        local order = getItem("orders", iItems[i])
        if not order or type(order) ~= "table" then return false end

        -- Определение флагов состояния ордера
        local OF_ACTIVE = bit.band(order.flags, 1) > 0
        local NOT_ACTIVE = bit.band(order.flags, 1) == 0
        local OF_FILL = bit.band(order.flags, 1) == 0 and bit.band(order.flags, 2) == 0
        local OF_KILL = bit.band(order.flags, 1) == 0 and bit.band(order.flags, 2) > 0
        
        if order.account == ACCOUNT and order.class_code == CLASSCODE and order.sec_code == SECCODE 
            and (OF_FILL or OF_ACTIVE) and not Orders[order.order_num] then

            Orders[order.order_num] = os.time() -- Запоминаем время

            -- Получаем информацию о заказе
            local order_n = order.order_num
            local order_dt = order.datetime
            local order_d = get_date(order_dt) -- Дата
            local order_t = get_time(order_dt) -- Время
            last_tradedate = order_d

            local order_b = order.balance
            local order_q = order.qty - order_b
            local order_p = order.price
            local order_op = bit.band(order.flags, 0x4) == 0 and 'BUY' or 'SELL'

            -- Логирование активных ордеров
            if OF_ACTIVE then
                Log:trace(NAME_OF_STRATEGY .. ' ' .. i .. ' ACTIVE лимитная заявка по ' .. order.sec_code
                    .. ' number: ' .. tostring(order_n)
                    .. ' ' .. tostring(order_d)
                    .. ' ' .. tostring(order_t)
                    .. ' ' .. tostring(order_op)
                    .. ' ' .. tostring(order_q) .. ' (' .. tostring(order_b) .. ')'
                    .. ' ' .. tostring(order_p))
            end

            -- Обработка исполненных ордеров
            if OF_FILL then
                Log:trace(NAME_OF_STRATEGY .. ' ' .. i .. ' Исполнена лимитная заявка по ' .. order.sec_code
                    .. ' ' .. tostring(order_d)
                    .. ' ' .. tostring(order_t)
                    .. ' ' .. tostring(order_op)
                    .. ' ' .. tostring(order_q) .. ' (' .. tostring(order_b) .. ')'
                    .. ' ' .. tostring(order_p)
                    .. ' number: ' .. tostring(order_n))

                local trade_q = 0
                local trade_p = 0
                local exchange_comission = 0

                -- Поиск сделок, соответствующих ордеру
                for trades_i = 0, getNumberOf("trades") - 1 do
                    local trade = getItem("trades", trades_i)

                    if trade.order_num == order_n then
                        last_order_id = order_n

                        local trade_d = get_date(trade.datetime)
                        local trade_t = get_time(trade.datetime)

                        local qq = trade.qty
                        local pp = trade.price

                        trade_q = trade_q + qq
                        trade_p = trade_p + (qq * pp)
                        exchange_comission = exchange_comission + trade.exchange_comission
                    end
                end

                if trade_q ~= 0 then
                    trade_p = trade_p / trade_q
                    exchange_comission = exchange_comission / trade_q
                end

                -- Проверка на рассинхронизацию заявок и сделок
                if order_q ~= trade_q then
                    Log:trace("Рассинхронизация заявок и сделок: " .. tostring(order_n) 
                            .. ", " .. tostring(order_q) .. "/" .. tostring(trade_q))
                    message("Рассинхронизация заявок и сделок: " .. tostring(order_n) 
                            .. ", " .. tostring(order_q) .. "/" .. tostring(trade_q))
                end

                -- Запись в журнал
                Log:trace('Получаю тек. позицию: ' 
                    .. " " .. tostring(pos.dir) 
                    .. ' ' .. tostring(pos.qty)
                    .. ' ' .. tostring(pos.op)
                    .. ' ' .. tostring(pos.cap)
                    .. ' ' .. tostring(pos.be))

                Log:trace('Получаю изменения в позиции: '
                    .. ' ' .. tostring(qcap)
                    .. ' order_op=' .. tostring(order_op)
                    .. ' order_q=' .. tostring(order_q)
                    .. ' order_b=' .. tostring(order_b)
                    .. ' order_p=' .. tostring(order_p)
                    .. ' / trade_q=' .. tostring(trade_q)
                    .. ' trade_p=' .. tostring(trade_p))

                -- Управление позицией
                local log_action = ""
                if pos.dir == "n" then
                    pos.dir, pos.qty, pos.op, pos.cap, pos.be, pos.open = set_position(order_op, trade_q, trade_p)
                    write_journal(order_op, qcap, trade_q, trade_p, trade_datetime)
                    log_action = "Открытие позиции " .. tostring(pos.dir) .. ' ' .. tostring(pos.qty) .. ' ' .. tostring(pos.op)
                    Log:trace(i .. ' ' .. log_action)
                    save_needed = 1
                elseif (pos.dir == "L" and order_op == "BUY") or (pos.dir == "S" and order_op == "SELL") then
                    pos.op = pos.op * pos.qty + trade_p * trade_q
                    pos.qty = pos.qty + trade_q
                    pos.op = pos.op / pos.qty
                    write_journal(order_op, -1, trade_q, trade_p, trade_datetime)
                    log_action = "Наращивание позиции " .. tostring(pos.dir) .. tostring(pos.qty)
                    Log:trace(i .. ' ' .. log_action)
                    save_needed = 1
                else
                    if trade_q == pos.qty then
                        pos.dir, pos.qty, pos.op, pos.cap, pos.be, pos.open = "n", 0, 0, 0, 0, bar.open
                        write_journal(order_op, 0, trade_q, trade_p, trade_datetime)
                        log_action = "Закрытие позиции " .. tostring(pos.dir) .. ' ' .. tostring(pos.qty)
                        Log:trace(i .. ' ' .. log_action)
                    end
                    save_needed = 1
                end
            end
        end
    end
end
Дата и время позиции
 
nikolz,  Вы опять правы, мои предположения и понимание не есть "истина в последней инстанции", и я не отношу себя к "гуру", бывает ошибаюсь. Мне просто не понятно, что на специализированном форуме проходится рассуждать про объективные вещи. Да по мере присутствия на бирже учусь и набираюсь опыта, им делюсь и обсуждаю.
Цитата
nikolz написал:
Вы полагаете что БКС гоняется за тиками и поэтому Вы его называете ММ?
Вы зачем ставите все "с ног на голову"?  Ведь это Ваше утверждение.
Цитата
nikolz написал:
Я утверждаю, что  понятие (кличка) "MM"  связано лишь с оказанием платных услуг биржи.  Это никак не связано ни со следами, ни с размером ни с чем другим .
Вот мое утверждение VPM написал:
Цитата
ММ это прежде всего коммерческий проект, целью которого является извлечение прибыли, как и любой другой  коммерческой организации. Обладая значительными средствами, набирают большие позиции которые, оставляя следы на графике, а значить могут повести рынок за собой или держать его в диапазоне. Это интересует трейдера, отвечая на вопрос в какую сторону держать позицию, и уж совсем не интересно сколько заработал ММ. Именно это поведение как крупного игра их отличает. Вы можете даже конкретные алгоритмы найти в сети. Обладая дополнительной информацией они строят свои торговые стратегии, свой бизнес.
"Что написано пиром, то не вырубить топором". Касаемо моего подхода, читайте выше, там есть и формализация понятия о чем я рассуждаю, а рассуждаю я о контрагентах в сделках, как их можно формализовать в алгоритмических стратегиях.  
Дата и время позиции
 
nikolz,  Все я прекрасно понял. Смею предположить, Ваши торговые стратегии, видимо не выходят за пределы технологий "скальпинга", отсюда и кругозор. Выше Вы опубликовали участников заключивших договора, Вам наименования организаций не о чем не говорят? Именно они гоняются за тиками? Вы просто посмотрите на ликвидность в стаканах, и на финансовые возможности компаний обеспечивающих эту ликвидность.  Что делать с остальными финансами? Могу предположить, что под скапинг выделяется не большая доля активного капитала на котором и крутятся HFT-алгоритмы,  выдели 1% а что делать с 99% средств?
Кстати, на эту же проблему эффективности, натолкнулся у себя в своих среднесрочных стратегиях, суть в следующем: есть 100% торговый капитал, по правилам риск менеджмента активный не более < 25%, что означает > 75% т. капитала лежит просто в обеспечении сделки, не плохо бы часть покрутить в скальперских стратегиях.
Касаемо придумок все за долго до меня, стратегии опубликованы, на классику жанра указал выше. И никаких кличек, терминология применяется разная но это для упрощения в пониманиях, сегодня модная есть "смарт мани",  там своя, у классиков своя, Суть одна. Касаемо следов не только на ценовых графиках отслеживаются, но часто в стакане, такой объем можно видеть, так как рассчитываемся по определенным правилам для данного эмитента то есть алгоритмический. Такие объемы определяются, и от них строятся разные стратегии. Платная услуга биржи, это не признак ММ, это один из источников дохода ММ.  Даже мне раньше прилетало от  биржи.
Дата и время позиции
 
nikolz,  Все это верно, это не предмет обсуждения. ММ это прежде всего коммерческий проект, целью которого является извлечение прибыли, как и любой другой  коммерческой организации. Обладая значительными средствами, набирают большие позиции которые, оставляя следы на графике, а значить могут повести рынок за собой или держать его в диапазоне. Это интересует трейдера, отвечая на вопрос в какую сторону держать позицию, и уж совсем не интересно сколько заработал ММ. Именно это поведение как крупного игра их отличает. Вы можете даже конкретные алгоритмы найти в сети. Обладая дополнительной информацией они строят свои торговые стратегии, свой бизнес.
Дата и время позиции
 
nikolz, На форуме существует некая путаница в понятиях, и Вы не первый кто рассуждая о Маркет - мейкерах, упрощает их деятельность или сравнивает их с некими злодеями Крупными игроками занимающихся манипуляциями рынков. На фондовых биржах это крупные инвестиционные банки (например, Goldman Sachs, Morgan Stanley) как Вы думаете их интересуют сделки в один тик? На разных рынках по разному, задачи и техники принципиально одни.
Отслеживая сделки на рынке в целях выявления крупных сделок для лучшего понимания ситуации и реализации в системах принятия решений, делю игроков условно на 3 категории:
1) Крупный игрок
2) Маркет-мейкер
3) Ретейл.
Различие в поведении в торгах! имелось в виду именно это, поэтому подробно подчернил технический аспект.
Касаемо ММ, хотя это специализированная участник, компания или и.банк, обязанные соблюдать строгие регуляторные требования, они тоже совершают ошибки. Давайте представим ситуацию набрана огромная позиция, а рынок пошел против, что на весах, штраф если заметят, или манипуляция во спасение добра. И таких ситуаций множество.
И это только моя точка зрения в основе которой, методологии Ричарда Вайкоффа (Wyckoff)  с его композитным игроком, решения как считать каждый принимает сам.
Дата и время позиции
 
Да, использую в обработке  собственных сделок комбинированный подход. Ну про это говорили. Вот коллбек которым пользуюсь, на форуме он широко обсуждался, сто лет пользуюсь не заглядывая.
Код
--[[ Trade CALLBACK ]]-- -- Вызов колбэка OnTrade, который использует self для контроля и записи данных
--function OnTrade(trade)    tradeManager:OnTrade(trade) end
function OnTrade(trade)

    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;
Дата и время позиции
 
Всем добрый день, хочу просто добавить фундамент, в о сознание цели. Знание сила!

Коллбеки (или обратные вызовы) — это механизм, при котором одна функция передается как параметр в другую функцию, и она вызывается (или "вызвана") внутри этой функции, когда наступает определенное событие или условие. В контексте торгового алгоритма и работы с терминалом QUIK, коллбеки используются для получения данных (например, сделок) и их обработки в реальном времени. В очередь ставятся данные полученные от них, для уменьшения нагрузки.

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

1) Рынки МосБиржи, если рассматриваете ее, управляются маркет-мейкерами. Основные алгоритмы для обеспечения максимальной эффективности которые, можно даже сказать, обязан использовать маркет-мейкер:
a) Алгоритмы выставления двустороних котировок;
b) Алгоритмы управления позицией;
c) Арбитражные алгоритмы;
d) Алгоритмы управления рисками;
e) Алгоритмы HFT (High-Frequency Trading).
Работают не со стаканом а с книгой ордеров.
Принцип работы HFT-алгоритмов (High-Frequency Trading):
       Осуществляют тысячи сделок в секунду.
       Мониторят микро изменения цен и мгновенно реагируют на рыночные дисбалансы.
Технически:
       Используются FPGA (платы программируемой логики) для минимизации задержек.
       Торговля осуществляется максимально близко к серверам биржи (co-location),
       используются прямые подключения к биржевым серверам через высокоскоростные сети.
       Современные алгоритмы маркет-мейкеров работают с задержкой менее 1 миллисекунды.
А в кризисных ситуациях может выйти из рынка.

2) На российском рынке сейчас преобладают частные инвесторы (МосБиржа), и этому есть простые объяснения.
Вот из оценки брокера, доля частных инвесторов в объеме торгов акциями на ноябрь 2024г. - 76% за 2023г. -40%.

Разрабатывая архитектуру своей алгоритмической торговой программы, на мой взгляд, это нужно учитывать, особенно если стратегии скальперские.
Луа в рамках QUIK, прекрасно справляется с торговыми задачами. Корутинный подход (асинхронность) прекрасно решает задачу Event и Wait озвученные nikolz,  для этого, один из подходов создается своя таблица событий (Event).
Подразумеваемая волатильность, Расчет подразумеваемой волатильности опционов
 
Для серии тогда так
Код
-- Функция для вычисления кумулятивной функции распределения нормального распределения (N(x))
function norm_cdf(x)
    local t = 1 / (1 + 0.2316419 * math.abs(x))
    local d = 0.3989422804014337 * math.exp(-0.5 * x * x)
    local prob = d * t * (0.319381530 + t * (-0.356563782 + t * (1.781477937 + t * (-1.821255978 + t * 1.330274429)))))
    if x >= 0 then
        return 1 - prob
    else
        return prob
    end
end

-- Основная функция для расчета цены опциона по модели Блэка-Шоулза
function black_scholes_call_price(S, K, T, r, sigma)
    local d1 = (math.log(S / K) + (r + 0.5 * sigma * sigma) * T) / (sigma * math.sqrt(T))
    local d2 = d1 - sigma * math.sqrt(T)
    return S * norm_cdf(d1) - K * math.exp(-r * T) * norm_cdf(d2)
end

-- Функция для нахождения подразумеваемой волатильности для одного опциона
function implied_volatility(S, K, T, r, market_price)
    local low = 0.0001
    local high = 2.0
    local tolerance = 0.0001
    local sigma = (low + high) / 2
    local price = black_scholes_call_price(S, K, T, r, sigma)

    -- Итерационный метод поиска
    while math.abs(price - market_price) > tolerance do
        if price < market_price then
            low = sigma
        else
            high = sigma
        end
        sigma = (low + high) / 2
        price = black_scholes_call_price(S, K, T, r, sigma)
    end
    return sigma
end

-- Функция для нахождения подразумеваемых волатильностей для серии опционов
function implied_volatilities_for_series(S, r, options)
    local ivs = {}
    for i, option in ipairs(options) do
        local iv = implied_volatility(S, option.K, option.T, r, option.market_price)
        table.insert(ivs, {K = option.K, T = option.T, implied_volatility = iv})
    end
    return ivs
end

-- Пример использования
local S = 100     -- Текущая цена актива
local r = 0.05    -- Безрисковая процентная ставка (5%)

-- Список опционов с параметрами: Цена исполнения (K), Время до экспирации (T в годах), Рыночная цена опциона (market_price)
local options = {
    {K = 95, T = 30 / 365, market_price = 6},
    {K = 100, T = 30 / 365, market_price = 5},
    {K = 105, T = 30 / 365, market_price = 3.5},
    {K = 110, T = 60 / 365, market_price = 4.5}
}

-- Вычисляем подразумеваемую волатильность для каждого опциона
local ivs = implied_volatilities_for_series(S, r, options)

-- Выводим результаты
for _, iv in ipairs(ivs) do
    print(string.format("Цена исполнения: %.2f, Время до экспирации: %.2f лет, Подразумеваемая волатильность: %.4f%%",
        iv.K, iv.T, iv.implied_volatility * 100))
end
Код
Что получилось:
Подразумеваемая волатильность: 42.0108
Цена исполнения: 95.00, Время до экспирации: 0.08 лет, Подразумеваемая волатильность: 21.5971%
Цена исполнения: 100.00, Время до экспирации: 0.08 лет, Подразумеваемая волатильность: 42.0108%
Цена исполнения: 105.00, Время до экспирации: 0.08 лет, Подразумеваемая волатильность: 46.9254%
Цена исполнения: 110.00, Время до экспирации: 0.16 лет, Подразумеваемая волатильность: 48.9867%
Подразумеваемая волатильность, Расчет подразумеваемой волатильности опционов
 
Может это подойдет?
Код
-- Функция для вычисления кумулятивной функции распределения нормального распределения (N(x))
function norm_cdf(x)
    local t = 1 / (1 + 0.2316419 * math.abs(x))
    local d = 0.3989422804014337 * math.exp(-0.5 * x * x)
    local prob = d * t * (0.319381530 + t * (-0.356563782 + t * (1.781477937 + t * (-1.821255978 + t * 1.330274429) )))
    if x >= 0 then
        return 1 - prob
    else
        return prob
    end
end

-- Основная функция для расчета цены опциона по модели Блэка-Шоулза
function black_scholes_call_price(S, K, T, r, sigma)
    local d1 = (math.log(S / K) + (r + 0.5 * sigma * sigma) * T) / (sigma * math.sqrt(T))
    local d2 = d1 - sigma * math.sqrt(T)
    return S * norm_cdf(d1) - K * math.exp(-r * T) * norm_cdf(d2)
end

-- Функция для нахождения подразумеваемой волатильности
function implied_volatility(S, K, T, r, market_price)
    local low = 0.0001
    local high = 2.0
    local tolerance = 0.0001
    local sigma = (low + high) / 2
    local price = black_scholes_call_price(S, K, T, r, sigma)

    -- Итерационный метод поиска
    while math.abs(price - market_price) > tolerance do
        if price < market_price then
            low = sigma
        else
            high = sigma
        end
        sigma = (low + high) / 2
        price = black_scholes_call_price(S, K, T, r, sigma)
    end
    return sigma
end

-- Для примера использования
local S = 100          -- Текущая цена актива
local K = 100          -- Цена исполнения
local T = 30 / 365     -- Время до экспирации (в годах)
local r = 0.05         -- Безрисковая процентная ставка (5%)
local market_price = 5 -- Рыночная цена опциона call

local iv = implied_volatility(S, K, T, r, market_price)
print(string.format("Подразумеваемая волатильность: %.4f", iv * 100))
Как обрезать число типа float до 2х знаков после запятой
 
Да действительно, есть особенности в самой функции  math.floor, углубляться не стал, вернулся к варианту изложенному Kolossi, с двумя правилами, сделал просто более читаемым для себя.
Спасибо за обсуждение.
Казалось бы простая задача округления числа, а вариантов собралось с десяток.
И снова CreateDataSource
 
Цитата
Acaw написал:
В блоке MAIN у меня создается источник данных (ДС):ds["NLMK"] = CreateDataSource("TQBR", "NLMK", INTERVAL_D1)Далее мне нужно в функции обращаться к нему, но не напрямую, а присвоив его локальному дс:local dsf = ds["NLMK"], т.е. чтобы можно обращаться через dsf:C(i).
В Lua, поведение относительно памяти зависит от того, является ли это совершенно новой таблицей или ссылкой на существующую таблицу.
1) Под новую таблицу, Lua выделит новую память. Предыдущая таблица, на которую ссылается пользователь, станет доступной для сборки мусора.
Утечки памяти нет.
2) Если это ссылка (или псевдоним) на таблицу, которая уже существует в программе, то она просто укажет на эту существующую таблицу.
Для самой таблицы не выделяется новая память.
Тем не менее, предыдущая таблица, на которую ссылается пользователь, все равно будет удалена сборщиком мусора, если на нее больше не ссылаются нигде.
Короче говоря, в целом безопасен и эффективен. Сборка мусора Lua отвечает за управление памятью, предотвращая утечки памяти в большинстве случаев.
Как обрезать число типа float до 2х знаков после запятой
 
За чем? Просто округление по единому правилу для положительных отрицательных чисел.
Как обрезать число типа float до 2х знаков после запятой
 
print(round(12.345, 2))  -- 12.35
print(round(-12.345, 2)) -- -12.35
Как обрезать число типа float до 2х знаков после запятой
 
Да заметил не точность вот так будет работать
Код
-- Округление для любого числа
    local rounded = math.floor(num * mult + 0.5 *(num >= 0 and 1 or -1)) / mult
Как обрезать число типа float до 2х знаков после запятой
 
Проверил. Нет необходимости отдельно обрабатывать отрицательные числа через math.ceil.
Код
print(round(12.345, 2))  -- 12.35
print(round(-12.345, 2)) -- -12.34
print(round(10.0))       -- 10
print(round(10))         -- 10
print(round(nil))        -- nil
print(round("abc"))      -- "abc"
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
 
Добрый день!
Решил разбавить свой портфель разными активами,  остановил выбор на ОФЗ, дописал под них свой класс. В общем не чего особенного, ОФЗ котируют трех типов поэтому в основу легло три стратегии, которые при одной и той же ситуации ведут себя по разному. Но столкнулся с проблемой  автоматического обновления показателей инфляции и ключевой ставки, то есть с необходимость подключить внешние данные? Возможно уже решали подобную задачу или есть идеи.
В основу создания универсального класса положена простая идея, класс который способен давать однозначные рекомендации по облигациям с указанием, на каких показателях основывается рекомендация.
Сейчас это выглядит примерно так
Код
-- Вывод рекомендаций
function Bond:print_recommendations(inflation_rate, expected_rate_change)
    local strategies = self:recommend_strategy(inflation_rate, expected_rate_change)
    print("Рекомендации для облигации:", self.name)
    for _, strategy in ipairs(strategies) do
        print(string.format("- Стратегия: %s", strategy.strategy))
        print(string.format("  Применима: %s", strategy.applicable and "Да" or "Нет"))
        print(string.format("  Рекомендация: %s", strategy.message))
    end
end

-- Пример использования
local myBond = Bond:new("ОФЗ 26207", "ОФЗ-ПД", 1000, 0.07, 950, 5)
local inflation_rate = 0.06   -- Текущая инфляция 6%
local expected_rate_change = -0.01 -- Ожидаемое снижение ставки на 1%

myBond:print_recommendations(inflation_rate, expected_rate_change)
Это ответ
Код
modules\Bond.lua"  1  
Рекомендации для облигации:   ОФЗ 26207
- Стратегия: Сохранение капитала
  Применима: Да
  Рекомендация: Облигация сохраняет капитал при текущей инфляции.
- Стратегия: Стабильный доход
  Применима: Да
  Рекомендация: ОФЗ-ПД подходят для стабильного дохода благодаря фиксированным купонам.
- Стратегия: Заработок на ставках
  Применима: Нет
  Рекомендация: Для заработка на ставках подходят долгосрочные ОФЗ-ПД.
>Exit code: 0    Time: 0.8326
Как обрезать число типа float до 2х знаков после запятой
 
Еще один вариант.
Код
function round(num, idp)
    
    -- Если num некорректное, вернуть как есть
    if not num or type(num) ~= "number" then return num end
   
    -- Если idp не указан, использовать 0 (округление до целого числа)
    idp = idp or 0 
    local mult = 10^idp

    -- Округление для любого числа
    local rounded = math.floor(num * mult + 0.5) / mult

    -- Если число целое, убрать .0
    if rounded == math.floor(rounded) then
        return math.floor(rounded)
    end

    return rounded
end
Страницы: 1 2 3 4 5 6 7 8 9 10 11 ... 21 След.
Наверх