Samedi 18 avril 2009
6
18
/04
/Avr
/2009
18:11
Voici l'implémentation du modèle binomial. L'arbre recombinant fait l'objet d'une procédure itérative calibrée pour converger vers le modèle de Black&Scholes pour un pas de 160 environ.
package fx.bidesign.maths
{
import fx.bidesign.maths.Combination;
import fx.bidesign.maths.ProbabilityTools;
public class CoxRossRubinstein
{
public function CoxRossRubinstein()
{
}
// (sous-jacent, prix d'exercice, jours restant, volatilté, taux sans risque, dividende, parité)
public static function value( s:Number, k:Number, t:Number, v:Number, r:Number, c:Number, steps:Number, p:Number = 1 ):Array
{
t = t / steps;
// 1 - q = ( u - Math.exp( ( r - c ) * t ) ) / ( u - d )
var d:Number = Math.exp( - v * Math.sqrt( t ) );
var u:Number = Math.exp( v * Math.sqrt( t ) );
var q:Number = ( Math.exp( ( r - c ) * t ) - d ) / ( u - d );
var call:Number = 0;
for( var i:int = 0; i < steps + 1; i++ )
{
call += Combination.evaluate( steps, i ) * Math.pow( q, i ) * Math.pow( 1 - q, steps - i ) * Math.max( s * Math.pow( u,
i ) * Math.pow( d, steps - i ) - k, 0 );
}
var put:Number = 0;
for( var j:int = 0; j < steps + 1; j++ )
{
put += Combination.evaluate( steps, j ) * Math.pow( q, j ) * Math.pow( 1 - q, steps - j ) * Math.max( k - ( s *
Math.pow( u, j ) * Math.pow( d, steps - j ) ), 0 );
}
return [call / p, put / p ];
}
// (sous-jacent, prix d'exercice, jours restant, volatilté, taux sans risque, dividende, parité)
public static function delta( s:Number, k:Number, t:Number, v:Number, r:Number, c:Number, p:Number = 1 ):Array
{
var d1:Number = ( Math.log( s / k ) + ( r + Math.pow( v, 2 ) / 2 ) * t ) / ( v * Math.sqrt( t ) );
var d2:Number = d1 - ( v * Math.sqrt( t ) );
var call:Number = Math.exp( - c * t) * ProbabilityTools.normalDistribution( d1 );
var put:Number = Math.exp( - c * t ) * ( ProbabilityTools.normalDistribution( d1 ) - 1 );
return [call * 100, put * 100];
}
// (sous-jacent, prix d'exercice, jours restant, volatilté, taux sans risque, dividende, parité)
public static function gamma( s:Number, k:Number, t:Number, v:Number, r:Number, c:Number, p:Number = 1 ):Array
{
var d1:Number = ( Math.log( s / k ) + ( r + Math.pow( v, 2 ) / 2 ) * t ) / ( v * Math.sqrt( t ) );
var d2:Number = d1 - ( v * Math.sqrt( t ) );
var call:Number = Math.exp( - c * t ) * ( ProbabilityTools.normalDensity( d1 ) / ( s * v * Math.sqrt( t ) ) );
var put:Number = call;
return [call / ( p / 100 ), put / ( p / 100 )];
}
// (sous-jacent, prix d'exercice, jours restant, volatilté, taux sans risque, dividende, prime du put ou du call, parité)
public static function theta( s:Number, k:Number, t:Number, v:Number, r:Number, c:Number, fv:Number, p:Number = 1 ):Array
{
var d1:Number = ( Math.log( s / k ) + ( r + Math.pow( v, 2 ) / 2 ) * t ) / ( v * Math.sqrt( t ) );
var d2:Number = d1 - ( v * Math.sqrt( t ) );
var call:Number = - Math.exp( - c * t ) * s * ProbabilityTools.normalDensity( d1 ) * v / ( 2 * Math.sqrt( t ) );
call += - r * k * Math.exp( - r * t ) * ProbabilityTools.normalDistribution( d2 );
call += c * s * Math.exp( - c * t ) * ProbabilityTools.normalDistribution( d1 );
var put:Number = - ( s * Math.exp( - c * t ) * v ) / ( 2 * Math.sqrt( t ) ) * ProbabilityTools.normalDensity( d1 );
put += + r * k * Math.exp( -r * t ) * ( 1 - ProbabilityTools.normalDistribution( d2 ) );
put += - c * s * Math.exp( - c * t) * ProbabilityTools.normalDistribution( 1 - d1 );
return [call / 52 / fv * 100, put / 52 / fv * 100];
}
// (sous-jacent, prix d'exercice, jours restant, volatilté, taux sans risque, dividende, prime du put ou du call, parité)
public static function rho( s:Number, k:Number, t:Number, v:Number, r:Number, c:Number, fv:Number, p:Number = 1 ):Array
{
var d1:Number = ( Math.log( s / k ) + ( r + Math.pow( v, 2 ) / 2 ) * t ) / ( v * Math.sqrt( t ) );
var d2:Number = d1 - ( v * Math.sqrt( t ) );
var call:Number = k * t * Math.exp( - r * t ) * ProbabilityTools.normalDistribution( d2 );
var put:Number = k * t * Math.exp( - r * t ) * ( ProbabilityTools.normalDistribution( d2 ) - 1 );
return [call / fv, put / fv];
}
// (sous-jacent, prix d'exercice, jours restant, volatilté, taux sans risque, dividende, prime du put ou du call, parité)
public static function vega( s:Number, k:Number, t:Number, v:Number, r:Number, c:Number, fv:Number, p:Number = 1 ):Array
{
var d1:Number = ( Math.log( s / k ) + ( r + Math.pow( v, 2 ) / 2 ) * t ) / ( v * Math.sqrt( t ) );
var d2:Number = d1 - ( v * Math.sqrt( t ) );
var call:Number = s * Math.exp(- c * t ) * ProbabilityTools.normalDensity( d1 ) * Math.sqrt( t );
var put:Number = call;
return [call / fv, put / fv];
}
// (sous-jacent, valeur du delta, prime du put ou du call)
public static function elasticity( s:Number, del:Number, fv:Number ):Array
{
var call:Number = s * del / fv;
var put:Number = s * del / fv;
return [call / 100, put / 100];
}
}
}
Les grecs sont calculés sur le modèle de Black&Scholes mais à l'occasion je mettrais à jour la classe avec les grecs binomiaux. Le pricer sera également mis à jour pour prendre en charge le
modèle binomial.