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.
Si tratta di un progetto di una certa dimensione che riproduce, in codice Assembly, alcuni dei concetti studiati nel corso di Laurea Magistrale in Finanza quantitativa. L’ho realizzato allo scopo di prendere maggiore confidenza con il basso livello della programmazione.
Allo scopo di contenere la complessità del progetto sono state introdotte alcune semplificazioni matematiche e finanziarie. In particolare si usa un Moto Browniano Geometrico, mentre sarebbero più opportuni modelli come quello di Black and Scholes. Vengono semplificate anche le proprietà della gaussiana – con varianza giornaliera – e la modalità di calcolo con cui si sconta il prezzo finale.
Il codice è depositato presso https://github.com/giosds/giasm
Per lo sviluppo è stato impiegato l’interprete 8088 Assembler and Tracer Toolkit: https://github.com/StoDevX/as88
Più sotto, in lingua inglese, è riportata la documentazione presente all’interno del codice.
Caratteristiche principali:
- Generazione di numeri pseudocasuali, con sequenza differente ad ogni esecuzione
- Pricing di un’opzione con doppia barriera, via Montecarlo
- Rappresentazione grafica animata del metodo Montecarlo
- Generazione della traiettoria casuale di un ipotetico sottostante e comunicazione all’utente del profitto (o perdita) generato da un contratto derivato
- Grafica su console testuale
- Numerose limitazioni dovute all’architettura impiegata: in particolare non sono possibili operazioni in aritmetica floating point (solo integer), i registri sono a 16 bit, solo 7 system-library calls disponibili
- Ogni elemento del programma è parametrizzato. Per ragioni computazionali o di altro tipo (es. rendere assolute o relative fra di loro certe componenti ) i parametri finanziari in alcuni casi subiscono alcune manipolazioni, di cui si occupa l’algoritmo
Il primo file chiama le necessarie funzioni, che si trovano in altri files collegati.
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.s 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> |
GENERAZIONE RANDOMNESS
Le limitazioni dell’interprete non consentono l’accesso al timer del sistema o ad altre fonti di casualità, si utilizza quindi un’interazione con l’utente.
- All’utente si chiede di tenere premuto il tasto invio per un certo tempo, quindi di premere un tasto differente. Viene così generato e contato un certo numero di caratteri (‘\n’); per rendere più realistica l’interazione, una pressione troppo breve resetta il conteggio. Naturalmente sarebbe possibile contare le singole pressioni dell’Enter, ma non si tratta di un’applicazione crittografica…
- Tre numeri vengono generati come sopra. I 4 bit di ordine inferiore (corrispondenti a MOD 16, meno gestibili dall’utente) sono conservati, per ciascuno dei 3 numeri. Vengono poi ricomposti nelle diverse possibili combinazioni in modo da ricreare 3 nuovi numeri a 12 bit, indipendenti dalla durata delle pressioni su Enter. Questi sono i seed che alimentano l’algoritmo di generazione numeri casuali
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> |
A partire dai seed, varie sequenze sono generate.
- Tre linear congruential generators creano una serie di 48 numeri uniformi.
- Queste 3 serie interagiscono per alimentare il seed di una quarta serie di 48 numeri, che avrà periodo più lungo di ciascuna delle precedenti
- Si esegue una sommatoria sui 48 numeri, che restituirà una variabile casuale distribuita in modo gaussiano
- Si standardizza la gaussiana
- Nelle precedenti operazioni si incontrano difficoltà relative alla dimensione limitata dei registri (occorre utilizzare il riporto) e dell’assenza di aritmetica decimale. Le formule vengono adattate per risolvere a monte alcuni problemi
Il nuovo numero gaussiano sarà la componente random di un Moto Browniano Geometrico. E’ la traiettoria di un ipotetico sottostante. Vengono generati tanti numeri gaussiani quanti sono gli intervalli nel periodo considerato (secondo i parametri forniti: 252 giorni).
- Questa componente gaussiana viene modificata in media e varianza secondo i parametri finanziari richiesti (drift e varianza giornaliera)
- Rimane necessario limitare il range di tale moto browniano, per ridurre la complessità dell’aritmetica. Vengono dunque comode le barriere
- Le barriere, cap e floor, se toccate fissano il prezzo del sottostante fino alla fine del periodo
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 ! ---> (200*sum(...48...)/2)/m_gauss -12*200 + 0 ! --->(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> |
Vengono generate tante sequenze quante sono le iterazioni richieste per il Montecarlo.
- Ogni traiettoria genera un Payoff, dipendente dai parametri finanziari (livelli di strike e barriere)
- Le iterazioni, superando i bit consentiti dal registro CX, richiedono un doppio ciclo. Anche le somme dei Payoff supererebbero i limiti consentiti
- Nel ciclo interno si calcola la media dei Payoff; in quello esterno la media delle medie
- Il Payoff medio viene attualizzato secondo un tasso 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 CALL pr4Seq ! THE LAST RUN OF UNIFORM SEQUENCES ! genfuncs.s 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 (> 16 bit) is achieved ! by running 2 loops ! ! EXPECTS the number of runs to be pushed on the stack: ! 2int < 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 >= 0 MOV AX, BX ! Price back to AX RET .SECT .DATA .SECT .BSS </pre> |
I valori di ogni traiettoria saranno disegnati sull’interfaccia testuale, per mezzo di caratteri ASCII.
- Una plot area è caratterizzata da un certo numero (impostabile) di righe e colonne. Se la traiettoria supera il numero di colonne previsto, viene generata una plot area aggiuntiva.
- Tutti i valori della traiettoria vengono scalati in modo da trovarsi all’interno di tale matrice – la plot area. Il range dei prezzi viene segmentato nel numero di colonne disponibili, in modo che tutta la traiettoria sia sempre visibile (e non generi overflow nella matrice, costituita da uno spazio di memoria lungo n_colonne * n_righe).
- Durante la simulazione Montecarlo alcune traiettorie sono disegnate. Affinchè restino visibili per un tempo sufficiente, un alto numero di NOP viene inserito fra l’una e l’altra.
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 > 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 --> 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> |
L’interazione utente prevede, oltre alla generazione delle componenti casuali, la scelta della direzione: se acquistare una PUT o una CALL. Dopo avere prezzato l’opzione, sarà generata un’ultima traiettoria; se ne ricava e il Payoff; si sottrae il costo del derivato e si comunica l’esito.
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 -> 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 -> 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 ! ----> 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 ! ---->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 ! ---->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 " ! ---->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>>> %d.%02d$ <<<Press ENTER to exit the program...\n" msg12b: .ASCIZ "\n\n\nTHIS IS YOUR LOSS:\n\n>>> %d.%02d$ <<<\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
LINK AS: ./as88 main prFuncs series genrand vars mtCarlo prTraj