Macd.lua
- 23 ноября 2014, 14:48
- |
- XXM
Воскресное чтиво.
В образовательных целях.
------------------------------------------------------------------------
— Macd.lua, © hismatullin.h@gmail.com, 23.11.2014
— Короткий период: period1
— Длинный период: period2
— Количество периодов сигнальной скользящей средней: period3
— метод усреднения линий: Exponential
------------------------------------------------------------------------
Settings =
{
Name = «Macd»,
period1 = 12, period2 = 26, period3 = 9,
line=
{
{Name = «Macd», Color = 8404992, Type = 1, Width = 2},
{Name = «Sign», Color = 32768, Type = 1, Width = 2}
}
}
-------------------------------
function Init()
Macd = cached_Macd()
return 2
end
-------------------------------
function OnCalculate(index)
return Macd(index, Settings.period1, Settings.period2, Settings.period3)
end
-------------------------------
function average(_start, _end)
local sum=0
for i = _start, _end do
sum=sum+C(i)
end
return sum/(_end-_start+1)
end
-------------------------------
function cached_Macd()
local cache_EMA_long={}
local cache_EMA_short={}
local cache_MACD={}
local cache_Sign={}
return function(ind, _p01, _p02, _p03)
local n_ema_short = 0 --теущий EMA короткий
local p_ema_short = 0 --предыдущий EMA короткий
local n_sign = 0 --теущий sign
local p_sign = 0 --предыдущий sign
local period_short = _p01
local period_long = _p02
local period_sign = _p03
local index = ind
local k_short = 2/(period_short+1)
local k_long = 2/(period_long+1)
local k_sign = 2/(period_sign+1)
if index == 1 then
cache_EMA_long = {}
cache_EMA_short = {}
cache_MACD = {}
cache_Sign={}
end
-----------------------------------------------
if index < period_long then
cache_EMA_long[index] = average(1,index)
return nil
end
p_ema_long = cache_EMA_long[index-1] or C(index)
n_ema_long = k_long*C(index)+(1-k_long)*p_ema_long
cache_EMA_long[index] = n_ema_long
-----------------------------------------------
if index < period_short then
cache_EMA_short[index] = average(1,index)
return nil
end
p_ema_short = cache_EMA_short[index-1] or C(index)
n_ema_short = k_short*C(index)+(1-k_short)*p_ema_short
cache_EMA_short[index] = n_ema_short
-----------------------------------------------
--считаем сигнальную
cache_MACD[index] = n_ema_short-n_ema_long
p_sign = cache_Sign[index-1] or cache_MACD[index]
n_sign = k_sign*cache_MACD[index]+(1-k_sign)*p_sign
cache_Sign[index] = n_sign
-----------------------------------------------
return n_ema_short-n_ema_long, n_sign
end
end
------------------------------------------------------------------------
Индикаторы технического анализа представляют собой отдельный класс скриптов, которые
удовлетворяют определенным условиям и расположены в папке LuaIndicators в каталоге
терминала. Если папка отсутствует в каталоге, необходимо создать ее вручную. Список
скриптов недоступен из диалога Таблицы / LUA / Доступные скрипты.
При добавлении нового индикатора на график плагин qlua сканирует папку LuaIndicators,
проверяет файлы с расширением lua и luac (скомпилированные скрипты lua) на соответствие
следующим требованиям:
● определена функция Init,
● определена функция OnCalculate,
● определена таблица Lua с именем Settings, в которой есть поле «Name».
Спасибо за пояснение)
Наткнулся вот на Ваш привод — SuperScalp)
Вопрос — для торговли одновременно несколькими инструментами — где и как надо редактировать function getIniSection() — а то в коде SuperScalp эту функцию вообще не нашёл?
можно с примером? как Вы указали для " переворота" в коментариях
Настройки в getInitParameter(). Для нескольких инструментов следует создать таблицу настроек. Переворот — в написанном в комментарии виде должен работать. Если что:
«Ваше пожелание зарегистрировано, будет рассмотрено и, возможно, реализовано в одной из следующих версий нашего ПО» © ;)
Спасибо за оперативный ответ)
а как создать таблицу настроек и где?
как это выглядит в коде например для пары инструментов?
если Вам не трудно)
--настройки
function getInitParameter()
account = 'SPBFUT00995'
classCode = 'SPBFUT'
Frequency = 1000
secCode = {SRZ4, RIZ4}
workSize = {10, 200}
OpenSlippage = {10,150}
end
--------------
Далее к SRZ4 следует обращаться как к secCode[1],
к RIZ4 следует обращаться как к secCode[2].
Это для прописки настроек в коде программы.
Спасибо буду пробовать, хотя сам только начал осваивать LUA
Я Вам ещё в личку написал по поводу индикатора на Lua
Тут ВСЕ прям знают как из простого текстового файла сделать скрипт LUA, поэтому и попросил ссылку.
Возмите любой файл с расширением lua, откройте в блокноте — сотрите все и копируйте этот (см выше) потом сохраняете — получатся то что надо — файл с расширением lua — его копируем в папку LuaIndicators
1. Color = RGB(255,0,0);
2. Color = 255.
Палитру RGB можно выбрать из QUIK (один из множества других способов).
Перевод в формат MSAccess: EXCEL — Макросы — в окне Immediate набираем "?RGB(255,0,0)", жмем «Enter» и получим результат.
Или этот индикатор позволяет:
1...
2...
…
Про сам индикатор написано — переписано. Даже на смарт-лабе несколько постов. Увы, мне добавить к ним нечего, кроме написанного выше кода на LUA.
вот если бы изложили не тривиальные моменты в программировании на qlua или в технологии разработки индикаторов на qlua
Это слишком глобально для «воскресного чтива»
Но про расчет EMA стоит отметить, что в расчетах с первого бара, когда еще нет предыдущих значений EMA(n-1), берутся простые средние SMA:
При сравнении с оригинальным QUIK-овским MACD разница не видна вплоть до пятого знака после запятой, из чего следует, что они считают также.
Вы ведь книжки читаете, хоть раз видели книгу, которая содержит код в чистом виде? — нет...
вот Вам пример, как я вижу «печеньки» в программировании индикаторов.
На мой взгляд, SMA рассчитывать как у Вас нельзя, а точнее, можно выполнить расчет более эффективно, с точки зрения времени вычисления SMA.
В вашем примере для текущего индекса выбирается N предыдущих, суммируются и находится среднее значение.
А можно:
1) завести массив из N элементов, при появлении новой свечи удалять первый и добавлять текущий в конец.
2) завести переменную S, в которой будет содержаться текущая сумма или среднее значение из N элементов
3) при появлении новой свечи из S вычесть первый элемент массива, удалить из массива первый элемент, добавить в конец новый и прибавить его к S
конечно же, в данном случае, может показаться, что это ничего не даст. Можно проверить на тиковых данных и замерить разницу во времени расчета индикатора с циклом и без, как я описал
UPDATE: циклы в любом языке программирования — ЗЛО (всегда замедляют процесс вычисления), их использовать нужно только тогда, когда без них никак нельзя обойтись.
©
Насчет же «печеньки»: первые N для SMA берутся, покуда они меньше некоего значения (например, period_long).
Далее:
Т.е. функция расчета SMA average(1,index) работает пока index<period_long. Далее она не участвует ни в каких расчетах. Без ее работы MACD не будет рассчитан, как заменить ее чем-то, более эффективным, не знаю. Уверен, никто не знает.
Далее, справедлив вопрос: можно ли сделать массивы cache_EMA_long и cache_EMA_short короче при наличии массивов cache_MACD и cache_Sign? Сходу не готов ответить. Подумаю.
я привел подход, который в некоторых задачах даст серьезный прирост производительности.
В данном случае, оптимизация без цикла может ничего особо не дать, но, если, будет на 5% лучше, я бы потратил время на оптимизацию.
Про сам MACD, я очень даже знаю. А вот Ваш MACD, чем отличается, чем замечателен? Чем может помочь трейдеру MACD на LUA, какие у него новые уникальные свойства?
Если внимательно почитать мой вопрос, то можно легко выяснить, что я не спрашиваю, что такое MACD! Я спрашиваю — чем Ваш MACD отличается от известного всем MACDа?
И можно было не отправлять меня на википедию, а просто ответить, что это MACD, просто MACD… (хотя и видно, что он модифицирован)…
Особенность кода индикатора MACD на LUA вижу в том, что у человека есть возможность не только читать где-то правила составления индикатора, знать что его создал некий Gerald Appel в далеком 1960-м году, но и построчно видеть его возникновение из рядов цифр.
Вышеприведенный код беднее QUIK-овского по параметрам, но зато позволяет вволю порезвиться: можно внести параметризацию свечной цены (Open, High, Low, Close) вместо «вшитого» Close, менять метод усреднения линий.
Именно это и хотелось бы сразу услышать)
Подсказываю стратегию, один macd расчитывать по High, второй по Low. Первый использовать для открытия лонгов, второй для выходов.
Для шортов наоборот.
На высоколиквидных инструментах, на старших таймфреймах, при соблюдении правил управления капиталом, может получиться прибыльная стратегия.
Удачи!
«Ну вот, спалил Грааль, блин» © Энергетический Дятел.
К Вашему посту как раз картинка)
Settings = {
Name = «Macd»,
period1 = 12, period2 = 26, period3 = 9, level = 0,
line={
{Name = «Macd», Color = 8404992, Type = 1, Width = 2},
{Name = «Sign», Color = 32768, Type = 1, Width = 2},
{Name = «Level», Color = 255, Type = 1, Width = 2}}}
2.
function Init()
Macd = cached_Macd()
return 3
end
3.
function OnCalculate(index)
local macd, sign = Macd(index, Settings.period1, Settings.period2, Settings.period3)
return macd, sign, Settings.level
end
-----------------
Должно сработать. Добавится «Красный» уровень Zero ;)
Про программное добавление уровней в окне свойств: я не знаю, как это сделать. Это вопрос к ARQA.