Могу сказать, что здесь сразу ряд ошибок мешает работе индикатора:
1. Меняем
на
т.к. иначе не сработает это:
Код: Выделить всё
var sma_v = SMA(Input.Close, SMA_P);
var ema_v = EMA(Input.Close, EMA_P);
В Input (Inputs.Price) нет Close
Или вариант 2:
меняем только вызов индикаторов, убрав .Close у Input
Код: Выделить всё
var sma_v = SMA(Input, SMA_P);
var ema_v = EMA(Input, EMA_P);
2. Это
Код: Выделить всё
if(sum.Count > 2)
{
foreach(double d in sum){
if(d > sum.Average()){
max.Add(d);
}
}
}
работает крайне медленно т.к. постоянно вычисляется средняя (Average) в цикле.
меняем на
Код: Выделить всё
if(sum.Count > 2)
{
double sumA = sum.Average();
foreach(double d in sum)
if(d > sumA) max.Add(d);
}
заодно убрал лишние "египетские скобки" { }
3. Вот это удаляем
Код: Выделить всё
// Отсечение средних
if(r_z_s > 0)
{
for(int i=0;i<r_z_s;i++){
diff_area.RemoveAt(i);
}
for(int i=(diff_area.Count-1);i>(diff_area.Count-1) - r_z_s;i--)
{
diff_area.RemoveAt(i);
}
avg_diff = diff_area.Average();
}
и меняем на
Код: Выделить всё
// Отсечение средних
if(r_z_s > 0)
{
diff_area.RemoveRange(0, r_z_s);
diff_area.RemoveRange(diff_area.Count - r_z_s, r_z_s);
avg_diff = diff_area.Average();
}
4. Аналогично поступаем с этим
Код: Выделить всё
if(r_z_m > 0)
{
for(int i=0;i<r_z_m;i++){
max_area.RemoveAt(i);
}
for(int i=(max_area.Count-1);i>(max_area.Count-1) - r_z_m;i--)
{
max_area.RemoveAt(i);
}
max_diff = max_area.Average();
}
меняем на
Код: Выделить всё
if(r_z_m > 0)
{
max_area.RemoveRange(0, r_z_m);
max_area.RemoveRange(max_area.Count - r_z_m, r_z_m);
max_diff = max_area.Average();
}
В итоге получаем следующее (полный код):
Код: Выделить всё
function Initialize()
{
IndicatorName = "Diff_Agg_PieAvg";
PriceStudy = false;
AddInput("Input", Inputs.Candle);
AddParameter("SMA_P", 384, 1); // SMA индикатора
AddParameter("EMA_P", 12, 1);
AddParameter("SMA_H", 384, 1); // SMA для истории
AddParameter("Diff_Avg", 12);
AddParameter("X_Avg", 4);
AddParameter("Percent_Avg", 50);
AddParameter("Percent_High", 50);
AddGlobalVariable("flag", Types.Int, 1); // Нужен для разового назначения при старте
AddGlobalVariable("Period", Types.Int, 0); // Период SMA
AddGlobalVariable("diff_sma", Types.DoubleList);
AddGlobalVariable("sum", Types.DoubleList);
AddSeries("EMA_Diff", DrawAs.Line, Color.Red);
AddSeries("EMA_Diff_Avg_Line", DrawAs.Line, Color.Navy);
AddSeries("EMA_Diff_Max_Avg_Line", DrawAs.Line, Color.Green);
}
function Evaluate()
{
List<double> max = new List<double> ();
// Ограничения пока не накопилась статистика
if (
CurrentIndex < Math.Max(SMA_P, EMA_P)
){
EMA_Diff = 0;
EMA_Diff_Avg_Line = 0;
EMA_Diff_Max_Avg_Line = 0;
return;
}
else
{
if(flag == 1)
{
Period = (int)Math.Round(SMA_H * X_Avg, 0);
flag = 0;
}
// Сначала считаем разлёт
var sma_v = SMA(Input.Close, SMA_P);
var ema_v = EMA(Input.Close, EMA_P);
double diff = (sma_v[0] >= ema_v[0]) ? ((sma_v[0] / ema_v[0] - 1.0)*10000.0) : ((ema_v[0] / sma_v[0] - 1.0)*10000.0);
// Сглаживаем разлет
diff_sma.Add(diff);
if(diff_sma.Count > Diff_Avg)
{
diff_sma.RemoveAt(0);
}
if(diff_sma.Count > 1)
{
diff = diff_sma.Average();
}
// Затем добавляем разлет к сумме
sum.Add(diff);
// Убираем из суммы лишний период
if(sum.Count > Period)
{
sum.RemoveAt(0);
}
// Наполняем массив максимумов
if(sum.Count > 2)
{
double sumA = sum.Average();
foreach(double d in sum)
if(d > sumA) max.Add(d);
}
int r_z_s, r_z_m;
// Определяем количество отсечения
if(sum.Count > 3)
{
r_z_s = (int)Math.Round((100-(double)Percent_Avg)/2/100 * sum.Count, 0);
if(r_z_s > (sum.Count - 2)/2){ r_z_s = (sum.Count - 2)/2; }
} else
{
r_z_s = 0;
}
if(max.Count > 3)
{
r_z_m = (int)Math.Round((100-(double)Percent_High)/2/100 * max.Count, 0);
if(r_z_m > (max.Count-2)/2){ r_z_m = (max.Count - 2)/2; }
} else
{
r_z_m = 0;
}
// Получаем область по всем разлетам
double avg_diff, max_diff;
List<double> diff_area = new List<double> (sum);
List<double> max_area = new List<double> (max);
diff_area.Sort();
max_area.Sort();
// Отсечение средних
if(r_z_s > 0)
{
diff_area.RemoveRange(0, r_z_s);
diff_area.RemoveRange(diff_area.Count - r_z_s, r_z_s);
avg_diff = diff_area.Average();
}
else
{
if(diff_area.Count > 1)
{
avg_diff = diff_area.Average();
} else avg_diff = diff_area[0];
}
if(r_z_m > 0)
{
max_area.RemoveRange(0, r_z_m);
max_area.RemoveRange(max_area.Count - r_z_m, r_z_m);
max_diff = max_area.Average();
}
else
{
if(max_area.Count > 1)
{
max_diff = max_area.Average();
}
else
{
max_diff = avg_diff;
}
}
EMA_Diff = diff;
EMA_Diff_Avg_Line = avg_diff;
EMA_Diff_Max_Avg_Line = max_diff;
}
}
- Diff_Agg_PieAvg-01.png (34.86 КБ) 18567 просмотров
Я не вникал в логику работы индикатора полностью, а лишь исправлял нерабочий код и местами оптимизировал, доведя до работающего индикатора.
Возможно, могут быть ещё проблемы. Проверяйте.