iStocks 是一款面向个人投资者的 多市场股票深度分析 iOS 应用,覆盖美股、日股、韩股、港股、A 股。不仅提供实时行情,更强调「深度分析」——技术面(K 线与指标)、基本面(财务与估值)与结构化分析报告。
- 平台:iOS 16+
- 语言/框架:Swift 5.9+ / SwiftUI / Combine / async-await
- 架构:MVVM + Repository + 数据源协议抽象
- 本地存储:SwiftData(自选、提醒、设置)+ 行情缓存
- 无自建后端:App 直连第三方行情 API
需求、设计与实现计划见 .kiro/specs/stock-analysis-app/。
工程按分层组织,目录与设计文档一一对应:
iStocks/
├── Package.swift # SPM 清单:定义逻辑层库 target 与测试 target
├── Sources/
│ ├── App/ # SwiftUI App 入口(@main)与根视图占位
│ ├── Models/ # 核心数据模型(Market/Stock/Quote/Candle/Fundamentals…)
│ ├── Common/ # 通用工具与扩展
│ ├── Domain/ # 领域逻辑(指标引擎、交易日历、报告生成、领域服务)
│ ├── Data/ # 数据层(Provider 协议、Router、Repository、缓存、持久化)
│ └── Features/ # SwiftUI 视图 + ViewModel(MVVM)
└── Tests/
├── iStocksTests/ # 单元测试与属性测试(PBT)
│ └── PropertyTesting/ # 轻量、零依赖的属性测试工具(forAll / Gen)
└── iStocksUITests/ # UI 测试占位(XCUITest,需在 Xcode 中承载)
最终交付形态是一个 Xcode 构建的 SwiftUI iOS App。当前仓库用 Package.swift 组织代码,原因:
- 让平台无关的逻辑层(Models / Domain / Data / Common)可在任意 Swift 工具链上编译与测试;
- 表现层(
App/、Features/)依赖 SwiftUI,使用#if canImport(SwiftUI)守护,便于在非 Apple 平台上仅编译逻辑层。
在 macOS + Xcode 环境中,可直接用 Xcode 打开 Package.swift,或将其迁移为标准 .xcodeproj App 工程并把上述目录加入对应 target。
在具备 Swift 工具链(macOS,含 Xcode 命令行工具)时:
# 编译逻辑层
swift build
# 运行单元测试与属性测试
swift test在 Xcode 中:打开 Package.swift → 选择 iOS 模拟器 → ⌘R 运行,⌘U 测试。
- 确保已安装 Xcode(含命令行工具)。iStocks 面向 iOS 16+,逻辑层同时支持 macOS 13+。
- 用 Xcode 直接 打开
Package.swift(File ▸ Open…选中仓库根目录的Package.swift), Xcode 会自动解析 SPM target 图(Models / Common / Data / Domain / Features / App)。 - 选择 iOS 模拟器方案,
⌘R运行 App(App/target 提供@main入口与RootView)。 若需产出可上架的 App,可将上述目录接入一个标准.xcodeprojApp 工程,target 划分与 现有分层一一对应,无需改动源码。
# 在仓库根目录(需 Apple / Swift 工具链)
swift test也可在 Xcode 中按 ⌘U 运行整个 iStocksTests 测试套件。测试全部为平台无关的
逻辑层测试(Models / Common / Data / Domain / Features 的 ViewModel),
包含单元测试、属性测试(PBT)与端到端主流程集成测试
(MainFlowIntegrationTests:搜索 → 加自选 → 看详情 → 分析 → 设提醒,使用 Mock
数据源与内存持久化驱动真实服务,不依赖网络与 SwiftUI)。
⚠️ 环境说明:当前开发环境为 Windows,未安装 Swift 工具链 / Xcode / xcodebuild, 因此无法在此环境执行swift build/swift test/xcodebuild。代码结构已就绪, 静态检查(诊断)无告警,测试按「可通过」编写,需在 macOS + Xcode 环境中实际构建与运行。
设计文档定义了 7 条正确性属性(Property 1–7,见 design.md)。本工程内置一个
零外部依赖的轻量属性测试工具(Tests/iStocksTests/PropertyTesting/):
Gen<Value>:可组合的值生成器(.int/.double/.array/.map);forAll(...):对大量随机样本断言性质,失败时打印可复现的 种子 与 反例;SeededGenerator:可复现的伪随机数发生器(SplitMix64)。
选择自研工具而非 SwiftCheck,是为了在离线环境下也能组织属性测试且无解析依赖。
若偏好 SwiftCheck,Package.swift 中已预留其依赖声明(注释状态),启用后可平滑迁移。
正式行情数据需第三方 API Key。iStocks 按市场路由到不同数据源:
| 市场 | 数据源 | Keychain account |
|---|---|---|
| 美股 | Finnhub | finnhub |
| A 股 | Tushare | tushare |
| 港 / 日 / 韩 | 骨架,暂无免费实时源 | —— |
配置步骤:
- 分别在 Finnhub、Tushare 注册并获取 API Key(token)。
- 在 App 内进入 设置(⚙️) 页面,在「API Key」区填入对应市场的 Key 并保存。
- Key 仅存入 Keychain(
KeychainAPIKeyWriter/KeychainAPIKeyStore, service =com.istocks.apikeys,account 分别为finnhub与tushare), 从不写入UserDefaults/ plist / 源码,也不入库。 - 运行时各 Provider 通过
APIKeyProviding从 Keychain 读取 Key;缺失或为空时 归一化为MarketDataError.invalidAPIKey,UI 提示前往设置页配置。
免费额度有限,正式版可能需要付费 Key。密钥安全见非功能性需求「隐私 / Keychain」。
- 港 / 日 / 韩股为骨架实现:免费实时数据源稀缺,
HKStockProvider/JPStockProvider/KRStockProvider目前对所有接口抛出MarketDataError.providerUnavailable(market),以触发缓存回退或空状态视图, 而非返回假数据。接入真实数据源时,只需在对应具名类型中实现MarketDataProvider的四个方法,ProviderRouter与上层无需改动。 - 深度分析报告为本地规则引擎:
AnalysisReportGenerator基于指标与基本面套用 确定性规则,尚未接入 LLM 研报解读(可作为后续 Provider/服务扩展)。
所有深度分析内容均附带「仅供参考,不构成投资建议」免责声明;应用不提供下单能力。