#!/usr/bin/perl

use 5.038.2;
# use utf8;

my $DEBUG = 0;

# Versión 2

### THIS VERSION IS TRASH!!!
# ...was, it was
# dom 26 abr 2026 10:00:41 CEST
# sáb 16 may 2026 05:51:29 CEST
# ejemplo de 1000 fondos y 5 años de datos de beneficio (sin especificar ;-)

my @nemp = 0 .. 999;   # número de empresa
my @nyear = 0 .. 4;    # número de año, convenientemente parte de 0, para mandar listas y recoger listas 
my @bemp;              # beneficio de la empresa i
my $riesgo = 0.25;     # reperesenta la probabilidad de pérdidas. No es aleatoria, como si sí

for my $i (0 .. scalar(@nyear)-1){
    for my $j (0 .. scalar(@nemp)-1){
	$bemp[$j][$i] = 1_000_000 * rand() for @nemp;
	$bemp[$j][$i] *= -1 if (rand() < $riesgo);
    }
}

# los datos ya están  *** DATOS SIMULADOS ***

# FASE 0 -> tomamos la media y no la suma de actualizaciones o número-índice, más tarde
# así no hace falta el interés

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

##################################################################################################

say "$0 v.2    ", scalar(localtime()),"\n"; 

# 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 = (-9e99) x scalar (@nemp);
my $max = -9e99;
my @filter;

say "\nFILTRO DE COMBINACIONES NO DOMINADAS";
say "Es decir, de la ordenación por menor riesgo y desempate mayor beneficio";
say "sale una lista de empresas simplemente mejores \:\-\) C\'est la vie"; 
my $i = 0;
my $contador = 0;
for my $profit (@combi){    
    if ($profit > $max){    # estrictamente
	$max = $profit;
	$filter[$contador] = $i;
	$contador++;                        # el 0 cuenta en $contador
	say "Empresa \#$i:   contador\=$contador   beneficio\=$profit   riesgo\=$risk[$i]";
    }
    $i++;
}
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 @maxgrad = (-9e99) x ($contador-1);
my $estrella;
my $gradiente;

say "\nLISTADO DE LA REMUNERACION MARGINAL DEL RIESGO";
for my $k (1 .. $contador-1){
    next if ( $risk[ $filter[$k] ] - $risk[ $filter[$k-1] ] == 0 );
    $gradiente = $bene[ $filter[$k] ] - ( $bene[ $filter[$k-1] ] / ( $risk[ $filter[$k] ] - $risk[ $filter[$k-1] ] ));       
    print "Empresa \#$filter[$k]:   unidad de beneficio añadido por unidad de riesgo = $gradiente";
    if ($gradiente > $maxgrad[$k]){                    # estrictamente mayor
	print "   (interesante) \n";
	$maxgrad[$k] = $gradiente;
	$estrella = $filter[$k];
	$maxgrad[$k+1] = $maxgrad[$k];
    }else{
	say "";
    }
}

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

# my ($bene0, $risk0) = (0,0);  # es dudoso que no invertir nada tenga riesgo 0 
# Nota: esto antes se llamaba @nada, lo cual no es un libro abierto 

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

# FASE 10: si $grad0 < $maxgrad[$n+1], la primera empresa listada no es interesante

for my $k (1 .. $contador-1){
    if ($maxgrad[$k-1] < $maxgrad[$k]){
	say "\nLa empresa número $filter[$k-1] deja de ser interesante sobre número $filter[$k]";
	say "El vector desde origen es menor que uno posterior, uno o varios";
    }
}
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 3;



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

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

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

__END__
  

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