#!/usr/bin/perl

use 5.038.4;

# ejemplo de 10 empresas y 5 años de datos de beneficio (sin especificar ;-)

my @nemp = 0 .. 9;   # número de empresa
my @noano = 0 .. 4;  # número de año, convenientemente parte de 0, para mandar listas y recoger listas 
my @bemp;    # beneficio de la empresa i

for my $i (@noano){
    $bemp[$_][$i] = 10_000_000 * rand() for @nemp;
}

# los datos ya están

my @risk;
my @bene;
say "\nDATOS DE PARTIDA";
for my $j (@nemp){
    $risk[$j] = stddev( @{ $bemp[$j] } );
    $bene[$j] = $bemp[$j][-1];
    say "Empresa $j:   $bene[$j]   $risk[$j]";
}

# FASE 1 y 2: ordenar de - a + riesgo

my @combi = sort { $risk[$a] <=> $risk[$b] || $bene[$b] <=> $bene[$a] } @nemp;

# FASE 3, 4 y 5: recorrer @combi por @bene

my @max;
$max[0] = -9e99;
my @filter;
my $contador = 0;
say "\nFILTRO DE COMBINACIONES NO DOMINADAS";
for my $j (@combi){
    if ($bene[$j] > $max[$contador]){
	push @filter, $j;
	$contador++;                        # el 0 cuenta en $contador
	$max[$contador] = $bene[$j];
	say "Empresa $j:   $bene[$j]   $risk[$j]";
    }
}
say "Hay $contador empresas interesantes\n";

# FASE 6, 7 y 8: calcular gradientes de los no dominados (a cuánto se paga el riesgo)

my $lastgrad = 0;
my $maxgrad = -9e99;
my $estrella;
say "\nENUMERACION DE LA REMUNERACION MARGINAL DEL RIESGO";
for my $k (1 .. $contador-1){
    my $jj = $filter[$k];
    my $gradiente = $bene[$jj] - $bene[$filter[$k-1]] / ( $risk[$jj] - $risk[$filter[$k-1]] );      
    print "Empresa $jj:   unidad de beneficio añadido por unidad de riesgo = $gradiente";
    if ($gradiente > $lastgrad){
	print " (interesante) \n";
	if ($gradiente > $maxgrad){
	    $maxgrad = $gradiente;    # the winner takes it all (por esta vez el máximo es sólo 1)	    
	    $estrella = $jj;
	}
    }
    $lastgrad = $gradiente;
}

# FASE 9: se compara la combinación de mínimo riesgo con la posibilidad de no hacer nada 

my @nada = (0,0);  # es dudoso que no invertir nada tenga riesgo 0 

my $grad0 = $bene[$filter[0]] - $nada[0] / ( $risk[$filter[0]] - $nada[1] );
    
say "\nEmpresa $filter[0]:   beneficio añadido por teórica primera inversión = $grad0";  

# FASE 10: si $grad0 < $maxgrad, la primera empresa listada no es interesante

if ($grad0 < $maxgrad){
    say "\nLa empresa número $filter[0] deja de ser interesante"; 
}else{
    say "\nLa empresa que diferencialmente paga más por riesgo es $estrella y da ", $bene[$estrella]/$risk[$estrella] ;
    say "y la empresa de mínimo riesgo que es $filter[0] y da ", $bene[$filter[0]] / $risk[$filter[0]] ;
}
say "-" x 80;
        
exit 2;



sub mean {
    my @l = @_;
    my $sum  = 0;
    $sum += $_ for @l;
    $sum /= scalar @l;
    return $sum;
}

sub variance {
    my @l = @_;
    my $v = 0;
    my $m = mean (@l);
    $v += ($_ - $m)**2 for @l;
    $v /= scalar(@l)-1;
    return $v;
}

sub stddev {
    my @l = @_;
    return sqrt(variance(@l));
}

__END__
  

Criba de pares rentabilidad-riesgo sobre aquellas
  combinaciones dominadas, sin muchos supuestos.
  (c) Jesús Lozano Mosterín, 2025
