"use client"; import { useEffect, useMemo, useState } from "react"; import type { Market } from "@/src/domain/types"; import type { Trade } from "@/src/trading/types"; import { computePositions } from "@/src/services/paperTrading"; import { toTrade } from "@/src/repositories/tradeRepo"; import { useTradingStore } from "@/src/stores/tradingStore"; function normalizeCode(raw: string) { return raw.trim(); } function toNumber(v: string) { const n = Number(v); return Number.isFinite(n) ? n : NaN; } export default function TradingPage() { const { trades, loading, error, refresh, add, remove } = useTradingStore(); const [code, setCode] = useState(""); const [market, setMarket] = useState("SZ"); const [side, setSide] = useState<"BUY" | "SELL">("BUY"); const [quantity, setQuantity] = useState("100"); const [price, setPrice] = useState("10"); const [fees, setFees] = useState("0"); const [note, setNote] = useState(""); useEffect(() => { void refresh(); }, [refresh]); const tradesParsed: Trade[] = useMemo(() => { return trades.map(toTrade); }, [trades]); const positions = useMemo(() => computePositions(tradesParsed), [tradesParsed]); const qtyNum = useMemo(() => toNumber(quantity), [quantity]); const priceNum = useMemo(() => toNumber(price), [price]); const canSubmit = useMemo(() => { return ( normalizeCode(code).length > 0 && qtyNum > 0 && priceNum > 0 && !Number.isNaN(qtyNum) && !Number.isNaN(priceNum) ); }, [code, qtyNum, priceNum]); return (

模拟盘

MVP:手动录入成交(买/卖),以平均成本计算持仓与已实现盈亏。

新增成交
{ e.preventDefault(); if (!canSubmit) return; await add({ code: normalizeCode(code), market, side, quantity: qtyNum, price: priceNum, fees: fees.trim() ? toNumber(fees) : undefined, tradeAt: new Date().toISOString(), note: note.trim() || undefined, }); setNote(""); }} >
{error ? (
{error}
) : null}
持仓
{positions.length === 0 ? ( ) : null} {positions.map((p) => ( ))}
代码 市场 数量 均价 已实现盈亏
暂无持仓
{p.code} {p.market} {p.quantity} {p.avgCost.toFixed(3)} {p.realizedPnl.toFixed(2)}
交易流水
{trades.length === 0 ? ( ) : null} {trades.map((t) => ( ))}
时间 代码 市场 方向 数量 价格 费用 备注 操作
暂无交易
{new Date(t.tradeAt).toLocaleString()} {t.code} {t.market} {t.side === "BUY" ? "买" : "卖"} {t.quantity} {t.price} {t.fees ?? 0} {t.note ?? ""}
{loading ? (
加载中…
) : null}
); }