TradingView 圖表

圖表串接

使用 React 進行圖表串接。

範例:

import { useEffect, useRef } from "react";
import { createChart } from "lightweight-charts";

// 範例資料
// priceHistoryData:
// [{
//   TIMESTAMP: "2021-11-30 09:59:00.000"
//   price: 2322
// }]

// swapHistoryData:
// [{
//   act:  "B",
//   block_time: "2022-08-26 07:03:32.000"
// }, ...]


// tradingView chart 使用 timestamp in seconds 顯示,而不是 timestamp in milliseconds
const PriceLineChart = ({ priceHistoryData, swapHistoryData }) => {
  const txDateList = [
    ...new Set(
      swapHistoryData.map(
        (_data) =>
          `${Date.parse(_data?.block_time.replace(":00.000", "")) / 1000}-${ // timestamp in seconds
            _data?.act
          }`
      )
    ),
  ];
  const isSellSignal = (s) => {
    return s.indexOf("S") !== -1;
  };
  const labelList = txDateList.map((_data) => ({
    time: Number(_data.slice(0, 10)) + 60 * 60 * 8,
    position: isSellSignal(_data) ? "aboveBar" : "belowBar",
    color: isSellSignal(_data) ? "#e91e63" : "Green",
    shape: isSellSignal(_data) ? "arrowDown" : "arrowUp",
    text: isSellSignal(_data) ? "Sell" : "Buy",
  }));

  const chartRef = useRef();

  useEffect(() => {
    const chart = createChart(chartRef.current, {
      width: chartRef.current.clientWidth,
      height: 300,
    });
    chart.applyOptions({
      timeScale: {
        // Adds hours and minutes scaling ability to the chart.
        timeVisible: true,
        secondsVisible: false,
      },
    });
    const lineSeries = chart.addLineSeries();
    lineSeries.setData(
      priceHistoryData.map((_data) => ({
        time: Date.parse(_data?.TIMESTAMP.replace(":00.000", "")) / 1000, // timestamp in seconds
        value: _data?.price,
      }))
    );
    lineSeries.setMarkers(labelList);
    return () => {
      chart.remove(); // 避免 Re-render 產生多個重複圖表
    };
  }, [priceHistoryData, swapHistoryData]);
  return (
    <div
      style={{
        width: "100%",
        height: "100%",
      }}
      ref={chartRef}
    ></div>
  );
};

export default PriceLineChart;

使用公開數據源 Widget

如果是 TradingView 本身提供的數據,可以使用他們的 widget 圖表,為免費

範例:

WidgetContainer

import { useEffect, useState } from "react";
import axios from "axios";
import styles from "./index.module.scss";
import WidgetComponent from "../../components/WidgetComponent";

const pairs = ["BTCUSDT", "ETHUSDT"];

const WidgetContainer = () => {
  const [selectedPair, setSelectedPair] = useState(pairs[0]);
  return (
    <div className={styles.container}>
      <div className={styles.top_pairTagContainer}>
        <div style={{ color: "#999", fontSize: "16px", fontWeight: "600" }}>
          Popular Trading Pairs
        </div>
        {pairs.map((pair) => (
          <div
            onClick={() => {
              setSelectedPair(pair);
            }}
            className={`${styles.pairTag} ${
              selectedPair === pair && styles.pairTag_active
            }`}
          >
            {pair}
          </div>
        ))}
      </div>
      <div
        style={{
          width: "70%",
          height: "641px",
        }}
      >
        <WidgetComponent selectedPair={selectedPair} />
      </div>
    </div>
  );
};

export default WidgetContainer;

WidgetComponent

import React, { useEffect, useRef } from 'react';

let tvScriptLoadingPromise;

export default function TradingViewWidget({ selectedPair }) {
  const onLoadScriptRef = useRef();

  useEffect(
    () => {
      console.log('selectedPair', selectedPair)
      onLoadScriptRef.current = createWidget;

      if (!tvScriptLoadingPromise) {
        tvScriptLoadingPromise = new Promise((resolve) => {
          const script = document.createElement('script');
          script.id = 'tradingview-widget-loading-script';
          script.src = 'https://s3.tradingview.com/tv.js';
          script.type = 'text/javascript';
          script.onload = resolve;

          document.head.appendChild(script);
        });
      }

      tvScriptLoadingPromise.then(() => onLoadScriptRef.current && onLoadScriptRef.current());

      return () => onLoadScriptRef.current = null;

      function createWidget() {
        if (document.getElementById('tradingview_ff115') && 'TradingView' in window) {
          new window.TradingView.widget({
            width: '100%',
            height: 641,
            symbol: `BIFINEX:${selectedPair}`,
            interval: "D",
            timezone: "Etc/UTC",
            theme: "light",
            style: "1",
            locale: "en",
            toolbar_bg: "#f1f3f6",
            enable_publishing: false,
            allow_symbol_change: true,
            container_id: "tradingview_ff115"
          });
        }
      }
    },
    [selectedPair]
  );

  return (
    <div className='tradingview-widget-container'>
      <div id='tradingview_ff115' />
      <div className="tradingview-widget-copyright">
        <a href="https://www.tradingview.com/symbols/BTCUSDT/?exchange=BITFINEX" rel="noopener" target="_blank"><span className="blue-text">BTCUSDT chart</span></a> by TradingView
      </div>
    </div>
  );
}

Last updated