PageSourceSearch

https://walnutlens.com/js/chart.js?v=5

js walnutlens.com collected 2026-10-02 01:48:09 UTC 12,586 bytes, 351 lines download raw bytes

1/* chart.js — Animated TradingView-style chart mock with live-feel candles + overlays.
2   All drawn to <canvas>; overlay toggles come in via props. */
3
4var h = React.createElement;
5
6function mulberry32(a) {
7  return function() {
8    var t = a += 0x6D2B79F5;
9    t = Math.imul(t ^ t >>> 15, t | 1);
10    t ^= t + Math.imul(t ^ t >>> 7, t | 61);
11    return ((t ^ t >>> 14) >>> 0) / 4294967296;
12  };
13}
14
15function generateCandles(n, seed, startPrice, vol) {
16  vol = vol || 8;
17  var rand = mulberry32(seed);
18  var candles = [];
19  var price = startPrice;
20  for (var i = 0; i < n; i++) {
21    var drift = (rand() - 0.5) * vol * 0.4;
22    var trend = Math.sin(i / 12) * 2 + Math.sin(i / 31) * 4;
23    var o = price;
24    var c = o + drift + trend * 0.3;
25    var spread = vol * (0.3 + rand() * 0.7);
26    var hh = Math.max(o, c) + rand() * spread;
27    var ll = Math.min(o, c) - rand() * spread;
28    var v = 0.2 + rand() * 0.8;
29    candles.push({ o: o, h: hh, l: ll, c: c, v: v });
30    price = c;
31  }
32  return candles;
33}
34
35function ChartMock(props) {
36  var overlays = props.overlays;
37  var height = props.height || 520;
38  var seed = props.seed || 7;
39  var candleCount = props.candleCount || 90;
40
41  var canvasRef = React.useRef(null);
42  var tickRef = React.useRef(0);
43
44  React.useEffect(function() {
45    var raf;
46    var last = performance.now();
47    var loop = function(t) {
48      if (t - last > 45) {
49        tickRef.current += 1;
50        last = t;
51        drawChart();
52      }
53      raf = requestAnimationFrame(loop);
54    };
55    raf = requestAnimationFrame(loop);
56    return function() { cancelAnimationFrame(raf); };
57  }, [overlays]);
58
59  // Redraw when overlays change
60  React.useEffect(function() {
61    drawChart();
62  }, [overlays]);
63
64  function drawChart() {
65    var canvas = canvasRef.current;
66    if (!canvas) return;
67    var tick = tickRef.current;
68    var dpr = Math.min(window.devicePixelRatio || 1, 2);
69    var parent = canvas.parentElement;
70    var cssW = parent.clientWidth;
71    var cssH = height;
72    canvas.width = cssW * dpr;
73    canvas.height = cssH * dpr;
74    canvas.style.width = cssW + 'px';
75    canvas.style.height = cssH + 'px';
76    var ctx = canvas.getContext('2d');
77    ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
78    draw(ctx, cssW, cssH, tick);
79  }
80
81  function draw(ctx, W, H, t) {
82    ctx.clearRect(0, 0, W, H);
83    ctx.fillStyle = '#08090d';
84    ctx.fillRect(0, 0, W, H);
85
86    var padL = 10;
87    var padR = 90;
88    var padT = 30;
89    var padB = 40;
90    var plotW = W - padL - padR;
91    var plotH = H - padT - padB;
92
93    var baseCandles = generateCandles(candleCount, seed, 7140, 9);
94    var lastIdx = baseCandles.length - 1;
95    var lc = baseCandles[lastIdx];
96    var animOsc = Math.sin(t / 8) * 4 + Math.sin(t / 3) * 1.2;
97    var animatedLast = {
98      o: lc.o, v: lc.v,
99      c: lc.c + animOsc,
100      h: Math.max(lc.h, lc.c + animOsc + 1.5),
101      l: Math.min(lc.l, lc.c + animOsc - 1.5),
102    };
103    var candles = baseCandles.slice(0, lastIdx).concat([animatedLast]);
104
105    var minP = Infinity, maxP = -Infinity;
106    for (var ci = 0; ci < candles.length; ci++) {
107      if (candles[ci].l < minP) minP = candles[ci].l;
108      if (candles[ci].h > maxP) maxP = candles[ci].h;
109    }
110    var pad = (maxP - minP) * 0.08;
111    minP -= pad;
112    maxP += pad;
113
114    var priceToY = function(p) { return padT + (1 - (p - minP) / (maxP - minP)) * plotH; };
115    var iToX = function(i) { return padL + (i + 0.5) * (plotW / candles.length); };
116    var cW = (plotW / candles.length) * 0.72;
117
118    // Grid
119    ctx.strokeStyle = 'rgba(120, 130, 150, 0.06)';
120    ctx.setLineDash([1, 4]);
121    ctx.lineWidth = 1;
122    var g;
123    for (g = 0; g <= 8; g++) {
124      var gy = padT + (g / 8) * plotH;
125      ctx.beginPath();
125 ctx.moveTo(padL, gy); ctx.lineTo(padL + plotW, gy); ctx.stroke();
126    }
127    for (g = 0; g <= 10; g++) {
128      var gx = padL + (g / 10) * plotW;
129      ctx.beginPath(); ctx.moveTo(gx, padT); ctx.lineTo(gx, padT + plotH); ctx.stroke();
130    }
131    ctx.setLineDash([]);
132
133    // GEX zone shading
134    if (overlays.gexZones) {
135      var zPut1 = priceToY(minP + (maxP - minP) * 0.12);
136      var zPut2 = priceToY(minP + (maxP - minP) * 0.28);
137      var gradPut = ctx.createLinearGradient(0, zPut2, 0, zPut1);
138      gradPut.addColorStop(0, 'rgba(255, 60, 170, 0.22)');
139      gradPut.addColorStop(1, 'rgba(255, 60, 170, 0.04)');
140      ctx.fillStyle = gradPut;
141      ctx.fillRect(padL, zPut2, plotW, zPut1 - zPut2);
142
143      var zNeu1 = priceToY(minP + (maxP - minP) * 0.42);
144      var zNeu2 = priceToY(minP + (maxP - minP) * 0.58);
145      ctx.fillStyle = 'rgba(255, 200, 50, 0.05)';
146      ctx.fillRect(padL, zNeu2, plotW, zNeu1 - zNeu2);
147
148      var zCall1 = priceToY(minP + (maxP - minP) * 0.72);
149      var zCall2 = priceToY(minP + (maxP - minP) * 0.88);
150      var gradCall = ctx.createLinearGradient(0, zCall2, 0, zCall1);
151      gradCall.addColorStop(0, 'rgba(70, 220, 255, 0.04)');
152      gradCall.addColorStop(1, 'rgba(70, 220, 255, 0.18)');
153      ctx.fillStyle = gradCall;
154      ctx.fillRect(padL, zCall2, plotW, zCall1 - zCall2);
155    }
156
157    // Gamma depth bars
158    if (overlays.gammaDepth) {
159      var gdRand = mulberry32(seed + 3);
160      var bars = 26;
161      var barH = plotH / bars;
162      var maxBarW = padR - 12;
163      for (var b = 0; b < bars; b++) {
164        var by = padT + b * barH;
165        var norm = b / bars;
166        var isCall = norm < 0.5;
167        var mag = Math.abs(gdRand() - 0.5) * 2;
168        var shape = Math.exp(-Math.pow((norm - 0.25) * 6, 2)) * 0.5 +
169                    Math.exp(-Math.pow((norm - 0.78) * 6, 2)) * 0.7;
170        var bw = (mag * 0.3 + shape) * maxBarW * 0.9;
171        ctx.fillStyle = isCall ? 'rgba(70, 220, 255, 0.7)' : 'rgba(255, 60, 170, 0.7)';
172        ctx.fillRect(W - padR + 6, by + 1, bw, barH - 2);
173      }
174      ctx.fillStyle = 'rgba(200,210,230,0.35)';
175      ctx.font = '9px ui-monospace, Menlo, monospace';
176      ctx.textAlign = 'right';
177      ctx.fillText('GAMMA DEPTH', W - 8, H - 8);
178    }
179
180    // Levels
181    var levelDefs = [];
182    if (overlays.sr) {
183      levelDefs.push({ price: minP + (maxP - minP) * 0.58, color: '#4db6ff', label: 'S/R 7,184', weight: 2.5, dash: [] });
184      levelDefs.push({ price: minP + (maxP - minP) * 0.32, color: '#4db6ff', label: 'S/R 7,141', weight: 2, dash: [] });
185    }
186    if (overlays.hvn) {
187      levelDefs.push({ price: minP + (maxP - minP) * 0.86, color: '#ffb84d', label: 'HVN 7,210', weight: 2, dash: [] });
188      levelDefs.push({ price: minP + (maxP - minP) * 0.18, color: '#ffb84d', label: 'HVN 7,118', weight: 2, dash: [] });
189    }
190    if (overlays.lvn) {
191      levelDefs.push({ price: minP + (maxP - minP) * 0.45, color: '#28f07c', label: 'LVN 7,156', weight: 1.5, dash: [4, 4] });
192    }
193    if (overlays.pivots) {
194      levelDefs.push({ price: minP + (maxP - minP) * 0.74, color: '#ff3caa', label: 'PIVOT', weight: 1.5, dash: [2, 6] });
195    }
196
197    for (var li = 0; li < levelDefs.length; li++) {
198      var lv = levelDefs[li];
199      var ly = priceToY(lv.price);
200      ctx.strokeStyle = lv.color;
201      ctx.lineWidth = lv.weight;
202      ctx.setLineDash(lv.dash);
203      ctx.beginPath();
204      ctx.moveTo(padL, ly);
205      ctx.lineTo(padL + plotW, ly);
206      ctx.stroke();
207      ctx.setLineDash([]);
208      ctx.font = '10px ui-monospace, Menlo, monospace';
209      var lw = ctx.measureText(lv.label).width + 10;
210      ctx.fillStyle = 'rgba(0,0,0,0.7)';
211      ctx.fillRect(padL + 6, ly - 7, lw, 14);
212      ctx.fillStyle = lv.color;
213      ctx.textAlign = 'left';
214      ctx.fillText(lv.label, padL + 11, ly + 3);
215    }
216    ctx.setLineDash([]);
217
218    // Blocks
219    if (overlays.blocks) {
220      var blocks = [
221        { x0: 0.10, x1: 0.55, y: 0.82, bh: 0.035 },
222        { x0: 0.04, x1: 0.40, y: 0.65, bh: 0.030 },
223        { x0: 0.35, x1: 0.78, y: 0.50, bh: 0.030 },
224        { x0: 0.15, x1: 0.38, y: 0.22, bh: 0.025 },
225      ];
226      for (var bi = 0; bi < blocks.length; bi++) {
227        var bl = blocks[bi];
228        var bx = padL + bl.x0 * plotW;
229        var bbw = (bl.x1 - bl.x0) * plotW;
230        var bby = priceToY(minP + (1 - bl.y) * (maxP - minP));
231        var bbh = bl.bh * plotH;
232        ctx.fillStyle = 'rgba(196, 140, 80, 0.35)';
233        ctx.fillRect(bx, bby - bbh / 2, bbw, bbh);
234        ctx.strokeStyle = 'rgba(230, 170, 100, 0.9)';
235        ctx.lineWidth = 1;
236        ctx.strokeRect(bx, bby - bbh / 2, bbw, bbh);
237      }
238    }
239
240    // Candles
241    for (var i = 0; i < candles.length; i++) {
242      var cd = candles[i];
243      var x = iToX(i);
244      var up = cd.c >= cd.o;
245      var col = up ? '#2de8b2' : '#ff3caa';
246      ctx.strokeStyle = col;
247      ctx.lineWidth = 1;
248      ctx.beginPath();
249      ctx.moveTo(x, priceToY(cd.h));
250      ctx.lineTo(x, priceToY(cd.l));
251      ctx.stroke();
252      var yO = priceToY(cd.o);
253      var yC = priceToY(cd.c);
254      var cby = Math.min(yO, yC);
255      var cbh = Math.max(1, Math.abs(yC - yO));
256      ctx.fillStyle = col;
257      ctx.fillRect(x - cW / 2, cby, cW, cbh);
258    }
259
260    // News pin
261    if (overlays.news) {
262      var pinI = Math.floor(candles.length * 0.72);
263      var px = iToX(pinI);
264      var py = priceToY(candles[pinI].h) - 14;
265      var pulse = 0.5 + 0.5 * Math.sin(t / 6);
266      ctx.fillStyle = 'rgba(255, 200, 50, ' + (0.6 + pulse * 0.4) + ')';
267      ctx.beginPath();
268      ctx.arc(px, py, 4 + pulse * 2, 0, Math.PI * 2);
269      ctx.fill();
270      ctx.strokeStyle = 'rgba(255, 200, 50, 0.4)';
271      ctx.beginPath();
272      ctx.arc(px, py, 8 + pulse * 4, 0, Math.PI * 2);
273      ctx.stroke();
274      ctx.strokeStyle = 'rgba(255, 200, 50, 0.8)';
275      ctx.setLineDash([2, 3]);
276      ctx.beginPath(); ctx.moveTo(px, py - 4); ctx.lineTo(px, padT + 10); ctx.stroke();
277      ctx.setLineDash([]);
278      ctx.fillStyle = 'rgba(255, 200, 50, 0.15)';
279      ctx.fillRect(px - 60, padT + 4, 120, 16);
280      ctx.fillStyle = '#ffd466';
281      ctx.font = '10px ui-monospace, Menlo, monospace';
282      ctx.textAlign = 'center';
283      ctx.fillText('CPI HOT \u00b7 +0.4% MoM', px, padT + 15);
284    }
285
286    // Expected move bands
287    if (overlays.emBands) {
288      var midY = priceToY(minP + (maxP - minP) * 0.55);
289      var bandWidth = plotH * 0.18;
290      ctx.strokeStyle = 'rgba(255, 200, 50, 0.55)';
291      ctx.setLineDash([5, 4]);
292      ctx.lineWidth = 1;
293      ctx.beginPath();
293 ctx.moveTo(padL, midY - bandWidth); ctx.lineTo(padL + plotW, midY - bandWidth); ctx.stroke();
294      ctx.beginPath(); ctx.moveTo(padL, midY + bandWidth); ctx.lineTo(padL + plotW, midY + bandWidth); ctx.stroke();
295      ctx.setLineDash([]);
296    }
297
298    // Last price tag
299    var lastPrice = candles[candles.length - 1].c;
300    var lastY = priceToY(lastPrice);
301    ctx.fillStyle = animOsc >= 0 ? 'rgba(45, 232, 178, 0.95)' : 'rgba(255, 60, 170, 0.95)';
302    ctx.fillRect(W - padR, lastY - 9, padR - 2, 18);
303    ctx.fillStyle = '#04060a';
304    ctx.font = 'bold 11px ui-monospace, Menlo, monospace';
305    ctx.textAlign = 'left';
306    ctx.fillText(lastPrice.toFixed(2), W - padR + 6, lastY + 3);
307    ctx.strokeStyle = animOsc >= 0 ? 'rgba(45, 232, 178, 0.35)' : 'rgba(255, 60, 170, 0.35)';
308    ctx.setLineDash([3, 3]);
309    ctx.beginPath(); ctx.moveTo(padL, lastY); ctx.lineTo(W - padR, lastY); ctx.stroke();
310    ctx.setLineDash([]);
311
312    // Price axis
313    ctx.fillStyle = 'rgba(180,190,210,0.45)';
314    ctx.font = '10px ui-monospace, Menlo, monospace';
315    ctx.textAlign = 'left';
316    for (g = 0; g <= 8; g++) {
317      var ay = padT + (g / 8) * plotH;
318      var ap = maxP - (g / 8) * (maxP - minP);
319      if (Math.abs(ay - lastY) > 14) {
320        ctx.fillText(ap.toFixed(0), W - padR + 6, ay + 3);
321      }
322    }
323
324    // Time axis
325    ctx.fillStyle = 'rgba(180,190,210,0.35)';
326    ctx.textAlign = 'center';
327    ctx.font = '10px ui-monospace, Menlo, monospace';
328    var times = ['09:30', '10:30', '11:30', '12:30', '13:30', '14:30'];
329    for (var ti = 0; ti < times.length; ti++) {
330      var tx = padL + (ti / (times.length - 1)) * plotW;
331      ctx.fillText(times[ti], tx, H - 14);
332    }
333
334    // Top bar
335    ctx.fillStyle = 'rgba(200,210,230,0.65)';
336    ctx.textAlign = 'left';
337    ctx.font = 'bold 11px ui-monospace, Menlo, monospace';
338    ctx.fillText('NQ1!', padL + 4, 18);
339    ctx.fillStyle = 'rgba(140,150,170,0.7)';
340    ctx.font = '10px ui-monospace, Menlo, monospace';
341    ctx.fillText('\u00b7 5m \u00b7 CME', padL + 34, 18);
342    ctx.fillStyle = animOsc >= 0 ? 'rgba(45, 232, 178, 0.95)' : 'rgba(255, 60, 170, 0.95)';
343    ctx.fillText(lastPrice.toFixed(2) + ' ' + (animOsc >= 0 ? '+' : '') + animOsc.toFixed(2), padL + 100, 18);
344  }
345
346  return h('div', { style: { position: 'relative', width: '100%' } },
347    h('canvas', { ref: canvasRef, style: { display: 'block', borderRadius: 12 } })
348  );
349}
350
351window.ChartMock = ChartMock;

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.