MTF Ichimoku
by MeMyselfAndI · 2 in use · published 3 months ago
Source
sha256 4711677f9ba5587d
1// MTF Ichimoku — VP Script port of anthonyf50's Pine v4 indicator.2//3// Uses VP Script's native drawing-only plot offset, chart-timeframe metadata,4// and per-bar fill colors. request.security remains causal by design, so HTF5// values appear only after the foreign bar has closed (unlike Pine lookahead).67indicator('MTF Ichimoku — VP', {8 shortTitle: 'MTF Ichimoku — VP',9 pane: 'overlay',10})1112const conversionPeriods = input.int('Conversion Line Periods', 9, { min: 1, max: 500 })13const basePeriods = input.int('Base Line Periods', 26, { min: 1, max: 500 })14const laggingSpan2Periods = input.int('Lagging Span 2 Periods', 52, { min: 1, max: 1000 })15const displacement = input.int('Displacement', 26, { min: 0, max: 500 })16const showLabels = input.bool('Show latest-value labels', true)1718// The useful default stack on a daily chart is D/W/M. A 60-minute default on19// a daily chart asks the data provider for lower-timeframe history, which is20// normally retained for a much shorter period and makes the indicator appear21// only at the chart's recent edge.22const firstActive = input.bool('First Ichimoku — Enable', true)23const firstTf = input.string('First Ichimoku — Timeframe', '1D', {24 options: ['1', '5', '15', '30', '60', '120', '240', '1D', '1W', '1M'],25})26const firstTenkanOn = input.bool('First Ichimoku — Tenkan', true)27const firstKijunOn = input.bool('First Ichimoku — Kijun', true)28const firstChikouOn = input.bool('First Ichimoku — Chikou', true)29const firstCloudOn = input.bool('First Ichimoku — Kumo', true)30const firstMonoCloud = input.bool('First Ichimoku — Monochrome Kumo', true)31const firstLight = input.color('First Ichimoku — Light Color', '#42a5f5')32const firstDark = input.color('First Ichimoku — Dark Color', '#1565c0')3334const secondActive = input.bool('Second Ichimoku — Enable', true)35const secondTf = input.string('Second Ichimoku — Timeframe', '1W', {36 options: ['1', '5', '15', '30', '60', '120', '240', '1D', '1W', '1M'],37})38const secondTenkanOn = input.bool('Second Ichimoku — Tenkan', true)39const secondKijunOn = input.bool('Second Ichimoku — Kijun', true)40const secondChikouOn = input.bool('Second Ichimoku — Chikou', true)41const secondCloudOn = input.bool('Second Ichimoku — Kumo', true)42const secondMonoCloud = input.bool('Second Ichimoku — Monochrome Kumo', true)43const secondLight = input.color('Second Ichimoku — Light Color', '#66bb6a')44const secondDark = input.color('Second Ichimoku — Dark Color', '#2e7d32')4546const thirdActive = input.bool('Third Ichimoku — Enable', true)47const thirdTf = input.string('Third Ichimoku — Timeframe', '1M', {48 options: ['1', '5', '15', '30', '60', '120', '240', '1D', '1W', '1M'],49})50const thirdTenkanOn = input.bool('Third Ichimoku — Tenkan', true)51const thirdKijunOn = input.bool('Third Ichimoku — Kijun', true)52const thirdChikouOn = input.bool('Third Ichimoku — Chikou', true)53const thirdCloudOn = input.bool('Third Ichimoku — Kumo', true)54const thirdMonoCloud = input.bool('Third Ichimoku — Monochrome Kumo', true)55const thirdLight = input.color('Third Ichimoku — Light Color', '#ec407a')56const thirdDark = input.color('Third Ichimoku — Dark Color', '#ad1457')5758const fourthActive = input.bool('Fourth Ichimoku — Enable', false)59const fourthTf = input.string('Fourth Ichimoku — Timeframe', '240', {60 options: ['1', '5', '15', '30', '60', '120', '240', '1D', '1W', '1M'],61})62const fourthTenkanOn = input.bool('Fourth Ichimoku — Tenkan', true)63const fourthKijunOn = input.bool('Fourth Ichimoku — Kijun', true)64const fourthChikouOn = input.bool('Fourth Ichimoku — Chikou', true)65const fourthCloudOn = input.bool('Fourth Ichimoku — Kumo', true)66const fourthMonoCloud = input.bool('Fourth Ichimoku — Monochrome Kumo', true)67const fourthLight = input.color('Fourth Ichimoku — Light Color', '#ffa726')68const fourthDark = input.color('Fourth Ichimoku — Dark Color', '#ef6c00')6970const empty = () => new Array(barCount).fill(null)71const midpoint = (hi, lo, length) => math.mul(math.add(ta.highest(hi, length), ta.lowest(lo, length)), 0.5)72const transparent = (color, alpha) => color[0] === '#' && color.length === 7 ? color + alpha : color7374// Pine converts 26 source-timeframe periods to the equivalent number of chart75// bars before applying its visual offset. VP's offset is also in chart bars.76const displacementInChartBars = (resolution) => {77 const sourceSeconds = timeframe.secondsOf(resolution)78 if (sourceSeconds === 0 || timeframe.seconds === 0) return displacement79 return Math.max(1, Math.round(sourceSeconds / timeframe.seconds)) * displacement80}8182const foreignWarmupBars = Math.max(conversionPeriods, basePeriods, laggingSpan2Periods) + displacement8384const requestIchi = (active, resolution) => {85 const visible = active && timeframe.compare(resolution, timeframe.period) >= 086 if (!visible) {87 return { visible: false, offset: 0, tenkan: empty(), kijun: empty(), chikou: empty(), spanA: empty(), spanB: empty() }88 }8990 const tenkan = request.security('', resolution, (f) => midpoint(f.high, f.low, conversionPeriods), {91 warmupBars: foreignWarmupBars,92 })93 const kijun = request.security('', resolution, (f) => midpoint(f.high, f.low, basePeriods), {94 warmupBars: foreignWarmupBars,95 })96 const chikou = request.security('', resolution, (f) => f.close, {97 warmupBars: foreignWarmupBars,98 })99 const spanA = request.security('', resolution, (f) => {100 const t = midpoint(f.high, f.low, conversionPeriods)101 const k = midpoint(f.high, f.low, basePeriods)102 return math.mul(math.add(t, k), 0.5)103 }, { warmupBars: foreignWarmupBars })104 const spanB = request.security('', resolution, (f) => {105 return midpoint(f.high, f.low, laggingSpan2Periods)106 }, { warmupBars: foreignWarmupBars })107 return { visible: true, offset: displacementInChartBars(resolution), tenkan, kijun, chikou, spanA, spanB }108}109110const mask = (series, visible) => visible ? series : empty()111112const first = requestIchi(firstActive, firstTf)113const second = requestIchi(secondActive, secondTf)114const third = requestIchi(thirdActive, thirdTf)115const fourth = requestIchi(fourthActive, fourthTf)116117const drawIchi = (name, tf, data, tenkanOn, kijunOn, chikouOn, cloudOn, monoCloud, light, dark) => {118 const tenkan = mask(data.tenkan, data.visible && tenkanOn)119 const kijun = mask(data.kijun, data.visible && kijunOn)120 const chikou = mask(data.chikou, data.visible && chikouOn)121 const spanA = mask(data.spanA, data.visible && cloudOn)122 const spanB = mask(data.spanB, data.visible && cloudOn)123124 const cloudColors = new Array(barCount).fill(null)125 if (data.visible && cloudOn) {126 const bullishCloud = transparent(light, '33')127 const bearishCloud = transparent(dark, '33')128 for (let i = 0; i < barCount; i++) {129 if (spanA[i] === null || spanB[i] === null) continue130 cloudColors[i] = monoCloud ? bearishCloud : spanA[i] > spanB[i] ? bullishCloud : bearishCloud131 }132 }133134 plot(tenkan, { title: name + ' Tenkan', color: light, width: 1 })135 plot(kijun, { title: name + ' Kijun', color: dark, width: 2 })136 plot(chikou, { title: name + ' Chikou', color: dark, width: 1, offset: -data.offset })137 const a = plot(spanA, { title: name + ' Senkou A', color: light, width: 1, offset: data.offset })138 const b = plot(spanB, { title: name + ' Senkou B', color: light, width: 1, offset: data.offset })139 fill(a, b, { color: cloudColors })140141 if (!showLabels || !data.visible) return142 let last = -1143 for (let i = barCount - 1; i >= 0; i--) {144 if (data.tenkan[i] !== null || data.kijun[i] !== null || data.spanA[i] !== null) {145 last = i146 break147 }148 }149 if (last < 0) return150 if (tenkanOn && data.tenkan[last] !== null) {151 label(last, data.tenkan[last], 'Tk ' + tf, { color: light, background: '#00000000', size: 10, align: 'left' })152 }153 if (kijunOn && data.kijun[last] !== null) {154 label(last, data.kijun[last], 'Kj ' + tf, { color: dark, background: '#00000000', size: 10, align: 'left' })155 }156 if (chikouOn && data.chikou[last] !== null) {157 label(last, data.chikou[last], 'Ck ' + tf, {158 color: dark, background: '#00000000', size: 10, align: 'left', offset: -data.offset,159 })160 }161 if (cloudOn && data.spanA[last] !== null && data.spanB[last] !== null) {162 label(last, (data.spanA[last] + data.spanB[last]) / 2, 'Kumo ' + tf, {163 color: dark, background: '#00000000', size: 10, align: 'left', offset: data.offset,164 })165 }166}167168drawIchi('First', firstTf, first, firstTenkanOn, firstKijunOn, firstChikouOn, firstCloudOn, firstMonoCloud, firstLight, firstDark)169drawIchi('Second', secondTf, second, secondTenkanOn, secondKijunOn, secondChikouOn, secondCloudOn, secondMonoCloud, secondLight, secondDark)170drawIchi('Third', thirdTf, third, thirdTenkanOn, thirdKijunOn, thirdChikouOn, thirdCloudOn, thirdMonoCloud, thirdLight, thirdDark)171drawIchi('Fourth', fourthTf, fourth, fourthTenkanOn, fourthKijunOn, fourthChikouOn, fourthCloudOn, fourthMonoCloud, fourthLight, fourthDark)172Versions
- v4current4711677f3 months ago
- v3497d0d493 months ago
- v2eb0a18383 months ago
- v1e1ffb0783 months ago
This indicator runs in an isolated sandbox: it cannot reach your account, your data or the network, and if it stops responding it is stopped for you. That does not make it correct — nobody has checked whether it is any good, which is why its source is above.