- Added FastAPI backend with core API endpoints for strategies, backtests, and data management. - Introduced Vue 3 frontend with a dark theme, enabling users to run backtests, adjust parameters, and compare results. - Implemented Pydantic schemas for request/response validation and SQLAlchemy models for database interactions. - Enhanced project structure with dedicated modules for services, routers, and components. - Updated dependencies in `pyproject.toml` and `frontend/package.json` to include FastAPI, SQLAlchemy, and Vue-related packages. - Improved `.gitignore` to exclude unnecessary files and directories.
151 lines
3.5 KiB
TypeScript
151 lines
3.5 KiB
TypeScript
/**
|
|
* Composable for managing backtest state across components.
|
|
*/
|
|
import { ref, computed } from 'vue'
|
|
import type { BacktestResult, BacktestSummary, StrategyInfo, SymbolInfo } from '@/api/types'
|
|
import { getStrategies, getSymbols, getBacktests, getBacktest, runBacktest, deleteBacktest } from '@/api/client'
|
|
import type { BacktestRequest } from '@/api/types'
|
|
|
|
// Shared state
|
|
const strategies = ref<StrategyInfo[]>([])
|
|
const symbols = ref<SymbolInfo[]>([])
|
|
const runs = ref<BacktestSummary[]>([])
|
|
const currentResult = ref<BacktestResult | null>(null)
|
|
const selectedRuns = ref<string[]>([])
|
|
const loading = ref(false)
|
|
const error = ref<string | null>(null)
|
|
|
|
// Computed
|
|
const symbolsByMarket = computed(() => {
|
|
const grouped: Record<string, SymbolInfo[]> = {}
|
|
for (const s of symbols.value) {
|
|
const key = `${s.market_type}`
|
|
if (!grouped[key]) grouped[key] = []
|
|
grouped[key].push(s)
|
|
}
|
|
return grouped
|
|
})
|
|
|
|
export function useBacktest() {
|
|
/**
|
|
* Load strategies and symbols on app init.
|
|
*/
|
|
async function init() {
|
|
try {
|
|
const [stratRes, symRes] = await Promise.all([
|
|
getStrategies(),
|
|
getSymbols(),
|
|
])
|
|
strategies.value = stratRes.strategies
|
|
symbols.value = symRes.symbols
|
|
} catch (e) {
|
|
error.value = `Failed to load initial data: ${e}`
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Refresh the run history list.
|
|
*/
|
|
async function refreshRuns() {
|
|
try {
|
|
const res = await getBacktests({ limit: 100 })
|
|
runs.value = res.runs
|
|
} catch (e) {
|
|
error.value = `Failed to load runs: ${e}`
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Execute a new backtest.
|
|
*/
|
|
async function executeBacktest(request: BacktestRequest) {
|
|
loading.value = true
|
|
error.value = null
|
|
try {
|
|
const result = await runBacktest(request)
|
|
currentResult.value = result
|
|
await refreshRuns()
|
|
return result
|
|
} catch (e: unknown) {
|
|
const msg = e instanceof Error ? e.message : String(e)
|
|
error.value = `Backtest failed: ${msg}`
|
|
throw e
|
|
} finally {
|
|
loading.value = false
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Load a specific run by ID.
|
|
*/
|
|
async function loadRun(runId: string) {
|
|
loading.value = true
|
|
error.value = null
|
|
try {
|
|
const result = await getBacktest(runId)
|
|
currentResult.value = result
|
|
return result
|
|
} catch (e) {
|
|
error.value = `Failed to load run: ${e}`
|
|
throw e
|
|
} finally {
|
|
loading.value = false
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Delete a run.
|
|
*/
|
|
async function removeRun(runId: string) {
|
|
try {
|
|
await deleteBacktest(runId)
|
|
await refreshRuns()
|
|
if (currentResult.value?.run_id === runId) {
|
|
currentResult.value = null
|
|
}
|
|
selectedRuns.value = selectedRuns.value.filter(id => id !== runId)
|
|
} catch (e) {
|
|
error.value = `Failed to delete run: ${e}`
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Toggle run selection for comparison.
|
|
*/
|
|
function toggleRunSelection(runId: string) {
|
|
const idx = selectedRuns.value.indexOf(runId)
|
|
if (idx >= 0) {
|
|
selectedRuns.value.splice(idx, 1)
|
|
} else if (selectedRuns.value.length < 5) {
|
|
selectedRuns.value.push(runId)
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Clear all selections.
|
|
*/
|
|
function clearSelections() {
|
|
selectedRuns.value = []
|
|
}
|
|
|
|
return {
|
|
// State
|
|
strategies,
|
|
symbols,
|
|
symbolsByMarket,
|
|
runs,
|
|
currentResult,
|
|
selectedRuns,
|
|
loading,
|
|
error,
|
|
// Actions
|
|
init,
|
|
refreshRuns,
|
|
executeBacktest,
|
|
loadRun,
|
|
removeRun,
|
|
toggleRunSelection,
|
|
clearSelections,
|
|
}
|
|
}
|