Multi-strategy UI
Adds a "Strategies (multi)" panel: add/remove strategy rows (strategy, symbol, timeframe, per-strategy params and weight), start all, stop all and kill all, plus a per-strategy status table (allocation, equity, P&L, halted). Polls /api/bot/status alongside the existing status. Includes component tests.
This commit is contained in:
1 parent
3229a0e2aa
commit
ce2b11a803
6 files changed
+499
-1
No files matched your search
+58
-1
@@ -4,6 +4,7 @@ import * as api from './api'
|
||||
import BacktestPanel from './components/BacktestPanel.vue'
|
||||
import EquityChart from './components/EquityChart.vue'
|
||||
import EventLog from './components/EventLog.vue'
|
||||
import MultiStrategyPanel from './components/MultiStrategyPanel.vue'
|
||||
import OrdersTable from './components/OrdersTable.vue'
|
||||
import PositionsTable from './components/PositionsTable.vue'
|
||||
import StatusCards from './components/StatusCards.vue'
|
||||
@@ -31,6 +32,7 @@ const status = ref({
|
||||
const strategies = ref([])
|
||||
const strategiesLoading = ref(true)
|
||||
const presets = ref([])
|
||||
const multiStatus = ref({ running: false, strategies: [], total_pnl: 0, equity: 0 })
|
||||
const positions = ref([])
|
||||
const orders = ref([])
|
||||
const events = ref([])
|
||||
@@ -106,10 +108,51 @@ async function handleStart(payload) {
|
||||
}
|
||||
}
|
||||
|
||||
async function refreshMulti() {
|
||||
multiStatus.value = await api.getMultiStatus()
|
||||
}
|
||||
|
||||
async function handleStartMany(payload) {
|
||||
busy.value = true
|
||||
try {
|
||||
multiStatus.value = await api.startMany(payload)
|
||||
status.value = await api.getStatus()
|
||||
await refreshAll()
|
||||
} catch (error) {
|
||||
status.value = { ...status.value, error: error.response?.data?.detail || error.message }
|
||||
} finally {
|
||||
busy.value = false
|
||||
}
|
||||
}
|
||||
|
||||
async function handleStopMany() {
|
||||
busy.value = true
|
||||
try {
|
||||
await api.stopBot()
|
||||
status.value = await api.getStatus()
|
||||
await refreshMulti()
|
||||
await refreshAll()
|
||||
} finally {
|
||||
busy.value = false
|
||||
}
|
||||
}
|
||||
|
||||
async function handleKillMany() {
|
||||
busy.value = true
|
||||
try {
|
||||
status.value = await api.killBot('manual kill switch (all)')
|
||||
await refreshMulti()
|
||||
await refreshAll()
|
||||
} finally {
|
||||
busy.value = false
|
||||
}
|
||||
}
|
||||
|
||||
async function handleStop() {
|
||||
busy.value = true
|
||||
try {
|
||||
status.value = await api.stopBot()
|
||||
await refreshMulti()
|
||||
await refreshAll()
|
||||
} finally {
|
||||
busy.value = false
|
||||
@@ -193,6 +236,7 @@ onMounted(() => {
|
||||
// Initial loads are best-effort.
|
||||
api.getStatus().then((s) => (status.value = s)).catch(() => {})
|
||||
refreshAll().catch(() => {})
|
||||
refreshMulti().catch(() => {})
|
||||
|
||||
// The strategy list and presets rarely change, so load them once but keep
|
||||
// retrying until they arrive: a single failed first request used to leave the
|
||||
@@ -203,7 +247,10 @@ onMounted(() => {
|
||||
// Poll fast enough that the UI feels live even when it is the only channel.
|
||||
pollTimer = setInterval(() => refreshAll().catch(() => {}), 3000)
|
||||
statusTimer = setInterval(
|
||||
() => api.getStatus().then((s) => (status.value = s)).catch(() => {}),
|
||||
() => {
|
||||
api.getStatus().then((s) => (status.value = s)).catch(() => {})
|
||||
refreshMulti().catch(() => {})
|
||||
},
|
||||
3000,
|
||||
)
|
||||
// Retry the static lists until non-empty (covers a failed first load and a
|
||||
@@ -279,6 +326,16 @@ onUnmounted(() => {
|
||||
@delete-preset="handleDeletePreset"
|
||||
/>
|
||||
|
||||
<MultiStrategyPanel
|
||||
:strategies="strategies"
|
||||
:multi-status="multiStatus"
|
||||
:busy="busy"
|
||||
:loading="strategiesLoading"
|
||||
@start-many="handleStartMany"
|
||||
@stop="handleStopMany"
|
||||
@kill="handleKillMany"
|
||||
/>
|
||||
|
||||
<BacktestPanel :strategies="strategies" :status="status" :loading="strategiesLoading" />
|
||||
<SweepPanel :strategies="strategies" :status="status" :loading="strategiesLoading" />
|
||||
|
||||
|
||||
Reference in new issue
Block a user