|
|
@@ -104,8 +104,123 @@ TradePanel → useTradeRecords → 状态更新 → ProfitDisplay更新
|
|
|
|
|
|
// WebSocket流程
|
|
|
useStockSocket → 连接建立 → 数据推送 → 答题卡功能
|
|
|
+
|
|
|
+// 数据过滤流程
|
|
|
+useStockDataFilter → 数据分段处理 → 历史数据 + 训练数据 → StockChart渲染
|
|
|
+```
|
|
|
+
|
|
|
+## useStockDataFilter Hook 详细分析
|
|
|
+
|
|
|
+### 核心功能
|
|
|
+`useStockDataFilter` 是一个专门用于股票训练场景的数据过滤钩子,主要功能包括:
|
|
|
+- **数据分段管理**:将完整的股票数据分为历史数据和训练数据两部分
|
|
|
+- **训练进度控制**:支持逐步展示训练日数据,模拟真实交易场景
|
|
|
+- **视图初始化**:控制数据何时开始显示,避免未初始化时显示错误数据
|
|
|
+- **进度信息提供**:返回当前训练进度、剩余天数等信息
|
|
|
+
|
|
|
+### 状态管理
|
|
|
+```typescript
|
|
|
+const [selectedDays, setSelectedDays] = useState(120); // 默认120天
|
|
|
+const [trainingProgress, setTrainingProgress] = useState(0); // 训练日进度
|
|
|
+const [isInitialized, setIsInitialized] = useState(false);
|
|
|
+```
|
|
|
+
|
|
|
+- **selectedDays**: 控制训练阶段的总天数,默认120天
|
|
|
+- **trainingProgress**: 当前训练进度(已展示的天数),从0开始递增
|
|
|
+- **isInitialized**: 初始化标志,确保数据在适当时候才开始显示
|
|
|
+
|
|
|
+### 核心算法 - filterData 方法
|
|
|
+```typescript
|
|
|
+// 计算训练日部分:从当前日期往前推选择的天数到当前日期
|
|
|
+const trainingStartIndex = totalDays - selectedDays;
|
|
|
+const trainingEndIndex = Math.min(trainingStartIndex + trainingProgress, totalDays);
|
|
|
+
|
|
|
+// 计算历史天数部分:从训练日开始日期往前推至少365天
|
|
|
+const historyEndIndex = trainingStartIndex;
|
|
|
+const historyStartIndex = Math.max(0, historyEndIndex - Math.max(selectedDays, 365));
|
|
|
+
|
|
|
+// 合并历史天数和已加载的训练日数据
|
|
|
+const historyData = fullData.slice(historyStartIndex, historyEndIndex);
|
|
|
+const trainingData = fullData.slice(trainingStartIndex, trainingEndIndex);
|
|
|
+
|
|
|
+return [...historyData, ...trainingData];
|
|
|
+```
|
|
|
+
|
|
|
+**算法逻辑**:
|
|
|
+1. **训练数据段**:从完整数据的末尾往前推 `selectedDays` 天开始,到当前训练进度结束
|
|
|
+2. **历史数据段**:从训练开始日期往前推至少365天(或与训练天数相同的天数),确保有足够的历史数据供分析
|
|
|
+3. **数据合并**:将历史数据和已训练的数据合并返回
|
|
|
+
|
|
|
+### moveToNextDay 方法实现
|
|
|
+```typescript
|
|
|
+const moveToNextDay = useCallback(() => {
|
|
|
+ return new Promise<string>((resolve) => {
|
|
|
+ setTrainingProgress((prev) => {
|
|
|
+ const newProgress = prev + 1;
|
|
|
+ // 计算新的训练结束索引
|
|
|
+ const trainingEndIndex = Math.min(trainingStartIndex + newProgress, totalDays);
|
|
|
+ // 返回最新日期
|
|
|
+ const nextDate = fullData[trainingEndIndex - 1]?.d || '';
|
|
|
+ resolve(nextDate);
|
|
|
+ return newProgress;
|
|
|
+ });
|
|
|
+ });
|
|
|
+}, [fullData, selectedDays]);
|
|
|
```
|
|
|
|
|
|
+### 辅助方法
|
|
|
+- **resetTrainingProgress**: 重置训练进度到0,用于重新开始训练
|
|
|
+- **setDayNumWithTraining**: 设置训练天数并重置进度,用于切换不同的训练周期
|
|
|
+- **initializeView**: 标记视图已初始化,开始显示数据
|
|
|
+- **getTrainingInfo**: 提供训练进度相关信息(当前进度、总天数、剩余天数、是否完成)
|
|
|
+
|
|
|
+### 返回值结构
|
|
|
+```typescript
|
|
|
+return {
|
|
|
+ filteredData: filterData(), // 过滤后的数据数组
|
|
|
+ moveToNextDay, // 前进到下一天的方法
|
|
|
+ resetTrainingProgress, // 重置进度的方法
|
|
|
+ setDayNum: setDayNumWithTraining, // 设置训练天数的方法
|
|
|
+ initializeView, // 初始化视图的方法
|
|
|
+ isInitialized, // 初始化状态
|
|
|
+ trainingInfo: getTrainingInfo() // 训练信息对象
|
|
|
+};
|
|
|
+```
|
|
|
+
|
|
|
+### 架构位置和作用
|
|
|
+**位置**: `src/client/mobile/components/stock/components/stock-chart/src/hooks/useStockDataFilter.ts`
|
|
|
+
|
|
|
+**核心作用**:
|
|
|
+1. **数据预处理**:为股票图表提供适当的数据切片
|
|
|
+2. **训练模拟**:支持逐步展示数据的训练模式
|
|
|
+3. **状态管理**:管理训练相关的状态和进度
|
|
|
+4. **接口提供**:为上层组件提供控制训练进度的方法
|
|
|
+
|
|
|
+### 性能优化
|
|
|
+**当前优化**:
|
|
|
+- 使用 `useCallback` 包装所有方法,避免不必要的重渲染
|
|
|
+- 依赖项数组合理设置,只在相关状态变化时重新计算
|
|
|
+
|
|
|
+**优化建议**:
|
|
|
+1. **数据缓存**:可考虑对 `filterData` 结果进行缓存,避免重复计算
|
|
|
+2. **批量更新**:如果支持批量前进多天,可优化 `moveToNextDay` 方法
|
|
|
+3. **内存优化**:对于大数据集,可考虑使用更高效的数据结构
|
|
|
+
|
|
|
+### 组件交互关系
|
|
|
+**上游依赖**:
|
|
|
+- 接收完整的 `fullData` 作为输入
|
|
|
+- 依赖 `StockData` 类型定义
|
|
|
+
|
|
|
+**下游服务**:
|
|
|
+- 为 `StockChart` 组件提供过滤后的数据
|
|
|
+- 为交易面板提供训练进度控制
|
|
|
+- 为收益计算提供当前训练状态信息
|
|
|
+
|
|
|
+**协同工作**:
|
|
|
+- 与 `useTradeRecords` 协同管理交易记录的时间线
|
|
|
+- 与 `useProfitCalculator` 配合计算基于训练进度的收益
|
|
|
+- 与 `useStockQueries` 形成数据获取→过滤→展示的完整流水线
|
|
|
+
|
|
|
## API Interfaces
|
|
|
|
|
|
**Main API Endpoints**:
|