Skip to content

MTF Ichimoku

by MeMyselfAndI · 2 in use · published 3 months ago

Loading MTF Ichimoku on BTC-USDT 1h…

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 HTF
5// values appear only after the foreign bar has closed (unlike Pine lookahead).
6
7indicator('MTF Ichimoku — VP', {
8 shortTitle: 'MTF Ichimoku — VP',
9 pane: 'overlay',
10})
11
12const 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)
17
18// The useful default stack on a daily chart is D/W/M. A 60-minute default on
19// a daily chart asks the data provider for lower-timeframe history, which is
20// normally retained for a much shorter period and makes the indicator appear
21// 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')
33
34const 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')
45
46const 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')
57
58const 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')
69
70const 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 : color
73
74// Pine converts 26 source-timeframe periods to the equivalent number of chart
75// 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 displacement
79 return Math.max(1, Math.round(sourceSeconds / timeframe.seconds)) * displacement
80}
81
82const foreignWarmupBars = Math.max(conversionPeriods, basePeriods, laggingSpan2Periods) + displacement
83
84const requestIchi = (active, resolution) => {
85 const visible = active && timeframe.compare(resolution, timeframe.period) >= 0
86 if (!visible) {
87 return { visible: false, offset: 0, tenkan: empty(), kijun: empty(), chikou: empty(), spanA: empty(), spanB: empty() }
88 }
89
90 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}
109
110const mask = (series, visible) => visible ? series : empty()
111
112const first = requestIchi(firstActive, firstTf)
113const second = requestIchi(secondActive, secondTf)
114const third = requestIchi(thirdActive, thirdTf)
115const fourth = requestIchi(fourthActive, fourthTf)
116
117const 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)
123
124 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) continue
130 cloudColors[i] = monoCloud ? bearishCloud : spanA[i] > spanB[i] ? bullishCloud : bearishCloud
131 }
132 }
133
134 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 })
140
141 if (!showLabels || !data.visible) return
142 let last = -1
143 for (let i = barCount - 1; i >= 0; i--) {
144 if (data.tenkan[i] !== null || data.kijun[i] !== null || data.spanA[i] !== null) {
145 last = i
146 break
147 }
148 }
149 if (last < 0) return
150 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}
167
168drawIchi('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)
172

Versions

  • 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.