Владимир написал: Я уже говорил, что мой личный рекорд 90.4% в день. И много раз говорил, что рынку насрать, что там МНЕ нужно: любой из тикеров может в любой момент и взлететь и упасть со страшной силой
Ну тут работает Ваше правило 300 * 9 = 2700 или 1/2700 капитала с работала на 90.4% в день.
Владимир написал: Потому в кубышке, что у Вас в коде указано ТРИ инструмента, а не 20. А если у Вас на 20 тикеров тупо денег нет? Или, наоборот, хватает на 200?
Цитата
VPM написал: У меня их не 3 это для простоты изложения, но точно не 300, к примеру для фондового рынка я установил правило ~ 5% Капитала на инструмент, 100% / 20% <= 20 бумаг в портфеле.
На фондовом у меня инвестиционный подход. А рассказываю я про срочный (спекулятивный подход). Сейчас торгую руками отслеживаю в основном 4 тикера, которые котируются в USD, для того чтоб оценить результаты одним взглядом т.е. посчитать пункты. А от 300 * 9 через пять минут можно в обморок упасть Для сравнения на стадии отладки пишу в скрипт тоже 4 , позволяет сравнивать два подхода!
Владимир написал: А что такое "достаточно ликвидные инструменты" на срочном рынке? Я вот с недавнего времени стал торговать НА ВСЕХ фьючах одного тикера - в частности, на квартальных: H, M, U, Z. Закрылись вот недавно Z3, открываю Z4 - пусть даже его пока и в природе не существует. Появится - начнёт торговаться. И ликвидность у него месяц-другой будет почти никакая. А потом постепенно раскочегарится. Мой скрипт умеет торговать при ЛЮБОЙ ликвидности. Между прочим, средняя прибыль на сделку у малоликвидных обычно даже выше.
Вы же сами говорите об эффективности использования капитала, а у Вас получается какую - то часть замораживаете на месяц, пусть даже небольшую, а зачем?
У фьючерса есть еще одна особенность, чем дальше срок исполнения, тем больше отклонение от справедливой цены! По мере приближения срока исполнения его цена будет смещаться в сторону цены актива!
Владимир написал: Ха-ха-ха! Комиссии НИКАК не зависят от количества тикеров. Если я сделаю 100 сделок на одном тикере или по одной на сотне тикерах, комиссия будет та же самая (если средняя цена лота у этой сотни такая же). И что делать с Вашим "правилом 5%", если у Вас те самые ТРИ тикера? Держать почти все деньги в кубышке? А ведь капитал и портфель меняются каждый день, если не каждую минуту!
1) Почему в кубышке? 20 инструментов * 5% капитала = 100% Капитала на 20 инструментов. 2) Как не зависит, у каждого инструмента своя комиссия. Но я даже не об этом. Представим, дневной диапазон одного инструмента в среднем ходит в день на 100 пунктов что составляет 2% изменения в цене. Мой Вариант чтоб взять 100 пунктов мне нужен 1 контракт, (2%), если риск позволяет получить 500 пунктов мне нужно 5 контракт (5*2%) и т.д. Ваш вариант так как тайм фреймы для принятия решений небольшие, а удержание позиции не значительное, то ценна на них делает несколько небольших колебаний, для простоты скажем 0.5%, для того чтоб набрать 2% нужно сделать 4 сделки (4 комиссии).
Владимир написал: Glukator , И у меня этот файл просто содержит строки вида "класс, код", только там ещё валюта, содержимое портфеля (если тикер там есть), настройки разные. Но тоже выдерживается правило "одна строка - один тикер". Кроме того, есть другие строки - данные по кошельку, номер счёта, можно переопределить режим работы скрипта (боевой, тестовый, по историческим данным), добавить или отнять денег или тикеров и т.д. Короче, структура внешнего файла тоже тщательно продумана и столь же подробно описана, как и структура данных в самом скрипте.
У меня это просто отдельный класс (таблица), то что пользователь задает , отвечает на вопросы , где торговать?, чем торговать? Какие средства использовать? и т.д. Я до пересмотра этого еще не дошел (у маркетмейкера структура, а я один ) Возможно далее что то автоматизирую.
Но сейчас актуально проблема как правильно организовать работу с получением хранением и обработкой РЫНОЧНЫХ данных! Что делать с памятью которая растет значительно к концу торгового дня (сессии)? Именно этот пример и привожу!
Владимир написал: VPM , Ну неужели не очевидно? НЕ НАДО КОД ПРАВИТЬ! Скину я, скажем, Борьке, последнюю версию скрипта, и он тут же будет работать, не меняя в нём ни единой запятой!
Согласен, но я так делаю пока для себя и для отладки , просто так удобней пока, и от этого принципиально не что не меняется. Но а если передавать код другому лицу, еще и пароль поставлю, чтоб не лазили!
DS[1][4][n].cc=n>1 and round(DS[i][j]:C(n) - DS[i][j]:C(n-1), feed[i].sec_scale) or 0;
feed[i].sec_scale -- это параметр тиккера sec_scale feed[i]. -- это таблица необходимых параметров? получаю при инициализации и обновляю при каждом обращении к инструменту (feed[i].bid)
Здесь нужно сказать, что у меня не одна глобальная таблица, а несколько и по возможности локальных + классы. Может этим ввел в заблуждение? Пока не вижу смысла собирать все в одну (придерживаюсь своего взгляда, принципиальную схему я показывал Выше)
VPM написал: И как вы будете искать нужный инструмент в этом индексированном массиве? Каждый раз будете в цикле перебирать?
Именно так при получении данных и их подготовке.
DS[1][4][n].cc=n>1 and round(DS[i][j]:C(n) - DS[i][j]:C(n-1), feed[i].sec_scale) or 0; 1 -- первый тикер, 4 тайм фрейм, n- последний бар , n-1 предпоследний бар. Я не понимаю что Вас смущает здесь?
А далее просто
if rule[i].open_buy and OrderSmart[i].position<=0 then --Открыть позицию
Glukator написал: Пока у вас 3 инструмента, эта хренота даже будет работать. Как только у вас их станет 300, или даже 30, вас не спасут ни терабайт оперативки, ни дох**ядерный процессор, потому что все это будет жрать память как голодный слон, тормозить и глючить. Задолбаетесь глюки обходить.
У меня их не 3 это для простоты изложения, но точно не 300, к примеру для фондового рынка я установил правило ~ 5% Капитала на инструмент, 100% / 20% <= 20 бумаг в портфеле. В Вашем варианте Капитал =100% / 300 бумаг <= 0.33% капитала на 1 бумагу? Но мне помнится у Вас еще нужно 300 * 9 тайм фреймов, считайте сами на кого работаете (комиссии).
ДА и на срочном 300 инструментов не нужны достаточно ликвидных. А стоимость позиции регулируется количеством контрактов, и зависит от риска принимаемого в данной позиции! Согласен есть некоторые сложности CreateDataSource, но к моему удивлению оказались не такими тяжелыми как предполагал ранее, видимо потому что лежат на сервере. Получаю так ds:SetEmptyCallback(); С памятью надо подчищать пока пробую варианты.
Glukator написал: Цитата VPM написал: Цитата Владимир написал: Во-вторых, закладыывать список тикеров в код и, следоватеьльно, править код на любой чих есть просто безумие А как нужно? Создайте текстовый файл со списком тикеров, которыми собираетесь торговать, и считывайте его при старте скрипта. У меня, к примеру, этот файл просто содержит строки вида КодTQBR:ABIO TQBR:ABRD TQBR:ZVEZ
В чем разница считывать из файла, или читать таблицу прямо из скрипта, кроме как удобства? local sec = { 'BRG4','NGF4', 'GDH4', }; for i=1,#sec do
Владимир написал: В-третьих, использовать CreateDataSource значит обрекать себя на бесконечные глюки даже если тикеров в портфеле будет столь жалкое количество. Ну и т.д.
Ну если считать то к примеру Н4 то не одной сделки не сделаешь, нужно тогда историю записывать и сохранять!
DS[i][j][n] На мой взгляд все логично, у каждого инструмента есть несколько тайм фреймов, в каждом тайм фрейме есть несколько баров (индексов), такая вложенность (матрешка), а дальше идут переменные или еще таблицы! Что не так?
Glukator написал: А не так что "хочу упихать все в таблицы" и все тут. Правильно организовать данные - это большая работа, и делается она не из желания упихать все куда-нибудь, а из соображений удобства и быстроты доступа к этим данным в дальнейшем.
"Таблицы в Lua — это не одна из структур данных, — это единственная структура данных". "Таблицы - это всё. Хотя, на самом деле, таблицы это просто способ хранить множество пар "ключ-значение", а все остальное - это то, какие вы выбираете ключи и какие значения."
Glukator, Согласен, Ну конечно все так и делают! Именно этим и занимаюсь, собираю отдельные переменные в таблицы. Цель максимально локализовать переменные. От этого тоже отказался лишнее bar={}; bar[ticer][tf][inde[]={}; Все уже и так есть.
nikolz написал: На верхнем графики автоматически строятся уровни поддержки и сопротивления и линии регрессии.
Если Вы используете в качестве входного параметра регрессию, то можно попробовать фильтровать цену за интересующий Вас период. Это позволит значительно уменьшить отставание, по сравнению с регрессией, а второе изменяя период можно пробовать на разных частотах, или сразу спектр частот. Если будете пробовать поделитесь результатом.
Склоняюсь к варианту А (подход Владимир,), подход опробован, как утверждает Владимир, показывает отличный результат, такое дерево всегда можно в последующим более аккуратно наследовать в глобальную таблицу. Подход Б требует дополнительного ознакомления, что можно чего нельзя. И так решено подход А, соберу в четырех этажную таблицу переменные. bar={}; bar[ticer][tf][inde[]={};
Пересмотрел главу Окружение. "Поскольку окружение — это обычная таблица, то вы можете просто индексировать ее нужным ключом (именем переменной). Похожим образом можно присвоить значение глобальной переменной, чье имя вычисляется динамически, если написать _G[varname] = value."
Есть еще одна интересная "штука": "Поскольку _ENV — это обычная переменная, мы можем обращаться к ней и присваивать значения как и любой другой переменной. Присваивание _ENV=nil сведет на нет любой прямой доступ к глобальным переменным в оставшейся части куска. Это может пригодиться для контроля над тем, какие переменные использует ваш код" "Конечно, главной областью применения _ENV является изменение окружения, используемого фрагментом кода."
for n in pairs(_G) do print(n) end; А так можно узнать какие глобальные переменные используются. Понимание организационной структуры приводит к пониманию, установлению компромисса между быстродействием и производительностью, ну и не забываем про простоту кода.
"Едем дальше, видим больше!" 1) Структура: Итак, вплотную подошли к вопросу организации структуры данных в скрипте.
Цитата
Владимир написал: Для меня давно очевидно, что чуть ли не единственная важная тема - это определение структур данных. Даже код скрипта базируется на этом! И это СЛОЖНАЯ тема.
Из того что выше обсуждалось можно сделать вывод, есть два подхода:
А) Создать внутреннею переменную (таблицу) и уже внутри нее строить дерево.
Цитата
Владимир написал: В частности, "таблица Lua" у меня представляет собой большое разветвлённое дерево уровней на пять, если не больше. А переменные туда целесообразно относить, где их удобнее всего использовать.
Б) Создать в глобальном окружении, служебные поля для переменных данного скрипта; Про такой подход подсказал Игорь М, описан автором языка в его книге, и применяется разработчиками QUIK при создании модуля qlua. Вот такие две записи идентичны:
local varname = 20 local value = load or loadstring("return " .. varname)() print(value)
Более эффективная: _G[varname] = value local value = _G[varname] print(value)
nikolz написал: Могу посоветовать следующее. Написали что-то. Поставьте в начале блока N=os.clock()и в конце time=os.clock() -N и выведите time в сообщение. Вы узнаете сколько реально в секундах у вас выполняется этот блок. Если это разовый блок в начале запуска, то время вообще не колышет. Если время вас устраивает, то забудьте про этот блок и пишите дальше.
Да я так делаю, еще получаю используемую память, а в главное окно скрипта вывожу прямо в заголовок окна, удобно всегда перед глазами информация как работает скрипт.
"Повторение мать ученья"! Благодарю за обсуждение и ликбез, не которые мои сомнения развеялись, понятно стало в какую сторону копать. Надеюсь что обсуждение было полезно не только мне.
Владимир, Ну мой пример маленько о другом, о тех переменных которыми редко пользуемся, те которые можно отправить на небольшое хранение и потом достать. Допустим торговая система открыла позицию, создали таблицу с параметрами этой позиции, писать в файл эту таблицу не эффективно, так как будем часто обращаться к ней , другое дело позицию закрыли записали свою сделку в файл, и достаем когда уже когда обрабатываем сделки.
Такой подход встречал в работах Nikolay, Не очень понятно зачем лезть в поле глобальной переменной, предполагал что ради видимости. Но не как не могу себе предположить, что это более эффективно, тогда возможно нужно дерево сделать как Владимир, ("Волки сыты и овцы целы")?
Цитата
Владимир написал: Для меня давно очевидно, что чуть ли не единственная важная тема - это определение структур данных. Даже код скрипта базируется на этом! И это СЛОЖНАЯ тема. В частности, "таблица Lua" у меня представляет собой большое разветвлённое дерево уровней на пять, если не больше. А переменные туда целесообразно относить, где их удобнее всего использовать.
Игорь М, Да нет в книге то, не понятно как в жизни этим пользоваться, чем руководствоваться можно какой - то не большой пример?
Цитата
Игорь М написал: Вы можете добиться того же эффекта при помощи следующего кода, который в десятки раз эффективнее предыдущего: value = _G[varname]".
Это что писать в глобальную переменную? Ну к примеру вот:
Код
local Order={}
function Order:new() -- проинициализируем поля, процедуры и фунции нашего класса
---- Создает экземпляр теперь уже объекта, описывает поля объекта и присваивает полям начальные значения.
local obj = {
[0]=0,
['id']=0,--['symbol']='X',
[1]={
['d']='0',
['t']='0',
['dir']='X',
['qty']=0,
['op']=0,
['id']=0
},
};
----далее превращаем таблицу в класс
setmetatable(obj,self)
---- объект получает доступ к методам класса
self.__index = self
---- возвращаем наш объект (экземпляр класса)
return obj
end
function Order:save(path) -- пишем
table.save(self,path)
end
Сделал класс, написал под него метод , вот использую
Код
local order=Order:new()
order:save(path..'\\1.dat')
order:printf()
local ord = table.read(path..'\\1.dat')
Log:info( 'table.read '..type(ord)..' '..tostring(ord[0])..' '..tostring(ord.id) )
Владимир написал: Небольшой парсер в main, заглатыающий исходные данные при запуске скрипта и небольшая функция, сбрасывающая в файл дамп текущего состояния каждые 3 минуты - всё, что требуется. Работает как часы, в любых версиях Квика и языка.
Если Вы про парсер который освещали в начале своих публикаций, то я на нем "зуб потерял"? Дамп текущего состояния, вообще не понятно что туда писать, почему через 3 минуты сохранять, нужен какой - то подход?
При организации структуры программы в виде классов, проявилась еще одна особенность lua! В случае обнаружения при выполнении ошибки, скрипт останавливается, там где раньше перепрыгивал через эту ошибку и продолжал выполнение. Нашел этому объяснение, хочу поделиться:
"Errare humanum est. Поэтому мы должны обрабатывать ошибки как можно лучше. Поскольку Lua — это язык расширения, часто встраиваемый в приложение, он не может просто аварийно завершить работу или завершить работу в случае возникновения ошибки. Вместо этого при возникновении ошибки Lua завершает текущий фрагмент и возвращается в приложение."
"Любое неожиданное условие, с которым сталкивается Lua, вызывает ошибку. Ошибки возникают, когда вы (то есть ваша программа) пытаетесь добавить значения, не являющиеся числами, вызвать значения, не являющиеся функциями, индексировать значения, не являющиеся таблицами, и т. д. (Вы можете изменить это поведение с помощью метатаблиц , как мы увидим позже.) " Стало чуть сложней искать, но появилась уверенность, что программа с ошибками не будет исполняться!
Владимир, Вы подняли сейчас, очень нужную техническую тему и даже не одну, там где для Вас вещи очевидные, для меня и таких как я полная "тьма".
Цитата
Владимир написал: Во-первых, формат данных в ОЗУ совершенно другой - там важна скорость, прямой доступ к данным. Во-вторых, не нужно сохранять всё - у меня объём таблицы в ОЗУ раз в пять больше, чем сохраняемых данных.
Вопрос такой, не вдаваясь сильно в детали, есть какие - то критерии оценки какие переменные куда целесообразно относить,
Ну здесь все просто, если читать из файла f:read("a") получим строковой формат, перевод в функцию и чтение из функции позволяет работать в формате таблицы. Не знаю насчет элегантности, но очень удобно при дальнейшей обработке.
Glukator, Я этим пользовался в lua 5.1 при переходе на 5.4 перестало работать, вот смысл:
Цитата
Используем преобразование таблицы в текстовое представление и сохраняем на диске результаты.
-- Сохранение таблицы или массива в файл function table.save(tbl,filename) local f,err = io.open(filename,"w") if not f then return nil,err end f:write(table.tostring(tbl)) f:close() return true end
В результате на диске мы получим файл, в котором в терминах синтаксика языка Lua описана наша таблица. Зачем сохранять в синтаксисе Lua? Причин две:
универсальность
элегантный способ чтения таблицы из файла
Вот функция, читающая файл и возвращающая сохранённую в нем таблицу:
-- Чтение таблицы из файла в массива или таблицу function table.read(filename) local f,err = io.open(filename,"r") if not f then return nil,err end local tbl = assert(loadstring("return " .. f:read("*a"))) f:close() return tbl() end
Все просто - читаем файл и запускаем его на выполнение
Вот как это выглядит:
table.save({11,22,33,{"gh",'jk'},44},"e:\\1.dat") -- пишем t = table.read("e:\\1.dat") -- читаем
Считывает файл fileв соответствии с заданными форматами, которые определяют, что читать. Для каждого формата функция возвращает строку или число с прочитанными символами или завершается ошибкой , если она не может прочитать данные в указанном формате. (В последнем случае функция не считывает последующие форматы.) При вызове без аргументов она использует формат по умолчанию, который считывает следующую строку (см. ниже).
Доступные форматы
« a»: читает весь файл, начиная с текущей позиции. В конце файла возвращается пустая строка; этот формат никогда не подводит.
----- Чтение таблицы из файла в массив или таблицу --message(filename) local f,err = io.open(filename,"r")--"r": режим чтения (используется по умолчанию); if not f then return nil,err end local tbl = assert(load("return "..f:read("a")))--"a": режим дозаписи в конец файла f:close()
Никак не могу понять, что изменилось в lua 5.4 и перестала работать строка, подскажите что тут не так?
Ну к примеру сделка прошла (не обязательно закрытие но и уменьшение позиции) я сохраняю в таблицу такие показатели (Выиграла +1 Проиграла -1,), то есть количество выиграны и проигранных сделок, плюс сам результат, это позволяет делать оценку торговой системы, как я уже приводил?
nikolz, Написаны они у меня практически все , отдельно оценить нельзя так как работают в составе какой то стратегии, активно пользуюсь Decycler только индикатором в основном однополосным. Но интересны не его примеры индикаторов, а его фильтры, посмотрите "швейцарский складешок", если не найдете я более точно на пишу. А Вам зачем?