1+ namespace StockSharp . Algo . Indicators ;
2+
3+ /// <summary>
4+ /// Fractal Dimension Index.
5+ /// </summary>
6+ /// <remarks>
7+ /// https://doc.stocksharp.com/topics/api/indicators/list_of_indicators/fractal_dimension.html
8+ /// </remarks>
9+ [ Display (
10+ ResourceType = typeof ( LocalizedStrings ) ,
11+ Name = LocalizedStrings . FractalDimensionKey ,
12+ Description = LocalizedStrings . FractalDimensionDescKey ) ]
13+ [ Doc ( "topics/api/indicators/list_of_indicators/fractal_dimension.html" ) ]
14+ public class FractalDimension : LengthIndicator < decimal >
15+ {
16+ /// <summary>
17+ /// Initializes a new instance of the <see cref="FractalDimension"/>.
18+ /// </summary>
19+ public FractalDimension ( )
20+ {
21+ Length = 30 ;
22+
23+ Buffer . MinComparer = new DecimalOperator ( ) ;
24+ Buffer . MaxComparer = new DecimalOperator ( ) ;
25+ }
26+
27+ /// <inheritdoc />
28+ public override IndicatorMeasures Measure => IndicatorMeasures . MinusOnePlusOne ;
29+
30+ /// <inheritdoc />
31+ protected override IIndicatorValue OnProcess ( IIndicatorValue input )
32+ {
33+ var price = input . GetValue < decimal > ( ) ;
34+
35+ var buffer = Buffer ;
36+
37+ if ( input . IsFinal )
38+ buffer . PushBack ( price ) ;
39+
40+ if ( buffer . Count < 2 )
41+ return new DecimalIndicatorValue ( this , 1.5m , input . Time ) ;
42+
43+ var maxHigh = buffer . Max . Value ;
44+ var minLow = buffer . Min . Value ;
45+
46+ var startIdx = input . IsFinal ? 1 : 2 ;
47+
48+ // Calculate the length of the price path
49+ var pathLength = 0m ;
50+ for ( var i = startIdx ; i < buffer . Count ; i ++ )
51+ {
52+ var prev = buffer [ i - 1 ] ;
53+ var curr = buffer [ i ] ;
54+ pathLength += ( curr - prev ) . Abs ( ) ;
55+ }
56+
57+ if ( ! input . IsFinal )
58+ {
59+ maxHigh = maxHigh . Max ( price ) ;
60+ minLow = minLow . Max ( price ) ;
61+
62+ pathLength += ( price - buffer . Last ( ) ) . Abs ( ) ;
63+ }
64+
65+ // Calculate FDI
66+ decimal fractalDimension ;
67+
68+ var range = maxHigh - minLow ;
69+
70+ if ( pathLength == 0 || range == 0 )
71+ {
72+ fractalDimension = 1.5m ;
73+ }
74+ else
75+ {
76+ // FDI formula: 1 + (log(pathLength) - log(range)) / log(2 * (Length-1))
77+ var logPathLength = pathLength . Log ( ) ;
78+ var logRange = range . Log ( ) ;
79+ var logDenominator = ( 2m * ( Length - 1 ) ) . Log ( ) ;
80+
81+ if ( logDenominator == 0 )
82+ {
83+ fractalDimension = 1.5m ;
84+ }
85+ else
86+ {
87+ fractalDimension = 1m + ( logPathLength - logRange ) / logDenominator ;
88+ }
89+ }
90+
91+ // Clamp between 1.0 and 2.0
92+ fractalDimension = 1.0m . Max ( 2.0m . Min ( fractalDimension ) ) ;
93+
94+ return new DecimalIndicatorValue ( this , fractalDimension , input . Time ) ;
95+ }
96+ }
0 commit comments