- 后端实现: - 实现 NBA 比赛数据服务,从 Polymarket API 获取数据 - 实现数据库存储和增量拉取逻辑(优先从 DB 获取,数据不足时增量拉取) - 使用 sports_market_types 参数直接筛选 moneyline 类型 - 实现分页拉取逻辑(基于 gameStartTime 和 createdAt) - 移除 nba_markets 相关的外键约束(V12 迁移) - 修复数据拉取逻辑:超过 3 天的数据不拉取 - 前端实现: - 实现策略创建/编辑/列表页面 - 实现交易信号展示页面和统计页面 - 修复重复请求问题(使用 useCallback 包装 fetchGames) - 支持选择单场比赛进行配置 - 使用西8区时间格式化显示 - 数据库: - 创建 NBA 量化交易相关表(V11 迁移) - 移除外键约束(V12 迁移) - 文档: - 添加产品需求文档、技术方案、算法文档等
4.0 KiB
4.0 KiB
NBA Stats API 验证检查清单
一、API 接口定义检查
1.1 接口路径
- ✅ 路径:
/Scoreboard - ✅ Base URL:
https://stats.nba.com/stats/ - ✅ 完整 URL:
https://stats.nba.com/stats/Scoreboard
1.2 请求参数
- ✅ GameDate: 日期格式
YYYY-MM-DD(如2024-12-15) - ✅ LeagueID: 联盟ID,默认
"00"(NBA) - ✅ DayOffset: 日期偏移,默认
0
注意: NBA Stats API 的参数名称是大小写敏感的:
- ✅
GameDate(正确) - ❌
gameDate(错误) - ✅
LeagueID(正确) - ❌
leagueId(错误)
1.3 请求头设置
- ✅ User-Agent:
Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 - ✅ Referer:
https://www.nba.com/ - ✅ Accept:
application/json - ✅ Accept-Language:
en-US,en;q=0.9 - ✅ Origin:
https://www.nba.com
二、响应格式检查
2.1 响应结构
NBA Stats API 返回的 JSON 结构:
{
"resultSets": [
{
"name": "GameHeader",
"headers": ["GAME_DATE_EST", "GAME_SEQUENCE", "GAME_ID", ...],
"rowSet": [[...], [...]]
},
{
"name": "LineScore",
"headers": ["GAME_DATE_EST", "GAME_SEQUENCE", "GAME_ID", "TEAM_ID", ...],
"rowSet": [[...], [...]]
}
]
}
2.2 ResultSet 名称
- ✅ GameHeader: 比赛基本信息
- ✅ LineScore: 比分信息(每支球队一行)
2.3 GameHeader 字段顺序
根据注释,字段顺序应该是:
[0] GAME_DATE_EST
[1] GAME_SEQUENCE
[2] GAME_ID
[3] GAME_STATUS_ID
[4] GAME_STATUS_TEXT
[5] GAMECODE
[6] HOME_TEAM_ID
[7] VISITOR_TEAM_ID
[8] SEASON
[9] LIVE_PERIOD
[10] LIVE_PC_TIME
[11] NATL_TV_BROADCASTER_ABBREV
[12] LIVE_PERIOD_TIME_BCAST
[13] WH_STATUS
2.4 LineScore 字段顺序
根据注释,字段顺序应该是:
[0] GAME_DATE_EST
[1] GAME_SEQUENCE
[2] GAME_ID
[3] TEAM_ID
[4] TEAM_ABBREVIATION
[5] TEAM_NAME
[6] PTS_QTR1
[7] PTS_QTR2
[8] PTS_QTR3
[9] PTS_QTR4
[10] PTS_OT1
[11] PTS_OT2
[12] PTS_OT3
[13] PTS_OT4
[14] PTS
[15] FG_PCT
[16] FT_PCT
[17] FG3_PCT
[18] AST
[19] REB
[20] TOV
三、代码实现检查
3.1 接口定义 ✅
@GET("Scoreboard")
suspend fun getScoreboard(
@Query("GameDate") gameDate: String? = null,
@Query("LeagueID") leagueId: String = "00",
@Query("DayOffset") dayOffset: Int = 0
): Response<ScoreboardResponse>
- ✅ 参数名称大小写正确
- ✅ 参数类型正确
3.2 请求头设置 ✅
- ✅ 已设置所有必需的请求头
- ✅ User-Agent 格式正确
3.3 响应解析 ⚠️
潜在问题:
-
ResultSet 查找方式: 使用
firstOrNull { it.name == "GameHeader" }可能不够准确- 建议:使用索引
resultSets[0]或resultSets.getOrNull(0) - 或者:先检查
resultSets.size >= 2
- 建议:使用索引
-
字段索引: 当前代码假设字段顺序固定
- 建议:根据
headers数组动态查找字段索引,而不是硬编码索引
- 建议:根据
-
错误处理: 当前有基本的错误处理,但可以更详细
四、建议的改进
4.1 使用 headers 动态查找字段
// 根据 headers 查找字段索引,而不是硬编码
val gameDateIndex = headers.indexOf("GAME_DATE_EST")
val gameIdIndex = headers.indexOf("GAME_ID")
// ...
4.2 增强错误处理
- 记录完整的响应内容(用于调试)
- 验证 headers 数量是否匹配
- 验证 rowSet 数据是否完整
4.3 添加响应验证
- 验证 resultSets 数量
- 验证每个 resultSet 的 name
- 验证 headers 和 rowSet 的对应关系
五、测试建议
- 单元测试: 测试 API 调用和响应解析
- 集成测试: 测试完整的获取流程
- 错误场景测试: 测试 API 失败、数据不完整等情况
六、已知问题
- API 限制: NBA Stats API 可能需要特定的请求头,否则可能返回 403 或空数据
- 数据格式: 响应格式可能因日期而异(有比赛 vs 无比赛)
- 时区问题:
GAME_DATE_EST是 EST 时区,需要注意时区转换