#!/usr/bin/perl -w

use strict;

my $INT = .04/365;      # dayly interest
my $INTMO = .04/12;
my $TC  = 10;           # transaction cost
my $MINI = 200;     # in MO and simulation


my $INMAX = 600;     # cash incomes, payments
my $INMIN = 100; 
my $PMAX = 400;
my $PMIN = 0;

my $ITERATIONS = 365*3;

my ($i,@cash,$inc,$pay,$variance,$mean,$momax,$modesir);
my ($invest,$obj,$iter,$simumax,$simudesir,$postcash);

srand( $$ );
for $i (1..$ITERATIONS){
    $inc = $INMIN+ rand($INMAX-$INMIN);
    $pay = $PMIN + rand($PMAX-$PMIN);
    $cash[$i] = $inc-$pay;
    $mean += $cash[$i];
}
$mean /= $ITERATIONS; 
for $i (1..$ITERATIONS){
    $variance += ($cash[$i] - $mean)**2; 
}
$variance /= $ITERATIONS; 
print "mean $mean  variance $variance\n";

$momax = &MO_max($variance,$INTMO,$TC);
$modesir = &MO_desir($variance,$INTMO,$TC);
print "momax $momax  modesir $modesir\n";
for $i (1..$ITERATIONS){
    $postcash += $cash[$i];
    $invest *= (1+$INT);
    if ($postcash>$momax) {
	$invest += $postcash - $modesir - $TC;
	$postcash=$modesir;
    }elsif ($postcash<$MINI) {
	if ($modesir-$postcash+$TC<$invest){
	    $invest -= ($modesir - $postcash) + $TC;
	    $postcash=$modesir;
	}else{
	    $postcash += $invest;
	    $invest = 0;
	}
    }
}
print "El objetivo es $invest\n";
$obj = $invest;


while (1){
    $iter++;
    $simumax = rand(3*$INMAX);
    $simudesir = $MINI + rand($INMAX);
    $invest = $postcash = 0;
    for $i (1..$ITERATIONS){
	$postcash += $cash[$i];
	$invest *= (1+$INT);
	if ($postcash>$simumax) {
	    $invest += $postcash - $simudesir - $TC;
	    $postcash=$simudesir;
	}elsif ($postcash<$MINI) {
	    if ($simudesir-$postcash+$TC<$invest){
		$invest -= ($simudesir - $postcash) + $TC;
		$postcash=$simudesir;
	    }else{
		$postcash += $invest;
		$invest =0;
	    }
	}
    }
    if ($invest > $obj) {
	print "$iter -> $simumax , $simudesir => $invest\n";
	$obj = $invest;
    }
}





sub MO {
    my ($var,$int,$ct) = @_;
    return 3*(.75*$ct*$var/$int)**(1/3);
}

sub MO_desir {
    my ($var,$int,$ct) = @_;
    return $MINI + &MO($var,$int,$ct)/3;
}

sub MO_max {
    my ($var,$int,$ct) = @_;
    return $MINI + &MO($var,$int,$ct);
}

__END__
