Adaptive AI Hedge Fund Replication Strategy (Simulator)
Strategy Definition
Factors ("AI Signals") & Assets
Factor Definition
Asset Definition (Portfolio Components)
Adaptive Rule Builder (IF-THEN for Allocation Changes)
Rules determine target asset allocations based on factor conditions. The sum of target allocations in a rule's actions should be 100%.
Initial Allocation & Rebalancing Rules
Initial Target Asset Allocation (%)
Set the starting allocation for your portfolio. Must sum to 100%.
Total Initial Allocation: 0%
Rebalancing Rules
Simulation Data Input (Market & Factor Steps)
For each simulation step, provide observed factor values and the performance change (%) for each asset.
Simulation Results
Performance summary will appear here after running the simulation.
Portfolio Value Over Time ($)
| Step | Factor Values | Rule Triggered | Old Alloc. (%) | New Alloc. (%) | Asset Perf. (%) | Step P&L ($) | Portfolio Value ($) |
|---|
Total Net P&L: $${totalReturn.toFixed(2)}
Total Return: ${totalReturnPercent.toFixed(2)}%
`; aahfrs_renderPortfolioChart(portfolioValueHistory); if (document.getElementById('aahfrs_downloadPdfButton')) document.getElementById('aahfrs_downloadPdfButton').style.display = 'block'; } function aahfrs_renderPortfolioChart(data) { const chartContainer = aahfrs_getEl('aahfrs_portfolioValueChart'); const containerEl = aahfrs_getEl('aahfrs_portfolioValueChartContainer'); if (!chartContainer || !containerEl) return; chartContainer.innerHTML = ''; containerEl.style.display = data.length > 1 ? 'block' : 'none'; const maxValue = Math.max(...data); const minValue = Math.min(...data); // Could be used for scaling from non-zero base data.forEach((value, index) => { const bar = document.createElement('div'); bar.className = 'aahfrs_chart_bar'; // Scale height relative to max value and container height const barHeight = maxValue > 0 ? (value / maxValue) * 100 : 0; bar.style.height = `${Math.max(0, barHeight)}%`; // Ensure non-negative height const valueLabel = document.createElement('div'); valueLabel.className = 'aahfrs_chart_bar_value'; valueLabel.textContent = Math.round(value).toLocaleString(); if (barHeight < 15) valueLabel.style.top = '-15px'; // Adjust label if bar is too short const stepLabel = document.createElement('div'); stepLabel.className = 'aahfrs_chart_bar_label'; stepLabel.textContent = `S${index}`; // S0 for initial bar.appendChild(valueLabel); bar.appendChild(stepLabel); chartContainer.appendChild(bar); }); } function aahfrs_collectModelInputs() { aahfrs_model.strategyName = aahfrs_getInputValue('aahfrs_strategyName', 'Unnamed Strategy'); aahfrs_model.archetype = aahfrs_getInputValue('aahfrs_archetype', 'general_adaptive'); aahfrs_model.initialCapital = aahfrs_getInputNumValue('aahfrs_initialCapital', 100000); aahfrs_model.transactionFeePercent = aahfrs_getInputNumValue('aahfrs_transactionFee', 0.05); aahfrs_model.rebalance.trigger = aahfrs_getInputValue('aahfrs_rebalanceTrigger', 'none'); aahfrs_model.rebalance.thresholdValue = aahfrs_getInputNumValue('aahfrs_rebalanceThresholdValue', 5); // Initial allocations are already in aahfrs_model.initialAllocationSet from their own update function // Factors, Assets, Rules, SimData are also updated directly into the model object } // --- PDF Generation --- function aahfrs_downloadPDF() { if (aahfrs_simulationLog.length === 0) { alert("Please run a simulation first to generate results for PDF."); return; } if (typeof window.jspdf === 'undefined' || typeof window.jspdf.jsPDF === 'undefined') { alert('PDF library (jsPDF) is not loaded.'); return; } const { jsPDF: JSPDF } = window.jspdf; const doc = new JSPDF(); let y = 15; const m = 15; const cw = doc.internal.pageSize.getWidth() - (2 * m); aahfrs_collectModelInputs(); // Ensure model is up-to-date function addLine(text, size, style = 'normal', indent = 0, spacing = 2.5) { if (y > 275) { doc.addPage(); y = m; } doc.setFontSize(size); doc.setFont(undefined, style); const lines = doc.splitTextToSize(text, cw - indent); doc.text(lines, m + indent, y); y += (lines.length * (size * 0.35)) + spacing; } addLine(`Adaptive Strategy: ${aahfrs_model.strategyName}`, 18, 'bold', 0, 5); addLine(`Archetype: ${aahfrs_model.archetype}, Initial Capital: $${aahfrs_model.initialCapital.toFixed(2)}`, 10); addLine(`Transaction Fee: ${aahfrs_model.transactionFeePercent}%`, 10, 'normal', 0, 6); addLine("Factors:", 14, 'bold'); aahfrs_model.factors.forEach(f => addLine(`- ${f.name}: ${f.type} ${f.type==='numerical' ? `(${f.scaleMin}-${f.scaleMax})` : `(${(f.categories||[]).join('/')})`}`, 9, 'normal', 5)); y+=3; addLine("Assets:", 14, 'bold'); aahfrs_model.assets.forEach(a => addLine(`- ${a.name}`, 9, 'normal', 5)); y+=3; addLine("Initial Allocation:", 14, 'bold'); for(const assetId in aahfrs_model.initialAllocationSet){ const asset = aahfrs_model.assets.find(a => a.id === assetId); if(asset) addLine(`- ${asset.name}: ${aahfrs_model.initialAllocationSet[assetId]}%`, 9, 'normal', 5); } y+=3; addLine(`Rebalancing: ${aahfrs_model.rebalance.trigger}, Threshold: ${aahfrs_model.rebalance.thresholdValue}${aahfrs_model.rebalance.trigger === 'deviation' ? '%' : (aahfrs_model.rebalance.trigger === 'periodic' ? ' steps' : '')}`, 10); y+=3; addLine("Adaptive Rules:", 14, 'bold'); aahfrs_model.rules.forEach((r, i) => { addLine(`Rule ${i+1}:`, 10, 'bold', 5); r.conditions.forEach(c => { const fDef = aahfrs_model.factors.find(f => f.id === c.factorId); addLine(` IF ${fDef ? fDef.name : c.factorId} ${c.operator} ${c.value}`, 9, 'normal', 10, 1); }); addLine(` THEN set allocations:`, 9, 'normal', 10, 1); r.actions.forEach(act => { const aDef = aahfrs_model.assets.find(a => a.id === act.assetId); addLine(` ${aDef ? aDef.name : act.assetId}: ${act.targetPercentage}%`, 9, 'normal', 15, 1); }); y+=1; }); y+=5; addLine("Simulation Results:", 16, 'bold', 0, 5); const summaryText = aahfrs_getEl('aahfrs_simulationSummary').innerText; addLine(summaryText.replace(/(\$NaN|NaN%)/g, '$0.00 (Error?)'), 10); y+=3; addLine("Simulation Log:", 14, 'bold'); aahfrs_simulationLog.forEach(log => { if (y > 270) { doc.addPage(); y = m; } let logLine = `Step ${log.step}: Factors (${log.factorValues.substring(0,30)}...), Rule: ${log.ruleTriggered}, P&L: $${log.stepPnl}, Value: $${log.portfolioValue}`; addLine(logLine, 7, 'normal', 0, 0.5); }); doc.save(`${aahfrs_model.strategyName.replace(/\s+/g, '_') || 'adaptive_strategy_sim'}.pdf`); }