# C++计算资本市场收益及成本分配数学方程

<details>

<summary>关键词</summary>

C++ | 利率 | 复利 | 债卷 | 建模 | 现金流 | 模型 | 数学 | 资本市场 | 波动性 | 财务 | 相关性 | 股票 | 分析师 | 价值 | 线性插值 | 多项式插值 | 交易 | 矩阵 | 时间序列 | 卡玛比率 | 统计分布 | 高斯 | 卡方 | 绘图 | Qt C++ | 方程 | 常微分方程 | 偏微分方程 | 中值法 | 梯形法 | 辛普森法 | 欧拉法 | 二分法 | 割线法 | 牛顿法 | 线性规划 | 混合整数规划 | 蒙特卡罗 | 期权 | 概率

</details>

{% embed url="https://viadean.notion.site/C-4982fabd33ca4b5ebd8c6c413cc5c7e9" %}

{% content-ref url="../zhi-dian-mi-jin-brief" %}
[zhi-dian-mi-jin-brief](../zhi-dian-mi-jin-brief)
{% endcontent-ref %}

### 🎯 要点

1. 固定收益市场计算公式和模型：🎯C++计算简单利率。🎯C++计算离散复利利率和连续复利。🎯现金流建模，C++计算未来付款的现值，使用STL容器。🎯债卷建模，创建 C++ 类模拟债券工具并确定其年利率。
2. 股票市场计算公式和模型：🎯C++计算给定股权投资，确定收盘价的简单移动平均线和指数移动平均线。🎯C++计算特定权益工具的波动性。🎯C++计算两种权益工具之间的相关性。🎯C++计算股票基本指标。
3. C++计算技巧：🎯C++计算投资工具的利率。🎯C++计算财务报表并将其返回给调用客户端，同时避免返回数据泄漏。🎯C++确定证券的信用评级。🎯C++处理交易订单（买入、卖出或卖空）。🎯C++处理分析师的建议并返回股票的平均目标价格。🎯C++设计常见时间序列转换（添加或减去价格值以及删除不需要的值）。🎯C++复制存储交易文件。🎯C++处理交易日期。🎯C++矩阵表示交易数据运算。🎯C++使用模板计算阶乘。🎯C++表示卡玛比率，其是投资回报与可能的年度损失相比的衡量标准。 🎯C++生成统计分布，如高斯和卡方。🎯使用绘图工具和Qt C++绘图绘制价格图。
4. 金融数学工具：🎯C++线性代数及其工具。🎯C++线性插值和多项式插值。🎯C++计算方程根方法：二分法、割线法、牛顿法。🎯C++数值积分法：中值法、梯形法、辛普森法和图解。🎯C++使用欧拉法求解常微分方程。🎯C++龙格-库塔法解常微分方程。🎯C++求解布莱克-斯科尔斯方程。🎯C++使用第三方库线性规划求解器。🎯C++线性规划建模，求解决已知回报投资的金融产品分配决策。🎯C++创建混合整数规划模型。
5. 🎯C++使用线性规划模型，确定项目及其成本的最佳资源分配。🎯C++资产定价模型，确定最佳投资组合。🎯C++蒙特卡罗积分函数，模拟资产价格波动。🎯C++计算期权概率。

### 🍇C++牛顿-拉夫逊法寻找隐含波动性

#### 牛顿-拉夫逊法

在满足某些假设的情况下，牛顿拉夫森算法是一种更有效的求根算法。特别是，g 必须具有易于计算的导数。如果导数是可分析计算的，那么这会进一步提高效率。 g 还必须“表现良好”，即它不能变化太大，否则该方法中使用的导数近似会变得更加不准确。

牛顿-拉夫逊的思想是使用解析导数对应该出现解的位置进行线性估计，这比区间二分法所采用的中点方法准确得多。因此，g 的起始近似值 $$g_0$$ 由下式给出（其中$$x_0$$ 是我们的初始猜测）：

$$g_0(x)=g\left(x_0\right)+\left(x-x_0\right) g^{\prime}\left(x_0\right)$$\


这可以重新排列为 x ：

$$x=\frac{y-g\left(x_0\right)}{g^{\prime}\left(x_0\right)}+x_0$$\


这会导致 x 的更准确值的递归关系：

$$x_{n+1}=\frac{y-g\left(x_n\right)}{g^{\prime}\left(x_n\right)}+x_n$$\


对于某些预先指定的容差 $$\epsilon$$，与区间二分一样，当$$\left|g\left(x_n\right)-y\right|<\epsilon$$ 时算法终止。

用我们的金融符号重写，关系变为：

$$\sigma_{n+1}=\frac{C_M-B\left(\sigma_n\right)}{\frac{\partial B}{\partial \sigma}\left(\sigma_n\right)}+\sigma_n$$\


我们可以使用这种关系通过终止标准找到隐含波动率。

#### 算法实现

```cpp
 double call_vega(const double S, const double K, const double r, const double sigma, const double T) {
   return S * sqrt(T) * norm_pdf(d_j(1, S, K, r, sigma, T));
 }
```

以下是 black\_scholes.h 的新标头列表：

```cpp
 #ifndef __BLACK_SCHOLES_H
 #define __BLACK_SCHOLES_H
 ​
 class BlackScholesCall {
 private:
   double S;  
   double K;  
   double r;  
   double T; 
 ​
 public:
   BlackScholesCall(double _S, double _K, 
                    double _r, double _T);
 ​
   double option_price(double sigma) const;
   double option_vega(double sigma) const;
 };
 #endif
```

源列表也已更改为包含 option\_vega 的实现，如 black\_scholes.cpp 中所示：

```cpp
 #ifndef __BLACK_SCHOLES_CPP
 #define __BLACK_SCHOLES_CPP
 ​
 #include "black_scholes.h"
 #include "bs_prices.h"
 ​
 BlackScholesCall::BlackScholesCall(double _S, double _K, 
                                    double _r, double _T) :
   S(_S), K(_K), r(_r), T(_T) {}
 ​
 ​
 double BlackScholesCall::option_price(double sigma) const {
   return call_price(S, K, r, sigma, T);
 }
 ​
 ​
 double BlackScholesCall::option_vega(double sigma) const {
   return call_vega(S, K, r, sigma, T);
 }
 ​
 #endif
```

下一阶段是创建牛顿-拉夫逊求解器本身。函数模板将接受一个 T 类型的对象（函子）和两个指向 T、g 和 g\_prime 的成员函数（方法）的指针。以下是 newton\_raphson.h 的列表：

```cpp
 #ifndef __NEWTON_RAPHSON_H
 #define __NEWTON_RAPHSON_H
 ​
 #include <cmath>
 ​
 template<typename T, 
          double (T::*g)(double) const,
          double (T::*g_prime)(double) const>
 double newton_raphson(double y_target,       
                       double init,           
                       double epsilon,        
                       const T& root_func) {  
 ​
   double y = (root_func.*g)(init);  
   double x = init;                  
 ​
   while (fabs(y-y_target) > epsilon) {
     double d_x = (root_func.*g_prime)(x);
     x += (y_target-y)/d_x;
     y = (root_func.*g)(x);
   }
   return x;
 }
 ​
 #endif
```

现在我们可以创建 main() 函数来将所有代码包装在一起：

```cpp
 #ifndef __MAIN_CPP
 #define __MAIN_CPP
 ​
 #include "black_scholes.h"
 #include "newton_raphson.h"
 #include <iostream>
 ​
 int main(int argc, char **argv) {
 ​
   double S = 100.0;  
   double K = 100.0;  
   double r = 0.05;   
   double T = 1.0;    
   double C_M = 10.5; 
 ​
   BlackScholesCall bsc(S, K, r, T);
 ​
   double init = 0.3; 
   double epsilon = 0.001;
 ​
   double sigma = newton_raphson<BlackScholesCall, 
                                 &BlackScholesCall::option_price,
                                 &BlackScholesCall::option_vega>(C_M, init, epsilon, bsc);
 ​
   std::cout << "Implied Vol: " << sigma << std::endl;
 ​
   return 0;
 }
 ​
 #endif
```

代码的输出由下式给出：

```cpp
 Implied Vol: 0.201317
```
