| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| |
|
| |
|
| |
|
| |
|
| |
|
| | const PRESETS = {
|
| | conservative: {
|
| | targetStocks: 30,
|
| | maxSector: 15,
|
| | solverTime: 60,
|
| | description: "Max diversification: 30 stocks, tight sector limits, longer solve time."
|
| | },
|
| | balanced: {
|
| | targetStocks: 20,
|
| | maxSector: 25,
|
| | solverTime: 30,
|
| | description: "Balanced settings for typical portfolio optimization."
|
| | },
|
| | aggressive: {
|
| | targetStocks: 10,
|
| | maxSector: 40,
|
| | solverTime: 30,
|
| | description: "Concentrated bets: fewer stocks, looser sector limits."
|
| | },
|
| | quick: {
|
| | targetStocks: 20,
|
| | maxSector: 25,
|
| | solverTime: 10,
|
| | description: "Fast iteration: same as balanced but 10s solve time."
|
| | }
|
| | };
|
| |
|
| |
|
| | let currentConfig = { ...PRESETS.balanced };
|
| |
|
| |
|
| |
|
| |
|
| |
|
| | |
| | |
| | |
| |
|
| | function initAdvancedConfig() {
|
| |
|
| | $("#presetSelector").change(function() {
|
| | const preset = $(this).val();
|
| | if (preset !== "custom" && PRESETS[preset]) {
|
| |
|
| | Object.assign(currentConfig, PRESETS[preset]);
|
| | updateConfigSliders();
|
| | updatePresetDescription(preset);
|
| | applyConfigToLoadedPlan();
|
| | }
|
| | });
|
| |
|
| |
|
| | $("#targetStocksSlider").on("input", function() {
|
| | currentConfig.targetStocks = parseInt(this.value);
|
| | $("#targetStocksValue").text(this.value);
|
| | markAsCustom();
|
| | applyConfigToLoadedPlan();
|
| | });
|
| |
|
| |
|
| | $("#maxSectorSlider").on("input", function() {
|
| | currentConfig.maxSector = parseInt(this.value);
|
| | $("#maxSectorValue").text(this.value + "%");
|
| | markAsCustom();
|
| | applyConfigToLoadedPlan();
|
| | });
|
| |
|
| |
|
| | $("#solverTimeSlider").on("input", function() {
|
| | currentConfig.solverTime = parseInt(this.value);
|
| | $("#solverTimeValue").text(formatSolverTime(this.value));
|
| | markAsCustom();
|
| | applyConfigToLoadedPlan();
|
| | });
|
| | }
|
| |
|
| |
|
| |
|
| |
|
| |
|
| | function updateConfigSliders() {
|
| | $("#targetStocksSlider").val(currentConfig.targetStocks);
|
| | $("#targetStocksValue").text(currentConfig.targetStocks);
|
| |
|
| | $("#maxSectorSlider").val(currentConfig.maxSector);
|
| | $("#maxSectorValue").text(currentConfig.maxSector + "%");
|
| |
|
| | $("#solverTimeSlider").val(currentConfig.solverTime);
|
| | $("#solverTimeValue").text(formatSolverTime(currentConfig.solverTime));
|
| | }
|
| |
|
| | function formatSolverTime(seconds) {
|
| | if (seconds >= 60) {
|
| | const mins = Math.floor(seconds / 60);
|
| | const secs = seconds % 60;
|
| | return secs > 0 ? `${mins}m ${secs}s` : `${mins}m`;
|
| | }
|
| | return `${seconds}s`;
|
| | }
|
| |
|
| | function markAsCustom() {
|
| |
|
| | for (const [name, preset] of Object.entries(PRESETS)) {
|
| | if (preset.targetStocks === currentConfig.targetStocks &&
|
| | preset.maxSector === currentConfig.maxSector &&
|
| | preset.solverTime === currentConfig.solverTime) {
|
| | $("#presetSelector").val(name);
|
| | updatePresetDescription(name);
|
| | return;
|
| | }
|
| | }
|
| |
|
| | $("#presetSelector").val("custom");
|
| | updatePresetDescription("custom");
|
| | }
|
| |
|
| | function updatePresetDescription(preset) {
|
| | const descriptions = {
|
| | conservative: PRESETS.conservative.description,
|
| | balanced: PRESETS.balanced.description,
|
| | aggressive: PRESETS.aggressive.description,
|
| | quick: PRESETS.quick.description,
|
| | custom: "Custom configuration. Adjust sliders to your needs."
|
| | };
|
| | $("#presetDescription").text(descriptions[preset] || descriptions.custom);
|
| | }
|
| |
|
| |
|
| |
|
| |
|
| |
|
| | |
| | |
| | |
| |
|
| | function applyConfigToLoadedPlan() {
|
| |
|
| | if (typeof loadedPlan !== 'undefined' && loadedPlan) {
|
| | loadedPlan.targetPositionCount = currentConfig.targetStocks;
|
| | loadedPlan.maxSectorPercentage = currentConfig.maxSector / 100;
|
| | loadedPlan.solverConfig = {
|
| | terminationSeconds: currentConfig.solverTime
|
| | };
|
| | }
|
| | }
|
| |
|
| | |
| | |
| | |
| |
|
| | function getCurrentConfig() {
|
| | return { ...currentConfig };
|
| | }
|
| |
|
| | |
| | |
| | |
| |
|
| | function getTargetStockCount() {
|
| | return currentConfig.targetStocks;
|
| | }
|
| |
|
| |
|
| | window.PRESETS = PRESETS;
|
| | window.currentConfig = currentConfig;
|
| | window.initAdvancedConfig = initAdvancedConfig;
|
| | window.applyConfigToLoadedPlan = applyConfigToLoadedPlan;
|
| | window.getCurrentConfig = getCurrentConfig;
|
| | window.getTargetStockCount = getTargetStockCount;
|
| |
|