From 2e9635ece8ecf2617b0144451029aeca78edd9d9 Mon Sep 17 00:00:00 2001 From: xuri Date: Wed, 27 Oct 2021 08:07:21 +0800 Subject: [PATCH] ref #65: new formula functions TBILLPRICE and TBILLYIELD --- calc.go | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++++ calc_test.go | 20 +++++++++++++++ 2 files changed, 92 insertions(+) diff --git a/calc.go b/calc.go index a21be0b..6f8dcb6 100644 --- a/calc.go +++ b/calc.go @@ -538,6 +538,8 @@ type formulaFuncs struct { // TAN // TANH // TBILLEQ +// TBILLPRICE +// TBILLYIELD // TEXTJOIN // TIME // TODAY @@ -9796,6 +9798,76 @@ func (fn *formulaFuncs) TBILLEQ(argsList *list.List) formulaArg { return newNumberFormulaArg((365 * discount.Number) / (360 - discount.Number*dsm)) } +// TBILLPRICE function returns the price, per $100 face value, of a Treasury +// Bill. The syntax of the function is: +// +// TBILLPRICE(settlement,maturity,discount) +// +func (fn *formulaFuncs) TBILLPRICE(argsList *list.List) formulaArg { + if argsList.Len() != 3 { + return newErrorFormulaArg(formulaErrorVALUE, "TBILLPRICE requires 3 arguments") + } + args := list.New().Init() + args.PushBack(argsList.Front().Value.(formulaArg)) + settlement := fn.DATEVALUE(args) + if settlement.Type != ArgNumber { + return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE) + } + args.Init() + args.PushBack(argsList.Front().Next().Value.(formulaArg)) + maturity := fn.DATEVALUE(args) + if maturity.Type != ArgNumber { + return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE) + } + dsm := maturity.Number - settlement.Number + if dsm > 365 || maturity.Number <= settlement.Number { + return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM) + } + discount := argsList.Back().Value.(formulaArg).ToNumber() + if discount.Type != ArgNumber { + return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE) + } + if discount.Number <= 0 { + return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM) + } + return newNumberFormulaArg(100 * (1 - discount.Number*dsm/360)) +} + +// TBILLYIELD function calculates the yield of a Treasury Bill. The syntax of +// the function is: +// +// TBILLYIELD(settlement,maturity,pr) +// +func (fn *formulaFuncs) TBILLYIELD(argsList *list.List) formulaArg { + if argsList.Len() != 3 { + return newErrorFormulaArg(formulaErrorVALUE, "TBILLYIELD requires 3 arguments") + } + args := list.New().Init() + args.PushBack(argsList.Front().Value.(formulaArg)) + settlement := fn.DATEVALUE(args) + if settlement.Type != ArgNumber { + return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE) + } + args.Init() + args.PushBack(argsList.Front().Next().Value.(formulaArg)) + maturity := fn.DATEVALUE(args) + if maturity.Type != ArgNumber { + return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE) + } + dsm := maturity.Number - settlement.Number + if dsm > 365 || maturity.Number <= settlement.Number { + return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM) + } + pr := argsList.Back().Value.(formulaArg).ToNumber() + if pr.Type != ArgNumber { + return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE) + } + if pr.Number <= 0 { + return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM) + } + return newNumberFormulaArg(((100 - pr.Number) / pr.Number) * (360 / dsm)) +} + // YIELDDISC function calculates the annual yield of a discounted security. // The syntax of the function is: // diff --git a/calc_test.go b/calc_test.go index 95b479c..06c7fe1 100644 --- a/calc_test.go +++ b/calc_test.go @@ -1362,6 +1362,10 @@ func TestCalcCellValue(t *testing.T) { "=SYD(10000,1000,5,2)": "2400", // TBILLEQ "=TBILLEQ(\"01/01/2017\",\"06/30/2017\",2.5%)": "0.0256680731364276", + // TBILLPRICE + "=TBILLPRICE(\"02/01/2017\",\"06/30/2017\",2.75%)": "98.86180555555556", + // TBILLYIELD + "=TBILLYIELD(\"02/01/2017\",\"06/30/2017\",99)": "0.024405125076266", // YIELDDISC "=YIELDDISC(\"01/01/2017\",\"06/30/2017\",97,100)": "0.0622012325059031", "=YIELDDISC(\"01/01/2017\",\"06/30/2017\",97,100,0)": "0.0622012325059031", @@ -2644,6 +2648,22 @@ func TestCalcCellValue(t *testing.T) { "=TBILLEQ(\"01/01/2017\",\"06/30/2017\",0)": "#NUM!", "=TBILLEQ(\"01/01/2017\",\"06/30/2018\",2.5%)": "#NUM!", "=TBILLEQ(\"06/30/2017\",\"01/01/2017\",2.5%)": "#NUM!", + // TBILLPRICE + "=TBILLPRICE()": "TBILLPRICE requires 3 arguments", + "=TBILLPRICE(\"\",\"06/30/2017\",2.5%)": "#VALUE!", + "=TBILLPRICE(\"01/01/2017\",\"\",2.5%)": "#VALUE!", + "=TBILLPRICE(\"01/01/2017\",\"06/30/2017\",\"\")": "#VALUE!", + "=TBILLPRICE(\"01/01/2017\",\"06/30/2017\",0)": "#NUM!", + "=TBILLPRICE(\"01/01/2017\",\"06/30/2018\",2.5%)": "#NUM!", + "=TBILLPRICE(\"06/30/2017\",\"01/01/2017\",2.5%)": "#NUM!", + // TBILLYIELD + "=TBILLYIELD()": "TBILLYIELD requires 3 arguments", + "=TBILLYIELD(\"\",\"06/30/2017\",2.5%)": "#VALUE!", + "=TBILLYIELD(\"01/01/2017\",\"\",2.5%)": "#VALUE!", + "=TBILLYIELD(\"01/01/2017\",\"06/30/2017\",\"\")": "#VALUE!", + "=TBILLYIELD(\"01/01/2017\",\"06/30/2017\",0)": "#NUM!", + "=TBILLYIELD(\"01/01/2017\",\"06/30/2018\",2.5%)": "#NUM!", + "=TBILLYIELD(\"06/30/2017\",\"01/01/2017\",2.5%)": "#NUM!", // YIELDDISC "=YIELDDISC()": "YIELDDISC requires 4 or 5 arguments", "=YIELDDISC(\"\",\"06/30/2017\",97,100,0)": "#VALUE!",