travail avec le contenu des backtests et amélioration graphs avec puces

This commit is contained in:
Jérôme Delacotte
2025-05-08 19:22:48 +02:00
parent e3e8c691f8
commit e34897e154
3 changed files with 324 additions and 43 deletions

View File

@@ -10,22 +10,32 @@ function loadJson(filename) {
const isMulti = typeof data === 'object' && !Array.isArray(data);
if (isMulti) {
let count = 0
Object.entries(data).forEach(([name, content], index) => {
const tabId = `tab-${index}`;
const li = document.createElement('li');
const btn = document.createElement('button');
btn.textContent = name;
btn.onclick = () => showTab(tabId);
li.appendChild(btn);
tabButtons.appendChild(li);
count = count + 1
if (name.includes("signals")) {
sessionStorage.setItem('signals', content);
addTab('signals', count, content)
}
if (name.includes("exited")) {
sessionStorage.setItem('exited', content);
addTab('exited', count, content)
}
if (name.includes("json")) {
sessionStorage.setItem('result_strategy', JSON.stringify(content.strategy));
sessionStorage.setItem('strategy_comparison', JSON.stringify(content.strategy_comparison));
addTab('result', count, JSON.stringify(content.strategy))
count = count + 1
addTab('comparaison', count, JSON.stringify(content.strategy_comparison))
}
if (name.includes("market")) {
sessionStorage.setItem('market', content);
addTab('market', count, content)
}
const div = document.createElement('div');
div.id = tabId;
div.className = 'tab-content';
div.style.display = index === 0 ? 'block' : 'none';
div.innerHTML = Array.isArray(content) ? renderTable(content) : `<pre>${JSON.stringify(content, null, 2)}</pre>`;
tabContents.appendChild(div);
});
// renderChart(data, '', true)
} else {
const div = document.createElement('div');
div.innerHTML = `<pre>${JSON.stringify(data, null, 2)}</pre>`;
@@ -35,6 +45,152 @@ function loadJson(filename) {
.catch(err => alert("Erreur : " + err.message));
}
function jsonToUl(json) {
if (typeof json !== 'object' || json === null) return document.createTextNode(json);
const ul = document.createElement('ul');
for (const key in json) {
const li = document.createElement('li');
const value = json[key];
if (typeof value === 'object' && value !== null) {
li.textContent = key;
li.appendChild(jsonToUl(value)); // recurse
} else {
li.textContent = `${key}: ${value}`;
}
ul.appendChild(li);
}
return ul;
}
//function jsonToTable(obj, depth = 0) {
// const table = document.createElement('table');
// table.border = 1;
//
// for (const key in obj) {
// const row = document.createElement('tr');
//
// const cellKey = document.createElement('td');
// cellKey.textContent = key;
// row.appendChild(cellKey);
//
// const cellValue = document.createElement('td');
// const value = obj[key];
//
// if (typeof value === 'object' && value !== null && depth < 4) {
// cellValue.appendChild(jsonToTable(value, depth + 1)); // recurse
// } else {
// cellValue.textContent = value;
// }
//
// row.appendChild(cellValue);
// table.appendChild(row);
// }
//
// return table;
//}
function jsonToTable(data, depth = 0) {
if (Array.isArray(data)) {
// Cas: tableau d'objets
if (data.length > 0 && typeof data[0] === 'object' && !Array.isArray(data[0])) {
const table = document.createElement('table');
table.border = 1;
// En-tête
const headerRow = document.createElement('tr');
Object.keys(data[0]).forEach(key => {
const th = document.createElement('th');
th.textContent = key;
headerRow.appendChild(th);
});
table.appendChild(headerRow);
// Lignes de données
data.forEach(item => {
const row = document.createElement('tr');
Object.values(item).forEach(value => {
const td = document.createElement('td');
td.textContent = (typeof value === 'object') ? JSON.stringify(value) : value;
row.appendChild(td);
});
table.appendChild(row);
});
return table;
} else {
// Liste simple : afficher horizontalement
const table = document.createElement('table');
table.border = 1;
const row = document.createElement('tr');
data.forEach(value => {
const td = document.createElement('td');
td.textContent = value;
row.appendChild(td);
});
table.appendChild(row);
return table;
}
} else if (typeof data === 'object' && data !== null) {
// Cas: objet clé/valeur
const table = document.createElement('table');
table.border = 1;
for (const key in data) {
const row = document.createElement('tr');
const tdKey = document.createElement('td');
tdKey.textContent = key;
row.appendChild(tdKey);
const tdValue = document.createElement('td');
const value = data[key];
if (typeof value === 'object') {
tdValue.appendChild(jsonToTable(value, depth + 1));
} else {
tdValue.textContent = value;
}
row.appendChild(tdValue);
table.appendChild(row);
}
return table;
} else {
const span = document.createElement('span');
span.textContent = data;
return span;
}
}
function addTab(name, index, content) {
const tabButtons = document.getElementById('tab-buttons');
const tabContents = document.getElementById('tab-contents');
const tabId = `tab-${index}`;
const li = document.createElement('li');
const btn = document.createElement('button');
btn.textContent = name;
btn.onclick = () => showTab(tabId);
li.appendChild(btn);
tabButtons.appendChild(li);
const div = document.createElement('div');
div.id = tabId;
div.className = 'tab-content';
div.style.display = index === 0 ? 'block' : 'none';
// div.innerHTML = Array.isArray(content) ? renderTable(content) : jsonToUl(JSON.parse(content));
ul = jsonToTable(JSON.parse(content))
div.appendChild(ul);
tabContents.appendChild(div);
}
function renderTable(rows) {
if (!rows.length) return "<p>Aucune donnée</p>";
const headers = Object.keys(rows[0]);
@@ -88,6 +244,15 @@ function renderChart(data, filename, create_columns) {
// let rows = data.map(row => '<tr>' + Object.values(row).map(v => `<td>${v}</td>`).join('') + '</tr>');
// table.innerHTML = header + rows.join('');
// }
let signals = JSON.parse(sessionStorage.getItem("signals"));
let exited = JSON.parse(sessionStorage.getItem("exited"));
let market = JSON.parse(sessionStorage.getItem("market"));
let result_strategy = JSON.parse(sessionStorage.getItem("result_strategy"));
let strategy_comparison = JSON.parse(sessionStorage.getItem("strategy_comparison"));
strategy_name = strategy_comparison[0].key;
result_of_strategy = result_strategy[strategy_name]
const cols = Object.keys(data[0])
if (create_columns === true) {
// string = "<ul class='indicators'>" + Object.keys(data[0]).map(cols => `<li><label><input id="${cols}" type="checkbox" value="${cols}" onchange="toggleIndicator(this)">${cols}</label></li>`).join('') + "</ul>"
@@ -102,7 +267,6 @@ function renderChart(data, filename, create_columns) {
indicators.innerHTML = string
}
// const label = document.createElement('label');
// label.innerHTML = `<input type="checkbox" value="${col}"> ${col}<br>`;
// indicators.appendChild(label);
@@ -139,6 +303,68 @@ function renderChart(data, filename, create_columns) {
// df_ohlc = data[['date', 'open', 'close', 'low', 'high']]
const result = data.map(({ open, close, low, high }) => [open, close, low, high]);
marks = []
const options = {
year: 'numeric',
month: '2-digit',
day: '2-digit',
hour: '2-digit',
minute: '2-digit',
second: '2-digit'
}
for (var key in result_of_strategy.trades) {
var d = result_of_strategy.trades[key];
var date = new Date(d.open_date);
marks.push({
name: 'Buy',
coord: [date.toLocaleString('fr-FR', options), d.open_rate],
value: d.open_rate,
itemStyle: {
color: 'rgb(0,90,0)'
}
})
for (var key2 in d.orders) {
var order = d.orders[key2]
date = new Date(order.order_filled_timestamp);
marks.push({
name: 'Buy',
coord: [date.toLocaleString('fr-FR', options), order.safe_price],
value: order.safe_price,
itemStyle: {
color: 'rgb(0,0,90)'
}
})
}
date = new Date(d.close_date);
marks.push({
name: 'Sell',
coord: [date.toLocaleString('fr-FR', options), d.close_rate],
value: d.close_rate,
itemStyle: {
color: 'rgb(90,0,0)'
}
})
// {
// name: 'highest value',
// type: 'max',
// valueDim: 'highest'
// },
// {
// name: 'lowest value',
// type: 'min',
// valueDim: 'lowest'
// },
// {
// name: 'average value on close',
// type: 'average',
// valueDim: 'close'
// }
}
series.push({
type: 'candlestick',
data: result,
@@ -147,10 +373,22 @@ function renderChart(data, filename, create_columns) {
color0: '#00da3c', // bougie baissière
borderColor: '#8A0000',
borderColor0: '#008F28'
},
markPoint: {
label: {
formatter: function (param) {
return param != null ? Math.round(param.value) + '' : '';
}
},
data: marks,
tooltip: {
formatter: function (param) {
return param.name + '<br>' + (param.data.coord || '');
}
}
}
}
)
// console.log(result)
series.push({
name: 'Volume',
@@ -167,6 +405,7 @@ function renderChart(data, filename, create_columns) {
},
data: data.map(d => d.volume)
})
for (var key in cols) {
var value = cols[key];
element=document.getElementById(value)
@@ -182,6 +421,7 @@ function renderChart(data, filename, create_columns) {
}
}
}
var option = {
title: {
text: filename
@@ -208,7 +448,7 @@ function renderChart(data, filename, create_columns) {
}
}
},
dataZoom: [
dataZoom: [
{
type: 'slider', // slider visible en bas
start: startPercent,
@@ -224,20 +464,20 @@ function renderChart(data, filename, create_columns) {
data: cols, // Affiche les noms de chaque série avec leur couleur
},
xAxis: [{
type: 'category',
data: data.map(d => {
const date = new Date(d.date);
return date.toLocaleDateString('fr-FR'); // ex : 07/05/2025
})
},
{
type: 'category',
data: data.map(d => {
const date = new Date(d.date);
return date.toLocaleDateString('fr-FR'); // ex : 07/05/2025
}),
gridIndex: 1
}
type: 'category',
data: data.map(d => {
const date = new Date(d.date);
return date.toLocaleString('fr-FR', options); // ex : 07/05/2025
})
},
{
type: 'category',
data: data.map(d => {
const date = new Date(d.date);
return date.toLocaleString('fr-FR', options); // ex : 07/05/2025
}),
gridIndex: 1
}
],
yAxis: [{
type: 'value',
@@ -312,3 +552,13 @@ function stringToColor(str) {
return `hsl(${hue}, 70%, 50%)`;
}
function init() {
const dialog = document.getElementById('indicatorDialog');
document.getElementById('openIndicatorsBtn').addEventListener('click', () => {
dialog.showModal();
});
document.getElementById('closeIndicatorsBtn').addEventListener('click', () => {
dialog.close();
});
}