From e24023cf4274182bfde5f6dcbb9fd93fe5eb83b0 Mon Sep 17 00:00:00 2001 From: Kunthawat Greethong Date: Tue, 25 Aug 2026 16:28:12 +0700 Subject: [PATCH] [verified] Add Thai Simulation tab (capital allocation 50/20/30); remove legacy paper-ledger section MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Simulation panel (07): capital input (บาท), mode (backtest/forward), calls /api/v1/simulation, renders 3 buckets with orders (symbol/qty/price/notional), invested + unallocated cash, honest non-PIT label - Removed legacy 'Paper ledger' section (superseded by simulation/forward-test per user) - Sidebar thumb จำลอง; responsive 1-col mobile - Verified: npm build + browser (3 bucket cards render, ลงทุนรวม/เงินสดเหลือ show) --- frontend/src/App.vue | 116 +++++++++++++++++++++++++++++++++-------- frontend/src/style.css | 23 ++++++++ 2 files changed, 118 insertions(+), 21 deletions(-) diff --git a/frontend/src/App.vue b/frontend/src/App.vue index 2897d3b..9ce6051 100644 --- a/frontend/src/App.vue +++ b/frontend/src/App.vue @@ -6,6 +6,10 @@ const observations = ref(null) const signalData = ref(null) const factorData = ref(null) const themeData = ref(null) +const simCapital = ref(1000000) +const simMode = ref('backtest') +const simLoading = ref(false) +const simResult = ref(null) const dividendOnly = ref(false) const sortKey = ref('signal_score') const sortDirection = ref('desc') @@ -189,6 +193,27 @@ async function runResearch() { } } +const simOrders = computed(() => simResult.value?.orders ?? []) +const simInvested = computed(() => simResult.value?.invested ?? 0) +const simUnallocated = computed(() => simResult.value?.unallocated_cash ?? 0) +const bucketOrders = (n) => simOrders.value.filter((o) => o.bucket === n) + +async function runSimulation() { + simLoading.value = true + simResult.value = null + try { + simResult.value = await fetchJson('/api/v1/simulation', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ capital: Number(simCapital.value), mode: simMode.value }), + }) + } catch (caught) { + notice.value = caught.message + } finally { + simLoading.value = false + } +} + async function loadDashboard() { loading.value = true error.value = '' @@ -312,6 +337,7 @@ onMounted(loadDashboard) ปัจจัย ที่มาข้อมูล งานวิจัย + จำลอง