mirror of
https://github.com/c9s/bbgo.git
synced 2024-11-22 06:53:52 +00:00
fix chart reload issue
This commit is contained in:
parent
fd45f801e2
commit
0a4c637209
|
@ -186,8 +186,6 @@ const ReportDetails = (props: ReportDetailsProps) => {
|
||||||
|
|
||||||
const volumeUnit = reportSummary.symbolReports.length == 1 ? reportSummary.symbolReports[0].market.baseCurrency : '';
|
const volumeUnit = reportSummary.symbolReports.length == 1 ? reportSummary.symbolReports[0].market.baseCurrency : '';
|
||||||
|
|
||||||
// reportSummary.startTime
|
|
||||||
|
|
||||||
return <div>
|
return <div>
|
||||||
<Container my="md" mx="xs">
|
<Container my="md" mx="xs">
|
||||||
<Title order={2}>RUN {props.runID}</Title>
|
<Title order={2}>RUN {props.runID}</Title>
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import React, {useEffect, useRef, useState} from 'react';
|
import React, {useEffect, useRef, useState} from 'react';
|
||||||
import {tsvParse} from "d3-dsv";
|
import {tsvParse} from "d3-dsv";
|
||||||
import { Button } from '@mantine/core';
|
import {Button} from '@mantine/core';
|
||||||
|
|
||||||
// https://github.com/tradingview/lightweight-charts/issues/543
|
// https://github.com/tradingview/lightweight-charts/issues/543
|
||||||
// const createChart = dynamic(() => import('lightweight-charts'));
|
// const createChart = dynamic(() => import('lightweight-charts'));
|
||||||
|
@ -194,6 +194,7 @@ const removeDuplicatedKLines = (klines) => {
|
||||||
const k = klines[i];
|
const k = klines[i];
|
||||||
|
|
||||||
if (i > 0 && k.time === klines[i - 1].time) {
|
if (i > 0 && k.time === klines[i - 1].time) {
|
||||||
|
console.warn(`duplicated kline at index ${i}`, k)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -234,6 +235,11 @@ const positionBaseHistoryToLineData = (interval, hs) => {
|
||||||
const intervalSeconds = parseInterval(interval);
|
const intervalSeconds = parseInterval(interval);
|
||||||
for (let i = 0; i < hs.length; i++) {
|
for (let i = 0; i < hs.length; i++) {
|
||||||
const pos = hs[i];
|
const pos = hs[i];
|
||||||
|
if (!pos.time) {
|
||||||
|
console.warn('position history record missing time field', pos)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
let t = pos.time.getTime() / 1000;
|
let t = pos.time.getTime() / 1000;
|
||||||
t = (t - t % intervalSeconds)
|
t = (t - t % intervalSeconds)
|
||||||
|
|
||||||
|
@ -255,6 +261,12 @@ const positionAverageCostHistoryToLineData = (interval, hs) => {
|
||||||
const intervalSeconds = parseInterval(interval);
|
const intervalSeconds = parseInterval(interval);
|
||||||
for (let i = 0; i < hs.length; i++) {
|
for (let i = 0; i < hs.length; i++) {
|
||||||
const pos = hs[i];
|
const pos = hs[i];
|
||||||
|
|
||||||
|
if (!pos.time) {
|
||||||
|
console.warn('position history record missing time field', pos)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
let t = pos.time.getTime() / 1000;
|
let t = pos.time.getTime() / 1000;
|
||||||
t = (t - t % intervalSeconds)
|
t = (t - t % intervalSeconds)
|
||||||
|
|
||||||
|
@ -279,14 +291,45 @@ const positionAverageCostHistoryToLineData = (interval, hs) => {
|
||||||
return avgCosts;
|
return avgCosts;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const createBaseChart = (chartContainerRef) => {
|
||||||
|
return createChart(chartContainerRef.current, {
|
||||||
|
width: chartContainerRef.current.clientWidth,
|
||||||
|
height: chartContainerRef.current.clientHeight,
|
||||||
|
timeScale: {
|
||||||
|
timeVisible: true,
|
||||||
|
borderColor: '#D1D4DC',
|
||||||
|
},
|
||||||
|
rightPriceScale: {
|
||||||
|
borderColor: '#D1D4DC',
|
||||||
|
},
|
||||||
|
leftPriceScale: {
|
||||||
|
visible: true,
|
||||||
|
borderColor: 'rgba(197, 203, 206, 1)',
|
||||||
|
},
|
||||||
|
layout: {
|
||||||
|
backgroundColor: '#ffffff',
|
||||||
|
textColor: '#000',
|
||||||
|
},
|
||||||
|
crosshair: {
|
||||||
|
mode: CrosshairMode.Normal,
|
||||||
|
},
|
||||||
|
grid: {
|
||||||
|
horzLines: {
|
||||||
|
color: '#F0F3FA',
|
||||||
|
},
|
||||||
|
vertLines: {
|
||||||
|
color: '#F0F3FA',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
const TradingViewChart = (props) => {
|
const TradingViewChart = (props) => {
|
||||||
const chartContainerRef = useRef();
|
const chartContainerRef = useRef();
|
||||||
const chart = useRef();
|
const chart = useRef();
|
||||||
const resizeObserver = useRef();
|
const resizeObserver = useRef();
|
||||||
const [data, setData] = useState(null);
|
const [data, setData] = useState(null);
|
||||||
const [orders, setOrders] = useState(null);
|
|
||||||
const [markers, setMarkers] = useState(null);
|
|
||||||
const [positionHistory, setPositionHistory] = useState(null);
|
|
||||||
const [currentInterval, setCurrentInterval] = useState('5m');
|
const [currentInterval, setCurrentInterval] = useState('5m');
|
||||||
|
|
||||||
const intervals = props.intervals || [];
|
const intervals = props.intervals || [];
|
||||||
|
@ -296,111 +339,86 @@ const TradingViewChart = (props) => {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!data) {
|
const chartData = {};
|
||||||
const fetchers = [];
|
const fetchers = [];
|
||||||
const ordersFetcher = fetchOrders(props.basePath, props.runID, (orders) => {
|
const ordersFetcher = fetchOrders(props.basePath, props.runID, (orders) => {
|
||||||
const markers = ordersToMarkets(currentInterval, orders);
|
const markers = ordersToMarkets(currentInterval, orders);
|
||||||
setOrders(orders);
|
chartData.orders = orders;
|
||||||
setMarkers(markers);
|
chartData.markers = markers;
|
||||||
});
|
});
|
||||||
fetchers.push(ordersFetcher);
|
fetchers.push(ordersFetcher);
|
||||||
|
|
||||||
if (props.reportSummary && props.reportSummary.manifests && props.reportSummary.manifests.length === 1) {
|
if (props.reportSummary && props.reportSummary.manifests && props.reportSummary.manifests.length === 1) {
|
||||||
const manifest = props.reportSummary?.manifests[0];
|
const manifest = props.reportSummary?.manifests[0];
|
||||||
if (manifest && manifest.type === "strategyProperty" && manifest.strategyProperty === "position") {
|
if (manifest && manifest.type === "strategyProperty" && manifest.strategyProperty === "position") {
|
||||||
const positionHistoryFetcher = fetchPositionHistory(props.basePath, props.runID, manifest.filename).then((data) => {
|
const positionHistoryFetcher = fetchPositionHistory(props.basePath, props.runID, manifest.filename).then((data) => {
|
||||||
setPositionHistory(data);
|
chartData.positionHistory = data;
|
||||||
});
|
});
|
||||||
fetchers.push(positionHistoryFetcher);
|
fetchers.push(positionHistoryFetcher);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const kLinesFetcher = fetchKLines(props.basePath, props.runID, props.symbol, currentInterval).then((klines) => {
|
||||||
|
chartData.klines = removeDuplicatedKLines(klines)
|
||||||
|
});
|
||||||
|
fetchers.push(kLinesFetcher);
|
||||||
|
|
||||||
|
Promise.all(fetchers).then(() => {
|
||||||
|
console.log("createChart")
|
||||||
|
|
||||||
|
if (chart.current) {
|
||||||
|
chart.current.remove();
|
||||||
}
|
}
|
||||||
|
|
||||||
Promise.all(fetchers).then(() => {
|
chart.current = createBaseChart(chartContainerRef);
|
||||||
fetchKLines(props.basePath, props.runID, props.symbol, currentInterval).then((data) => {
|
|
||||||
setData(removeDuplicatedKLines(data));
|
const series = chart.current.addCandlestickSeries({
|
||||||
})
|
upColor: 'rgb(38,166,154)',
|
||||||
|
downColor: 'rgb(255,82,82)',
|
||||||
|
wickUpColor: 'rgb(38,166,154)',
|
||||||
|
wickDownColor: 'rgb(255,82,82)',
|
||||||
|
borderVisible: false,
|
||||||
});
|
});
|
||||||
|
series.setData(chartData.klines);
|
||||||
|
series.setMarkers(chartData.markers);
|
||||||
|
|
||||||
return;
|
const volumeData = klinesToVolumeData(chartData.klines);
|
||||||
}
|
const volumeSeries = chart.current.addHistogramSeries({
|
||||||
|
color: '#182233',
|
||||||
console.log("createChart")
|
lineWidth: 2,
|
||||||
|
priceFormat: {
|
||||||
chart.current = createChart(chartContainerRef.current, {
|
type: 'volume',
|
||||||
width: chartContainerRef.current.clientWidth,
|
|
||||||
height: chartContainerRef.current.clientHeight,
|
|
||||||
timeScale: {
|
|
||||||
timeVisible: true,
|
|
||||||
borderColor: '#D1D4DC',
|
|
||||||
},
|
|
||||||
rightPriceScale: {
|
|
||||||
borderColor: '#D1D4DC',
|
|
||||||
},
|
|
||||||
leftPriceScale: {
|
|
||||||
visible: true,
|
|
||||||
borderColor: 'rgba(197, 203, 206, 1)',
|
|
||||||
},
|
|
||||||
layout: {
|
|
||||||
backgroundColor: '#ffffff',
|
|
||||||
textColor: '#000',
|
|
||||||
},
|
|
||||||
crosshair: {
|
|
||||||
mode: CrosshairMode.Normal,
|
|
||||||
},
|
|
||||||
grid: {
|
|
||||||
horzLines: {
|
|
||||||
color: '#F0F3FA',
|
|
||||||
},
|
},
|
||||||
vertLines: {
|
overlay: true,
|
||||||
color: '#F0F3FA',
|
scaleMargins: {
|
||||||
|
top: 0.8,
|
||||||
|
bottom: 0,
|
||||||
},
|
},
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const series = chart.current.addCandlestickSeries({
|
|
||||||
upColor: 'rgb(38,166,154)',
|
|
||||||
downColor: 'rgb(255,82,82)',
|
|
||||||
wickUpColor: 'rgb(38,166,154)',
|
|
||||||
wickDownColor: 'rgb(255,82,82)',
|
|
||||||
borderVisible: false,
|
|
||||||
});
|
|
||||||
series.setData(data);
|
|
||||||
series.setMarkers(markers);
|
|
||||||
|
|
||||||
if (positionHistory) {
|
|
||||||
const lineSeries = chart.current.addLineSeries();
|
|
||||||
const costLine = positionAverageCostHistoryToLineData(currentInterval, positionHistory);
|
|
||||||
lineSeries.setData(costLine);
|
|
||||||
|
|
||||||
const baseLineSeries = chart.current.addLineSeries({
|
|
||||||
priceScaleId: 'left',
|
|
||||||
color: '#98338C',
|
|
||||||
});
|
});
|
||||||
const baseLine = positionBaseHistoryToLineData(currentInterval, positionHistory)
|
volumeSeries.setData(volumeData);
|
||||||
baseLineSeries.setData(baseLine);
|
|
||||||
}
|
|
||||||
|
|
||||||
const volumeData = klinesToVolumeData(data);
|
if (chartData.positionHistory) {
|
||||||
const volumeSeries = chart.current.addHistogramSeries({
|
const lineSeries = chart.current.addLineSeries();
|
||||||
color: '#182233',
|
const costLine = positionAverageCostHistoryToLineData(currentInterval, chartData.positionHistory);
|
||||||
lineWidth: 2,
|
lineSeries.setData(costLine);
|
||||||
priceFormat: {
|
|
||||||
type: 'volume',
|
const baseLineSeries = chart.current.addLineSeries({
|
||||||
},
|
priceScaleId: 'left',
|
||||||
overlay: true,
|
color: '#98338C',
|
||||||
scaleMargins: {
|
});
|
||||||
top: 0.8,
|
const baseLine = positionBaseHistoryToLineData(currentInterval, chartData.positionHistory)
|
||||||
bottom: 0,
|
baseLineSeries.setData(baseLine);
|
||||||
},
|
}
|
||||||
|
|
||||||
|
chart.current.timeScale().fitContent();
|
||||||
});
|
});
|
||||||
volumeSeries.setData(volumeData);
|
|
||||||
|
|
||||||
chart.current.timeScale().fitContent();
|
|
||||||
return () => {
|
return () => {
|
||||||
chart.current.remove();
|
if (chart.current) {
|
||||||
setData(null);
|
chart.current.remove();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}, [props.runID, props.reportSummary, currentInterval, data])
|
}, [props.runID, props.reportSummary, currentInterval])
|
||||||
|
|
||||||
// see:
|
// see:
|
||||||
// https://codesandbox.io/s/9inkb?file=/src/styles.css
|
// https://codesandbox.io/s/9inkb?file=/src/styles.css
|
||||||
|
|
|
@ -27,7 +27,7 @@ const withTM = require('next-transpile-modules')([
|
||||||
|
|
||||||
/** @type {import('next').NextConfig} */
|
/** @type {import('next').NextConfig} */
|
||||||
const nextConfig = {
|
const nextConfig = {
|
||||||
reactStrictMode: true,
|
reactStrictMode: false,
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = withTM(nextConfig);
|
module.exports = withTM(nextConfig);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user