option.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "finance.h"
#define MAX_BUFFER (100)
#define ERR_BADVAL (1)
#define ERR_NOVAL (2)
#define ERR_BADTYPE (3)
void ParseCmdLine (int argc, char *argv[]);
double GetOptVal (char *arg, int n);
int GetOptType (char *arg);
void OptErr (int n, int errcode);
void ShowHelpMessage();
void ShowVars ();
double Stock, Strike, SD, Rate, Time;
int Type;
char variables[][25] = { "Stock price",
"Strike price",
"Standard deviation",
"Risk-free rate of return",
"Time to expiration",
"Option type" };
int main(int argc, char *argv[]) {
ParseCmdLine(argc, argv);
ShowVars();
printf("%-25s: %14.4f\n\n", "Price", OptionPrice(Stock, Strike,
SD, Rate,
Time, Type));
return EXIT_SUCCESS;
}
void ParseCmdLine(int argc, char *argv[]) {
int optFlags[6] = {0}, count = 0;
while ( argv[count] ) {
if ( !strncmp(argv[count], "-s", 2) ||
!strncmp(argv[count], "-S", 2) ) {
Stock = GetOptVal(argv[count], 0);
optFlags[0] = 1;
}
else if ( !strncmp(argv[count], "-x", 2) ||
!strncmp(argv[count], "-X", 2) ) {
Strike = GetOptVal(argv[count], 1);
optFlags[1] = 1;
}
else if ( !strncmp(argv[count], "-d", 2) ||
!strncmp(argv[count], "-D", 2) ) {
SD = GetOptVal(argv[count], 2);
optFlags[2] = 1;
}
else if ( !strncmp(argv[count], "-r", 2) ||
!strncmp(argv[count], "-R", 2) ) {
Rate = GetOptVal(argv[count], 3);
optFlags[3] = 1;
}
else if ( !strncmp(argv[count], "-t", 2) ||
!strncmp(argv[count], "-T", 2) ) {
Time = GetOptVal(argv[count], 4);
optFlags[4] = 1;
}
else if ( !strncmp(argv[count], "-o", 2) ||
!strncmp(argv[count], "-O", 2) ) {
Type = GetOptType(argv[count]);
optFlags[5] = 1;
}
else if ( !strncmp(argv[count], "-h", 2) ||
!strncmp(argv[count], "-H", 2) )
ShowHelpMessage();
count++;
}
for ( count = 0; count < 6; count++ )
if ( !optFlags[count] )
OptErr(count, ERR_NOVAL);
}
void OptErr(int n, int errcode) {
switch ( errcode ) {
case ERR_BADVAL:
fprintf(stderr, "Error: You did not specify a valid value for %s.\n",
variables[n]);
break;
case ERR_NOVAL:
fprintf(stderr, "Error: You did not specify a value for %s.\n",
variables[n]);
break;
case ERR_BADTYPE:
fprintf(stderr, "Error: You did not specify a valid type.\n");
break;
}
exit(EXIT_FAILURE);
}
double GetOptVal(char *arg, int n) {
char temp[MAX_BUFFER] = {0}, *endptr;
int count = 2;
double result;
while ( arg[count] && count < (MAX_BUFFER + 1) )
temp[count-2] = arg[count++];
result = strtod(temp, &endptr);
if ( endptr[0] )
OptErr(n, ERR_BADVAL);
return result;
}
int GetOptType(char *arg) {
char temp[MAX_BUFFER] = {0};
int count = 2;
while ( arg[count] && (count < (MAX_BUFFER + 1)) ) {
temp[count-2] = toupper(arg[count]);
++count;
}
if ( !strncmp(temp, "CALL", 4) )
return EUROPEAN_CALL;
else if ( !strncmp(temp, "PUT", 3) )
return EUROPEAN_PUT;
else
OptErr(0, ERR_BADTYPE);
}
void ShowHelpMessage() {
printf("\nOption Price Calculator\n");
printf("=======================\n");
printf("(c) Paul Griffiths 1999\n\n");
printf("Usage:\n");
printf(" option -s{n} -x{n} -d{n} -r{n} -t{n} -o{call,put} [-h]\n\n");
printf("Switches:\n");
printf(" -s | -S : Price of underlying stock\n");
printf(" -x | -X : Strike/Exercise price of option\n");
printf(" -d | -D : Standard deviation of price of\n");
printf(" underlying stock per time period,\n");
printf(" expressed as a decimal percentage\n");
printf(" -r | -R : Risk-free rate of return per time period,\n");
printf(" expressed as a decimal percentage\n");
printf(" -t | -T : Number of time periods to expiration\n");
printf(" -o | -O : Type of option, can be \"call\" or \"put\"\n");
printf(" -h | -H : Show this help message\n\n");
printf("Example:\n");
printf(" For a call option on a stock with a price of $42, which\n");
printf(" has a standard deviation of 20%% per year, when the\n");
printf(" risk-free rate of return is 10%% per year, the strike\n");
printf(" price is $40, and the option has six months to expiration,\n");
printf(" use:\n\n");
printf(" option -s42 -x40 -s0.2 -r0.1 -t0.5 -ocall\n\n");
exit(EXIT_SUCCESS);
}
void ShowVars() {
printf("\nOption Price Calculator\n");
printf("=======================\n\n");
printf("%-25s: %14.4f\n", variables[0], Stock);
printf("%-25s: %14.4f\n", variables[1], Strike);
printf("%-25s: %14.4f\n", variables[2], SD);
printf("%-25s: %14.4f\n", variables[3], Rate);
printf("%-25s: %14.4f\n", variables[4], Time);
printf("%-25s: %14s\n\n", variables[5],
(Type == EUROPEAN_CALL) ? "European call" : "European put");
}
finance.h
#ifndef PG_FINANCE_H
#define PG_FINANCE_H
#define EUROPEAN_CALL 1
#define EUROPEAN_PUT 2
#define AMERICAN_CALL 3
#define AMERICAN_PUT 4
#define OPTERROR_TYPE 1
double OptionPrice(double Stock, double Strike, double SD,
double Rate, double Time, int Type);
double CND(double n);
double D(double Stock, double Strike, double SD,
double Rate, double Time, int Flag);
#endif
finance.c
#include "finance.h"
#include <math.h>
double OptionPrice(double Stock, double Strike, double SD,
double Rate, double Time, int Type) {
switch ( Type ) {
case EUROPEAN_CALL:
case AMERICAN_CALL:
return Stock * CND(D(Stock, Strike, SD, Rate, Time, 1)) -
Strike * exp(-Rate * Time) *
CND(D(Stock, Strike, SD, Rate, Time, 2));
case EUROPEAN_PUT:
case AMERICAN_PUT:
return Strike * exp(-Rate * Time) *
CND(-D(Stock, Strike, SD, Rate, Time, 2)) -
Stock * CND(-D(Stock, Strike, SD, Rate, Time, 1));
default:
return OPTERROR_TYPE;
}
}
double CND(double x) {
int i;
double a[5] = { 0.319381530, -0.356563782, 1.781477937,
-1.821255978, 1.330274429 };
double result = 0, k = 1 / (1 + 0.2316419 * fabs(x));
for ( i = 0; i < 5; i++ ) result += a[i] * pow(k, i+1);
result = 1 - result * 1/sqrt(2*3.141592654) * exp(-(x*x)/2);
if ( x >= 0 ) return result;
else return (1 - result);
}
double D(double Stock, double Strike, double SD,
double Rate, double Time, int Flag) {
double result;
if ( Flag == 1 )
result = Rate + (SD*SD)/2;
else if ( Flag == 2 )
result = Rate - (SD*SD)/2;
else
return 0;
return (log(Stock/Strike) + result*Time) / (SD*sqrt(Time));
}
Please send all comments, suggestions, bug reports etc to mail@paulgriffiths.net