################################################
##
## This script simulates long trading strategies
##
################################################


use warnings;
use strict;

###
# Init
###

my $money_init = 10000;
my $transactionfee = 0.000;	#0.005
my $tradingpercentage = 0.5;
my $transactionpercentage = 0.5;
my $buy_offset = -5; # Days to event	#   -60/63;-60/75;-5/8;1/14
my $sell_offset = 8; # Sell x days after buy
my $indexticker = "NBI";

###
# Init packages 
###

# Custom packages
use Finance::EventDayChain;
use Finance::EventBackpack;
use Finance::SingleTradingDay;
use Finance::SingleDecisionEvent;

# Dumper package
use Data::Dumper;

# DB packages
use DBI;
use DBD::mysql;

###
# 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;


for (my $i = 1; $i<=1000; $i++){

	# Reset portfolio
	my $money = $money_init;

	###
	# Query events (positive and negative)
	###

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

	# Generate query
	my $option1;	# Product characteristics
	$option1->{"duplicate"} = 0;		# Ignore duplicate applications
	$option1->{"hist"}      = 0; 		# Ignore dead stock tickers
	my $option2;	# Company characteristics
	$option2->{"Xchange"} = "NASDAQ";	# [NASDAQ|NYSE]

	# Run query
	$eventBackpack_obj1->query_events("FDA",$option1,$option2,$dbh);
	$eventBackpack_obj2->query_events("FDA2",$option1,$option2,$dbh);

	###
	# Query trading days
	###

	my @days;

	my $query = "SELECT date FROM _prices_NASDAQ_NBI WHERE date > '2007-11-20' ORDER BY date ASC";
	my $sth = $dbh->prepare($query);
	$sth->execute();

	while (my @data = $sth->fetchrow_array()){
		my $obj->{"day"} = $data[0];

		push(@days,$obj);	
	}
	$sth->finish();

	###
	# Store events in days array
	###

	foreach my $event (@{$eventBackpack_obj1->get_backpack_content()}){
		for (my $index = 0; $index <scalar(@days); $index++){
			my $obj = $days[$index];
			if ($obj->{"day"} eq $event->get_date()){
				my $obj2 = $days[($index + $buy_offset)];
				if (not defined $obj2->{"buy"}){
					$obj2->{"buy"} = $event->get_ticker();
				}
				else{
					$obj2->{"buy"} .= "|".$event->get_ticker()
				}

				$days[($index + $buy_offset)] = $obj2;
			}
		}	
	}
	
	#foreach my $event (@{$eventBackpack_obj2->get_backpack_content()}){
	#	for (my $index = 0; $index <scalar(@days); $index++){
	#		my $obj = $days[$index];
	#		if ($obj->{"day"} eq $event->get_date()){
	#			my $obj2 = $days[($index + $buy_offset)];
	#			if (not defined $obj2->{"buy"}){
	#				$obj2->{"buy"} = $event->get_ticker();
	#			}
	#			else{
	#				$obj2->{"buy"} .= "|".$event->get_ticker()
	#			}
#
	#			$days[($index + $buy_offset)] = $obj2;
	#		}
	#	}	
	#}	
	
	###
	# Init PF
	###
	
	#my $index_volume = $money/2696.24;		# NBI: 837.07, IXIC: 2696.24
	#my $index_volume = $money/837.07;
	#$money = 0;		# Swap to index

	###
	# Make buy decisions
	###
	
	my $index = 0;
	foreach my $day_obj (@days){
		if (defined $day_obj->{"buy"}){
			my @tickers = split(/\|/, $day_obj->{"buy"});
			foreach my $ticker (@tickers){
				if (rand() > $tradingpercentage){	# Buy!
				
					# Get price for the reference investment
					my $iquery = "SELECT price_day_high FROM _prices_NASDAQ_".$indexticker." WHERE date = '".$day_obj->{"day"}."'";
					my $isth = $dbh->prepare($iquery);
					$isth->execute();
					my @idata = $isth->fetchrow_array();
					my $iprice = $idata[0];
					$isth->finish();
					
					# Do Reference transaction
					#$money += ($index_volume * $iprice);
					#$index_volume = 0;
				
					# Do Asset transaction
					if ($money > 1000){		# Only play if money > 1000;
					
						# Get upper price 
						my $query = "SELECT price_day_high FROM _prices_NASDAQ_".$ticker." WHERE date = '".$day_obj->{"day"}."'";
						my $sth = $dbh->prepare($query);
						$sth->execute();
						my @data = $sth->fetchrow_array();
						my $price = $data[0];
						$sth->finish();

						# Do transaction
						my $money_to_spend = ($money*$transactionpercentage)*(1-$transactionfee);
						my $number_of_shares = int($money_to_spend / $price);
						my $transaction_cost = ($number_of_shares*$price)*(1+$transactionfee);

						$money -= $transaction_cost;

						# Enter sell transaction
						my $future_obj = $days[($index+$sell_offset)];

						if (not defined $future_obj->{"sell"}){
							$future_obj->{"sell"} = $ticker."-".$number_of_shares;
						}
						else{
							$future_obj->{"sell"} .= "|".$ticker."-".$number_of_shares;
						}

						$days[($index+$sell_offset)] = $future_obj;

						# Print
						#print "BUY\t".$day_obj->{"day"}."\t".$ticker."\t".$price."\t".$number_of_shares."\n";
					}
					
					# Do reference index excess swap
					#$index_volume = $money/$iprice;
					#$money = 0;
				}
			}
		}
		if (defined $day_obj->{"sell"}){
			my @tickersraw = split(/\|/, $day_obj->{"sell"});
			foreach (@tickersraw){
				my @a = split(/-/,$_);
				my $ticker = $a[0];
				my $number_of_shares = $a[1];

				# Get lower price (or halfway between average up and down max??)
				my $query = "SELECT price_day_low FROM _prices_NASDAQ_".$ticker." WHERE date = '".$day_obj->{"day"}."'";
				my $sth = $dbh->prepare($query);
				$sth->execute();
				my @data = $sth->fetchrow_array();
				my $price = $data[0];
				$sth->finish();

				# Sell
				my $transaction_return = ($number_of_shares*$price)*(1-$transactionfee);
				$money += $transaction_return;

				# Print
				#print "SELL\t".$day_obj->{"day"}."\t".$ticker."\t".$price."\t".$number_of_shares."\n";
				
				# Get price for the reference investment
				my $iquery = "SELECT price_day_high FROM _prices_NASDAQ_".$indexticker." WHERE date = '".$day_obj->{"day"}."'";
				my $isth = $dbh->prepare($iquery);
				$isth->execute();
				my @idata = $isth->fetchrow_array();
				my $iprice = $idata[0];
				$isth->finish();
				
				# Swap excess money to reference
				#$money += ($index_volume * $iprice);
				#$index_volume = 0;
				#$index_volume = $money/$iprice;
				#$money = 0;				
			}
		}
		$index++;
	}
	
	# Swap all back
	#$money = $index_volume * 3040.24;	#IXIC
	#$money = $index_volume * 1411.65;	#NBI

	print $money_init."\t".$money."\t".($money-$money_init)."\t".(($money-$money_init)/$money_init)."\n";
	# Calculate Sharpe as return>NBI index, var = variance of simulated returns;
}

$dbh->disconnect();

sub index_return {
	
	my $index = $_[0];
	
	## NBI 
	## 1/12/2007: 873.07
	## 1/9/2012: 1411.65
	
	## IXIC
	## 1/12/2007: 2696.24
	## 1/9/2012: 3040.24
	
	if ($index eq "NBI"){
		my $hpr = (1411.65-873.07)/873.07;
		return($hpr);
	}
	
	if ($index eq "IXIC"){
		my $hpr = (3040.24-2696.24)/2696.24;
		return($hpr);
	}	
}