Reinforcement Learning-Based Trading Model (Simulator)

Environment Setup

Define States & Actions

State Variables (What the "Agent" Observes)

Actions (What the "Agent" Can Do)

Strategy Rule Builder (Simulated Policy IF-THEN)

Define rules that map observed states to actions. The "Reward" is conceptual and tied to P&L minus fees during simulation.

Simulation Data Input (Mock Market Steps)

For each step, provide the observed state values and the percentage price change for P&L calculation.

Simulation Results

Summary of performance will appear here after running the simulation.

Step State(s) Action Price Change % Trade P&L ($) Reward ($) Balance ($) Position

Initial Capital: $${rlbtm_model.initialCapital.toFixed(2)}

Final Capital: $${currentCapital.toFixed(2)}

Total Net P&L: $${totalPnl.toFixed(2)} (${profitFactor.toFixed(2)}%)

Total Conceptual Reward: $${totalReward.toFixed(2)}

`; const pdfButton = document.getElementById('rlbtm_downloadPdfButton'); if (pdfButton) pdfButton.style.display = rlbtm_simulationLog.length > 0 ? 'block' : 'none'; } function rlbtm_calculateFee(transactionAmount) { if (rlbtm_model.feeType === 'percentage') { return transactionAmount * (rlbtm_model.feeValue / 100); } else if (rlbtm_model.feeType === 'fixed') { return rlbtm_model.feeValue; } return 0; } function rlbtm_collectModelInputs() { // Call before simulation or PDF rlbtm_model.name = rlbtm_getInputValue('rlbtm_modelName', 'Unnamed RL Model'); rlbtm_model.assetName = rlbtm_getInputValue('rlbtm_assetName', 'SIM_ASSET'); rlbtm_model.initialCapital = parseFloat(rlbtm_getInputValue('rlbtm_initialCapital', '10000')) || 10000; rlbtm_model.feeType = rlbtm_getInputValue('rlbtm_feeType', 'percentage'); rlbtm_model.feeValue = parseFloat(rlbtm_getInputValue('rlbtm_feeValue', '0.1')) || 0; // States, Actions, Rules, SimData are updated in their respective `update` functions. } // --- PDF Generation --- function rlbtm_downloadPDF() { if (rlbtm_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 yPos = 15; const m = 15; // margin const pw = doc.internal.pageSize.getWidth(); const contentWidth = pw - (2 * m); rlbtm_collectModelInputs(); // Ensure model object has latest UI data function addText(text, size, style = 'normal', indent = 0, spacing = 3) { if (yPos > 275) { doc.addPage(); yPos = m; } doc.setFontSize(size); doc.setFont(undefined, style); const lines = doc.splitTextToSize(text, contentWidth - indent); doc.text(lines, m + indent, yPos); yPos += (lines.length * (size * 0.35)) + spacing; } addText(`RL Trading Model: ${rlbtm_model.name}`, 18, 'bold', 0, 5); addText(`Asset: ${rlbtm_model.assetName}, Initial Capital: $${rlbtm_model.initialCapital.toFixed(2)}`, 10, 'normal', 0, 3); addText(`Fees: ${rlbtm_model.feeValue}${rlbtm_model.feeType === 'percentage' ? '%' : '$ fixed'} per trade`, 10, 'normal', 0, 6); addText("Defined States:", 14, 'bold', 0, 4); rlbtm_model.states.forEach(s => addText(`- ${s.name || 'Unnamed'}: ${s.type} ${s.type === 'categorical' ? `(${(s.values || []).join('/')})` : `(${s.numMin}-${s.numMax})`}`, 10, 'normal', 5, 2)); yPos += 3; addText("Defined Actions:", 14, 'bold', 0, 4); rlbtm_model.actions.forEach(a => { let actionDesc = `- ${a.name}`; if (a.id === 'action_buy' && a.params) { actionDesc += ` (${a.params.value}${a.params.type === 'percentage_capital' ? '% of capital' : ' units'})`; } addText(actionDesc, 10, 'normal', 5, 2); }); yPos += 3; addText("Strategy Rules (Policy):", 14, 'bold', 0, 4); rlbtm_model.rules.forEach((r, i) => { addText(`Rule ${i+1}:`, 10, 'bold', 5, 2); r.conditions.forEach(c => { const sDef = rlbtm_model.states.find(s => s.id === c.stateId); addText(` IF ${sDef ? sDef.name : c.stateId} ${c.operator} ${c.value}`, 9, 'normal', 10, 1); }); const aDef = rlbtm_model.actions.find(a => a.id === r.actionId); addText(` THEN ${aDef ? aDef.name : r.actionId}`, 9, 'normal', 10, 2); }); yPos += 5; addText("Simulation Log:", 16, 'bold', 0, 5); // Simple text log for PDF to avoid complex table drawing rlbtm_simulationLog.forEach(log => { if (yPos > 270) { doc.addPage(); yPos = m; } addText(`Step ${log.step}: [States: ${log.states}] -> Action: ${log.action}, PrcChg: ${log.priceChange}%, P&L: $${log.pnl}, Reward: $${log.reward}, Bal: $${log.balance}, Pos: ${log.position}`, 8, 'normal', 0, 1); }); yPos += 5; // Summary from HTML (captured during simulation) const summaryHTML = rlbtm_getEl('rlbtm_simulationSummary').innerText; // Basic text capture addText("Performance Summary:", 14, 'bold', 0, 4); addText(summaryHTML.replace(/(\$NaN|NaN%)/g, '$0.00 (Error?)'), 10); doc.save(`${rlbtm_model.name.replace(/\s+/g, '_') || 'rl_trading_sim'}_results.pdf`); }
Scroll to Top