tradingview / charting-library-tutorial

This tutorial explains step by step how to connect your data to the Charting Library
MIT License
434 stars 317 forks source link

Invalid Symbol #103

Open vnxz opened 1 year ago

vnxz commented 1 year ago

Can make own trading symbol using tradingview? I get invalid symbol when make own symbol,

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <div id="tvchart"></div>

    <!-- TradingView Widget BEGIN -->
<div class="tradingview-widget-container" style="height:100%;width:100%">
  <div id="tradingview_6ef43" style="height:calc(100% - 32px);width:100%"></div>

  <script type="text/javascript" src="https://s3.tradingview.com/tv.js"></script>
  <script src="index.js"></script>
</div>
</body>
</html>

js

function parseCSVData(data) {
  // Split the data into lines
  const lines = data.trim().split('\n');

  // Map each line to a bar object
  const bars = lines.map(line => {
    // Split the line into fields
    const fields = line.split(',');

    // Parse the fields into a bar object
    const bar = {
      time: new Date(fields[0] + ' ' + fields[1]).getTime(),
      open: parseFloat(fields[2]),
      high: parseFloat(fields[3]),
      low: parseFloat(fields[4]),
      close: parseFloat(fields[5]),
      volume: parseFloat(fields[6])
    };

    return bar;
  });

  return bars;
}

// Replace the sample CSV data below with your own CSV data
const csvData = `
1/25/2022, 10:50:00 AM,35964.4,35964.4,35908.52,35922.24,31.63878
1/25/2022, 10:51:00 AM,35922.23,35953.93,35908.65,35952.12,25.06247
1/25/2022, 10:52:00 AM,35949.49,35964.4,35945,35961.94,13.20111
1/25/2022, 10:53:00 AM,35961.86,35979.31,35897.84,35926.1,28.14962
1/25/2022, 10:54:00 AM,35929,35930.94,35881.37,35898.68,17.63856
1/25/2022, 10:55:00 AM,35898.84,35934.19,35848.94,35856.63,45.07581
1/25/2022, 10:56:00 AM,35858.13,35873,35829.21,35869.72,36.11276
1/25/2022, 10:57:00 AM,35869.72,35896.52,35865.3,35871.59,13.44813
1/25/2022, 10:58:00 AM,35871.59,35890.91,35865.98,35878.27,7.46477
1/25/2022, 10:59:00 AM,35878.27,35893.78,35857.31,35857.31,11.45737
1/25/2022, 11:00:00 AM,35857.32,35922.52,35828.56,35921.72,55.67646
1/25/2022, 11:01:00 AM,35921.72,35957.43,35912.64,35952.07,23.02352
1/25/2022, 11:02:00 AM,35951.6,35958.53,35876.42,35878.64,43.56076
`;

const parsedData = parseCSVData(csvData);

const tvWidget = new TradingView.widget({

  symbol : "EEC/USDT",
  interval : "D",
  timezone : "Etc/UTC",
  theme : "light",
  style : "1",
  locale : "en",
  enable_publishing : false,
  backgroundColor : "rgba(255, 255, 255, 1)",
  withdateranges : true,
  hide_side_toolbar : false,
  allow_symbol_change : true,
  details : true,
  hotlist : true,
  calendar: true,
  studies : [
    "STD;EMA"
  ],

  fullscreen : true,
  container : 'tvchart',
  datafeed  : {
    disable_quote_request: true,
    onReady: function (callback) {
      setTimeout(function () {
        callback({
          supported_resolutions: ['1D', '1W', '1M']
        });
      }, 0);
    },
    resolveSymbol: function(symbolName, onSymbolResolvedCallback, onResolveErrorCallback) {
      var symbolInfo = {
        name: 'EEC/USDT',
        ticker: 'EEC/USDT',
        description: 'EEC/USDT',
        type: 'crypto',
        session: '24x7',
        exchange: 'Your Exchange',
        listed_exchange: 'Your Exchange',
        timezone: 'Etc/UTC',
        pricescale: 100,
        minmov: 1,
        has_intraday: true,
        intraday_multipliers: ['1', '60'],
        supported_resolutions: ['1D', '1W', '1M'],
        volume_precision: 2,
        data_status: 'streaming',
      };

      if (symbolName == 'EEC/USDT') {
        onSymbolResolvedCallback(symbolInfo);
      } else {
        onResolveErrorCallback('Unknown symbol');
      }
    },
    getBars: function (symbolInfo, resolution, from, to, onHistoryCallback, onErrorCallback, firstDataRequest) {
      // Filter and return the parsed data within the specified date range
      const bars = parsedData.filter(bar => bar.time >= from && bar.time <= to);
      onHistoryCallback(bars, { noData: false });
    },
    subscribeBars: function (symbolInfo, resolution, onRealtimeCallback, subscriberUID, onResetCacheNeededCallback) {
      // You can implement real-time updates here if needed
    },
    unsubscribeBars: function (subscriberUID) {
      // Unsubscribe from real-time updates if implemented
    },
  },
});

Screenshot_5

what wrong?

vnxz commented 1 year ago

why no reply.is it legit?

romfrancois commented 1 year ago

Could you please enable debug: true in Widget Constructor and provide the full logs in a separate text file?

vnxz commented 1 year ago

Could you please enable debug: true in Widget Constructor and provide the full logs in a separate text file?

it show error ChartApi.AbstractSession:[cs_zbRlhweXwEUB] Critical error. Reason=invalid parameters, info=method: create_series. args: "[sds_1, s1, sds_sym_1, 1h, 300, ]". by this codes

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-eval' https://s3.tradingview.com; script-src-elem 'self' 'unsafe-eval' https://s3.tradingview.com;">
    <title>Document</title>
</head>
<body>
    <div id="tvchart"></div>

    <!-- TradingView Widget BEGIN -->
<div class="tradingview-widget-container" style="height:100%;width:100%">
  <div id="tradingview_6ef43" style="height:calc(100% - 32px);width:100%"></div>

  <script type="text/javascript" src="https://s3.tradingview.com/tv.js"></script>

  <script src="index.js"></script>
</div>
</body>
</html>

javascript code


function parseCSVData(csvData) {
  const lines = csvData.split('\n');
  const data = [];

  for (let i = 1; i < lines.length; i++) { // Start from 1 to skip the header
    const values = lines[i].split(',');

    const [date, time, open, high, low, close, volume] = values;

    const dateTime = new Date(`${date} ${time}`);

    data.push({
      time: dateTime.getTime(), // Use the timestamp instead of a Date object
      open: parseFloat(open),
      high: parseFloat(high),
      low: parseFloat(low),
      close: parseFloat(close),
      volume: parseFloat(volume),
    });
  }

  return data;
}

// // Replace the sample CSV data below with your own CSV data
const csvData = `
1/25/2022, 10:50:00 AM,35964.4,35964.4,35908.52,35922.24,31.63878
1/25/2022, 10:51:00 AM,35922.23,35953.93,35908.65,35952.12,25.06247
1/25/2022, 10:52:00 AM,35949.49,35964.4,35945,35961.94,13.20111
1/25/2022, 10:53:00 AM,35961.86,35979.31,35897.84,35926.1,28.14962
1/25/2022, 10:54:00 AM,35929,35930.94,35881.37,35898.68,17.63856
1/25/2022, 10:55:00 AM,35898.84,35934.19,35848.94,35856.63,45.07581
1/25/2022, 10:56:00 AM,35858.13,35873,35829.21,35869.72,36.11276
1/25/2022, 10:57:00 AM,35869.72,35896.52,35865.3,35871.59,13.44813
1/25/2022, 10:58:00 AM,35871.59,35890.91,35865.98,35878.27,7.46477
1/25/2022, 10:59:00 AM,35878.27,35893.78,35857.31,35857.31,11.45737
1/25/2022, 11:00:00 AM,35857.32,35922.52,35828.56,35921.72,55.67646
1/25/2022, 11:01:00 AM,35921.72,35957.43,35912.64,35952.07,23.02352
1/25/2022, 11:02:00 AM,35951.6,35958.53,35876.42,35878.64,43.56076
1/25/2022, 11:03:00 AM,35876.42,35920.02,35875.2,35916.6,10.09799
1/25/2022, 11:04:00 AM,35916.6,35921.87,35886.94,35899.94,8.74919
1/25/2022, 11:05:00 AM,35899.94,35939.22,35888.57,35933.03,8.83709
1/25/2022, 11:06:00 AM,35933.03,35934.83,35900,35903.41,9.96881
1/25/2022, 11:07:00 AM,35900.01,35939.06,35900,35909.53,5.33006
1/25/2022, 11:08:00 AM,35909.53,35944.3,35908.51,35942.5,8.56769
1/25/2022, 11:09:00 AM,35942.49,35972.77,35924.25,35927.79,8.66962
1/25/2022, 11:10:00 AM,35927.79,35996.56,35921.21,35985.68,14.21842
1/25/2022, 11:11:00 AM,35985.68,36018,35983.49,35998.88,11.86331
1/25/2022, 11:12:00 AM,35998.88,36025.53,35995,36013.85,11.14951
1/25/2022, 11:13:00 AM,36013.86,36029.99,36007.63,36014.93,26.2514
1/25/2022, 11:14:00 AM,36014.93,36021.92,35987.32,36021.91,11.2334
1/25/2022, 11:15:00 AM,36021.91,36028.7,36002.09,36007.7,7.51064
1/25/2022, 11:16:00 AM,36007.7,36059.24,36004.58,36054.32,28.7523
1/25/2022, 11:17:00 AM,36054.32,36059.24,35980,35982.29,10.04538
`;

const parsedData = parseCSVData(csvData);

const tvWidget = new TradingView.widget({

  widgetReady: () => {
    // Inside widgetReady

    // Inside widgetReady

    const chart = tvWidget.chart()

    chart.onChartReady(() => {

      // Now session_id will be available
      const sessionId = chart.session_id()

      console.log(sessionId)

      chart.create_series(
        sessionId,
        "s1",
        "EEC/USDT",
        "1h",
        300
      )

    })

  },

  symbol: 'EEC/USDT',
  interval: '1h',
  timezone: 'Etc/UTC',
  theme: 'light',
  style: '1',
  locale: 'en',
  enable_publishing: false,
  backgroundColor: 'rgba(255, 255, 255, 1)',
  withdateranges: true,
  hide_side_toolbar: false,
  allow_symbol_change: true, // Allowing symbol change
  debug: true,
  details: true,
  hotlist: true,
  fullscreen: true,
  container: 'tvchart',
 // library_path: '/charting_library.standalone.js',

  datafeed: {
    disable_quote_request: true,
    onReady: function (callback) {
      setTimeout(function () {
        callback({
          supported_resolutions: ['1h'], // Supporting only 1-hour resolution
        });
      }, 0);
    },
    resolveSymbol: function (symbolName, onSymbolResolvedCallback, onResolveErrorCallback) {
      var symbolInfo = {
        name: 'EEC/USDT',
        ticker: 'EEC/USDT',
        description: 'EEC/USDT',
        type: 'crypto',
        session: '24x7',
        exchange: 'Your Exchange',
        listed_exchange: 'Your Exchange',
        timezone: 'Etc/UTC',
        pricescale: 100,
        minmov: 1,
        has_intraday: true,
        intraday_multipliers: ['1', '60'],
        supported_resolutions: ['1h'], // Supporting only 1-hour resolution
        volume_precision: 2,
        data_status: 'streaming',
      };

      if (symbolName === 'EEC/USDT') {
        onSymbolResolvedCallback(symbolInfo);
      } else {
        onResolveErrorCallback('Unknown symbol');
      }
    },
    getBars: function (symbolInfo, resolution, from, to, onHistoryCallback, onErrorCallback, firstDataRequest) {
      const timeframeInMinutes = getMinutesFromResolution(resolution);
      const ohlcData = [];

      // Filter and return the parsed data within the specified date range
      parsedData.forEach(bar => {
        if (bar.time >= from && bar.time <= to) {
          ohlcData.push(bar);
        }
      });

      // Convert the OHLC data to the requested resolution
      const bars = convertToResolution(ohlcData, timeframeInMinutes);
      onHistoryCallback(bars, { noData: false });
    },

    subscribeBars: function (symbolInfo, resolution, onRealtimeCallback, subscriberUID, onResetCacheNeededCallback) {
      // You can implement real-time updates here if needed
    },
    unsubscribeBars: function (subscriberUID) {
      // Unsubscribe from real-time updates if implemented
    },
  },

});

is there any issue in data csv ??

Screenshot_6

romfrancois commented 1 year ago

Kind of hard to follow but your instantiation of the widget looks strange. Where did you get those additional parameters such as enable_publishing, with_date_ranges, etc. ? Also, widgetReady: () => {...} should not be part of Widget Constructor. I would encourage you to read the doc.