function [train_rets, test_rets] = ga(ts, ret_mat, train_prop, tree_size, pop_size, generations)

tree_size = tree_size - 1;

rand('state', sum(100 * clock));

lengo = length(ts);

train_start = 1;
train_end = ceil(train_prop * lengo);

test_start = train_end + 1;
test_end = lengo;


%calculate moving averages

n_operators = 2;
n_terminals = 20;

if (tree_size == 1)
  gen_len = 3;
else
  gen_len = 7;   %%%change
end  
  



if (tree_size == 1)
  

  %generate trees
  for i = 1:pop_size
    pop(i,1) = ceil(rand(1) * n_operators);    
    pop(i,2) =  ceil(rand(1) * n_terminals);   
    pop(i,3) = ceil(rand(1) * n_terminals);
  end


  for cur_tree = 1:pop_size
    if (pop(cur_tree,1) == 1)
      signal(cur_tree,:) = ts(pop(cur_tree,2),:) >...
	  ts(pop(cur_tree,3),:);
    else	
      signal(cur_tree,:) = ts(pop(cur_tree,2),:) <...
	  ts(pop(cur_tree,3),:);
    end	
    
    returns(cur_tree,:) = (signal(cur_tree,:) == 1) .* ret_mat(1,:);
    returns(cur_tree,:) = returns(cur_tree,:) +...
	(signal(cur_tree,:) == 0) .* ret_mat(2,:);
    
  end      

  ltrain_rets = mean(returns(:,train_start:train_end)');
  ltest_rets = mean(returns(:,test_start:test_end)');        

  ltrain_rets = exp(ltrain_rets * 260) - 1;
  ltest_rets = exp(ltest_rets * 260) - 1;

  old_ltrain_rets = ltrain_rets;	
  old_ltest_rets = ltest_rets;		

  train_rets(1) = mean(ltrain_rets);
  test_rets(1) = mean(ltest_rets);
    

  for i = 2:generations

    %alter:
    if (pop_size == 1) %we've got hillclimbing
      new_pop = pop;      
      chango = ceil(rand(1) * gen_len);
      if (chango == 1)
	new_pop(1,chango) = ceil(rand(1) * n_operators);    
      else	
	new_pop(1,chango) =  ceil(rand(1) * n_terminals);   
      end
    else %pop_size > 1


      pick_mat = max(ltrain_rets, .005);
      pick_mat;
      pick_mat = pick_mat / sum(pick_mat);

      for q = 2:pop_size
	pick_mat(q) = pick_mat(q-1) + pick_mat(q);	
      end	

      for cur_tree = 1:pop_size
	if cur_tree <= (pop_size * .5)
	  %mutate
	  [junk,new_tree] = max(rand(1) < pick_mat);
  
	  new_pop(cur_tree,:) = pop(new_tree,:); 	  
	  chango = ceil(rand(1) * gen_len);
	  if (chango == 1)
	    new_pop(cur_tree,chango) = ceil(rand(1) * n_operators);    
	  else	
	    new_pop(cur_tree,chango) =  ceil(rand(1) * n_terminals);   
	  end
	else
	  %crossover	  
	  [junk,tree_a] = max(rand(1) < pick_mat);	  
	  [junk,tree_b] = max(rand(1) < pick_mat);	  	  
	  cross_point = ceil(rand(1) * gen_len-1);
	  new_pop(cur_tree,:) = [pop(tree_a,1:cross_point) pop(tree_b,cross_point+1:gen_len)];
	end %if
      end %for
    end %pop_size?     
    %no more alter    


    for cur_tree = 1:pop_size
      if (new_pop(cur_tree,1) == 1)
	signal(cur_tree,:) = ts(new_pop(cur_tree,2),:) >...
	    ts(new_pop(cur_tree,3),:);
      else	
	signal(cur_tree,:) = ts(new_pop(cur_tree,2),:) <...
	    ts(new_pop(cur_tree,3),:);
      end	

      returns(cur_tree,:) = (signal(cur_tree,:) == 1) .* ret_mat(1,:);
      returns(cur_tree,:) = returns(cur_tree,:) +...
	  (signal(cur_tree,:) == 0) .* ret_mat(2,:);

    end          
    
    ltrain_rets = mean(returns(:,train_start:train_end)');
    ltest_rets = mean(returns(:,test_start:test_end)');        

    ltrain_rets = exp(ltrain_rets * 260) - 1;
    ltest_rets = exp(ltest_rets * 260) - 1;



    if (pop_size == 1)
    
      if ltrain_rets > train_rets(i-1);

	train_rets(i) = ltrain_rets;
	test_rets(i) = ltest_rets;	
	pop = new_pop;

      else	
	train_rets(i) = train_rets(i-1);
	test_rets(i) = test_rets(i-1);	
      end
      
    else
      %      train_rets(i,:) = ltrain_rets;
      %      test_rets(i,:) = ltest_rets;	

      for cur_tree = 1:pop_size
	old_tree = ceil(rand(1) * pop_size);
	if ltrain_rets(cur_tree) > old_ltrain_rets(old_tree);
	  old_ltrain_rets(old_tree) = ltrain_rets(cur_tree);
	  old_ltest_rets(old_tree) = ltest_rets(cur_tree);	  
	  pop(old_tree) = new_pop(cur_tree);	  
	end	  
	  
	train_rets(i) = mean(old_ltrain_rets);
	test_rets(i) = mean(old_ltest_rets);	

      end	
    end      

  end
    
else   %tree size 2;

  %generate trees
  for i = 1:pop_size
    pop(i,1) = ceil(rand(1) * n_operators);    

    pop(i,2) = ceil(rand(1) * n_operators);        
    pop(i,3) = ceil(rand(1) * n_terminals);        
    pop(i,4) = ceil(rand(1) * n_terminals);            

    pop(i,5) = ceil(rand(1) * n_operators);        
    pop(i,6) = ceil(rand(1) * n_terminals);        
    pop(i,7) = ceil(rand(1) * n_terminals);            

  end


  for cur_tree = 1:pop_size
    if (pop(cur_tree,2) == 1)
      signal1(cur_tree,:) = ts(pop(cur_tree,3),:) >...
	  ts(pop(cur_tree,4),:);
    else	
      signal1(cur_tree,:) = ts(pop(cur_tree,3),:) <...
	  ts(pop(cur_tree,4),:);
    end	
    
    
    if (pop(cur_tree,5) == 1)
      signal2(cur_tree,:) = ts(pop(cur_tree,6),:) >...
	  ts(pop(cur_tree,7),:);
    else	
      signal2(cur_tree,:) = ts(pop(cur_tree,6),:) <...
	  ts(pop(cur_tree,7),:);
    end	
    
    if (pop(cur_tree,1) == 1) %and
      signal(cur_tree,:) = signal1(cur_tree,:) .* signal2(cur_tree,:);
    else      %or
      signal(cur_tree,:) = ((signal1(cur_tree,:) + signal2(cur_tree,:)) > 0);
    end      
      
    returns(cur_tree,:) = (signal(cur_tree,:) == 1) .* ret_mat(1,:);
    returns(cur_tree,:) = returns(cur_tree,:) +...
	(signal(cur_tree,:) == 0) .* ret_mat(2,:);
      
  end
    
  ltrain_rets = mean(returns(:,train_start:train_end)');
  ltest_rets = mean(returns(:,test_start:test_end)');        
  
  ltrain_rets = exp(ltrain_rets * 260) - 1;
  ltest_rets = exp(ltest_rets * 260) - 1;
  

  old_ltrain_rets = ltrain_rets;	
  old_ltest_rets = ltest_rets;		

  
  
  train_rets(1) = mean(ltrain_rets);
  test_rets(1) = mean(ltest_rets);
  
  
  for i = 2:generations
    
    %alter:
    if (pop_size == 1) %we've got hillclimbing
      new_pop = pop;      
      chango = ceil(rand(1) * gen_len);
      if ((chango == 1) | (chango == 2) | (chango == 5))
	new_pop(1,chango) = ceil(rand(1) * n_operators);    
      else	
	new_pop(1,chango) =  ceil(rand(1) * n_terminals);   
      end
    else %pop_size > 1
      
      
      pick_mat = max(ltrain_rets, .005);
      pick_mat;
      pick_mat = pick_mat / sum(pick_mat);
      
      for q = 2:pop_size
	pick_mat(q) = pick_mat(q-1) + pick_mat(q);	
      end	
      
      for cur_tree = 1:pop_size
	if cur_tree <= (pop_size * .33)
	  [junk,new_tree] = max(rand(1) < pick_mat);
	  
	  new_pop(cur_tree,:) = pop(new_tree,:); 	  
	elseif cur_tree <= (pop_size * .66)	  
	  %mutate
	  [junk,new_tree] = max(rand(1) < pick_mat);
	  
	  new_pop(cur_tree,:) = pop(new_tree,:); 	  
	  chango = ceil(rand(1) * gen_len);
	  if ((chango == 1) | (chango == 2) | (chango == 5))	  
	    new_pop(cur_tree,chango) = ceil(rand(1) * n_operators);    
	  else	
	    new_pop(cur_tree,chango) =  ceil(rand(1) * n_terminals);   
	  end
	else
	  %crossover	  
	  [junk,tree_a] = max(rand(1) < pick_mat);	  
	  [junk,tree_b] = max(rand(1) < pick_mat);	  	  
	  cross_point = ceil(rand(1) * gen_len-1);
	  new_pop(cur_tree,:) = [pop(tree_a,1:cross_point) pop(tree_b,cross_point+1:gen_len)];
	end %if
      end %for
    end %pop_size?     
    %no more alter    
    
    
    for cur_tree = 1:pop_size

      if (new_pop(cur_tree,2) == 1)
	signal1(cur_tree,:) = ts(new_pop(cur_tree,3),:) >...
	    ts(new_pop(cur_tree,4),:);
      else	
	signal1(cur_tree,:) = ts(new_pop(cur_tree,3),:) <...
	    ts(new_pop(cur_tree,4),:);
      end	
      
      
      if (new_pop(cur_tree,5) == 1)
	signal2(cur_tree,:) = ts(new_pop(cur_tree,6),:) >...
	    ts(new_pop(cur_tree,7),:);
      else	
	signal2(cur_tree,:) = ts(new_pop(cur_tree,6),:) <...
	    ts(new_pop(cur_tree,7),:);
      end	
      
      if (new_pop(cur_tree,1) == 1) %and
	signal(cur_tree,:) = signal1(cur_tree,:) .* signal2(cur_tree,:);
      else      
	signal(cur_tree,:) = ((signal1(cur_tree,:) + signal2(cur_tree,:)) > 0);
      end          
      
      returns(cur_tree,:) = (signal(cur_tree,:) == 1) .* ret_mat(1,:);
      returns(cur_tree,:) = returns(cur_tree,:) +...
	  (signal(cur_tree,:) == 0) .* ret_mat(2,:);
      
    end      

    ltrain_rets = mean(returns(:,train_start:train_end)');
    ltest_rets = mean(returns(:,test_start:test_end)');        
      
    ltrain_rets = exp(ltrain_rets * 260) - 1;
    ltest_rets = exp(ltest_rets * 260) - 1;
    
    
    
    if (pop_size == 1)
      
      if ltrain_rets > train_rets(i-1);
	
	train_rets(i) = ltrain_rets;
	test_rets(i) = ltest_rets;	
	pop = new_pop;
	
      else	
	train_rets(i) = train_rets(i-1);
	test_rets(i) = test_rets(i-1);	
      end
      
    else
      %      train_rets(i,:) = ltrain_rets;
      %      test_rets(i,:) = ltest_rets;	

      for cur_tree = 1:pop_size
	old_tree = ceil(rand(1) * pop_size);
	if ltrain_rets(cur_tree) > old_ltrain_rets(old_tree);
	  old_ltrain_rets(old_tree) = ltrain_rets(cur_tree);
	  old_ltest_rets(old_tree) = ltest_rets(cur_tree);	  
	  pop(old_tree) = new_pop(cur_tree);	  
	end	  
	  
	train_rets(i) = mean(old_ltrain_rets);
	test_rets(i) = mean(old_ltest_rets);	

      end	
      

    end      
    
  end
  
  
  
end

hold off;

plot(train_rets);

hold on;

plot(test_rets,'r');

hold off;