// Downloaded From https://www.WiseStockTrader.com /// This is an improved McGinleyDynamic to address the problem with the original. /// See author ImmortalFreedom notes at the link below /// @link https://www.tradingview.com/script/AKsKg1ih-McGinley-Dynamic-Improved-John-R-McGinley-Jr /// /// An example of a problem - pick a stock that has gap down a lot and see what the functions oMD() and iMD() show. _SECTION_BEGIN( "Price" ); SetChartOptions( 0, chartShowArrows | chartShowDates ); _N( Title = StrFormat( "{{NAME}} - {{INTERVAL}} {{DATE}} Open %g, Hi %g, Lo %g, Close %g (%.1f%%) Vol " + WriteVal( V, 1.0 ) + " {{VALUES}}", O, H, L, C, SelectedValue( ROC( C, 1 ) ) ) ); Plot( C, "Close", ParamColor( "Color", colorBlack ), styleNoTitle | ParamStyle( "Style" ) | GetPriceStyle() ); _SECTION_END(); // Original McGinleyDynamic function oMD( array, period ) { local array, period; local i, j, MD; MD = Null; j = NullCount( array ); MD[j] = array[j]; for( i = j + 1; i < BarCount; i++ ) { // The equation is: D = D1 + (I - D1) / ( N * (I/D1)^4) // where // D1 = yesterday's Dynamic, // I = today's price, // N = smoothing factor. MD[ i ] = MD[ i - 1 ] + ( array[i] - MD[i - 1] ) / ( period * ( array[i] / MD[i - 1] ) ^ 4 ); } return MD; } /// @link https://www.tradingview.com/script/AKsKg1ih-McGinley-Dynamic-Improved-John-R-McGinley-Jr /// Improved McGinleyDynamic function iMD( array, period, custom_k, custom_exp ) { local array, period, custom_k, custom_exp; local i, j, MD; period = max( 1.0, Period ); MD = Null; j = NullCount( array ); MD[j] = array[j]; for( i = j + 1; i < BarCount; i++ ) { // original MD // MD[ i ] = MD[ i - 1 ] + ( array[i] - MD[i - 1] ) / ( period * ( array[i] / MD[i - 1] ) ^ 4 ); // author ImmortalFreedom came up with the formula // MD[ i ] = MD[ i - 1 ] + ( array[i] - MD[i - 1] ) / ( custom_k * period * ( array[i] / MD[i - 1] ) ^ custom_exp ); // but author ImmortalFreedom finds Unconstrained McGinley Dynamic, susceptible to miscalculation // It required upgrading the formulation with two constraints. // MD[ i ] = MD[ i - 1 ] + ( array[i] - MD[i - 1] ) / Min( period, Max( 1.0, custom_k * period * ( array[i] / MD[i - 1] ) ^ custom_exp )) // so even with k = 1 and exponent = 4, MD will not give the calculation of the original md MD[ i ] = MD[ i - 1 ] + ( array[i] - MD[i - 1] ) / Min( period, Max( 1.0, custom_k * period * ( array[i] / MD[i - 1] ) ^ custom_exp ) ); } return MD; } _SECTION_BEGIN( "MD" ); source = ParamField( "Price field", -1 ); length = Param( "Length", 25, 1, 300, 0.5 ); Plot( oMD( source, length ), _DEFAULT_NAME(), ParamColor( "Color", colorCycle ), ParamStyle( "Style" ), Null, Null, 0, 1, 2 ); _SECTION_END(); _SECTION_BEGIN( "iMD" ); source = ParamField( "Price field", -1 ); _N( param_source = StrReplace( _PARAM_VALUES(), ")", "" ) ); length = Param( "Length", 25, 1, 300, 0.5 ); _N( formula = ParamList( "Formulas k value", "Modern|Original|Custom k", 0 ) ); kCustom = Param( "Custom k (tweak)", 0.5, 0.3, 1.0, 0.05 ); exponent = Param( "Exponent (tweak)", 4.0, 1.0, 5.0, 0.1 ); switch( formula ) { case "Modern": k_value = 0.6; break; case "Original": k_value = 1.0; break; case "Custom k": default: k_value = kCustom; break; } _N( Param_title = _SECTION_NAME() + Param_source + "," + length + "," + k_value + "," + exponent + ")" ); Plot( iMD( source, length, k_value, exponent ), _DEFAULT_NAME(), ParamColor( "Color", colorCycle ), ParamStyle( "Style" ), Null, Null, 0, 1, 2 ); _SECTION_END();