Sunday, August 17, 2014

MACD fitness function for the GA

I have finished programming the MACD fitness function in C. This function takes in the 3 usual parameters for the MACD and returns the balance after the last sell. This function will be useful in implementing the genetic algorithm (GA).

In the following source code, macdbal() is this fitness function. The program works by filling in all the missing candles from the data downloaded by the dl2.sh script from an earlier post. It then calculates the Simple Moving Averages used to obtain the MACD. Based on the MACD, macdbal() "buys" (subtracts the closing ask price from the balance) and "sells" (adds the closing bid price to the balance).

 /*  
      MACD fitness function  
      Vicente Oscar Mier Vela  
      <vomv1988@gmail.com>  
   
      Use the output of "Oanda 5000 candle limit bypasser" script  
      as input for this program.  
   
      Example:  
           $ ./dl2.sh "Aug 3 21:00:00 GMT 2014" "Aug 8 21:00:00 GMT 2014" M1 > 5KOUT  
           $ cat 5KOUT | ./gen2 1407099600 1407531600 60 17 91 99  
   
      The output from above should be:  
           Success rate 29.411765%  
           Final balance: 0.001420  
   
      The first two arguments of gen2.c are the dates used for dl2.sh in UNIX time format.  
   
      For example, use:  
           $ date -d "Aug 3 21:00:00 GMT 2014" +%s  
   
      to obtain  
           1407099600  
 */  
   
 #include <stdio.h>  
 #include <stdlib.h>  
   
 #define closeBid 0  
 #define closeAsk 1  
   
 double macdbal(int emalow, int emahigh, int emasignal, double *closeask, double *closebid, int length);  
   
 int main(int argc, char *argv[]){  
      int startdate = atoi(argv[1]);  
      int enddate = atoi(argv[2]);  
      int timebase = atoi(argv[3]);  
   
      int emalow = atoi(argv[4]);  
      int emahigh = atoi(argv[5]);  
      int emasignal = atoi(argv[6]);  
   
      int nsamples = (enddate - startdate) / timebase;  
      int expdate;  
      int currdate;  
   
      double *samples[2];  
      samples[closeBid] = malloc(sizeof(double)*nsamples);  
      samples[closeAsk] = malloc(sizeof(double)*nsamples);  
   
      int i;  
      for(i = 0, expdate = startdate; i < nsamples; i ++, expdate += timebase){  
           scanf("%d", &currdate);  
 /*  
           The following assumes that the first date from the  
           dataset will always yield a value. That is: 1st date is  
           always "ticked".  
 */  
           if(currdate == expdate){  
                scanf("%lf", samples[closeBid] + i);  
                scanf("%lf", samples[closeAsk] + i);  
           } else {  
                while(currdate != expdate && i < nsamples){  
                     samples[closeBid][i] = samples[closeBid][i-1];  
                     samples[closeAsk][i] = samples[closeAsk][i-1];  
                     expdate += timebase;  
                     i++;  
                }  
                if(i < nsamples){  
                     scanf("%lf", samples[closeBid] + i);  
                     scanf("%lf", samples[closeAsk] + i);  
                }  
           }  
      }  
   
      double x = macdbal(  
                emalow, emahigh, emasignal,  
                samples[closeAsk], samples[closeBid],  
                nsamples  
      );  
   
      printf("Final balance: %f\n",x);  
   
      free(samples[closeBid]);  
      free(samples[closeAsk]);  
   
      return 0;  
 }  
   
 double macdbal(int emalow, int emahigh, int emasignal, double *closeask, double *closebid, int length){  
      int i;  
      double *emalows = malloc(sizeof(double)*length);  
      double *emahighs = malloc(sizeof(double)*length);  
      double *emasignals = malloc(sizeof(double)*length);  
   
      for(i = 0; i < length; i ++){  
           scanf("%lf", closebid + i);  
           emalows[i] = emahighs[i] = emasignals[i] = 0;  
      }  
   
      double sum;  
      for(i = 0, sum = 0; i < emalow; i ++){  
           emalows[i] = closebid[0];  
           sum += closebid[i];  
      }  
   
      emalows[emalow - 1] = sum / ((double) emalow);  
      double lowmult = 2.0 / (((double) emalow) + 1.0);  
      emalows[emalow] = (closebid[emalow] - emalows[emalow - 1]) * lowmult + emalows[emalow - 1];  
   
      for(i = emalow + 1; i < length; i ++)  
           emalows[i] = (closebid[i] - emalows[i - 1]) * lowmult + emalows[i - 1];  
   
      for(i = 0, sum = 0; i < emahigh; i ++){  
           emahighs[i] = closebid[0];  
           sum += closebid[i];  
      }  
      emahighs[emahigh - 1] = sum / ((double) emahigh);  
      double highmult = 2.0 / (((double) emahigh) + 1.0);  
      emahighs[emahigh] = (closebid[emahigh] - emahighs[emahigh - 1]) * highmult + emahighs[emahigh - 1];  
   
      for(i = emahigh + 1; i < length; i ++)  
           emahighs[i] = (closebid[i] - emahighs[i - 1]) * highmult + emahighs[i - 1];  
   
      int signalstart = emahigh * 2;  
      for(i = 0; i < signalstart + emasignal; i ++)  
           emasignals[i] = 0;  
   
      for(i = signalstart, sum = 0; i < signalstart + emasignal; i ++)  
           sum += emalows[i] - emahighs[i];  
      emasignals[signalstart + emasignal - 1] = sum / ((double) emasignal);  
      double signalmult = 2.0 / (((double) emasignal) + 1.0);  
      emasignals[signalstart + emasignal] =  
           (  
                (emalows[signalstart + emasignal] - emahighs[signalstart + emasignal]) -  
                emasignals[signalstart + emasignal - 1]  
           ) * signalmult + emasignals[signalstart + emasignal - 1]  
      ;  
   
      for(i = signalstart + emasignal + 1; i < length; i ++)  
           emasignals[i] =  
                ((emalows[i] - emahighs[i]) - emasignals[i - 1]) * signalmult + emasignals[i - 1]  
           ;  
   
      double last = 0;  
      double balance = 0;  
      double prevbal = 0;  
      double lastsell = 0;  
      double total = 0;  
      double success = 0;  
      for(i = signalstart + emasignal; i < length; i ++){  
           if(emasignals[i] > 0 && last < 0){  
                last = emasignals[i];  
                prevbal = balance;  
                balance -= closeask[i];  
           }  
           if(emasignals[i] < 0){  
                if(last == 0){  
 /* memo to myself: get ready to buy before starting this loop */  
                     last = emasignals[i];  
                }  
                if(last > 0){  
                     last = emasignals[i];  
                     prevbal = balance;  
                     balance += closebid[i];  
                     if(lastsell < balance)  
                          success ++;  
                     total ++;  
                     lastsell = balance;  
                }  
           }  
      }  
   
 /* remove this for genetic algorithm */  
   
      printf("Success rate %f%\n",100*(success/total));  
   
      free(emalows);  
      free(emahighs);  
      free(emasignals);  
   
 /* return balance after last sell */  
      if(last > 0)  
           return prevbal;  
      else  
           return balance;  
   
 }  

No comments:

Post a Comment