Serie ficheros virtuales 

 

 

C Ficheros Virtuales

 

 

 

A.II Ejemplos

 

 

A.II.6 Calculadora hipotecaria

 

 A.II.6.1 Presentación

 A.II.6.2 Interfaz

 A.II.6.3 Formulación financiera de los servicios de SRRCH

  Calculo del valor final de una renta postpagable

  Calculo del valor actual de una renta postpagable

  Calculo del término periódico de una renta renta postpagable necesario para obtener el valor final sni = 1

  Calculo del término periódico de una renta renta postpagable necesario para obtener el valor actual ani = 1

  Cálculo del número de periodos de la renta conociendo i & sni

  Cálculo del número de periodos de la renta conociendo i & ani

  Cálculo del tanto de interés

 

 A.II.6.4 Estructura de soporte del cuadro de amortización

  A.II.6.5 Implementación

  A.II.6.5.1 Implementación de la formulación financiera

  A.II.6.5.2 Implementación del cuadro de amortización y del cuadro de amortización ajustado
  A.II.6.5.3 Implementación del cálculo del tanto de interés

 

                                                                                                                _______


A.II.6.1 Presentación

 

La calculadora que se presenta implementa las fórmulas clásicas del cálculo hipotecario así como el problema de ajuste de cuota para los cuadros calculados por días reales.

 

Las funciones se implementan en la DLL SRRCH, que se aplican en el interfaz PSRRCH, donde se utiliza un fichero virtual para la presentación de los cuadros de amortización y se introduce un mecanismo de salvado y restauración de consultas históricas. Para ello se utiliza otro fichero virtual que se mantiene en pantalla y que se restaura y salva a disco utilizando las funciones SRRCW_RSTF y SRRCW_SAVF al abrir y cerrar el programa.

 

Las fórmulas implementadas resuelven el cálculo hipotecario habitual, esto es, la formulación asociada al sistema francés postpagable, que se ha codificado por trascripción directa desde la fuente bibliográfica.

 

Conviene destacar que para el cálculo del tipo de interés como incógnita del resto de variables se utiliza un procedimiento de inversión cuasi newton, el método Müller, que también se aplica al problema de ajuste de cuota de los cuadros calculados por días reales. Este método se comenta en detalle en el anexo C, epígrafe C.1.1.3.2 Implementación del algoritmo Müller

 

La formulación hipotecaria no precisa utilizar ficheros virtuales, pero a la hora de construir el cuadro de amortización proporciona una herramienta muy útil, que aún resulta más interesante al enfrentarse al problema de ajuste de cuota de los cuadros calculados por días reales.

 

                                         _______


Un cuadro de amortización presenta la evolución temporal de un préstamo. Veamos un ejemplo, característico de la amortización de una tarjeta de crédito a alto tipo de interés

 

 

Capital 10000

Nº de meses 12

Interés nominal 24%

=> Cuota 945.6

 

 

 

 

Capital

Intereses

Capital

 

Capital

Periodo / Fechas

Días

inicial

periodo

amortizado

   Cuota

pendiente

1 20060101 20060131

31

10000.00

200.00

745.60

945.6

9254.4

2 20060102 20060228

28

9254.40

185.09

760.51

945.6

8493.89

3 20060301 20060331

31

8493.89

169.88

775.72

945.6

7718.18

...

 

 

 

 

 

 

 

12 20061201 20061231

31

927.06

18.54

927.06

945.6

0

 

(Cuadro "por periodos")

 

                                                                                                                _______

 
A.II.6.2 Interfaz

 

El cuadro completo se muestra en la imagen siguiente

 

 

                                         _______

 

 

Este es el cálculo ordinario, sin embargo si además del alto tipo de interés se aplicara un cálculo de intereses diario, obtendríamos el resultado siguiente:

 

 

 

Capital

Intereses

Capital

 

Capital

Periodo / Fechas

Días

inicial

periodo

amortizado

Cuota

pendiente

1 20060101 20060131

31

10000

203.84

741.76

945.6

9258.24

2 20060102 20060228

28

9258.24

170.45

775.14

945.6

8483.10

3 20060301 20060331

31

8483.10

172.92

772.68

945.6

7710.42

...

 

 

 

 

 

 

12 20061201 20061231

31

920.22

18.76

920.22

938.98

0

 

(Cuadro "por días" [Aplicando cuota de intereses diarios, sin ajustar])

 

 

Se produce una amortización antes de tiempo de 6.62 unidades, hay pues un cobro anticipado de intereses y se produce un lucro cesante latente que afloraría en caso de amortización anticipada.

 

                                         _______

 

Su imagen completa sería

 

 

                                         _______

 

 

Si se desea aplicar un cálculo de intereses diario, la cuota debe recalcularse para evitar lucros cesantes del prestatario en caso de amortización anticipada.

 

En un cálculo ajustado obtendríamos el siguiente cuadro

 

 

 

Capital

Intereses

Capital

 

Capital

Periodo / Fechas

Días

inicial

periodo

amortizado

  Cuota

pendiente

1 20060101 20060131

31

10000

203.84

741.26

945.1

9258.74

2 20060102 20060228

28

9258.74

170.46

774.64

945.1

8484.09

3 20060301 20060331

31

8484.09

172.94

772.16

945.1

7711.93

...

 

 

 

 

 

 

12 20061201 20061231

31

926.22

18.88

926.22

945.1

0

 

(Cuadro "por días", aplicando cuota ajustada)

 

 

En este cuadro ajustado, con una cuota rebajada en .5 unidades, no se incurre en una amortización prematura.

 

                                         _______

 

Su imagen completa sería

 

 

 

En resumen, el interfaz presenta unos campos de entrada a la izquierda de la pantalla en donde pueden introducirse las variables de cada solicitud.

 

Los campos de Capital, Nº de Meses, Interés y Cuota son de entrada reversible, esto es, dejando uno de ellos a blancos éste se calcula como función incógnita de los demás.

 

En la parte derecha se presenta una relación de consultas históricas, de manera que haciendo doble clic en cualquiera de sus líneas sus datos se cargan en los campos de solicitud; en cambio, con un solo clic, la línea queda señalada para poder ser borrada pulsando luego el botón “Suprimir ítem”. Con el botón vaciar lista se eliminaría toda la relación de consultas históricas.

 

Por último, en la lista inferior se presenta el cuadro de amortización de la consulta en curso.

 

                                                                                                                 _______

 

 

A.II.6.3 Formulación financiera de los servicios de SRRCH

 

PSRRCH proporciona un interfaz a los servicios de SRRCH, cuya relación completa se expone a continuación:

 

double SRRCH_i_ani(double ani, long n);

 

Cálculo del tanto de interés

 

long SRRCH_n_ani(double ani, double Ani, double i);

 

Cálculo del nº de periodos de la renta conociendo

i & ani.

 

long SRRCH_n_sni(double sni, double Pni, double i);

 

Cálculo del nº de periodos de la renta conociendo

i & sni.

 

double SRRCH_TerminoDeRenta_Ani(long n, double i);

 

Calcula el término periódico de una renta renta postpagable: ani = 1

 

double SRRCH_TerminoDeRenta_Pni(long n, double i);

 

Calcula el término periódico de una renta renta postpagable: sni = 1

 

double SRRCH_ValorAdquiridoRenta_sni(long n, double i);

 

Calcula el valor final de una renta postpagable

 

double SRRCH_ValorActualRenta_ani(long n, double i);

 

Calcula el valor actual de una renta postpagable

 

double SRRCH_Cuadro(short int iOpc, double dCapital, long ln, double i, double dCuota,                        long lFecha);

 

Generación del cuadro de amortización

 

double SRRCH_Cuota(double dCapital, long ln, double i, long lFecha);

 

Cálculo de la cuota y cuadro ajustados para una amortización por días

void *SRRCH_LeeCuadro(long lk);

 

Extracción del cuadro de amortización, registro a registro del tipo sDsCuadro

 

 

 

SRRCH da servicios de resolución de las siguientes fórmulas financieras de amortización de un préstamo mediante una renta inmediata constante y postpagable, según el sistema denominado progresivo o francés, y que además se presentan bajo el valor numérico que corresponde al ejemplo que se ha estado mostrando:

                                         _______

 

 

 

double SRRCH_ValorAdquiridoRenta_sni(long n, double i);

 

Calcula el valor final de una renta postpagable:

 

sni = ( (1+i)^n - 1 ) / i

 

 

i = 0.02 n = 12  ->  sni = 13.412089728127

 

 

                                         _______

 

 

 

double SRRCH_ValorActualRenta_ani(long n, double i);

 

Calcula el valor actual de una renta postpagable:

 

ani = sni / (1+i)^n  ->  ani = 10.575341220917

 

 

                                         _______

 

 

 

double SRRCH_TerminoDeRenta_Pni(long n, double i);

 

Calcula el término periódico de una renta renta postpagable necesario

para obtener el valor final sni = 1

 

Pni = 1 / sni  ->  Pni = 0.074559596622951

 

 

                                         _______

 

 

 

double SRRCH_TerminoDeRenta_Ani(long n, double i);

 

Calcula el término periódico de una renta renta postpagable necesario

para obtener el valor actual ani = 1

 

Ani = i + Pni  ->  Ani = 0.094559596622951

 

 

También es

 

Ani = 1 / ani

 

 

Que se aplica directamente para obtener la cuota

 

Cuota = Capital * Ani  ->  945.59596622951 = 10000 * 0.094559596622951


 

 

                                         _______

 

 

 

long SRRCH_n_sni(double sni, double Pni, double i);

 

Cálculo del nº de periodos de la renta conociendo i & sni.

 

N = log(1 + i * sni) / log(1 + i)  ->  12 = 0.23763152755416 / 0.01980262729618

 

Opcionalmente, puede ajustarse n+-1 para minimizar diferencias a Pni dado.

 

 

                                         _______

 

 

 

 

long SRRCH_n_ani(double ani, double Ani, double i);

 

Cálculo del nº de periodos de la renta conociendo i & ani.

 

N = log(1 - i * ani) / log(1/(1 + i))

 

Opcionalmente, puede ajustarse n+-1 para minimizar diferencias a Ani dado.

 

 

                                         _______

 

 

 

double SRRCH_i_ani(double ani, long n);

 

Cálculo del tanto de interés

 

Partiendo de la formulación

 

ani = sni / (1+i)^n

 

para el cálculo del tipo de interés como incógnita del resto de variables,

se utiliza un procedimiento de inversión cuasi-newton, el método Müller,

que es un método de obtención de raíces por aproximación de secantes

parabólicas y que se comentará con más detalle en la presentación de los servicios de la dll SRRCU en el apéndice C.

 

 

                                         _______

 

 

Además de la formulación clásica, se incluyen las siguientes funciones adicionales:

 

 

double SRRCH_Cuota(double dCapital, long ln, double i, long lFecha)

 

 Cálculo de la cuota y cuadro ajustados para una amortización por días, aplicando de nuevo el método Müller a la propia   función cuadro buscando un residuo nulo

 

 

 

SRRCH_Cuadro

 

 Generación del cuadro de amortización

 

                                         _______

 

 

 

A.II.6.4 Estructura de soporte del cuadro de amortización

 

Para construir los cuadros de amortización se utiliza un fichero virtual que se apoya en la siguiente definición de estructuras, abstracción de los ejemplos presentados:

 

 

// Subestructuras del fichero virtual soporte del cuadro de amortización

 

 

 // Ds de claves de acceso al cuadro de amortización

 

 struct sDsK

 {

  long lk;  // Indice k del cuadro de amortización

  char EOR; // Marca de fin de registro

            // Se incluye para eludir anomalías en la respuesta de sizeof, tal

            // como se explica en el capítulo de estructuras

 };

 

 

 

 // Ds datos

 

 struct sDsD // Estructura de datos del cuadro de amortización

 {

  long lFede;   // Fecha desde del registro

  long lFeha;   // Fecha hasta del registro

  long lDias;   // Días del periodo

  double dCini; // Capital al inicio del periodo

  double dInt;  // Interés del periodo

  double dAmt;  // Amortización del periodo

  double dCfin; // Capital al final del periodo

  char EOR;     // Marca de fin de registro

 };

 

 

 

 // Ds del fichero virtual soporte del cuadro de amortización

 

 static struct sDsCuadroAmortizacion

 {

  struct sDsK sDk;

  struct sDsD sDd;

 } sDsCuadro // Registro de paso

 

 

 

Como complemento al resto de funciones se introduce

 

                      void *SRRCH_LeeCuadro(long lk)

 

 

Que permite la extracción del cuadro de amortización, registro a registro del tipo sDsCuadro

 

                                                                                                                _______

 

A.II.6.5 Implementación

 

A.II.6.5.1 Implementación de la formulación financiera

 

La formulación financiera se implementa por transcripción directa, tal como se hace por ejemplo en

 

//----------------------------------------------------------------------------

//

// SRRCH_ValorAdquiridoRenta_sni

//

// Calcula el valor final de una renta postpagable

//

// sni = ( (1+i)^n - 1 ) / i

//

//

// Parámetros:

//

// (I) n = Nº de periodos

// (I) i = Interés aplicable (En cada periodo)

//

// Retorno: sni o *ZEROS en caso de entrada errónea

//

//----------------------------------------------------------------------------

double SRRCH_ValorAdquiridoRenta_sni(long n, double i)

{

 . . .

 

 // Fórmula

 

 sni = ( pow(1.0 + i, n) - 1.0 ) / i;

 

 return sni;

}

                                                                                                                _______

 

 

A.II.6.5.2 Implementación del cuadro de amortización y del cuadro de amortización ajustado

 

Para la implementación del cuadro de amortización se utiliza un fichero virtual basado en la estructura presentada antes, y se extracta como sigue

 

//-----------------------------------------------------------------------------

// SRRCH_Cuadro

//

// Generación del cuadro de amortización

//

// Parámetros:

//

// (I) iOpc = 0/1 Cálculo especial en función de los días de cada periodo

// (I) dCapital = Capital a amortizar

// (I) ln = Nºde meses para efectuar la amortización

// (I) i = Interés aplicable (En cada periodo)

// (I) dCuota = Cuota mensual

// (I) lFecha = Fecha de constitución del préstamo

//

// Retorno: Capital final restante al final del cuadro.

// En cálculo por periodos será nulo, en cálculo por días será -

// Si los parámetros no son consistentes será <> 0

//

//-----------------------------------------------------------------------------

 

double SRRCH_Cuadro(short int iOpc, double dCapital, long ln, double i, double dCuota, long lFecha)

{

 double dResto = dCapital; // Capital resto, y salida final

 . . .

 

 

 // Inz.fichero virtual soporte del cuadro

 

 lNID = SRRCW_NEW("DSCUADRO", sizeof(sDsK), sizeof(sDsCuadro));

 

 

 // Ciclo de proceso

 

 for (lk=1;lk<=ln;++lk)

 {

  sDsCuadro.sDk.lk = lk;

  sDsCuadro.sDk.EOR = '*';

 

  sDsCuadro.sDd.dCini = dResto;

  sDsCuadro.sDd.dInt  = sDsCuadro.sDd.dCini * i;

  sDsCuadro.sDd.dAmt  = dCuota - sDsCuadro.sDd.dInt;

  sDsCuadro.sDd.dCfin = sDsCuadro.sDd.dCini - sDsCuadro.sDd.dAmt;

  sDsCuadro.sDd.lFede = SRFECHA_SMES(lFecha, lk-1);

  sDsCuadro.sDd.lFeha = SRFECHA_SMES(lFecha, lk);

  sDsCuadro.sDd.lDias = SRFECHA_DIFF(sDsCuadro.sDd.lFede,

  sDsCuadro.sDd.lFeha);

  sDsCuadro.sDd.EOR = '*';

 

  lResu = SRRCW_WRITE("DSCUADRO", &sDsCuadro);

 

  dResto = sDsCuadro.sDd.dCfin;

 }

 

 return dResto;

}

 

(Nota: Se ha eludido el cálculo especial basado en nº de días del mes para simplificar la visión del procedimiento)

 

                                                                                                                _______

 

Para su lectura se emplea la función SRRCH_LeeCuadro

 

//-----------------------------------------------------------------------------

// SRRCH_LeeCuadro

//

// Extracción del cuadro de amortización, registro a registro del tipo sDsCuadro

//

//

// Parámetros:

//

// (I) lk = Nºde registo a extraer 1..N

//

// Retorno: (Dirección de la) Estructura de soporte del registro k o registro nulo en caso de error

//

//-----------------------------------------------------------------------------

void *SRRCH_LeeCuadro(long lk)

{

 long lIndi = 0; // Control acceso a SRRCW

 

 static sDsCuadroAmortizacion sDsCuadroNull; // Aux.para devolver en error de acceso

 

 

 // Acceso al cuadro de amortización

 

 sDsCuadro.sDk.lk = lk;

 sDsCuadro.sDk.EOR = '*';

 

 

 lIndi = SRRCW_CHAIN("DSCUADRO", &sDsCuadro, &sDsCuadro);

 if (!lIndi)

 {

 

  // Devuelve registro nulo

 

  sDsCuadroNull.sDk.lk = 0;

  . . .

  return &sDsCuadroNull;

 }

 

 

 // Devuelve el registro solicitado

 

 return &sDsCuadro;

}

                                                                                                                _______

 

 

Para la aplicación del método Müller, que está diseñado para utilizarse sobre una función tipo double f(double), se introducen las siguientes variables de paso implícito

 

 

// Variables globales para calculos de función inversa

 

static double CAPITAL = 0.0; // Paso de dCapital

static long N = 0;           // Paso de n

static double I = 0.0;       // Paso de i

static long FECHA = 0;       // Paso de lFecha

 

que se pasan como variables globales a la función auxiliar

 

 

// Función auxiliar para cálculo de cuota ajustada

 

double PrCuadro(double dCuota)

{

 double dResul = 0.0; // Variable retorno

 

 dResul = SRRCH_Cuadro(1, CAPITAL, N, I, dCuota, FECHA);

 

 return dResul;

}

                                                                                                                _______

 

Incluida en

 

//-----------------------------------------------------------------------------

// SRRCH_Cuota

//

// Cálculo de la cuota y cuadro ajustados para una amortización por días

//

// Se aplica el método Müller a la propia función cuadro buscando un residuo nulo

//

// Parámetros:

//

// (I) dCapital = Capital a amortizar

// (I) ln = Nºde meses para efectuar la amortización

// (I) i = Interés aplicable (En cada periodo)

// (I) lFecha = Fecha de constitución del préstamo

//

// Retorno: Cuota ajustada. Implícitamente se devuelve también el cuadro ajustado correspondiente

//

//-----------------------------------------------------------------------------

double SRRCH_Cuota(double dCapital, long ln, double i, long lFecha)

{

 double dCuota = 0.0; // Variable de retorno

 double dCuota1 = 0.0; // Cota inferior

 double dCuota2 = 0.0; // Cota superior

 

 

 . . .

 

 

 // Cálculo de cuota base y cotas

 

 dCuota = dCapital * SRRCH_TerminoDeRenta_Ani(ln, i);

 

 dCuota1 = dCuota - 1.0;

 if (dCuota1 <= 0) dCuota1 = EPSILON;

 

 dCuota2 = dCuota + 1.0;

 

 

 // Paso de variables para cálculo de la cuota ajustada

 

 CAPITAL = dCapital;

 N = ln;

 I = i;

 FECHA = lFecha;

 

 

 // Calcula la cuota ajustada como aquella que proporciona un cuadro de resto 0

 

 dCuota = SRRCU_FINVMU(EPSILON, dCuota1, dCuota2, PrCuadro);

 

 return dCuota;

}

                                                                                                                _______

 

 

A.II.6.5.3 Implementación del cálculo del tanto de interés

 

De la misma manera se procede con SRRCH_i_ani que se presenta ahora al completo por ser más sencilla

 

//-----------------------------------------------------------------------------
// SRRCH_i_ani
//
// Cálculo del tanto de interés
//
// Partiendo de la formulación
//
//   ani = sni / (1+i)^n
//
// para el cálculo del tipo de interés como incógnita del resto de variables
// se utiliza un procedimiento de inversión cuasi-newton, el método Müller,
// que es un método de obtención de raíces por aproximación de secantes
// parabólicas
//
// Parámetros:
//
// (I)      ani = Valor actual de una renta postpagable
// (I)      i   = Interés aplicable (En cada periodo)
//
// Retorno: i o *ZEROS en caso de error
//
//----------------------------------------------------------------------------
double SRRCH_i_ani(double ani, long n)                              
{
 short int iDebug = 0; // 0/1 Establecer reolución por Newton (Por debug)

 double di1 = 0.0; // solución inexacta inferior
 double di2 = 0.0; // solución inexacta superior
 double di  = 0.0; // solución buscada
 double h   = 0.0; // Término Baily para aproximación superior


 // Filtro

 if ( (ani <= 0.0) || (n <= 0) ) return 0.0;


 // Paso de parámetros globales

 N = n;


 // Cálculo de extremos

 h = pow( (double)N / ani,  2.0 / (double)(N+1) ) - 1.0;

 di1 = 6.0 * (  (double)N - ani ) / ( (double)(N*(N-1)) + (double)(2*(N+2) )  *  ani  );
 
 di2 = h * ( 12.0 - (double)(N-1) * h ) / ( 12.0 - 2.0 * (double)(N-1) * h ) ;


 // Resolución por algoritmo de inversión Müller

 di = SRRCU_FINVMU(ani, di1, di2, Prani);

 return di;
}


 

 

Que utiliza a su vez a la función auxiliar Prani, pasándole implícitamente el valor N

 

 

// Función auxiliar para cálculo inverso de i dados ani y n

double Prani(double i) 
{
 double dResul = 0.0; // Variable retorno

 dResul = SRRCH_ValorActualRenta_ani(N, i);

 return dResul;
}

 

Más adelante, en el apéndice C, retomaremos este ejemplo con datos numéricos y veremos el detalle de la progresión de resultados parciales del algoritmo Müller, en el epígrafe C.1.1.3.1 Un ejemplo numérico de resolución con el algoritmo Müller.

 

 

                                                                                                                _______

 

 

La codificación completa extractada aquí se adjunta en el apéndice

"C5 Relación de programas de muestra desarrollados en el libro"



 

                                                                                                                _______