本页源码来自 TradingView 公开发布的开源脚本,版权归原作者所有, 请遵循其原始许可(Pine 脚本常见 CC BY-NC-SA / MPL-2.0 / MIT)。 本项目仅用于研究检索与许可范围内的移植。
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © HeWhoMustNotBeNamed
// ░▒
// ▒▒▒ ▒▒
// ▒▒▒▒▒ ▒▒
// ▒▒▒▒▒▒▒░ ▒ ▒▒
// ▒▒▒▒▒▒ ▒ ▒▒
// ▓▒▒▒ ▒ ▒▒▒▒▒▒▒▒▒▒▒
// ▒▒▒▒▒▒▒▒▒▒▒ ▒ ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
// ▒ ▒ ░▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒░
// ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒░▒▒▒▒▒▒▒▒
// ▓▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒ ▒▒
// ▒▒▒▒▒ ▒▒▒▒▒▒▒
// ▒▒▒▒▒▒▒▒▒
// ▒▒▒▒▒ ▒▒▒▒▒
// ░▒▒▒▒ ▒▒▒▒▓ ████████╗██████╗ ███████╗███╗ ██╗██████╗ ██████╗ ███████╗ ██████╗ ██████╗ ██████╗ ███████╗
// ▓▒▒▒▒ ▒▒▒▒ ╚══██╔══╝██╔══██╗██╔════╝████╗ ██║██╔══██╗██╔═══██╗██╔════╝██╔════╝██╔═══██╗██╔══██╗██╔════╝
// ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒ ██║ ██████╔╝█████╗ ██╔██╗ ██║██║ ██║██║ ██║███████╗██║ ██║ ██║██████╔╝█████╗
// ▒▒▒▒▒ ▒▒▒▒▒ ██║ ██╔══██╗██╔══╝ ██║╚██╗██║██║ ██║██║ ██║╚════██║██║ ██║ ██║██╔═══╝ ██╔══╝
// ▒▒▒▒▒ ▒▒▒▒▒ ██║ ██║ ██║███████╗██║ ╚████║██████╔╝╚██████╔╝███████║╚██████╗╚██████╔╝██║ ███████╗
// ▒▒ ▒
//@version=5
import HeWhoMustNotBeNamed/DrawingTypes/1 as dr
import HeWhoMustNotBeNamed/DrawingMethods/1
import HeWhoMustNotBeNamed/ZigzagTypes/2 as zg
import HeWhoMustNotBeNamed/ZigzagMethods/3
import HeWhoMustNotBeNamed/utils/1 as ut
import HeWhoMustNotBeNamed/TradeTracker/1 as t
import HeWhoMustNotBeNamed/ReversalChartPatternLibrary/1 as rcp
import HeWhoMustNotBeNamed/Logger/1 as l
indicator("Recursive Reversal Chart Patterns [Trendoscope]", "RRCP[Trendoscope]", overlay = true, max_lines_count=500, max_labels_count=500, max_bars_back = 1000)
theme = input.string('Dark', title='Theme', options=['Light', 'Dark'], group='Generic Settings',
tooltip='Chart theme settings. Line and label colors are generted based on the theme settings. If dark theme is selected, '+
'lighter colors are used and if light theme is selected, darker colors are used.')
var logger = l.Logger.new(pageSize=20, minimumLevel = 'DEBUG')
logger.init()
zigzagLength = input.int(8, step=5, minval=3, title='Length', group='Zigzag', tooltip='Zigzag length for level 0 zigzag')
depth = input.int(50, "Depth", step=25, maxval=500, group='Zigzag', tooltip='Zigzag depth refers to max number of pivots to be held for multi level calculations')
minimumZigZagLevel = input.int(0, "Minimum Zigzag Level", group='Zigzag', minval = 0, tooltip = 'Minimum zigzag level to consider for pattern scanning')
useRealTimeBars = true
enableDoubleTap = input.bool(true, 'Double Tap', group='Patterns')
enableTripleTap = input.bool(true, 'Triple Tap', group='Patterns')
enableCupAndHandle = input.bool(false, 'Cup And Handle', group='Patterns')
enableHeadAndShoulders = input.bool(false, 'Head And Shoulders', group='Patterns')
errorPercent = input.int(13, 'Error Percent', 0, 50, 5, group='Scanner', tooltip = 'Error percent threshold used for ratio based calculations')
shoulderStart = input.float(0.1, 'Shoulder Start', 0.1, 1.0, 0.05, group='Scanner', tooltip= 'Start of shoulder ratio range. Used for identifying handle, necks, shoulders')
shoulderEnd = input.float(0.5, 'Shoulder End', 0.5, 1.0, 0.05, group='Scanner', tooltip = 'End of shoulder ratio range. Used for identifying handle, necks, shoulders')
riskAdjustment = input.int(13, 'Risk Adjustment Percent', 0, 50, 5, group='Scanner', tooltip = 'Additional padding on the risk. Used for stop loss calculation')
enableRsi = input.bool(false, 'RSI', group='Indicators', inline='rsi')
rsiLength = input.int(14, '', group='Indicators', inline='rsi', tooltip='Enable and configure RSI indicator. When checked, an additional check for divergence is used for confirming Patterns')
enableMfi = input.bool(false, 'MFI', group='Indicators', inline='mfi')
mfiLength = input.int(14, '', group='Indicators', inline='mfi', tooltip='Enable and configure MFI indicator. When checked, an additional check for divergence is used for confirming Patterns')
enableObv = input.bool(false, 'OBV', group='Indicators', inline='obv', tooltip = 'Enable and configure OBV indicator. When checked, an additional check for divergence is used for confirming Patterns')
enableCustom = input.bool(false, '', group='Custom External Indicator', inline='custom')
customName = input.string('Custom', '', group='Custom External Indicator', inline='custom')
customValue = input.source(close, '', group='Custom External Indicator', inline='custom', tooltip = 'Enable and configure custom external indicator. When checked, an additional check for divergence is used for confirming Double tap')
showLabel = false
offset = useRealTimeBars? 0 : 1
validPatterns = array.from(false, enableDoubleTap, enableTripleTap, enableCupAndHandle, enableHeadAndShoulders)
indicators = matrix.new<float>()
indicatorNames = array.new<string>()
if(enableRsi)
indicatorNames.unshift('RSI'+str.tostring(rsiLength))
indicators.add_row(0, array.from(ta.rsi(high, rsiLength), ta.rsi(low, rsiLength), ta.rsi(close, rsiLength)))
showLabel := true
if(enableMfi)
indicatorNames.unshift('MFI'+str.tostring(mfiLength))
indicators.add_row(0, array.from(ta.mfi(high, mfiLength), ta.mfi(low, mfiLength), ta.mfi(close, mfiLength)))
showLabel := true
if(enableObv)
indicatorNames.unshift('OBV')
indicators.add_row(0, array.from(ta.obv, ta.obv, ta.obv))
if(enableCustom and customValue!=close)
indicatorNames.unshift(customName)
indicators.add_row(0, array.from(customValue, customValue, customValue))
var themeColors = ut.getColors(theme)
var zg.Zigzag zigzag = zg.Zigzag.new(zigzagLength, depth, offset)
zigzag.calculate(array.from(high, low), indicators, indicatorNames)
var array<rcp.ReversalChartPattern> patterns = array.new<rcp.ReversalChartPattern>()
mlzigzag = zigzag
var count = 0
while(mlzigzag.zigzagPivots.size() > 4)
if(mlzigzag.level >= minimumZigZagLevel)
patternType = mlzigzag.scan(patterns, errorPercent, shoulderStart, shoulderEnd)
if(validPatterns.get(patternType))
count += 1
patternColor = themeColors.remove(0)
themeColors.push(patternColor)
pattern = mlzigzag.createPattern(patternType, patternColor, riskAdjustment).init().draw()
patterns.lpush(pattern)
alert(pattern.getDescription())
mlzigzag := mlzigzag.nextlevel()
logger.info('Number of Patterns : '+str.tostring(count))