Step 1 - Defining the Core Model:

First off, we have the model's sets section.  Unlike the previous gas-buying model, which was entirely scalar, we will make use of LINGO's set-based modeling capabilities in this example.  Any set-based model will have at least one sets section, and for the core model for this example we have the following:

SETS:

  PERIODS: !six periods (1 initial and 5 recourse);

   RETURN,        !return of underlying stock, a r.v.;

   PRICE,         !current price of underlying stock;

   SELL,          ! = 1 if option exercised in period;

   WLTH,          !wealth in period from exercise of option;

   SAMP_SZ;       !sample size;

ENDSETS

Sets Section

As mentioned, this is a six-period (one initial and five recourse) model.  Across the six periods, we have the following attributes:

RETURN - the stock's return (fractional price change), a random variable,
PRICE - the current price of the stock (a function of the RETURN),
SELL - a recourse variable indicating the fraction of the option position sold,
WLTH - wealth in the current period consisting of the wealth from the previous period multiplied by the risk free rate plus any proceeds from exercising all, or part, of the option, and
SAMP_SZ - the sample sizes used for sampling the distribution for RETURN.

Next we have the data section containing the parameters we mentioned above, consisting of the stock's initial price, the option's strike price and the risk free rate for discounting:

DATA:

  PERIODS = P0..P5;     !names for the periods;

  INIT_PRICE = 100;     !initial underlying stock price;

  STRIKE_PRICE = 99;    !option strike price;

  RISK_FREE_RATE = .03; !risk free rate for discounting;

ENDDATA

Data Section

Next, we have the core model.  You will recall that the core model is the model we would construct if the random variables were know with certainty.

! Core Model -------------------------------------------+;

 

NP = @SIZE( PERIODS); ! Number of periods;

 

! Maximize the present value of the option in period 0;

[R_OBJ] MAX = WLTH( NP)/( 1 + RISK_FREE_RATE) ^ ( NP - 1);

 

! Compute stock's price in each period;

[R_PRICE_INIT] PRICE( 1) = INIT_PRICE;

@FOR( PERIODS( P) | P #GT# 1:

[R_PRICE] PRICE( P) = PRICE( P - 1) * ( 1 + RETURN( P));

 );

 

! Calculate our compounded wealth in each period;

[R_PV_1] WLTH( 1) =

SELL( 1) *

 ( STRIKE_PRICE - PRICE( 1));

 

@FOR( PERIODS( P) | P #GT# 1:

[R_PV] WLTH( P) = SELL( P) * ( STRIKE_PRICE - PRICE( P)) +

 WLTH( P - 1) * ( 1 + RISK_FREE_RATE);

  );

 

! Can't sell more than we have;

[R_SELL_EQ_1] @SUM( PERIODS( P): SELL( P)) <= 1;

 

! Random variables not allowed in initial period;

[R_RETURN_P0] RETURN( 1) = 0;

Core Model for Stock Option Example

As mentioned, our objective is to maximize the present value of the option in the initial period, which will tell us the maximum we should be willing to pay for the option.  To compute the present value in period 0, we discount wealth in the final period back to the initial period using the risk-free rate:

! Maximize the present value of the option in period 0;

[R_OBJ] MAX = WLTH( NP)/( 1 + RISK_FREE_RATE) ^ ( NP - 1);

where NP is the number of periods, calculated using the @SIZE function:

NP = @SIZE( PERIODS); ! Number of periods;

Technically, NP is actually equal to the number of periods plus 1, due to P0 being part of the PERIODS set.  So, when we discount wealth, we discount by NP - 1 periods as opposed to NP periods.

In the next section of the core model we compute wealth in each period:

! Calculate our compounded wealth in each period;

[R_PV_1] WLTH( 1) =

SELL( 1) *

 ( STRIKE_PRICE - PRICE( 1));

 

@FOR( PERIODS( P) | P #GT# 1:

[R_PV] WLTH( P) = SELL( P) * ( STRIKE_PRICE - PRICE( P)) +

 WLTH( P - 1) * ( 1 + RISK_FREE_RATE);

  );

Wealth can potentially come from two sources: sale of the option and/or carryover wealth from the previous period.  In the first period, carryover wealth is not possible, so period 1 is handled as a special case with sale of the option being the only source of wealth.  Subsequent periods' wealth are then computed in an @FOR loop and include both sales and carryover sources of wealth.  Revenue from sales is computed as: SELLp * ( STRIKE_PRICE - PRICEp). Note, that the SELL variable may be fractional if we choose to sell less than the full position on a period.  Carryover wealth is computed  as: WLTHp-1  *  ( 1 + RISK_FREE_RATE), where we multiply by the risk free rate to account for interest payments on wealth.

Clearly, we can't sell more of full option position, so the sum of the SELL attribute across all periods cannot exceed 1:

! Can't sell more than we have;

[R_SELL_EQ_1] @SUM( PERIODS( P): SELL( P)) <= 1;

Finally, there can be no return in period 0, so we set RETURN to 0 in the initial period:

! Random variables not allowed in initial period;

[R_RETURN_P0] RETURN( @INDEX( P0)) = 0;

In the next section, we will cover the final part of the model listing the stochastic properties.