Значит так, я нашел две проблемы и сделал хотфиксы, однако мне нужен ревью от кого нибудь кто больше понимает в проекте.
Проблема №1. Если использовать индикатор AverageTrueRange через IndicatorManager то он никогда не расчитывается. Проблема в файле AverageTrueRange.cs строчка 92:
Code
/// <summary>
/// Возможно ли обработать входное значение.
/// </summary>
/// <param name="input">Входное значение.</param>
/// <returns>True, если возможно, иначе, false.</returns>
public override bool CanProcess(IIndicatorValue input)
{
return TrueRange.CanProcess(input) && MovingAverage.CanProcess(input);
}
Тут проверяется может ли индикатор обработать входящее значение. ATR построили как комбинацию TrueRange (который принимает параметр Candle а результатом вычисления является double) и SMA (вход double и выход double). Вообщем это условие будет всегда ложно, т.к. в функцию передается свечка а MA ее не может обработать. Поэтому просто меняем ее на:
Code
return TrueRange.CanProcess(input);
Проблема №2.
После этого изменения у нас будет опять выбрасываться старый эксепшн, из-за которого я открыл этот топик. Ищем откуда растут ноги, смотрим на файл BaseIndicator.cs в районе строки 129 функция Process:
Code
public virtual IIndicatorValue Process(IIndicatorValue input)
{
var value = OnProcess(input);
this.LastValue = value;
var result = value as IIndicatorValue ?? input.SetValue(value);
if (IsFormed && !result.IsEmpty)
RaiseChangedEvent(input, result);
return result;
}
Экспешн происходит на строчке
Code
var result = value as IIndicatorValue ?? input.SetValue(value);
Пытаемся понять что тут происходит. Ага, получается так: мы вычисляем значение индикатор через своего потомка (нас ведь создадут наследовав от BaseIndicator), но вот незадача: что бы быть type safe нам нужно вернуть значение IIndicatorValue, а что может вернуть наша текущая реализация мы не знаем.
Поэтому мы смотрим: если то что вернул process является IIndicatorValue то, возвращаем его, иначе, мы считаем что значение должно быть того же типа что было входящее!
Вот тут то и приходит пушной зверек сверкая глазками. Дело в том что TrueRange принимает на вход Candle а возвращает Double. Здесь и происходит класс каст эксепшн.
К сожалению, я пока еще не знаю всю структуру проекта, поэтому не придумал ничего лучшего как сделать такой хотфикс, который поидее ничего не должен сломать, но починить этот эксепшн. Заменяем строку 135 на:
Code
var result = value is decimal ? new DecimalIndicatorValue(value.To<decimal>()) : value as IIndicatorValue ?? input.SetValue(value);
После этого atr начинает работать :)
Но я думаю это стоит починить по-правильному.