Commit bd6fe694 authored by Dmitry.Shahtanov's avatar Dmitry.Shahtanov Committed by Alexander.Trofimov

add: ODDFYIELD

fix: исправлен подсчеn формулы ODDFPRICE

git-svn-id: svn://192.168.3.15/activex/AVS/Sources/TeamlabOffice/trunk/OfficeWeb@55886 954022d7-b5bf-4e40-9824-e11837661b57
parent 96568e0f
...@@ -4665,7 +4665,40 @@ ...@@ -4665,7 +4665,40 @@
ok( oParser.parse() ); ok( oParser.parse() );
strictEqual( oParser.calculate().getValue(), vdb(2400,300,10*12,6,18) ); strictEqual( oParser.calculate().getValue(), vdb(2400,300,10*12,6,18) );
} )
test( "Test: \"ODDFPRICE\"", function () {
oParser = new parserFormula( "ODDFPRICE(DATE(1999,2,28),DATE(2016,1,1),DATE(1998,2,28),DATE(2015,1,1),7%,0,100,2,1)", "A2", ws );
ok( oParser.parse() );
ok( difBetween(oParser.calculate().getValue(), 217.878453038674) );
oParser = new parserFormula( "ODDFPRICE(DATE(2008,11,11),DATE(2021,3,1),DATE(2008,10,15),DATE(2009,3,1),0.0785,0.0625,100,2,1)", "A2", ws );
ok( oParser.parse() );
ok( difBetween(oParser.calculate().getValue(), 113.597717474079) );
oParser = new parserFormula( "ODDFPRICE(DATE(1990;6;1);DATE(1995;12;31);DATE(1990;1;1);DATE(1990;12;31);6%;5%;1000;1;1)", "A2", ws );
ok( oParser.parse() );
ok( difBetween(oParser.calculate().getValue(), 790.11323221867) );
} ) } )
test( "Test: \"ODDFYIELD\"", function () {
oParser = new parserFormula( "ODDFYIELD(DATE(1990;6;1);DATE(1995;12;31);DATE(1990;1;1);DATE(1990;12;31);6%;790;100;1;1)", "A2", ws );
ok( oParser.parse() );
ok( difBetween(oParser.calculate().getValue(),-0.2889178784774840 ) );
oParser = new parserFormula( "ODDFYIELD(DATE(2008,11,11),DATE(2021,3,1),DATE(2008,10,15),DATE(2009,3,1),0.0575,84.5,100,2,0)", "A2", ws );
ok( oParser.parse() );
ok( difBetween(oParser.calculate().getValue(), 0.0772455415972989 ) );
oParser = new parserFormula( "ODDFYIELD(DATE(2008;12;11);DATE(2021;4;1);DATE(2008;10;15);DATE(2009;4;1);6%;100;100;4;1)", "A2", ws );
ok( oParser.parse() );
ok( difBetween(oParser.calculate().getValue(), 0.0599769985558904 ) );
} )
} ); } );
...@@ -184,7 +184,7 @@ function lcl_GetCoupncd( settl, matur, freq ) { ...@@ -184,7 +184,7 @@ function lcl_GetCoupncd( settl, matur, freq ) {
if ( matur > settl ) { if ( matur > settl ) {
matur.addYears( -1 ); matur.addYears( -1 );
} }
while ( matur <= settl ) { while ( matur < settl ) {
matur.addMonths( 12 / freq ); matur.addMonths( 12 / freq );
} }
} }
...@@ -331,7 +331,7 @@ function getduration( settlement, maturity, coupon, yld, frequency, basis ) { ...@@ -331,7 +331,7 @@ function getduration( settlement, maturity, coupon, yld, frequency, basis ) {
function oddFPrice(settl,matur,iss,firstCoup,rate,yld,redemption,frequency,basis) { function oddFPrice(settl,matur,iss,firstCoup,rate,yld,redemption,frequency,basis) {
function positiveDaysBetween( d1, d2, b ) { function positiveDaysBetween( d1, d2, b ) {
var res = diffDate( d1, d2, b ); var res = diffDate( d1, d2, b ).getValue();
return res > 0 ? res : 0; return res > 0 ? res : 0;
} }
...@@ -364,7 +364,7 @@ function oddFPrice(settl,matur,iss,firstCoup,rate,yld,redemption,frequency,basis ...@@ -364,7 +364,7 @@ function oddFPrice(settl,matur,iss,firstCoup,rate,yld,redemption,frequency,basis
var res = 0, DSC, var res = 0, DSC,
numMonths = 12 / frequency, numMonths = 12 / frequency,
numMonthsNeg = -numMonths, numMonthsNeg = -numMonths,
E = getcoupdays( settl, new Date( firstCoup ), frequency, basis ), E = getcoupdays( settl, new Date( firstCoup ), frequency, basis ).getValue(),
coupNums = getcoupnum( settl, new Date( matur ), frequency ), coupNums = getcoupnum( settl, new Date( matur ), frequency ),
dfc = positiveDaysBetween( new Date( iss ), new Date( firstCoup ), basis ); dfc = positiveDaysBetween( new Date( iss ), new Date( firstCoup ), basis );
...@@ -408,7 +408,7 @@ function oddFPrice(settl,matur,iss,firstCoup,rate,yld,redemption,frequency,basis ...@@ -408,7 +408,7 @@ function oddFPrice(settl,matur,iss,firstCoup,rate,yld,redemption,frequency,basis
DSC = positiveDaysBetween( settl, getcoupncd( settl, firstCoup, frequency ), basis ); DSC = positiveDaysBetween( settl, getcoupncd( settl, firstCoup, frequency ), basis );
} }
else { else {
DSC = E - diffDate( getcoupncd( settl, firstCoup, frequency ), settl, basis ); DSC = E - diffDate( lcl_GetCouppcd( settl, firstCoup, frequency ), settl, basis );
} }
var Nq = coupNumber( firstCoup, settl, numMonths, true ); var Nq = coupNumber( firstCoup, settl, numMonths, true );
...@@ -3421,11 +3421,23 @@ cODDFPRICE.prototype.getInfo = function () { ...@@ -3421,11 +3421,23 @@ cODDFPRICE.prototype.getInfo = function () {
}; };
function cODDFYIELD() { function cODDFYIELD() {
cBaseFunction.call( this, "ODDFYIELD" ); // cBaseFunction.call( this, "ODDFYIELD" );
this.name = "ODDFYIELD";
this.type = cElementType.func;
this.value = null;
this.argumentsMin = 8;
this.argumentsCurrent = 0;
this.argumentsMax = 9;
this.formatType = {
def:-1, //подразумевается формат первой ячейки входящей в формулу.
noneFormat:-2
};
this.numFormat = this.formatType.noneFormat;
} }
cODDFYIELD.prototype = Object.create( cBaseFunction.prototype ); cODDFYIELD.prototype = Object.create( cBaseFunction.prototype );
/*cODDFYIELD.prototype.Calculate = function ( arg ) { cODDFYIELD.prototype.Calculate = function ( arg ) {
var settlement = arg[0], var settlement = arg[0],
maturity = arg[1], maturity = arg[1],
issue = arg[2], issue = arg[2],
...@@ -3542,7 +3554,78 @@ cODDFYIELD.prototype = Object.create( cBaseFunction.prototype ); ...@@ -3542,7 +3554,78 @@ cODDFYIELD.prototype = Object.create( cBaseFunction.prototype );
iss = Date.prototype.getDateFromExcel( issue ), iss = Date.prototype.getDateFromExcel( issue ),
firstCoup = Date.prototype.getDateFromExcel( first_coupon ); firstCoup = Date.prototype.getDateFromExcel( first_coupon );
this.value = new cNumber( oddFPrice(settl,matur,iss,firstCoup,rate,pr,redemption,frequency,basis) ); var years = diffDate(settl, matur,basis ),
px = pr - 100,
num = rate * years * 100 - px,
denum = px * 0.25 * ( 1 + 2 * years ) + years * 100,
guess = num / denum, x = guess, g_Eps = 1e-7, nIM = 500, eps = 1, nMC= 0, xN;
function iterF(yld) {return pr - oddFPrice( settl, matur, iss, firstCoup, rate, yld, redemption, frequency, basis)}
while ( eps > g_Eps && nMC < nIM ) {
xN = x - iterF( x ) / (iterF( x + g_Eps ) - iterF( x - g_Eps )) / (2 * g_Eps);
nMC++;
eps = Math.abs( xN - x );
x = xN;
}
if ( isNaN( x ) || Infinity == Math.abs(x) ) {
var max = Number.MAX_VALUE, min = -Number.MAX_VALUE,
step = 1.6,
low = guess - 0.01 <= min ? min + g_Eps : guess - 0.01,
high = guess + 0.01 >= max ? max - g_Eps : guess + 0.01,
i, xBegin, xEnd, x, y, currentIter = 0;
if ( guess <= min || guess >= max ) {
return new cError( cErrorType.not_numeric );
}
for ( i = 0; i < nIM; i++ ) {
xBegin = low <= min ? min + g_Eps : low;
xEnd = high >= max ? max - g_Eps : high;
x = iterF( xBegin );
y = iterF( xEnd );
if ( x * y == 0 || x * y < 0 ) {
break;
}
else if ( x * y > 0 ) {
low = (xBegin + step * (xBegin - xEnd));
high = (xEnd + step * (xEnd - xBegin));
}
else {
return new cError( cErrorType.not_numeric );
}
}
if ( i == nIM ) {
return new cError( cErrorType.not_numeric );
}
var fXbegin = iterF( xBegin ), fXend = iterF( xEnd ), fXi, xI;
if ( Math.abs( fXbegin ) < g_Eps ) {
return this.value = new cNumber( fXbegin );
}
if ( Math.abs( fXend ) < g_Eps ) {
return this.value = new cNumber( fXend );
}
do {
xI = xBegin + (xEnd - xBegin) / 2;
fXi = iterF( xI );
if ( fXbegin * fXi < 0 ) {
xEnd = xI;
}
else {
xBegin = xI;
}
fXbegin = iterF( xBegin );
currentIter++;
} while ( Math.abs( fXi ) > g_Eps && currentIter < nIM )
this.value = new cNumber( xI );
}
else
this.value = new cNumber( x );
return this.value; return this.value;
}; };
...@@ -3551,7 +3634,7 @@ cODDFYIELD.prototype.getInfo = function () { ...@@ -3551,7 +3634,7 @@ cODDFYIELD.prototype.getInfo = function () {
name:this.name, name:this.name,
args:"( settlement , maturity , issue , first-coupon , rate , pr , redemption , frequency [ , [ basis ] ] )" args:"( settlement , maturity , issue , first-coupon , rate , pr , redemption , frequency [ , [ basis ] ] )"
}; };
};*/ };
function cODDLPRICE() { function cODDLPRICE() {
// cBaseFunction.call( this, "ODDLPRICE" ); // cBaseFunction.call( this, "ODDLPRICE" );
......
...@@ -159,6 +159,10 @@ Math.approxEqual = function ( a, b ) { ...@@ -159,6 +159,10 @@ Math.approxEqual = function ( a, b ) {
return this.abs( a - b ) < 1e-15; return this.abs( a - b ) < 1e-15;
}; };
Math.sign = function(a){
return (a < 0) ? -1 : (a == 0) ? 0 : 1;
}
/** @constructor */ /** @constructor */
function cBaseType( val ) { function cBaseType( val ) {
this.needRecalc = false; this.needRecalc = false;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment