Files
v2realbot/v2realbot/static/js/tables/archivetable/functions.js
2024-03-15 11:06:18 +01:00

597 lines
21 KiB
JavaScript

//funkce a promenne specificke pro archiveTable
//usually work with archiveRecords
//ARCHIVE TABLES
let editor_diff_arch1
let editor_diff_arch2
var archData = null
var batchHeaders = []
var editorLog = null
function refresh_arch_and_callback(row, callback) {
//console.log("entering refresh")
var request = $.ajax({
url: "/archived_runners/"+row.id,
beforeSend: function (xhr) {
xhr.setRequestHeader('X-API-Key',
API_KEY); },
method:"GET",
contentType: "application/json",
dataType: "json",
success:function(data){
//console.log("fetched data ok")
//console.log(JSON.stringify(data,null,2));
},
error: function(xhr, status, error) {
var err = eval("(" + xhr.responseText + ")");
window.alert(JSON.stringify(xhr));
console.log(JSON.stringify(xhr));
}
});
// Handling the responses of both requests
$.when(request).then(function(response) {
// Both requests have completed successfully
//console.log("Result from request:", response);
//console.log("Response received. calling callback")
//call callback function
callback(response)
}, function(error) {
// Handle errors from either request here
// Example:
console.error("Error from first request:", error);
console.log("requesting id error")
});
}
//triggers charting
function get_detail_and_chart(row) {
$.ajax({
url:"/archived_runners_detail/"+row.id,
beforeSend: function (xhr) {
xhr.setRequestHeader('X-API-Key',
API_KEY); },
method:"GET",
contentType: "application/json",
dataType: "json",
success:function(data){
$('#button_show_arch').attr('disabled',false);
$('#chartContainerInner').addClass("show");
//$("#lines").html("<pre>"+JSON.stringify(row.stratvars,null,2)+"</pre>")
//$('#chartArchive').append(JSON.stringify(data,null,2));
//console.log(JSON.stringify(data,null,2));
//if lower res is required call prepare_data otherwise call chart_archived_run()
//get other base resolutions
// console.log("received detail", data)
// data = JSON.parse(data)
// console.log("parsed detail", data)
prepare_data(row, 1, "Min", data)
},
error: function(xhr, status, error) {
var err = eval("(" + xhr.responseText + ")");
window.alert(JSON.stringify(xhr));
//console.log(JSON.stringify(xhr));
$('#button_show_arch').attr('disabled',false);
}
})
}
//rerun stratin (use to rerun strategy and also to rerun live/paper as bt on same period)
function run_day_again(turnintobt=false) {
row = archiveRecords.row('.selected').data();
var button_name = turnintobt ? '#button_runbt_arch' : '#button_runagain_arch'
$(button_name).attr('disabled',true)
var record1 = new Object()
//console.log(JSON.stringify(rows))
//record1 = JSON.parse(rows[0].strat_json)
//record1.json = rows[0].json
//TBD mozna zkopirovat jen urcite?
//getting required data (detail of the archived runner + stratin to be run)
var request1 = $.ajax({
url: "/archived_runners/"+row.id,
beforeSend: function (xhr) {
xhr.setRequestHeader('X-API-Key',
API_KEY); },
method:"GET",
contentType: "application/json",
dataType: "json",
success:function(data){
//console.log("fetched data ok")
//console.log(JSON.stringify(data,null,2));
},
error: function(xhr, status, error) {
var err = eval("(" + xhr.responseText + ")");
window.alert(JSON.stringify(xhr));
console.log(JSON.stringify(xhr));
}
});
//nalaodovat data pro strategii
var request2 = $.ajax({
url: "/stratins/"+row.strat_id,
beforeSend: function (xhr) {
xhr.setRequestHeader('X-API-Key',
API_KEY); },
method:"GET",
contentType: "application/json",
dataType: "json",
success:function(data){
//console.log("fetched data ok")
//console.log(JSON.stringify(data,null,2));
},
error: function(xhr, status, error) {
var err = eval("(" + xhr.responseText + ")");
window.alert(JSON.stringify(xhr));
console.log(JSON.stringify(xhr));
}
});
// Handling the responses of both requests
$.when(request1, request2).then(function(response1, response2) {
// Both requests have completed successfully
var result1 = response1[0];
var result2 = response2[0];
//console.log("Result from first request:", result1);
//console.log("Result from second request:", result2);
//console.log("calling compare")
rerun_strategy(result1, result2, turnintobt)
// Perform your action with the results from both requests
// Example:
}, function(error1, error2) {
// Handle errors from either request here
// Example:
console.error("Error from first request:", error1);
console.error("Error from second request:", error2);
});
function rerun_strategy(archRunner, stratData, turnintobt) {
record1 = archRunner
//console.log(record1)
var note_prefix = "RERUN "
if ((turnintobt) && ((record1.mode == 'live') || (record1.mode == 'paper'))) {
record1.mode = 'backtest'
record1.bt_from = record1.started
record1.bt_to = record1.stopped
note_prefix = "BT SAME PERIOD "
}
record1.note = note_prefix + record1.note
//nebudeme muset odstanovat pri kazdem pridani noveho atributu v budoucnu
//smazeneme nepotrebne a pridame potrebne
//do budoucna predelat na vytvoreni noveho objektu
delete record1["end_positions"];
delete record1["end_positions_avgp"];
delete record1["profit"];
delete record1["trade_count"];
delete record1["stratvars_toml"];
delete record1["started"];
delete record1["stopped"];
delete record1["metrics"];
delete record1["settings"];
delete record1["stratvars"];
if (record1.bt_from == "") {delete record1["bt_from"];}
if (record1.bt_to == "") {delete record1["bt_to"];}
//mazeme, pouze rerunujeme single
delete record1["test_batch_id"];
delete record1["batch_id"];
const rec = new Object()
rec.id2 = parseInt(stratData.id2);
rec.name = stratData.name;
rec.symbol = stratData.symbol;
rec.class_name = stratData.class_name;
rec.script = stratData.script;
rec.open_rush = stratData.open_rush;
rec.close_rush = stratData.close_rush;
rec.stratvars_conf = stratData.stratvars_conf;
rec.add_data_conf = stratData.add_data_conf;
rec.note = stratData.note;
rec.history = "";
strat_json = JSON.stringify(rec, null, 2);
record1.strat_json = strat_json
//zkopirujeme strat_id do id a smazeme strat_id
record1.id = record1.strat_id
delete record1["strat_id"];
//console.log("record1 pred odeslanim", record1)
jsonString = JSON.stringify(record1);
$.ajax({
url:"/stratins/"+record1.id+"/run",
beforeSend: function (xhr) {
xhr.setRequestHeader('X-API-Key',
API_KEY); },
method:"PUT",
contentType: "application/json",
data: jsonString,
success:function(data){
$(button_name).attr('disabled',false);
setTimeout(function () {
runnerRecords.ajax.reload();
stratinRecords.ajax.reload();
}, 1500);
},
error: function(xhr, status, error) {
var err = eval("(" + xhr.responseText + ")");
window.alert(JSON.stringify(xhr));
//console.log(JSON.stringify(xhr));
$(button_name).attr('disabled',false);
}
})
}
}
function expand_collapse_rows(event) {
event.stopPropagation()
var headerRow = $(this);
var name = headerRow.data('name');
var collapsed = headerRow.hasClass('collapsed');
// Toggle the expand icon name
var expandIcon = headerRow.find('.expand-icon');
if (collapsed) {
expandIcon.text('expand_less');
} else {
expandIcon.text('expand_more');
}
headerRow.toggleClass('collapsed');
archiveRecords.rows().every(function () {
var row = $(this.node());
var rowGroup = row.attr('data-group-name');
if (rowGroup == name) {
row.toggle();
}
});
// Save the state
if (collapsed) {
localStorage.setItem('dt-group-state-' + name, 'expanded');
} else {
localStorage.setItem('dt-group-state-' + name, 'collapsed');
}
}
function delete_batch(event){
event.preventDefault();
batch_id = $('#batch_id_del').val();
$('#deletebatch').attr('disabled', 'disabled');
$.ajax({
url:"/archived_runners/batch/"+batch_id,
beforeSend: function (xhr) {
xhr.setRequestHeader('X-API-Key',
API_KEY); },
method:"DELETE",
contentType: "application/json",
dataType: "json",
data: JSON.stringify(batch_id),
success:function(data){
$('#delFormBatch')[0].reset();
window.$('#delModalBatch').modal('hide');
$('#deletebatch').attr('disabled', false);
$('#button_delete_batch').attr('disabled', false);
//console.log(data)
archiveRecords.ajax.reload();
disable_arch_buttons();
},
error: function(xhr, status, error) {
var err = eval("(" + xhr.responseText + ")");
window.alert(JSON.stringify(xhr));
console.log(JSON.stringify(xhr));
$('#deletebatch').attr('disabled', false);
$('#button_delete_batch').attr('disabled', false);
archiveRecords.ajax.reload();
disable_arch_buttons();
}
})
}
function analyze_optimal_cutoff(batch_id = null) {
//definice parametru
param_obj = { rem_outliers:false, steps:50}
obj = {function: "analyze_optimal_cutoff", runner_ids:[], batch_id:null, params:param_obj}
//bereme bud selected runners
if (!batch_id) {
rows = archiveRecords.rows('.selected').data();
if (rows == undefined) {
return
}
$('#button_analyze').attr('disabled','disabled');
// Extract IDs from each row's data and store them in an array
obj.runner_ids = [];
for (var i = 0; i < rows.length; i++) {
obj.runner_ids.push(rows[i].id); // Assuming 'id' is the property that contains the row ID
}
}
//nebo batch
else {
obj.batch_id = batch_id
}
console.log("analyze cutoff objekt", obj)
// batch_id: Optional[str] = None
// runner_ids: Optional[List[UUID]] = None
// #additional parameter
// params: Optional[dict] = None
$.ajax({
url:"/batches/optimizecutoff/",
beforeSend: function (xhr) {
xhr.setRequestHeader('X-API-Key',
API_KEY); },
method:"POST",
xhrFields: {
responseType: 'blob'
},
xhr: function() {
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (xhr.readyState === 2) { // Headers have been received
if (xhr.status === 200) {
xhr.responseType = "blob"; // Set responseType to 'blob' for successful image responses
} else {
xhr.responseType = "text"; // Set responseType to 'text' for error messages
}
}
};
return xhr;
},
contentType: "application/json",
processData: false,
data: JSON.stringify(obj),
success:function(blob){
var url = window.URL || window.webkitURL;
console.log("vraceny obraz", blob)
console.log("url",url.createObjectURL(blob))
display_image(url.createObjectURL(blob))
if (!batch_id) {
$('#button_analyze').attr('disabled',false);
}
},
error: function(xhr, status, error) {
console.log("proc to skace do erroru?")
window.alert(JSON.stringify(xhr));
console.log(JSON.stringify(xhr));
$('#button_analyze').attr('disabled',false);
if (!batch_id) {
$('#button_analyze').attr('disabled',false);
}
}
})
}
//pomocna funkce, ktera vraci filtrovane radky tabulky (bud oznacene nebo batchove)
function get_selected_or_batch(batch_id = null) {
if (!batch_id) {
rows = archiveRecords.rows('.selected');
} else {
rows = archiveRecords.rows( function ( idx, data, node ) {
return data.batch_id == batch_id;
});
//console.log("batch rows",batch_id, rows)
}
return rows
}
//prepares export data, either for selected rows or based on batch_id
function prepare_export(batch_id = null) {
rows = get_selected_or_batch(batch_id)
var trdList = []
if(rows.data().length > 0 ) {
//console.log(rows.data())
// Loop through the selected rows and display an alert with each row's ID
rows.every(function (rowIdx, tableLoop, rowLoop ) {
var data = this.data()
data.metrics.prescr_trades.forEach((trade) => {
new_obj = {}
new_obj["entry_time"] = (trade.entry_time) ? new Date(trade.entry_time * 1000) : null
new_obj["entry_time"] = (new_obj["entry_time"]) ? new_obj["entry_time"].toLocaleString('cs-CZ', {
timeZone: 'America/New_York',
}) : null
new_obj["exit_time"] = (trade.exit_time) ? new Date(trade.exit_time * 1000):null
new_obj["exit_time"] = (new_obj["exit_time"]) ? new_obj["exit_time"].toLocaleString('cs-CZ', {
timeZone: 'America/New_York',
}) : null
new_obj["direction"] = trade.direction
new_obj["profit"] = trade.profit
new_obj["rel_profit"] = trade.rel_profit
trdList.push(new_obj)
})
});
}
return trdList
}
function download_exported_data(type, batch_id = null) {
filename = batch_id ? "batch"+batch_id+"-trades" : "trades"
if (type == "xml") {
response_type = "application/xml"
output = convertToXml(prepare_export(batch_id))
}
else {
response_type = "text/csv"
output = convertToCsv(prepare_export(batch_id))
}
console.log(output)
downloadFile(response_type,type, filename, output)
}
function display_image(imageUrl) {
// Attempt to load the image
var img = new Image();
img.src = imageUrl;
img.onload = function() {
// If the image loads successfully, display it
$('#previewImg').attr('src', imageUrl);
//$('#imagePreview').show();
window.$('#imageModal').modal('show');
};
img.onerror = function(e) {
console.log("Image load error", e);
console.log("Image object:", img);
console.log("no image available")
// If the image fails to load, do nothing
};
}
function display_batch_report(batch_id) {
//var imageUrl = '/media/report_'+data.id+".png"; // Replace with your logic to get image URL
var imageUrl = '/media/basic/'+batch_id+'.png'; // Replace with your logic to get image URL
//console.log(imageUrl)
display_image(imageUrl)
}
function refresh_logfile() {
logfile = $("#logFileSelect").val()
lines = 1200
$.ajax({
url:"/log?lines="+lines+"&logfile="+logfile,
beforeSend: function (xhr) {
xhr.setRequestHeader('X-API-Key',
API_KEY); },
method:"GET",
contentType: "application/json",
dataType: "json",
success:function(response){
if (editorLog) {
editorLog.dispose();
}
if (response.lines.length == 0) {
value = "no records";
// $('#log-content').html("no records");
}
else {
//console.log(response.lines)
//var escapedLines = response.lines.map(line => escapeHtml(line));
value = response.lines.join('\n')
// $('#log-content').html(escapedLines.join('\n'));
}
require(["vs/editor/editor.main"], () => {
editorLog = monaco.editor.create(document.getElementById('log-container'), {
value: value,
language: 'mylogs',
theme: 'tomlTheme-dark',
automaticLayout: true,
readOnly: true
});
});
},
error: function(xhr, status, error) {
var err = eval("(" + xhr.responseText + ")");
window.alert(JSON.stringify(xhr));
}
})
}
function escapeHtml(text) {
return text
.replace(/&/g, "&amp;")
.replace(/</g, "&lt;")
.replace(/>/g, "&gt;")
.replace(/"/g, "&quot;")
.replace(/'/g, "&#039;");
}
function delete_arch_rows(ids) {
$.ajax({
url:"/archived_runners/",
beforeSend: function (xhr) {
xhr.setRequestHeader('X-API-Key',
API_KEY); },
method:"DELETE",
contentType: "application/json",
dataType: "json",
data: JSON.stringify(ids),
success:function(data){
$('#delFormArchive')[0].reset();
window.$('#delModalArchive').modal('hide');
$('#deletearchive').attr('disabled', false);
//console.log(data)
archiveRecords.ajax.reload();
disable_arch_buttons()
},
error: function(xhr, status, error) {
var err = eval("(" + xhr.responseText + ")");
window.alert(JSON.stringify(xhr));
console.log(JSON.stringify(xhr));
$('#deletearchive').attr('disabled', false);
//archiveRecords.ajax.reload();
}
})
}
function extractNumbersFromString(str) {
// Regular expression to match the pattern #number1/number2
const pattern = /#(\d+)\/(\d+)/;
const match = str.match(pattern);
if (match) {
// Extract number1 and number2 from the match
const number1 = parseInt(match[1], 10);
const number2 = parseInt(match[2], 10);
//return { number1, number2 };
return number2;
} else {
return null;
}
}
// Function to generate a unique key for localStorage based on batch_id
function generateStorageKey(batchId) {
return 'dt-group-state-' + batchId;
}
function disable_arch_buttons() {
//disable buttons (enable on row selection)
$('#button_runagain_arch').attr('disabled','disabled');
$('#button_runbt_arch').attr('disabled','disabled');
$('#button_show_arch').attr('disabled','disabled');
$('#button_delete_arch').attr('disabled','disabled');
$('#button_delete_batch').attr('disabled','disabled');
$('#button_analyze').attr('disabled','disabled');
$('#button_edit_arch').attr('disabled','disabled');
$('#button_compare_arch').attr('disabled','disabled');
$('#button_report').attr('disabled','disabled');
$('#button_export_xml').attr('disabled','disabled');
$('#button_export_csv').attr('disabled','disabled');
}
function enable_arch_buttons() {
$('#button_analyze').attr('disabled',false);
$('#button_show_arch').attr('disabled',false);
$('#button_runagain_arch').attr('disabled',false);
$('#button_delete_arch').attr('disabled',false);
$('#button_delete_batch').attr('disabled',false);
$('#button_edit_arch').attr('disabled',false);
$('#button_compare_arch').attr('disabled',false);
$('#button_report').attr('disabled',false);
$('#button_export_xml').attr('disabled',false);
$('#button_export_csv').attr('disabled',false);
//Backtest same period button is displayed only when row with mode paper/live is selected
row = archiveRecords.row('.selected').data();
if ((row.mode == 'paper') || (row.mode == 'live')) {
$('#button_runbt_arch').attr('disabled',false);
}
}