lightweight-chartsを使用してFXのチャートを表示する。
TradingViewが提供するlightweight-chartsを活用し、FXチャートの作成に挑戦しました。このプロジェクトでは、バックエンドにPythonのFastAPIを、フロントエンドにはReactを使用しています。以下、そのプロセスを詳しくご紹介します。
コードはこちらになります
https://github.com/konohazukux/fxChart/tree/v0.1.0
1.バック側を構築する
Dockerを使用して環境を構築しました。
docker-compose.ymlとDockerfileを使用して、FastAPIアプリケーションをコンテナ化しました。これにより、どの環境でも同じ設定でアプリケーションを実行できるようになります。
1. 環境構築
ファイル構造は下記のようになります
% tree -L 4
.
├── api
│ ├── Dockerfile
│ ├── app
│ │ ├── data
│ │ │ └── 2023-09-12.csv
│ │ └── main.py
│ └── requirements.txt
├── docker-compose.yml
docker-compose.yml
version: '3.9'
services:
app:
build:
context: ./app
dockerfile: Dockerfile
command: ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000", "--reload"]
volumes:
- ./backend/app:/app
ports:
- "8000:8000"
Dockerfile
# Dockerfile
FROM tiangolo/uvicorn-gunicorn-fastapi:python3.9
# アプリケーションのディレクトリを作成
WORKDIR /app
# 依存関係のファイルをコピー
COPY requirements.txt .
# 依存関係をインストール
RUN pip install --no-cache-dir -r requirements.txt
# requirements.txt
fastapi==0.70.0
uvicorn==0.15.0
pandas
データについて
FXの市場データをCSVファイルで管理しています。
データの内容は下記のようになっています。(頭10行のみ表示しています)
% head ./api/app/data/2023-09-12.csv
datetime,symbol,open,high,low,close
2023-09-12 00:00, USDJPY, 146.394, 146.419, 146.385, 146.41
2023-09-12 00:01, USDJPY, 146.415, 146.433, 146.414, 146.429
2023-09-12 00:02, USDJPY, 146.43, 146.449, 146.417, 146.448
2023-09-12 00:03, USDJPY, 146.452, 146.472, 146.449, 146.464
2023-09-12 00:04, USDJPY, 146.461, 146.482, 146.461, 146.482
2023-09-12 00:05, USDJPY, 146.476, 146.495, 146.457, 146.457
2023-09-12 00:06, USDJPY, 146.456, 146.456, 146.426, 146.429
2023-09-12 00:07, USDJPY, 146.427, 146.441, 146.426, 146.436
2023-09-12 00:08, USDJPY, 146.436, 146.441, 146.428, 146.429
%
main.py
main.pyでは、FastAPIを使用してデータを提供するエンドポイントを設定しました。CORSの設定を行うことで、Reactアプリケーションからのリクエストを安全に処理できます。
# main.py
from fastapi import FastAPI, HTTPException
from fastapi.middleware.cors import CORSMiddleware
import pandas as pd
import os
DATA_DIR = "./data"
app = FastAPI()
origins = [
"http://localhost:3000", # Reactのアドレス
]
app.add_middleware(
CORSMiddleware,
allow_origins=origins,
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
@app.get("/")
def read_root():
return {"Hello": "World"}
@app.get("/items/{item_id}")
def read_item(item_id: int, query_param: str = None):
return {"item_id": item_id, "query_param": query_param}
@app.get("/data")
def read_data(date: str = "2023-09-12"):
# ディレクトリの存在確認
data_path = os.path.join(DATA_DIR, date)
if not os.path.exists(data_path):
raise HTTPException(status_code=404, detail="Data not found")
# ログファイルの読み込み
all_data = []
for hour in range(24):
for minute in range(60):
log_file_name = f"{date.replace('-', '')}-{hour:02}{minute:02}.log"
log_file_path = os.path.join(data_path, log_file_name)
if os.path.exists(log_file_path):
df = pd.read_csv(log_file_path, header=None, names=["datetime", "symbol", "open", "high", "low", "close"])
all_data.append(df)
final_df = pd.concat(all_data, ignore_index=True)
return final_df.to_dict(orient="records")
2. dockerを再起動
docker compose down
docker compose up -d --build
3. ブラウザで確認
ブラウザのURL欄にパスを入れるとresponseが表示されます
http://localhost:8000/data?date=2023-09-12
2.フロントエンドを構築する
1. 環境構築
まず、dockerで環境を構築したいので、下記のようなファイルを用意します
% tree -L 3
.
├── docker-compose.yml
└── web
└── Dockerfile
docker-compose.yml
version: '3.9'
services:
web:
build:
context: ./web
dockerfile: Dockerfile
volumes:
- ./web:/usr/src/app
ports:
- "3000:3000"
stdin_open: true
tty: true
Dockerfile
FROM node:16.15.0-alpine
WORKDIR /usr/src/app
RUN apk add bash
RUN apk update
RUN apk add vim
RUN apk add git
RUN npm install -g create-react-app
Dockerイメージをビルドします
docker compose up -d --build
reactアプリケーションを作成します
docker-compose run --rm web sh -c "create-react-app fx-chart"
アプリケーション自動起動設定
docker-compose.yml を修正
version: '3.9'
services:
web:
build:
context: ./web
dockerfile: Dockerfile
volumes:
- ./web:/usr/src/app
command: sh -c "cd fx-chart && yarn start" # ここを追加
ports:
- "3000:3000"
stdin_open: true
tty: true
dockerを再起動
docker compose down
docker compose up -d --build
ブラウザで確認
http://localhost:3000/
2.lightweight-charts のインストール
docker-compose run --rm web sh -c "npm install --save lightweight-charts axios"
3.App.jp
import React, { useEffect, useRef, useState } from "react";
import { createChart, CrosshairMode } from 'lightweight-charts';
import axios from 'axios';
const App = () => {
const chartRef = useRef(null);
const [date, setDate] = useState("2023-09-12"); // デフォルトの日付
useEffect(() => {
if(chartRef.current) {
const chart = createChart(chartRef.current, {
width: 800,
height: 600,
layout: {
backgroundColor: '#ffffff',
textColor: 'rgba(33, 56, 77, 1)',
},
crosshair: {
mode: CrosshairMode.Normal,
},
grid: {
vertLines: {
color: 'rgba(197, 203, 206, 0.5)',
},
horzLines: {
color: 'rgba(197, 203, 206, 0.5)',
},
},
});
const candlestickSeries = chart.addCandlestickSeries();
// APIからデータを取得
const fetchData = async () => {
try {
const response = await axios.get(`http://localhost:8000/data?date=${date}`);
const data = response.data.map(item => {
console.log(item);
const timestamp = new Date(item.datetime).getTime() / 1000; // UNIXタイムスタンプに変換
return {
time: timestamp,
open: parseFloat(item.open),
high: parseFloat(item.high),
low: parseFloat(item.low),
close: parseFloat(item.close)
};
});
candlestickSeries.setData(data);
} catch (error) {
console.error("Error fetching data:", error);
}
};
fetchData();
}
}, [date]);
return (
<>
<h1 style={{ color: 'red' }}> Candlestick Chart </h1>
<div ref={chartRef} style={{ width: '800px', height: '600px' }}></div>
<input type="date" value={date} onChange={e => setDate(e.target.value)} />
</>
);
};
// Appを外のファイルからも使用できるように export default で外から参照可能にする
export default App;
4. ブラウザで確認
http://localhost:3000
すべてのセットアップが完了した後、ブラウザでアプリケーションを開くと、FXチャートが表示されます。
この記事が気に入ったらサポートをしてみませんか?