From e06b575e4677bb46b8bc71dee3ad9ff47a2ab4a7 Mon Sep 17 00:00:00 2001 From: olli Date: Mon, 15 Jul 2024 17:10:48 +0200 Subject: [PATCH] niver code --- data/charts.js | 649 +++++++++++++++++++++++++------------------------ 1 file changed, 328 insertions(+), 321 deletions(-) diff --git a/data/charts.js b/data/charts.js index 267bcf5..6f9b1ef 100644 --- a/data/charts.js +++ b/data/charts.js @@ -2,341 +2,348 @@ const urlParams = new URLSearchParams(window.location.search); const symbol = urlParams.get('symbol'); const time = urlParams.get('time'); -//window.dispatchEvent(new Event('resize')); - function timeToLocal(originalTime) { const d = new Date(originalTime * 1000); return Date.UTC(d.getFullYear(), d.getMonth(), d.getDate(), d.getHours(), d.getMinutes(), d.getSeconds(), d.getMilliseconds()) / 1000; } - function parseCSV(data) { - const rows = data.split("\n"); - const result = []; - let start = Math.max(rows.length - 298, 0); - let lastElements = rows.slice(start) - for (let i = start; i < rows.length; i++) { - const cols = rows[i].split(","); - if (cols.length >= 23 && cols.every(element => element !== undefined && element !== null)) { // check for existing lines - // parse the date so seconds since 1970 - cols[0] = Date.parse(cols[0])/1000,result.push(cols); - cols[0] = timeToLocal(cols[0]); - // coloring for MACD-Histogram - if (cols[20] < 0) { - cols[100] = "orange"; - if (cols[23] > 20) { - cols[100] = "red"; - } - } - else { - cols[100] = "lightgreen"; - if (cols[23] > 20) { - cols[100] = "green"; - } - } - } - else { - console.log("invalid line on linenr " + i + ": " +rows[i]); - } - } - return result; - } - - // Create the Lightweight Chart within the container element - const chart = LightweightCharts.createChart(document.getElementById('container'), - { - rightPriceScale: { - minimumWidth: 100, - borderVisible: false - }, - - height: 500, - crosshair: { - mode: 0, - }, - timeScale: { - timeVisible: true, - secondsVisible: false, - }, - layout: { - background: { - type: 'solid', - color: '#222', - }, - textColor: '#DDD', - }, - grid: { - vertLines: { color: '#444' }, - horzLines: { color: '#444' }, - }, - }); - - chart.applyOptions({ - watermark: { - visible: true, - fontSize: 18, - horzAlign: 'top', - vertAlign: 'left', - color: '#DDD', - text: symbol + " " + time, - }}); - - - // define chart - const candleSeries = chart.addCandlestickSeries(); - const lineSeriesEMA12 = chart.addLineSeries({ color: 'red', lineWidth: 1, priceLineVisible: false}); - const lineSeriesEMA26 = chart.addLineSeries({ color: 'pink', lineWidth: 1, lineStyle: 2, priceLineVisible: false}); - const lineSeriesEMA50 = chart.addLineSeries({ color: 'cyan', lineWidth: 1, priceLineVisible: false}); - const lineSeriesEMA100 = chart.addLineSeries({ color: 'yellow', lineWidth: 1, priceLineVisible: false}); - const lineSeriesEMA200 = chart.addLineSeries({ color: 'white', lineWidth: 1, priceLineVisible: false}); - const lineSeriesEMA400 = chart.addLineSeries({ color: 'orange', lineWidth: 1, priceLineVisible: false}); - const lineSeriesEMA800 = chart.addLineSeries({ color: 'purple', lineWidth: 1, priceLineVisible: false}); - - - // RSI Chart - const chartrsi = LightweightCharts.createChart(document.getElementById("container"), - { - rightPriceScale: { - minimumWidth: 100, - borderVisible: false - }, - height: 200, - timeScale: { - visible: false, - }, - layout: { - background: { - type: 'solid', - color: '#222', - }, - textColor: '#DDD', - }, - grid: { - vertLines: { color: '#444' }, - horzLines: { color: '#444' }, - }, - }); - - chartrsi.applyOptions({ - watermark: { - visible: true, - fontSize: 18, - horzAlign: 'top', - vertAlign: 'left', - color: '#DDD', - text: 'RSI 5,14,21', - }}); - - const lineSeriesRSI5 = chartrsi.addLineSeries({ color: 'orange', lineWidth: 1, lineStyle: 2, priceLineVisible: false}); - const lineSeriesRSI14 = chartrsi.addLineSeries({ color: 'yellow', lineWidth: 2, priceLineVisible: false}); - const lineSeriesRSI21 = chartrsi.addLineSeries({ color: 'lightgreen', lineWidth: 1, lineStyle: 2, priceLineVisible: false}); - - // MACD Chart - const chartmacd = LightweightCharts.createChart(document.getElementById("container"), - { - rightPriceScale: { - minimumWidth: 100, - borderVisible: false - }, - - height: 200, - timeScale: { - timeVisible: true, - secondsVisible: false, - }, - layout: { - background: { - type: 'solid', - color: '#222', - }, - textColor: '#DDD', - }, - grid: { - vertLines: { color: '#444' }, - horzLines: { color: '#444' }, - }, - }); - - chartmacd.applyOptions({ - watermark: { - visible: true, - fontSize: 18, - horzAlign: 'top', - vertAlign: 'left', - color: '#DDD', - text: 'MACD 12 26', - }}); - - const lineSeriesMACD = chartmacd.addLineSeries({ color: 'blue', lineWidth: 1, lineStyle: 0, priceLineVisible: false}); - const lineSeriesMACDSignal = chartmacd.addLineSeries({ color: 'orange', lineWidth: 1, lineStyle: 0, priceLineVisible: false}); - const histogramSeriesMACD = chartmacd.addHistogramSeries({ - priceFormat: { - type: 'volume', - color: 'orange', - }, - //priceScaleId: '', // set as an overlay by setting a blank priceScaleId - }); - - - - fetch("/botdata/asset-histories/" + symbol + ".history." + time + ".csv") - .then(response => response.text()) - .then(data => { - const parsedData = parseCSV(data); - - // OHLC Data - const bars = parsedData.map(item => ({ - time: item[0], - open: item[1], - high: item[2], - low: item[3], - close: item[4] - })); - candleSeries.setData(bars); - - // EMA Data - candleSeries.setData(bars); - const lineSeriesEMA12Data = parsedData.map(item => ({ - time: item[0], - value: item[8] - })); - lineSeriesEMA12.setData(lineSeriesEMA12Data); - - const lineSeriesEMA26Data = parsedData.map(item => ({ - time: item[0], - value: item[9] - })); - lineSeriesEMA26.setData(lineSeriesEMA26Data); - - const lineSeriesEMA50Data = parsedData.map(item => ({ - time: item[0], - value: item[10] - })); - lineSeriesEMA50.setData(lineSeriesEMA50Data); - - const lineSeriesEMA100Data = parsedData.map(item => ({ - time: item[0], - value: item[11] - })); - lineSeriesEMA100.setData(lineSeriesEMA100Data); - - const lineSeriesEMA200Data = parsedData.map(item => ({ - time: item[0], - value: item[12] - })); - lineSeriesEMA200.setData(lineSeriesEMA200Data); - - const lineSeriesEMA400Data = parsedData.map(item => ({ - time: item[0], - value: item[13] - })); - lineSeriesEMA400.setData(lineSeriesEMA400Data); - - const lineSeriesEMA800Data = parsedData.map(item => ({ - time: item[0], - value: item[14] - })); - lineSeriesEMA800.setData(lineSeriesEMA800Data); - - // RSI Data - const lineSeriesRSI5Data = parsedData.map(item => ({ - time: item[0], - value: item[15] - })); - lineSeriesRSI5.setData(lineSeriesRSI5Data); - - const lineSeriesRSI14Data = parsedData.map(item => ({ - time: item[0], - value: item[16] - })); - lineSeriesRSI14.setData(lineSeriesRSI14Data); - - const lineSeriesRSI21Data = parsedData.map(item => ({ - time: item[0], - value: item[17] - })); - lineSeriesRSI21.setData(lineSeriesRSI21Data); - - // MACD Data - const lineSeriesMACDData = parsedData.map(item => ({ - time: item[0], - value: item[18] - })); - lineSeriesMACD.setData(lineSeriesMACDData); - - const lineSeriesMACDSignalData = parsedData.map(item => ({ - time: item[0], - value: item[19] - })); - lineSeriesMACDSignal.setData(lineSeriesMACDSignalData); - - const histogramSeriesMACDData = parsedData.map(item => ({ - time: item[0], - value: item[20], - color: item[100] - })); - histogramSeriesMACD.setData(histogramSeriesMACDData); - }); - - - // Lines for price levels - fetch("/botdata/asset-histories/" + symbol + ".history.csv.levels") - .then(response => response.text()) - .then(text => { - const levels = text.split('\n'); - levels.forEach(function(level) { - candleSeries.createPriceLine({price: level, color: "darkblue", lineWidth: 0.5, lineStyle: 0, axisLabelVisible: true, title: 'Level'}); - }); - }); - - - // Sync charts timeScale - chart.timeScale().fitContent(); - chart.timeScale().subscribeVisibleLogicalRangeChange(timeRange => { - chartrsi.timeScale().setVisibleLogicalRange(timeRange); - chartmacd.timeScale().setVisibleLogicalRange(timeRange); - }); - - chartrsi.timeScale().subscribeVisibleLogicalRangeChange(timeRange => { - chart.timeScale().setVisibleLogicalRange(timeRange); - }); - - chartmacd.timeScale().subscribeVisibleLogicalRangeChange(timeRange => { - chart.timeScale().setVisibleLogicalRange(timeRange); - }); - +function parseCSV(data) { + const rows = data.split("\n"); + const result = []; + let start = Math.max(rows.length - 298, 0); + let lastElements = rows.slice(start) + for (let i = start; i < rows.length; i++) { + const cols = rows[i].split(","); + if (cols.length >= 23 && cols.every(element => element !== undefined && element !== null)) { // check for existing lines + // parse the date so seconds since 1970 + cols[0] = Date.parse(cols[0])/1000,result.push(cols); + cols[0] = timeToLocal(cols[0]); + // coloring for MACD-Histogram + if (cols[20] < 0) { + cols[100] = "orange"; + if (cols[23] > 20) { + cols[100] = "red"; + } + } + else { + cols[100] = "lightgreen"; + if (cols[23] > 20) { + cols[100] = "green"; + } + } + } + else { + console.log("invalid line on linenr " + i + ": " +rows[i]); + } + } + return result; +} function getCrosshairDataPoint(series, param) { - if (!param.time) { - return null; - } - const dataPoint = param.seriesData.get(series); - return dataPoint || null; + if (!param.time) { + return null; + } + const dataPoint = param.seriesData.get(series); + return dataPoint || null; } function syncCrosshair(chart, series, dataPoint) { - if (dataPoint) { - chart.setCrosshairPosition(dataPoint.value, dataPoint.time, series); - return; - } - chart.clearCrosshairPosition(); + if (dataPoint) { + chart.setCrosshairPosition(dataPoint.value, dataPoint.time, series); + return; + } + chart.clearCrosshairPosition(); } + +// Create the Lightweight Chart within the container element +const chart = LightweightCharts.createChart(document.getElementById('container'), +{ + rightPriceScale: { + minimumWidth: 100, + borderVisible: false + }, + + height: 500, + + crosshair: { + mode: 0, + }, + + timeScale: { + timeVisible: true, + secondsVisible: false, + }, + + layout: { + background: { + type: 'solid', + color: '#222', + }, + textColor: '#DDD', + }, + + grid: { + vertLines: { color: '#444' }, + horzLines: { color: '#444' }, + }, + +}); + +chart.applyOptions({ + watermark: { + visible: true, + fontSize: 18, + horzAlign: 'top', + vertAlign: 'left', + color: '#DDD', + text: symbol + " " + time, + } +}); + +// define chart +const candleSeries = chart.addCandlestickSeries(); +const lineSeriesEMA12 = chart.addLineSeries({ color: 'red', lineWidth: 1, priceLineVisible: false}); +const lineSeriesEMA26 = chart.addLineSeries({ color: 'pink', lineWidth: 1, lineStyle: 2, priceLineVisible: false}); +const lineSeriesEMA50 = chart.addLineSeries({ color: 'cyan', lineWidth: 1, priceLineVisible: false}); +const lineSeriesEMA100 = chart.addLineSeries({ color: 'yellow', lineWidth: 1, priceLineVisible: false}); +const lineSeriesEMA200 = chart.addLineSeries({ color: 'white', lineWidth: 1, priceLineVisible: false}); +const lineSeriesEMA400 = chart.addLineSeries({ color: 'orange', lineWidth: 1, priceLineVisible: false}); +const lineSeriesEMA800 = chart.addLineSeries({ color: 'purple', lineWidth: 1, priceLineVisible: false}); + + +// RSI Chart +const chartrsi = LightweightCharts.createChart(document.getElementById("container"), +{ + rightPriceScale: { + minimumWidth: 100, + borderVisible: false + }, + height: 200, + + timeScale: { + visible: false, + }, + + layout: { + background: { + type: 'solid', + color: '#222', + }, + textColor: '#DDD', + }, + + grid: { + vertLines: { color: '#444' }, + horzLines: { color: '#444' }, + }, +}); + +chartrsi.applyOptions({ + watermark: { + visible: true, + fontSize: 18, + horzAlign: 'top', + vertAlign: 'left', + color: '#DDD', + text: 'RSI 5,14,21', + } +}); + +const lineSeriesRSI5 = chartrsi.addLineSeries({ color: 'orange', lineWidth: 1, lineStyle: 2, priceLineVisible: false}); +const lineSeriesRSI14 = chartrsi.addLineSeries({ color: 'yellow', lineWidth: 2, priceLineVisible: false}); +const lineSeriesRSI21 = chartrsi.addLineSeries({ color: 'lightgreen', lineWidth: 1, lineStyle: 2, priceLineVisible: false}); + +// MACD Chart +const chartmacd = LightweightCharts.createChart(document.getElementById("container"), +{ + rightPriceScale: { + minimumWidth: 100, + borderVisible: false + }, + + height: 200, + + timeScale: { + timeVisible: true, + secondsVisible: false, + }, + + layout: { + background: { + type: 'solid', + color: '#222', + }, + textColor: '#DDD', + }, + + grid: { + vertLines: { color: '#444' }, + horzLines: { color: '#444' }, + }, +}); + +chartmacd.applyOptions({ + watermark: { + visible: true, + fontSize: 18, + horzAlign: 'top', + vertAlign: 'left', + color: '#DDD', + text: 'MACD 12 26', + } +}); + +const lineSeriesMACD = chartmacd.addLineSeries({ color: 'blue', lineWidth: 1, lineStyle: 0, priceLineVisible: false}); +const lineSeriesMACDSignal = chartmacd.addLineSeries({ color: 'orange', lineWidth: 1, lineStyle: 0, priceLineVisible: false}); +const histogramSeriesMACD = chartmacd.addHistogramSeries({ + priceFormat: { + type: 'volume', + color: 'orange', + }, +}); + + +fetch("/botdata/asset-histories/" + symbol + ".history." + time + ".csv") +.then(response => response.text()) +.then(data => { + const parsedData = parseCSV(data); + + // OHLC Data + const bars = parsedData.map(item => ({ + time: item[0], + open: item[1], + high: item[2], + low: item[3], + close: item[4] + })); + candleSeries.setData(bars); + + // EMA Data + candleSeries.setData(bars); + const lineSeriesEMA12Data = parsedData.map(item => ({ + time: item[0], + value: item[8] + })); + lineSeriesEMA12.setData(lineSeriesEMA12Data); + + const lineSeriesEMA26Data = parsedData.map(item => ({ + time: item[0], + value: item[9] + })); + lineSeriesEMA26.setData(lineSeriesEMA26Data); + + const lineSeriesEMA50Data = parsedData.map(item => ({ + time: item[0], + value: item[10] + })); + lineSeriesEMA50.setData(lineSeriesEMA50Data); + + const lineSeriesEMA100Data = parsedData.map(item => ({ + time: item[0], + value: item[11] + })); + lineSeriesEMA100.setData(lineSeriesEMA100Data); + + const lineSeriesEMA200Data = parsedData.map(item => ({ + time: item[0], + value: item[12] + })); + lineSeriesEMA200.setData(lineSeriesEMA200Data); + + const lineSeriesEMA400Data = parsedData.map(item => ({ + time: item[0], + value: item[13] + })); + lineSeriesEMA400.setData(lineSeriesEMA400Data); + + const lineSeriesEMA800Data = parsedData.map(item => ({ + time: item[0], + value: item[14] + })); + lineSeriesEMA800.setData(lineSeriesEMA800Data); + + // RSI Data + const lineSeriesRSI5Data = parsedData.map(item => ({ + time: item[0], + value: item[15] + })); + lineSeriesRSI5.setData(lineSeriesRSI5Data); + + const lineSeriesRSI14Data = parsedData.map(item => ({ + time: item[0], + value: item[16] + })); + lineSeriesRSI14.setData(lineSeriesRSI14Data); + + const lineSeriesRSI21Data = parsedData.map(item => ({ + time: item[0], + value: item[17] + })); + lineSeriesRSI21.setData(lineSeriesRSI21Data); + + // MACD Data + const lineSeriesMACDData = parsedData.map(item => ({ + time: item[0], + value: item[18] + })); + lineSeriesMACD.setData(lineSeriesMACDData); + + const lineSeriesMACDSignalData = parsedData.map(item => ({ + time: item[0], + value: item[19] + })); + lineSeriesMACDSignal.setData(lineSeriesMACDSignalData); + + const histogramSeriesMACDData = parsedData.map(item => ({ + time: item[0], + value: item[20], + color: item[100] + })); + histogramSeriesMACD.setData(histogramSeriesMACDData); +}); + + +// Lines for price levels +fetch("/botdata/asset-histories/" + symbol + ".history.csv.levels") +.then(response => response.text()) +.then(text => { + const levels = text.split('\n'); + levels.forEach(function(level) { + candleSeries.createPriceLine({price: level, color: "darkblue", lineWidth: 0.5, lineStyle: 0, axisLabelVisible: true, title: 'Level'}); + }); +}); + + +// Sync charts timeScale +chart.timeScale().fitContent(); +chart.timeScale().subscribeVisibleLogicalRangeChange(timeRange => { + chartrsi.timeScale().setVisibleLogicalRange(timeRange); + chartmacd.timeScale().setVisibleLogicalRange(timeRange); +}); + +chartrsi.timeScale().subscribeVisibleLogicalRangeChange(timeRange => { + chart.timeScale().setVisibleLogicalRange(timeRange); +}); + +chartmacd.timeScale().subscribeVisibleLogicalRangeChange(timeRange => { + chart.timeScale().setVisibleLogicalRange(timeRange); +}); + chart.subscribeCrosshairMove(param => { - const dataPoint = getCrosshairDataPoint(lineSeriesEMA50, param); - syncCrosshair(chartrsi, lineSeriesRSI14, dataPoint); - const dataPointmacd = getCrosshairDataPoint(lineSeriesEMA50, param); - syncCrosshair(chartmacd, lineSeriesMACD, dataPointmacd); + const dataPoint = getCrosshairDataPoint(lineSeriesEMA50, param); + syncCrosshair(chartrsi, lineSeriesRSI14, dataPoint); + const dataPointmacd = getCrosshairDataPoint(lineSeriesEMA50, param); + syncCrosshair(chartmacd, lineSeriesMACD, dataPointmacd); }); chartrsi.subscribeCrosshairMove(param => { - const dataPoint = getCrosshairDataPoint(lineSeriesRSI14, param); - syncCrosshair(chart, lineSeriesEMA50, dataPoint); - const dataPointmacd = getCrosshairDataPoint(lineSeriesRSI14, param); - syncCrosshair(chartmacd, lineSeriesMACD, dataPointmacd); - + const dataPoint = getCrosshairDataPoint(lineSeriesRSI14, param); + syncCrosshair(chart, lineSeriesEMA50, dataPoint); + const dataPointmacd = getCrosshairDataPoint(lineSeriesRSI14, param); + syncCrosshair(chartmacd, lineSeriesMACD, dataPointmacd); }); chartmacd.subscribeCrosshairMove(param => { - const dataPoint = getCrosshairDataPoint(lineSeriesMACD, param); - syncCrosshair(chart, lineSeriesEMA50, dataPoint); - const dataPointrsi = getCrosshairDataPoint(lineSeriesMACD, param); - syncCrosshair(chartrsi, lineSeriesRSI14, dataPointrsi); + const dataPoint = getCrosshairDataPoint(lineSeriesMACD, param); + syncCrosshair(chart, lineSeriesEMA50, dataPoint); + const dataPointrsi = getCrosshairDataPoint(lineSeriesMACD, param); + syncCrosshair(chartrsi, lineSeriesRSI14, dataPointrsi); }); -