Assembly code – Exotic option simulation

THIS PROGRAM SIMULATES THE BEHAVIOR OF AN EXOTIC OPTION.

THE PROGRAM ASKS THE USER WHETHER HE PREFERS TO BUY A PUT OR A CALL. SUBSEQUENTLY, IT PRICES THE DERIVATIVE VIA MONTECARLO. A SIMULATED UNDERLYING ASSET TRAJECTORY IS COMPUTED AND SHOWN THE USER. A PAYOFF IS CALCULATED AND THE USER IS FINALLY INFORMED OF THE OUTCOME OF HIS BET.

This is a project of a certain size that replicates, in Assembly code, some of the concepts studied in the Master’s Degree in Quantitative Finance. I created it in order to become more familiar with low-level programming.

To contain the complexity of the project, some mathematical and financial simplifications have been introduced. In particular, a Geometric Brownian Motion is used, while more appropriate models like Black-Scholes would be used in practice. The properties of the Gaussian distribution are also simplified, assuming daily variance, and the method of calculating the final price is simplified.

The code is deposited at https://github.com/giosds/giasm

The 8088 interpreter was used for development, Assembler and Tracer Toolkit: https://github.com/StoDevX/as88

Più sotto, in lingua inglese, è riportata la documentazione presente all’interno del codice.

ChatGPT

Here is the English documentation for the code:

Main Features:

  • Generation of pseudorandom numbers, with a different sequence in each execution.
  • Pricing of a double-barrier option using Monte Carlo simulation.
  • Animated graphical representation of the Monte Carlo method.
  • Generation of the random path of a hypothetical underlying asset and communication of the profit (or loss) generated by a derivative contract to the user.
  • Text-based console graphics.
  • Numerous limitations due to the architecture used, including the inability to perform floating-point arithmetic (only integer), 16-bit registers, and only 7 available system-library calls.
  • Each element of the program is parameterized. For computational or other reasons (e.g., making certain components absolute or relative to each other), financial parameters undergo some manipulations in some cases, which the algorithm handles.

 

The first file calls the necessary functions, which are located in other linked files.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
<pre>#include "consts.h"    !
#include "usrPrms.h"    !

!   THIS PROGRAM SIMULATES THE BEHAVIOR OF AN EXOTIC OPTION.

!   -----------------------------------------------------------------
!   PROGRAM:
!   THE PROGRAM ASKS THE USER WHETHER HE PREFERS TO BUY A PUT OR A CALL.
!   SUBSEQUENTLY, IT PRICES THE DERIVATIVE VIA MONTECARLO. 
!   A SIMULATED UNDERLYING ASSET TRAJECTORY IS COMPUTED AND SHOWN THE USER.
!   A PAYOFF IS CALCULATED AND THE USER IS FINALLY INFORMED OF THE OUTCOME OF HIS BET.

!   -----------------------------------------------------------------
!   OPTION BEHAVIOR:
!   THE OPTION PAYS THE DIFFERENCE BETWEEN THE UNDERLYING ASSET
!   AND THE STRIKE IF IT IS IN THE MONEY, ZERO OTHERWISE.
!   THERE ARE TWO KNOCK-OUT BARRIERS, A CAP AND A FLOOR: IF THE ASSET
!   REACHES A BARRIER, THE PRICE IS FIXED UNTIL EXPIRATION.

!   -----------------------------------------------------------------
!   PROGRAM DESCRIPTION:
!   Whenever possible, multiplications are done before divisions, in order
!       to contain remainder approximations.
!
!   The user helps generating 3 initial numbers by keeping the Enter key pressed
!       for a while (too small a time is not allowed).
!   The lowest binary digits of those initial numbers form the basis for new numbers.
!   Three different combinations of those basis are assembled to form 3 different numbers,
!       which   are less predictable than the original ones.
!   These new numbers are 3 random seeds for 3 Linear Congruential Generators.
!   Three sequences are thus generated: they contain uniform pseudo-random variables.
!   The 3 sequences interact to generate one longer-period sequence (still uniforms).
!       This one is used as a source of randomness for all the simulations.
!   Next: 48 uniform variables are used at a time to yeld an approximated gaussian-distributed
!       random variable, relying on the Central Limit theorem.
!       The number 48 is a convenient number, it being: 2 squared, times 12.
!       Still, it produces better gaussians than 12.
!       12 is related to the uniform distribution standard deviation; 4 saves us a square-root computation,
!       which   would complicate matters in an environment where floating-point arithmetic is not available.
!   The gaussian variable is appropriately standardized and scaled (the values must fit in the registers)
!       and used to form a Geometric Brownian Motion for the prices of the asset.
!   Then barriers are applied, limiting the asset prices.
!   A payoff is computed, relative to a strike price.
!   Using Montecarlo, many payoffs are averaged and discounted to price the derivative.
!   Some of the asset trajectories are shown in an animated plot, in the text-based console.
!   Prices are scaled and matched to a row number. If the columns allowed are fewer than
!       the whole trajectory, the plot is split into as many parts as needed.
!       The trajectory is rescaled for every example, so that each time the maximum and
!       minimum values are placed on the upper and lower rows of the plot.
!   The strike price is shown as a heavy line: ======

!   -----------------------------------------------------------------
!   PARAMETERS FOR THE PROGRAM
!  
!   USER MODIFIABLE PARAMETERS [usrPrms.h] file:
!   The first section of the file contains the parameters that determine the
!   asset trajectory in time and the behavior of the derivative. The user can modify them.
!   _days: the number of days the simulation will cover. E.g. Tn = 252
!   _startPr: price of the asset in T0. It is also the basis for other transformations.
!                   20000 performs better in divisions (smaller remainders), 10000 is nicer
!   _bpDrift: drift of the asset, expressed in basis points, relative to the prices of the GBM
!   _bpReqStd: the standard deviation which the simulator is required to generate for the asset
!   _put: whether the option is a put or a call
!   _strike: the strike price
!   _cap: the upper barrier
!   _floor: the lower barrier
!
!   DEBUG AND PROGRAM:
!   Parameters used for debugging and fine-tuning the program.
!   _nRows, _nCols: rows and columns to display the plot.
! _dbgSd1, _dbgSd2, _dbgSd3: random seeds used to bypass the user-generation section.
!
!   CONSTANTS [consts.h] file:
!   This file should need no modifications.
!   It is worth mentioning the LOOPS part. Two variables are used to overcome the 16-bit constraint
!   on the CX register.
!   _hMcCount * _lMcCount is the number of trajectories Montecarlo runs on.
!   NOP1 * NOP2 is the number of cycles the program skips between the demonstrative plots.

!   =================================================================
!   This file, [main.s], contains the main part of the program:
!       - Computes some useful math initializations
!       - If the debug flag is on, assigns values and skip parts
!       Otherwise:
!       - Requires the user to generate 3 numbers as time spans
!       - Assembles the numbers into seeds
!               the seeds are used to initialize the random sequences
!               every sequence generation updates the seeds with the last generated element
!       - Runs Montecarlo and stores the payoff
!           Also plots the first MAXMCPLT sequences, inserting NOPs to let the user see them
!       - Computes one last trajetory and plots it

!   -----------------------------------------------------------------
! ASSEMBLE AS:
!   ./as88 main prFuncs series genrand vars mtCarlo prTraj
! GOOD VALUES: _days:252, rows 30, cols 100


.SECT .TEXT        
   
! PERFORM SOME INITIALIZATIONS
    CALL initVars  
! CHECK DEBUG
    JMP dbgChk1 ! If debug flag is on, set some values and jump to dbg1
    noDbg1:
! INFORM THE USER ABOUT THE PARAMETERS
    CALL prInfo1
    CALL pause
   
! ASK THE USER WHETHER PUT OR CALL
    CALL askPut
    CALL pause
    CALL pause
   




! ASK USER TO GENERATE SEED COMPONENTS

    CALL get3nums                                   !   User generates 3 ints pressing Enter for some time (genrand.s)
   
! BUILD SEEDS
    CALL getSeeds                                   !   User ints are converted into better numbers, usable as seeds (genrand.s):
                                                                    !           user numbers are shifted to keep 3 modulo values, used as
                                                                    !           bases of different order. They are switched in 3 combinations
                                                                    !           to get 3 different seeds.

! RUN A MONTECARLO EXPERIMENT  
dbg1:
    PUSH (hMcCount)                             !   Higherpart of the counter Should not overflow 3*32000
    PUSH (lMcCount)                             !   Lower part of the counter
    CALL runMc                                          !   Generates one complete Geometric Brownian price trajectory
                                                                    !       Also plots the first trajectories (mtCarlo.s)
    ADD SP,4
    MOV AX, (mcPayOff)
    CALL dscnt
    MOV (dscPayOff), AX

! INFORM THE USER ABOUT THE COST
    CALL prInfo2
    CALL pause

! RUN AND PRINT ONE TRAJECTORY
    !CALL runEpr                                        ! Runs a single trajectory and prints the sequences values (mtCarlo.s)
    CALL trjctry
    CALL prInfo3
    CALL pr4Seq                                     !   THE LAST RUN OF UNIFORM SEQUENCES
                                                                    !   genfuncs.
    CALL pause
    CALL prInfo4
    CALL prGaSeq                                    !   GAUSSIANS
                                                                    !   genfuncs.s
    CALL pause
    CALL prInfo5
    CALL prGmb                                      ! BROWNIAN MOTION
                                                                    !   genfuncs.s
    CALL pause
    CALL prInfo6
    CALL pause
! PLOT ONE TRAJECTORY
    CALL fullPlot                                       ! Plots the trajectory calculated above
    CALL pause
   
! TELL THE USER THE OUTCOME
    CALL payOff
    CALL tellOutc
    CALL pause
   
    PUSH _EXIT     
    PUSH _EXIT     
    SYS        
   
   
!   -----------------------------------------------------------------
!   DEBUG

dbgChk1:
    CMP (debug), TRUE                               ! Jump if not debugging. Next lines bypass inputs
    JNE noDbg1
    MOV (seed1), _dbgSd1
    MOV (seed2), _dbgSd2
    MOV (seed3), _dbgSd3       
    JMP dbg1</pre>

RANDOMNESS GENERATION

The limitations of the interpreter do not allow access to the system timer or other sources of randomness, so interaction with the user is used.

  • The user is asked to hold down the Enter key for a certain amount of time and then press a different key. This generates and counts a certain number of characters (‘\n’); to make the interaction more realistic, too short a press resets the count. Of course, it would be possible to count individual Enter key presses, but this is not a cryptographic application…
  • Three numbers are generated as described above. The lower 4 bits (corresponding to MOD 16, less manageable by the user) are retained for each of the 3 numbers. They are then recombined in various possible combinations to recreate 3 new 12-bit numbers, independent of the duration of the Enter key presses. These are the seeds that feed the random number generation algorithm.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
<pre>! THIS MODULE GENERATES RANDOMNESS
! The getnum function returns a random value
! Prints messages. User is asked to press key in order
! to generate one component of a random seed.
! Returns seed in AX

.SECT .TEXT    
           
!   -----------------------------------------------------------------
! BUILD SEEDS
! Builds 3 random seeds using the 3 components
! Seeds vary between [0, 4367]
getSeeds:                      
                                       
    PUSH BP
    MOV  BP,SP                                         
       
    PUSH (chaos1)                                   ! Compute seed 1
    PUSH (chaos2)
    PUSH (chaos3)
    CALL getSeed
    MOV (seed1), AX                             ! Store seed1 in memory
   
    PUSH (chaos3)                                   ! Compute seed 2
    PUSH (chaos1)
    PUSH (chaos2)
    CALL getSeed
    MOV (seed2), AX                             ! Store seed2 in memory
   
    PUSH (chaos2)                                   ! Compute seed 3
    PUSH (chaos3)
    PUSH (chaos1)
    CALL getSeed
    MOV (seed3), AX                             ! Store seed3 in memory
   
! PRINT SEEDS
    MOV AX, step
    MOV DX,(seed1)
    CALL prnt_msg
    MOV AX, step
    MOV DX,(seed2)
    CALL prnt_msg
    MOV AX, step
    MOV DX,(seed3)
    CALL prnt_msg
   
    MOV SP,BP                  
    POP BP
    RET

!   -----------------------------------------------------------------
!   ASK USER TO GENERATE 3 NUMBERS
get3nums:

    PUSH BP
    MOV  BP,SP     
    PUSH BX
    PUSH DI
   
   
    MOV AX,msg1                                     ! Msg to user
    CALL prnt_msg
    MOV BX,0
    MOV CX, (lp_chaos)                          ! Times the input is asked
    MOV DI,chaos3                                   ! 3rd seed component

1:MOV AX, step                                      !Msg to user
    MOV DX,CX                                           !    Num value for print (loop n. CX)
    CALL prnt_msg
    CALL getNum                                     ! Get random seed: prompt msg to user
                                                                    !       collects input, returns rnd seed [0,9]
                                                                    !       uses BX to generate seed (seed accumulator)                                    
    STOS                                                        ! Store seed in AX to DI variable, then increment DI
    MOV BX,0                                                ! Reset seed accumulator
    LOOP 1b                                             ! More input asked for

    POP DI                                                  ! Reset state
    POP BX
    MOV SP,BP                  
    POP BP
    RET

getNum:                            
    PUSH BP
    MOV  BP,SP                 
    PUSH BX                                             ! Save state
   
    MOV AX, prompt_ms                           ! Print message
    CALL prnt_msg                                   ! =
    CALL pause                                          ! Wait
    PUSH _GETCHAR                               ! =
    CALL  cls                                               ! Clear screen (azzera AL)
   
1:                                                              ! Enter-reading loop
    INC BX                                                  ! Increment counter
    SYS                                                     ! Get char
    CMPB AL,'\n'               
    JE 1b                                                       ! If Enter, continues loop.
   
rd:SYS                                                      ! Clears possible extra chars
    CMPB AL,'\n'                                        ! =
    JNE rd                                                  ! =
   
    CMP BX, (n_chars)                               ! If not Enter, tries to exit loop: if BX below n_chars stays in, otherwise exits loop
    JLE k_psh                                               ! If below threshold: prints message, decreases counter, loops back to 1
    CALL  cls                                               ! Exit conditions satisfied:  exit getNum function
    AND BX, 0XF                                     ! Only keeps the last 4 bits, yelding mod 16
   
    MOV AX,BX                                           ! Return value in register AX

                                                                    ! Reset state
    POP BX
    MOV SP,BP                                           ! Clear stack
    POP BP
    RET
!   -----------------------------------------------------------------
! PRINTS "KEEP PUSHING" if release is too quick
k_psh:
    PUSH BP                    
    MOV BP,SP
    SUB BX, (bck_chars)                         ! Decrements counter
    PUSH k_push             ! Prints 'keep pushing'
    PUSH _PRINTF
    SYS
    PUSH _GETCHAR
    SYS
    CALL  cls
    MOV SP,BP
    POP BP
    JMP 1b                                                  ! Back to loop


!   -----------------------------------------------------------------
!   GET ONE SEED OUT OF THREE
!   KEYPRESS COMPONENTS
!   components: number after AND (0-15)

getSeed:                                                    ! needs 3 components on the stack, returns
                                                                    ! seed in AX
    PUSH BP
    MOV BP,SP  
   
! ADD AND SHIFT
! Equivalent to: n1*16*16+n2*16+n3
    MOVB CL,4                  
    MOV AX, 4(BP)                                   ! Use 1st seed component
    SHL AX, CL                 
    ADD AX, 6(BP)                                   ! Use 2nd seed component
    SHL AX, CL
    ADD AX, 8(BP)                                   ! Use 3rd seed component
    MOV SP,BP
    POP BP
    RET 6                                                   ! Clean up the stack
</pre>

Starting from the seeds, various sequences are generated.

  • Three linear congruential generators create a sequence of 48 uniform numbers.
  • These three sequences interact to feed the seed of a fourth sequence of 48 numbers, which will have a longer period than each of the previous ones.
  • A summation is performed on the 48 numbers, which will return a random variable distributed in a Gaussian manner.
  • The Gaussian variable is standardized.

In the previous operations, difficulties arise due to the limited size of the registers (carry-over must be used) and the absence of decimal arithmetic. The formulas are adapted to address some of the issues upstream.

 

The new Gaussian number will be the random component of a Geometric Brownian Motion. It represents the path of a hypothetical underlying asset. As many Gaussian numbers are generated as there are intervals in the considered period (according to the provided parameters: 252 days).

  • This Gaussian component is modified in terms of mean and variance according to the required financial parameters (drift and daily variance).
  • It is necessary to limit the range of this Brownian motion to reduce the complexity of the arithmetic. Barriers come in handy here.
  • The barriers, cap, and floor, when touched, fix the price of the underlying asset until the end of the period.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
<pre>! The getnum function returns a random value [0-7]
! Prints messages. User is asked to press key in order
! to generate one component of a random seed.
! Returns seed in AX

.SECT .TEXT        

! -------------------------------------------------------------------
!   APPLY BARRIERS
!   Reads in a whole trajectory and applies two knock-out
!   barriers to it.
!   Optimization: the barriers could either be applied where
!       the trajectory is made, or they could just be tested after plotPars.
!       The Apply Barriers step simplifies
!       the code, which is thus more modular.
!
!   NOTE: The option doesnt die when knocked-out.
!       The underlying asset price freezes until expiration.
!       This means that the present value of the payoff
!       will be discounted considering the full period.
!   CALLED: after the gmb call.
!   EXPECTS: nothing - uses global variables for everything,
!       for consistency with functions related to this one
!   ALTERS: CX, AX

applBarr:
    PUSH BP
    MOV BP,SP
    PUSH SI

    MOV SI, brownSeq                                    ! Put brownian sequence in SI
    MOV CX, (days)                                      ! Length of the br. sequence
   
    MOV DX, (floor)                                     ! Down and out level
    MOV AX, (cap)                                           ! Up and out level
   
! LOOK FOR KNOCK OUTS
!   If the price reaches a barrier, enter the next loop.
!   Otherwise jump to return
1:CMP DX, (SI)
    JG 2f                                                           ! Knock out (down)
    CMP AX, (SI)
    JL 2f                                                           ! Knock out (up)
    ADD SI,2
    LOOP 1b
    JMP 4f                                                      ! The loop completed without reaching barriers. Exit
! BARRIER REACHED
!   Continue the previous loop, copying
!   the last price (currently in (SI) ) until expiration
2:MOV DX, (SI)                                          ! Store last price
3:MOV (SI), DX                                          ! Copy last price to the sequence
    ADD SI, 2
    LOOP 3b
    MOV AX, DX
    MOV (lstBrPr), DX
4:
    POP SI
    MOV SP, BP
    POP BP
    RET
   

! -------------------------------------------------------------------
!   GENERATE GEOMETRIC BROWNIAN MOTION
!   EXPECTS price on the stack (AX will be price)
!
!   LAST PRICE IS RETURNED IN AX and saved in lstBrPr
!   ALTERS CX, AX

gbm:
    PUSH BP
    MOV BP,SP
    PUSH DI
    PUSH SI
    PUSH BX
       
    MOV AX, 4(BP)                                       ! Start price
    MOV CX,(days)                                       ! Number of gaussians to generate
    XOR SI,SI
   
gbmLp: 
    MOV DI, gaussSeq(SI)                            ! Take the gaussian
    ADD DI, (drift)                                         ! Add the drift
    CMP DI,0
    JG 1f                                                           ! If positive, branch
    NEG DI                                                      ! NEGATIVE CASE
    MOV BX, AX                                              ! Save price   
    MUL DI                                                      ! Multiply price times (drift+random)
    DIV (basePct)                                           ! Percentify the price movement
    NEG AX                                                      ! Restore negative sign
    ADD AX, BX                                              ! Add the price movement to the price
    XOR DX, DX                                              ! Reset DX
    JMP 2f
   
1:MOV BX, AX                                                ! POSITIVE  CASE
    MUL DI                                                      ! Same as negative, without sign issues
    DIV (basePct)              
    ADD AX, BX             
    XOR DX, DX
   
   
2:MOV brownSeq(SI), AX                          ! Store value in brownian sequence, same position as in gaussian
    ADD SI,2                                                    ! Advance sequences pointer
    LOOP gbmLp                                          ! Continue until days finish
   
    MOV (lstBrPr), AX
    POP BX
    POP SI
    POP DI
    MOV SP,BP
    POP BP         
    RET

!   -----------------------------------------------------------------
! GENERATE AND ADD A GAUSSIAN SEQUENCE
!   The number of gaussian numbers to generate is
!   on the stack
!   Uses global variable gaussCount to keep track of current gaussian being written.

genGaSeq:
    PUSH BP
    MOV  BP,SP
    PUSH DI
   
    MOV CX, 4(BP)                                       ! Get number of gaussians to generate
    XOR DI,DI                                                   ! Set gauss array to 0
1:PUSH CX                                                   ! Save loop state. Will change in genGausN
    MOV (gaussCount),DI                         ! Update counter of generated gaussians
    CALL genGausN                                       ! Generate one gaussian variable
    ADD DI,2                                                    ! Increment destination
    POP CX                                                      ! Retrieve loop state
    LOOP 1b

    POP DI
    MOV  SP,BP
    POP BP
    RET
   
!   -----------------------------------------------------------------
! GENERATE AND ADD A GAUSSIAN NUMBER
genGausN:
    PUSH BP
    MOV  BP,SP
    PUSH SI                                             ! Save SI state

! GENERATE THE 3 UNIFORM SEQUENCES
    CALL genSeqs   
   
! GENERATE THE COMBINED SEQUENCE
    CALL genCmbA                           
   
! GENERATE GAUSSIAN
    PUSH (nUnif)                                        ! Number of uniforms to sum up for one gaussian
    CALL uni2gaus
    ADD SP, 2
test0:
    POP SI
    MOV  SP,BP
    POP BP
    RET
   
     
!   -----------------------------------------------------------------
!   GENERATE 3 LINEAR CONGRUENTIAL SEQUENCES
!   GIVEN LENGTH, POINTER, SEEDS

genSeqs:
    PUSH BP
    MOV  BP,SP
    PUSH DI                                             ! Save DI state
    PUSH SI
   
! GENERATE FIRST SEQUENCE (Jumping)
    PUSH 0                                              ! First combination of parameters
    CALL updPars                                    ! Assign parameters to a, c, m
    ADD SP,2                                            ! Clean up the stack from parameter index
    PUSH _nSeq                                  ! Length of sequence 1a on the stack
    PUSH rndSeq1                                ! Sequence 1a pointer to stack 4(BP) in called
    PUSH (seed1)                                    ! Seed 1 to stack
    CALL rndLp                                      ! Returns result in AX
    MOV (seed1),AX                              ! Update seed to last rand element
    ADD SP, 6                                       ! Clean up the stack from sequence data
   
! GENERATE SECOND SEQUENCE
    PUSH 2                                              ! Second combination of parameters
    CALL updPars                       
    ADD SP,2                               
    PUSH _nSeq                     
    PUSH rndSeq2                   
    PUSH (seed2)                       
    CALL rndLp
    MOV (seed2),AX                 
    ADD SP,6       

! GENERATE THIRD SEQUENCE
    PUSH 4                                 
    CALL updPars                       
    ADD SP,2                               
    PUSH _nSeq                     
    PUSH rndSeq3                   
    PUSH (seed3)                       
    CALL rndLp
    MOV (seed3),AX                 
    ADD SP,6
   
    POP SI                                              ! Retrieve DI state
    POP DI                                 
    MOV BP,SP
    POP BP
    RET
   

! -------------------------------------------------------------------
!   UPDATE PARAMETERS
! a, c, m get updated to a different combination
!   finds the parameter index on the stack
! ALTERS AX
updPars:
    PUSH BP
    MOV BP,SP
    PUSH SI
   
    MOV SI,4(BP)
    MOV AX, aVec(SI)
    MOV (a),AX
    MOV AX, cVec(SI)
    MOV (c),AX
    MOV AX, mVec(SI)
    MOV (m),AX
   
    POP SI
    MOV SP, BP
    POP BP
    RET


!   -----------------------------------------------------------------
!   GENERATE SEQUENCE FROM SEED
!   ALTERS AX, DX, CX
rndLp:         
    PUSH BP
    MOV  BP,SP
    PUSH DI
   
    MOV AX, 4(BP)                                       ! Get seed
    MOV DI, 6(BP)                                           ! Get sequence pointer
    MOV CX, 8(BP)                                       ! Initialize counter

! (a*[seed])+0 mod m
nxtRnd:
    MUL (a)                                
    ADD AX, (c)
    DIV (m)
    MOV AX, DX
    MOV (DI),DX                                         ! Store number in rndSeq
    ADD DI,2                                                    ! Increment pointer to stored rand vars
    LOOP nxtRnd
   
    POP DI
    MOV  SP,BP
    POP BP
    RET


!   -----------------------------------------------------------------
! COMBINE 3 SEQUENCES AND GENERATE
! NEW ONE WITH LONGER PERIOD   
! ALTERS CX, DX
genCmbA:       
    PUSH BP
    MOV  BP,SP
    PUSH DI                                                 ! Save register states
    PUSH SI
    PUSH BX
   
    MOV CX, (nUnif)                                     ! From _nSeq-1 to 0
    XOR DI, DI                                              ! Make sure the sequence pointers start from 0
    XOR SI,SI
   
cmbLp:                                                          ! Sum/subtract 3 sequences
    XOR DX,DX                                               ! Reset register
   
    MOV AX,rndSeq1(SI)
    MOV BX,rndSeq2(SI)
    ADD AX, BX
    ADC DX,0
   
    MOV BX,rndSeq3(SI)
    ADD AX,BX                          
    ADC DX,0
    DIV (m_gauss)  
                        ! If second number was to be subtracted (to be tested):
                        !cmbLp:                                    
                            !MOV DX,0
                            !MOV AX,rndSeq1(SI)
                            !MOV BX,rndSeq2(SI)
                            !SUB AX,BX                 
                            !JS negative                                    ! Handle negative case below
                            !! positive
                            !MOV BX,rndSeq3(SI)
                            !ADD AX,BX             
                            !DIV (m_gauss)                          ! Just divide the result.
                            !JMP store                                 
                            !negative:                                      ! Twos complement on 32 bits
                            !CWD
                            !NOT AX
                            !ADD AX,1
                            !NOT DX
                            !ADC DX,0
                            !DIV (m_gauss) 
    MOV rndSeq4(SI),DX                                          ! Store number in rndSeq4          
    ADD SI,2
    LOOP cmbLp
   
    !MOV SI,0
   
    POP BX
    POP SI
    POP DI                                                                  ! Retrieve DI state
    MOV  SP,BP
    POP BP
    RET


!   -----------------------------------------------------------------
!   TRANSFORM A BATCH OF UNIFORMS
!   TO A GAUSSIAN RANDOM VARIABLE
!
!   GENERAL FORMULA to get
!   mean req_avg, standard deviation req_std,
!   having n numbers from a Uniform [0-m]
!  
!   req_std*    [sum(...n..)-m/2]/(sqrt(n*m**2/12))  + req_avg
!
!   FORMULA with n=48, m approaching 16 bit.
!   Starting price of asset (range under 16 bit) startPr: 20,000
!   Standard deviation = 1% of Starting price = 200; req_std = 300; req_avg = 0
!   ---&gt; (200*sum(...48...)/2)/m_gauss -12*200 + 0
!   ---&gt;(100*sum(...48...))/m_gauss -2400
!  
!   Requires additions resulting up to 32 bits, multiplications 32*16 bits
!   EXPECTS the number of uniforms (48)on the stack
!   ALTERS AX, CX, DX

uni2gaus:
    PUSH BP
    MOV  BP,SP
    PUSH BX                                             ! Save register states
    PUSH SI
    PUSH DI
   
    MOV CX, 4(BP)                                   ! Get batch length
    XOR AX,AX                                           ! Initialize lower bits of Total
    XOR DX,DX                                           ! Initialize higher bits of Total
    XOR SI,SI                                               ! Start the 48 uniforms counter

! SUM UP THE 48 NUMBERS
sumLp:                                                      ! SUM UP THE 48 NUMBERS
    MOV BX,rndSeq4(SI)                          ! Fetch new number 
    ADD AX,BX                                           ! Add new number to lower bits of total
    ADC DX,0                                                ! If AX+BX generates carry, add it to DX
    ADD SI,2                                                ! Point to next number
    LOOP sumLp                                      ! Repeat until number of elements is 0

! MULTIPLY THE SUM BY HALF STD
    MOV CX, DX                                      ! Save Old Higher part of N
    MUL (halfStd)                                       ! Multiply the Lower part of N times halfStd
    MOV BX, DX                                          ! Save New Higher of Low
    XCHG AX, CX                                     ! Now CX contains the New Lower of Lower. AX contains Old Higher
    MUL (halfStd)                                       ! Multiply Old Higher times halfStd
    ADD AX, BX                                          ! Add New Higher of Low to New Low of Higher
                                                                    ! 32bit * 16 bit: no carry to Higher of Higher

    MOV DX, AX                                          ! High part result
    MOV AX, CX                                          ! Low part result
   
    DIV (m_gauss)                                       ! If m_gauss is big enough, the result will fit in AX
    SUB AX, (mean)                                  ! Subtract the mean
   
    MOV DI, (gaussCount)
    MOV gaussSeq(DI), AX                        ! Store
   
    POP DI
    POP SI
    POP BX                                                  ! Restore BX state
    MOV BP,SP
    POP BP
    RET


</pre>

Many sequences are generated as there are iterations required for the Monte Carlo simulation.

  • Each trajectory generates a Payoff, depending on financial parameters (strike levels and barriers).
  • The iterations, exceeding the bits allowed by the CX register, require a double loop. Even the sums of Payoffs would exceed the allowed limits.
  • In the inner loop, the average of Payoffs is calculated; in the outer loop, the average of averages.
  • The average Payoff is updated according to an interest rate R.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
<pre>!  THIS MODULE HANDLES THE CREATION OF A SET OF SIMULATED PRICE TRAJECTORIES
!   AND CALCULATES THE AVERAGE PAYOFF.
!

.SECT .TEXT            

!   -----------------------------------------------------------------
!   GENERATES A TRAJECTORY. PRINTS:
!       the 3 base uniform sequences;
!       the derived uniform sequence; the Gaussian sequence;
!       the brownian motion.

runEpr:
    PUSH BP
   
    CALL trjctry           
   
    ! PRINT
    CALL pr4Seq                         !   THE LAST RUN OF UNIFORM SEQUENCES
                                                        !   genfuncs.
    CALL prGaSeq                        !   GAUSSIANS
                                                        !   genfuncs.s
    CALL prGmb                          ! BROWNIAN MOTION
                                                        !   genfuncs.s
    POP BP
    RET

!   -----------------------------------------------------------------
! GENERATES MANY TRAJECTORIES
! COMPUTES AVERAGE AND PRESENT VALUE
! Yelds a mean value - the fair price
! A high number of trajectories (&gt; 16 bit) is achieved
! by running 2 loops
!
! EXPECTS the number of runs to be pushed on the stack:
!   2int &lt; 16 bit. The number of runs is their product.
! RETURNS the average Mc Price in AX

runMc:
   
    PUSH BP
    MOV BP, SP
    dbg3:
    MOV CX, 6(BP)                       ! Set higher counter
    PUSH 4(BP)                              ! Pass lower counter to function
   
    XOR AX,AX                               ! Resets the accumulator
    XOR DX, DX 

1:                                                  ! OUTER LOOP STARTS HERE
    PUSH CX                                 ! Save higher counter  
    PUSH AX                                 ! Save last cumulated values - lower word
    PUSH DX                                 ! Save last cumulated values - higher word
   
    CALL mcPart

    ! CUMULATE THE PRICES
    POP DX                                      ! Last cumulated values, higher word
    POP BX                                      ! Last cumulated values, lower word, go in BX
    ADD AX, BX                              ! Add the last generated price to the cumulated values
    ADC DX, 0                               ! Add carry if needed
   
    POP CX                                      ! Retrieve higher counter
    LOOP 1b                                 ! CONTINUE OUTER LOOP

    ! AVERAGE THE AVERAGES
    DIV 6(BP)                                   ! Divide by higher loop length to get the mean 
    MOV (mcPayOff), AX              ! Save the Montecarlo average value
    MOV SP, BP
    POP BP
    RET

!   -----------------------------------------------------------------
mcPart:
    PUSH BP
    MOV BP, SP
   

    MOV CX, 10(BP)                      ! Set CX to lower counter.
                                                        ! Finds the counter value on the stack before:
                                                        ! 3 saved values, the function address and the bp address
    XOR AX,AX                               ! Resets the accumulator
    XOR DX, DX
   
1: 
    dbg4:
    PUSH CX                                 ! Save loop counter before next functions
    PUSH AX                                 ! Save last cumulated values - lower word
    PUSH DX                                 ! Save last cumulated values - higher word
   
    CALL trjctry                                ! BUILD A TRAJECTORY
    CALL prFrstPlt                          ! Plot one of the first trajectories

    CALL payOff                             ! Must find last price in (lstBrPr). Returns payoff in AX
   
    ! CUMULATE THE PAYOFFS
    dbg5:                                          
    POP DX                                      ! Last cumulated values, higher word
    POP BX                                      ! Last cumulated values, lower word, go in BX
    ADD AX, BX                              ! Add the last generated price to the cumulated values
    ADC DX, 0                               ! Add carry if needed
   
    dbg6:
    POP CX
    LOOP 1b
   
    ! AVERAGE THE PAYOFFS
    DIV 10(BP)                              ! Divide by lower loop length to get the mean
    MOV SP, BP
    POP BP
    RET

!   -----------------------------------------------------------------
!   GENERATE A COMPLETE PRICE TRAJECTORY
!   Stored in brownSeq
!   RETURNS: AX, the last day price
trjctry:                                           
! GENERATE A GAUSSIAN SEQUENCE

    PUSH (days)                         ! Push length of sequence
    CALL genGaSeq                       ! series2.s
    ADD SP, 2                               ! Clean up stack   
   
! GENERATE BROWNIAN MOTION
    PUSH (startPr)
    CALL gbm                                ! series.s
    ADD SP, 2                               ! Clean up stack
!   APPLY BARRIERS
    CALL applBarr
    RET
   
!   -----------------------------------------------------------------
!   GENERATE A PAYOFF
!  
!   EXPECTS: (lstBrPr) in memory, the last price of the sequence
!   RETURNS: AX, the payoff
!   ALTERS AX, DX
payOff:
    PUSH BP
    MOV BP, SP
   
    MOV AX, (lstBrPr)
    MOV DX, (strike)
    CMP (put),TRUE
    JNE 1f
    XCHG AX, DX
1:SUB AX, DX
    JNS 2f 
    XOR AX, AX
2:
    MOV SP, BP
    POP BP
    RET
   


   
!   -----------------------------------------------------------------
!   DISCOUNT A PRICE   
!   Uses the full period, base rate of return, rateR.
!  
!   RETURNS: AX, the discounted price
!   EXPECTS: AX, the future payoff. (days)
!   ALTERS AX, DX
dscnt:
                                                            ! The price is in AX
    XOR DX,DX
    MOV BX, AX                                  ! Save price for later
    MUL (rateR)                                 ! Multiply price by return - could use AX-DX
    DIV (basePct)                               ! Percentify the price movement - AX is enough
    SUB BX, AX                                  ! Subtract the discount from the price
                                                            ! Always &gt;= 0
    MOV AX, BX                                  ! Price back to AX
    RET

.SECT .DATA
.SECT .BSS             
</pre>

The values of each trajectory will be displayed on the text interface using ASCII characters.

  • A plot area is characterized by a certain number (configurable) of rows and columns. If the trajectory exceeds the expected number of columns, an additional plot area is generated.
  • All values of the trajectory are scaled to fit within this matrix – the plot area. The price range is segmented into the available number of columns so that the entire trajectory is always visible (and does not overflow the matrix, which is composed of memory space with a length of n_columns * n_rows).
  • During the Monte Carlo simulation, some trajectories are drawn. To ensure they remain visible for a sufficient amount of time, a large number of NOP (no-operation) instructions are inserted between them.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
<pre>!  PRINTS ASSET PRICE TRAJECTORIES

.SECT .TEXT

!   -----------------------------------------------------------------
! DRAWS A FULL PLOT AREA
! Draws a partial plot area [_nCols] long.
!   Continues drawing until the accumulated prtFrm
!   is bigger than [_days], then draws the last part
!   with the difference
!   SI accumulates the pointer position, in terms of days
!  
!  
fullPlot:
    PUSH BP
    MOV BP,SP
    PUSH SI
    PUSH DI
    PUSH BX
    MOV SI, 0
    MOV DI, 0
    MOV BX, (days)                                  ! For comparison
   
! GET THE OPTIMAL PARAMETERS FOR PLOTTING
    PUSH brownSeq                                   ! Push the brownian sequence
    PUSH (days)                                     ! Push the length of the sequence
    PUSH _nRows                                 ! Push the number of rows of the plot
    CALL plotPars                                       ! Get the optimal parameters for plotting
                                                                    ! Shrink in AX, Shift in DX, max in CX
    ADD SP, 6
   
    MOV (lstMinPr), DX                              ! Copy min and maxin global variable
    MOV (lstMaxPr), CX                          ! Used for the plot frame in prPlot
   
! GET THE PLOTTABLE VALUES
    ! The next functions require on the stack:
    ! min price, shrink, days, price sequence, axis sequence
    PUSH DX
    PUSH AX
    PUSH (days)
    PUSH brownSeq
    PUSH redPrSeq
    CALL redPric                                        ! Reduce prices to axis values
    ADD SP, 6                                           ! Make place for the STRIKE parmeters
    PUSH 1                                                  ! Strike is only 1 number
    PUSH strike
    PUSH redStrk                       
    CALL redPric                                        ! Reduce strike price to axis values
    ADD SP,10
   
1:
    MOV SI, DI                                          ! Prepare next frame
    ADD DI, _nCols
    CMP DI, BX
    JGE 2f                                                  ! If DI &gt; days, draw the remaining part and exit
    PUSH redPrSeq
    PUSH _nCols                                     ! Otherwise draw a full col-length frame
    PUSH SI                                             ! Starting day
    CALL partPlot                                       ! Draw a plot frame
    ADD SP, 6

    JMP 1b 
   
    2:                                                          ! draw the remaining part and exit
    SUB BX, SI 
    PUSH redPrSeq      
    PUSH BX                
    PUSH SI                                             ! Starting day
    CALL partPlot                                       ! Draw a plot frame
    ADD SP, 6
   
    POP BX
    POP DI
    POP SI
    MOV SP,BP
    POP BP     
    RET

!   -----------------------------------------------------------------
!   TRANSFORMS THE PRICES TO PLOTTABLE VALUES
!   Subtracts the minimum value, then divides by the shrink factor
!   EXPECTS: red. price seq. address, displacement, shrink,
!       price sequence length,price sequence address on the stack
!   ALTERS CX

redPric:
    PUSH BP
    MOV BP,SP
    PUSH SI
    PUSH DI
    PUSH BX
   
   
    MOV SI, 6(BP)
    MOV DI, 4(BP)
    MOV BX,0

    CMP 10(BP),0                                        ! If all the prices are equal, modify shrink and displacement.
    JNE 1f                                                  ! Otherwise, continue
    MOV AX, 12(BP)
    MOV 10(BP), AX
    MOV 12(BP), 0
   
   
1:  MOV CX, 8(BP)                               ! Set loop to number of days
   
2:XOR DX,DX
    MOV AX, (BX)(SI)                                ! Get number from prices sequence
    SUB AX, 12(BP)                                  ! Shift it by displacement
    DIV 10(BP)                                          ! Divide by shrink
   
    MOV (BX)(DI), AX
    ADD BX,2
    LOOP 2b
   
    POP BX
    POP DI
    POP SI
    MOV SP,BP
    POP BP     
    RET


!   -----------------------------------------------------------------
! COMPUTES OPTIMAL PARAMETERS FOR PLOTTING
!   The SHRINK factor is the resolution of the plot. It divides the
!       price value.
!   The SHIFT parameter is the lowest value. It is subtracted from the
!       price to center the plot.
! RETURNS:
!       SHRINK factor in AX,
!       SHIFT factor in DX (also the min price), max price in CX
! EXPECTS:
!       brownian sequence pointer, sequence length,  
!       number of rows on the stack
! ALTERS: AX, DX, CX
!
plotPars:
    PUSH BP
    MOV BP,SP
    PUSH SI

    MOV SI, 8(BP)                                       ! Put brownian sequence pointer in SI
    MOV CX, 6(BP)                                   ! Length of the br. sequence
   
    MOV DX, 32767                                   ! Keeps the minimum value found in the sequence
    MOV AX, 0                                           ! Keeps the maximum value found in the sequence
   
1:CMP DX, (SI)
    JLE 2f                                                  ! If min value is smaller than current value, continue on 2
    MOV DX, (SI)                                        ! Otherwise, set min value
2:CMP AX, (SI)
    JGE 3f                                                  ! If max value is greater than current value, continue on 3
    MOV AX, (SI)                                        ! Otherwise, set max value
3:
    ADD SI,2
    LOOP 1b

    PUSH AX                                             ! Save max and min values
    PUSH DX
    SUB AX, DX                                          ! Get range
! SHRINK FACTOR in AX
    XOR DX, DX                                          ! Clean DX for division
    DEC 4(BP)
    DIV 4(BP)                                               ! Divide by rows number to get the SHRINK factor

! SHIFT PARAMETER IS DX, being DX the minimum value
    POP DX
! MAX VALUE in CX
    POP CX
   
    POP SI
    MOV SP,BP
    POP BP     
    RET


!   -----------------------------------------------------------------
! DRAWS A PARTIAL PLOT AREA
!
! EXPECTS source sequence pointer, sequence length, sequence on the stack
partPlot:
    PUSH BP
    MOV BP,SP
    PUSH BX

    PUSH 6(BP)                                          ! Length of the sequence to draw (excluding newlines)
    CALL voidPlt                                        ! Build an empty plot area
                                                                    ! Optimization: could be computed just once, in fullPlot
    ! 6(BP) still on the stack, used by the next function
    CALL cpVoid                                     ! Copy the void plot area to the trajectory plot area
   
    ! 6(BP) still on the stack, used by the next function
    MOV BX, 4(BP)                                   ! Get the offset of the days for the next plot (number of days already plotted)
    SHL BX,1                                                ! Double the offset - the days need be converted to WORD
    ADD BX, 8(BP)                                   ! Add the starting sequence pointer (redPrSeq)
    PUSH BX                                             ! Push the new pointer for the prices on the stack
    PUSH  (redStrk)                                 ! Push the strike
    CALL addDots                                        ! Add dots to the plot area
    ADD SP,6                                                ! Clean up: BX and 6(BP)
    CALL prPlot                                         ! Print the plotted area

    POP BX
    MOV SP,BP
    POP BP     
    RET
   
   
!   -----------------------------------------------------------------
! BUILDS AN EMPTY PLOT AREA
!
! EXPECTS number of cols on the stack
! ALTERS AX, DX
voidPlt:   
    PUSH BP
    MOV BP,SP
    PUSH DI
    PUSH BX
   
    MOV DI, voidMat
    MOV DX, _nRows
    MOV BX, 4(BP)                                   ! Number of columns to draw
1:MOV CX, BX                                            ! Number of columns to draw
    ! FILL A ROW WITH NULLS
    MOVB AL," "                                         ! Fill value
    REPNZ STOSB                                 ! space fill until CX==0
    MOVB AL,"\n"                                        ! Place a newline at the end
    STOSB                                                   ! =
    DEC DX                                              ! Move to next row
    LOOPNZ 1b
    MOVB AL, 0
    STOSB                                                   ! Signal string ending
   
    POP BX
    POP DI
    MOV SP,BP
    POP BP     
    RET
   
!   -----------------------------------------------------------------
! COPY AN EMPTY PLOT AREA IN trjPlot
!
! EXPECTS number of cols on the stack
cpVoid:
    PUSH BP
    MOV BP,SP
    PUSH SI
    PUSH DI
    PUSH BX

    MOV SI, voidMat
    MOV DI, trjPlot
    ! Copy the rows*cols + nrows (the newlines)+1 end string
    MOV AX, _nRows
    MOV BX, 4(BP)                                   ! Number of cols
    INC BX                                                  ! Make space for newline
    MUL BX
    INC AX                                                  ! Line ending will also be copied
    MOV CX, AX
    REPNZ MOVSB
   
    !MOV AX,0
    !MOVSB
   
    POP BX
    POP DI
    POP SI
    MOV SP,BP
    POP BP     
    RET
   
!   -----------------------------------------------------------------
! ADDS THE DOTS TO THE PLOT AREA
! ADDS STRIKE PRICE, BARRIERS
!
! EXPECTS sequence length, sequence pointer, reduced strike on the stack
! ALTERS AX, DX
addDots:
    PUSH BP
    MOV BP,SP
    PUSH BX
    PUSH DI
    PUSH SI
   
    XOR SI, SI
    XOR DI, DI
    MOV CX, 8(BP)                                   ! Get sequence length
    PUSH CX                                             ! Get days + 1 and push it on the stack --&gt; LOCAL VARIABLE -8(BP)
    INC -8(BP)                                          ! =

1:
! DOTS:
! The memory location of a dot is:
!   Location of row (from the axis-price sequence) +  col (the current in the cycle)
!   Price is _nRows-price, to let the plot start on the lower border
!   price*(row_length+1) + col, where +1 refers to the newline
! STRIKE AND BARRIERS:
!   Same as above, but the price comes from the appropriate global variable

! DRAW STRIKE
    MOV BX, 4(BP)                                   ! Get the row of the strike price
    MOV AX, _nRows
    SUB AX,BX                                           ! Reduced price (in sequence pointer+SI) to AX, in reverse order   
    MUL -8(BP)                                          ! -8(BP) is the local variable for [days+1]
                                                                    ! Now AX contains memory location of row                                                       
    MOV BX,AX                                           ! Location of row goes to BX for Register index displacement   
    MOVB trjPlot(BX)(DI), "="                   ! Place a hyphen in  trjPlot where row = strike, column DI

! DRAW DOT
! COLUMN IS IN DI
! GET ROW IN AX

    MOV BX, 6(BP)                                   ! Move sequence pointer from stack to BX   
    MOV AX, _nRows-1                            ! dont want max rows
    SUB AX,(BX)(SI)                                 ! Reduced price (in sequence pointer+SI) to AX, in reverse order   
   
! GET MEMORY LOCATION OF ROW according to formula above
    MUL -8(BP)                                          ! -8(BP) is the local variable for [days+1]
                                                                    ! Now AX contains memory location of row                                                       
    MOV BX,AX                                           ! Location of row goes to BX for Register index displacement   
    MOVB trjPlot(BX)(DI), "|"                   ! Place a dot in  trjPlot where row = price, column DI
    INC DI                                                  ! Next column
    ADD SI,2                                                ! Next pointer for price sequence
    LOOP 1b                                             ! Plot one more column 
   
    ADD SP,2
    POP SI
    POP DI
    POP BX
    MOV SP,BP
    POP BP     
    RET


!   -----------------------------------------------------------------
! PRINTS THE PLOT AREA
!   Prints the plotstring and 2 strings as divisors with high and low prices
!   For the frame, finds the minimum, maximum, last prices of the
!       brownian sequence in lstMinPr, lstMaxPr, lstBrPr
!
! ALTERS AX, DX
prPlot:
    PUSH BP
    MOV BP,SP
    PUSH DI

! TOP SEPARATOR
    MOV DI, voidStr
    MOVB AL, "\n"
    STOSB
    MOVB AL, "#"                                        ! Print a separator nCols times
    MOV CX, (nCols)
    REPNZ STOSB
    MOVB AL, "\n"
    STOSB
    MOVB AL, 0                                          ! End the string
    STOSB                      
   
    PUSH voidStr
    PUSH _PRINTF
    SYS
    ADD SP, 4  

! TOP LEFT
    MOV AX,(lstMaxPr)
    CALL axdxDecN
    PUSH DX
    PUSH AX
    PUSH maxStr1
    PUSH _PRINTF
    SYS
    ADD SP, 8
   
! TOP CENTER
    MOVB AL, "-"
    MOV DI, voidStr
    MOV CX, (nCols)                        
    SUB CX, (maxStrSp)                          ! If there is space enough to add hyphens, add as many as the columns,
    JNS 1f                                                  ! subtracting the start and end strings. Otherwise, repeat 0 times
    XOR CX, CX
1:REPNZ STOSB
    MOVB AL, 0                                          ! End the string
    STOSB                      

    PUSH voidStr
    PUSH _PRINTF
    SYS
    ADD SP, 4
   
! TOP RIGHT
    MOV AX,(lstBrPr)
    CALL axdxDecN
    PUSH DX
    PUSH AX
    PUSH maxStr2
    PUSH _PRINTF
    SYS
    ADD SP, 8
   
! PLOT THE TRAJECTORY
    PUSH trjPlot
    PUSH _PRINTF
    SYS
    ADD SP, 4
   
! BOTTOM LEFT
    MOV AX,(lstMinPr)
    CALL axdxDecN
    PUSH DX
    PUSH AX
    PUSH minStr1
    PUSH _PRINTF
    SYS
    ADD SP, 8

! BOTTOM CENTER
    MOVB AL, '-'
    MOV DI, voidStr
    MOV CX, (nCols)
    SUB CX, (minStrSp)                                  ! If there is space enough to add hyphens, add as many as the columns,
    JNS 1f                                                          ! subtracting the start and end strings. Otherwise, repeat 0 times
    XOR CX, CX
1:REPNZ STOSB
    MOVB AL, "+"
    STOSB
    MOVB AL, "\n"
    STOSB
    MOVB AL, 0                                                  ! End the string
    STOSB                      
   
    PUSH voidStr
    PUSH _PRINTF
    SYS
    ADD SP, 4
   
    POP DI
    MOV SP,BP
    POP BP         
    RET
   

.SECT .DATA

.SECT .BSS 
redPrSeq: .SPACE _days*2
voidMat: .SPACE _nRows*_nCols+_nRows+1
.ALIGN 2
trjPlot: .SPACE  _nRows*_nCols+_nRows+1
.ALIGN 2
topBfr: .SPACE 1000
botBfr: .SPACE 1000

</pre>

User interaction includes, in addition to generating random components, the choice of direction: whether to buy a PUT or a CALL option. After pricing the option, a final trajectory is generated; the Payoff is derived from it. The cost of the derivative is subtracted, and the outcome is communicated to the user.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
<pre>.SECT .TEXT

!   -----------------------------------------------------------------
!   PRINT THE FIRST N PLOTS WITH DELAY
!   For every run in Montecarlo, checks
!   if it must be printer. Inserts NOPs in order
!   to let the user see the plot.
!   Keeps count in a global variable.
!   Used in mtCarlo.s -&gt; mcPart

prFrstPlt: 
    CMP (pltCntr), MAXMCPLT                             ! check counter. If it reaches constant, jmp to return
    JGE 3f
    CALL fullPlot

    MOV CX, NOP1    ! First part of waiting cycle
1:PUSH CX
    MOV CX, NOP2   
2:XCHG AX, AX       ! Insert NOP
    LOOP 2b
    POP CX
    LOOP 1b
    ! Increase counter
    INC (pltCntr)
3:
    RET


!   -----------------------------------------------------------------
!   PRINT GEOMETRIC BROWNIAN MOTION
prGmb:
    PUSH (days)                                         ! Length of sequence to the stack
    PUSH brownSeq                                       ! Sequence 1a pointer to stack 4(BP) in called
    CALL prDecSeq
    ADD SP,4
    MOV AX,prDiv                                            ! Msg to user
    CALL prnt_msg
    RET
   
!   -----------------------------------------------------------------
! PRINT GAUSSIAN SEQUENCE
prGaSeq:   
    PUSH (days)                                         ! Length of sequence to the stack
    PUSH gaussSeq                                       ! Sequence 1a pointer to stack 4(BP) in called
    CALL prSeq
    ADD SP,4
    MOV AX,prDiv                                            ! Msg to user
    CALL prnt_msg
    RET

!   -----------------------------------------------------------------
! PRINT THE 4 SEQUENCES
! Alters AX
pr4Seq:
! PRINT FIRST SEQUENCE 
   
    PUSH (nUnif)                                            ! Length of sequence 1b on the stack
    PUSH rndSeq1                                        ! Sequence 1a pointer to stack 4(BP) in called
    CALL prSeq
    ADD SP,2
    MOV AX,prDiv                                            ! Msg to user
    CALL prnt_msg
   
! PRINT SECOND SEQUENCE
    PUSH rndSeq2                                        ! Sequence 1a pointer to stack 4(BP) in called
    CALL prSeq
    ADD SP,2
    MOV AX,prDiv                                            ! Msg to user
    CALL prnt_msg
   
! PRINT THIRD SEQUENCE
    PUSH rndSeq3                                        ! Sequence 1a pointer to stack 4(BP) in called
    CALL prSeq
    ADD SP,2
    MOV AX,prDiv                                            ! Msg to user
    CALL prnt_msg

! PRINT COMBINED SEQUENCE
    PUSH rndSeq4                                        ! Sequence 1a pointer to stack 4(BP) in called
    CALL prSeq
    ADD SP,4
    MOV AX,prDiv                                            ! Msg to user
    CALL prnt_msg
   
    RET

!   -----------------------------------------------------------------
! PRINT SEQUENCE
! EXPECTS number of chars , then sequence pointer on the stack
prSeq: 
    PUSH BP
    MOV BP,SP
    PUSH SI
   
    MOV CX,6(BP)                                        ! Get  total days
    MOV SI, 4(BP)                                       ! Get position of prices
1: 
    MOV AX, (SI)                                        ! Get a price
    ADD SI, 2
    PUSH AX
    PUSH prNum
    PUSH _PRINTF
    SYS
    ADD SP, 6
    LOOP 1b
   
    tst1:
    POP SI
    MOV SP,BP
    POP BP         
    RET

!   -----------------------------------------------------------------
! PRINT DECIMAL SEQUENCE
!   Same as above, but prints a decimal number
! EXPECTS number of chars , then sequence pointer on the stack
! ALTERS AX, CX, DX
prDecSeq:  
    PUSH BP
    MOV BP,SP
    PUSH SI
   
    MOV CX,6(BP)                                        ! Get  total days
    MOV SI, 4(BP)                                       ! Get position of prices
   
1: 
    MOV AX, (SI)                                        ! Get a price  
    CALL axdxDecN                                   ! Produce a decimal string using AX.
                                                                    ! result in dcmlBuf
    PUSH DX
    PUSH AX
    PUSH frmtDecN
    PUSH _PRINTF
    SYS
   
    ADD SP, 4
    ADD SI, 2                                               ! Prepare for next price   
    LOOP 1b
   
    POP SI
    MOV SP,BP
    POP BP         
    RET

!   -----------------------------------------------------------------
! DECIMAL NUMBER
!   Transforms an int number into a decimal number
! EXPECTS number in AX
! RETURNS values in AX, DX
axdxDecN:
    PUSH BP
    MOV BP,SP
   
    XOR DX,DX
    DIV (HUNDRED)
   
    MOV SP,BP
    POP BP
    RET

!   -----------------------------------------------------------------
! PRINTS INFORMATION ON PARAMETERS
! All the parameters are pushed on the stack
! and printed
! The values are divided by 100
! ALTERS AX, DX
prInfo1:
    PUSH BP
    MOV BP,SP
   
    PUSH msg2
    PUSH _PRINTF
    SYS
    PUSH msg3
    PUSH _PRINTF
    SYS
    MOV AX, (floor)
    DIV (HUNDRED)
    PUSH AX
    MOV AX, (cap)
    DIV (HUNDRED)
    PUSH AX
    MOV AX, (strike)
    DIV (HUNDRED)
    PUSH AX
    PUSH (reqStd)
    PUSH (drift)
    PUSH (rateR)
    PUSH msg4
    PUSH _PRINTF
    SYS
    PUSH msg5
    PUSH _PRINTF
    SYS
   
    MOV SP,BP
    POP BP
    RET

!   -----------------------------------------------------------------
! ASK PUT
! Asks the user if he wants a put (p)
! ALTERS AX
askPut:
    PUSH BP
    MOV BP,SP
   
    ! PRINT REQUEST
    PUSH msg6
    PUSH _PRINTF
    SYS

    ! GET ANSWER
    PUSH _GETCHAR
    SYS                            
    CMPB AL,'p'            
    JNE 1f                             
    MOV (put), TRUE                                     ! It is a PUT
    MOV AX, msg6p
    JMP 2f
1:MOV (put), FALSE                                      ! It is a CALL
    MOV AX, msg6c
2:PUSH AX
    PUSH _PRINTF
    SYS
   
    MOV SP,BP
    POP BP
    RET

!   -----------------------------------------------------------------
! TELL THE COST
!   Tells the user the discounted, average Montecarlo price
!   of the option
prInfo2:
    PUSH BP
    MOV BP,SP
   
    MOV AX, (dscPayOff)
    CALL axdxDecN
    PUSH DX
    PUSH AX
    MOV AX,  (mcPayOff)
    CALL axdxDecN
    PUSH DX
    PUSH AX
    PUSH msg7
    PUSH _PRINTF
    SYS
   
   
    MOV SP,BP
    POP BP
    RET

!   -----------------------------------------------------------------
! EXPLAIN THE UNIFORMS
prInfo3:
    PUSH BP
    MOV BP,SP
    PUSH msg8
    PUSH _PRINTF
    SYS
    MOV SP,BP
    POP BP
    RET

!   -----------------------------------------------------------------
! EXPLAIN THE GAUSSIANS
prInfo4:
    PUSH BP
    MOV BP,SP
    PUSH msg9
    PUSH _PRINTF
    SYS
    MOV SP,BP
    POP BP
    RET

!   -----------------------------------------------------------------
! EXPLAIN THE UNIFORMS
prInfo5:
    PUSH BP
    MOV BP,SP
    PUSH msg10
    PUSH _PRINTF
    SYS
    MOV SP,BP
    POP BP
    RET

!   -----------------------------------------------------------------
! SHOW THE TRAJECTORY
prInfo6:
    PUSH BP
    MOV BP,SP
    PUSH msg11
    PUSH _PRINTF
    SYS
    MOV SP,BP
    POP BP
    RET

!   -----------------------------------------------------------------
!   TELL THE OUTCOME
!   Subtracts the previously computed discounted
!   Montecarlo payoff from the new payoff
!
!   EXPECTS payOff in AX
tellOutc:
    PUSH BP
    MOV BP,SP
    SUB AX, (dscPayOff)
    JS 1f
    PUSH AX
    CALL axdxDecN
    PUSH DX
    PUSH AX
    PUSH msg12a
    JMP 2f
1:NEG AX
    PUSH AX
    CALL axdxDecN
    PUSH DX
    PUSH AX
    PUSH msg12b
   
2:PUSH _PRINTF
    SYS
    MOV SP,BP
    POP BP
    RET
   
!   -----------------------------------------------------------------
! PRINT A TEXT AND POSSIBLY A NUMBER
! Requires string pointer in AX, number in DX
prnt_msg:
    PUSH BP
    MOV BP,SP
    PUSH DX
    PUSH AX
    PUSH _PRINTF
    SYS
    MOV SP,BP
    POP BP
    RET

!   -----------------------------------------------------------------
! WAITS FOR KEYPRESS
pause:                             
    PUSH BP
    MOV BP,SP
    PUSH _GETCHAR
    SYS
    MOV SP,BP
    POP BP
    RET

!   -----------------------------------------------------------------
!   INSERTS NEW LINES TO CLEAR THE SCREEN
cls:                                        !
    PUSH BP
    MOV BP,SP
    PUSH clear
    PUSH _PRINTF
    SYS
    MOV SP,BP
    POP BP
    RET
   
</pre>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
<pre>! This file contains parameters that are allowed to be changed
!   for debugging or usage.

!   ######################################
!   USER MODIFIABLE DATA

!   -----------------------------------------------------------------
!   FINANCIAL DATA

 _days = 252!45                                     ! Length of the generated final sequence. Note: Tracer only supports up to 45.
_startPr = 10000                                        ! The value of the asset at T0.
                                                                    !   Should be small enough to fit in a register when growing,
                                                                    !       big enough to get meaningful results when manipulating.
                                                                    !       Multiple of 10.000 gets the drift right
                                                                    !   Also used as the quotient of percent values
_bpDrift =  0!25                                        ! Basis points; eg: 0.25% of 20000 basePct yelds 50 absolute
 _bpReqStd=100                                      ! Basis points; eg: 0.100% of 20000 basePct yelds 200 absolute.
                                                                    ! The absolute value should be a multiple of 4 for a good mean calculation
_rateR = 200                                            ! Rate of return - yearly, in basis points.
                                                                    ! Eg: price in T252 = 30000; bpR = 200; basePct = 20000 -&gt; return 1%
                                                                    ! Discount in T0: (30000*200)/20000=300
 _put = TRUE
 _strike = 10000
 _cap = 12000
 _floor = 8000
 

!   ######################################
!   DEBUG AND PROGRAM
 
!   -----------------------------------------------------------------
! PLOTS
! Number of rows and columns
_nRows = 30
_nCols = 150

!   -----------------------------------------------------------------
 _debug = FALSE                                     ! TRUE if debug mode, FALSE otherwise
                                                                        ! If DEBUG, jumps over the user input with preset values
 _dbgSd1 = 50
 _dbgSd2 = 70
 _dbgSd3 = 90

 
.SECT .TEXT
.SECT .DATA

.SECT .BSS

! SEQUENCES
rndSeq1: .SPACE 2*_nSeq
rndSeq2: .SPACE 2*_nSeq
rndSeq3: .SPACE 2*_nSeq
rndSeq4: .SPACE 2*_nSeq

! GAUSSIAN VARIABLES
gaussSeq: .SPACE _days*2

! BROWNIAN MOTION
brownSeq: .SPACE _days*2
</pre>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
<pre>.SECT .TEXT
!   -----------------------------------------------------------------
!   INITIALIZE VARIABLES
!   Alters AX, CX, DX

initVars:                                      
    ! PERFORMS SOME NEEDED CALCULATIONS ON THE PARAMETERS  

    ! Required Standard Deviation, as a base value
    XOR DX, DX
    MOV AX, (basePct)
    DIV (pcFier)
    MUL (bpReqStd)
    MOV (reqStd), AX   
   
    ! Normalizer-mean calculated (in accordance with the 48 summation formula) 
    XOR DX, DX
    MOV AX, (reqStd)
    SHR AX,1                                                ! Divide by 4
    SHR AX,1
    MUL (nUnif)                                         ! Multiply by 48
    MOV (mean), AX
       
    ! Drift, as a base value
    XOR DX, DX
    MOV AX, (basePct)
    DIV (pcFier)
    MUL (bpDrift)
    MOV (drift), AX

    !Half of required standard deviation, base value
    !   (in accordance with the 48 summation)
    MOV AX, (reqStd)
    SHR AX,1   
    MOV (halfStd), AX
   
    ! rateR, as a base value
    XOR DX, DX
    MOV AX, (basePct)
    DIV (pcFier)
    MUL (bpRateR)
    MOV (rateR), AX
   
    RET
   
!   -----------------------------------------------------------------
    .SECT .DATA

!   -----------------------------------------------------------------
! MISCELLANEOUS
    debug: .WORD _debug                         ! 1 if debug mode, 0 otherwise
    HUNDRED: .WORD _HUNDRED     ! 100

!   -----------------------------------------------------------------
!   MONTECARLO
hMcCount: .WORD _hMcCount               ! 100
lMcCount: .WORD _lMcCount                   ! 100        100 * 100 = 10k runs
pltCntr: .WORD ZEROINT  ! 0 Counter of Montecarlo plots displayed

!   -----------------------------------------------------------------
! FINANCIAL DATA
!   By using the percentifier, the basis point values are made independent respect the
!   base price of the asset.

    days: .WORD _days                               ! 252 Number of time steps
    startPr: .WORD _startPr                         ! 20000 Starting price of the asset
   
    ! DevStd and Average are expressed as a percentage multiplied by
    ! the base number
    basePct: .WORD _startPr                     ! 20000 Used to get percent values

    pcFier: .WORD _pcFier                           ! 10000      Used to transform drift, std, r
    bpDrift: .WORD _bpDrift                     ! 25                 Relative - basis points
    bpReqStd: .WORD _bpReqStd           ! 100 daily stdev of the asset - basis points
    bpRateR: .WORD _rateR                       ! 200 Rate of return - year, in basis points.
   
    strike: .WORD _strike                               !   20000 Strike price of the asset for the option
    redStrk: .WORD ZEROINT 
    cap: .WORD _cap
    floor: .WORD _floor
   
    put: .WORD _put ! TRUE  Boolean. The option behaves like a put if True, as a call if False
   
    mcPayOff: .WORD 0
    dscPayOff: .WORD 0

!   -----------------------------------------------------------------
! GAUSSIANS
    m_gauss:    .WORD   32362                   ! For the combined sequence, LCG
    nUnif: .WORD _nSeq  ! 48                        ! Number of uniforms to sum up

!   -----------------------------------------------------------------
! BROWNIAN MOTION
    lstBrPr:  .WORD 0                                   !Last brownian price computed
    lstMinPr:  .WORD 0                                  !Minimum brownian price computed
    lstMaxPr:  .WORD 0                              !Maximum brownian price computed
   

!   -----------------------------------------------------------------
! UNIFORMS
! a, c, m  coefficients of LCG are stored into vectors: for each index into them,
! a different combination of parameters is chosen

    a:  .SPACE  2              
    c:  .SPACE  2      
    m:  .SPACE  2
    aVec:   .WORD 157, 146, 142
    cVec:   .WORD 0, 0, 0
    mVec: .WORD 32363, 31727, 31657

!   ######################################
!   MESSAGES AND RELATED PARAMETERS
 
!   -----------------------------------------------------------------
! PLOT
!   ----&gt; prTraj.s
    maxStrSp:   .WORD 46                            ! Space taken by the maxStr and minStr
    minStrSp: .WORD 20                              ! on the plot borders
    nRows:  .WORD _nRows                        ! 30     Rows and columns of the plot area
    nCols:  .WORD _nCols                            ! 100
    voidStr:    .SPACE 1000                         ! For the frame
    maxStr1: .ASCIZ "\n+ %d.%02d  $ MAX VALUE"
    maxStr2: .ASCIZ " %d.%02d  $ AT EXPIRATION + \n"
    minStr1: .ASCIZ "\n+ %d.%02d  $ MIN VALUE"

.ALIGN 2

!   -----------------------------------------------------------------
! INPUT
!   ----&gt;genrand.s
    lp_chaos: .WORD 3
    n_chars: .WORD 2                                ! At least n_chars pressed before exiting the read loop
    bck_chars: .WORD 2                          ! If user exits too early, decrease counter by bck_chars

!   -----------------------------------------------------------------
! OUTPUT
!   ----&gt;genrand.s, prFuncs.s
    k_push: .ASCIZ "KEEP PUSHING!!!!!!"
    prompt_ms: .ASCIZ "a.Press ENTER for a few seconds (count to 10)\nb.Press any other key\nc.Press ENTER again, once"
    prNum: .ASCIZ "%d "
    clear: .ASCIZ "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
    frmtDecN: .ASCIZ "%d.%02d "
   
!   ----&gt;main.s
    prDiv: .ASCIZ "\n-------------------------------------------------------------------\n"
    step: .ASCIZ "\n=====================\nSTILL %d TO GO\n"
   
!   -----------------------------------------------------------------  
! MESSAGES
    msg1: .ASCIZ "2) NOW: CREATE CHAOS!!\nCharge your generator by pressing [ENTER... - ANY KEY - ENTER] 3 times\n"
    msg2: .ASCIZ "*******************************************\n*                                         *  \n* WELCOME TO THE BARRIER OPTION SIMULATOR * \n*                                         *  \n*******************************************\n"
    msg3: .ASCIZ "\n\n1) Choose the option type\n2) Generate randomness\n3) Wait for Montecarlo pricing\n4) See if you gain or loose\n\n\nBuy a CALL or a PUT "
    msg4: .ASCIZ "on an asset where:\nR (Basis Points): %d\nDRIFT (Basis Points): %d\nSTANDARD DEVIATION (Basis Points): %d\nSTRIKE PRICE: %d\nCAP: %d\nFLOOR: %d\n\n"
    msg5: .ASCIZ "These parameters are modifiable in the source code. Rows and columns of the plot can also be set. \nPress ENTER to continue..."
    msg6: .ASCIZ "\n\n1) Please, CHOOSE YOUR OPTION. Enter [p] (lowercase) for a PUT, any other character for a CALL. Then press ENTER.\nType:  "
    msg6p: .ASCIZ "You own a PUT option! \nPress ENTER..."
    msg6c: .ASCIZ "You own a CALL option! \n3) Now, run Montecarlo\n\nPress ENTER..."
    msg7: .ASCIZ "\n\n\nThe estimated payoff of your derivative is %d.%02d$ in a year\nNow it costs you %d.%02d$\n\n4) Now, see what happens to the underlying asset in the next year:\n\nPress ENTER..."
    msg8: .ASCIZ "\n\n\n(See how a trajectory is made)\nThe next 4 sequences are uniform distributions. They will be used to generate a single gaussian random variable\n\nPress ENTER...\n"
    msg9: .ASCIZ  "\n\n\n(See how a trajectory is made)\nThat way, a sequence of gaussians is built\n\nPress ENTER...\n"
    msg10: .ASCIZ  "\n\n\nTHESE ARE YOUR ASSET PRICES:\n\nPress ENTER...\n"
    msg11: .ASCIZ  "\n\n\nTHIS IS THE PLOT OF THE PERIOD:\n\nPress ENTER...\n"
    msg12a: .ASCIZ  "\n\n\nTHIS IS YOUR GAIN:\n\n&gt;&gt;&gt;   %d.%02d$  &lt;&lt;&lt;Press ENTER to exit the program...\n"
    msg12b: .ASCIZ  "\n\n\nTHIS IS YOUR LOSS:\n\n&gt;&gt;&gt;   %d.%02d$  &lt;&lt;&lt;\nPress ENTER to exit the program...\n"
   
   

.ALIGN 2

.SECT .BSS

!   -----------------------------------------------------------------
! FINANCIAL DATA

    halfStd: .SPACE 2!  100                         ! To use in computation of gaussian, precomputed element
    mean: .SPACE 2  ! 2400                          ! reqStd*48/4
    drift: .SPACE 2! 50                                     ! Base daily drift of asset: 0.25%*basePct = 50
    reqStd: .SPACE 2!                                       ! Daily standard deviation of asset: 1%*basePct = 200
   
    rateR: .SPACE 2! 50                                 ! Base rate of return
!   -----------------------------------------------------------------
! RANDOMNESS GENERATION

    gaussCount: .SPACE 2                                ! Where to put next gaussian

    chaos3:  .SPACE 2                                       ! Seed components
    chaos2:  .SPACE 2      
    chaos1:  .SPACE 2      

    seed1:  .SPACE  2                                       ! seeds obtained by reordering components
    seed2:  .SPACE  2      
    seed3:  .SPACE  2

   

</pre>

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
<pre>! This file contains constants used along the program.
! No interaction is ever expected between the user and these values.
! The parameters the user is allowed to tweak (for debugging or usage)
!   are grouped in usrPrms.h

!   ######################################
! SYSTEM AND LIBRARY CALLS

_EXIT      =      1
_GETCHAR   =    117
_SPRINTF   =    121
_PRINTF    =    127

 !  ######################################
 ! OTHER CONSTANTS
 TRUE = 1
 FALSE = 0
 
 ZEROINT = 0
 _HUNDRED = 100
 
!   ######################################
!   PROGRAM CONSTANTS

!   -----------------------------------------------------------------
!   SEQUENCES
_nSeq = 48                                          !   Number of variables in a generated uniform sequence
                                                                !   Should match the gaussian generator
                                                                !   To be changed to obtain longer uniform sequences
                                                                !   DO NOT CHANGE: the formulas depend on it
                                                                !           In case it is changed, halfStd has
                                                                !           to be changed accordingly with the squared-root
                                                                !           formula in series.s


!   -----------------------------------------------------------------
!   MATH
  _pcFier = 10000                               ! DO NOT CHANGE, used to set drift and Std percentages
 
 
!   -----------------------------------------------------------------
!   LOOPS

 ! MONTECARLO
    !   The Montecarlo trajectories amount to H*L
    ! Neither should exceed 16 bit unsigned
    ! Neither should exceed 32 bit unsigned, when multiplied by m_gauss
 _hMcCount = 20
 _lMcCount = 50
 
 ! PLOT
 NOP1 = 1000    ! Higher and lower parts of the waiting cycles for displaying Mc Plots
 NOP2 = 32000
 MAXMCPLT = 20  ! Total number of Montecarlo plots to display  
 

 
.SECT .TEXT
.SECT .DATA
.SECT .BSS</pre>

OPTION BEHAVIOR: THE OPTION PAYS THE DIFFERENCE BETWEEN THE UNDERLYING ASSET AND THE STRIKE IF IT IS IN THE MONEY, ZERO OTHERWISE. THERE ARE TWO KNOCK-OUT BARRIERS, A CAP AND A FLOOR: IF THE ASSET REACHES A BARRIER, THE PRICE IS FIXED UNTIL EXPIRATION.


PROGRAM DESCRIPTION:

Whenever possible, multiplications are done before divisions, in order to contain remainder approximations.

The user helps generating 3 initial numbers by keeping the Enter key pressed for a while (too small a time is not allowed). The lowest binary digits of those initial numbers form the basis for new numbers. Three different combinations of those basis are assembled to form 3 different numbers, which are less predictable than the original ones. These new numbers are 3 random seeds for 3 Linear Congruential Generators. Three sequences are thus generated: they contain uniform pseudo-random variables. The 3 sequences interact to generate one longer-period sequence (still uniforms). This one is used as a source of randomness for all the simulations. Next: 48 uniform variables are used at a time to yeld an approximated gaussian-distributed random variable, relying on the Central Limit theorem. The number 48 is a convenient number, it being: 2 squared, times 12. Still, it produces better gaussians than 12. 12 is related to the uniform distribution standard deviation; 4 saves us a square-root computation, which would complicate matters in an environment where floating-point arithmetic is not available. The gaussian variable is appropriately standardized and scaled (the values must fit in the registers) and used to form a Geometric Brownian Motion for the prices of the asset. Then barriers are applied, limiting the asset prices. A payoff is computed, relative to a strike price. Using Montecarlo, many payoffs are averaged and discounted to price the derivative. Some of the asset trajectories are shown in an animated plot, in the text-based console. Prices are scaled and matched to a row number. If the columns allowed are fewer than the whole trajectory, the plot is split into as many parts as needed. The trajectory is rescaled for every example, so that each time the maximum and minimum values are placed on the upper and lower rows of the plot. The strike price is shown as a heavy line: ======

 

 

 

 

 

 

 


PARAMETERS FOR THE PROGRAM

USER MODIFIABLE PARAMETERS [usrPrms.h] file: The first section of the file contains the parameters that determine the asset trajectory in time and the behavior of the derivative. The user can modify them. _days: the number of days the simulation will cover. E.g. Tn = 252 _startPr: price of the asset in T0. It is also the basis for other transformations. 20000 performs better in divisions (smaller remainders), 10000 is nicer _bpDrift: drift of the asset, expressed in basis points, relative to the prices of the GBM _bpReqStd: the standard deviation which the simulator is required to generate for the asset _put: whether the option is a put or a call _strike: the strike price _cap: the upper barrier _floor: the lower barrier

DEBUG AND PROGRAM: Parameters used for debugging and fine-tuning the program. _nRows, _nCols: rows and columns to display the plot. _dbgSd1, _dbgSd2, _dbgSd3: random seeds used to bypass the user-generation section.

CONSTANTS [consts.h] file: This file should need no modifications. It is worth mentioning the LOOPS part. Two variables are used to overcome the 16-bit constraint on the CX register. _hMcCount * _lMcCount is the number of trajectories Montecarlo runs on. NOP1 * NOP2 is the number of cycles the program skips between the demonstrative plots.


RUN AS: ./s88 main

ASSEMBLE AS: ./as88 main prFuncs series genrand vars mtCarlo prTraj

Note: Automatically translated from Italian.