├── MMISignal.pinescript └── README.md /MMISignal.pinescript: -------------------------------------------------------------------------------- 1 | //@version=3 2 | study("MMI Signal", overlay=true, precision=8) 3 | 4 | // 5 | // Revision: 1 6 | // Author: @sherwind 7 | // URL: https://github.com/sherwind/pinescript-mmi_signal 8 | // 9 | // Trend trading strategies filtered by the Market Meanness Index. 10 | // 11 | // This is a port of the experiment described at 12 | // 13 | // http://www.financial-hacker.com/boosting-systems-by-trade-filtering/ 14 | // http://www.financial-hacker.com/trend-delusion-or-reality/ 15 | // http://www.financial-hacker.com/trend-and-exploiting-it/ 16 | // http://www.financial-hacker.com/whites-reality-check/ 17 | // 18 | // The Market Meanness Index tells whether the market is currently moving in or out of a "trending" regime. 19 | // It can this way prevent losses by false signals of trend indicators. It is a purely statistical algorithm 20 | // and not based on volatility, trends, or cycles of the price curve. 21 | // 22 | // The indicator measures the meanness of the market - its tendency to revert to the mean after pretending 23 | // to start a trend. If that happens too often, all trend following systems will bite the dust. 24 | // 25 | // Inputs: 26 | // 27 | // Price Source: Either open, high, low, close, hl2, hlc3, or ohlc4. The default value is hlc3. 28 | // Trend MA Type: Either SMA, EMA, LowPass, Hull MA, Zero-Lag MA, ALMA, Laguerre, Smooth, Decycle. The default value is LowPass. 29 | // Trend MA Period: Sets the lookback period of trend MA. The default value is 200. 30 | // MMI Period: Sets the lookback period of the Market Meanness Index. The default value is 300. 31 | // 32 | // 33 | // ----------------------------------------------------------------------------- 34 | // Copyright 2018 sherwind 35 | // 36 | // This program is free software: you can redistribute it and/or modify 37 | // it under the terms of the GNU General Public License as published by 38 | // the Free Software Foundation, either version 3 of the License, or 39 | // any later version. 40 | // 41 | // This program is distributed in the hope that it will be useful, 42 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 43 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 44 | // GNU General Public License for more details. 45 | // 46 | // The GNU General Public License can be found here 47 | // . 48 | // 49 | // ----------------------------------------------------------------------------- 50 | // 51 | 52 | price_src = input(title="Price Source", type=source, defval=hlc3) 53 | trend_filter_type = input(defval="LowPass", title="Trend MA Type: ", options=["SMA", "EMA", "LowPass", "Hull MA", "Zero-Lag MA", "ALMA", "Laguerre", "Smooth", "Decycle"], type=string) 54 | trend_filter_len = input(defval=200, title="Trend MA Period", minval=10) 55 | mmi_len = input(defval=300, title="MMI Period", minval=200, maxval=500) // See http://www.opserver.de/ubb7/ubbthreads.php?ubb=showflat&Number=453245#Post453245 56 | 57 | 58 | is_peak(src) => rising(src[1], 1) and falling(src, 1) 59 | is_valley(src) => falling(src[1], 1) and rising(src, 1) 60 | is_rising(src) => rising(src, 1) 61 | is_falling(src) => falling(src, 1) 62 | 63 | median(src, len) => percentile_nearest_rank(src, len, 50) 64 | 65 | // Market Meanness Index by Johann C. Lotter 66 | mmi(src, len) => 67 | len_ = min(len, 1000) 68 | mmi_ = 0.0 69 | if (len_ < 2) 70 | mmi_ := 75 71 | else 72 | nh = 0 73 | nl = 0 74 | median_ = median(src, len_) 75 | for i = 1 to len_ - 1 76 | if (src[i] > median_ and src[i] > src[i - 1]) 77 | nl := nl + 1 78 | else 79 | if (src[i] < median_ and src[i] < src[i - 1]) 80 | nh := nh + 1 81 | mmi_ := 100.0 * (nl + nh) / (len_ - 1) 82 | mmi_ 83 | 84 | // A second order lowpass filter by Johann C. Lotter 85 | lowpass(src, len) => 86 | a = 2.0 / (1 + len) 87 | a2 = a * a 88 | lp = 0.0 89 | lp := (a - 0.25 * a2) * src + 0.5 * a2 * src[1] - (a - 0.75 * a2) * src[2] + 2 * (1.0 - a) * nz(lp[1]) - (1.0 - a) * (1.0 - a) * nz(lp[2]) 90 | lp 91 | 92 | // John Ehlers' "Super Smoother", a 2-pole Butterworth filter combined with a 2-bar SMA that suppresses the Nyquist frequency 93 | smooth(src, len) => 94 | f = (1.414 * 3.14159) / len 95 | a = exp(-f) 96 | c2 = 2 * a * cos(f) 97 | c3 = (-a) * a 98 | c1 = 1 - c2 - c3 99 | s = 0.0 100 | s := c1 * (src + nz(src[1])) * 0.5 + c2 * nz(s[1]) + c3 * nz(s[2]) 101 | s 102 | 103 | // Ehlers' Zero-Lag Moving Average, an EMA with a correction term for removing lag 104 | zma(src, len) => 105 | zma = 0.0 106 | a = 2.0 / (1 + len) 107 | //ema_ = ema(src, len) 108 | ema_ = 0.0 109 | ema_ := a * src + (1 - a) * nz(ema_[1]) 110 | least_error = 1000000.0 111 | gain_limit = 5 112 | best_gain = 0 113 | for gain = -gain_limit to gain_limit - 0.1 by 0.1 114 | zma := a * (ema_ + gain * (src - nz(zma[1]))) + (1 - a) * nz(zma[1]) 115 | error = src - zma 116 | if (abs(error) < least_error) 117 | least_error := abs(error) 118 | best_gain := gain 119 | zma := a * (ema_ + best_gain * (src - nz(zma[1]))) + (1 - a) * nz(zma[1]) 120 | zma 121 | 122 | // A 4-element Laguerre filter 123 | laguerre(src, alpha) => 124 | L0 = 0.0 125 | L0 := alpha * src + (1 - alpha) * nz(L0[1]) 126 | L2 = 0.0 127 | L2 := -(1 - alpha) * L0 + nz(L0[1]) + (1 - alpha) * nz(L2[1]) 128 | L4 = 0.0 129 | L4 := -(1 - alpha) * L2 + nz(L2[1]) + (1 - alpha) * nz(L4[1]) 130 | L6 = 0.0 131 | L6 := -(1 - alpha) * L4 + nz(L4[1]) + (1 - alpha) * nz(L6[1]) 132 | (L0 + 2 * L2 + 2 * L4 + L6) / 6 133 | 134 | // Highpass filter by John F. Ehlers 135 | highpass2(src, len) => 136 | a = (0.707 * 2 * 3.14159) / len 137 | alpha1 = 1.0 + (sin(a) - 1.0) / cos(a) 138 | b = 1.0 - alpha1 / 2.0 139 | c = 1.0 - alpha1 140 | hp = 0.0 141 | hp := b * b * (src - 2 * nz(src[1]) + nz(src[2])) + 2 * c * nz(hp[1]) - c * c * nz(hp[2]) 142 | hp 143 | 144 | // Another low-lag indicator by John Ehlers 145 | decycle(src, len) => 146 | src - highpass2(src, len) 147 | 148 | filter(type, src, len) => 149 | type == "EMA" ? ema(src, len) : 150 | type == "LowPass" ? lowpass(src, len) : 151 | type == "Hull MA" ? wma(2 * wma(src, ceil(len / 2)) - wma(src, len), ceil(sqrt(len))) : 152 | type == "Zero-Lag MA" ? zma(src, len) : 153 | type == "ALMA" ? alma(src, len, 0.85, 6) : 154 | type == "Laguerre" ? laguerre(src, 4.0 / (1 + len)) : 155 | type == "Smooth" ? smooth(src, len) : 156 | type == "Decycle" ? decycle(src, len) : 157 | sma(src, len) 158 | 159 | trend = filter(trend_filter_type, price_src, trend_filter_len) 160 | mmi_raw = mmi(price_src, mmi_len) 161 | mmi_smooth = lowpass(mmi_raw, mmi_len) // SMA is slow, better use LowPass for smoothing MMI. See http://www.financial-hacker.com/boosting-systems-by-trade-filtering/#comment-12654 162 | 163 | // when the smoothed MMI is falling, it means that the market has entered trending mode within the last 200 to 500 bars 164 | plot(trend, linewidth=2) 165 | plotshape(is_valley(trend) and is_falling(mmi_smooth) ? close : na, style=shape.triangleup, location=location.belowbar, color=green, size=size.small) 166 | plotshape(is_peak(trend) and is_falling(mmi_smooth) ? close : na, style=shape.triangledown, location=location.abovebar, color=maroon, size=size.small) 167 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # pinescript-mmi_signal 2 | Trend trading strategies filtered by the Market Meanness Index. 3 | 4 | This is a port of the experiment described at 5 | 6 | http://www.financial-hacker.com/boosting-systems-by-trade-filtering/ 7 | http://www.financial-hacker.com/trend-delusion-or-reality/ 8 | http://www.financial-hacker.com/trend-and-exploiting-it/ 9 | http://www.financial-hacker.com/whites-reality-check/ 10 | 11 | The Market Meanness Index tells whether the market is currently moving in or out of a "trending" regime. 12 | It can this way prevent losses by false signals of trend indicators. It is a purely statistical algorithm 13 | and not based on volatility, trends, or cycles of the price curve. 14 | 15 | The indicator measures the meanness of the market - its tendency to revert to the mean after pretending 16 | to start a trend. If that happens too often, all trend following systems will bite the dust. 17 | 18 | ## Inputs 19 | 20 | - `Price Source`: Either open, high, low, close, hl2, hlc3, or ohlc4. The default value is hlc3. 21 | - `Trend MA Type`: Either SMA, EMA, LowPass, Hull MA, Zero-Lag MA, ALMA, Laguerre, Smooth, Decycle. The default value is LowPass. 22 | - `Trend MA Period`: Sets the lookback period of trend MA. The default value is 200. 23 | - `MMI Period`: Sets the lookback period of the Market Meanness Index. The default value is 300. 24 | --------------------------------------------------------------------------------