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

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

Страницы: 1 2 След.
ввод параметров с клавиатуры для робота lua, способы ввода параметров с клавиатуры для робота lua не заходя в сам код
 
Можно, конечно.

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

Допустим обращаемся к данным в 10:00.

Есть параметр TIME - время последней сделки. А дата?
TRADE_DATE_CODE - это дата прошлого торгового дня или дата дня где были сделки или дата текущего нового торгового дня, раз он уже наступил?

Да, можно взять время последнего любого бара, но проблема как раз в том, что бары при заказе не сразу поступают с сервера, надо подождать. Вот сравнивая дату-время сделки и дату-время бара хочется понять, что все бары загружены. Но если даты сделки нет, то гарантии, что это сделка прошлой сессии нет, может это сделка позапрошлой и т.д.  
Функция CreateDataSource, Возможно ли получать данные с её помощью по любому инструменту не открывая его график?
 
Подниму тему, дабы не создавать новую.

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

Вот я отправил число 615 вместо интервала.

Get DataSource: SBER|QJSIM, интервал: 615
InitSec DS all bars: 2, last bar: 2019.12.03 10:15:00

Также возвращается и для 619. Это фича или все же баг. Я вполне ожидаю, что мне вернется ошибка, чтобы как-то отреагировать.
HHTP запросы в LUA и проблема с 32-битной версией библиотеки LuaSocket
 
У меня есть сборка для 32 бита.
Там есть пример отправки запроса с использованием cURL. Но можно и руками отправлять, только с Socket
https://github.com/nick-nh/qlua/tree/master/lua_socket_ssl
QUIK 8.0
 
Цитата
Анатолий написал:
Цитата
Nikolay написал:
Если кому еще необходимо. Я бился над сборкой socket и ssl под x64. Вроде собрал
Незаработали они у меня потому что собрал ты их строго под Луа 5.1, может будешь так добр что соберешь все это еще и под Луа 5.3?
А зачем под Lua 5.3? В Квике 5.1. Все это только ради Квика и собиралось. В этом весь смысл.
Если под 5.3 и для сторонних скриптов, то, кажется, сборки есть готовые под 5.3.
QUIK 8.0
 
Если кому еще необходимо.
Я бился над сборкой socket и ssl под x64. Вроде собрал, но как-то нестабильно оно работало. В итоге нашел готовые сборки, более стабильно работающие.
А вот lCurl пока не удалось собрать под x64.

Вот сборки и примеры:
https://github.com/nick-nh/qlua/tree/master/lua_socket_ssl
QUIK 8 и компиляция luasql
 
Все проверялось на свежеустановленной демо версии 8.0.3.14. Или нужна именно локальная копия для исключения влияния среды исполнения?
QUIK 8 и компиляция luasql
 
Возвращаюсь к вопросу.
Тех. поддержка ответила (Падение Quik 8.0.3.14 (CQ02527163)), что ошибка в файле alltrade.dat.
Но это явно не оно. Т.к. удаление файла не приводит к другому поведению. Квик 8 стабильно падает без дампов.
Сделал простой тестовый скрипт, стабильно работающий в 7-ой версии с 32 битной библиотекой, но приводящий к падению Квика 8 с 64 битной.
Причем падает непостоянно в одном месте, то при выборке из базы данных, то, что более странно, при вызове getQuoteLevel2.

https://yadi.sk/d/abcYTS_w9TQoQQ
ОШИБКА: (533) Неверно указан код клиента.
 
Да, для основной секции, большинство брокеров, при подаче заявки проверяет наличие /. Поэтому проще принять за данность и просто добавлять его.
Не завершается main после остановки скрипта
 
Если под некорретным поведением подразумевается ошибка, которая здесь не указана, то предположу, что есть проблема вывода в таблицу, т.к. при остановке скрипта окно таблицы закрывается, а OnStop еще не вызван. В main нет ни одной проверки, что таблица существует и она не закрыта, вот и падает при попытке вывести в закрытую таблицу.
Также sleep лучше повысить до 50 мс (т.к. используется вывод в таблицу), иначе Квик начнет процессор нагружать.
Функция подключения к другому серверу, Есть ли?
 
Для этой же задачи был переписан скрипт автологина, использующий w32 библиотеку, который при обрыве связи, нажимает на список выбора сервера в форме логина/пароля.
QUIK 8 и компиляция luasql
 
Попробовал еще раз. Файлы dmp не формируются. В папке есть два файла от прошлых запусков. Отправлю их.
Ошибка такого рода:

Имя события проблемы: APPCRASH

 Имя приложения: info.exe

 Версия приложения: 8.0.3.14

 Отметка времени приложения: 5d282989

 Имя модуля с ошибкой: StackHash_f988

 Версия модуля с ошибкой: 6.3.9600.19304

 Отметка времени модуля с ошибкой: 5c7f684f

 Код исключения: c0000374

 Смещение исключения: PCH_9D_FROM_ntdll+0x0000000000090D0A

 Версия ОС: 6.3.9600.2.0.0.16.33

 Код языка: 1049

 Дополнительные сведения 1: f988

 Дополнительные сведения 2: f9888e0a087b444ad5df05a65c8fed35

 Дополнительные сведения 3: 9540

 Дополнительные сведения 4: 954017ff240795f447e29bd8d973bef5

Но далее все интереснее. При возникновении ошибки, я попробовал запустить отладку приложения.
Получил сообщение об ошибке в ntdll.dll
Закрыл сообщение и запустил продолжить выполнение приложения. Вернулся в окно Квика и он продолжил работать как будто ничего не произошло. Скрипт работает.

Далее останавливаю скрипт и получаю еще раз эту же ошибку. Опять в отладе нажимаю продолжить и возвращаюсь в окно терминала, он работает, выведя сообщение:

LuaVM closed with error

Снимки экрана приложу в письме.

QUIK 8 и компиляция luasql
 
Куда отправлять?
QUIK 8 и компиляция luasql
 
Вопрос разработчикам: как можно посмотреть лог термнала, чтобы понять от чего происходит падение программы при использовании библиотеки?
QUIK 8 и компиляция luasql
 
Вернулся к вопросу. Скомпилировал драйвер ODBC, т.к. он мне больше всего нужен.
Что пришлось менять:
В файле ls_odbc.c пришлось заменить определение окружения на _WIN64.
Пришлось заменить тип SQLINTEGER на SQLLEN, т.к. в библиотеке ODBC 64 другие типы.

Также надо удалить все файлы *.obj, т.к. они собраны для x86.

После библиотека собралась.
Даже запустился скрипт, работающий под x86.

Но, пришлось переписать код обхода курсора на итератор. Прямой обход приводит к ошибке.
Но даже это не долго живет, Квик падает без слов через секунд 10-20 работы.

SQL Profiler показывает, что запросы идут нормально, ошибок нет. В те несколько секунд, что успевает отработать скрипт, данные стакана выводятся в окно исправно.
Но падает Квик всегда.

Что может быть, драйвер или все же Квик? Этот же драйвер под 7 Квик работает исправно.

Возможно, как писали в одной из веток, надо еще и lua5.1.dll самому собирать. Есть подозрение, что некорректно обрабатываются таблицы в луа стеке.

Если кто захочет попробовать:
https://github.com/nick-nh/qlua/tree/master/luasql
QUIK 8 и компиляция luasql
 
Добрый день.
Я пробовал скомпилировать через make файл, но лезут ошибки линковки целевой платформы. Хотя делалось все под окружением x64.
Остается вариант сконвертировать проект VS6 под VS2015-2017 и собирать, меняя зависимости. Он есть в исходниках.
Но напрямую он не конвертируется, слишком старая версия. Видел собщение, что надо делать через VS2010, т.к. более поздние версии не конвертируют проект.
Отправка уведомления в Telegram через прокси
 
Я собирал на vs17

Вот я дополнительно собрал lcurl https://github.com/Lua-cURL/Lua-cURLv3 с последним cURL

Проверил, работает. Вот сборка и примеры
https://github.com/nick-nh/qlua/tree/master/lua_socket_ssl
Кто как решил вопрос уведомления о сделках?
 
Как я выше написал, я решил проблему просто - сам скомпилировал библиотеки. И все заработало. Никаких переименований библиотек я не делал.
Отправка уведомления в Telegram через прокси
 
Добрый день.
Я бился с подключением SSL библиотеки. Не подключалась никак из готовых библиотек. На стороне тоже все работало.
В конечном итоге пришлось просто пересобрать конкретную версию библиотеки, которая в итоге заработала.
Так что советую собрать luacurl через luarocks именно под lua 5.1.

Еще один момент важный, такого рода библиотеки в Квике работают, если они лежат в папке с библиотекой lua5.1, т.е. в папке установки Квика.
В чем здесь особенность Квика не знаю, но пришлось так сделать, иначе никак не запускалось.
Кто как решил вопрос уведомления о сделках?
 
Проблему решил.
Пришлось скомпилировать самому luaSec 0.8-1 под lua 5.1, используя Open SSL.
Файлы libeay32 и ssleay32 обязаны быть рядом с файлом lua 5.1, т.е. в папке установки Quik.

У меня отправка почты совершается за секунду, две. Не более. Никаких задержек.

Теперь можно приступать к использованию библиотеки для интересных вещей, типа чтения Twitter и т.д.

Если кому интересно, готовая сборка с примером отправки почты с моего Гита:
https://github.com/nick-nh/qlua/tree/master/lua_socket_ssl
Кто как решил вопрос уведомления о сделках?
 
Цитата
Анатолий написал:
Цитата
Nikolay написал:
socket  = require("socket")
А у меня такой строчки нету и все работает, короче у меня все прописано вот так:
Ну я хочу использовать эту библиотеку не для отправки почты. Для почты я написал на C# програмульку на 10 строк, вызываю ее из Квика и все.
А вот для других целей хочется запустить. Ясно, что дело в путях, т.к. в другом месте работает. Будем копать...
Кто как решил вопрос уведомления о сделках?
 
Цитата
Анатолий написал:
Сложно так сказать не видя что у тебя в скрипте и в папках квика, покажи тогда свой кусок скрипта где обьявляются пути

package.cpath  = ...
package.path  = ...

и идет подключение библиотек командой require
Так а что здесь такого при подключении... Я же говорю, что этот же скрипт ZeroBraneStudio в работает.
Отличие в том, что у него свои пути к библиотекам. А здесь такие.
Попытка поставить пути из ZeroBraneStudio для Квика приводит к аналогичной ошибке.

gSPath = 'D:\\Projects\\qlua_work'
gPath  = 'C:\\QUIK-Junior'
package.cpath = gPath.."\\?.dll;"..gSPath .."\\lua_socket_ssl\\?.dll;" ..gSPath .."\\lua_socket_ssl\\clibs\\?.dll;" ..gSPath .."\\lua_socket_ssl\\clibs\\mime\\?.dll;" ..gSPath .."\\lua_socket_ssl\\clibs\\socket\\?.dll;" .. package.cpath
package.path  = gSPath .."\\lua_socket_ssl\\?.lua;"..gSPath .."\\lua_socket_ssl\\socket\\?.lua;"..gSPath .."\\lua_socket_ssl\\ssl\\?.lua;" ..package.path

print(package.cpath)
print(package.path)

socket  = require("socket")
smtp    = require("socket.smtp")
ssl     = require("ssl") --- вот здесь и падает в Квике
Кто как решил вопрос уведомления о сделках?
 
Цитата
Анатолий написал:
Цитата
Nikolay написал:
Я тоже подозреваю, что с интерпретатором lua в Квике не все ладно. У меня также из ZeroBraneStudio все работает.
С интерпретатором луа в квике все ладно, просто там есть нюансы, у меня были все эти проблемы и я их решил, помоему ты всетаки не все скопировал из окна ошибок, полностью все оттуда скопируй и вставь сюда, или лучше сделай скрин и выложи
Я скопировал все, кроме полного пути до файла ssl.dll. Больше ошибок нет. Выше по сообщениям этой темы были аналогичные сообщения.Если бы интерпретатор луа был чист, то типовая библиотека strict не приводила бы к падению терминала.
Кто как решил вопрос уведомления о сделках?
 
Цитата
Анатолий написал:
В момент выполнения строки registry = ctx:   ctx= SSL context: 0D72EE88    тип - userdata   s = SSL connection: 0D848F00  тип - userdatasock = tcp{client}:0D846E88    setfd=nilВообщем мне кажется что это связано с квиковским интерпретатором луа, т.к. операция registry это сохранение любых значений C кода в специальной общей таблице для всех выполняемых С кодов, вот тут в чем о и проблема, т.к. в других интерпретаторах, том же Zerobrane, такой проблемы нет
Я тоже подозреваю, что с интерпретатором lua в Квике не все ладно. У меня также из ZeroBraneStudio все работает.
Также не все библиотеки можно подключить в Квике, для примера strict -  Квик падает без слов.
Также обнаружил, что внутри фунции SearchItems (в функции проверки) у меня почему-то проверка nil как false не срабатывает. Приходится явно писать ~= nil
Кто как решил вопрос уведомления о сделках?
 
Цитата
Анатолий написал:
Цитата
Nikolay написал:
Я подключил все библиотеки, socket подключается нормально. Но при подключении ssl, не находит ssl.core. ssl.lua, собственно, и пытается его включить local core    = require("ssl.core")Т.е. нужна папка \ssl а в ней файл core.dll
Скопируй из квика из окна "Ошибки выполнения скрипта" то что там пишется при твоей попытке выполнить скрипт и выложи это сюда"
Ну так и пишется, что не может загрузить модуль. Все пути прописаны, библиотека рабочая, взята из поставки ZeroBraneStudio. Из нее все прекрасно работает. При этом просто socket загружается нормально.

Код
error loading module 'ssl.core' from file 'ssl.dll':
   Не найден указанный модуль.
Кто как решил вопрос уведомления о сделках?
 
А тоже самое из ZeroBraneStudio работает. ssl.core - ошибку не дает, письма отправляются. А Квик ошибку выдает на local core    = require("ssl.core") в  ssl.lua
Кто как решил вопрос уведомления о сделках?
 
Добрый день.

Я подключил все библиотеки, socket подключается нормально. Но при подключении ssl, не находит ssl.core. ssl.lua, собственно, и пытается его включить local core    = require("ssl.core")
Т.е. нужна папка \ssl а в ней файл core.dll

Попробовал взять сборку Телеграм бота, что здесь выкладывали, аналогичная проблема. Похоже какая-то библиотека все же отсутствует.
Кто-то встречал похожую ошибку? Я нашел упоминания, то это связано с libeay32 и ssleay32, но они есть, путь к ним прописан. Плюс пробовал класть их в разные папки.
64-битная версия QUIK
 
Добрый день.

А UTF-8 завезут в этот релиз или все по-старому?
strict lua
 
Цитата
Egor Zaytsev написал:
Добрый день.
Согласно сторонним источникам должно работать:
https://www.yamaha.com/products/en/network/techdocs/others/lua/strict_lua/
Ну вопрос был задан потому, что при вызове strict = require('strict') Квик валится намертво. Тихо и быстро.
strict lua
 
Добрый день.

Если qlua это lua 5.1, то разве не должна быть поддержка библиотеки strict?
Проработка стратегии на виртуальной торговле, Формирование стратегии, виртуальная торговля
 
Добрый день.

Что касается "стандартных стратегий", то я не верю в них, т.к. они основаны на предположеннии, что тенденция прошлого сохранятся и в будущем, что, естественно, не так.
Да, есть решения, позволяющие минимизировать риски, но рынок меняет свои характеристики так, что требуется пересчет оптимальных параметров стратегии. Что, в свою очередь, приводит к проблеме переоптимизации. А это замкнутый круг.

Я же больше верю в стратегии с элементами количественнго анализа, основанные на потоке реальных данных. При этом, естественно, стратегия строится на выявлении закономерностей на истории, но не путем усреднения характеристик движения цены (скользящие, осцилляторы и др.), а на анализе абсолютных значений движения цены и их отношений друг к другу. Свечи же - это искусственное загрубление характеристик. Скажем, почему ТФ - минута, а если я хочу 25 секунд. Кто решил, что всем хватит минуты? Ведь, если хоть немнго сдвинуть ТФ, то картина может кардинально измениться, сменятся максимумы-минимумы, открытия-закрытия. Поэтому более важна характеристика сколько цена прошла за отведенный период. Период, при этом, не привязан к ТФ, хоть, зачастую, им и является.

Для примера, безумная стратегия: если цена в 13:00 выше открытия дня (или недели), то покупаем и наоборот Закрытие сделки по рассчитанному профиту или через 45 минут, что раньше. Это выдуманный пример выявленной закономерности. Такая стратегия живет месяц-два, а то и меньше. Также выявляются и другие закономерности вплоть до тикового уровня. При этом также находятся и закономерности типа гармонических фигур любого перирода, их последовательности, отношений.

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

Цитата
Константин ...

Спасибо Николай, но видимо так я и не дождался этой доработки. Пока ждал данный функционал был разработан уже, причем в веб интерфейсе, и ровно так как я его описывал год назад  http://bit.ly/2TKazri

Для информации  https://ru.tradingview.com/chart/2jGvtivq/

Николай так скажите, а Вы какого подхода придерживаетесь при работе с стратегиями, если "не очень верю в торговлю по инерционным индикаторам" немного поподробней??
Проработка стратегии на виртуальной торговле, Формирование стратегии, виртуальная торговля
 
На нашем рынке, данный виртуальный режим реализован в TigerTrade и SBPro. Второй правда только на срочном рынке, но думаю, что в основном это и надо только на срочке. Данные платформы имеют демо, где можно все посмотреть.

Реализация данного режима - это запуск экземпляра приложения с последовательным чтением данных из истории (не только сохраненной, но и загрузка с сервера). Что важно, реализовано это все с поддержкой склейки контрактов. Также важно, что даные режимы для ручной торговли. Т.е. сделки на истории вы будете совершать руками.

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

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

Единственное замечание - я не очень верю в торговлю по инерционным индикаторам, поэтому решение по написанию конструктора стратегии псевдоязыком (что реализовано в MT5, WealthLab и др.) видится сомнительным занятием. Но здесь, как говориться, вопрос про деньги. Если бы платформа Квик была платной для конечного пользователя, то возможно можно  бы реализовать такую функциональность для завлечения новых "инвесторов", заявив, что теперь наша платформа позволяет обучаться "трейдингу" и вы легко можете написать своего робота.
Обновление пользовательской таблицы/окна
 
Здесь, скорее всего, проблема скорости выполнения цикла.
У меня есть сложный скрипт, выполняющий много расчетов в main. В нем все работает без задержек. А простейшие скрипты, которые делают мало действий в main, не обнолвяют таблицу. Возможно, идет переполнение стека вызовов обновления окна.

Хотя разработчки выше писали, что проблема не воспроизводится.
Обновление пользовательской таблицы/окна
 
Можешь попробовать найти окно как это делают в автологине
https://smart-lab.ru/blog/444805.php

и подергать окно.

Я плюнул искать причины. Перенес отрисовку части вещей в колбеки, хоть это и не самый лучший вариант.
Динамическое количество линий индикатора
 
А вот сделав такие изменения в цикл вывода строк, все работает.
Код
        for i=1,lines do                                        

            outlines[i] = {index = index-shift+bars, val = maxPrice}
            
            if sortedProfile[i]~=nil then               
                sortedProfile[i].vol=math.floor(sortedProfile[i].vol/MAXV*bars)
                if sortedProfile[i].vol>0 then
                    outlines[i].index = index-shift+sortedProfile[i].vol
                    outlines[i].val = sortedProfile[i].price                           
                end                                               
            end                   
            SetValue(index-shift,       i+1, outlines[i].val)
            SetValue(outlines[i].index, i+1, outlines[i].val)
                    
            --WriteLog('line '..tostring(i).." price "..tostring(GetValue(index-shift, i)).." - "..tostring(GetValue(outlines[i].index, i)).." vol "..tostring(outlines[i].index-index+shift))
                
        end

Код
--logfile=io.open(getWorkingFolder().."\\LuaIndicators\\priceAvgProfile.txt", "w")

Settings={}
Settings.period = 150
Settings.shift = 100
Settings.Name = "*priceAvgProfile"
Settings.weeks = 0 -- 1 - текущая, отрицательное число - сколько прошлых недель, включая текущую
Settings.fixShift = 1 -- 1 - всегда смещено на указанное количество shift, если 0, то будет смещено на дату начала неделеи расчета
Settings.showMaxLine = 1
---------------------------------------------------------------------------------------

lines = 100
scale = 2
min_price_step = 1

function Init()
    Settings.line = {}
    Settings.line[1] = {}
    Settings.line[1] = {Name = 'maxVol', Color = RGB(255, 128, 64), Type = TYPE_LINE, Width = 2}
    for i = 1, lines do
        Settings.line[i+1] = {}
        Settings.line[i+1] = {Color = RGB(185, 185, 185), Type = TYPE_LINE, Width = 2}
    end
    
    myFFF = FFF()
    return lines
end

function OnCalculate(index)
    if index == 1 then
        DSInfo = getDataSourceInfo()        
        min_price_step = getParamEx(DSInfo.class_code, DSInfo.sec_code, "SEC_PRICE_STEP").param_value
        scale = getSecurityInfo(DSInfo.class_code, DSInfo.sec_code).scale
    end 
    return myFFF(index, Settings)
end

---------------------------------------------------------------------------------------
function FFF()

    local cacheL={}
    local cacheH={}
    local cacheC={}
    local weeksBegin={}
    local maxPriceLine={}

    local outlines = {}
    local calculated_buffer={}
    
    return function(ind, Fsettings)

        local period = Fsettings.period or 150
        local shift = Fsettings.shift or 150
        local weeks = Fsettings.weeks or 0
        local fixShift = Fsettings.fixShift or 0
        local showMaxLine = Fsettings.showMaxLine or 0
        local bars = 50

        shift = math.max(bars+1, shift)

        local index = ind

        if index == 1 then          
            maxPriceLine = {}
            weeksBegin = {}
            cacheL = {}
            cacheL[index] = 0           
            cacheH = {}
            cacheH[index] = 0           
            cacheC = {}
            cacheC[index] = 0           

            calculated_buffer = {}
            outlines = {}

            return nil
        end
    ------------------------------      

        --maxPriceLine[index] = maxPriceLine[index-1] 
        cacheL[index] = cacheL[index-1] 
        cacheH[index] = cacheH[index-1] 
        cacheC[index] = cacheC[index-1] 

        if not CandleExist(index) then
            return maxPriceLine[index]
        end

        cacheH[index] = H(index)
        cacheL[index] = L(index)
        cacheC[index] = C(index)
        
        if T(index).week_day<T(index-1).week_day or T(index).year>T(index-1).year then
            weeksBegin[#weeksBegin+1] = index
        end

        if index < Size() then return nil end   

        if calculated_buffer[index] ~= nil then
            return maxPriceLine[index]
        end

        if showMaxLine==1 then
            SetValue(index-shift-1, 1, nil)
            SetValue(index-shift,   1, nil)
        end

        for i=1,#outlines do                        
            SetValue(index-shift-1,          i+1, nil)
            SetValue(index-shift,            i+1, nil)
            SetValue(outlines[i].index,      i+1, nil)
            
            outlines[i].index = index-shift
            outlines[i].val = nil
        end            
        
        local beginIndex = index-period
        if weeks == 1 then
            beginIndex = weeksBegin[#weeksBegin] or beginIndex
        end
        if weeks < 0 then
            beginIndex = weeksBegin[#weeksBegin+weeks] or beginIndex
        end
        
        if fixShift==0 then
            shift = math.max(bars+1, index-beginIndex)
        end

        --WriteLog('weeks '..tostring(weeks)..' last '..tostring(weeksBegin[#weeksBegin])..' beginIndex '..tostring(beginIndex))
        
        local maxPrice = math.max(unpack(cacheH,math.max(beginIndex, 1),index))
        local minPrice = math.min(unpack(cacheL,math.max(beginIndex, 1),index))       
        
        ----------------------------------------
        local priceProfile = {}
        --local clasterStep = math.max((maxPrice - minPrice)/lines, min_price_step)
        --local clasterStep = (maxPrice - minPrice)/lines
        local clasterStep = 10*min_price_step

        --WriteLog('minPrice '..tostring(minPrice)..' maxPrice '..tostring(maxPrice)..' clasterStep '..tostring(clasterStep))
        
        for i = 0, (index-beginIndex) do
            if CandleExist(index-i) then                
                local barSteps = math.max(math.ceil((H(index-i) - L(index-i))/clasterStep),1)
                for j=0,barSteps-1 do
                    local clasterPrice = math.floor((L(index-i) + j*clasterStep)/clasterStep)*clasterStep
                    local clasterIndex = clasterPrice*math.pow(10, scale)
                    if priceProfile[clasterIndex] == nil then
                        priceProfile[clasterIndex] = {price = clasterPrice, vol = 0}
                    end
                    priceProfile[clasterIndex].vol = priceProfile[clasterIndex].vol + V(index-i)/barSteps
                end
            end
        end

        --------------------
        local MAXV = 0
        local maxPrice = 0
        local maxCount = 0 

        local sortedProfile = {}

        for i, profileItem in pairs(priceProfile) do
            MAXV=math.max(MAXV,profileItem.vol)
            if MAXV == profileItem.vol then
                maxPrice=profileItem.price
            end
            maxCount = maxCount + 1
            sortedProfile[maxCount] = {price = profileItem.price, vol = profileItem.vol}
        end
                
        --WriteLog('maxV '..tostring(MAXV)..' tblMax '..tostring(sortedProfile[1].vol))

        if maxPrice == 0 then
            maxPrice = O(index) 
        end

        table.sort(sortedProfile, function(a,b) return (a['vol'] or 0) > (b['vol'] or 0) end)

        ---------------------
        for i=1,lines do                                        

            outlines[i] = {index = index-shift+bars, val = maxPrice}
            
            if sortedProfile[i]~=nil then               
                sortedProfile[i].vol=math.floor(sortedProfile[i].vol/MAXV*bars)
                if sortedProfile[i].vol>0 then
                    outlines[i].index = index-shift+sortedProfile[i].vol
                    outlines[i].val = sortedProfile[i].price                           
                end                                               
            end                   
            SetValue(index-shift,       i+1, outlines[i].val)
            SetValue(outlines[i].index, i+1, outlines[i].val)
                    
            --WriteLog('line '..tostring(i).." price "..tostring(GetValue(index-shift, i)).." - "..tostring(GetValue(outlines[i].index, i)).." vol "..tostring(outlines[i].index-index+shift))
                
        end                

        if showMaxLine==1 then
            SetValue(index-shift, 1, maxPrice)
            maxPriceLine[index] = maxPrice
        end

        calculated_buffer[index] = true
                
        return maxPriceLine[index]
    end
end

function WriteLog(text)

    logfile:write(tostring(os.date("%c",os.time())).." "..text.."\n");
    logfile:flush();
    LASTLOGSTRING = text;
 
end
Динамическое количество линий индикатора
 
Я привел весь код индикатора.
Больше кода в нем нет.

Вы хотите увидеть ка формируется табоица algoResults? Но она получается из dll. Это простая таблица в которой накопленный объем по цене.
Далее они просто выводятся.

В Вашем примере, данные не получаются онлайн. Вы их вывели по данным прошлых свечек. А значит, при первом вызове OnCalculate, все данные для линий получены. При установке индикатора OnCalculate вызывается же два раза. Хотя зачем?

Делаю предположение, что это как-то связано.

Вот, для примера, испорченный индикатор горизонтальных объемов. Он реализует такой же алгоритм, получая данные из свечек, а не из dll.
В таком варианте он не работает как надо:
Код
--logfile=io.open(getWorkingFolder().."\\LuaIndicators\\priceAvgProfile.txt", "w")

Settings={}
Settings.period = 150
Settings.shift = 100
Settings.Name = "*priceAvgProfile"
Settings.weeks = 0 -- 1 - текущая, отрицательное число - сколько прошлых недель, включая текущую
Settings.fixShift = 1 -- 1 - всегда смещено на указанное количество shift, если 0, то будет смещено на дату начала неделеи расчета
Settings.showMaxLine = 1
---------------------------------------------------------------------------------------

lines = 100
scale = 2
min_price_step = 1

function Init()
    Settings.line = {}
    Settings.line[1] = {}
    Settings.line[1] = {Name = 'maxVol', Color = RGB(255, 128, 64), Type = TYPE_LINE, Width = 2}
    for i = 1, lines do
        Settings.line[i+1] = {}
        Settings.line[i+1] = {Color = RGB(185, 185, 185), Type = TYPE_LINE, Width = 2}
    end
    
    myFFF = FFF()
    return lines
end

function OnCalculate(index)
    if index == 1 then
        DSInfo = getDataSourceInfo()        
        min_price_step = getParamEx(DSInfo.class_code, DSInfo.sec_code, "SEC_PRICE_STEP").param_value
        scale = getSecurityInfo(DSInfo.class_code, DSInfo.sec_code).scale
    end 
    return myFFF(index, Settings)
end

---------------------------------------------------------------------------------------
function FFF()

    local cacheL={}
    local cacheH={}
    local cacheC={}
    local weeksBegin={}
    local maxPriceLine={}

    local outlines = {}
    local calculated_buffer={}
    
    return function(ind, Fsettings)

        local period = Fsettings.period or 150
        local shift = Fsettings.shift or 150
        local weeks = Fsettings.weeks or 0
        local fixShift = Fsettings.fixShift or 0
        local showMaxLine = Fsettings.showMaxLine or 0
        local bars = 50

        shift = math.max(bars+1, shift)

        local index = ind

        if index == 1 then          
            maxPriceLine = {}
            weeksBegin = {}
            cacheL = {}
            cacheL[index] = 0           
            cacheH = {}
            cacheH[index] = 0           
            cacheC = {}
            cacheC[index] = 0           

            calculated_buffer = {}
            outlines = {}

            return nil
        end
    ------------------------------      

        --maxPriceLine[index] = maxPriceLine[index-1] 
        cacheL[index] = cacheL[index-1] 
        cacheH[index] = cacheH[index-1] 
        cacheC[index] = cacheC[index-1] 

        if not CandleExist(index) then
            return maxPriceLine[index]
        end

        cacheH[index] = H(index)
        cacheL[index] = L(index)
        cacheC[index] = C(index)
        
        if T(index).week_day<T(index-1).week_day or T(index).year>T(index-1).year then
            weeksBegin[#weeksBegin+1] = index
        end

        if index < Size() then return nil end   

        if calculated_buffer[index] ~= nil then
            return maxPriceLine[index]
        end

        if showMaxLine==1 then
            SetValue(index-shift-1, 1, nil)
            SetValue(index-shift,   1, nil)
        end

        for i=1,#outlines do                        
            SetValue(index-shift-1,          i+1, nil)
            SetValue(index-shift,            i+1, nil)
            SetValue(outlines[i].index,      i+1, nil)
            
            outlines[i].index = index-shift
            outlines[i].val = nil
        end            
        
        local beginIndex = index-period
        if weeks == 1 then
            beginIndex = weeksBegin[#weeksBegin] or beginIndex
        end
        if weeks < 0 then
            beginIndex = weeksBegin[#weeksBegin+weeks] or beginIndex
        end
        
        if fixShift==0 then
            shift = math.max(bars+1, index-beginIndex)
        end

        --WriteLog('weeks '..tostring(weeks)..' last '..tostring(weeksBegin[#weeksBegin])..' beginIndex '..tostring(beginIndex))
        
        local maxPrice = math.max(unpack(cacheH,math.max(beginIndex, 1),index))
        local minPrice = math.min(unpack(cacheL,math.max(beginIndex, 1),index))       
        
        ----------------------------------------
        local priceProfile = {}
        --local clasterStep = math.max((maxPrice - minPrice)/lines, min_price_step)
        --local clasterStep = (maxPrice - minPrice)/lines
        local clasterStep = 10*min_price_step

        --WriteLog('minPrice '..tostring(minPrice)..' maxPrice '..tostring(maxPrice)..' clasterStep '..tostring(clasterStep))
        
        for i = 0, (index-beginIndex) do
            if CandleExist(index-i) then                
                local barSteps = math.max(math.ceil((H(index-i) - L(index-i))/clasterStep),1)
                for j=0,barSteps-1 do
                    local clasterPrice = math.floor((L(index-i) + j*clasterStep)/clasterStep)*clasterStep
                    local clasterIndex = clasterPrice*math.pow(10, scale)
                    if priceProfile[clasterIndex] == nil then
                        priceProfile[clasterIndex] = {price = clasterPrice, vol = 0}
                    end
                    priceProfile[clasterIndex].vol = priceProfile[clasterIndex].vol + V(index-i)/barSteps
                end
            end
        end

        --------------------
        local MAXV = 0
        local maxPrice = 0
        local maxCount = 0 

        local sortedProfile = {}

        for i, profileItem in pairs(priceProfile) do
            MAXV=math.max(MAXV,profileItem.vol)
            if MAXV == profileItem.vol then
                maxPrice=profileItem.price
            end
            maxCount = maxCount + 1
            sortedProfile[maxCount] = {price = profileItem.price, vol = profileItem.vol}
        end
                
        --WriteLog('maxV '..tostring(MAXV)..' tblMax '..tostring(sortedProfile[1].vol))

        if maxPrice == 0 then
            maxPrice = O(index) 
        end

        table.sort(sortedProfile, function(a,b) return (a['vol'] or 0) > (b['vol'] or 0) end)

        ---------------------
        for i=1,lines do                                        

            
            if sortedProfile[i]~=nil then               
                outlines[i] = {index = index-shift+bars, val = maxPrice}
                sortedProfile[i].vol=math.floor(sortedProfile[i].vol/MAXV*bars)
                if sortedProfile[i].vol>0 then
                    outlines[i].index = index-shift+sortedProfile[i].vol
                    outlines[i].val = sortedProfile[i].price                           
                end                                               
                SetValue(index-shift,       i+1, outlines[i].val)
                SetValue(outlines[i].index, i+1, outlines[i].val)
            end                   
                    
            --WriteLog('line '..tostring(i).." price "..tostring(GetValue(index-shift, i)).." - "..tostring(GetValue(outlines[i].index, i)).." vol "..tostring(outlines[i].index-index+shift))
                
        end                

        if showMaxLine==1 then
            SetValue(index-shift, 1, maxPrice)
            maxPriceLine[index] = maxPrice
        end

        calculated_buffer[index] = true
                
        return maxPriceLine[index]
    end
end

function WriteLog(text)

    logfile:write(tostring(os.date("%c",os.time())).." "..text.."\n");
    logfile:flush();
    LASTLOGSTRING = text;
 
end
Динамическое количество линий индикатора
 
Инициализация производится на полные 150 линий

вот же
Код
lines = 150
min_price_step = 1
scale = 2

function Init()
    Settings.line = {}
    for i = 1, lines do
        Settings.line[i] = {}
        Settings.line[i] = {Color = RGB(185, 185, 185), Type = TYPE_LINE, Width = 2}
    end
        
    algoF = getResults()
    return lines
end

Проблема именно в том, что если выводить линии не все сразу, они почему-то потом не показываются, а только те, что имели значение при запуске.
Далее, по мере поступления новых данных (цена же двигается и торовый диапазон расширяется) в таблицу algoResults, надо выводить новые линии, но они не показываются. Именно визуально не видны, но при этом, что очень странно, GetValue возвращает значение.

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

Если было выведено при инициализации 100 линий (т.е. когда происходит первый вызов OnCalculate), то больше не показывает индикатор.
Далее линии вроде имеют значение, но не видны.
Динамическое количество линий индикатора
 
Цитата
Sergey Gorokhov написал:
Здравствуйте,
Приведите полную версию кода.
Здравствуйте.

Код простой.
Код
require("StaticVar")

Settings ={
    Name = "*priceProfile",
    shift = 150,
    ChartId = "Sheet11"
}   

lines = 150
min_price_step = 1
scale = 2

function Init()
    Settings.line = {}
    for i = 1, lines do
        Settings.line[i] = {}
        Settings.line[i] = {Color = RGB(185, 185, 185), Type = TYPE_LINE, Width = 2}
    end
        
    algoF = getResults()
    return lines

end

function getResults()
    
    local outlines = {}
    local priceProfile = {}
    local tmpOutlines = {}

    return function(index, Fsettings)

        local shift = Fsettings.shift or 150
        local bars = 50

      if index == 1 then
            outlines = {}
            tmpOutlines = {}
            for i=1,lines do --необходимо вывести все линии хотя бы один раз, чтобы потом они отображались без проблем                  
                tmpOutlines[i] = O(Size())
            end
            return unpack(tmpOutlines)
        end
        if index == 2 then
            for i=1,lines do                  
                SetValue(1,i,nil)
            end
            return nil
        end

        if index == Size() then
                    
            stv.UseNameSpace(Fsettings.ChartId)
            algoResults = stv.GetVar('priceProfile')
            
            priceProfile = {}

            if algoResults ~= nil and type(algoResults) == "table" then 
                
                for i=1,#outlines do                   
                
                    SetValue(index-shift-1,          i, nil)
                    SetValue(index-shift,            i, nil)
                    SetValue(outlines[i].index,   i, nil)
                    
                    outlines[i].index = index-shift
                    outlines[i].val = nil
                end            

                local MAXV = 0
                
                local maxCount = 0 
                for i, profileItem in pairs(algoResults) do
                    MAXV=math.max(MAXV,profileItem.vol)
                    maxCount = maxCount + 1
                    priceProfile[maxCount] = {price = profileItem.price, vol = profileItem.vol}
                end
                
                table.sort(priceProfile, function(a,b) return (a['vol'] or 0) > (b['vol'] or 0) end)

                for i=1,math.min(#priceProfile, lines) do                                        
                    if priceProfile[i]~=nil then
                        
                        outlines[i] = {index = index-shift, val = nil}
                        priceProfile[i].vol=math.floor(priceProfile[i].vol/MAXV*bars)
                       
                        if priceProfile[i].vol>0 then
                            outlines[i].index = index-shift+priceProfile[i].vol
                            outlines[i].val = priceProfile[i].price                           
                        end                       
                        
                        SetValue(index-shift,       i, outlines[i].val)
                        SetValue(outlines[i].index, i, outlines[i].val)
                    end                   
                end                
            end
        end

        return nil
    end
end
Динамическое количество линий индикатора
 
Добрый день.

Т.к. в индикаторе необходимо при инициализации указывать количество возвращаемых линий, то написана такая конструкция в функции init:
Код
for i = 1, lines do
        Settings.line[i] = {}
        Settings.line[i] = {Color = RGB(185, 185, 185), Type = TYPE_LINE, Width = 2}
    end
Алгоритм вводит линии по мере наполнения массива линий. Сначала их может быть 20, потом уже 100 и т.д. Для оптимизации линии выводятся только с не пустым значением.

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

Пришлось сделать такой странный костыль:
Код
if index == 1 then
    tmpOutlines = {}
    for i=1,lines do --необходимо вывести все линии хотя бы один раз, чтобы потом они отображались без проблем                  
       tmpOutlines[i] = O(Size())
    end
    return unpack(tmpOutlines)
end
if index == 2 then
    for i=1,lines do                  
        SetValue(1,i,nil)
    end
    return nil
end
Индекс бара
 
Цитата
Виктория написал:
Перезвоните мне пожалуйста     8(904)628-97-40 Виктория
Добрый день.

Не очень понятно кому адресовано данное сообщение.
Индекс бара
 
Цитата
s_mike@rambler.ru написал:
Можно написать простейший индикатор:

function OnCalculate(indx)
return indx
end

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

Есть пожелание по вводу индекса бара (свечи) в контекстной подсказке при наведении на бар.
Сейчас выводится только дата, время и торговые параметры бара, но при отладе скриптов, да и просто для удобства задания диапазона,
хотелось бы видеть индекс без костылей в виде доп. индикаторов.
Высота метки в шагах цены
 
Точнее, если в контекстном меню графика выбрать подменю удалить, то активна команда удалить метки. Но они не виды.
Метки выводятся текстовые, с такими параметрами:
         
Код
FONT_FACE_NAME = "Arial",
            FONT_HEIGHT = 4,
            R = 64,
            G = 200,
            B = 64,
            TRANSPARENT_BACKGROUND = 1,
            ALIGNMENT = "RIGHT",
            YVALUE = 0,
            DATE = (tt.year*10000+tt.month*100+tt.day),
            TIME = ((tt.hour)*10000+(tt.min-2)*100)
Высота метки в шагах цены
 
А еще вопрос - у меня почему-то метки, установленные из кода lua, исчезают при перезапуске Квика.
Мне казалось, что они должны сохраняться. Это же метка.
Обновление пользовательской таблицы/окна
 
Цитата
Александр написал:
хотя если sleep добавить в цикл побольше - перерисовывает..
интересно, какой sleep в цикле main оптимален, чтобы таблица успевала перерисовываться..
Возможно, но тормозить основной поток скрипта, только чтобы вывод был как-то не очень.
У меня установлено 100 - все равно не хватает. А выше ставить уже слишком.

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

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

Собственно очень не хватает процедур пересчета абсолютных координат окна (идеально еще бы иметь событие - "изменение масштаба") в ценовую и временную шкалы. Сразу бы решились многие проблемы. Сейчас просто невозможно рассчитать линию под определенным углом, или, наоборот, рассчитать угол линии.
Обновление пользовательской таблицы/окна
 
Добрый день.

Подниму тему.

Все же есть особенность обновления данных пользовательской таблицы.

Я заметил особенность, что если обновлять данные через SetCell в main, или в фунции вызванной из main, то обновляется таблица только если произвести действия с ней. Скажем, нажать правой клавишей мышки по полю таблицы или подвигать мышкой по шапке таблицы. Иначе данные обновляются с очень большим лагом - до минуты и более. А может и зависнуть совсем - даже остается цвет подсветки цвета от Highlight.

Вот простейший код скрипта. Вывод данных выведен в коллбэк. Все работает "на лету".
Код
CLASS_CODE        = 'SPBFUT'
SEC_CODE          = 'SiU8'
INTERVAL          = INTERVAL_M1

t_id = nil
isRun = true

SeaGreen=12713921       --  RGB(193, 255, 193) нежно-зеленый
RosyBrown=12698111  --  RGB(255, 193, 193) нежно-розовый

function dsCallback()
    local last_price = tonumber(getParamEx(CLASS_CODE,SEC_CODE,"last").param_value)
    local lp = GetCell(t_id, 1, 0).value or last_price
    if lp < last_price then
        Highlight(t_id, 1, 0, SeaGreen, QTABLE_DEFAULT_COLOR,1000)
    elseif lp > last_price then
        Highlight(t_id, 1, 0, RosyBrown, QTABLE_DEFAULT_COLOR,1000)
    end   
    SetCell(t_id, 1, 0, tostring(last_price), last_price) 
end

function OnInit()
  
     local Error = ''
     DS,Error = CreateDataSource(CLASS_CODE, SEC_CODE, INTERVAL)
     -- Проверка
     if DS == nil then
         message('ОШИБКА получения доступа к свечам! '..Error)
         isRun = false
         return
     end
            
     CreateTable()
 
     local last_price = tonumber(getParamEx(CLASS_CODE,SEC_CODE,"last").param_value)
     SetCell(t_id, 1, 0, tostring(last_price), last_price) 
        
     DS:SetUpdateCallback(function(...) dsCallback(...) end)
    
 end

function main()
    
    SetTableNotificationCallback(t_id, event_callback)

    while isRun do 
        sleep(10)           
    end
end

function CreateTable() -- Функция создает таблицу
    
    t_id = AllocTable()
    
    AddColumn(t_id, 0, "price", true, QTABLE_DOUBLE_TYPE, 15)

    tbl = CreateWindow(t_id) 
    SetWindowPos(t_id, 90, 120, 170, 100)
    
    InsertRow(t_id, 1)
    
end

function event_callback(t_id, msg, par1, par2)
    if (msg==QTABLE_CLOSE) then
        isRun = false
    end
end

function OnStop()
    isRun = false
    if t_id~= nil then
        DestroyTable(t_id)
    end
end
Но стоит изменить код на такой (обновление данных помещено внутрь цикла main), то все замирает, пока не "дернешь" окно.
Код
CLASS_CODE        = 'SPBFUT'
SEC_CODE          = 'SiU8'
INTERVAL          = INTERVAL_M1

t_id = nil
isRun = true

SeaGreen=12713921       --  RGB(193, 255, 193) нежно-зеленый
RosyBrown=12698111  --  RGB(255, 193, 193) нежно-розовый

function dsCallback()
   --[[
    local last_price = tonumber(getParamEx(CLASS_CODE,SEC_CODE,"last").param_value)
    local lp = GetCell(t_id, 1, 0).value or last_price
    if lp < last_price then
        Highlight(t_id, 1, 0, SeaGreen, QTABLE_DEFAULT_COLOR,1000)
    elseif lp > last_price then
        Highlight(t_id, 1, 0, RosyBrown, QTABLE_DEFAULT_COLOR,1000)
    end   
    SetCell(t_id, 1, 0, tostring(last_price), last_price) 
    ]]--
end

function OnInit()
  
     local Error = ''
     DS,Error = CreateDataSource(CLASS_CODE, SEC_CODE, INTERVAL)
     -- Проверка
     if DS == nil then
         message('ОШИБКА получения доступа к свечам! '..Error)
         isRun = false
         return
     end
            
     CreateTable()
 
     local last_price = tonumber(getParamEx(CLASS_CODE,SEC_CODE,"last").param_value)
     SetCell(t_id, 1, 0, tostring(last_price), last_price) 
        
     DS:SetUpdateCallback(function(...) dsCallback(...) end)
    
 end

function main()
    
    SetTableNotificationCallback(t_id, event_callback)

    while isRun do 
        local last_price = tonumber(getParamEx(CLASS_CODE,SEC_CODE,"last").param_value)
        local lp = GetCell(t_id, 1, 0).value or last_price
        if lp < last_price then
            Highlight(t_id, 1, 0, SeaGreen, QTABLE_DEFAULT_COLOR,1000)
        elseif lp > last_price then
            Highlight(t_id, 1, 0, RosyBrown, QTABLE_DEFAULT_COLOR,1000)
        end   
        SetCell(t_id, 1, 0, tostring(last_price), last_price) 
        sleep(10)           
    end
end

function CreateTable() -- Функция создает таблицу
    
    t_id = AllocTable()
    
    AddColumn(t_id, 0, "price", true, QTABLE_DOUBLE_TYPE, 15)

    tbl = CreateWindow(t_id) 
    SetWindowPos(t_id, 90, 120, 170, 100)
    
    InsertRow(t_id, 1)
    
end

function event_callback(t_id, msg, par1, par2)
    if (msg==QTABLE_CLOSE) then
        isRun = false
    end
end

function OnStop()
    isRun = false
    if t_id~= nil then
        DestroyTable(t_id)
    end
end
Пришел OnTransReply с пустым brokerref
 
Добрый день.

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

Да, можно хранить отправленные номера и ID в временной таблице, но иногда происходят ситуации когда происходит перезапуск скрипта и надо перечитать заявки и отобрать нужные по параметрам. Поле BROKERREF не подходит совершенно, т.к. на фондовой секции брокер запрещает писать туда что либо отличное от кода клиента. Ка же так? Приходится сейчас городить внешнюю базу данных, чтобы понять, что эта заявка была выставлена роботом и у нее такие-то праметры.
Страницы: 1 2 След.
Наверх