Electronで動くTrading View – Ticker Tapeのデスクトップウィジェット作成

この記事はAIによって生成し、筆者が加筆・訂正を加えた記事です

仕様

  • Trading ViewのTicker TapeウィジェットをElectronアプリケーションに組み込み、リアルタイムな株価情報を表示する。
  • Electronアプリケーションは、タスクバーの右上に固定して表示される。
  • Electronアプリケーションは、他のアプリケーションが起動しても最前面に表示される。
  • Electronアプリケーションは、ウィンドウのシステムがライトかダークに合わせて背景色も変更される。

開発環境

  • OS: Windows 11
  • Node.js: 18.x
  • npm: 9.x
  • Electron: 25.x
  • Electron Forge: 6.x

目的

Electronフレームワークを使用して、Trading ViewのTicker Tapeウィジェットをデスクトップアプリケーションとして実装し、リアルタイムな株価情報を手軽に確認できるようにすることを目指します。

開発手順

Trading ViewにてTicker TapeウィジェットのHTMLを生成します。

<!-- TradingView Widget BEGIN -->
<div class="tradingview-widget-container">
  <div class="tradingview-widget-container__widget"></div>
  <div class="tradingview-widget-copyright"><a href="https://jp.tradingview.com/" rel="noopener nofollow" target="_blank"><span class="blue-text">TradingViewですべてのマーケットを追跡</span></a></div>
  <script type="text/javascript" src="https://s3.tradingview.com/external-embedding/embed-widget-ticker-tape.js" async>
  {
  "symbols": [
    {
      "proName": "FOREXCOM:SPXUSD",
      "title": "S&P 500 Index"
    },
    {
      "proName": "FOREXCOM:NSXUSD",
      "title": "US 100 Cash CFD"
    },
    {
      "proName": "FX_IDC:EURUSD",
      "title": "EUR to USD"
    },
    {
      "proName": "BITSTAMP:BTCUSD",
      "title": "Bitcoin"
    }
  ],
  "showSymbolLogo": true,
  "isTransparent": true,
  "displayMode": "adaptive",
  "colorTheme": "dark",
  "locale": "ja"
}
  </script>
</div>
<!-- TradingView Widget END -->

プロジェクトの初期化

まず、Electronプロジェクトを初期化します。ターミナルを開き、以下のコマンドを実行します。

mkdir tradingview-ticker
cd tradingview-ticker
npm init -y
npm install --save-dev electron-forge @electron-forge/cli
npm install --save electron-squirrel-startup
npm install --save @electron-forge/maker-squirrel @electron-forge/maker-zip @electron-forge/maker-deb @electron-forge/maker-rpm
npm install electron --save-dev
npm install electron-packager --save-dev

これらのコマンドは、Electron Forgeをインストールし、必要な依存関係を追加します。

Trading Viewウィジェットの組み込み

Trading Viewから提供されるTicker Tapeウィジェットのコードをindex.htmlファイルに組み込みます。index.htmlファイルを作成し、以下のコードを追加します。

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8" />
  <title>Trading View</title>
  <style>
  body {
    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
    margin: auto;
    max-width: 38rem;
  }
  </style>
</head>
<body>
  <div class="tradingview-widget-container">
    <div class="tradingview-widget-container__widget" data-widget-type="ticker-tape"
      data-symbols="FOREXCOM:SPXUSD,FOREXCOM:NSXUSD,FX_IDC:EURUSD,BITSTAMP:BTCUSD"
      data-show-symbol-logo="true" data-is-transparent="true" data-display-mode="compact" data-color-theme="dark"
      data-locale="ja">
    </div>
    <script type="text/javascript" src="https://s3.tradingview.com/external-embedding/embed-widget-ticker-tape.js"
      async>
        {
          "symbols": [
            {
              "proName": "FOREXCOM:SPXUSD",
              "title": "S&P 500 Index"
            },
            {
              "proName": "FOREXCOM:NSXUSD",
              "title": "US 100 Cash CFD"
            },
            {
              "proName": "FX_IDC:EURUSD",
              "title": "EUR to USD"
            },
            {
              "proName": "BITSTAMP:BTCUSD",
              "title": "Bitcoin"
            }
          ],
            "showSymbolLogo": true,
              "isTransparent": true,
                "displayMode": "compact",
                  "colorTheme": "dark",
                    "locale": "ja"
        }
      </script>
  </div>
</body>
</html>

Electronウィンドウのカスタマイズ

tradingview-app/src/index.jsファイルを編集し、以下のコードを追加します。

const { app, BrowserWindow } = require("electron");
const path = require("node:path");

// インストール/アンインストール時にWindowsのショートカットを作成/削除する処理
if (require("electron-squirrel-startup")) {
  app.quit();
}

const createWindow = () => {
  // ブラウザウィンドウを作成
  const { screen } = require("electron");

  const primaryDisplay = screen.getPrimaryDisplay();
  const { width, height } = primaryDisplay.workAreaSize;

  const mainWindow = new BrowserWindow({
    x: width - 800,
    y: 0,
    webPreferences: {
      preload: path.join(__dirname, "preload.js"),
      transparent: true,
    },
  });

  mainWindow.loadFile(path.join(__dirname, "index.html"));
  mainWindow.setMenu(null);

  mainWindow.webContents.on("did-finish-load", () => {
    const size = mainWindow.webContents.executeJavaScript(
      "electronAPI.getSize()"
    );
    size.then((result) => {
      mainWindow.setContentSize(result.width, result.height);
    });

    const theme = mainWindow.webContents.executeJavaScript(
      "electronAPI.getSystemTheme()"
    );
    theme.then((result) => {
      mainWindow.setBackgroundColor(result === "dark" ? "#1e1e1e" : "#ffffff");
    });
  });

  mainWindow.setAlwaysOnTop(true);

  mainWindow.on("focus", () => {
    mainWindow.setOpacity(1);
  });

  mainWindow.on("blur", () => {
    mainWindow.setOpacity(0.7);
  });
};

// Electronの初期化が完了し、ブラウザウィンドウを作成する準備ができたときに、このメソッドが呼び出されます。
// このイベントが発生した後でのみ、一部のAPIを使用できます。
const { session } = require("electron");

app.whenReady().then(() => {
  session.defaultSession.clearCache();
  session.defaultSession.clearStorageData({
    storages: [
      "appcache",
      "cookies",
      "filesystem",
      "indexdb",
      "localstorage",
      "shadercache",
      "websql",
    ],
    quota: true,
  });
  createWindow();

  // OS Xでは、ドックアイコンがクリックされ、他にウィンドウが開いていない場合に、アプリでウィンドウを再作成するのが一般的です。
  app.on("activate", () => {
    if (BrowserWindow.getAllWindows().length === 0) {
      createWindow();
    }
  });
});

// macOSを除き、すべてのウィンドウが閉じられたときに終了します。そこでは、アプリケーションとそのメニューバーは、ユーザーがCmd + Qで明示的に終了するまでアクティブなままにしておくのが一般的です。
app.on("window-all-closed", () => {
  if (process.platform !== "darwin") {
    app.quit();
  }
});

// このファイルには、アプリの特定のメインプロセスコードの残りの部分を含めることができます。また、それらを個別のファイルに入れて、ここでインポートすることもできます。

プリロードスクリプトの作成

tradingview-app/src/preload.jsファイルを作成し、以下のコードを追加します。

const { contextBridge, ipcRenderer } = require("electron");

contextBridge.exposeInMainWorld("electronAPI", {
  getSize: () => {
    const container = document.querySelector(".tradingview-widget-container");
    return {
      width: container.offsetWidth,
      height: container.offsetHeight,
    };
  },
  getSystemTheme: () => {
    return window.matchMedia("(prefers-color-scheme: dark)").matches
      ? "dark"
      : "light";
  },
});

まとめ

ElectronフレームワークとTrading ViewのTicker Tapeウィジェットを組み合わせることで、リアルタイムな株価情報を表示するデスクトップアプリケーションを開発することができました。

Github

https://github.com/bytedesign-net/tradeviewer-tickertape-widget