This commit is contained in:
2026-06-01 19:05:46 +02:00
parent abb810d544
commit 27e25d5bf4
59 changed files with 5727 additions and 1706 deletions

View File

@@ -186,6 +186,32 @@ function renderCatalogTextareas(
pairsTextarea.value = JSON.stringify(catalog.pairs, null, 2);
}
function toChartNumber(value: number | string | null | undefined): number {
if (value === null || value === undefined) {
return 0;
}
if (typeof value === "number") {
return Number.isFinite(value) ? value : 0;
}
const parsed = Number.parseFloat(value);
if (Number.isNaN(parsed) || !Number.isFinite(parsed)) {
return 0;
}
return parsed;
}
function calculateVisibleWindowStart(totalCandles: number): number {
if (totalCandles <= 90) {
return 0;
}
return Math.max(0, ((totalCandles - 90) / totalCandles) * 100);
}
function parseCandlesJson(raw: string): PairCandle[] {
if (raw.trim() === "") {
return [];
@@ -239,16 +265,18 @@ function renderCandlesChart(
);
const ohlcData = sorted.map((candle) => [
candle.open_price_quote_per_base,
candle.close_price_quote_per_base,
candle.low_price_quote_per_base,
candle.high_price_quote_per_base,
toChartNumber(candle.open_price_quote_per_base),
toChartNumber(candle.close_price_quote_per_base),
toChartNumber(candle.low_price_quote_per_base),
toChartNumber(candle.high_price_quote_per_base),
]);
const volumeData = sorted.map((candle) =>
parseVolume(candle.quote_volume_raw, candle.trade_count),
);
const zoomStart = calculateVisibleWindowStart(sorted.length);
chartMeta.textContent =
`Pair #${pairId.toString()} • timeframe ${timeframeSeconds.toString()}s • ${sorted.length} candles`;
@@ -256,7 +284,8 @@ function renderCandlesChart(
animation: false,
legend: {
data: ["OHLC", "Volume"],
top: 0,
top: 4,
left: 16,
},
tooltip: {
trigger: "axis",
@@ -268,8 +297,8 @@ function renderCandlesChart(
link: [{ xAxisIndex: "all" }],
},
grid: [
{ left: 60, right: 24, top: 40, height: "58%" },
{ left: 60, right: 24, top: "74%", height: "16%" },
{ left: 76, right: 32, top: 52, height: "58%" },
{ left: 76, right: 32, top: "77%", height: "12%" },
],
xAxis: [
{
@@ -277,7 +306,9 @@ function renderCandlesChart(
data: categoryData,
boundaryGap: true,
axisLine: { onZero: false },
splitLine: { show: false },
axisTick: { alignWithLabel: true },
splitLine: { show: true },
axisLabel: { hideOverlap: true, margin: 14 },
min: "dataMin",
max: "dataMax",
},
@@ -287,9 +318,9 @@ function renderCandlesChart(
data: categoryData,
boundaryGap: true,
axisLine: { onZero: false },
axisTick: { show: false },
axisTick: { alignWithLabel: true },
splitLine: { show: false },
axisLabel: { show: false },
axisLabel: { hideOverlap: true, margin: 10 },
min: "dataMin",
max: "dataMax",
},
@@ -297,27 +328,33 @@ function renderCandlesChart(
yAxis: [
{
scale: true,
splitNumber: 5,
splitArea: { show: false },
axisLabel: { margin: 12 },
},
{
gridIndex: 1,
scale: true,
splitNumber: 2,
axisLabel: { margin: 12 },
},
],
dataZoom: [
{
type: "inside",
xAxisIndex: [0, 1],
start: 0,
filterMode: "none",
start: zoomStart,
end: 100,
},
{
show: true,
type: "slider",
xAxisIndex: [0, 1],
bottom: 6,
start: 0,
filterMode: "none",
bottom: 8,
height: 22,
start: zoomStart,
end: 100,
},
],
@@ -326,11 +363,12 @@ function renderCandlesChart(
name: "OHLC",
type: "candlestick",
data: ohlcData,
xAxisIndex: 0,
yAxisIndex: 0,
barMinWidth: 4,
barMaxWidth: 16,
itemStyle: {
color: "#16a34a",
color0: "#dc2626",
borderColor: "#15803d",
borderColor0: "#b91c1c",
borderWidth: 1.4,
},
},
{
@@ -339,9 +377,13 @@ function renderCandlesChart(
xAxisIndex: 1,
yAxisIndex: 1,
data: volumeData,
barMinWidth: 2,
barMaxWidth: 10,
},
],
}, true);
window.setTimeout(() => chart.resize(), 0);
}
document.addEventListener("DOMContentLoaded", async () => {
@@ -468,6 +510,10 @@ document.addEventListener("DOMContentLoaded", async () => {
const chart = echarts.init(safeChartElement);
setEmptyChart(chart, safeChartMeta, "Aucune candle disponible.");
window.addEventListener("resize", () => chart.resize());
const chartCollapse = document.querySelector<HTMLDivElement>("#demoPipeline2ChartCollapse");
chartCollapse?.addEventListener("shown.bs.collapse", () => {
window.setTimeout(() => chart.resize(), 0);
});
clearLogButton.addEventListener("click", () => {
logTextarea.value = "";