| import { defineStore } from 'pinia' |
| import { ref, computed } from 'vue' |
| import { marketApi, accountApi, positionApi, orderApi, tradeApi, riskApi } from '../api' |
|
|
| export const useTradingStore = defineStore('trading', () => { |
| const quotes = ref([]) |
| const contracts = ref([]) |
| const categories = ref({}) |
| const exchanges = ref({}) |
| const marketMode = ref('simulated') |
| const account = ref({ |
| total_balance: 1000000, available_balance: 1000000, |
| used_margin: 0, unrealized_pnl: 0, realized_pnl: 0, positions: [] |
| }) |
| const positions = ref([]) |
| const orders = ref([]) |
| const trades = ref([]) |
| const riskMetrics = ref({}) |
| const selectedSymbol = ref('') |
| const selectedCategory = ref('') |
| const wsConnection = ref(null) |
|
|
| const filteredQuotes = computed(() => { |
| let result = [...quotes.value] |
| if (selectedCategory.value) { |
| result = result.filter(q => q.category === selectedCategory.value) |
| } |
| return result.sort((a, b) => (a.name || a.symbol).localeCompare(b.name || b.symbol, 'zh')) |
| }) |
|
|
| const categoryList = computed(() => { |
| return [{ key: '', label: '全部' }, ...Object.entries(categories.value).map(([k, v]) => ({ key: k, label: v }))] |
| }) |
|
|
| const symbolList = computed(() => contracts.value.map(c => ({ symbol: c.symbol, name: c.name_cn, exchange: c.exchange, category: c.category }))) |
|
|
| async function fetchContracts(params) { |
| try { |
| const { data } = await marketApi.getContracts(params) |
| contracts.value = data |
| } catch (e) { console.error('Failed to fetch contracts:', e) } |
| } |
|
|
| async function fetchCategories() { |
| try { |
| const { data } = await marketApi.getCategories() |
| categories.value = data |
| } catch (e) { console.error('Failed to fetch categories:', e) } |
| } |
|
|
| async function fetchExchanges() { |
| try { |
| const { data } = await marketApi.getExchanges() |
| exchanges.value = data |
| } catch (e) { console.error('Failed to fetch exchanges:', e) } |
| } |
|
|
| async function fetchMarketMode() { |
| try { |
| const { data } = await marketApi.getMode() |
| marketMode.value = data.mode |
| } catch (e) { console.error('Failed to fetch mode:', e) } |
| } |
|
|
| async function setMarketMode(mode) { |
| try { |
| const { data } = await marketApi.setMode(mode) |
| marketMode.value = data.mode |
| } catch (e) { console.error('Failed to set mode:', e) } |
| } |
|
|
| async function fetchQuotes(params) { |
| try { |
| const { data } = await marketApi.getQuotes(params) |
| quotes.value = data |
| } catch (e) { console.error('Failed to fetch quotes:', e) } |
| } |
|
|
| async function fetchAccount() { |
| try { |
| const { data } = await accountApi.getAccount() |
| account.value = data |
| } catch (e) { console.error('Failed to fetch account:', e) } |
| } |
|
|
| async function fetchPositions() { |
| try { |
| const { data } = await positionApi.getPositions() |
| positions.value = data |
| } catch (e) { console.error('Failed to fetch positions:', e) } |
| } |
|
|
| async function fetchOrders() { |
| try { |
| const { data } = await orderApi.getOrders() |
| orders.value = data |
| } catch (e) { console.error('Failed to fetch orders:', e) } |
| } |
|
|
| async function fetchTrades() { |
| try { |
| const { data } = await tradeApi.getTrades() |
| trades.value = data |
| } catch (e) { console.error('Failed to fetch trades:', e) } |
| } |
|
|
| async function fetchRisk() { |
| try { |
| const { data } = await riskApi.getMetrics() |
| riskMetrics.value = data |
| } catch (e) { console.error('Failed to fetch risk:', e) } |
| } |
|
|
| function connectWebSocket() { |
| if (wsConnection.value) return |
| const wsProtocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:' |
| const ws = new WebSocket(`${wsProtocol}//${window.location.host}/ws/market`) |
| ws.onmessage = (event) => { |
| const msg = JSON.parse(event.data) |
| if (msg.type === 'market_data') { |
| const idx = quotes.value.findIndex(q => q.symbol === msg.data.symbol) |
| if (idx >= 0) { |
| quotes.value[idx] = { ...quotes.value[idx], ...msg.data } |
| } else { |
| quotes.value.push(msg.data) |
| } |
| } |
| } |
| ws.onclose = () => { |
| wsConnection.value = null |
| setTimeout(connectWebSocket, 3000) |
| } |
| wsConnection.value = ws |
| } |
|
|
| function disconnectWebSocket() { |
| if (wsConnection.value) { |
| wsConnection.value.close() |
| wsConnection.value = null |
| } |
| } |
|
|
| return { |
| quotes, filteredQuotes, contracts, categories, exchanges, categoryList, symbolList, |
| marketMode, account, positions, orders, trades, riskMetrics, |
| selectedSymbol, selectedCategory, |
| fetchContracts, fetchCategories, fetchExchanges, fetchMarketMode, setMarketMode, |
| fetchQuotes, fetchAccount, fetchPositions, fetchOrders, fetchTrades, fetchRisk, |
| connectWebSocket, disconnectWebSocket, |
| } |
| }) |
|
|