tarf_monte_carlo 3.52 → 3.57

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 981ac06c2a4fa081cd670f85bc08c2efc714ed6d057618b3347b0e2d6596a84b
4
- data.tar.gz: 9127b590ee3001d5ca31cfb97428f9a479b5f598f7376fe004eb4c3613e7c564
3
+ metadata.gz: 37cf728f754098494cffed6ce0f9f8c3dde4e593702a748cdc8bca2d1c5182cd
4
+ data.tar.gz: 76e9c21b88d3ecb5925c525420fc704fcf8e8cf992b2db3bd9f4367c1d20396c
5
5
  SHA512:
6
- metadata.gz: fb8304019cfe8d1eed96bf4a7535ea21399b4f6d58e9eb649034a1b8ee6423c12d3b4ea18ee922e8b8351466c1f05f58d96a8999ecf65367a3845bbac2115586
7
- data.tar.gz: 3cedfd64107a5fd9639509375eda6b42fda41d04f7339aa2d5a1eae24ec16da62a9f5623e67557e0b8f0b70a979f15c86a01469cdffb9045be3cb2654b36aba3
6
+ metadata.gz: fb5a2d931a8ea07cf8fa49b2ca4ef2341474fbf59431b2fb16c8188df43018c146fd70dbb0f907ce921657b01aca8c4e35600ded2075e5bd16d2435619565671
7
+ data.tar.gz: 490bacf7090a637d5c3b9f54176c80d5419f13f5b8e4320634977bc1815b3f8430dca1072c347b07b268cdec0fc152959e7d4d2f4d459dc0a3c6164516ffb5b5
@@ -45,6 +45,12 @@
45
45
  #define FX_AMERICAN_BARRIER_KNOCKOUT_DISCRETE 14
46
46
  #define FX_AMERICAN_BARRIER_WINDOW_KNOCKIN 15
47
47
  #define FX_AMERICAN_BARRIER_WINDOW_KNOCKOUT 16
48
+ #define FX_AMERICAN_BARRIER_KIKO_UNTIL_EXP 17
49
+ #define FX_AMERICAN_BARRIER_KIKO_UNTIL_KI 18
50
+ #define FX_AMERICAN_BARRIER_BINARY_IN_DISCRETE 19
51
+ #define FX_AMERICAN_BARRIER_BINARY_OUT_DISCRETE 20
52
+ #define FX_AMERICAN_BARRIER_BINARY_CALLPUT_IN_DISCRETE 21
53
+ #define FX_AMERICAN_BARRIER_BINARY_CALLPUT_OUT_DISCRETE 22
48
54
 
49
55
  #define DATAPOINTS 200 // data for plotting
50
56
  #define BARRIER_DP 4 // data for plotting
@@ -63,6 +69,7 @@ double european_payoff(double, double, int, int, double);
63
69
  double get_equivalent_notional(int, double, float);
64
70
  double get_equivalent_rebate(int, double, float, int);
65
71
  bool barrier_variations(int);
72
+ bool double_barrier_variations(int);
66
73
  // Prototype for our methods - methods are prefixed by 'method_' here
67
74
  VALUE method_box_muller( VALUE );
68
75
  VALUE method_run_monte_carlo( VALUE, VALUE );
@@ -98,11 +105,15 @@ double get_equivalent_notional(int conversion_sign, double notional, float rate)
98
105
 
99
106
  double get_equivalent_rebate(int conversion_sign, double rebate, float rate, int dir_sign){
100
107
  double total = (conversion_sign == 1) ? (rebate * rate) : rebate;
101
- return (-1 * dir_sign * total);
108
+ return (dir_sign * total);
102
109
  }
103
110
 
104
111
  bool barrier_variations(int KType){
105
- return (KType == FX_AMERICAN_BARRIER_KNOCKIN_DISCRETE || KType == FX_AMERICAN_BARRIER_KNOCKOUT_DISCRETE || KType == FX_AMERICAN_BARRIER_WINDOW_KNOCKIN || KType == FX_AMERICAN_BARRIER_WINDOW_KNOCKOUT);
112
+ return (KType == FX_AMERICAN_BARRIER_KNOCKIN_DISCRETE || KType == FX_AMERICAN_BARRIER_KNOCKOUT_DISCRETE || KType == FX_AMERICAN_BARRIER_WINDOW_KNOCKIN || KType == FX_AMERICAN_BARRIER_WINDOW_KNOCKOUT || KType == FX_AMERICAN_BARRIER_KIKO_UNTIL_EXP || KType == FX_AMERICAN_BARRIER_KIKO_UNTIL_KI || KType == FX_AMERICAN_BARRIER_BINARY_IN_DISCRETE || KType == FX_AMERICAN_BARRIER_BINARY_OUT_DISCRETE || KType == FX_AMERICAN_BARRIER_BINARY_CALLPUT_IN_DISCRETE || KType == FX_AMERICAN_BARRIER_BINARY_CALLPUT_OUT_DISCRETE);
113
+ }
114
+
115
+ bool double_barrier_variations(int KType){
116
+ return (KType == FX_AMERICAN_BARRIER_WINDOW_KNOCKIN || KType == FX_AMERICAN_BARRIER_WINDOW_KNOCKOUT || KType == FX_AMERICAN_BARRIER_KIKO_UNTIL_EXP || KType == FX_AMERICAN_BARRIER_KIKO_UNTIL_KI);
106
117
  }
107
118
  // main method for running monte carlo simulation from sidekiq worker/outside method
108
119
  VALUE method_run_monte_carlo( VALUE self, VALUE args ) {
@@ -122,6 +133,7 @@ VALUE method_run_monte_carlo( VALUE self, VALUE args ) {
122
133
  int NL = NUM2INT( rb_hash_aref(MCInputs, rb_str_new2("legs_count")) );
123
134
  int BS = NUM2INT( rb_hash_aref(MCInputs, rb_str_new2("buy_sell")) );
124
135
  double K = NUM2DBL( rb_hash_aref(MCInputs, rb_str_new2("knockout")) );
136
+ int CP = NUM2DBL( rb_hash_aref(MCInputs, rb_str_new2("callput")) );
125
137
  int KType = NUM2INT( rb_hash_aref(MCInputs, rb_str_new2("knockout_type")) );
126
138
  double S = NUM2DBL( rb_hash_aref(MCInputs, rb_str_new2("spot_rate")) );
127
139
  int Ko_compare_mult = NUM2INT( rb_hash_aref(MCInputs, rb_str_new2("multiplier")) );
@@ -195,7 +207,7 @@ VALUE method_run_monte_carlo( VALUE self, VALUE args ) {
195
207
  for (leg = 0; leg < NL; ++leg) {
196
208
  Barrier_array[leg] = NUM2DBL( rb_ary_entry(Brs, leg) );
197
209
  Rebate_array[leg] = NUM2DBL( rb_ary_entry(Rbts, leg) );
198
- if(KType == FX_AMERICAN_BARRIER_WINDOW_KNOCKIN || KType == FX_AMERICAN_BARRIER_WINDOW_KNOCKOUT){
210
+ if(double_barrier_variations(KType)){
199
211
  Barrier2_array[leg] = NUM2DBL( rb_ary_entry(Brs2, leg) );
200
212
  }
201
213
  }
@@ -241,8 +253,7 @@ VALUE method_run_monte_carlo( VALUE self, VALUE args ) {
241
253
  sim_dash_neg[leg] = 0.0;
242
254
  }
243
255
 
244
- int knockedLeg = -1;
245
- int knockedLeg_dash = -1;
256
+ int knockedLeg = -1, knockedLeg_dash = -1, knockedLeg2 = -1, knockedLeg2_dash = -1;
246
257
  // legs loop start
247
258
  for( leg = 0; leg < NL; ++leg ) {
248
259
  double eps, eps_dash, drift, vSqrdt, profit_loss, profit_loss_dash;
@@ -259,7 +270,7 @@ VALUE method_run_monte_carlo( VALUE self, VALUE args ) {
259
270
  Spot = Spot * exp( drift + vSqrdt * eps );
260
271
  Spot_dash = Spot_dash * exp( drift + vSqrdt * eps_dash );
261
272
 
262
- if(KType == FX_AMERICAN_BARRIER_KNOCKIN_DISCRETE || KType == FX_AMERICAN_BARRIER_KNOCKOUT_DISCRETE){
273
+ if(KType == FX_AMERICAN_BARRIER_KNOCKIN_DISCRETE || KType == FX_AMERICAN_BARRIER_KNOCKOUT_DISCRETE || KType == FX_AMERICAN_BARRIER_BINARY_IN_DISCRETE || KType == FX_AMERICAN_BARRIER_BINARY_OUT_DISCRETE || KType == FX_AMERICAN_BARRIER_BINARY_CALLPUT_IN_DISCRETE || KType == FX_AMERICAN_BARRIER_BINARY_CALLPUT_OUT_DISCRETE){
263
274
  profit_loss = Spot;
264
275
  profit_loss_dash = Spot_dash;
265
276
 
@@ -272,6 +283,23 @@ VALUE method_run_monte_carlo( VALUE self, VALUE args ) {
272
283
  if(knockedLeg_dash == -1 && knockin_dash >= 0){
273
284
  knockedLeg_dash = leg;
274
285
  }
286
+ } else if(KType == FX_AMERICAN_BARRIER_KIKO_UNTIL_KI || KType == FX_AMERICAN_BARRIER_KIKO_UNTIL_EXP){
287
+ profit_loss = Spot;
288
+ profit_loss_dash = Spot_dash;
289
+
290
+ if(knockedLeg == -1 && (Spot >= *(Barrier_array + leg))){
291
+ knockedLeg = leg;
292
+ }
293
+ if(knockedLeg_dash == -1 && (Spot_dash >= *(Barrier_array + leg))){
294
+ knockedLeg_dash = leg;
295
+ }
296
+
297
+ if(knockedLeg2 == -1 && (Spot >= *(Barrier2_array + leg))){
298
+ knockedLeg2 = leg;
299
+ }
300
+ if(knockedLeg2_dash == -1 && (Spot_dash >= *(Barrier2_array + leg))){
301
+ knockedLeg2_dash = leg;
302
+ }
275
303
  } else if(KType == FX_AMERICAN_BARRIER_WINDOW_KNOCKIN || KType == FX_AMERICAN_BARRIER_WINDOW_KNOCKOUT){
276
304
  profit_loss = Spot;
277
305
  profit_loss_dash = Spot_dash;
@@ -438,6 +466,119 @@ VALUE method_run_monte_carlo( VALUE self, VALUE args ) {
438
466
  else{
439
467
  sim_dash_pos[NL-1] = get_equivalent_rebate(rebate_conversion_sign, ( *( Rebate_array + 0 ) ), sim_dash[NL-1], dir_sign);
440
468
  }
469
+ if ((point_pos < DATAPOINTS) && (sim_count % INTERVAL) == 0){
470
+ metrics[0][point_pos] = sim[NL-1];
471
+ metrics[1][point_pos] = (knockedLeg >= 0) ? ( *( Xs_array + (knockedLeg) ) ) : 0;
472
+ metrics[3][point_pos] = knockedLeg;
473
+ metrics[0][point_pos+1] = sim_dash[NL-1];
474
+ metrics[1][point_pos+1] = (knockedLeg_dash >= 0) ? ( *( Xs_array + (knockedLeg_dash) ) ) : 0;
475
+ metrics[3][point_pos+1] = knockedLeg_dash;
476
+ }
477
+ } else if(KType == FX_AMERICAN_BARRIER_BINARY_IN_DISCRETE || KType == FX_AMERICAN_BARRIER_BINARY_CALLPUT_IN_DISCRETE){
478
+ if(knockedLeg >= 0){
479
+ int legIndex = (CP == 2) ? knockedLeg : (NL - 1);
480
+ int itm = true;
481
+ if (CP <= 1){
482
+ double tempPayOff = european_payoff(( *( Xs_array + legIndex ) ), sim[NL-1], cp_sign, dir_sign, 1);
483
+ if(tempPayOff == 0){
484
+ itm = false;
485
+ }
486
+ }
487
+ if (itm){
488
+ sim_pos[legIndex] = get_equivalent_rebate(rebate_conversion_sign, ( *( Rebate_array + 0 ) ), sim[legIndex], dir_sign);
489
+ }
490
+ }
491
+
492
+ if(knockedLeg_dash >= 0){
493
+ int legIndex_dash = (CP == 2) ? knockedLeg_dash : (NL - 1);
494
+ int itm = true;
495
+ if (CP <= 1){
496
+ double tempPayOff = european_payoff(( *( Xs_array + legIndex_dash ) ), sim_dash[NL-1], cp_sign, dir_sign, 1);
497
+ if(tempPayOff == 0){
498
+ itm = false;
499
+ }
500
+ }
501
+ if (itm){
502
+ sim_dash_pos[legIndex_dash] = get_equivalent_rebate(rebate_conversion_sign, ( *( Rebate_array + 0 ) ), sim_dash[legIndex_dash], dir_sign);
503
+ }
504
+ }
505
+ } else if(KType == FX_AMERICAN_BARRIER_BINARY_OUT_DISCRETE || KType == FX_AMERICAN_BARRIER_BINARY_CALLPUT_OUT_DISCRETE){
506
+ if(knockedLeg == -1){
507
+ int itm = true;
508
+ if (CP <= 1){
509
+ double tempPayOff = european_payoff(( *( Xs_array + 0 ) ), sim[NL-1], cp_sign, dir_sign, 1);
510
+ if(tempPayOff == 0){
511
+ itm = false;
512
+ }
513
+ }
514
+ if (itm){
515
+ sim_pos[NL - 1] = get_equivalent_rebate(rebate_conversion_sign, ( *( Rebate_array + 0 ) ), sim[NL - 1], dir_sign);
516
+ }
517
+ }
518
+
519
+ if(knockedLeg_dash == -1){
520
+ int itm = true;
521
+ if (CP <= 1){
522
+ double tempPayOff = european_payoff(( *( Xs_array + 0 ) ), sim_dash[NL-1], cp_sign, dir_sign, 1);
523
+ if(tempPayOff == 0){
524
+ itm = false;
525
+ }
526
+ }
527
+ if (itm){
528
+ sim_dash_pos[NL - 1] = get_equivalent_rebate(rebate_conversion_sign, ( *( Rebate_array + 0 ) ), sim_dash[NL - 1], dir_sign);
529
+ }
530
+ }
531
+ } else if(KType == FX_AMERICAN_BARRIER_KIKO_UNTIL_EXP){
532
+ if(knockedLeg2 >= 0){
533
+ sim_pos[NL-1] = get_equivalent_rebate(rebate_conversion_sign, ( *( Rebate_array + 0 ) ), sim[NL-1], dir_sign);
534
+ } else if(knockedLeg >= 0) {
535
+ double equivalent_notional = get_equivalent_notional(conversion_sign, ( *( Ns_array + knockedLeg ) ), sim[NL-1]);
536
+ sim_pos[NL-1] = european_payoff(( *( Xs_array + (knockedLeg) ) ), sim[NL-1], cp_sign, dir_sign, equivalent_notional);
537
+ }
538
+ if(knockedLeg2_dash >= 0){
539
+ sim_dash_pos[NL-1] = get_equivalent_rebate(rebate_conversion_sign, ( *( Rebate_array + 0 ) ), sim_dash[NL-1], dir_sign);
540
+ } else if(knockedLeg_dash >= 0) {
541
+ double equivalent_notional = get_equivalent_notional(conversion_sign, ( *( Ns_array + knockedLeg_dash ) ), sim_dash[NL-1]);
542
+ sim_dash_pos[NL-1] = european_payoff(( *( Xs_array + (knockedLeg_dash) ) ), sim_dash[NL-1], cp_sign, dir_sign, equivalent_notional);
543
+ }
544
+
545
+ if ((point_pos < DATAPOINTS) && (sim_count % INTERVAL) == 0){
546
+ metrics[0][point_pos] = sim[NL-1];
547
+ metrics[1][point_pos] = (knockedLeg >= 0) ? ( *( Xs_array + (knockedLeg) ) ) : 0;
548
+ metrics[3][point_pos] = knockedLeg;
549
+ metrics[0][point_pos+1] = sim_dash[NL-1];
550
+ metrics[1][point_pos+1] = (knockedLeg_dash >= 0) ? ( *( Xs_array + (knockedLeg_dash) ) ) : 0;
551
+ metrics[3][point_pos+1] = knockedLeg_dash;
552
+ }
553
+ } else if(KType == FX_AMERICAN_BARRIER_KIKO_UNTIL_KI){
554
+ if(knockedLeg >= 0 && knockedLeg2 >= 0){
555
+ if(knockedLeg < knockedLeg2){
556
+ double equivalent_notional = get_equivalent_notional(conversion_sign, ( *( Ns_array + knockedLeg ) ), sim[NL-1]);
557
+ sim_pos[NL-1] = european_payoff(( *( Xs_array + (knockedLeg) ) ), sim[NL-1], cp_sign, dir_sign, equivalent_notional);
558
+ } else {
559
+ sim_pos[knockedLeg2] = get_equivalent_rebate(rebate_conversion_sign, ( *( Rebate_array + 0 ) ), sim[knockedLeg2], dir_sign);
560
+ }
561
+ } else if(knockedLeg2 >= 0){
562
+ sim_pos[knockedLeg2] = get_equivalent_rebate(rebate_conversion_sign, ( *( Rebate_array + 0 ) ), sim[knockedLeg2], dir_sign);
563
+ } else if(knockedLeg >= 0) {
564
+ double equivalent_notional = get_equivalent_notional(conversion_sign, ( *( Ns_array + knockedLeg ) ), sim[NL-1]);
565
+ sim_pos[NL-1] = european_payoff(( *( Xs_array + (knockedLeg) ) ), sim[NL-1], cp_sign, dir_sign, equivalent_notional);
566
+ }
567
+
568
+ if(knockedLeg_dash >= 0 && knockedLeg2_dash >= 0){
569
+ if(knockedLeg_dash < knockedLeg2_dash){
570
+ double equivalent_notional = get_equivalent_notional(conversion_sign, ( *( Ns_array + knockedLeg_dash ) ), sim_dash[NL-1]);
571
+ sim_dash_pos[NL-1] = european_payoff(( *( Xs_array + (knockedLeg_dash) ) ), sim_dash[NL-1], cp_sign, dir_sign, equivalent_notional);
572
+ } else {
573
+ sim_dash_pos[knockedLeg2_dash] = get_equivalent_rebate(rebate_conversion_sign, ( *( Rebate_array + 0 ) ), sim_dash[knockedLeg2_dash], dir_sign);
574
+ }
575
+ } else if(knockedLeg2_dash >= 0){
576
+ sim_dash_pos[knockedLeg2_dash] = get_equivalent_rebate(rebate_conversion_sign, ( *( Rebate_array + 0 ) ), sim_dash[knockedLeg2_dash], dir_sign);
577
+ } else if(knockedLeg_dash >= 0) {
578
+ double equivalent_notional = get_equivalent_notional(conversion_sign, ( *( Ns_array + knockedLeg_dash ) ), sim_dash[NL-1]);
579
+ sim_dash_pos[NL-1] = european_payoff(( *( Xs_array + (knockedLeg_dash) ) ), sim_dash[NL-1], cp_sign, dir_sign, equivalent_notional);
580
+ }
581
+
441
582
  if ((point_pos < DATAPOINTS) && (sim_count % INTERVAL) == 0){
442
583
  metrics[0][point_pos] = sim[NL-1];
443
584
  metrics[1][point_pos] = (knockedLeg >= 0) ? ( *( Xs_array + (knockedLeg) ) ) : 0;
@@ -3,5 +3,5 @@
3
3
  # gem yank tarf_monte_carlo -v 2.3
4
4
 
5
5
  module TarfMonteCarlo
6
- VERSION = "3.52"
6
+ VERSION = "3.57"
7
7
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tarf_monte_carlo
3
3
  version: !ruby/object:Gem::Version
4
- version: '3.52'
4
+ version: '3.57'
5
5
  platform: ruby
6
6
  authors:
7
7
  - Vivek Routh
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-10-07 00:00:00.000000000 Z
11
+ date: 2020-10-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler