Тогда не надо хранить старые значения. На каждой итерации делаем 2000 сложений. Меньше никак.
Если надо не с периода 1 или 2 начать, тогда для минимального периода применять ускоренный алгоритм с хранением старого значения, а дальше только прибавлять.
Ускоренный алгоритм это два действия - отнять старое, прибавить новое. Значит если минимальный период больше от 4, то есть смысл в его использовании для минимального периода.
Я когда-то давно написал для себя самый простой, но весьма быстрый SMA (один из первым классов у меня был, чтобы научиться).
Может быть пригодится кому такой вариант:
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Sma.mqh
Fry
smart-lab.ru
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/#property copyright"Fry"#property link"smart-lab.ru"// SMA класс:class CSma
{
private:
double SmaBuf[]; // буфер усредненияdouble total; // сумма SМАint p; // указатель буфераint countMA; // счётчик кол-ва проходовint PeriodMA; // периодint digits; // точностьpublic:
// Конструктор объекта// ma_period - период SMA, digits_ - точность результата (кол-во знаков после запятой)
CSma(){Set(10,5);}
~CSma(){ArrayFree(SmaBuf);}
// Этот метод необходим при любом обновлении кривой (всегда от начала)// ma_period - период SMA, digits_ - точность результата (кол-во знаков после запятой)void Set(constint ma_period, constint digits_)
{
digits=digits_;
PeriodMA=ma_period;
ArrayResize(SmaBuf,PeriodMA);
for(int i=0; i<PeriodMA;i++) SmaBuf[i]=0;
total=0; p=0; countMA=0;
}
// метод расчёта закрытых баров. Он обычно вызывается как .Bar(Buf[i-1]) - (-1), потому что не на текущий тик, а на закрытую свечку// Вход : очередной элемент из цепи для сглаживания// Выход: значение SMA для элемента цепи с точностью результата до digits_double Bar(constdouble Input)
{
total += Input-SmaBuf[p]; // получаем новую сумму из цепи входных значений (от 0 до PeriodMA-1 значений)
SmaBuf[p]=Input; // обновляем значение в малой цепиif (p<1) p=PeriodMA; // закольцовка указателя SmaBuf
p--;
countMA++;
if (countMA>PeriodMA) countMA=PeriodMA; // макс состояние счётчика = PeriodMAreturn (NormalizeDouble(total/countMA,digits));
}
// метод расчёта открытых баров. Использовать только для расчёта свежих тиков, а когда свеча закрывается её надо обязательно пересчитать в Bardouble Tick(constdouble Input) {return (NormalizeDouble((total+Input-SmaBuf[p])/countMA,digits));}
// Инициализация цепочки SMA (расчёт на глубину периода)// метод можно вызвать в начале калькуляции, чтобы дальше расчёт SMA строго соответствовал ma_period// суть: от массива Input[] на отрезке [i-ma_period-2]...[i-2] считает цепочку SMA, где i - указатель на старшее значение массива (обычно это текущий бар)// вернёт false, если в массиве недостаточно значенийbool Start(constdouble &Input[])
{
int limit=ArraySize(Input)-3;
int i=limit-PeriodMA;
if(i<0) return(false);
for(;i<limit;i++) Bar(Input[i]); // пересчитываем цепочку SMA на глубину MaPeriodreturn (true);
}
};
Его можно дополнить легко если надо обёрткой, так чтобы тики обрабатывать тем же методом и вообще можно развивать.
Я когда-то давно написал для себя самый простой, но весьма быстрый SMA (один из первым классов у меня был, чтобы научиться).
Может быть пригодится кому такой вариант:
Его можно дополнить легко если надо обёрткой, так чтобы тики обрабатывать тем же методом и вообще можно развивать.
А как его подключить - класс объявил в #include <Sma.mqh> , что ещё надо сделать, что б он заработал? Для четверки будет работать? Быстрей iMA работает, или преимущество в экономии памяти?
-Aleks-: А как его подключить - класс объявил в #include <Sma.mqh> , что ещё надо сделать, что б он заработал? Для четверки будет работать? Быстрей iMA работает, или преимущество в экономии памяти?
*Выше в коде у меня был серьёзный баг! Сейчас увидел и исправил (две строки местами переставил).
Когда я это написал в четвёрке не было никаких классов и не планировалось даже близко, а сейчас у меня нет четвёрки, так что проверить не могу. Работает быстро и экономно, но окупается по настоящему если алгоритм не простой SMA вставить, а какой-нибудь сложный расчёт. Вот тогда разница офигенная.
Этот класс сырой, так что использовать его не очень удобно, но можно развить. Тут главное сам принцип расчёта по цепочке.
Вообще можно статически объявить объект... Индюк для примера (тоже очень давно кодил):
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
_SMA_.mq5
Fry
smart-lab.ru
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/#include <Sma.mqh> // класс SMA//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#property version"1.000"#property description"Simple Moving Average"#property link"smart-lab.ru"#property indicator_chart_window#property indicator_buffers1#property indicator_plots1#property indicator_type1 DRAW_LINE#property indicator_color1 clrGray#property indicator_style1 STYLE_SOLID#property indicator_applied_pricePRICE_CLOSE//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~inputint sma_period=12 ; //Периодinputint Shift=0 ; //Смещение по оси времени//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~double buf_sma[]; // indicator buffer
CSma sma; // Объект расчёта цепочки SMA//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~intOnInit()
{
string label="SMA("+(string)sma_period+")";
IndicatorSetString (INDICATOR_SHORTNAME,label); // set shortname PlotIndexSetString (0,PLOT_LABEL ,label); // and change labelSetIndexBuffer (0,buf_sma,INDICATOR_DATA); // set bufferIndicatorSetInteger(INDICATOR_DIGITS,_Digits); // set accuracyPlotIndexSetInteger(0,PLOT_SHIFT,Shift); // set index shiftreturn(INIT_SUCCEEDED);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~intOnCalculate(constint rates_total, constint prev_calculated, constint begin, constdouble &price[])
{
if(ArrayGetAsSeries(price)) ArraySetAsSeries(price,false); //!!! в доке написано, что надо, а надо ли?if(begin>rates_total) return(0); // исключаем случай, когда начало отрисовки больше, чем баров в историиif(begin!=0) PlotIndexSetInteger(0,PLOT_DRAW_BEGIN,begin); // begin определяет кол-во баров в истории слева, которые не надо отрисовыватьint i=prev_calculated-1; // detect positionif(i<begin) // если требуется полный пересчёт индикатора (бывает довольно часто)
{
i=begin;
sma.Set(sma_period,_Digits); // первичная инициализация объекта
}
for(; i<rates_total-1 && !IsStopped(); i++) // Цикл расчёта закрытых баров (расчёт истории)
{
buf_sma[i]=sma.Bar(price[i]);
}
buf_sma[i]=sma.Tick(price[i]); // Расчёт свежего тика отличается, чтобы не искажать цепочку SMA тикамиreturn(rates_total);
}
Для автора топика здесь самое полезное, то, что не надо создавать 2000 буферов индикатора если нет нужды графику всю это на каждый бар накладывать. Можно создать 2000 экземпляров объекта и сам расчёт будет весьма экономным во всех смыслах.
Другое дело, что я абсолютно согласен с Андреем (Andrey Khatimlianskii)- столько мувингов не нужно =)
2000 с разными периодами
Тогда не надо хранить старые значения. На каждой итерации делаем 2000 сложений. Меньше никак.
Если надо не с периода 1 или 2 начать, тогда для минимального периода применять ускоренный алгоритм с хранением старого значения, а дальше только прибавлять.
Ускоренный алгоритм это два действия - отнять старое, прибавить новое. Значит если минимальный период больше от 4, то есть смысл в его использовании для минимального периода.
Здравствуйте. один вопрос, подскажите пожалуйста, как в эксперт перенести данные индикатора.
Здравствуйте. один вопрос, подскажите пожалуйста, как в эксперт перенести данные индикатора.
iCustom не подходит?
Данные выходят не те, работает как счетчик тиков похоже.
Данные выходят не те, работает как счетчик тиков похоже.
Не понимаю.
И не вижу кода с попыткой вызова. И собственных исследований тоже не вижу.
Пример есть в справке.
Я когда-то давно написал для себя самый простой, но весьма быстрый SMA (один из первым классов у меня был, чтобы научиться).
Может быть пригодится кому такой вариант:
Его можно дополнить легко если надо обёрткой, так чтобы тики обрабатывать тем же методом и вообще можно развивать.
Я когда-то давно написал для себя самый простой, но весьма быстрый SMA (один из первым классов у меня был, чтобы научиться).
Может быть пригодится кому такой вариант:
Его можно дополнить легко если надо обёрткой, так чтобы тики обрабатывать тем же методом и вообще можно развивать.
Не понимаю.
И не вижу кода с попыткой вызова. И собственных исследований тоже не вижу.
Пример есть в справке.
Дело то в том, что нечего интересного я не придумал.
Вообще задача в том чтоб появилась возможность, по заданным параметрам:
- № бара
-№ период МА
Определить значение периода МА на заданном баре в Эксперте через индикатор
Дело то в том, что нечего интересного я не придумал.
Вообще задача в том чтоб появилась возможность, по заданным параметрам:
- № бара
-№ период МА
Определить значение периода МА на заданном баре в Эксперте через индикатор
Придумали, придумали )
Это же МТ5, тут другой подход к кастомным индикаторам. Я же не зря говорил справку почитать )
Все работает:
А чтоб вернуть период МА, заведите для него еще один буффер индикатора (можно невидимый) и обращайтесь к нему.
А как его подключить - класс объявил в #include <Sma.mqh> , что ещё надо сделать, что б он заработал? Для четверки будет работать? Быстрей iMA работает, или преимущество в экономии памяти?
*Выше в коде у меня был серьёзный баг! Сейчас увидел и исправил (две строки местами переставил).
Когда я это написал в четвёрке не было никаких классов и не планировалось даже близко, а сейчас у меня нет четвёрки, так что проверить не могу. Работает быстро и экономно, но окупается по настоящему если алгоритм не простой SMA вставить, а какой-нибудь сложный расчёт. Вот тогда разница офигенная.
Этот класс сырой, так что использовать его не очень удобно, но можно развить. Тут главное сам принцип расчёта по цепочке.
Вообще можно статически объявить объект... Индюк для примера (тоже очень давно кодил):
Для автора топика здесь самое полезное, то, что не надо создавать 2000 буферов индикатора если нет нужды графику всю это на каждый бар накладывать. Можно создать 2000 экземпляров объекта и сам расчёт будет весьма экономным во всех смыслах.
Другое дело, что я абсолютно согласен с Андреем (Andrey Khatimlianskii) - столько мувингов не нужно =)