Files
AI-Trader/market/store/statistics_store.py
T

110 lines
3.4 KiB
Python

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
统计数据存储模块
"""
from collections import deque, defaultdict
from datetime import datetime, timedelta
from typing import List, Dict, Optional
import threading
from ..models.statistics import StatisticsData
class StatisticsStore:
"""
统计数据存储
保留最近的数据用于:
1. 获取品种价差
2. 获取账户信息
"""
def __init__(self, max_per_symbol: int = 10, max_total: int = 100):
"""
Args:
max_per_symbol: 每个品种保留的最大记录数
max_total: 总共保留的最大记录数
"""
# 按品种分组存储
self._by_symbol: Dict[str, deque] = defaultdict(lambda: deque(maxlen=max_per_symbol))
# 全局存储(用于获取最新账户信息)
self._all_data: deque = deque(maxlen=max_total)
# 线程锁
self._lock = threading.RLock()
print(f"[StatisticsStore] 统计数据存储已初始化 (max_per_symbol={max_per_symbol}, max_total={max_total})")
def add(self, data: StatisticsData) -> None:
"""添加统计数据"""
with self._lock:
self._by_symbol[data.symbol].append(data)
self._all_data.append(data)
def get_latest(self, symbol: str = None) -> Optional[StatisticsData]:
"""获取最新的统计数据"""
with self._lock:
if symbol:
if self._by_symbol[symbol]:
return self._by_symbol[symbol][-1]
return None
else:
if self._all_data:
return self._all_data[-1]
return None
def get_by_symbol(self, symbol: str, count: int = 10) -> List[StatisticsData]:
"""获取指定品种的统计数据"""
with self._lock:
data = list(self._by_symbol[symbol])[-count:]
return data
def get_spread(self, symbol: str) -> Optional[float]:
"""获取品种价差"""
with self._lock:
# 规范化品种名称(去掉#后缀)
symbol_normalized = symbol.replace('#', '')
for stat in reversed(list(self._all_data)):
stat_normalized = stat.symbol.replace('#', '')
if stat_normalized == symbol_normalized:
if stat.spread > 0:
return stat.spread
return None
def get_account_info(self, symbol: str = None) -> Dict:
"""获取账户信息"""
latest = self.get_latest(symbol)
if not latest:
return {
"balance": 0,
"equity": 0,
"margin_level": 0
}
return {
"balance": latest.balance,
"equity": latest.equity,
"margin_level": latest.margin_level
}
def get_all_recent(self, count: int = 10) -> List[StatisticsData]:
"""获取最近的所有统计数据"""
with self._lock:
return list(self._all_data)[-count:]
def clear(self) -> None:
"""清空数据"""
with self._lock:
self._by_symbol.clear()
self._all_data.clear()
def get_status(self) -> Dict:
"""获取存储状态"""
with self._lock:
return {
"total_count": len(self._all_data),
"symbol_count": len(self._by_symbol),
"symbols": list(self._by_symbol.keys())
}