/* 
   Adaline for Dow Jones prediction
   by Andres Perez-Uribe
   Sep, 1998
   
   Email : aperez@lslsun.epfl.ch
           Logic Systems Laboratory
           Swiss Federal Institute of Technology
           http://lslwww.epfl.ch/~aperez/

   Compile : gcc -o tempadaline tempadaline.c -lm

*/

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

#define IN         15    /* number if inputs */
#define OUT         1    /* number of outputs */

#define MAX      5000    /* max Dow Jones value */
#define SIZE     2528    /* data base size */
#define TRSIZE   2500    /* training size */

#define LR         0.1   /* learning rate */

float w[IN];   /* synaptic weights */
float b;    /* bias */

float dd[SIZE];    /* data */ 
float x[IN];

/* prototypes */
void init(void);
void read_data();
void delay_inputs(int i,float x[IN]);
float output(int i,float x[IN]);
void train();
void test();

main(void) 
{
 srand(time(NULL));
 init();
 read_data();
 train();
 test();
}

void init(void) 
{
 int i;

 for(i=0;i<IN;i++)
  w[i] = -0.5 + ((float)rand() / RAND_MAX);
 b = -0.5 + ((float)rand() / RAND_MAX);
}

void read_data()
{
 FILE *fp;
 int i;
 
 if((fp=fopen("dow_data.txt","r")) == NULL)
  printf("ERROR!!!");
 else {
  for(i=0;i<SIZE;i++)
   fscanf(fp,"%f\n",&(dd[i]));
 }  
 fclose(fp);
}

void delay_inputs(int i,float x[IN])
{
 int j;

 for(j=0;j<IN;j++)
  if((i-j-1) >= 0)
   x[j] = dd[i-j-1];
  else x[j] = 0;
}

float output(int i,float x[IN])
{
 float sum;
 int j;

 sum = 0.0;
 for(j=0;j<IN;j++)
  sum += w[j]*x[j];
 sum += b;

 return(sum);
}

void train()
{
 int i,k;
 float y; 
 float e;

 for(i=0;i<TRSIZE;i++) {

  /* compute output */ 
  delay_inputs(i,x);
  y = output(i,x); 

  /* compute error */
  e = dd[i] - y;

  /* update weights and bias */
  for(k=0;k<IN;k++) 
   w[k] += LR*e*x[k];
  b += LR*e; 
 }
}

void test()
{
 int i,j;
 float last_pred;

 /* first test: prediction day by day */
 for(i=2472;i<2500;i++) {
  delay_inputs(i,x);  
  printf("\n Dow[%d] = %f predicted = %f err=%f",i,dd[i],output(i,x),fabs(dd[i]-output(i,x)));
 }

 /* second test: long term prediction */
 for(i=0;i<IN;i++)
  x[i] = dd[2501-IN+i];
 printf("\n Dow[%d] = %f predicted = %f err=%f",2501,dd[2501],output(2501,x),fabs(dd[2501]-output(2501,x))); 

 last_pred = output(2501,x);

 for(i=2502;i<2528;i++) {
  for(j=1;j<IN;j++)
   x[j-1] = x[j]; 
  x[IN-1] = last_pred;
  last_pred = output(i,x); 
  printf("\n Dow[%d] = %f predicted = %f err=%f",i,dd[i],last_pred,fabs(dd[i]-last_pred));

 }

}

