@stvy/fund-indicators 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.en.md +617 -0
- package/README.md +617 -0
- package/dist/browser/fund-indicators.esm.js +7505 -0
- package/dist/browser/fund-indicators.esm.min.js +8 -0
- package/dist/browser/fund-indicators.esm.min.js.map +7 -0
- package/dist/browser/fund-indicators.js +7517 -0
- package/dist/browser/fund-indicators.min.js +8 -0
- package/dist/browser/fund-indicators.min.js.map +7 -0
- package/dist/dca.d.ts +91 -0
- package/dist/dca.d.ts.map +1 -0
- package/dist/dca.js +354 -0
- package/dist/dca.js.map +1 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +141 -0
- package/dist/index.js.map +1 -0
- package/dist/pattern.d.ts +60 -0
- package/dist/pattern.d.ts.map +1 -0
- package/dist/pattern.js +386 -0
- package/dist/pattern.js.map +1 -0
- package/dist/risk.d.ts +115 -0
- package/dist/risk.d.ts.map +1 -0
- package/dist/risk.js +502 -0
- package/dist/risk.js.map +1 -0
- package/dist/statistics.d.ts +78 -0
- package/dist/statistics.d.ts.map +1 -0
- package/dist/statistics.js +402 -0
- package/dist/statistics.js.map +1 -0
- package/dist/technical.d.ts +105 -0
- package/dist/technical.d.ts.map +1 -0
- package/dist/technical.js +633 -0
- package/dist/technical.js.map +1 -0
- package/dist/types.d.ts +327 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +7 -0
- package/dist/types.js.map +1 -0
- package/package.json +75 -0
package/README.md
ADDED
|
@@ -0,0 +1,617 @@
|
|
|
1
|
+
# @stvy/fund-indicators
|
|
2
|
+
|
|
3
|
+
**[English](README.en.md)** | 中文
|
|
4
|
+
|
|
5
|
+
**基金自动化交易指标计算工具库** — 基于历史净值 (NAV) 数据计算全部技术指标。
|
|
6
|
+
|
|
7
|
+
[](https://www.npmjs.com/package/@stvy/fund-indicators)
|
|
8
|
+
[](https://opensource.org/licenses/MIT)
|
|
9
|
+
[](https://www.typescriptlang.org/)
|
|
10
|
+
[](https://github.com/stevieyu/fund-indicators/actions/workflows/ci.yml)
|
|
11
|
+
|
|
12
|
+
专为场外基金、指数基金、ETF 联接基金等设计的量化分析工具库,只需传入每日净值数组,即可计算 70+ 种技术指标、风险指标、绩效指标、统计特征、定投分析和形态识别信号。
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## 特性
|
|
17
|
+
|
|
18
|
+
- **零门槛输入**:所有函数只需一个 `number[]`(每日净值数组)即可调用
|
|
19
|
+
- **TypeScript 原生**:完整的类型定义和 JSDoc 注释,IDE 智能提示友好
|
|
20
|
+
- **覆盖全面**:技术指标 + 风险绩效 + 统计特征 + 定投分析 + 形态识别,5 大模块 70+ 函数
|
|
21
|
+
- **基金场景优化**:年化参数基于 A 股 242 个交易日,支持场外基金净值分析
|
|
22
|
+
- **轻量依赖**:仅依赖 `technicalindicators` + `simple-statistics` + `jstat` 三个库
|
|
23
|
+
- **经过验证**:35 项自动化测试覆盖所有核心功能
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## 安装
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
npm install @stvy/fund-indicators
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
### 浏览器直接使用
|
|
34
|
+
|
|
35
|
+
本库同时提供浏览器可用的构建产物,可以直接在 HTML 页面中使用。
|
|
36
|
+
|
|
37
|
+
**方式一:`<script>` 标签(IIFE)**
|
|
38
|
+
|
|
39
|
+
```html
|
|
40
|
+
<script src="https://unpkg.com/@stvy/fund-indicators/dist/browser/fund-indicators.min.js"></script>
|
|
41
|
+
<script>
|
|
42
|
+
const nav = [1.0, 1.02, 1.01, 1.05, 1.03, 1.08];
|
|
43
|
+
|
|
44
|
+
const ma = FundIndicators.sma(nav, 3);
|
|
45
|
+
console.log('SMA(3):', ma.current);
|
|
46
|
+
|
|
47
|
+
const rsi = FundIndicators.rsi(nav, 3);
|
|
48
|
+
console.log('RSI(3):', rsi.current);
|
|
49
|
+
|
|
50
|
+
const sharpe = FundIndicators.sharpeRatio(nav);
|
|
51
|
+
console.log('夏普比率:', sharpe);
|
|
52
|
+
</script>
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
**方式二:`<script type="module">`(ESM)**
|
|
56
|
+
|
|
57
|
+
```html
|
|
58
|
+
<script type="module">
|
|
59
|
+
import { sma, rsi, sharpeRatio } from 'https://unpkg.com/@stvy/fund-indicators/dist/browser/fund-indicators.esm.js';
|
|
60
|
+
|
|
61
|
+
const nav = [1.0, 1.02, 1.01, 1.05, 1.03, 1.08];
|
|
62
|
+
|
|
63
|
+
console.log('SMA(3):', sma(nav, 3).current);
|
|
64
|
+
console.log('RSI(3):', rsi(nav, 3).current);
|
|
65
|
+
console.log('夏普比率:', sharpeRatio(nav));
|
|
66
|
+
</script>
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
**产物说明:**
|
|
70
|
+
|
|
71
|
+
| 文件 | 格式 | 大小 | 用途 |
|
|
72
|
+
|------|------|------|------|
|
|
73
|
+
| `fund-indicators.js` | IIFE | ~257 KB | `<script>` 标签,暴露全局变量 `FundIndicators` |
|
|
74
|
+
| `fund-indicators.min.js` | IIFE minified | ~99 KB | 生产环境推荐 |
|
|
75
|
+
| `fund-indicators.esm.js` | ESM | ~241 KB | `<script type="module">` 或前端打包工具 |
|
|
76
|
+
| `fund-indicators.esm.min.js` | ESM minified | ~99 KB | 生产环境 ESM 推荐 |
|
|
77
|
+
|
|
78
|
+
> 浏览器构建将所有依赖打包在内,无需额外安装任何依赖。
|
|
79
|
+
|
|
80
|
+
---
|
|
81
|
+
|
|
82
|
+
## 快速开始
|
|
83
|
+
|
|
84
|
+
```typescript
|
|
85
|
+
import {
|
|
86
|
+
sma, macd, rsi, kdj, bollingerBands,
|
|
87
|
+
sharpeRatio, maxDrawdown, performanceMetrics,
|
|
88
|
+
hurstExponent, simulateDCA,
|
|
89
|
+
} from '@stvy/fund-indicators';
|
|
90
|
+
|
|
91
|
+
// 你的基金历史净值序列(按日期升序)
|
|
92
|
+
const nav = [1.0, 1.02, 1.01, 1.05, 1.03, 1.08, /* ... */];
|
|
93
|
+
|
|
94
|
+
// ── 技术指标 ──
|
|
95
|
+
const ma20 = sma(nav, 20);
|
|
96
|
+
console.log('20日均线:', ma20.current);
|
|
97
|
+
|
|
98
|
+
const m = macd(nav);
|
|
99
|
+
console.log('MACD DIF/DEA:', m.currentDIF, m.currentDEA);
|
|
100
|
+
|
|
101
|
+
const r = rsi(nav, 14);
|
|
102
|
+
console.log('RSI(14):', r.current);
|
|
103
|
+
|
|
104
|
+
const k = kdj(nav);
|
|
105
|
+
console.log('KDJ:', k.currentK, k.currentD, k.currentJ);
|
|
106
|
+
|
|
107
|
+
// ── 风险与绩效 ──
|
|
108
|
+
console.log('夏普比率:', sharpeRatio(nav, 0.025));
|
|
109
|
+
console.log('最大回撤:', maxDrawdown(nav).maxDrawdown);
|
|
110
|
+
|
|
111
|
+
const perf = performanceMetrics(nav);
|
|
112
|
+
console.log('年化收益:', perf.annualizedReturn);
|
|
113
|
+
console.log('索提诺比率:', perf.sortinoRatio);
|
|
114
|
+
|
|
115
|
+
// ── 统计特征 ──
|
|
116
|
+
const hurst = hurstExponent(nav);
|
|
117
|
+
console.log('Hurst 指数:', hurst.hurstExponent, '→', hurst.interpretation);
|
|
118
|
+
|
|
119
|
+
// ── 定投模拟 ──
|
|
120
|
+
const dca = simulateDCA(nav, { amount: 1000, interval: 22 });
|
|
121
|
+
console.log('定投收益率:', dca.returnRate, 'IRR:', dca.irr);
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
---
|
|
125
|
+
|
|
126
|
+
## 模块文档
|
|
127
|
+
|
|
128
|
+
### 1. 技术指标模块 (`technical`)
|
|
129
|
+
|
|
130
|
+
基于历史净值计算趋势、动量、震荡和通道类指标。
|
|
131
|
+
|
|
132
|
+
#### 均线系列
|
|
133
|
+
|
|
134
|
+
| 函数 | 说明 | 参数 |
|
|
135
|
+
|------|------|------|
|
|
136
|
+
| `sma(nav, period)` | 简单移动平均线 | `period` 默认 20 |
|
|
137
|
+
| `ema(nav, period)` | 指数移动平均线 | `period` 默认 20 |
|
|
138
|
+
| `wma(nav, period)` | 加权移动平均线 | `period` 默认 20 |
|
|
139
|
+
| `dema(nav, period)` | 双重指数移动平均线 | `period` 默认 20 |
|
|
140
|
+
| `tema(nav, period)` | 三重指数移动平均线 | `period` 默认 20 |
|
|
141
|
+
| `kama(nav, period, fast?, slow?)` | 考夫曼自适应均线 | `period` 默认 10 |
|
|
142
|
+
|
|
143
|
+
所有均线函数返回 `MAResult`:
|
|
144
|
+
|
|
145
|
+
```typescript
|
|
146
|
+
interface MAResult {
|
|
147
|
+
values: (number | null)[]; // 与输入等长的数组,前 N-1 个为 null
|
|
148
|
+
current: number | null; // 最后一个有效值
|
|
149
|
+
period: number;
|
|
150
|
+
type: string;
|
|
151
|
+
}
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
**示例 — 均线交叉检测:**
|
|
155
|
+
|
|
156
|
+
```typescript
|
|
157
|
+
const fast = ema(nav, 10);
|
|
158
|
+
const slow = ema(nav, 30);
|
|
159
|
+
const signal = detectCrossSignal(fast, slow);
|
|
160
|
+
|
|
161
|
+
if (signal.type === 'golden_cross') console.log('金叉!买入信号');
|
|
162
|
+
if (signal.type === 'death_cross') console.log('死叉!卖出信号');
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
**示例 — 均线多空排列:**
|
|
166
|
+
|
|
167
|
+
```typescript
|
|
168
|
+
const alignment = detectMAAlignment([
|
|
169
|
+
sma(nav, 5), sma(nav, 10), sma(nav, 20), sma(nav, 60),
|
|
170
|
+
]);
|
|
171
|
+
console.log(alignment.alignment); // 'bullish' | 'bearish' | 'neutral'
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
#### MACD
|
|
175
|
+
|
|
176
|
+
```typescript
|
|
177
|
+
const result = macd(nav, 12, 26, 9);
|
|
178
|
+
// result.currentDIF — DIF 线(快线)
|
|
179
|
+
// result.currentDEA — DEA 线(慢线)
|
|
180
|
+
// result.currentHistogram — 柱状线
|
|
181
|
+
// result.dif / .dea / .histogram — 完整序列
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
#### 动量与震荡指标
|
|
185
|
+
|
|
186
|
+
| 函数 | 说明 | 典型用法 |
|
|
187
|
+
|------|------|----------|
|
|
188
|
+
| `rsi(nav, period?)` | RSI 相对强弱指标 | >70 超买,<30 超卖 |
|
|
189
|
+
| `kdj(nav, kPeriod?, kSmooth?, dPeriod?)` | KDJ 随机指标(含 J 值) | K/D 金叉死叉 |
|
|
190
|
+
| `roc(nav, period?)` | 变动率 | 动量强弱 |
|
|
191
|
+
| `momentum(nav, period?)` | 动量指标 | 趋势加速/减速 |
|
|
192
|
+
| `williamsR(nav, period?)` | 威廉指标 | 超买超卖 |
|
|
193
|
+
| `cci(nav, period?)` | 商品通道指数 | >100 / <-100 |
|
|
194
|
+
| `trix(nav, period?)` | 三重平滑指数 | 过滤噪音的趋势 |
|
|
195
|
+
| `dpo(nav, period?)` | 去趋势价格震荡器 | 识别周期 |
|
|
196
|
+
| `stochasticRSI(nav, ...)` | 随机 RSI | 更灵敏的超买超卖 |
|
|
197
|
+
| `massIndex(nav, emaPeriod?, sumPeriod?)` | 质量指数 | 识别变盘点 |
|
|
198
|
+
|
|
199
|
+
#### 通道与波动
|
|
200
|
+
|
|
201
|
+
| 函数 | 说明 |
|
|
202
|
+
|------|------|
|
|
203
|
+
| `bollingerBands(nav, period?, stdDev?)` | 布林带(含带宽和 %B) |
|
|
204
|
+
| `donchianChannel(nav, period?)` | 唐奇安通道 |
|
|
205
|
+
| `keltnerChannel(nav, emaPeriod?, atrPeriod?, multiplier?)` | 肯特纳通道 |
|
|
206
|
+
| `adx(nav, period?)` | ADX 平均趋向指标 + DI+/DI- |
|
|
207
|
+
| `atr(nav, period?)` | ATR 平均真实波幅(近似) |
|
|
208
|
+
| `sar(nav, step?, max?)` | SAR 抛物线转向 |
|
|
209
|
+
|
|
210
|
+
#### 衍生指标
|
|
211
|
+
|
|
212
|
+
| 函数 | 说明 |
|
|
213
|
+
|------|------|
|
|
214
|
+
| `bias(nav, period?)` | 乖离率 = (净值 - MA) / MA × 100 |
|
|
215
|
+
| `navPercentile(nav, lookback?)` | 净值在历史区间中的百分位 (0-100) |
|
|
216
|
+
|
|
217
|
+
---
|
|
218
|
+
|
|
219
|
+
### 2. 风险与绩效模块 (`risk`)
|
|
220
|
+
|
|
221
|
+
#### 基础工具
|
|
222
|
+
|
|
223
|
+
```typescript
|
|
224
|
+
import { navToReturns, totalReturn, annualizeReturn } from '@stvy/fund-indicators';
|
|
225
|
+
|
|
226
|
+
const returns = navToReturns(nav); // 净值 → 日收益率
|
|
227
|
+
const tr = totalReturn(nav); // 累计收益率
|
|
228
|
+
const ar = annualizeReturn(returns); // 年化收益率(几何平均)
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
#### 波动率
|
|
232
|
+
|
|
233
|
+
```typescript
|
|
234
|
+
import { annualizedVolatility, downsideVolatility, rollingVolatility, volatilityCone } from '@stvy/fund-indicators';
|
|
235
|
+
|
|
236
|
+
annualizedVolatility(returns); // 年化波动率
|
|
237
|
+
downsideVolatility(returns, 0.025); // 下行波动率
|
|
238
|
+
rollingVolatility(returns, 20); // 滚动 20 日波动率
|
|
239
|
+
volatilityCone(returns, [5,10,20,60,120]); // 波动率锥
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
#### 回撤分析
|
|
243
|
+
|
|
244
|
+
```typescript
|
|
245
|
+
const dd = maxDrawdown(nav, dates?);
|
|
246
|
+
|
|
247
|
+
// dd.maxDrawdown — 最大回撤(负数,如 -0.25)
|
|
248
|
+
// dd.peakIndex — 回撤起点索引
|
|
249
|
+
// dd.troughIndex — 回撤谷底索引
|
|
250
|
+
// dd.durationDays — 下跌持续天数
|
|
251
|
+
// dd.recoveryDays — 恢复天数(null 表示未恢复)
|
|
252
|
+
// dd.drawdownSeries — 完整回撤序列
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
#### VaR / CVaR
|
|
256
|
+
|
|
257
|
+
```typescript
|
|
258
|
+
calculateVaR(returns, 0.95, 'historical'); // 95% 历史模拟 VaR
|
|
259
|
+
calculateVaR(returns, 0.99, 'parametric'); // 99% 参数法 VaR
|
|
260
|
+
calculateCVaR(returns, 0.95); // 95% 条件在险价值
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
#### 风险指标汇总
|
|
264
|
+
|
|
265
|
+
```typescript
|
|
266
|
+
const risk = riskMetrics(nav, 0.025);
|
|
267
|
+
// risk.annualizedVolatility — 年化波动率
|
|
268
|
+
// risk.downsideVolatility — 下行波动率
|
|
269
|
+
// risk.maxDrawdown — 最大回撤
|
|
270
|
+
// risk.maxDrawdownDuration — 最大回撤持续天数
|
|
271
|
+
// risk.var95 / risk.var99 — VaR
|
|
272
|
+
// risk.cvar95 / risk.cvar99 — CVaR
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
#### 绩效评价指标
|
|
276
|
+
|
|
277
|
+
| 函数 | 公式 |
|
|
278
|
+
|------|------|
|
|
279
|
+
| `sharpeRatio(nav, rf?)` | (年化收益 - 无风险利率) / 年化波动率 |
|
|
280
|
+
| `sortinoRatio(nav, rf?)` | (年化收益 - 无风险利率) / 下行波动率 |
|
|
281
|
+
| `calmarRatio(nav)` | 年化收益 / \|最大回撤\| |
|
|
282
|
+
| `treynorRatio(nav, benchmark, rf?)` | (年化收益 - 无风险利率) / Beta |
|
|
283
|
+
| `omegaRatio(nav, threshold?)` | 加权上行收益 / 加权下行亏损 |
|
|
284
|
+
| `winRate(returns)` | 正收益天数 / 总天数 |
|
|
285
|
+
| `profitLossRatio(returns)` | 平均盈利 / 平均亏损 |
|
|
286
|
+
| `profitFactor(returns)` | 总盈利 / 总亏损 |
|
|
287
|
+
| `consecutiveWinLoss(returns)` | 最大连续盈利/亏损天数 |
|
|
288
|
+
|
|
289
|
+
**一键获取全部绩效指标:**
|
|
290
|
+
|
|
291
|
+
```typescript
|
|
292
|
+
const perf = performanceMetrics(nav, 0.025);
|
|
293
|
+
// perf.totalReturn / .annualizedReturn
|
|
294
|
+
// perf.sharpeRatio / .sortinoRatio / .calmarRatio
|
|
295
|
+
// perf.omegaRatio / .winRate / .profitLossRatio / .profitFactor
|
|
296
|
+
// perf.maxConsecutiveWins / .maxConsecutiveLosses
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
#### 基准对比指标
|
|
300
|
+
|
|
301
|
+
```typescript
|
|
302
|
+
const bm = benchmarkMetrics(fundNav, benchmarkNav, 0.025);
|
|
303
|
+
// bm.alpha — Alpha(超额收益)
|
|
304
|
+
// bm.beta — Beta 系数
|
|
305
|
+
// bm.trackingError — 跟踪误差(年化)
|
|
306
|
+
// bm.informationRatio — 信息比率
|
|
307
|
+
// bm.correlation — 相关系数
|
|
308
|
+
// bm.rSquared — R²
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
---
|
|
312
|
+
|
|
313
|
+
### 3. 统计特征模块 (`statistics`)
|
|
314
|
+
|
|
315
|
+
```typescript
|
|
316
|
+
import {
|
|
317
|
+
statisticalFeatures, hurstExponent, autocorrelation,
|
|
318
|
+
ljungBoxTest, garch11, returnQuantiles,
|
|
319
|
+
rollingSkewness, rollingKurtosis,
|
|
320
|
+
} from '@stvy/fund-indicators';
|
|
321
|
+
|
|
322
|
+
// 完整统计特征
|
|
323
|
+
const stats = statisticalFeatures(nav);
|
|
324
|
+
// stats.mean / .median / .stdDev
|
|
325
|
+
// stats.skewness / .kurtosis
|
|
326
|
+
// stats.jarqueBera — 正态性检验
|
|
327
|
+
|
|
328
|
+
// 赫斯特指数
|
|
329
|
+
const h = hurstExponent(nav);
|
|
330
|
+
// h.hurstExponent — >0.5 趋势性 / <0.5 均值回归 / ≈0.5 随机
|
|
331
|
+
// h.interpretation — 'trending' | 'mean_reverting' | 'random_walk'
|
|
332
|
+
|
|
333
|
+
// 自相关分析
|
|
334
|
+
const acf = autocorrelation(nav, 20);
|
|
335
|
+
// acf.coefficients — 各滞后期自相关系数
|
|
336
|
+
// acf.interpretation — 'persistent' | 'anti_persistent' | 'no_correlation'
|
|
337
|
+
|
|
338
|
+
// Ljung-Box 检验
|
|
339
|
+
const lb = ljungBoxTest(returns, 10);
|
|
340
|
+
// lb.qStatistic / lb.approximatePValue
|
|
341
|
+
|
|
342
|
+
// GARCH(1,1) 波动率预测
|
|
343
|
+
const g = garch11(returns);
|
|
344
|
+
// g.nextPeriodForecast — 下一期条件方差预测
|
|
345
|
+
// g.omega / g.alpha / g.beta — GARCH 参数
|
|
346
|
+
|
|
347
|
+
// 收益率分位数
|
|
348
|
+
const quantiles = returnQuantiles(nav, [0.01, 0.05, 0.5, 0.95, 0.99]);
|
|
349
|
+
|
|
350
|
+
// 滚动偏度/峰度
|
|
351
|
+
const skew = rollingSkewness(returns, 60);
|
|
352
|
+
const kurt = rollingKurtosis(returns, 60);
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
---
|
|
356
|
+
|
|
357
|
+
### 4. 定投与盈亏分析模块 (`dca`)
|
|
358
|
+
|
|
359
|
+
#### 定投模拟
|
|
360
|
+
|
|
361
|
+
```typescript
|
|
362
|
+
const dca = simulateDCA(nav, {
|
|
363
|
+
amount: 1000, // 每次投入金额
|
|
364
|
+
interval: 22, // 定投周期(交易日数),22 ≈ 每月
|
|
365
|
+
startIndex: 0, // 起始位置
|
|
366
|
+
});
|
|
367
|
+
|
|
368
|
+
// dca.totalInvestments — 定投次数
|
|
369
|
+
// dca.totalInvested — 总投入金额
|
|
370
|
+
// dca.currentValue — 当前市值
|
|
371
|
+
// dca.averageCost — 平均持仓成本
|
|
372
|
+
// dca.returnRate — 收益率
|
|
373
|
+
// dca.irr — 内部收益率(年化)
|
|
374
|
+
```
|
|
375
|
+
|
|
376
|
+
#### 止盈止损
|
|
377
|
+
|
|
378
|
+
```typescript
|
|
379
|
+
// 固定止盈止损
|
|
380
|
+
const signal = takeProfitStopLoss(nav, costPrice, 0.30, -0.15);
|
|
381
|
+
// signal.takeProfitTriggered — 是否触发 30% 止盈
|
|
382
|
+
// signal.stopLossTriggered — 是否触发 15% 止损
|
|
383
|
+
|
|
384
|
+
// 跟踪止盈(从最高点回撤 N% 触发)
|
|
385
|
+
const trail = trailingStop(nav, 0.10, costPrice);
|
|
386
|
+
// trail.triggered — 是否触发
|
|
387
|
+
// trail.drawdownFromPeak — 距最高点回撤幅度
|
|
388
|
+
```
|
|
389
|
+
|
|
390
|
+
#### 智能定投
|
|
391
|
+
|
|
392
|
+
```typescript
|
|
393
|
+
// 根据净值相对均线位置动态调整定投金额
|
|
394
|
+
const multiplier = smartDCAMultiplier(nav, 250, 2.0, 0.5);
|
|
395
|
+
// 低于均线时 > 1(加大投入),高于均线时 < 1(减少投入)
|
|
396
|
+
|
|
397
|
+
// 分批买入/卖出信号
|
|
398
|
+
const buyLevel = tieredBuySignal(nav, [0.3, 0.2, 0.1]);
|
|
399
|
+
const sellLevel = tieredSellSignal(nav, [0.7, 0.8, 0.9]);
|
|
400
|
+
```
|
|
401
|
+
|
|
402
|
+
#### 辅助工具
|
|
403
|
+
|
|
404
|
+
```typescript
|
|
405
|
+
safetyMargin(nav); // 距历史最高点的回撤幅度
|
|
406
|
+
pricePosition(nav); // 当前价格在历史高低点之间的位置(0-1)
|
|
407
|
+
positionPnL(nav, buyIdx, sellIdx?, amount?); // 单笔持仓盈亏明细
|
|
408
|
+
```
|
|
409
|
+
|
|
410
|
+
---
|
|
411
|
+
|
|
412
|
+
### 5. 形态识别模块 (`pattern`)
|
|
413
|
+
|
|
414
|
+
```typescript
|
|
415
|
+
import {
|
|
416
|
+
supportResistance, doubleBottomTop,
|
|
417
|
+
detectGaps, trendStrength, headAndShoulders,
|
|
418
|
+
} from '@stvy/fund-indicators';
|
|
419
|
+
|
|
420
|
+
// 支撑位/阻力位
|
|
421
|
+
const sr = supportResistance(nav, 0.02, 3);
|
|
422
|
+
// sr.supports[0].level / .strength / .touches
|
|
423
|
+
// sr.resistances[0].level / .strength / .touches
|
|
424
|
+
|
|
425
|
+
// 双底(W底) / 双顶(M头)
|
|
426
|
+
const dbt = doubleBottomTop(nav, 60, 0.03, 10);
|
|
427
|
+
// dbt.type — 'double_bottom' | 'double_top' | 'none'
|
|
428
|
+
// dbt.breakout — 是否突破颈线
|
|
429
|
+
// dbt.confidence — 信号强度 0-1
|
|
430
|
+
|
|
431
|
+
// 缺口识别
|
|
432
|
+
const gaps = detectGaps(nav, 0.02);
|
|
433
|
+
// gaps[i].type — 'gap_up' | 'gap_down'
|
|
434
|
+
// gaps[i].gapSize — 缺口大小
|
|
435
|
+
// gaps[i].filled — 是否已回补
|
|
436
|
+
|
|
437
|
+
// 趋势强度评分
|
|
438
|
+
const score = trendStrength(nav, 20); // 0-100
|
|
439
|
+
|
|
440
|
+
// 头肩形态
|
|
441
|
+
const hs = headAndShoulders(nav, 90);
|
|
442
|
+
// hs.type — 'head_and_shoulders_top' | 'head_and_shoulders_bottom' | 'none'
|
|
443
|
+
```
|
|
444
|
+
|
|
445
|
+
---
|
|
446
|
+
|
|
447
|
+
## 完整 API 列表
|
|
448
|
+
|
|
449
|
+
| 模块 | 函数 | 输入 | 输出 |
|
|
450
|
+
|------|------|------|------|
|
|
451
|
+
| **均线** | `sma` `ema` `wma` `dema` `tema` `kama` | `nav, period` | `MAResult` |
|
|
452
|
+
| **趋势** | `macd` | `nav, fast?, slow?, signal?` | `MACDResult` |
|
|
453
|
+
| **动量** | `rsi` `kdj` `roc` `momentum` `williamsR` `cci` `trix` `dpo` `stochasticRSI` `massIndex` | `nav, period?` | `MAResult` / `KDJResult` |
|
|
454
|
+
| **通道** | `bollingerBands` `donchianChannel` `keltnerChannel` | `nav, ...params` | `BollingerResult` / `ChannelResult` |
|
|
455
|
+
| **趋势强度** | `adx` `atr` `sar` | `nav, period?` | `ADXResult` / `MAResult` / `SARResult` |
|
|
456
|
+
| **衍生** | `bias` `navPercentile` `detectCrossSignal` `detectMAAlignment` | `nav, ...` | 各有不同 |
|
|
457
|
+
| **波动率** | `annualizedVolatility` `downsideVolatility` `rollingVolatility` `volatilityCone` | `returns` | `number` / `array` |
|
|
458
|
+
| **回撤** | `maxDrawdown` `maxDrawdownDuration` | `nav, dates?` | `DrawdownResult` / `number` |
|
|
459
|
+
| **VaR** | `calculateVaR` `calculateCVaR` | `returns, confidence` | `number` |
|
|
460
|
+
| **风险汇总** | `riskMetrics` | `nav, rf?` | `RiskMetrics` |
|
|
461
|
+
| **绩效** | `sharpeRatio` `sortinoRatio` `calmarRatio` `treynorRatio` `omegaRatio` `winRate` `profitLossRatio` `profitFactor` `consecutiveWinLoss` `performanceMetrics` | `nav` / `returns` | `number` / `PerformanceMetrics` |
|
|
462
|
+
| **基准对比** | `calculateBeta` `calculateAlpha` `trackingError` `informationRatio` `benchmarkMetrics` | `nav, benchmark` | `number` / `BenchmarkMetrics` |
|
|
463
|
+
| **统计** | `statisticalFeatures` `navStatisticalFeatures` | `nav` | `StatisticalFeatures` |
|
|
464
|
+
| **Hurst** | `hurstExponent` | `nav, ...` | `HurstResult` |
|
|
465
|
+
| **自相关** | `autocorrelation` `ljungBoxTest` | `nav, maxLag` | `AutocorrelationResult` |
|
|
466
|
+
| **GARCH** | `garch11` | `returns` | `{ conditionalVariance, nextPeriodForecast, ... }` |
|
|
467
|
+
| **分布** | `returnQuantiles` `rollingSkewness` `rollingKurtosis` | `nav` / `returns` | `Map` / `array` |
|
|
468
|
+
| **定投** | `simulateDCA` | `nav, config` | `DCAResult` |
|
|
469
|
+
| **止盈止损** | `takeProfitStopLoss` `trailingStop` | `nav, cost, ...` | `TakeProfitStopLossSignal` |
|
|
470
|
+
| **智能定投** | `smartDCAMultiplier` `tieredBuySignal` `tieredSellSignal` | `nav, ...` | `number` |
|
|
471
|
+
| **辅助** | `safetyMargin` `pricePosition` `positionPnL` | `nav, ...` | `number` / `object` |
|
|
472
|
+
| **形态** | `supportResistance` `doubleBottomTop` `detectGaps` `trendStrength` `headAndShoulders` | `nav, ...` | 各有不同 |
|
|
473
|
+
|
|
474
|
+
---
|
|
475
|
+
|
|
476
|
+
## 数据要求
|
|
477
|
+
|
|
478
|
+
本库仅需要**历史每日净值序列**即可工作,不需要成交量、持仓、资金流等额外数据。
|
|
479
|
+
|
|
480
|
+
输入格式要求:
|
|
481
|
+
|
|
482
|
+
```typescript
|
|
483
|
+
// 按日期升序排列的净值数组
|
|
484
|
+
const nav: number[] = [1.0000, 1.0032, 0.9985, 1.0120, ...];
|
|
485
|
+
```
|
|
486
|
+
|
|
487
|
+
注意事项:
|
|
488
|
+
|
|
489
|
+
- 净值序列应按时间正序排列(最早的在前)
|
|
490
|
+
- 建议至少提供 60 个数据点,部分指标(如 Hurst 指数、GARCH)建议 250+
|
|
491
|
+
- 分红会导致净值跳变,建议使用**复权净值**(累计净值或分红再投资净值)
|
|
492
|
+
- 年化参数基于 A 股 **242 个交易日**,如需适配其他市场可修改 `TRADING_DAYS_PER_YEAR` 常量
|
|
493
|
+
|
|
494
|
+
---
|
|
495
|
+
|
|
496
|
+
## 开发指南
|
|
497
|
+
|
|
498
|
+
### 环境要求
|
|
499
|
+
|
|
500
|
+
- Node.js >= 18
|
|
501
|
+
- npm >= 9
|
|
502
|
+
|
|
503
|
+
### 本地开发
|
|
504
|
+
|
|
505
|
+
```bash
|
|
506
|
+
# 克隆项目
|
|
507
|
+
git clone https://github.com/stevieyu/fund-indicators.git
|
|
508
|
+
cd fund-indicators
|
|
509
|
+
|
|
510
|
+
# 安装依赖
|
|
511
|
+
npm install
|
|
512
|
+
|
|
513
|
+
# 运行测试
|
|
514
|
+
npm test
|
|
515
|
+
|
|
516
|
+
# 编译 TypeScript
|
|
517
|
+
npm run build
|
|
518
|
+
```
|
|
519
|
+
|
|
520
|
+
### 项目结构
|
|
521
|
+
|
|
522
|
+
```
|
|
523
|
+
fund-indicators/
|
|
524
|
+
├── src/
|
|
525
|
+
│ ├── index.ts # 统一导出入口
|
|
526
|
+
│ ├── types.ts # 完整类型定义(30+ 接口)
|
|
527
|
+
│ ├── technical.ts # 技术指标(均线/MACD/RSI/KDJ/布林带/通道)
|
|
528
|
+
│ ├── risk.ts # 风险与绩效(波动率/回撤/VaR/夏普/Alpha/Beta)
|
|
529
|
+
│ ├── statistics.ts # 统计特征(偏度/峰度/Hurst/GARCH/自相关)
|
|
530
|
+
│ ├── dca.ts # 定投分析(模拟/IRR/智能定投/止盈止损)
|
|
531
|
+
│ ├── pattern.ts # 形态识别(支撑阻力/双底双顶/头肩/缺口)
|
|
532
|
+
│ └── jstat.d.ts # jstat 类型声明
|
|
533
|
+
├── scripts/
|
|
534
|
+
│ └── build-browser.mjs # 浏览器构建脚本(esbuild)
|
|
535
|
+
├── test/
|
|
536
|
+
│ └── index.test.ts # 35 项验证测试
|
|
537
|
+
├── dist/
|
|
538
|
+
│ ├── *.js / *.d.ts # Node.js 构建产物(CommonJS + 类型声明)
|
|
539
|
+
│ └── browser/ # 浏览器构建产物(IIFE + ESM)
|
|
540
|
+
├── .github/
|
|
541
|
+
│ └── workflows/
|
|
542
|
+
│ ├── ci.yml # CI 持续集成(Node LTS)
|
|
543
|
+
│ └── publish.yml # Release 时自动发布到 npm
|
|
544
|
+
├── package.json
|
|
545
|
+
├── tsconfig.json
|
|
546
|
+
├── .gitignore
|
|
547
|
+
├── LICENSE
|
|
548
|
+
└── README.md
|
|
549
|
+
```
|
|
550
|
+
|
|
551
|
+
---
|
|
552
|
+
|
|
553
|
+
## 依赖说明
|
|
554
|
+
|
|
555
|
+
| 依赖 | 用途 | 大小 |
|
|
556
|
+
|------|------|------|
|
|
557
|
+
| [technicalindicators](https://github.com/anandanand84/technicalindicators) | 经典技术指标计算(均线/MACD/RSI/布林带等) | ~150KB |
|
|
558
|
+
| [simple-statistics](https://github.com/simple-statistics/simple-statistics) | 统计函数(标准差/偏度/峰度/回归/分位数等) | ~50KB |
|
|
559
|
+
| [jstat](https://github.com/jstat/jstat) | 概率分布函数(正态/卡方/t分布,用于 VaR 计算) | ~30KB |
|
|
560
|
+
|
|
561
|
+
---
|
|
562
|
+
|
|
563
|
+
## 贡献指南
|
|
564
|
+
|
|
565
|
+
欢迎贡献代码!请遵循以下流程:
|
|
566
|
+
|
|
567
|
+
1. Fork 本项目
|
|
568
|
+
2. 创建功能分支 (`git checkout -b feature/amazing-feature`)
|
|
569
|
+
3. 编写代码和对应的测试
|
|
570
|
+
4. 确保测试通过 (`npm test`) 和 TypeScript 编译无错误 (`npm run build`)
|
|
571
|
+
5. 提交代码 (`git commit -m 'feat: add amazing feature'`)
|
|
572
|
+
6. 推送分支 (`git push origin feature/amazing-feature`)
|
|
573
|
+
7. 创建 Pull Request
|
|
574
|
+
|
|
575
|
+
### 提交规范
|
|
576
|
+
|
|
577
|
+
本项目遵循 [Conventional Commits](https://www.conventionalcommits.org/) 规范:
|
|
578
|
+
|
|
579
|
+
- `feat:` 新功能
|
|
580
|
+
- `fix:` Bug 修复
|
|
581
|
+
- `docs:` 文档变更
|
|
582
|
+
- `test:` 测试相关
|
|
583
|
+
- `refactor:` 重构
|
|
584
|
+
- `perf:` 性能优化
|
|
585
|
+
- `chore:` 构建/工具变更
|
|
586
|
+
|
|
587
|
+
---
|
|
588
|
+
|
|
589
|
+
## 常见问题
|
|
590
|
+
|
|
591
|
+
**Q: 基金净值没有成交量数据,ATR 和 OBV 等指标能用吗?**
|
|
592
|
+
|
|
593
|
+
A: 可以。基金净值没有日内高低点,本库将 high/low/close 均设为当日净值。ATR 退化为 EMA(|ΔNAV|),仍可用于度量日常波动幅度。OBV 因缺少量数据而无意义,不建议使用。
|
|
594
|
+
|
|
595
|
+
**Q: 年化参数为什么是 242?**
|
|
596
|
+
|
|
597
|
+
A: A 股每年约 242 个交易日。如果你分析港股(约 250 天)或美股(约 252 天),可以 fork 后修改 `TRADING_DAYS_PER_YEAR` 常量。
|
|
598
|
+
|
|
599
|
+
**Q: 如何处理基金分红导致的净值跳变?**
|
|
600
|
+
|
|
601
|
+
A: 建议使用**复权净值**(累计净值或分红再投资净值)作为输入。如果使用单位净值,分红会导致净值突降,影响指标计算准确性。本库的 `detectGaps` 函数可以帮助识别这类异常跳变。
|
|
602
|
+
|
|
603
|
+
**Q: 为什么 Hurst 指数结果不稳定?**
|
|
604
|
+
|
|
605
|
+
A: Hurst 指数的 R/S 分析对数据长度敏感,建议至少使用 500 个数据点。数据过短时 R² 较低,结果不可靠。可以通过 `hurst.rSquared` 评估结果可信度(R² > 0.9 较好)。
|
|
606
|
+
|
|
607
|
+
---
|
|
608
|
+
|
|
609
|
+
## 许可证
|
|
610
|
+
|
|
611
|
+
[MIT](LICENSE)
|
|
612
|
+
|
|
613
|
+
---
|
|
614
|
+
|
|
615
|
+
## 致谢
|
|
616
|
+
|
|
617
|
+
本项目的技术指标计算基于 [technicalindicators](https://github.com/anandanand84/technicalindicators),统计分析基于 [simple-statistics](https://github.com/simple-statistics/simple-statistics),概率分布计算基于 [jstat](https://github.com/jstat/jstat)。感谢这些优秀的开源项目。
|