################################################
##
## This script calculates abnormal returns
##
################################################

use strict;
use Finance::EventDayChain;
use Finance::EventBackpack;
use Finance::SingleTradingDay;
use Finance::SingleDecisionEvent;
use Data::Dumper;
use DBI;
use DBD::mysql;

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

# Window sizes
my $training_start  = 140;
my $training_stop   = 90;
my $anticipation_start = 60;
my $anticipation_end = 1;
my $event_offset    = 1;
my $event_post      = 30;

# Training set
my $training_bourse = "NYSE";
my $training_index  = "DRG";
my $FFbourse1 = "famafrench";
my $FFindex1  = "HML";
my $FFbourse2 = "famafrench";
my $FFindex2  = "SMB";

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

###
# Open DB connection
###

my $db  = "DBI:mysql:thesis_economie:athos.ugent.be";
my $us  = "ewthesis";
my $pw  = "thesisew";
my $dbh = DBI->connect($db,$us,$pw) || die "Cannot connect: " . $DBI::errstr;

###
# Query events
###

# Initialise query
my $eventBackpack_obj = Finance::EventBackpack->new();

# Generate query
my $agency = "EMA";

my $option1;	# Product characteristics
$option1->{"duplicate"} = 0;		# Ignore duplicate applications
$option1->{"hist"}      = 0; 		# Ignore dead stock tickers
$option1->{"status"}    = "AUTHORISED";	# Refusals
#$option1->{"generic"}   = "NO";		# Ignore generic product applications
#$option1->{"biosimilar"}= "NO";		# Ignore biosimilar applications
#$option1->{"orphan"}    = "NO";		# Ignore orphan diseases applications
#$option1->{"NDA_type"}  = "1";		# NDA type [1-6]
#$option1->{"review_classification"} = "S";	# Standard [S] or Priority [R]

my $option2;	# Company characteristics
$option2->{"Xchange"} = "NYSE";	# [NASDAQ|NYSE]
#$option2->{"name"}    = "AFFYMAX";	# Run single company (debug mode)
#$option2->{"ticker"}  = "VRTX";
#$option2->{"ticker"}  = "LLY|PFE|MRK|ABT|GSK|BMY|JNJ|NVS|SNY";	# Run single ticker (debug mode)

# Run query
$eventBackpack_obj->query_events($agency,$option1,$option2,$dbh);

###
# Process queried events
###

# Generate super bag
my $superBag = {};
my @a = ();
my @b = ();
my @c = ();
my @d = ();
$superBag->{"training"} = \@a;
$superBag->{"anticipation"} = \@b;
$superBag->{"event"} = \@c;
$superBag->{"post"} = \@d;

# Init counter
my $event_count=0;

# Process
foreach my $event (@{$eventBackpack_obj->get_backpack_content()}){

	# Count
	$event_count++;
	
	# Print 
	print "** ".$event->get_ticker()." **\n";
	
	# Training data
	my $dayChain1 = generate_trainer($event->get_date(),$training_bourse,$training_index,$FFbourse1,$FFindex1,$FFbourse2,$FFindex2,$event->get_ticker(),$training_start,-$training_stop,$dbh,1);	# 1 for FF, 0 for factor model
	
	# Analyis
	my $dayChain2 = analyse($dayChain1,$anticipation_start,-$anticipation_end,$dbh,1);	# 1 for FF, 0 for factor model
	my $dayChain3 = analyse($dayChain1,0,$event_offset,$dbh,1);
	my $dayChain4 = analyse($dayChain1,-$event_offset,$event_post,$dbh,1);
	
	# Store
	my @superBagA = @{$superBag->{"training"}};
	push(@superBagA,$dayChain1);
	$superBag->{"training"} = \@superBagA;

	my @superBagB = @{$superBag->{"anticipation"}};
	push(@superBagB,$dayChain2);
	$superBag->{"anticipation"} = \@superBagB;	

	my @superBagC = @{$superBag->{"event"}};
	push(@superBagC,$dayChain3);
	$superBag->{"event"} = \@superBagC;	

	my @superBagD = @{$superBag->{"post"}};
	push(@superBagD,$dayChain4);
	$superBag->{"post"} = \@superBagD;	

	# print 
	#print_for_R ($dayChain1,$dayChain2,$dayChain3,$dayChain4);
}

print "!!Aggregating!!";

#print Dumper($superBag);

# Calculate average
my $averages = {};
my @types = ("anticipation", "event", "post");
foreach my $type (@types){

	foreach my $event (@{$superBag->{$type}}){
		
		my $chain = $event->get_cumulative_abnormal_return();
		my $chain2 = $event->get_abnormal_return();
		
		foreach my $day (keys %{$chain}){
			$averages->{$type}->{"cumulu"}->{$day} += $chain->{$day};
			$averages->{$type}->{"normal"}->{$day} += $chain2->{$day};
		}
	}
}

foreach my $type (@types){
	foreach my $day (keys %{$averages->{$type}->{"cumulu"}}){
		$averages->{$type}->{"cumulu"}->{$day} /= $event_count;
		$averages->{$type}->{"normal"}->{$day} /= $event_count;
		
		print $day."\t".$averages->{$type}->{"cumulu"}->{$day}."\t".$averages->{$type}->{"normal"}->{$day}."\n";
		
	}
}

# Print
my $Chain1 = Finance::EventDayChain->new();
my $Chain2 = Finance::EventDayChain->new();
my $Chain3 = Finance::EventDayChain->new();
my $Chain4 = Finance::EventDayChain->new();

$Chain1->set_ticker("AVG");
$Chain1->set_date("AVG");
$Chain1->set_Xchange("AVG");
$Chain1->set_abnormal_variance(1/$event_count);

$Chain2->set_cumulative_abnormal_return($averages->{"anticipation"}->{"cumulu"});
$Chain3->set_cumulative_abnormal_return($averages->{"event"}->{"cumulu"});
$Chain4->set_cumulative_abnormal_return($averages->{"post"}->{"cumulu"});

print_for_R ($Chain1,$Chain2,$Chain3,$Chain4);

###############
## FUNCTIONS ##
###############

# Generate trainer

sub generate_trainer {

	# Catch parameters
	my $date      = $_[0];
	my $bourse    = $_[1];
	my $index     = $_[2];
	my $FFbourse1 = $_[3];
	my $FFindex1  = $_[4];
	my $FFbourse2 = $_[5];
	my $FFindex2  = $_[6];	
	my $ticker    = $_[7];
	my $window1   = $_[8];
	my $window2   = $_[9];
	my $dbh       = $_[10];
	my $modeltype = $_[11];

	# Get reference data
	my $dayChainRef1 = Finance::EventDayChain->new();
	$dayChainRef1->retrieve_SingleTradingDays_around_window($date,$bourse,$index,$window1,$window2,$dbh);	

	# Get reference HML data
	my $dayChainRef2 = Finance::EventDayChain->new();
	$dayChainRef2->retrieve_SingleTradingDays_around_window($date,$FFbourse1,$FFindex1,$window1,$window2,$dbh);	
	
	# Get reference SMB data
	my $dayChainRef3 = Finance::EventDayChain->new();
	$dayChainRef3->retrieve_SingleTradingDays_around_window($date,$FFbourse2,$FFindex2,$window1,$window2,$dbh);
	
	# Init data chain
	my $dayChainAsset = Finance::EventDayChain->new();
	$dayChainAsset->retrieve_SingleTradingDays_around_window($date,$bourse,$ticker,$window1,$window2,$dbh);
	
	# Attach and check reference
	$dayChainAsset->attach_index_reference($dayChainRef1);
	$dayChainAsset->attach_HML_reference($dayChainRef2);
	$dayChainAsset->attach_SMB_reference($dayChainRef3);
	$dayChainAsset->reference_sanity_check($modeltype);	# 1 for Fama French sanity check / 0 for other

	# Calculate Fama French model
	$dayChainAsset->calculate_Fama_French();
	
	# Calculate variance of prediction errors
	$dayChainAsset->calculate_chain_abnormal_return($modeltype);	# 1 for Fama French method / 0 for other
	
	# Return
	return($dayChainAsset);
}

# Analyse
sub analyse {

	### Catch

	# Catch parameters
	my $training_obj  = $_[0];
	my $window1       = $_[1];
	my $window2       = $_[2];
	my $dbh           = $_[3];
	my $modeltype     = $_[4];
		
	# Fetch asset ticker/Xchange
	my $date    = $training_obj->get_date();
	my $ticker  = $training_obj->get_ticker();
	my $Xchange = $training_obj->get_Xchange();
	
	### Asset
	
	# Init Asset data chain
	my $dayChain = Finance::EventDayChain->new();
	
	# Process Asset data chain
	$dayChain->retrieve_SingleTradingDays_around_window($date,$Xchange,$ticker,$window1,$window2,$dbh);

	### References

	# Fetch index parameters
	my $index_object  = $training_obj->get_reference_index();
	my $index_date    = $index_object->get_date();
	my $index_Xchange = $index_object->get_Xchange();
	my $index_ticker  = $index_object->get_ticker();

	# Get reference data (index is shared)
	my $dayChainRef1 = Finance::EventDayChain->new();
	$dayChainRef1->retrieve_SingleTradingDays_around_window($date,$index_Xchange,$index_ticker,$window1,$window2,$dbh);	
	
	# Factor model
	if ($modeltype == 0){
		
		# Attach and check reference
		$dayChain->attach_index_reference($dayChainRef1);
		$dayChain->reference_sanity_check(0);
		
		# Set alfa and beta from training set
		$dayChain->set_ref_index_slope($training_obj->get_ref_index_slope());
		$dayChain->set_ref_intercept($training_obj->get_ref_intercept());
		
		# Calculate normal returns of reference index
		$dayChain->get_reference_index->calculate_chain_normal_return();
		
	}
	# FF model
	elsif ($modeltype == 1){
	
		# Fetch HML parameters
		my $HML_object  = $training_obj->get_reference_HML();
		my $HML_date    = $HML_object->get_date();
		my $HML_Xchange = $HML_object->get_Xchange();
		my $HML_ticker  = $HML_object->get_ticker();

		# Fetch SMB parameters
		my $SMB_object  = $training_obj->get_reference_SMB();
		my $SMB_date    = $SMB_object->get_date();
		my $SMB_Xchange = $SMB_object->get_Xchange();
		my $SMB_ticker  = $SMB_object->get_ticker();
		
		# Get reference data
		my $dayChainRef2 = Finance::EventDayChain->new();
		$dayChainRef2->retrieve_SingleTradingDays_around_window($HML_date,$HML_Xchange,$HML_ticker,$window1,$window2,$dbh);
		
		my $dayChainRef3 = Finance::EventDayChain->new();
		$dayChainRef3->retrieve_SingleTradingDays_around_window($SMB_date,$SMB_Xchange,$SMB_ticker,$window1,$window2,$dbh);;
		
		# Attach and check references
		$dayChain->attach_index_reference($dayChainRef1);
		$dayChain->attach_HML_reference($dayChainRef2);
		$dayChain->attach_SMB_reference($dayChainRef3);
		$dayChain->reference_sanity_check(1);
		
		# Set coefficients from training set
		$dayChain->set_ref_index_slope($training_obj->get_ref_index_slope());
		$dayChain->set_ref_HML_slope($training_obj->get_ref_HML_slope());
		$dayChain->set_ref_SMB_slope($training_obj->get_ref_SMB_slope());
		$dayChain->set_ref_intercept($training_obj->get_ref_intercept());
		
		# Calculate normal returns of references
		$dayChain->get_reference_HML->calculate_chain_normal_return();
		$dayChain->get_reference_SMB->calculate_chain_normal_return();
		$dayChain->get_reference_index->calculate_chain_normal_return();
	}
	else{
		die "error, fix error message !!!";
	}

	# calculate normal returns in data
	$dayChain->calculate_chain_normal_return();
			
	# calculcate abnormal returns
	$dayChain->calculate_chain_abnormal_return($modeltype);
	
	# Normalize abnormal returns
	$dayChain->normalize_chain_abnormal_return($training_obj->get_abnormal_variance);
	
	# calculate cumulative abnormal returns	
	$dayChain->calculate_chain_abnormal_cumulative_return();	
	
	# Return
	return($dayChain);
}

sub print_for_R {

	# Catch parameters
	my $dayChain1 = $_[0];
	my $dayChain2 = $_[1];
	my $dayChain3 = $_[2];
	my $dayChain4 = $_[3];
	
	# Open file
	open (OUT1,">tmp/to_plot1.txt");
	open (OUT2,">tmp/to_plot2.txt");
	open (OUT3,">tmp/to_plot3.txt");
	
	# Init headers
	print OUT1 "day\treturn\tvar\tvar2\tvar3\tvar4\tvar5\tvar6\tvar7\tvar8\n";
	print OUT2 "day\treturn\tvar\tvar2\tvar3\tvar4\tvar5\tvar6\tvar7\tvar8\n";
	print OUT3 "day\treturn\tvar\tvar2\tvar3\tvar4\tvar5\tvar6\tvar7\tvar8\n";
	
	# Fetch
	my $variance = $dayChain1->get_abnormal_variance();
	my $stdev = sqrt($variance);
		
	# Print
	my %returns2 = %{$dayChain2->get_cumulative_abnormal_return()};
	my %returns3 = %{$dayChain3->get_cumulative_abnormal_return()};
	my %returns4 = %{$dayChain4->get_cumulative_abnormal_return()};
	
	# Crit values
	my $crit_val1 = 2.5758;
	my $crit_val2 = 1.96;
	my $crit_val3 = 1.6449;
	my $crit_val4 = 1.2816;
	
	# Init last
	my $final_return1 = 0;
	my $final_return2= 0;
	
	# Up
	my $counter2 = 1;
	foreach my $day (sort {$a <=> $b} keys %returns2){
	
		my $var_limit1 = $counter2*$stdev*$crit_val1;
		my $var_limit2 = $counter2*$stdev*$crit_val2;
		my $var_limit3 = $counter2*$stdev*$crit_val3;
		my $var_limit4 = $counter2*$stdev*$crit_val4;
		print OUT1 $day."\t".$returns2{$day}."\t".$var_limit1."\t".(-$var_limit1)."\t".$var_limit2."\t".(-$var_limit2)."\t".$var_limit3."\t".(-$var_limit3)."\t".$var_limit4."\t".(-$var_limit4)."\n";
		
		$counter2++;
		$final_return1 = $returns2{$day};
	}

	# Event
	my $counter3 = 1;
	foreach my $day (sort {$a <=> $b} keys %returns3){
	
		my $var_limit1 = $counter3*$stdev*$crit_val1;
		my $var_limit2 = $counter3*$stdev*$crit_val2;
		my $var_limit3 = $counter3*$stdev*$crit_val3;
		my $var_limit4 = $counter3*$stdev*$crit_val4;
		print OUT2 $day."\t".($final_return1+$returns3{$day})."\t".($final_return1+$var_limit1)."\t".($final_return1-$var_limit1)."\t".($final_return1+$var_limit2)."\t".($final_return1-$var_limit2)."\t".($final_return1+$var_limit3)."\t".($final_return1-$var_limit3)."\t".($final_return1+$var_limit4)."\t".($final_return1-$var_limit4)."\n";	
	
		$counter3++;
		$final_return2 = $final_return1+$returns3{$day};
	}
	
	# Down
	my $counter4 = 1;
	foreach my $day (sort {$a <=> $b} keys %returns4){
	
		my $var_limit1 = $counter4*$stdev*$crit_val1;
		my $var_limit2 = $counter4*$stdev*$crit_val2;
		my $var_limit3 = $counter4*$stdev*$crit_val3;
		my $var_limit4 = $counter4*$stdev*$crit_val4;
		print OUT3 $day."\t".($final_return2+$returns4{$day})."\t".($final_return2+$var_limit1)."\t".($final_return2-$var_limit1)."\t".($final_return2+$var_limit2)."\t".($final_return2-$var_limit2)."\t".($final_return2+$var_limit3)."\t".($final_return2-$var_limit3)."\t".($final_return2+$var_limit4)."\t".($final_return2-$var_limit4)."\n";
			
		$counter4++;
	}
	
	# Close files
	close(OUT1);
	close(OUT2);
	close(OUT3);
	
	# Open R file
	open (OUT4,">tmp/R_to_plot.R");
	
	# Generate R script
	print OUT4 "setwd(\"C:/Users/f/Dropbox/__WORK/Thesis_EW/\")\n";
	
	print OUT4 "pdf(\"tmp/".$dayChain1->get_Xchange().".".$dayChain1->get_ticker().".".$dayChain1->get_date().".pdf\")\n";
	print OUT4 "plot_data1 <- read.table(\"tmp/to_plot1.txt\", header=T, sep=\"\\t\")\n";
	print OUT4 "plot_data2 <- read.table(\"tmp/to_plot2.txt\", header=T, sep=\"\\t\")\n";
	print OUT4 "plot_data3 <- read.table(\"tmp/to_plot3.txt\", header=T, sep=\"\\t\")\n";
	
	print OUT4 "plot(plot_data1\$day, plot_data1\$return, type=\"l\", xlim=c(-60,30), ylim=c(-10,10), ann=FALSE)\n";
	print OUT4 "lines(plot_data1\$day, plot_data1\$var7, col=\"red\")\n";
	print OUT4 "lines(plot_data1\$day, plot_data1\$var8, col=\"red\")\n";
	
	print OUT4 "lines(plot_data2\$day, plot_data2\$return, type=\"l\")\n";
	print OUT4 "lines(plot_data2\$day, plot_data2\$var7, col=\"red\")\n";
	print OUT4 "lines(plot_data2\$day, plot_data2\$var8, col=\"red\")\n";
	
	print OUT4 "lines(plot_data3\$day, plot_data3\$return, type=\"l\")\n";
	print OUT4 "lines(plot_data3\$day, plot_data3\$var7, col=\"red\")\n";
	print OUT4 "lines(plot_data3\$day, plot_data3\$var8, col=\"red\")\n";
	
	print OUT4 "abline(h = seq(-10, 10, 1), col = \"gray60\", lty=3)\n";
	print OUT4 "abline(h = 0, lty=3)\n";
	print OUT4 "abline(v = 0, col = \"gray60\", lty=3)\n";
	print OUT4 "abline(v = 2, col = \"gray60\", lty=3)\n";
	
	print OUT4 "title(main=\"".$dayChain1->get_Xchange().".".$dayChain1->get_ticker().".".$dayChain1->get_date()."\", font.main=4)\n";
	
	print OUT4 "title(xlab=\"T\")\n";
	print OUT4 "title(ylab=\"Cumulative return\")\n";	
	
	print OUT4 "dev.off()";
	
	# Close R file
	close(OUT4);
	
	# Run file
	system ("\"C:/Program Files/R/R-2.15.2/bin/Rscript.exe\" C:/Users/f/Dropbox/__WORK/Thesis_EW/tmp/R_to_plot.R");
}	

# Close connection
$dbh->disconnect();