Bondya commited on
Commit
79cc9b7
·
verified ·
1 Parent(s): bd5f654

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +285 -133
index.html CHANGED
@@ -254,6 +254,43 @@
254
  color: #666;
255
  font-size: 0.9rem;
256
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
257
  </style>
258
  </head>
259
  <body>
@@ -262,7 +299,7 @@
262
  <div class="logo">
263
  <h1>财顾报价通</h1>
264
  </div>
265
- <p class="subtitle">理财公司预期收益率报价系统</p>
266
  </header>
267
 
268
  <div class="calculator">
@@ -298,7 +335,7 @@
298
  <div id="plus-section" class="form-group hidden">
299
  <label>增强资产类别</label>
300
  <div class="button-group">
301
- <button class="btn" data-type="asset" data-value="CONVERTIBLE_BOND">转债</button>
302
  <button class="btn" data-type="asset" data-value="EQUITY">权益</button>
303
  <button class="btn" data-type="asset" data-value="REITS">REITs</button>
304
  </div>
@@ -309,6 +346,9 @@
309
  <button class="btn active" data-type="expectation" data-value="NEUTRAL">中性</button>
310
  <button class="btn" data-type="expectation" data-value="OPTIMISTIC">乐观</button>
311
  </div>
 
 
 
312
  </div>
313
 
314
  <button id="calculate" class="calculate-btn">🚀 计算预期收益率</button>
@@ -331,20 +371,20 @@
331
  </div>
332
  <div class="preview-item hidden" id="preview-asset-item">
333
  <span class="preview-label">增强资产:</span>
334
- <span id="preview-asset" class="preview-value">-</span>
335
  </div>
336
  <div class="preview-item hidden" id="preview-expectation-item">
337
  <span class="preview-label">资产预期:</span>
338
- <span id="preview-expectation" class="preview-value">-</span>
339
  </div>
340
  </div>
341
 
342
  <h2 style="margin-top: 30px;">✨ 系统特点</h2>
343
  <ul class="feature-list">
344
  <li><i>✓</i> 基于量化模型计算</li>
345
- <li><i>✓</i> 考虑资本利得概率分布</li>
346
- <li><i>✓</i> 提供市场实际参考区间</li>
347
- <li><i>✓</i> 支持纯债/固收+策略</li>
348
  <li><i>✓</i> 纯前端计算,保护隐私</li>
349
  </ul>
350
  </div>
@@ -375,7 +415,6 @@
375
  expectation: 'NEUTRAL',
376
 
377
  updatePreview() {
378
- // 更新预览显示
379
  document.getElementById('preview-strategy').textContent =
380
  this.strategy === 'PURE_BOND' ? '纯债策略' : '固收+策略';
381
  document.getElementById('preview-period').textContent =
@@ -383,7 +422,6 @@
383
  document.getElementById('preview-risk').textContent =
384
  this.getRiskLabel(this.risk);
385
 
386
- // 显示/隐藏固收+相关预览
387
  const plusSection = document.getElementById('plus-section');
388
  const assetPreview = document.getElementById('preview-asset-item');
389
  const expectationPreview = document.getElementById('preview-expectation-item');
@@ -441,39 +479,122 @@
441
  }
442
  };
443
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
444
  // 初始化
445
  document.addEventListener('DOMContentLoaded', function() {
446
- // 按钮点击事件
447
  document.querySelectorAll('.btn').forEach(btn => {
448
  btn.addEventListener('click', function() {
449
  const type = this.dataset.type;
450
  const value = this.dataset.value;
451
 
452
- // 移除同类型按钮的active类
453
  document.querySelectorAll(`.btn[data-type="${type}"]`).forEach(b => {
454
  b.classList.remove('active');
455
  });
456
 
457
- // 为当前按钮添加active类
458
  this.classList.add('active');
459
 
460
- // 更新状态
461
  state[type] = value;
462
  state.updatePreview();
463
  });
464
  });
465
 
466
- // 计算按钮事件
467
  document.getElementById('calculate').addEventListener('click', calculateQuotation);
468
  });
469
 
470
  // 计算核心函数
471
  function calculateQuotation() {
472
- // 显示加载动画
473
  document.getElementById('loading').classList.remove('hidden');
474
  document.getElementById('result').classList.add('hidden');
475
 
476
- // 模拟计算延迟
477
  setTimeout(() => {
478
  try {
479
  const result = performCalculation();
@@ -490,34 +611,49 @@
490
  function performCalculation() {
491
  const { strategy, period, risk, asset, expectation } = state;
492
 
493
- // 默认收益率数据
494
  const defaultReturns = {
495
- // 短期资产
496
- "7d_notice_deposit": 1.2,
497
- "3m_state_ncd": 2.0,
498
- "overnight_rate": 1.5,
499
 
500
- // 中期资产
501
- "gov_bond_under_1y": 2.1,
502
- "gov_bond_under_2y": 2.3,
503
- "gov_bond_under_3y": 2.5,
504
- "gov_bond_under_5y": 2.8,
505
 
506
- // 同业存单
507
- "ncd_1y_state": 2.2,
508
- "ncd_1y_aaa": 2.4,
509
- "ncd_1y_aa": 2.8,
510
 
511
- // 信用债
512
- "credit_1y_aaa_plus": 2.3,
513
- "credit_1y_aaa": 2.6,
514
- "credit_1y_aa": 3.2,
515
- "credit_2y_aaa_plus": 2.5,
516
- "credit_2y_aaa": 2.8,
517
- "credit_2y_aa": 3.5,
518
  };
519
 
520
- // 市场参考数据您提供的数据)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
521
  const marketRef = {
522
  pure_bond: {
523
  'SHORT': [1.24, 1.40],
@@ -531,32 +667,8 @@
531
  }
532
  };
533
 
534
- // 资本利得计算(简化版
535
- function calculateCapitalGain() {
536
- // 模拟正态分布
537
- const mean = 0.03; // 平均3bp/次
538
- const std = 0.04; // 标准差4bp/次
539
- const cycles = 3; // 年波动次数
540
-
541
- // 计算年化分布参数
542
- const annualMean = mean * cycles;
543
- const annualStd = std * Math.sqrt(cycles);
544
-
545
- // 计算80%置信区间
546
- const z80 = 1.28; // 80%置信度的Z值
547
- const lower80 = annualMean - z80 * annualStd;
548
- const upper80 = annualMean + z80 * annualStd;
549
-
550
- return {
551
- lower: lower80,
552
- upper: upper80,
553
- probability: 65 // 正收益概率65%
554
- };
555
- }
556
-
557
- // 纯债策略计算
558
- if (strategy === 'PURE_BOND') {
559
- // 根据期限和风险风格计算基础收益率
560
  let baseReturn = 0;
561
  let leverage = 100;
562
 
@@ -619,46 +731,51 @@
619
  leveredReturn = L * baseReturn - (L - 1) * fundingCost;
620
  }
621
 
622
- // 计算资本利得
623
- const capGain = calculateCapitalGain();
624
- const totalLower = leveredReturn + capGain.lower;
625
- const totalUpper = leveredReturn + capGain.upper;
 
 
 
 
 
 
 
 
 
 
626
 
627
  return {
628
  strategy: '纯债策略',
629
  period: state.getPeriodLabel(period),
630
  risk: state.getRiskLabel(risk),
631
- leverage: leverage + '%',
632
- fundingCost: fundingCost + '%',
633
- baseReturn: leveredReturn.toFixed(2) + '%',
634
- capitalGainRange: `${(capGain.lower * 100).toFixed(1)}bp ~ ${(capGain.upper * 100).toFixed(1)}bp`,
 
 
635
  totalReturn: `${totalLower.toFixed(2)}% ~ ${totalUpper.toFixed(2)}%`,
636
- positiveProbability: capGain.probability + '%',
637
- marketRef: `${marketRef.pure_bond[period][0]}% - ${marketRef.pure_bond[period][1]}%`
 
 
 
638
  };
639
  }
640
  // 固收+策略计算
641
  else {
642
- // 计算纯债部分
643
- let pureBondReturn = 0;
644
-
645
- // 简化计算,使用固定值
646
- if (period === 'SHORT') pureBondReturn = 1.5;
647
- else if (period === 'MEDIUM') pureBondReturn = 2.4;
648
- else pureBondReturn = 2.8;
649
 
650
- // 加上资本利得(取乐观情景
651
- const capGain = calculateCapitalGain();
652
- pureBondReturn += capGain.upper;
653
 
654
- // 资产预期收益率
655
- const assetReturns = {
656
- 'CONVERTIBLE_BOND': { 'PESSIMISTIC': 10.0, 'NEUTRAL': 12.5, 'OPTIMISTIC': 15.0 },
657
- 'EQUITY': { 'PESSIMISTIC': 15.0, 'NEUTRAL': 17.5, 'OPTIMISTIC': 20.0 },
658
- 'REITS': { 'PESSIMISTIC': 5.0, 'NEUTRAL': 7.5, 'OPTIMISTIC': 10.0 }
659
- };
660
-
661
- const assetReturn = assetReturns[asset][expectation];
662
 
663
  // 配置比例
664
  let bondWeight, assetWeight;
@@ -676,20 +793,38 @@
676
  // 计算总收益率
677
  const totalReturn = (pureBondReturn * bondWeight + assetReturn * assetWeight) / 100;
678
 
 
 
 
 
 
 
679
  return {
680
  strategy: '固收+策略',
681
  period: state.getPeriodLabel(period),
682
  risk: state.getRiskLabel(risk),
683
  asset: state.getAssetLabel(asset),
684
  expectation: state.getExpectationLabel(expectation),
 
685
  bondWeight: bondWeight + '%',
686
  assetWeight: assetWeight + '%',
 
 
 
687
  pureBondReturn: pureBondReturn.toFixed(2) + '%',
688
- assetReturn: assetReturn.toFixed(1) + '%',
 
689
  totalReturn: totalReturn.toFixed(2) + '%',
690
- capitalGain: (capGain.upper * 100).toFixed(1) + 'bp',
691
- positiveProbability: capGain.probability + '%',
692
- marketRef: `${marketRef.fixed_income_plus[period][0]}% - ${marketRef.fixed_income_plus[period][1]}%`
 
 
 
 
 
 
 
693
  };
694
  }
695
  }
@@ -733,7 +868,12 @@
733
  </div>
734
  <div class="result-item">
735
  <span>资产预期:</span>
736
- <span>${result.expectation}</span>
 
 
 
 
 
737
  </div>
738
  <div class="result-item">
739
  <span>债券比例:</span>
@@ -753,48 +893,56 @@
753
 
754
  if (result.strategy === '纯债策略') {
755
  html += `
756
- <div class="result-item">
757
- <span>基础收益率:</span>
758
- <span>${result.baseReturn}</span>
 
 
 
 
 
 
 
 
 
 
759
  </div>
760
- <div class="result-item">
761
- <span>资本利得贡献:</span>
762
- <span>${result.capitalGainRange}</span>
763
- </div>
764
- <div class="result-item">
765
- <span>理论预期收益率:</span>
766
- <span class="highlight">${result.totalReturn}</span>
767
- </div>
768
- <div class="result-item">
769
  <span>正收益概率:</span>
770
  <span>${result.positiveProbability}</span>
771
  </div>`;
772
  } else {
773
  html += `
774
- <div class="result-item">
775
- <span>纯债部分收益率:</span>
776
- <span>${result.pureBondReturn}</span>
777
- </div>
778
- <div class="result-item">
779
- <span>资本利得贡献:</span>
780
- <span>${result.capitalGain}</span>
781
- </div>
782
- <div class="result-item">
783
- <span>资产预期收益率:</span>
784
- <span>${result.assetReturn}</span>
 
 
 
 
 
 
 
 
 
 
785
  </div>
786
- <div class="result-item">
787
- <span>理论预期收益率:</span>
788
- <span class="highlight">${result.totalReturn}</span>
789
- </div>
790
- <div class="result-item">
791
  <span>正收益概率:</span>
792
  <span>${result.positiveProbability}</span>
793
  </div>`;
794
  }
795
 
796
  html += `
797
- <div class="result-item">
798
  <span>市场实际参考区间:</span>
799
  <span>${result.marketRef}</span>
800
  </div>
@@ -802,17 +950,21 @@
802
  </div>
803
 
804
  <div style="margin-top: 30px; padding: 20px; background: #f0f8ff; border-radius: 8px;">
805
- <h3>💡 使用说明</h3>
806
- <p>1. 以上计算结果基于预设的量化模型和市场</p>
807
- <p>2. 资本利得考虑了交易员的波段操作能力和市场波动</p>
808
- <p>3. 市场参考区间基于近实际理财收益率数据</p>
809
- <p>4. 计算结果仅供参考,实际收益可能受多种因素影响</p>
 
 
 
 
 
 
810
  </div>`;
811
 
812
  content.innerHTML = html;
813
  document.getElementById('result').classList.remove('hidden');
814
-
815
- // 滚动到结果区域
816
  document.getElementById('result').scrollIntoView({ behavior: 'smooth' });
817
  }
818
  </script>
 
254
  color: #666;
255
  font-size: 0.9rem;
256
  }
257
+
258
+ .contribution-breakdown {
259
+ background: #f0f8ff;
260
+ padding: 15px;
261
+ border-radius: 6px;
262
+ margin-top: 15px;
263
+ }
264
+
265
+ .contribution-item {
266
+ display: flex;
267
+ justify-content: space-between;
268
+ margin-bottom: 8px;
269
+ font-size: 0.95rem;
270
+ }
271
+
272
+ .range-indicator {
273
+ display: inline-block;
274
+ padding: 2px 8px;
275
+ border-radius: 4px;
276
+ font-size: 0.85rem;
277
+ margin-left: 5px;
278
+ }
279
+
280
+ .range-pessimistic {
281
+ background: #ffebee;
282
+ color: #c62828;
283
+ }
284
+
285
+ .range-neutral {
286
+ background: #fff3e0;
287
+ color: #ef6c00;
288
+ }
289
+
290
+ .range-optimistic {
291
+ background: #e8f5e9;
292
+ color: #2e7d32;
293
+ }
294
  </style>
295
  </head>
296
  <body>
 
299
  <div class="logo">
300
  <h1>财顾报价通</h1>
301
  </div>
302
+ <p class="subtitle">理财公司预期收益率报价系统 - 增强版</p>
303
  </header>
304
 
305
  <div class="calculator">
 
335
  <div id="plus-section" class="form-group hidden">
336
  <label>增强资产类别</label>
337
  <div class="button-group">
338
+ <button class="btn active" data-type="asset" data-value="CONVERTIBLE_BOND">转债</button>
339
  <button class="btn" data-type="asset" data-value="EQUITY">权益</button>
340
  <button class="btn" data-type="asset" data-value="REITS">REITs</button>
341
  </div>
 
346
  <button class="btn active" data-type="expectation" data-value="NEUTRAL">中性</button>
347
  <button class="btn" data-type="expectation" data-value="OPTIMISTIC">乐观</button>
348
  </div>
349
+ <div style="margin-top: 10px; font-size: 0.9rem; color: #666; padding: 8px; background: #f5f5f5; border-radius: 4px;">
350
+ <div><strong>配置比例:</strong> 悲观(95%债+5%资产) | 中性(90%债+10%资产) | 乐观(80%债+20%资产)</div>
351
+ </div>
352
  </div>
353
 
354
  <button id="calculate" class="calculate-btn">🚀 计算预期收益率</button>
 
371
  </div>
372
  <div class="preview-item hidden" id="preview-asset-item">
373
  <span class="preview-label">增强资产:</span>
374
+ <span id="preview-asset" class="preview-value">转债</span>
375
  </div>
376
  <div class="preview-item hidden" id="preview-expectation-item">
377
  <span class="preview-label">资产预期:</span>
378
+ <span id="preview-expectation" class="preview-value">中性</span>
379
  </div>
380
  </div>
381
 
382
  <h2 style="margin-top: 30px;">✨ 系统特点</h2>
383
  <ul class="feature-list">
384
  <li><i>✓</i> 基于量化模型计算</li>
385
+ <li><i>✓</i> 正态分布资本利得模型</li>
386
+ <li><i>✓</i> 详细收益贡献分解</li>
387
+ <li><i>✓</i> 市场实际参考区间</li>
388
  <li><i>✓</i> 纯前端计算,保护隐私</li>
389
  </ul>
390
  </div>
 
415
  expectation: 'NEUTRAL',
416
 
417
  updatePreview() {
 
418
  document.getElementById('preview-strategy').textContent =
419
  this.strategy === 'PURE_BOND' ? '纯债策略' : '固收+策略';
420
  document.getElementById('preview-period').textContent =
 
422
  document.getElementById('preview-risk').textContent =
423
  this.getRiskLabel(this.risk);
424
 
 
425
  const plusSection = document.getElementById('plus-section');
426
  const assetPreview = document.getElementById('preview-asset-item');
427
  const expectationPreview = document.getElementById('preview-expectation-item');
 
479
  }
480
  };
481
 
482
+ // 正态分布函数
483
+ function normalCDF(x, mean = 0, std = 1) {
484
+ return 0.5 * (1 + erf((x - mean) / (std * Math.sqrt(2))));
485
+ }
486
+
487
+ function erf(x) {
488
+ const a1 = 0.254829592;
489
+ const a2 = -0.284496736;
490
+ const a3 = 1.421413741;
491
+ const a4 = -1.453152027;
492
+ const a5 = 1.061405429;
493
+ const p = 0.3275911;
494
+
495
+ const sign = (x >= 0) ? 1 : -1;
496
+ x = Math.abs(x);
497
+
498
+ const t = 1.0 / (1.0 + p * x);
499
+ const y = 1.0 - (((((a5 * t + a4) * t) + a3) * t + a2) * t + a1) * t * Math.exp(-x * x);
500
+
501
+ return sign * y;
502
+ }
503
+
504
+ function normalQuantile(p, mean = 0, std = 1) {
505
+ if (p <= 0 || p >= 1) return mean;
506
+
507
+ const a1 = -39.6968302866538, a2 = 220.946098424521, a3 = -275.928510446969;
508
+ const a4 = 138.357751867269, a5 = -30.6647980661472, a6 = 2.50662827745924;
509
+
510
+ const b1 = -54.4760987982241, b2 = 161.585836858041, b3 = -155.698979859887;
511
+ const b4 = 66.8013118877197, b5 = -13.2806815528857;
512
+
513
+ const c1 = -7.78489400243029E-03, c2 = -0.322396458041136, c3 = -2.40075827716184;
514
+ const c4 = -2.54973253934373, c5 = 4.37466414146497, c6 = 2.93816398269878;
515
+
516
+ const d1 = 7.78469570904146E-03, d2 = 0.32246712907004, d3 = 2.445134137143;
517
+ const d4 = 3.75440866190742;
518
+
519
+ let q, r;
520
+
521
+ if (p < 0.02425) {
522
+ q = Math.sqrt(-2 * Math.log(p));
523
+ return mean + std * (((((c1 * q + c2) * q + c3) * q + c4) * q + c5) * q + c6) /
524
+ ((((d1 * q + d2) * q + d3) * q + d4) * q + 1);
525
+ } else if (p <= 0.97575) {
526
+ q = p - 0.5;
527
+ r = q * q;
528
+ return mean + std * (((((a1 * r + a2) * r + a3) * r + a4) * r + a5) * r + a6) * q /
529
+ (((((b1 * r + b2) * r + b3) * r + b4) * r + b5) * r + 1);
530
+ } else {
531
+ q = Math.sqrt(-2 * Math.log(1 - p));
532
+ return mean + std * -(((((c1 * q + c2) * q + c3) * q + c4) * q + c5) * q + c6) /
533
+ ((((d1 * q + d2) * q + d3) * q + d4) * q + 1);
534
+ }
535
+ }
536
+
537
+ // 计算资本利得区间(基于正态分布)
538
+ function calculateCapitalGainRange(period) {
539
+ // 确定波段次数
540
+ let cycles;
541
+ switch(period) {
542
+ case 'SHORT': cycles = 1; break; // 0-3个月:1次
543
+ case 'MEDIUM': cycles = 1.5; break; // 3-6个月:1.5次
544
+ case 'LONG': cycles = 3; break; // 6-12个月:3次
545
+ default: cycles = 1;
546
+ }
547
+
548
+ // 单次波段参数:标准正态分布,±15bp波动(标准差15bp)
549
+ const singleStd = 15; // 15bp标准差
550
+ const singleMean = 0; // 均值为0,表示对称波动
551
+
552
+ // 年化分布参数(n次独立同分布的和)
553
+ const annualMean = singleMean * cycles;
554
+ const annualStd = singleStd * Math.sqrt(cycles);
555
+
556
+ // 计算50%-80%交易员的收益区间(即第25百分位到第75百分位)
557
+ const p25 = normalQuantile(0.25, annualMean, annualStd);
558
+ const p75 = normalQuantile(0.75, annualMean, annualStd);
559
+
560
+ // 计算正收益概率
561
+ const positiveProb = (1 - normalCDF(0, annualMean, annualStd)) * 100;
562
+
563
+ return {
564
+ lower: p25 / 100, // 转换为百分比
565
+ upper: p75 / 100,
566
+ mean: annualMean / 100,
567
+ std: annualStd / 100,
568
+ positiveProbability: positiveProb.toFixed(1)
569
+ };
570
+ }
571
+
572
  // 初始化
573
  document.addEventListener('DOMContentLoaded', function() {
 
574
  document.querySelectorAll('.btn').forEach(btn => {
575
  btn.addEventListener('click', function() {
576
  const type = this.dataset.type;
577
  const value = this.dataset.value;
578
 
 
579
  document.querySelectorAll(`.btn[data-type="${type}"]`).forEach(b => {
580
  b.classList.remove('active');
581
  });
582
 
 
583
  this.classList.add('active');
584
 
 
585
  state[type] = value;
586
  state.updatePreview();
587
  });
588
  });
589
 
 
590
  document.getElementById('calculate').addEventListener('click', calculateQuotation);
591
  });
592
 
593
  // 计算核心函数
594
  function calculateQuotation() {
 
595
  document.getElementById('loading').classList.remove('hidden');
596
  document.getElementById('result').classList.add('hidden');
597
 
 
598
  setTimeout(() => {
599
  try {
600
  const result = performCalculation();
 
611
  function performCalculation() {
612
  const { strategy, period, risk, asset, expectation } = state;
613
 
614
+ // 使用您提供的默认收益率数据
615
  const defaultReturns = {
616
+ "7d_notice_deposit": 1.35,
617
+ "3m_state_ncd": 1.5,
618
+ "overnight_rate": 1.28,
 
619
 
620
+ "gov_bond_under_1y": 1.33,
621
+ "gov_bond_under_2y": 1.38,
622
+ "gov_bond_under_3y": 1.41,
623
+ "gov_bond_under_5y": 1.55,
 
624
 
625
+ "ncd_1y_state": 1.62,
626
+ "ncd_1y_aaa": 1.64,
627
+ "ncd_1y_aa": 1.68,
 
628
 
629
+ "credit_1y_aaa_plus": 1.62,
630
+ "credit_1y_aaa": 1.66,
631
+ "credit_1y_aa": 2.1,
632
+ "credit_2y_aaa_plus": 1.77,
633
+ "credit_2y_aaa": 1.8,
634
+ "credit_2y_aa": 2.9,
 
635
  };
636
 
637
+ // 资产预期收益率区间使用您提供的数据)
638
+ const assetReturnRanges = {
639
+ 'CONVERTIBLE_BOND': {
640
+ 'PESSIMISTIC': { min: 5, max: 8, label: '5-8%' },
641
+ 'NEUTRAL': { min: 8, max: 11, label: '8-11%' },
642
+ 'OPTIMISTIC': { min: 11, max: 14, label: '11-14%' }
643
+ },
644
+ 'EQUITY': {
645
+ 'PESSIMISTIC': { min: 5, max: 10, label: '5-10%' },
646
+ 'NEUTRAL': { min: 10, max: 15, label: '10-15%' },
647
+ 'OPTIMISTIC': { min: 15, max: 20, label: '15-20%' }
648
+ },
649
+ 'REITS': {
650
+ 'PESSIMISTIC': { min: 4, max: 6, label: '4-6%' },
651
+ 'NEUTRAL': { min: 6, max: 8, label: '6-8%' },
652
+ 'OPTIMISTIC': { min: 8, max: 10, label: '8-10%' }
653
+ }
654
+ };
655
+
656
+ // 市场参考数据
657
  const marketRef = {
658
  pure_bond: {
659
  'SHORT': [1.24, 1.40],
 
667
  }
668
  };
669
 
670
+ // 计算基础收益率(不含资本利得)
671
+ function calculateBaseReturn() {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
672
  let baseReturn = 0;
673
  let leverage = 100;
674
 
 
731
  leveredReturn = L * baseReturn - (L - 1) * fundingCost;
732
  }
733
 
734
+ return {
735
+ baseReturn: leveredReturn,
736
+ leverage: leverage,
737
+ fundingCost: fundingCost
738
+ };
739
+ }
740
+
741
+ // 纯债策略计算
742
+ if (strategy === 'PURE_BOND') {
743
+ const bondResult = calculateBaseReturn();
744
+ const capGain = calculateCapitalGainRange(period);
745
+
746
+ const totalLower = bondResult.baseReturn + capGain.lower;
747
+ const totalUpper = bondResult.baseReturn + capGain.upper;
748
 
749
  return {
750
  strategy: '纯债策略',
751
  period: state.getPeriodLabel(period),
752
  risk: state.getRiskLabel(risk),
753
+ leverage: bondResult.leverage + '%',
754
+ fundingCost: bondResult.fundingCost.toFixed(2) + '%',
755
+ baseReturn: bondResult.baseReturn.toFixed(2) + '%',
756
+ capitalGainRange: `${(capGain.lower * 100).toFixed(2)}bp ~ ${(capGain.upper * 100).toFixed(2)}bp`,
757
+ capitalGainLower: capGain.lower,
758
+ capitalGainUpper: capGain.upper,
759
  totalReturn: `${totalLower.toFixed(2)}% ~ ${totalUpper.toFixed(2)}%`,
760
+ totalLower: totalLower,
761
+ totalUpper: totalUpper,
762
+ positiveProbability: capGain.positiveProbability + '%',
763
+ marketRef: `${marketRef.pure_bond[period][0]}% - ${marketRef.pure_bond[period][1]}%`,
764
+ hasCapitalGain: true
765
  };
766
  }
767
  // 固收+策略计算
768
  else {
769
+ // 计算纯债部分
770
+ const bondResult = calculateBaseReturn();
771
+ const capGain = calculateCapitalGainRange(period);
 
 
 
 
772
 
773
+ // 使用乐观情景的资本利得(75分位数
774
+ const pureBondReturn = bondResult.baseReturn + capGain.upper;
 
775
 
776
+ // 获取资产预期收益率(使用中性值)
777
+ const assetRange = assetReturnRanges[asset][expectation];
778
+ const assetReturn = (assetRange.min + assetRange.max) / 2; // 取区间中值
 
 
 
 
 
779
 
780
  // 配置比例
781
  let bondWeight, assetWeight;
 
793
  // 计算总收益率
794
  const totalReturn = (pureBondReturn * bondWeight + assetReturn * assetWeight) / 100;
795
 
796
+ // 计算各部分贡献
797
+ const bondContribution = pureBondReturn * bondWeight / 100;
798
+ const assetContribution = assetReturn * assetWeight / 100;
799
+ const capitalGainContribution = capGain.upper * bondWeight / 100;
800
+ const baseBondContribution = bondResult.baseReturn * bondWeight / 100;
801
+
802
  return {
803
  strategy: '固收+策略',
804
  period: state.getPeriodLabel(period),
805
  risk: state.getRiskLabel(risk),
806
  asset: state.getAssetLabel(asset),
807
  expectation: state.getExpectationLabel(expectation),
808
+ expectationType: expectation,
809
  bondWeight: bondWeight + '%',
810
  assetWeight: assetWeight + '%',
811
+ baseBondReturn: bondResult.baseReturn.toFixed(2) + '%',
812
+ capitalGain: (capGain.upper * 100).toFixed(2) + 'bp',
813
+ capitalGainValue: capGain.upper,
814
  pureBondReturn: pureBondReturn.toFixed(2) + '%',
815
+ assetReturnRange: assetRange.label,
816
+ assetReturn: assetReturn.toFixed(2) + '%',
817
  totalReturn: totalReturn.toFixed(2) + '%',
818
+
819
+ // 贡献分解
820
+ bondContribution: bondContribution.toFixed(2) + '%',
821
+ assetContribution: assetContribution.toFixed(2) + '%',
822
+ capitalGainContribution: capitalGainContribution.toFixed(2) + '%',
823
+ baseBondContribution: baseBondContribution.toFixed(2) + '%',
824
+
825
+ positiveProbability: capGain.positiveProbability + '%',
826
+ marketRef: `${marketRef.fixed_income_plus[period][0]}% - ${marketRef.fixed_income_plus[period][1]}%`,
827
+ hasCapitalGain: true
828
  };
829
  }
830
  }
 
868
  </div>
869
  <div class="result-item">
870
  <span>资产预期:</span>
871
+ <span>${result.expectation}
872
+ <span class="range-indicator range-${result.expectationType.toLowerCase()}">
873
+ ${result.expectationType === 'PESSIMISTIC' ? '悲观' :
874
+ result.expectationType === 'NEUTRAL' ? '中性' : '乐观'}
875
+ </span>
876
+ </span>
877
  </div>
878
  <div class="result-item">
879
  <span>债券比例:</span>
 
893
 
894
  if (result.strategy === '纯债策略') {
895
  html += `
896
+ <div class="contribution-breakdown">
897
+ <div class="contribution-item">
898
+ <span>基础收益率:</span>
899
+ <span>${result.baseReturn}</span>
900
+ </div>
901
+ <div class="contribution-item">
902
+ <span>资本利得贡献:</span>
903
+ <span>${result.capitalGainRange}</span>
904
+ </div>
905
+ <div class="contribution-item" style="margin-top: 10px; padding-top: 10px; border-top: 1px dashed #ddd;">
906
+ <span><strong>理论预期收益率:</strong></span>
907
+ <span class="highlight"><strong>${result.totalReturn}</strong></span>
908
+ </div>
909
  </div>
910
+ <div class="result-item" style="margin-top: 15px;">
 
 
 
 
 
 
 
 
911
  <span>正收益概率:</span>
912
  <span>${result.positiveProbability}</span>
913
  </div>`;
914
  } else {
915
  html += `
916
+ <div class="contribution-breakdown">
917
+ <div class="contribution-item">
918
+ <span>纯债基础部分:</span>
919
+ <span>${result.baseBondReturn}</span>
920
+ </div>
921
+ <div class="contribution-item">
922
+ <span>资本利得贡献:</span>
923
+ <span>${result.capitalGain}</span>
924
+ </div>
925
+ <div class="contribution-item">
926
+ <span>增强资产贡献:</span>
927
+ <span>${result.assetReturn}
928
+ <span class="range-indicator range-${result.expectationType.toLowerCase()}">
929
+ ${result.assetReturnRange}
930
+ </span>
931
+ </span>
932
+ </div>
933
+ <div class="contribution-item" style="margin-top: 10px; padding-top: 10px; border-top: 1px dashed #ddd;">
934
+ <span><strong>理论预期收益率:</strong></span>
935
+ <span class="highlight"><strong>${result.totalReturn}</strong></span>
936
+ </div>
937
  </div>
938
+ <div class="result-item" style="margin-top: 15px;">
 
 
 
 
939
  <span>正收益概率:</span>
940
  <span>${result.positiveProbability}</span>
941
  </div>`;
942
  }
943
 
944
  html += `
945
+ <div class="result-item" style="margin-top: 15px;">
946
  <span>市场实际参考区间:</span>
947
  <span>${result.marketRef}</span>
948
  </div>
 
950
  </div>
951
 
952
  <div style="margin-top: 30px; padding: 20px; background: #f0f8ff; border-radius: 8px;">
953
+ <h3>💡 计算说明</h3>
954
+ <p><strong>资本利得模型:</strong>基于标准正态分布(±15bp波动),不同期限对应不同波段次</p>
955
+ <ul style="margin-left: 20px; margin-top: 5px;">
956
+ <li>(0-3个月):1次波段</li>
957
+ <li>中期(3-6个月):1.5次波段</li>
958
+ <li>长期(6-12个月):3次波段</li>
959
+ </ul>
960
+ <p><strong>展示区间:</strong>50%-80%交易员收益区间(第25-75百分位)</p>
961
+ <p><strong>资产预期:</strong>${result.strategy === '固收+策略' ?
962
+ `采用${result.expectation}预期,${result.asset}指数预测区间为${result.assetReturnRange}` :
963
+ '纯债策略主要依赖票息收入和资本利得'}</p>
964
  </div>`;
965
 
966
  content.innerHTML = html;
967
  document.getElementById('result').classList.remove('hidden');
 
 
968
  document.getElementById('result').scrollIntoView({ behavior: 'smooth' });
969
  }
970
  </script>