Team Ai
Apppublic

blackopsrepl/portfolio-optimization-python

sourceHugging Faceapache-2.0updated 10mo agoView on Hugging Face
1likes
config.js184 linesDownload Raw Back to static
1/**
2 * Advanced Configuration Module
3 *
4 * This module provides advanced configuration options for the portfolio optimization
5 * quickstart, including presets and configurable solver parameters.
6 *
7 * NOTE: This is an optional enhancement. The core quickstart works without this module.
8 * To use it, include this script after app.js and call initAdvancedConfig().
9 */
10
11// =============================================================================
12// Configuration Presets
13// =============================================================================
14
15const PRESETS = {
16    conservative: {
17        targetStocks: 30,
18        maxSector: 15,
19        solverTime: 60,
20        description: "Max diversification: 30 stocks, tight sector limits, longer solve time."
21    },
22    balanced: {
23        targetStocks: 20,
24        maxSector: 25,
25        solverTime: 30,
26        description: "Balanced settings for typical portfolio optimization."
27    },
28    aggressive: {
29        targetStocks: 10,
30        maxSector: 40,
31        solverTime: 30,
32        description: "Concentrated bets: fewer stocks, looser sector limits."
33    },
34    quick: {
35        targetStocks: 20,
36        maxSector: 25,
37        solverTime: 10,
38        description: "Fast iteration: same as balanced but 10s solve time."
39    }
40};
41
42// Current configuration state
43let currentConfig = { ...PRESETS.balanced };
44
45// =============================================================================
46// Initialization
47// =============================================================================
48
49/**
50 * Initialize advanced configuration UI and event handlers.
51 * Call this after the DOM is ready.
52 */
53function initAdvancedConfig() {
54    // Preset selector
55    $("#presetSelector").change(function() {
56        const preset = $(this).val();
57        if (preset !== "custom" && PRESETS[preset]) {
58            // Use Object.assign to mutate in place - preserves window.currentConfig reference
59            Object.assign(currentConfig, PRESETS[preset]);
60            updateConfigSliders();
61            updatePresetDescription(preset);
62            applyConfigToLoadedPlan();
63        }
64    });
65
66    // Target stocks slider
67    $("#targetStocksSlider").on("input", function() {
68        currentConfig.targetStocks = parseInt(this.value);
69        $("#targetStocksValue").text(this.value);
70        markAsCustom();
71        applyConfigToLoadedPlan();
72    });
73
74    // Max sector slider
75    $("#maxSectorSlider").on("input", function() {
76        currentConfig.maxSector = parseInt(this.value);
77        $("#maxSectorValue").text(this.value + "%");
78        markAsCustom();
79        applyConfigToLoadedPlan();
80    });
81
82    // Solver time slider
83    $("#solverTimeSlider").on("input", function() {
84        currentConfig.solverTime = parseInt(this.value);
85        $("#solverTimeValue").text(formatSolverTime(this.value));
86        markAsCustom();
87        applyConfigToLoadedPlan();
88    });
89}
90
91// =============================================================================
92// Configuration UI Updates
93// =============================================================================
94
95function updateConfigSliders() {
96    $("#targetStocksSlider").val(currentConfig.targetStocks);
97    $("#targetStocksValue").text(currentConfig.targetStocks);
98
99    $("#maxSectorSlider").val(currentConfig.maxSector);
100    $("#maxSectorValue").text(currentConfig.maxSector + "%");
101
102    $("#solverTimeSlider").val(currentConfig.solverTime);
103    $("#solverTimeValue").text(formatSolverTime(currentConfig.solverTime));
104}
105
106function formatSolverTime(seconds) {
107    if (seconds >= 60) {
108        const mins = Math.floor(seconds / 60);
109        const secs = seconds % 60;
110        return secs > 0 ? `${mins}m ${secs}s` : `${mins}m`;
111    }
112    return `${seconds}s`;
113}
114
115function markAsCustom() {
116    // Check if current settings match any preset
117    for (const [name, preset] of Object.entries(PRESETS)) {
118        if (preset.targetStocks === currentConfig.targetStocks &&
119            preset.maxSector === currentConfig.maxSector &&
120            preset.solverTime === currentConfig.solverTime) {
121            $("#presetSelector").val(name);
122            updatePresetDescription(name);
123            return;
124        }
125    }
126    // No match - mark as custom
127    $("#presetSelector").val("custom");
128    updatePresetDescription("custom");
129}
130
131function updatePresetDescription(preset) {
132    const descriptions = {
133        conservative: PRESETS.conservative.description,
134        balanced: PRESETS.balanced.description,
135        aggressive: PRESETS.aggressive.description,
136        quick: PRESETS.quick.description,
137        custom: "Custom configuration. Adjust sliders to your needs."
138    };
139    $("#presetDescription").text(descriptions[preset] || descriptions.custom);
140}
141
142// =============================================================================
143// Apply Configuration to Plan
144// =============================================================================
145
146/**
147 * Apply current configuration to the loaded plan.
148 * This updates the plan object that will be sent to the solver.
149 */
150function applyConfigToLoadedPlan() {
151    // loadedPlan is defined in app.js
152    if (typeof loadedPlan !== 'undefined' && loadedPlan) {
153        loadedPlan.targetPositionCount = currentConfig.targetStocks;
154        loadedPlan.maxSectorPercentage = currentConfig.maxSector / 100;
155        loadedPlan.solverConfig = {
156            terminationSeconds: currentConfig.solverTime
157        };
158    }
159}
160
161/**
162 * Get the current configuration.
163 * @returns {Object} Current configuration with targetStocks, maxSector, solverTime
164 */
165function getCurrentConfig() {
166    return { ...currentConfig };
167}
168
169/**
170 * Get target stock count from current configuration.
171 * Used by app.js for KPI display.
172 */
173function getTargetStockCount() {
174    return currentConfig.targetStocks;
175}
176
177// Export for use in app.js
178window.PRESETS = PRESETS;
179window.currentConfig = currentConfig;
180window.initAdvancedConfig = initAdvancedConfig;
181window.applyConfigToLoadedPlan = applyConfigToLoadedPlan;
182window.getCurrentConfig = getCurrentConfig;
183window.getTargetStockCount = getTargetStockCount;
184