/*
  summary.c
  Summarize GLOBEX Futures Market data
  (C) Copyright 2008 Eric Shalov. All Rights Reserved.
  
  Trading days:
  3pm-4pm closing Monday
  5pm-4pm closing Tue-Fri
*/

#include <stdio.h>
#include <time.h>
#include <string.h>

char data_filename[] = "6E.dat";
char output_filename[] = "6E.summary";

struct day_data {
  long date;
  long start_time,end_time;
  time_t start_time_t, end_time_t;
  float open,high,low,close;
  long volume;
  long largest_trade;
  long num_trades;
};

int num_days = 0;
struct day_data day[1000];

int main() {
  FILE *f, *of;
  long date,time,trading_date;
  float price;
  long size;
  long trade = 0;
  int i, index;

  struct tm start_of_trading_day_tm;
  time_t start_of_trading_day_t;

  struct tm trade_tm;
  time_t trade_t, t;
  
  struct tm *tm_calculated;
  

  if( ! (of=fopen(output_filename,"w"))) {
    fprintf(stderr,"Error opening `%s'.\n", output_filename);
    return 1;
  }
  
  if( (f=fopen(data_filename,"r"))) {
    while( fscanf(f,"%ld %ld;%f;%ld", &date, &time, &price, &size) != EOF && (trade < 100000000)) {
      ++trade;
      if((trade%100000)==0) printf("Trade %ld: %08ld, %06ld, %6.4f, %8ld\n",
        trade, date, time, price, size);

      /* Okay, there's holidays with varient schedules and other fucked-up shit,
         but this seems to be our consistantly safe rule about CME schedules:
         
           If a given trade occurs on a Mon-Fri, AFTER 5pm,
           or on a Sunday AFTER 3pm, it's attributed to THE NEXT day,
           otherwise it is attributed to THAT day.
         
         ALL trades on Sunday are attributed to Sunday.
      */
      if(0) printf("\nDate: %08ld, Time=%06ld\n", date, time);
      /* Check if trade occured on a Sunday or on AFTER 5pm Mon-Fri Chicago time,
         and if it DID, attribute the trade's effective trading date to the NEXT day */
      trade_tm.tm_sec = time % 100;
      trade_tm.tm_min = (time / 100) % 100;
      trade_tm.tm_hour = (time / 10000);
      trade_tm.tm_mday = date % 100;
      trade_tm.tm_mon = ((date % 10000) / 100) - 1; /* months since January [0-11] */
      trade_tm.tm_year = (date / 10000) - 1900; /* years since 1900 */
      trade_tm.tm_zone = NULL;
      if(0) printf("trade_tm: sec=%d, min=%d, hour=%d, mday=%d, mon=%d, year=%d\n",
        trade_tm.tm_sec, trade_tm.tm_min, trade_tm.tm_hour, trade_tm.tm_mday, trade_tm.tm_mon, trade_tm.tm_year);
      trade_t = mktime(&trade_tm);
      tm_calculated = localtime(&trade_t);

      /* if it's a Sunday or it's after 5pm, change the trading date to the next day */
      if((tm_calculated->tm_wday == 0) || (time >= 170000)) {
        if(0) printf("%08ld %06ld: Trade occured on Sunday or after 5pm, trade is for tomorrow's trading day.\n",
          date,time);
          
        t = trade_t + 60*60*24; /* Step forward one day */
        tm_calculated = localtime(&t);
        trading_date = (tm_calculated->tm_year+1900)*10000 + (tm_calculated->tm_mon+1)*100 + tm_calculated->tm_mday;
      } else {
        trading_date = date;
      }

      if(0) printf("Trading_date: %08ld\n", trading_date);
      /* Determine the start of the trading day on which this trade occured-

        The start is always the day before the closing "trading day" */
      
      /* if the trade is after 5pm (or 3pm on Sundays), trading started
         the PREVIOUS day, otherwise it started on THAT day */
      start_of_trading_day_tm.tm_hour = 00;
      start_of_trading_day_tm.tm_min =  00;
      start_of_trading_day_tm.tm_sec =  00;
      start_of_trading_day_tm.tm_mday = trading_date % 100;
      start_of_trading_day_tm.tm_mon =  ((trading_date % 10000) / 100) - 1; /* months since January [0-11] */
      start_of_trading_day_tm.tm_year = (trading_date / 10000) - 1900; /* years since 1900 */
      start_of_trading_day_tm.tm_zone = NULL;
      start_of_trading_day_t = mktime(&start_of_trading_day_tm) - 60*60*24;
      tm_calculated = localtime(&start_of_trading_day_t);
      /* If the "trading day" (when it ends) is Monday, then start of
         trading time is 3pm (Sunday), otherwise it's 5pm */
      if(tm_calculated->tm_wday == 1) {
        start_of_trading_day_tm.tm_hour = 15;
        start_of_trading_day_tm.tm_min =  00;
        start_of_trading_day_tm.tm_sec =  00;
      } else {
        start_of_trading_day_tm.tm_hour = 17;
        start_of_trading_day_tm.tm_min =  00;
        start_of_trading_day_tm.tm_sec =  00;
      }
      start_of_trading_day_tm.tm_mday = tm_calculated->tm_mday;
      start_of_trading_day_tm.tm_mon =  tm_calculated->tm_mon;
      start_of_trading_day_tm.tm_year = tm_calculated->tm_year;
      if(0) printf("start_of_trading_day_tm: sec=%d, min=%d, hour=%d, mday=%d, mon=%d, year=%d\n",
        start_of_trading_day_tm.tm_sec, start_of_trading_day_tm.tm_min, start_of_trading_day_tm.tm_hour, start_of_trading_day_tm.tm_mday, start_of_trading_day_tm.tm_mon, start_of_trading_day_tm.tm_year);
      start_of_trading_day_t = mktime(&start_of_trading_day_tm);
         
      if(0) printf("Date: %08ld, Time: %06ld, Seconds into trading day: %ld\n",
        date, time, trade_t-start_of_trading_day_t);



      /* see if we're already tracking that day, check backwards */
      index = -1;
      for(i=num_days-1;(i>=0) && (index==-1);i--)
        if(day[i].date == trading_date) index=i;

      if(index != -1) {    
        ++day[index].num_trades;
        day[index].volume += size;
          
        if(price < day[index].low) day[index].low = price;
        if(price > day[index].high) day[index].high = price;
        if(size > day[index].largest_trade) day[index].largest_trade = size;

        if(trade_t < day[i].start_time_t) {
          day[index].start_time_t = trade_t;
          day[index].start_time = time;
          day[index].open = price;
        }
        
        if(trade_t > day[i].end_time_t) {
          day[index].start_time_t = trade_t;
          day[index].end_time = time;
          day[index].close = price;
        }
      } else {
        /* Add new date */
        day[num_days].date = trading_date;
        day[num_days].start_time = time;
        day[num_days].end_time = time;
        day[num_days].start_time_t = trade_t;
        day[num_days].end_time_t = trade_t;
        day[num_days].open = price;
        day[num_days].high = price;
        day[num_days].low = price;
        day[num_days].close = price;
        day[num_days].volume = size;
        day[num_days].largest_trade = size;
        day[num_days].num_trades = 1;
        ++num_days;
      }
    }
  } else {
    fprintf(stderr,"Error opening `%s'.\n", data_filename);
    return 1;
  }

  printf("Analyzed %ld trades over %d trading days.\n", trade, num_days);
  for(i=0;i<num_days;i++) {
    printf("Day %d: date=%08ld, start_time=%06ld, end_time=%06ld, open=%6.4f, high=%6.4f, low=%6.4f, close=%6.4f, volume=%ld, largest_trade=%ld\n",
      i+1,
      day[i].date,
      day[i].start_time, day[i].end_time,
      day[i].open, day[i].high, day[i].low, day[i].close,
      day[i].volume, day[i].largest_trade);

    fprintf(of,"%08ld %06ld %06ld %6.4f %6.4f %6.4f %6.4f %10ld %10ld %10ld\n",
      day[i].date,
      day[i].start_time, day[i].end_time,
      day[i].open, day[i].high, day[i].low, day[i].close,
      day[i].volume, day[i].largest_trade, day[i].num_trades);
  }

  fclose(f);
  fclose(of);
  
  return 0;
}

