I am trying to create an indicator using c# which decides the momentum rating based on the last 30 days of minutes data, every bar is 1 min. I want to rate the momentum on a scale of -10 to +10 depending on how fast it is in either direction negative is down and positive is up. I am using ninjatrader for this. right now I am just smoothing the momentum value, but I need better calculation for this. Please help.
protected override void OnBarUpdate()
{
if (CurrentBar < MomentumPeriod + SmoothnessPeriod + windowSize) return;
momentumValues.Add(momentumValues.Count > 0 ? momentumValues[0] : 0);
double smoothedMomentum = momentumValues.Count >= SmoothnessPeriod
? momentumValues.Skip(momentumValues.Count - SmoothnessPeriod).Take(SmoothnessPeriod).Average()
: momentumValues.Last();
smoothedMomentumValues.Add(smoothedMomentum);
lastSmoothedMomentumValues.Add(smoothedMomentum);
if (lastSmoothedMomentumValues.Count > windowSize)
{
lastSmoothedMomentumValues.RemoveAt(0);
}
double minMomentum = smoothedMomentumValues.Min();
double maxMomentum = smoothedMomentumValues.Max();
double momentumRange = maxMomentum - minMomentum;
double momentumRating = momentumRange != 0
? ((smoothedMomentum - minMomentum) / momentumRange * 20.0) - 10.0
: 0;
momentumRatings.Append(momentumRating);
RoundedSmoothedValue = Math.Round(smoothedMomentum, 2);
double momentumScore = CalculateMomentumScore(RoundedSmoothedValue);
ImmediateMomentum = momentumScore <= -7 ? "Down" : momentumScore >= 7 ? "Up" : "NA";
SolidColorBrush brushColor = momentumScore <= -7 ? Brushes.LightPink : momentumScore >= 7 ? Brushes.LightGreen : Brushes.White;
UpdateOverallMomentum(RoundedSmoothedValue);
if (RoundedSmoothedValue >= 7.0 || RoundedSmoothedValue <= -7.0)
{
PrintMomentumInfo(Time[0], ImmediateMomentum, OverallMomentum, minMomentum, maxMomentum, momentumRating, smoothedMomentum, RoundedSmoothedValue, (int)momentumScore, brushColor);
}
DrawMomentumInfo(OverallMomentum, ImmediateMomentum, momentumScore, RoundedSmoothedValue, (TextPosition)DisplayPosition, brushColor, DisplayFont);
}
private void UpdateOverallMomentum(double roundedSmoothedValue)
{
if (roundedSmoothedValue >= 7.0 && (OverallMomentum == "" || OverallMomentum == "Down"))
{
OverallMomentum = "Up";
}
else if (roundedSmoothedValue <= -7.0 && (OverallMomentum == "" || OverallMomentum == "Up"))
{
OverallMomentum = "Down";
}
}
public int CalculateMomentumScore(double smoothedValue)
{
int momentumScore = (int)Math.Round(smoothedValue);
return Clamp(momentumScore, -10, 10);
}
private int Clamp(int value, int min, int max)
{
if (value < min) return min;
if (value > max) return max;
return value;
}