- Published on
TradingViewのチャート上データをデータベースに保存するツール
- Authors
- Name
- Shou Arisaka / 有坂翔
トレーダー諸姉諸君はTradingViewにおいてインディケータを無論使っているだろう。それらの数値的なデータは右側サイドメニューの「データウィンドウ」から確認することができる。
アルゴトレード(システムトレード)において、TradingViewを活用する方法は大別して2つある。
TradingView上のPine Scriptで売買の意思決定を完結させる。
buyシグナル、sellシグナルが出るようにアルゴリズムを書き、値が出たらwebhookリクエストして注文を出す。
TradingView上のPine Scriptと売買の意思決定アルゴリズムを区分する。
TradingViewはあくまでインディケータの作成、レンダリング、チャーティングとして用途を限定し、売買の意思決定はそこから得られたデータを元に別のプログラムで行う。
今回のツールは後者の方法を取る場合に有用である。
以下はこのツールがTradingViewのデータウィンドウ上から取得したデータをログしている様子である。
上記スクリーンショットではログがされているだけだが、実際にはこのツールはデータベースにデータを保存させる機能を有している。
ツール、というよりも、ツールチェイン、あるいはシステムと呼んだ方が正確かもしれない。
このツールは以下のような構成になっている。
Chrome拡張機能
TradingViewのデータウィンドウ上のデータを取得(スクレイピング)し、データをウェブサーバに送る
ウェブサーバ
Chrome拡張機能から送られてきたデータを受け取り、データベース(mongodb)に保存する
さらに言うと、私のセットアップでは、ここにもう二つのツールがシステムの構成に含まれる。これにより、アルゴトレードのシステムが完全性を持って構築される。
アルゴリズムプログラム
データベースからデータを取得し、売買の意思決定を行う。これは手動、半自動(条件下実行、遅延実行など)、あるいは自動で行われる。
ウェブサーバ(トレードサーバ)
アルゴリズムプログラムからのリクエストを受け取り、注文を出す。これによりポジションの管理が行われる。
以下はこのツールのChrome拡張機能のコードの一部だ。
/**
* tradingview data emitter
*/
(async () => {
const sleep = m => new Promise(r => setTimeout(r, m));
const moment = (await import('https://cdn.jsdelivr.net/npm/moment@2.29.4/+esm')).default;
const axios = (await import('https://cdn.skypack.dev/axios@1.4.0')).default;
const URLParse = (await import('https://cdn.skypack.dev/url-parse@1.5.10')).default;
const uuid = (await import('https://cdn.skypack.dev/@lukeed/uuid@2.0.1')).v4;
const jsyaml = (await import('https://cdn.skypack.dev/js-yaml@4.1.0')).default;
const script = (await axios.get(`http://localhost:8080/web/lib/utils.js?ts=${(+new Date())}`)).data;
eval(script);
app.console.setLogPrefix("[tradingview data emitter]");
tabs = await ChromeUtils.getTabs();
app.console.log("waiting... (a tab matches)")
const match = `https://www.tradingview.com/chart/`
await waitUntil(() => typeof tabs.filter(a => a.url.match(match))?.[0]?.id == "number");
let __target = tabs.filter(a => a.url.match(match))?.[0]?.id;
const code = `
Array.from(document.querySelectorAll('div[class*=chart-data-window] div[class^=view-]')).map(
view => {
const headerTitle = view.querySelector('div[class^="header-"] > span[class^=headerTitle]')?.textContent
// (続く)
このツールおよびシステムの大枠は上述の通りである。
ツールの紹介は以上である。