/* * prem.c - calculate premium of S&P futures to SPX spot index * * written by: Gary Funck, Intrepid Technology (gary@intrepid.com) * * COPYRIGHT: Gary Funck, Intrepid Technolory, Inc., 1995 * * USAGE: prem * * DISCLARIMER: no warranty claimed or implied. Use at your own risk. * All rights of use are granted as long as proper credit is given. * */ #include #include #include #include #ifndef TRUE #define FALSE 0 #define TRUE 1 #endif #ifndef NULL #define NULL 0 #endif #define max(x,y) ((x) > (y) ? (x) : (y)) #define min(x,y) ((x) < (y) ? (x) : (y)) /* risk free interest rate, use T-BILL rate ($IRX) */ /* double i_rate = 0.0571; */ double i_rate = 0.0592; /* S&P 500 dividend rate */ double div_rate = 0.0251; /* commission costs in SPX points (estimated) */ double commish = 0.50; /* slippage cost in SPX points (estimated) */ double slippage = 0.65; /* program name taken from command line */ char *pgm_name; /* SPX spot value taken from the command line */ char *spx_image; /* SPX cash index - taken from command line */ double spx_spot; /* today's date, encoded as an integer */ int now; int jday(d,m,y) /* Julian day from day, month, year */ int d,m,y; /* valid for any date. */ { int c, ya, j; if (m > 2) m -= 3; else { m += 9; --y; } c = y / 100; ya = y - 100 * c; j = (146097 * c) / 4 + (1461 * ya) / 4 + (153 * m + 2) / 5 + d + 1721119; return j; } void jdate(j,d,m,y) /* day, month, year from Julian day */ int j; /* astronomically correct. */ int *d, *m, *y; /* valid for any date. */ { j -= 1721119; *y = (4 * j - 1) / 146097; j = 4 * j - 1 - 146097 * *y; *d = j / 4; j = (4 * *d + 3) / 1461; *d = 4 * *d + 3 - 1461 * j; *d = (*d + 4) / 4; *m = ( 5 * *d - 3) / 153; *d = 5 * *d - 3 - 153 * *m; *d = (*d + 5) / 5; *y = 100 * *y + j; if (*m < 10) *m += 3; else { *m -= 9; (*y)++; } } int datevalue(d, m, ya) /* Converts calendar date, Gregorian Calendar */ int d, m, ya; /* to corresponding serial day number */ { /* valid from 1 March 1900 (k = 1) to 31 Dec 1999 */ /* (k = 36465), to obtain Julian day number (valid */ /* at noon) add 2415079 to k */ int k; if ( m > 2 ) m -= 3; else { m += 9; ya--; } k = (1461 * ya) / 4 + (153 * m + 2) / 5 + d; return k; } int weekday(k) /* converts serial day to day of week */ int k; /* where 0 = Sunday */ { return (k + 1) % 7; } void kdate(k, d, m, ya) /* Converts serial day number to the corresponding */ int k; /* calendar date, Gregorian calendar, valid for */ int *d, *m, *ya; /* k = 1 (1 March 1900) to k = 36465 (31 Dec 1999) */ { *ya = (4 * k - 1) / 1461; *d = 4 * k - 1 - 1461 * *ya; *d = (*d + 4) / 4; *m = (5 * *d - 3) / 153; *d = (5 * *d - 3) - 153 * *m; *d = (*d + 5) / 5; if ( *m < 10 ) *m += 3; else { *m -= 9; *ya += 1; } } int kmonth(k) { int m, d, y; kdate(k, &d, &m, &y); return m; } int kday(k) { int m, d, y; kdate(k, &d, &m, &y); return d; } int kyear(k) { int m, d, y; kdate(k, &d, &m, &y); return y; } int today() { static int this_day = 0; time_t now_t; struct tm *t; if (this_day == 0) { now_t = time(0); t = localtime(&now_t); this_day = datevalue(t->tm_mday, t->tm_mon+1, t->tm_year+1900); } return this_day; } char * month_abbrev(m) int m; { static char *m_abbrev[12] = {"Jan","Feb","Mar","Apr","May","Jun", "Jul","Aug","Sep","Oct","Nov","Dec" }; return m_abbrev[m-1]; } /* * third_friday - given a month, year return the 3rd Friday. */ int third_friday(m, y) int m; int y; { int mm_01_yy = datevalue(1, m, y); return mm_01_yy + (12 - weekday(mm_01_yy)) % 7 + 15; } /* * front_month - return the next month that SPX futures expire */ int front_month() { int m; m = kmonth(now); /* find next month that is a multiple of 3 */ m = (m + 2) / 3 * 3; return m; } void calc_fair_value(expire_date, fair_value, prem_value, prem_buy, prem_sell) int expire_date; double *fair_value; double *prem_value; double *prem_buy; double *prem_sell; { int days_til_expire; double t_expire; double int_expense; double div_income; days_til_expire = max(expire_date - now, 1); t_expire = days_til_expire / 365.0; int_expense = spx_spot * (pow(1.0 + i_rate, t_expire) - 1.0); div_income = spx_spot * (pow(1.0 + div_rate, t_expire) - 1.0); *prem_value = int_expense - div_income; *fair_value = spx_spot + *prem_value; *prem_buy = *prem_value + commish + slippage; *prem_sell = *prem_value - slippage; } main(argc, argv) int argc; char *argv[]; { int nf; int front_expire_month; int front_expire_year; int front_expire_date; double front_fair_value; double front_prem_value; double front_prem_buy; double front_prem_sell; int back_expire_month; int back_expire_year; int back_expire_date; double back_fair_value; double back_prem_value; double back_prem_buy; double back_prem_sell; double spread_value; pgm_name = argv[0]; /* don't count arg 0 */ argc = argc - 1; if (argc == 1) { spx_image = argv[1]; nf = sscanf(spx_image, "%lf", &spx_spot); if (nf != 1 || spx_spot < 100.00 || spx_spot > 1000.0) { fprintf(stderr, "invalid SPX spot value: %s\n", spx_image); exit(2); } } else { fprintf(stderr, "%s: expected single arg with SPX spot value\n", pgm_name); fprintf(stderr, "usage: %s \n", pgm_name); exit(1); } now = today(); front_expire_month = front_month(); front_expire_year = kyear(now); front_expire_date = third_friday(front_expire_month, front_expire_year); if (front_expire_date <= now) { if (front_expire_month < 12 ) { front_expire_month = front_expire_month + 3; front_expire_year = front_expire_year; } else { front_expire_month = 3; front_expire_year = front_expire_year + 1; } front_expire_date = third_friday(front_expire_month, front_expire_year); } calc_fair_value(front_expire_date, &front_fair_value, &front_prem_value, &front_prem_buy, &front_prem_sell); if (front_expire_month < 12 ) { back_expire_month = front_expire_month + 3; back_expire_year = front_expire_year; } else { back_expire_month = 3; back_expire_year = front_expire_year + 1; } back_expire_date = third_friday(back_expire_month, back_expire_year); calc_fair_value(back_expire_date, &back_fair_value, &back_prem_value, &back_prem_buy, &back_prem_sell); spread_value = back_prem_value - front_prem_value; printf("\n"); printf("Front Month (%s)\n", month_abbrev(front_expire_month)); printf("-----------------\n"); printf("\n"); printf(" fair value: %8.2f\n", front_fair_value); printf(" prem: %8.2f\n", front_prem_value); printf(" buy limit: %8.2f\n", front_prem_buy); printf(" sell limit: %8.2f\n", front_prem_sell); printf("\n"); printf("Back Month (%s)\n", month_abbrev(back_expire_month)); printf("----------------\n"); printf("\n"); printf(" fair value: %8.2f\n", back_fair_value); printf(" prem: %8.2f\n", back_prem_value); printf(" buy limit: %8.2f\n", back_prem_buy); printf(" sell limit: %8.2f\n", back_prem_sell); printf("\n"); printf(" spread: %8.2f\n", spread_value); printf("\n"); exit(0); }