@@ -19,10 +19,26 @@ import {
1919 type MarketType ,
2020 type BinanceWsKlineMsg ,
2121 type BinanceWsDepthMsg ,
22+ type BinanceWsTradeMsg ,
23+ type BinanceTicker24h ,
2224 type ConnectionStatus ,
2325} from '../services/binance' ;
2426import type { OrderBook , HistoryCandle } from '../types/index' ;
2527
28+ /** 最近成交记录 */
29+ export interface TradeRecord {
30+ /** 交易 ID */
31+ id : number ;
32+ /** 价格 */
33+ price : number ;
34+ /** 数量 */
35+ qty : number ;
36+ /** 成交时间 (毫秒) */
37+ time : number ;
38+ /** 是否是买方主动成交 */
39+ isBuyerMaker : boolean ;
40+ }
41+
2642// ============================================================================
2743// 类型定义
2844// ============================================================================
@@ -63,6 +79,12 @@ export interface UseBinanceMarketReturn {
6379 currentPrice : number | null ;
6480 /** 错误信息 */
6581 error : string | null ;
82+ /** 24h Ticker 统计数据 (来自 Binance REST API) */
83+ ticker24h : BinanceTicker24h | null ;
84+ /** 最近成交记录 (来自 WebSocket trade stream) */
85+ recentTrades : TradeRecord [ ] ;
86+ /** Taker 买入比例 (0~1,实时计算) */
87+ takerBuyRatio : number | null ;
6688}
6789
6890// ============================================================================
@@ -194,6 +216,9 @@ export function useBinanceMarket(
194216 useState < ConnectionStatus > ( 'disconnected' ) ;
195217 const [ currentPrice , setCurrentPrice ] = useState < number | null > ( null ) ;
196218 const [ error , setError ] = useState < string | null > ( null ) ;
219+ const [ ticker24h , setTicker24h ] = useState < BinanceTicker24h | null > ( null ) ;
220+ const [ recentTrades , setRecentTrades ] = useState < TradeRecord [ ] > ( [ ] ) ;
221+ const [ takerBuyRatio , setTakerBuyRatio ] = useState < number | null > ( null ) ;
197222
198223 // ========== Refs ==========
199224 const wsRef = useRef < BinanceWebSocket | null > ( null ) ;
@@ -305,6 +330,15 @@ export function useBinanceMarket(
305330 setIsRunning ( true ) ;
306331 setError ( null ) ;
307332
333+ // 获取 24h Ticker 统计数据
334+ try {
335+ const ticker = await BinanceAPI . getTicker24h ( opts . symbol , opts . market ) ;
336+ setTicker24h ( ticker ) ;
337+ console . log ( '[Binance] ✅ 24h Ticker 已加载' ) ;
338+ } catch ( tickerErr ) {
339+ console . warn ( '[Binance] ⚠️ 获取 24h Ticker 失败,使用 K 线估算:' , tickerErr ) ;
340+ }
341+
308342 // 如果有起始价格,设置它
309343 if ( startPrice ) {
310344 priceRef . current = startPrice ;
@@ -468,8 +502,11 @@ export function useBinanceMarket(
468502 prevKlineVolumeRef . current = volume ;
469503 currentKlineVolumeRef . current = volume ;
470504
471-
472-
505+ // 计算 Taker 买入比例(实时)
506+ const takerBuyVol = parseFloat ( k . V ) ;
507+ if ( volume > 0 ) {
508+ setTakerBuyRatio ( takerBuyVol / volume ) ;
509+ }
473510 // K 线完结后,下一根 K 线开始时 prevKlineVolumeRef 会重置为 0
474511
475512 // 立即更新 OrderBook(包含成交量)
@@ -553,10 +590,24 @@ export function useBinanceMarket(
553590 }
554591 }
555592 } ,
593+ onTrade : ( trade : BinanceWsTradeMsg ) => {
594+ // 维护最近 50 笔成交记录
595+ const record : TradeRecord = {
596+ id : trade . t ,
597+ price : parseFloat ( trade . p ) ,
598+ qty : parseFloat ( trade . q ) ,
599+ time : trade . T ,
600+ isBuyerMaker : trade . m ,
601+ } ;
602+ setRecentTrades ( ( prev ) => {
603+ const next = [ record , ...prev ] ;
604+ return next . length > 50 ? next . slice ( 0 , 50 ) : next ;
605+ } ) ;
606+ } ,
556607 } ) ;
557608
558- // 订阅 K 线和深度数据
559- ws . connectKline ( ) . connectDepth ( '100ms' ) . start ( ) ;
609+ // 订阅 K 线、深度和逐笔交易数据
610+ ws . connectKline ( ) . connectDepth ( '100ms' ) . connectTrade ( ) . start ( ) ;
560611 wsRef . current = ws ;
561612
562613 // 定时更新 OrderBook(即使没有深度更新,也定期刷新价格)
@@ -644,5 +695,8 @@ export function useBinanceMarket(
644695 connectionStatus,
645696 currentPrice,
646697 error,
698+ ticker24h,
699+ recentTrades,
700+ takerBuyRatio,
647701 } ;
648702}
0 commit comments