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