/// <summary> /// 计算器初始化,计算中间变量 /// </summary> /// <param name="info"></param> public AmericanOptionCalc(AmericanOptionInfo info) { try { #region 期权信息检查 if (info.OptionType != 1 && info.OptionType != -1) { throw new Exception("期权类型非法"); } if (info.N < 2) { throw new Exception("期数(执行步数)非法"); } if (info.AssetPrice < 0) { throw new Exception("标的当前价格非法"); } if (info.ExercisePrice < 0) { throw new Exception("执行价格非法"); } if (info.EndDate <= info.StartDate) { throw new Exception("起始到期日期非法"); } if (info.r < 0) { throw new Exception("无风险利率r非法"); } if (info.q < 0) { throw new Exception("股息率q非法"); } if (info.sigma == 0) { throw new Exception("波动率非法"); } #endregion ExpiryDays = (info.EndDate - info.StartDate).Days; AnnualTimePerStep = (double)ExpiryDays / 365 / info.N; b = info.r - info.q; a = Math.Exp(b * AnnualTimePerStep); DiscountRate = Math.Exp(-info.r * AnnualTimePerStep); OptionType = info.OptionType; Info = info; Calc(info, out u, out d, out p, out pNegative, out TreeAssetPrice, out TreeOptionPrice); } catch (Exception ex) { throw ex; } }
private void Calc(AmericanOptionInfo info, out double tu, out double td, out double tp, out double tpNegative, out double[] tTreeAssetPrice, out double[] tTreeOptionPrice) { tu = Math.Exp(info.sigma * Math.Sqrt(AnnualTimePerStep)); td = Math.Exp(-info.sigma * Math.Sqrt(AnnualTimePerStep)); tp = (a - td) / (tu - td); tpNegative = 1 - tp; #region 生成二叉树 int numberOfNodes = (info.N + 2) * (info.N + 1) / 2; //计算标的价格 tTreeAssetPrice = new double[numberOfNodes]; //根节点 tTreeAssetPrice[0] = info.AssetPrice; for (int i = 1; i <= info.N; i++) //i为层数,第i层有i+1个点,根节点在0层 { int index = (i * (i + 1) / 2); //第i层第1个点的索引 int father = index - i; //第i层第1个点父节点的索引 tTreeAssetPrice[index] = tTreeAssetPrice[father] * tu; //第i层第1个点由父节点上涨一次所得,乘上涨幅度u for (int j = 2; j <= i + 1; j++) //j为点数,首个点编号为1 { index = (i * (i + 1) / 2) + j - 1; //第i层第j个点的索引 father = index - i - 1; //父节点的索引 tTreeAssetPrice[index] = tTreeAssetPrice[father] * td; //由父节点下跌一次所得,乘下跌幅度d } } //计算期权价格 tTreeOptionPrice = new double[numberOfNodes]; //首先计算最底层N,共N+1个点 for (int i = numberOfNodes - info.N - 1; i < numberOfNodes; i++) { tTreeOptionPrice[i] = Math.Max((tTreeAssetPrice[i] - info.ExercisePrice) * OptionType, 0); } //倒推 int level = info.N - 1; //当前层数,初始在N-1层 int cnt = 0; for (int i = numberOfNodes - info.N - 2; i >= 0; i--) //i为索引 { cnt++; //当前为本层倒数第cnt个点 double tmp1 = tp * tTreeOptionPrice[i + level + 1] + tpNegative * tTreeOptionPrice[i + level + 2]; double tmp2 = Math.Exp(-info.r * AnnualTimePerStep) * tmp1; tTreeOptionPrice[i] = Math.Max((tTreeAssetPrice[i] - info.ExercisePrice) * OptionType, tmp2); if (cnt == level + 1) //本层遍历结束 { cnt = 0; level--; } } #endregion }
/// <summary> /// 获取Rho /// </summary> public double GetRho() { double epsilon = 0.00001; AmericanOptionInfo info2 = AmericanOptionInfo.Clone(Info); info2.r += epsilon; double tu = 0, td = 0, tp = 0, tpNegative = 0; double[] tTreeAssetPrice = null; double[] tTreeOptionPrice = null; Calc(info2, out tu, out td, out tp, out tpNegative, out tTreeAssetPrice, out tTreeOptionPrice); if (tTreeOptionPrice == null || tTreeOptionPrice.Length < 1) { throw new Exception("获取Rho失败"); } return((tTreeOptionPrice[0] - TreeOptionPrice[0]) / epsilon * OptionType * 0.01); }
static void Main(string[] args) { try { //double test3 = 40927.52 * 100; //double test6 = (double)((decimal)40927.52 * 100); //double test9 = (double)((decimal)40927.525 * 100); //double test10 = Math.Floor(test9) / 100; //double test11 = (double)Math.Floor((decimal)40927.525 * 100) / 100; //double test7 = (float)40927.52 * 100; //double test2 = -40927.52 * 100; //double test1 = -Math.Abs(40927.52) * 100; //double test = Math.Ceiling(-Math.Abs(40927.52) * 100) / 100; //double test4 = -Math.Ceiling(Math.Abs(40927.52) * 100) / 100; //double test8 = -Math.Ceiling(Math.Abs(40927.5199) * 100) / 100; double test5 = Math.Floor(40927.52 * 100) / 100; double test12 = (double)Math.Floor((decimal)40927.52 * 100) / 100; #region 美式期权 //某美式期权信息 AmericanOptionInfo americanOptionInfo = new AmericanOptionInfo() { OptionType = -1, N = 2, AssetPrice = 3.061, ExercisePrice = 3.12, MarketPrice = -0.0833, StartDate = new DateTime(2019, 12, 1), EndDate = new DateTime(2020, 1, 22), sigma = 0.1105, r = 0.0303, q = 0 }; Stopwatch sw1 = Stopwatch.StartNew(); //美式期权计算器初始化 AmericanOptionCalc americanOptionCalc = new AmericanOptionCalc(americanOptionInfo); sw1.Stop(); Console.WriteLine(string.Format("初始化用时:{0}秒", sw1.Elapsed.TotalSeconds)); Stopwatch sw2 = Stopwatch.StartNew(); //获取理论价格 double TheoreticalPrice = americanOptionCalc.GetTheoreticalPrice(); //获取理论价格% double TheoreticalPricePer = americanOptionCalc.GetTheoreticalPricePercent(); double Delta = americanOptionCalc.GetDelta(); double Gamma = americanOptionCalc.GetGamma(); double Vega = americanOptionCalc.GetVega(); double Theta = americanOptionCalc.GetTheta(); double Rho = americanOptionCalc.GetRho(); double IntriValue = americanOptionCalc.GetIntriValue(); double TimeValue = americanOptionCalc.GetTimeValue(); double DueProfit = americanOptionCalc.GetDueProfit(); double CurrentProfit = americanOptionCalc.GetCurrentProfit(); sw2.Stop(); Console.WriteLine(string.Format("获取结果用时:{0}秒\r\n共{1}秒", sw2.Elapsed.TotalSeconds, sw1.Elapsed.TotalSeconds + sw2.Elapsed.TotalSeconds)); #endregion #region 概率图 Stopwatch sw3 = Stopwatch.StartNew(); //样本价格序列S0 List <double> S0 = new List <double>() { 3, 2, 3, 4, 5, 6, 7, 8, 7 }; //当前标的价格 double AssetPrice = 3; //盈亏平衡点 List <double> BalancePoints = new List <double>() { 4, 6 }; ProbabilityCalc probabilityCalc = new ProbabilityCalc(S0); //概率图点集(步骤八) List <Node> ProbabilityMap = probabilityCalc.GetProbabilityMap(AssetPrice, BalancePoints); //各区间概率大小(步骤七) List <double> IntervalProbability = probabilityCalc.GetIntervalProbability(BalancePoints); sw3.Stop(); //各区间概率和越接近1,区间概率结果越精确 Console.WriteLine(string.Format("概率图用时:{0}秒,各区间概率和:{1}", sw3.Elapsed.TotalSeconds, IntervalProbability.Sum())); #endregion Console.WriteLine("Hello World!"); } catch (Exception ex) { Console.WriteLine(ex.Message); } }