脚本结合了两个范围过滤器,一个EMA和最终振荡器。 这是一种带有警报的指示器类型的脚本,非常适合一分钟的头皮操作,最初是为NAS100开发的,但已成功用于其他符号。 这两个范围过滤器用于检测短期和中期趋势何时处于同一方向。 EMA表示长期趋势,UO用于确定资产是超买还是超卖。 这一指标与分歧指标很好地结合在一起,以增加方向变化的汇合。
此指示器的其他功能: -配置是否仅在资产未超买或超卖时显示买卖标签 -选择是仅在价格高于均线时显示买入,还是仅在均线以下显示卖出 -指示趋势穿过均线的条形图,并选择交叉或交叉下方是否应仅在反向趋势中显示。 -可以确定趋势中的回调。这可能表明趋势持续。 -可以为回调、均线交叉和买入或卖出信号创建警报
回测测试
/*backtest start: 2022-01-01 09:00:00 end: 2022-05-24 15:00:00 period: 5m basePeriod: 1m exchanges: [{"eid":"Futures_CTP","currency":"FUTURES"}] args: [["ContractType","rb888",360008]] */ //@version=5 // Original Script > @DonovanWall // Previous Version > @guikroth // Ultimate Oscillator > @PineCoders // Updated by > @jwelmac ////////////////////////////////////////////////////////////////////////// // Range Filter x 2, EMA and UO ////////////////////////////////////////////////////////////////////////// indicator(title='FTL - Range Filter X2 + EMA + UO', overlay=true) // Groups string groupLeadingRange = "Leading Range Filter" string groupTriggerRange = "Trigger Range Filter" string groupEMA = "EMA" string groupUO = "Ultimate Oscillator (UO)" string GROUP_BUY_OPTIONS = "Buy Options" string GROUP_SELL_OPTIONS = "Sell Options" //------- ********* -------- ********* --------- // Range Filter (Leader) { // Source src = input(defval=hl2, title='数据源', group=groupLeadingRange) // Sampling Period per = input.int(defval=30, minval=1, title='采样周期', group=groupLeadingRange) // Range Multiplier mult = input.float(defval=2.6, minval=0.1, title='区间乘数', group=groupLeadingRange) // Smooth Average Range { smoothrng(x, t, m) => wper = t * 2 - 1 avrng = ta.ema(math.abs(x - x[1]), t) _smoothrng = ta.ema(avrng, wper) * m _smoothrng // } smrng = smoothrng(src, per, mult) // Range Filter{ rngfilter(x, r) => rngfilt = x rngfilt := x > nz(rngfilt[1]) ? x - r < nz(rngfilt[1]) ? nz(rngfilt[1]) : x - r : x + r > nz(rngfilt[1]) ? nz(rngfilt[1]) : x + r rngfilt //} filt = rngfilter(src, smrng) // Filter Direction upward = 0.0 upward := filt > filt[1] ? nz(upward[1]) + 1 : filt < filt[1] ? 0 : nz(upward[1]) downward = 0.0 downward := filt < filt[1] ? nz(downward[1]) + 1 : filt > filt[1] ? 0 : nz(downward[1]) // Colors filtcolor = upward > 0 ? color.lime : downward > 0 ? color.red : color.orange filtplot = plot(filt, color=filtcolor, linewidth=1, title='Range Filter (Leader)') // } //------- ********* -------- ********* --------- //------- ********* -------- ********* --------- // Range Filter (Trigger){ // Source src2 = input(defval=ohlc4, title='数据源', group=groupTriggerRange) // Sampling Period // Settings for 1min chart, US 100. per2 = input.int(defval=48, minval=1, title='采样周期', group=groupTriggerRange) // Range Multiplier mult2 = input.float(defval=3.4, minval=0.1, title='区间乘数', group=groupTriggerRange) // Smooth Average Range smrng2 = smoothrng(src2, per2, mult2) // Range Filter rngfilt2(x, r) => rngfilt = x rngfilt := x > nz(rngfilt[1]) ? x - r < nz(rngfilt[1]) ? nz(rngfilt[1]) : x - r : x + r > nz(rngfilt[1]) ? nz(rngfilt[1]) : x + r rngfilt filt2 = rngfilt2(src2, smrng2) // Filter Direction upward2 = 0.0 upward2 := filt2 > filt2[1] ? nz(upward2[1]) + 1 : filt2 < filt2[1] ? 0 : nz(upward2[1]) downward2 = 0.0 downward2 := filt2 < filt2[1] ? nz(downward2[1]) + 1 : filt2 > filt2[1] ? 0 : nz(downward2[1]) // Colors filtcolor2 = upward2 > 0 ? color.lime : downward2 > 0 ? color.red : color.orange filtplot2 = plot(filt2, color=filtcolor2, linewidth=3, title='Range Filter (trigger)') barcolor = src2 > filt2 and upward2 > 0 ? color.green : src2 < filt2 and downward > 0 ? color.red : color.rgb(120, 123, 134) // Bar Color //barcolor(barcolor) // } //------- ********* -------- ********* --------- //------- ********* -------- ********* --------- // Default EMA 144 { len4 = input.int(144, minval=1, title='周期', group=groupEMA) src4 = input(close, title='数据源') ema = ta.ema(src4, len4) plot(ema, linewidth=3, color=color.new(color.yellow, 0), title='EMA') closeAboveEma = close > ema closeBelowEma = close < ema uptrendCrossoverOnly = input.bool(false, title="仅在上升趋势中显示交叉", group=groupEMA) downtrendCrossunderOnly = input.bool(false, title="仅在下降趋势中显示交叉", group=groupEMA) // END EMA // } //------- ********* -------- ********* --------- // ------ UO { average(bp, tr_, length) => math.sum(bp, length) / math.sum(tr_, length) uo() => length1 = input.int(7, minval=1, title = "快线周期", group=groupUO), length2 = input.int(14, minval=1, title = "中线周期", group=groupUO), length3 = input.int(28, minval=1, title = "慢线周期", group=groupUO) high_ = math.max(high, close[1]) low_ = math.min(low, close[1]) bp = close - low_ tr_ = high_ - low_ avg7 = average(bp, tr_, length1) avg14 = average(bp, tr_, length2) avg28 = average(bp, tr_, length3) 100 * (4*avg7 + 2*avg14 + avg28)/7 uoLevel = uo() // } // Break Outs // Conditions { longCond = bool(na) shortCond = bool(na) longCond := src > filt2 and src > src[1] and upward2 > 0 or src > filt2 and src < src[1] and upward2 > 0 shortCond := src < filt2 and src < src[1] and downward2 > 0 or src < filt2 and src > src[1] and downward2 > 0 CondIni = 0 CondIni := longCond ? 1 : shortCond ? -1 : CondIni[1] // Long (Buy){ overBoughtLevel = input.float(defval=60, minval=50, title='UO超买值', group=GROUP_BUY_OPTIONS) longWhenNotOverbought = input.bool(true, title = '仅在未超买时显示买入(UO)', tooltip = 'Show BUY Signal only when not overbought according to UO', group=GROUP_BUY_OPTIONS) longOnlyAboveEma = input.bool(true, title = '仅在均线上方显示买入', tooltip = 'Show BUY Signal only when price closes above the EMA', group=GROUP_BUY_OPTIONS) longCondition = longCond and CondIni[1] == -1 overBought = uoLevel > overBoughtLevel if (longCondition and longWhenNotOverbought) longCondition := not overBought if (longCondition and longOnlyAboveEma) longCondition := closeAboveEma //} // Short (Sell){ overSoldLevel = input.float(defval=40, maxval=50, title='UO超卖值', group=GROUP_SELL_OPTIONS) shortWhenNotOversold = input.bool(true, title = '仅在未超卖时显示卖出(UO)', tooltip = 'Show SELL Signal only when not oversold according to UO', group=GROUP_SELL_OPTIONS) shortOnlyBelowEma = input.bool(true, title = '仅在均线以下显示卖出', tooltip = 'Show SELL Signal only when price closes below the EMA', group=GROUP_SELL_OPTIONS) shortCondition = shortCond and CondIni[1] == 1 overSold = uoLevel < overSoldLevel if (shortCondition and shortWhenNotOversold) shortCondition := not overSold if (shortCondition and shortOnlyBelowEma) shortCondition := closeBelowEma //} // } // Trend directions { trendUp = upward and upward2 trendDown = downward and downward2 // } // MA Crossover{ arrowSize = size.small emaCrossover = 'EMA Crossover' didEmaCrossover = (not uptrendCrossoverOnly or trendUp) and ta.crossover(close, ema) plotshape( didEmaCrossover, title = emaCrossover, style = shape.triangleup, size = arrowSize, location = location.belowbar, color = color.new(color.green, 0) ) emaCrossunder = 'EMA Crossunder' didEmaCrossunder = (not downtrendCrossunderOnly or trendDown) and ta.crossunder(close, ema) plotshape( didEmaCrossunder, title = emaCrossunder, style = shape.triangledown, size = arrowSize, location = location.abovebar, color = color.new(color.red, 0) ) // } // Pullbacks (a possible indicator of trend continuation) { // Conditions: // - Both filters going in same direction sameDirection = trendUp or trendDown // Did the previous candle close in the opposite direction prevOpp = (trendUp and close[1] < open[1]) or (trendDown and open[1] < close[1]) // Is the current candle in the trend direction inTrendDirection = (trendDown and close < open) or (trendUp and close > open) // - previous candle: crossover one or both in downtrend, crossunder one or both in uptrend prevLimit = trendDown ? high[1] : low[1] var previousCross = false if (trendDown) previousCross := ta.crossover(prevLimit, filt[1]) or ta.crossover(prevLimit, filt2[1]) else previousCross := ta.crossunder(prevLimit, filt[1]) or ta.crossunder(prevLimit, filt2[1]) // - current candle: crossunder one or both in downtrend, crossover one or both in uptrend currentReturn = trendDown ? close < filt : close > filt pullback = prevOpp and inTrendDirection and sameDirection and previousCross and currentReturn uptrendPullback = 'Uptrend Pullback' isUptrendPullback = pullback and trendUp plotshape( isUptrendPullback, title = uptrendPullback, style = shape.diamond, size = arrowSize, location = location.belowbar, color = color.new(color.green, 0) ) downtrendPullback = 'Downtrend Pullback' isDowntrendPullback = pullback and trendDown plotshape( isDowntrendPullback, title = 'Downtrend Pullback', style = shape.diamond, size = arrowSize, location = location.abovebar, color = color.new(color.red, 0) ) // } // Buy/Sell Signal { plotshape(longCondition, title='Buy Signal', text='BUY', textcolor=color.new(color.white, 0), style=shape.labelup, size=size.normal, location=location.belowbar, color=color.new(color.green, 0)) plotshape(shortCondition, title='Sell Signal', text='SELL', textcolor=color.new(color.white, 0), style=shape.labeldown, size=size.normal, location=location.abovebar, color=color.new(color.red, 0)) //} //Alerts{ alertcondition(longCondition, title='Buy Alert', message='BUY') alertcondition(shortCondition, title='Sell Alert', message='SELL') alertcondition(didEmaCrossover, title = emaCrossover, message = emaCrossover) alertcondition(didEmaCrossunder, title = emaCrossunder, message = emaCrossover) alertcondition(isUptrendPullback, title=uptrendPullback, message = uptrendPullback) alertcondition(isDowntrendPullback, title=downtrendPullback, message = downtrendPullback) // } // For use like Strategy, { //1. Change the word "indicator" for "strategy" at the top //2. Remove the "//" below //strategy.entry( id = "Long", long = true, when = longCondition ) //strategy.close( id = "Long", when = shortCondition ) // } if longCondition strategy.entry("Enter Long", strategy.long) else if shortCondition strategy.entry("Enter Short", strategy.short)