mirror of
https://github.com/c9s/bbgo.git
synced 2024-09-20 08:11:08 +00:00
migrate javascript to typescript
This commit is contained in:
parent
d88e41c20c
commit
0b082e5fe1
|
@ -5,9 +5,10 @@ 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'));
|
||||||
import {createChart, CrosshairMode} from 'lightweight-charts';
|
import {createChart, CrosshairMode} from 'lightweight-charts';
|
||||||
|
import {ReportSummary} from "../types";
|
||||||
|
|
||||||
const parseKline = () => {
|
const parseKline = () => {
|
||||||
return (d) => {
|
return (d : any) => {
|
||||||
d.startTime = new Date(Number(d.startTime) * 1000);
|
d.startTime = new Date(Number(d.startTime) * 1000);
|
||||||
d.endTime = new Date(Number(d.endTime) * 1000);
|
d.endTime = new Date(Number(d.endTime) * 1000);
|
||||||
d.time = d.startTime.getTime() / 1000;
|
d.time = d.startTime.getTime() / 1000;
|
||||||
|
@ -33,7 +34,7 @@ const parseKline = () => {
|
||||||
|
|
||||||
|
|
||||||
const parseOrder = () => {
|
const parseOrder = () => {
|
||||||
return (d) => {
|
return (d: any) => {
|
||||||
for (const key in d) {
|
for (const key in d) {
|
||||||
// convert number fields
|
// convert number fields
|
||||||
if (Object.prototype.hasOwnProperty.call(d, key)) {
|
if (Object.prototype.hasOwnProperty.call(d, key)) {
|
||||||
|
@ -56,7 +57,7 @@ const parseOrder = () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
const parsePosition = () => {
|
const parsePosition = () => {
|
||||||
return (d) => {
|
return (d: any) => {
|
||||||
for (const key in d) {
|
for (const key in d) {
|
||||||
// convert number fields
|
// convert number fields
|
||||||
if (Object.prototype.hasOwnProperty.call(d, key)) {
|
if (Object.prototype.hasOwnProperty.call(d, key)) {
|
||||||
|
@ -77,32 +78,29 @@ const parsePosition = () => {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const fetchPositionHistory = (basePath, runID, filename) => {
|
const fetchPositionHistory = (basePath: string, runID: string, filename: string) => {
|
||||||
return fetch(
|
return fetch(
|
||||||
`${basePath}/${runID}/${filename}`,
|
`${basePath}/${runID}/${filename}`,
|
||||||
)
|
)
|
||||||
.then((response) => response.text())
|
.then((response) => response.text())
|
||||||
.then((data) => tsvParse(data, parsePosition()))
|
.then((data) => tsvParse(data, parsePosition()) as Array<PositionHistoryEntry>)
|
||||||
.catch((e) => {
|
.catch((e) => {
|
||||||
console.error("failed to fetch orders", e)
|
console.error("failed to fetch orders", e)
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const fetchOrders = (basePath, runID, setter) => {
|
const fetchOrders = (basePath: string, runID: string) => {
|
||||||
return fetch(
|
return fetch(
|
||||||
`${basePath}/${runID}/orders.tsv`,
|
`${basePath}/${runID}/orders.tsv`,
|
||||||
)
|
)
|
||||||
.then((response) => response.text())
|
.then((response) => response.text())
|
||||||
.then((data) => tsvParse(data, parseOrder()))
|
.then((data: string) => tsvParse(data, parseOrder()) as Array<Order>)
|
||||||
.then((data) => {
|
|
||||||
setter(data);
|
|
||||||
})
|
|
||||||
.catch((e) => {
|
.catch((e) => {
|
||||||
console.error("failed to fetch orders", e)
|
console.error("failed to fetch orders", e)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const parseInterval = (s) => {
|
const parseInterval = (s: string) => {
|
||||||
switch (s) {
|
switch (s) {
|
||||||
case "1m":
|
case "1m":
|
||||||
return 60;
|
return 60;
|
||||||
|
@ -127,28 +125,33 @@ const parseInterval = (s) => {
|
||||||
return 60;
|
return 60;
|
||||||
};
|
};
|
||||||
|
|
||||||
const orderAbbr = (order) => {
|
interface Order {
|
||||||
let s = '';
|
order_type: string;
|
||||||
switch (order.side) {
|
side: string;
|
||||||
case "BUY":
|
price: number;
|
||||||
s += 'B';
|
quantity: number;
|
||||||
break;
|
executed_quantity: number;
|
||||||
case "SELL":
|
status: string;
|
||||||
s += 'S';
|
update_time: Date;
|
||||||
break
|
creation_time: Date;
|
||||||
}
|
|
||||||
|
|
||||||
switch (order.order_type) {
|
|
||||||
case "STOP_LIMIT":
|
|
||||||
s += ' StopLoss';
|
|
||||||
}
|
|
||||||
return s
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const ordersToMarkets = (interval, orders) => {
|
interface Marker {
|
||||||
const markers = [];
|
time: number;
|
||||||
|
position: string;
|
||||||
|
color: string;
|
||||||
|
shape: string;
|
||||||
|
text: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ordersToMarkets = (interval: string, orders: Array<Order> | void): Array<Marker> => {
|
||||||
|
const markers: Array<Marker> = [];
|
||||||
const intervalSecs = parseInterval(interval);
|
const intervalSecs = parseInterval(interval);
|
||||||
|
|
||||||
|
if (!orders) {
|
||||||
|
return markers;
|
||||||
|
}
|
||||||
|
|
||||||
// var markers = [{ time: data[data.length - 48].time, position: 'aboveBar', color: '#f68410', shape: 'circle', text: 'D' }];
|
// var markers = [{ time: data[data.length - 48].time, position: 'aboveBar', color: '#f68410', shape: 'circle', text: 'D' }];
|
||||||
for (let i = 0; i < orders.length; i++) {
|
for (let i = 0; i < orders.length; i++) {
|
||||||
let order = orders[i];
|
let order = orders[i];
|
||||||
|
@ -190,7 +193,7 @@ const ordersToMarkets = (interval, orders) => {
|
||||||
return markers;
|
return markers;
|
||||||
};
|
};
|
||||||
|
|
||||||
const removeDuplicatedKLines = (klines) => {
|
const removeDuplicatedKLines = (klines: Array<KLine>): Array<KLine> => {
|
||||||
const newK = [];
|
const newK = [];
|
||||||
for (let i = 0; i < klines.length; i++) {
|
for (let i = 0; i < klines.length; i++) {
|
||||||
const k = klines[i];
|
const k = klines[i];
|
||||||
|
@ -205,19 +208,30 @@ const removeDuplicatedKLines = (klines) => {
|
||||||
return newK;
|
return newK;
|
||||||
}
|
}
|
||||||
|
|
||||||
function fetchKLines(basePath, runID, symbol, interval, setter) {
|
function fetchKLines(basePath: string, runID: string, symbol: string, interval: string) {
|
||||||
return fetch(
|
return fetch(
|
||||||
`${basePath}/${runID}/klines/${symbol}-${interval}.tsv`,
|
`${basePath}/${runID}/klines/${symbol}-${interval}.tsv`,
|
||||||
)
|
)
|
||||||
.then((response) => response.text())
|
.then((response) => response.text())
|
||||||
.then((data) => tsvParse(data, parseKline()))
|
.then((data) => tsvParse(data, parseKline()))
|
||||||
// .then((data) => tsvParse(data))
|
|
||||||
.catch((e) => {
|
.catch((e) => {
|
||||||
console.error("failed to fetch klines", e)
|
console.error("failed to fetch klines", e)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const klinesToVolumeData = (klines) => {
|
interface KLine {
|
||||||
|
time: Date;
|
||||||
|
startTime: Date;
|
||||||
|
endTime: Date;
|
||||||
|
interval: string;
|
||||||
|
open: number;
|
||||||
|
high: number;
|
||||||
|
low: number;
|
||||||
|
close: number;
|
||||||
|
volume: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
const klinesToVolumeData = (klines: Array<KLine>) => {
|
||||||
const volumes = [];
|
const volumes = [];
|
||||||
|
|
||||||
for (let i = 0; i < klines.length; i++) {
|
for (let i = 0; i < klines.length; i++) {
|
||||||
|
@ -232,7 +246,14 @@ const klinesToVolumeData = (klines) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const positionBaseHistoryToLineData = (interval, hs) => {
|
interface PositionHistoryEntry {
|
||||||
|
time: Date;
|
||||||
|
base: number;
|
||||||
|
quote: number;
|
||||||
|
average_cost: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
const positionBaseHistoryToLineData = (interval: string, hs: Array<PositionHistoryEntry>) => {
|
||||||
const bases = [];
|
const bases = [];
|
||||||
const intervalSeconds = parseInterval(interval);
|
const intervalSeconds = parseInterval(interval);
|
||||||
for (let i = 0; i < hs.length; i++) {
|
for (let i = 0; i < hs.length; i++) {
|
||||||
|
@ -242,10 +263,15 @@ const positionBaseHistoryToLineData = (interval, hs) => {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ignore duplicated entry
|
||||||
|
if (hs[i].time.getTime() === hs[i - 1].time.getTime()) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
let t = pos.time.getTime() / 1000;
|
let t = pos.time.getTime() / 1000;
|
||||||
t = (t - t % intervalSeconds)
|
t = (t - t % intervalSeconds)
|
||||||
|
|
||||||
if (i > 0 && (pos.base === hs[i - 1].base || t === hs[i - 1].time)) {
|
if (i > 0 && (pos.base === hs[i - 1].base)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -258,7 +284,7 @@ const positionBaseHistoryToLineData = (interval, hs) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const positionAverageCostHistoryToLineData = (interval, hs) => {
|
const positionAverageCostHistoryToLineData = (interval: string, hs: Array<PositionHistoryEntry>) => {
|
||||||
const avgCosts = [];
|
const avgCosts = [];
|
||||||
const intervalSeconds = parseInterval(interval);
|
const intervalSeconds = parseInterval(interval);
|
||||||
for (let i = 0; i < hs.length; i++) {
|
for (let i = 0; i < hs.length; i++) {
|
||||||
|
@ -269,10 +295,16 @@ const positionAverageCostHistoryToLineData = (interval, hs) => {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ignore duplicated entry
|
||||||
|
if (hs[i].time.getTime() === hs[i - 1].time.getTime()) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
let t = pos.time.getTime() / 1000;
|
let t = pos.time.getTime() / 1000;
|
||||||
t = (t - t % intervalSeconds)
|
t = (t - t % intervalSeconds)
|
||||||
|
|
||||||
if (i > 0 && (pos.average_cost === hs[i - 1].average_cost || t === hs[i - 1].time)) {
|
if (i > 0 && (pos.average_cost === hs[i - 1].average_cost)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -293,7 +325,7 @@ const positionAverageCostHistoryToLineData = (interval, hs) => {
|
||||||
return avgCosts;
|
return avgCosts;
|
||||||
}
|
}
|
||||||
|
|
||||||
const createBaseChart = (chartContainerRef) => {
|
const createBaseChart = (chartContainerRef: React.RefObject<any>) => {
|
||||||
return createChart(chartContainerRef.current, {
|
return createChart(chartContainerRef.current, {
|
||||||
width: chartContainerRef.current.clientWidth,
|
width: chartContainerRef.current.clientWidth,
|
||||||
height: chartContainerRef.current.clientHeight,
|
height: chartContainerRef.current.clientHeight,
|
||||||
|
@ -327,10 +359,17 @@ const createBaseChart = (chartContainerRef) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
const TradingViewChart = (props) => {
|
interface TradingViewChartProps {
|
||||||
const chartContainerRef = useRef();
|
basePath: string;
|
||||||
const chart = useRef();
|
runID: string;
|
||||||
const resizeObserver = useRef();
|
reportSummary: ReportSummary;
|
||||||
|
symbol: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const TradingViewChart = (props: TradingViewChartProps) => {
|
||||||
|
const chartContainerRef = useRef<any>();
|
||||||
|
const chart = useRef<any>();
|
||||||
|
const resizeObserver = useRef<any>();
|
||||||
const intervals = props.reportSummary.intervals || [];
|
const intervals = props.reportSummary.intervals || [];
|
||||||
const [currentInterval, setCurrentInterval] = useState(intervals.length > 0 ? intervals[0] : '1m');
|
const [currentInterval, setCurrentInterval] = useState(intervals.length > 0 ? intervals[0] : '1m');
|
||||||
|
|
||||||
|
@ -339,12 +378,13 @@ const TradingViewChart = (props) => {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const chartData = {};
|
const chartData: any = {};
|
||||||
const fetchers = [];
|
const fetchers = [];
|
||||||
const ordersFetcher = fetchOrders(props.basePath, props.runID, (orders) => {
|
const ordersFetcher = fetchOrders(props.basePath, props.runID).then((orders) => {
|
||||||
const markers = ordersToMarkets(currentInterval, orders);
|
const markers = ordersToMarkets(currentInterval, orders);
|
||||||
chartData.orders = orders;
|
chartData.orders = orders;
|
||||||
chartData.markers = markers;
|
chartData.markers = markers;
|
||||||
|
return orders;
|
||||||
});
|
});
|
||||||
fetchers.push(ordersFetcher);
|
fetchers.push(ordersFetcher);
|
||||||
|
|
||||||
|
@ -359,7 +399,7 @@ const TradingViewChart = (props) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
const kLinesFetcher = fetchKLines(props.basePath, props.runID, props.symbol, currentInterval).then((klines) => {
|
const kLinesFetcher = fetchKLines(props.basePath, props.runID, props.symbol, currentInterval).then((klines) => {
|
||||||
chartData.klines = removeDuplicatedKLines(klines)
|
chartData.klines = removeDuplicatedKLines(klines as Array<KLine>)
|
||||||
});
|
});
|
||||||
fetchers.push(kLinesFetcher);
|
fetchers.push(kLinesFetcher);
|
||||||
|
|
||||||
|
@ -444,7 +484,7 @@ const TradingViewChart = (props) => {
|
||||||
<div>
|
<div>
|
||||||
<span>
|
<span>
|
||||||
{intervals.map((interval) => {
|
{intervals.map((interval) => {
|
||||||
return <Button key={interval} compact onClick={(e) => {
|
return <Button key={interval} compact onClick={() => {
|
||||||
setCurrentInterval(interval)
|
setCurrentInterval(interval)
|
||||||
}}>
|
}}>
|
||||||
{interval}
|
{interval}
|
Loading…
Reference in New Issue
Block a user