在 Javascript 中构建求解器算法的最佳方法是什么?

发布于 2025-01-13 16:42:09 字数 2361 浏览 1 评论 0原文

我正在构建一个金融应用程序,其中我必须求解将现金流贴现回现值的利率(债券收益率)。我们正在解决费率问题。

在 Javascript 中执行此操作的最佳方法是什么?我所拥有的有效,但我觉得它可以优化,因为即使使用可靠的“最佳猜测”参数,目前它也可能需要 60/70 毫秒。

另外 - 是否有一种算法方法可以确定 iteratingIncrement 和允许的错误,以便永远不会出现 iteratingIncrement 太大而无法找到 allowedError 的情况?

非常欢迎所有建议。

非常感谢

const solveDcfYield = ( workoutCashflows, target, bestGuess=0.00, iteratingIncrement=0.000001, allowableError=0.0001, maxIterations=1000000) => {
    /**
     * @param               {array}             workoutCashflows                Array of cashflows for specific settle and exchange.
     * @param               {float}             target                          Value for which to solve toward.
     * @param               {float}             bestGuess                       Best Guess to optimise algorithm solve time. As percentage e.g. 5.00.
     * @param               {float}             iteratingIncrement              Value to increment solver each iteration.
     * @param               {float}             allowableError                  Minimum distance from target to solve, unless max iterations hit.
     * @param               {int}               maxIterations                   Maximum number of iterations to un in the solver
     * 
     * @return              {float}             r                               Rate/yield that discounts cashflows coto within allowableError of target
     */
    let iteratingDifference = allowableError + 10;
    let r = bestGuess/100;
    let iterations = 0;

    let startTime = new Date().getTime();

    while ((( iteratingDifference > allowableError) || (iteratingDifference < -allowableError)) && (iterations <= maxIterations)) {
        iteratingDifference = target - sumAndDiscountCashFlows(workoutCashflows, r);
        r = (iteratingDifference > 0) ? (r - iteratingIncrement) : (r + iteratingIncrement);
        iteratingDifference = parseFloat(iteratingDifference.toFixed(8));
        iterations = iterations + 1;
        if (iterations === (maxIterations - 1)){
            console.log("maximum iterations hit...");
        }
    };

    let endTime = new Date().getTime();
    let time = endTime - startTime
    console.log("Solver Algorithm Execution Time: ", time);

    return r;

};

I am building a financial application in which I have to solve for a rate( bond yield ) that discounts cashflows back to a present value. We are solving for the rate.

What would the best way to do this in Javascript? What I have works, but I feel it can be optimised as it currently might take 60/70ms even with a solid 'best guess' parameter.

Also - is there a algorithmic way of determining the iteratingIncrement and allowable error such that there is never a time when the iteratingIncrement is too large to be able to find the allowableError?

All suggestions very welcome.

Many Thanks

const solveDcfYield = ( workoutCashflows, target, bestGuess=0.00, iteratingIncrement=0.000001, allowableError=0.0001, maxIterations=1000000) => {
    /**
     * @param               {array}             workoutCashflows                Array of cashflows for specific settle and exchange.
     * @param               {float}             target                          Value for which to solve toward.
     * @param               {float}             bestGuess                       Best Guess to optimise algorithm solve time. As percentage e.g. 5.00.
     * @param               {float}             iteratingIncrement              Value to increment solver each iteration.
     * @param               {float}             allowableError                  Minimum distance from target to solve, unless max iterations hit.
     * @param               {int}               maxIterations                   Maximum number of iterations to un in the solver
     * 
     * @return              {float}             r                               Rate/yield that discounts cashflows coto within allowableError of target
     */
    let iteratingDifference = allowableError + 10;
    let r = bestGuess/100;
    let iterations = 0;

    let startTime = new Date().getTime();

    while ((( iteratingDifference > allowableError) || (iteratingDifference < -allowableError)) && (iterations <= maxIterations)) {
        iteratingDifference = target - sumAndDiscountCashFlows(workoutCashflows, r);
        r = (iteratingDifference > 0) ? (r - iteratingIncrement) : (r + iteratingIncrement);
        iteratingDifference = parseFloat(iteratingDifference.toFixed(8));
        iterations = iterations + 1;
        if (iterations === (maxIterations - 1)){
            console.log("maximum iterations hit...");
        }
    };

    let endTime = new Date().getTime();
    let time = endTime - startTime
    console.log("Solver Algorithm Execution Time: ", time);

    return r;

};

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

素罗衫 2025-01-20 16:42:09

计算债券到期收益率1的有效方法是使用 牛顿法,需要计算导数,我在下面推导出来。


您可以如下表达您的问题。

  • n = 到期前的年数
  • f = n 年后债券的价值(面值)
  • c = 年息票支付(f 的百分比)
  • p = 债券的购买成本
  • 确定的年收益率

α = 1/(1+i)

i =待

p = α nf + c(1+α-0.5j=1.. nαj

请注意α-0.5 是一种调整,稍微增加年中优惠券的价值,以便它们可以从同年年底开始打折以提供同等的现值。这是从以下恒等式得出的。

α(cα-0.5) = cα0.5

由于

Σj=1.. nαj

可见是我们可以写成的几何级数的和:

p = fαn + (1+α-0.5)cα(αn-1)/(1-α)

等价于:

p = (f(1-α) + (1+α-0.5)αc)αn - (1+α-0.5)αc)(1-α)-1


现在定义以下函数。

g1(α) = (1+α-0.5)ac

g2(α) = (f(1-α)+g1(α))

g3(α) = αn

g4(α) = (1-α)-1

g5(α) = g2(α)g3(α)-1

h(α) = g1(α)g5(α)g4(α)

我们希望找到 α+,其中

h(α+) = p

As α+ > = 1/(1+i),因此到期收益率等于 1/α+-1。


h相对于α的导数如下:

h'(α) = g1'(α)g5(α)g4(α) + g1(α)g5 '(α)g4(α) + g1(α)g5(α)g4'(α)

其中

g1'(α) = (-0.5α-1.5)ac + (1+α-0.5)c

g2'(α) = -f+g1'(α)

g3'(α) = nαn-1

g4'(α ) = -1/(1-α)2

g5'(α) = g2'(α)g3(α) + g2(α)g3'(α)


我们可以首先将 α 设置为等于对某些人平均收益率 α0。然后使用直线近似(即牛顿法)估计 α 的新值:

h(α0) + (α0+d)*h'( α0) = p

并求解 d:

d = (ph(α0))/h'(α0) - α< sub>0

α 的新估计为因此 α + d。接下来,计算

d = (ph(α))/h'(α) - α

update α 并以这种方式继续,直到 α 的变化足够小。这应该很快收敛,当然比不使用导数的方法更快。

1.债券的到期收益率是导致债券购买价格等于息票支付现值(每年两次)加上到期日债券面值支付现值之和的年贴现率.

An efficient way to compute the yield to maturity of a bond1 is to use Newton's method, which requires the calculation of derivatives, which I derive below.


You can express your problem as follows.

  • n = number of years until maturity
  • f = value of bond after n years (face value)
  • c = annual coupon payment (percentage of f)
  • p = purchase cost of bond
  • i = annual yield to be determined

Let

α = 1/(1+i)

Then

p = αnf + c(1+α-0.5j=1.. nαj

Note that α-0.5 is an adjustment that slightly increases the value of mid-year coupons so that they may be discounted from the end of the same year to provide an equivalent present value. This follows from the following identity.

α(cα-0.5) = cα0.5

As

Σj=1.. nαj

is seen to be the sum of a geometric series we can write:

p = fαn + (1+α-0.5)cα(αn-1)/(1-α)

which is equivalent to the following:

p = (f(1-α) + (1+α-0.5)αc)αn - (1+α-0.5)αc)(1-α)-1


Now define the following functions.

g1(α) = (1+α-0.5)ac

g2(α) = (f(1-α)+g1(α))

g3(α) = αn

g4(α) = (1-α)-1

g5(α) = g2(α)g3(α)-1

h(α) = g1(α)g5(α)g4(α)

We wish to find α+ for which

h(α+) = p

As α+ = 1/(1+i), the yield to maturity therefore equals 1/α+-1.


The derivative of h relative to α is as follows:

h'(α) = g1'(α)g5(α)g4(α) + g1(α)g5'(α)g4(α) + g1(α)g5(α)g4'(α)

where

g1'(α) = (-0.5α-1.5)ac + (1+α-0.5)c

g2'(α) = -f+g1'(α)

g3'(α) = nαn-1

g4'(α) = -1/(1-α)2

g5'(α) = g2'(α)g3(α) + g2(α)g3'(α)


We might begin by setting α equal to some average yield α0. Then estimate a new value of α using the straight-line approximation (i.e., Newton's method):

h(α0) + (α0+d)*h'(α0) = p

and solving for d:

d = (p-h(α0))/h'(α0) - α0

The new estimate of α is therefore α + d. Next, calculate

d = (p-h(α))/h'(α) - α

update α and continue in this fashion until the change in α is sufficiently small. This should quickly converge, certainly faster that methods that do not use derivates.

1. A bond's yield to maturity is the annual discount rate that causes the purchase price of the bond to equal the sum of the present values of coupon payments (two per year) plus the present value of the payment of the bond's face value on the maturity date.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文