Skip to content

Commit ad2d511

Browse files
committed
MarketMeannessIndex indicator.
1 parent 8c60332 commit ad2d511

File tree

1 file changed

+104
-0
lines changed

1 file changed

+104
-0
lines changed
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
namespace StockSharp.Algo.Indicators;
2+
3+
/// <summary>
4+
/// Market Meanness Index indicator.
5+
/// </summary>
6+
[Display(
7+
ResourceType = typeof(LocalizedStrings),
8+
Name = LocalizedStrings.MMIKey,
9+
Description = LocalizedStrings.MarketMeannessIndexKey)]
10+
[Doc("topics/indicators/market_meanness_index.html")]
11+
public class MarketMeannessIndex : LengthIndicator<decimal>
12+
{
13+
private int _priceChanges;
14+
private int _directionChanges;
15+
private int _prevDirection;
16+
17+
/// <summary>
18+
/// Initializes a new instance of the <see cref="MarketMeannessIndex"/>.
19+
/// </summary>
20+
public MarketMeannessIndex()
21+
{
22+
Length = 200;
23+
}
24+
25+
/// <inheritdoc />
26+
public override IndicatorMeasures Measure => IndicatorMeasures.Percent;
27+
28+
/// <inheritdoc />
29+
protected override IIndicatorValue OnProcess(IIndicatorValue input)
30+
{
31+
var price = input.ToDecimal();
32+
33+
if (input.IsFinal)
34+
{
35+
if (Buffer.Count == Length)
36+
{
37+
var oldPrice = Buffer[0];
38+
UpdateChanges(oldPrice, Buffer[1], true);
39+
}
40+
41+
Buffer.PushBack(price);
42+
43+
if (Buffer.Count > 1)
44+
{
45+
UpdateChanges(Buffer[^2], price, false);
46+
}
47+
}
48+
49+
if (IsFormed)
50+
{
51+
decimal mmi;
52+
53+
if (input.IsFinal)
54+
{
55+
mmi = _priceChanges > 0 ? 100m * _directionChanges / _priceChanges : 0;
56+
}
57+
else
58+
{
59+
var tempPriceChanges = _priceChanges;
60+
var tempDirectionChanges = _directionChanges;
61+
62+
if (Buffer.Count > 1 && price != Buffer[^1])
63+
{
64+
tempPriceChanges++;
65+
66+
var tempDirection = Math.Sign(price - Buffer[^1]);
67+
68+
if (tempDirection != _prevDirection && _prevDirection != 0)
69+
tempDirectionChanges++;
70+
}
71+
72+
mmi = tempPriceChanges > 0 ? 100m * tempDirectionChanges / tempPriceChanges : 0;
73+
}
74+
75+
return new DecimalIndicatorValue(this, mmi, input.Time);
76+
}
77+
78+
return new DecimalIndicatorValue(this, input.Time);
79+
}
80+
81+
private void UpdateChanges(decimal prevPrice, decimal currentPrice, bool isRemoving)
82+
{
83+
var currentDirection = Math.Sign(currentPrice - prevPrice);
84+
85+
if (currentDirection != 0)
86+
_priceChanges += isRemoving ? -1 : 1;
87+
88+
if (currentDirection != _prevDirection && _prevDirection != 0)
89+
_directionChanges += isRemoving ? -1 : 1;
90+
91+
if (!isRemoving)
92+
_prevDirection = currentDirection;
93+
}
94+
95+
/// <inheritdoc />
96+
public override void Reset()
97+
{
98+
_priceChanges = default;
99+
_directionChanges = default;
100+
_prevDirection = default;
101+
102+
base.Reset();
103+
}
104+
}

0 commit comments

Comments
 (0)