tarf_monte_carlo 3.56 → 3.61

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: e049edbb4b08e73240bcefcb197f9f29d9d7491c6dba1d4c97130af405cfbfcf
4
- data.tar.gz: 92ff0b4ad25f0e871ccbaa6e14f62e5eaabbe1500b9a7724bda47bd09839ee23
3
+ metadata.gz: 157664b6dfd86644998da3438b564db2580b1f4503bb602ab321bf2b4863d63c
4
+ data.tar.gz: aec6753b1e912651e2c04357d833dbacc920442a32956993d25f37c1b07de19d
5
5
  SHA512:
6
- metadata.gz: 4d2514c2a003eb7d117519e3c17e4d68bc00dec97ffc4bb2ac3498076b80612c15df901d94faee6087552876ba050899fe0d7beeee7b62bbd192777f4f9888e8
7
- data.tar.gz: 71fa095eb08d47d02335e63d4800b20c9714215aaa17d3993567ff7d2ae861acbae22499490ae852727018908a36da319eaec08e1a1413ad00a4e8a4774bf20d
6
+ metadata.gz: b6f807aca25b23bef95d81eea2a6bf938f9a9a607e16ffdb5d5b2ae8179555c23ef052d67ac12edef921a12ce6657035b7347d3f1b763163af847f2851b132bd
7
+ data.tar.gz: 7e30863271c763a7b57033c5d24434a1b20f908e9627e3e4ec6c2cc533c28b3f0243e67ab2511896d9beae4d83544069d494dbae815785a8fd3f0962f935ccd9
@@ -49,6 +49,8 @@
49
49
  #define FX_AMERICAN_BARRIER_KIKO_UNTIL_KI 18
50
50
  #define FX_AMERICAN_BARRIER_BINARY_IN_DISCRETE 19
51
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
52
54
 
53
55
  #define DATAPOINTS 200 // data for plotting
54
56
  #define BARRIER_DP 4 // data for plotting
@@ -64,7 +66,6 @@ VALUE cTarfMonteCarlo = Qnil;
64
66
  // Prototype for the initialization method - Ruby calls this, not you
65
67
  void Init_tarf_monte_carlo();
66
68
  double european_payoff(double, double, int, int, double);
67
- double get_equivalent_notional(int, double, float);
68
69
  double get_equivalent_rebate(int, double, float, int);
69
70
  bool barrier_variations(int);
70
71
  bool double_barrier_variations(int);
@@ -97,17 +98,13 @@ double european_payoff(double strike, double spot, int cp_sign, int dir_sign, do
97
98
  return (diff * notional * dir_sign);
98
99
  }
99
100
 
100
- double get_equivalent_notional(int conversion_sign, double notional, float rate){
101
- return (conversion_sign == 1) ? (notional / rate) : notional;
102
- }
103
-
104
101
  double get_equivalent_rebate(int conversion_sign, double rebate, float rate, int dir_sign){
105
102
  double total = (conversion_sign == 1) ? (rebate * rate) : rebate;
106
103
  return (dir_sign * total);
107
104
  }
108
105
 
109
106
  bool barrier_variations(int KType){
110
- 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);
107
+ 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);
111
108
  }
112
109
 
113
110
  bool double_barrier_variations(int KType){
@@ -214,6 +211,7 @@ VALUE method_run_monte_carlo( VALUE self, VALUE args ) {
214
211
  //
215
212
  // first create a 1-D array of pointers, and then, for each array entry, create another 1-D array.
216
213
  //
214
+ double payoffmet[SCount];
217
215
  double **metrics;
218
216
  if (barrier_variations(KType)){
219
217
  metrics = ( double** ) malloc( BARRIER_DP * sizeof(double*) );
@@ -238,6 +236,8 @@ VALUE method_run_monte_carlo( VALUE self, VALUE args ) {
238
236
  // run simulations loop
239
237
  for( sim_count = 0; sim_count < SCount; sim_count += 2 ) {
240
238
  // initial spot rate for each iteration would be current spot rate
239
+ payoffmet[sim_count] = 0;
240
+ payoffmet[sim_count + 1] = 0;
241
241
  double Spot = S, Spot_dash = S;
242
242
  double sim[NL], sim_pos[NL], sim_neg[NL], sim_dash[NL], sim_dash_pos[NL], sim_dash_neg[NL];
243
243
 
@@ -268,7 +268,7 @@ VALUE method_run_monte_carlo( VALUE self, VALUE args ) {
268
268
  Spot = Spot * exp( drift + vSqrdt * eps );
269
269
  Spot_dash = Spot_dash * exp( drift + vSqrdt * eps_dash );
270
270
 
271
- 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){
271
+ 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){
272
272
  profit_loss = Spot;
273
273
  profit_loss_dash = Spot_dash;
274
274
 
@@ -451,14 +451,14 @@ VALUE method_run_monte_carlo( VALUE self, VALUE args ) {
451
451
  double ko_so_far = K, ko_so_far_dash = K;
452
452
  if(KType == FX_AMERICAN_BARRIER_KNOCKIN_DISCRETE || KType == FX_AMERICAN_BARRIER_WINDOW_KNOCKIN){
453
453
  if(knockedLeg >= 0){
454
- double equivalent_notional = get_equivalent_notional(conversion_sign, ( *( Ns_array + knockedLeg ) ), sim[NL-1]);
454
+ double equivalent_notional = *( Ns_array + knockedLeg );
455
455
  sim_pos[NL-1] = european_payoff(( *( Xs_array + (knockedLeg) ) ), sim[NL-1], cp_sign, dir_sign, equivalent_notional);
456
456
  }
457
457
  else{
458
458
  sim_pos[NL-1] = get_equivalent_rebate(rebate_conversion_sign, ( *( Rebate_array + 0 ) ), sim[NL-1], dir_sign);
459
459
  }
460
460
  if(knockedLeg_dash >= 0 ){
461
- double equivalent_notional = get_equivalent_notional(conversion_sign, ( *( Ns_array + knockedLeg_dash ) ), sim_dash[NL-1]);
461
+ double equivalent_notional = *( Ns_array + knockedLeg_dash );
462
462
  sim_dash_pos[NL-1] = european_payoff(( *( Xs_array + (knockedLeg_dash) ) ), sim_dash[NL-1], cp_sign, dir_sign, equivalent_notional);
463
463
  }
464
464
  else{
@@ -472,35 +472,83 @@ VALUE method_run_monte_carlo( VALUE self, VALUE args ) {
472
472
  metrics[1][point_pos+1] = (knockedLeg_dash >= 0) ? ( *( Xs_array + (knockedLeg_dash) ) ) : 0;
473
473
  metrics[3][point_pos+1] = knockedLeg_dash;
474
474
  }
475
- } else if(KType == FX_AMERICAN_BARRIER_BINARY_IN_DISCRETE){
475
+ } else if(KType == FX_AMERICAN_BARRIER_BINARY_IN_DISCRETE || KType == FX_AMERICAN_BARRIER_BINARY_CALLPUT_IN_DISCRETE){
476
476
  if(knockedLeg >= 0){
477
477
  int legIndex = (CP == 2) ? knockedLeg : (NL - 1);
478
- sim_pos[legIndex] = get_equivalent_rebate(rebate_conversion_sign, ( *( Rebate_array + 0 ) ), sim[legIndex], dir_sign);
478
+ int itm = true;
479
+ if (CP <= 1){
480
+ double tempPayOff = european_payoff(( *( Xs_array + legIndex ) ), sim[NL-1], cp_sign, dir_sign, 1);
481
+ if(tempPayOff == 0){
482
+ itm = false;
483
+ }
484
+ }
485
+ if (itm){
486
+ sim_pos[legIndex] = get_equivalent_rebate(rebate_conversion_sign, ( *( Rebate_array + 0 ) ), sim[legIndex], dir_sign);
487
+ }
479
488
  }
480
489
 
481
490
  if(knockedLeg_dash >= 0){
482
491
  int legIndex_dash = (CP == 2) ? knockedLeg_dash : (NL - 1);
483
- sim_dash_pos[legIndex_dash] = get_equivalent_rebate(rebate_conversion_sign, ( *( Rebate_array + 0 ) ), sim_dash[legIndex_dash], dir_sign);
492
+ int itm = true;
493
+ if (CP <= 1){
494
+ double tempPayOff = european_payoff(( *( Xs_array + legIndex_dash ) ), sim_dash[NL-1], cp_sign, dir_sign, 1);
495
+ if(tempPayOff == 0){
496
+ itm = false;
497
+ }
498
+ }
499
+ if (itm){
500
+ sim_dash_pos[legIndex_dash] = get_equivalent_rebate(rebate_conversion_sign, ( *( Rebate_array + 0 ) ), sim_dash[legIndex_dash], dir_sign);
501
+ }
502
+ }
503
+ if ((point_pos < DATAPOINTS) && (sim_count % INTERVAL) == 0){
504
+ metrics[0][point_pos] = sim[NL-1];
505
+ metrics[1][point_pos] = *( Xs_array + 0 );
506
+ metrics[0][point_pos+1] = sim_dash[NL-1];
507
+ metrics[1][point_pos+1] = *( Xs_array + 0 );
484
508
  }
485
- } else if(KType == FX_AMERICAN_BARRIER_BINARY_OUT_DISCRETE){
509
+ } else if(KType == FX_AMERICAN_BARRIER_BINARY_OUT_DISCRETE || KType == FX_AMERICAN_BARRIER_BINARY_CALLPUT_OUT_DISCRETE){
486
510
  if(knockedLeg == -1){
487
- sim_pos[NL - 1] = get_equivalent_rebate(rebate_conversion_sign, ( *( Rebate_array + 0 ) ), sim[NL - 1], dir_sign);
511
+ int itm = true;
512
+ if (CP <= 1){
513
+ double tempPayOff = european_payoff(( *( Xs_array + 0 ) ), sim[NL-1], cp_sign, dir_sign, 1);
514
+ if(tempPayOff == 0){
515
+ itm = false;
516
+ }
517
+ }
518
+ if (itm){
519
+ sim_pos[NL - 1] = get_equivalent_rebate(rebate_conversion_sign, ( *( Rebate_array + 0 ) ), sim[NL - 1], dir_sign);
520
+ }
488
521
  }
489
522
 
490
523
  if(knockedLeg_dash == -1){
491
- sim_dash_pos[NL - 1] = get_equivalent_rebate(rebate_conversion_sign, ( *( Rebate_array + 0 ) ), sim_dash[NL - 1], dir_sign);
524
+ int itm = true;
525
+ if (CP <= 1){
526
+ double tempPayOff = european_payoff(( *( Xs_array + 0 ) ), sim_dash[NL-1], cp_sign, dir_sign, 1);
527
+ if(tempPayOff == 0){
528
+ itm = false;
529
+ }
530
+ }
531
+ if (itm){
532
+ sim_dash_pos[NL - 1] = get_equivalent_rebate(rebate_conversion_sign, ( *( Rebate_array + 0 ) ), sim_dash[NL - 1], dir_sign);
533
+ }
534
+ }
535
+ if ((point_pos < DATAPOINTS) && (sim_count % INTERVAL) == 0){
536
+ metrics[0][point_pos] = sim[NL-1];
537
+ metrics[1][point_pos] = *( Xs_array + 0 );
538
+ metrics[0][point_pos+1] = sim_dash[NL-1];
539
+ metrics[1][point_pos+1] = *( Xs_array + 0 );
492
540
  }
493
541
  } else if(KType == FX_AMERICAN_BARRIER_KIKO_UNTIL_EXP){
494
542
  if(knockedLeg2 >= 0){
495
543
  sim_pos[NL-1] = get_equivalent_rebate(rebate_conversion_sign, ( *( Rebate_array + 0 ) ), sim[NL-1], dir_sign);
496
544
  } else if(knockedLeg >= 0) {
497
- double equivalent_notional = get_equivalent_notional(conversion_sign, ( *( Ns_array + knockedLeg ) ), sim[NL-1]);
545
+ double equivalent_notional = *( Ns_array + knockedLeg );
498
546
  sim_pos[NL-1] = european_payoff(( *( Xs_array + (knockedLeg) ) ), sim[NL-1], cp_sign, dir_sign, equivalent_notional);
499
547
  }
500
548
  if(knockedLeg2_dash >= 0){
501
549
  sim_dash_pos[NL-1] = get_equivalent_rebate(rebate_conversion_sign, ( *( Rebate_array + 0 ) ), sim_dash[NL-1], dir_sign);
502
550
  } else if(knockedLeg_dash >= 0) {
503
- double equivalent_notional = get_equivalent_notional(conversion_sign, ( *( Ns_array + knockedLeg_dash ) ), sim_dash[NL-1]);
551
+ double equivalent_notional = *( Ns_array + knockedLeg_dash );
504
552
  sim_dash_pos[NL-1] = european_payoff(( *( Xs_array + (knockedLeg_dash) ) ), sim_dash[NL-1], cp_sign, dir_sign, equivalent_notional);
505
553
  }
506
554
 
@@ -515,7 +563,7 @@ VALUE method_run_monte_carlo( VALUE self, VALUE args ) {
515
563
  } else if(KType == FX_AMERICAN_BARRIER_KIKO_UNTIL_KI){
516
564
  if(knockedLeg >= 0 && knockedLeg2 >= 0){
517
565
  if(knockedLeg < knockedLeg2){
518
- double equivalent_notional = get_equivalent_notional(conversion_sign, ( *( Ns_array + knockedLeg ) ), sim[NL-1]);
566
+ double equivalent_notional = *( Ns_array + knockedLeg );
519
567
  sim_pos[NL-1] = european_payoff(( *( Xs_array + (knockedLeg) ) ), sim[NL-1], cp_sign, dir_sign, equivalent_notional);
520
568
  } else {
521
569
  sim_pos[knockedLeg2] = get_equivalent_rebate(rebate_conversion_sign, ( *( Rebate_array + 0 ) ), sim[knockedLeg2], dir_sign);
@@ -523,13 +571,13 @@ VALUE method_run_monte_carlo( VALUE self, VALUE args ) {
523
571
  } else if(knockedLeg2 >= 0){
524
572
  sim_pos[knockedLeg2] = get_equivalent_rebate(rebate_conversion_sign, ( *( Rebate_array + 0 ) ), sim[knockedLeg2], dir_sign);
525
573
  } else if(knockedLeg >= 0) {
526
- double equivalent_notional = get_equivalent_notional(conversion_sign, ( *( Ns_array + knockedLeg ) ), sim[NL-1]);
574
+ double equivalent_notional = *( Ns_array + knockedLeg );
527
575
  sim_pos[NL-1] = european_payoff(( *( Xs_array + (knockedLeg) ) ), sim[NL-1], cp_sign, dir_sign, equivalent_notional);
528
576
  }
529
577
 
530
578
  if(knockedLeg_dash >= 0 && knockedLeg2_dash >= 0){
531
579
  if(knockedLeg_dash < knockedLeg2_dash){
532
- double equivalent_notional = get_equivalent_notional(conversion_sign, ( *( Ns_array + knockedLeg_dash ) ), sim_dash[NL-1]);
580
+ double equivalent_notional = *( Ns_array + knockedLeg_dash );
533
581
  sim_dash_pos[NL-1] = european_payoff(( *( Xs_array + (knockedLeg_dash) ) ), sim_dash[NL-1], cp_sign, dir_sign, equivalent_notional);
534
582
  } else {
535
583
  sim_dash_pos[knockedLeg2_dash] = get_equivalent_rebate(rebate_conversion_sign, ( *( Rebate_array + 0 ) ), sim_dash[knockedLeg2_dash], dir_sign);
@@ -537,7 +585,7 @@ VALUE method_run_monte_carlo( VALUE self, VALUE args ) {
537
585
  } else if(knockedLeg2_dash >= 0){
538
586
  sim_dash_pos[knockedLeg2_dash] = get_equivalent_rebate(rebate_conversion_sign, ( *( Rebate_array + 0 ) ), sim_dash[knockedLeg2_dash], dir_sign);
539
587
  } else if(knockedLeg_dash >= 0) {
540
- double equivalent_notional = get_equivalent_notional(conversion_sign, ( *( Ns_array + knockedLeg_dash ) ), sim_dash[NL-1]);
588
+ double equivalent_notional = *( Ns_array + knockedLeg_dash );
541
589
  sim_dash_pos[NL-1] = european_payoff(( *( Xs_array + (knockedLeg_dash) ) ), sim_dash[NL-1], cp_sign, dir_sign, equivalent_notional);
542
590
  }
543
591
 
@@ -554,14 +602,14 @@ VALUE method_run_monte_carlo( VALUE self, VALUE args ) {
554
602
  sim_pos[knockedLeg] = get_equivalent_rebate(rebate_conversion_sign, ( *( Rebate_array + knockedLeg ) ), sim[knockedLeg], dir_sign);
555
603
  }
556
604
  else{
557
- double equivalent_notional = get_equivalent_notional(conversion_sign, ( *( Ns_array + 0 ) ), sim[NL-1]);
605
+ double equivalent_notional = *( Ns_array + 0 );
558
606
  sim_pos[NL-1] = european_payoff(( *( Xs_array + 0 ) ), sim[NL-1], cp_sign, dir_sign, equivalent_notional);
559
607
  }
560
608
  if(knockedLeg_dash >= 0 ){
561
609
  sim_dash_pos[knockedLeg_dash] = get_equivalent_rebate(rebate_conversion_sign, ( *( Rebate_array + knockedLeg_dash ) ), sim[knockedLeg_dash], dir_sign);
562
610
  }
563
611
  else{
564
- double equivalent_notional = get_equivalent_notional(conversion_sign, ( *( Ns_array + 0 ) ), sim_dash[NL-1]);
612
+ double equivalent_notional = *( Ns_array + 0 );
565
613
  sim_dash_pos[NL-1] = european_payoff(( *( Xs_array + 0 ) ), sim_dash[NL-1], cp_sign, dir_sign, equivalent_notional);
566
614
  }
567
615
 
@@ -701,6 +749,8 @@ VALUE method_run_monte_carlo( VALUE self, VALUE args ) {
701
749
  pvs_neg[sim_count] = sim_neg_sum;
702
750
  pvs_neg[sim_count + 1] = sim_dash_neg_sum;
703
751
 
752
+ payoffmet[sim_count] = sim_pos_sum;
753
+ payoffmet[sim_count + 1] = sim_dash_pos_sum;
704
754
 
705
755
  if (barrier_variations(KType)){
706
756
  if ((point_pos < DATAPOINTS) && (sim_count % INTERVAL) == 0){
@@ -776,12 +826,18 @@ VALUE method_run_monte_carlo( VALUE self, VALUE args ) {
776
826
  }
777
827
  }
778
828
 
829
+
830
+ VALUE py_final_metrics = rb_ary_new();
831
+ for(metric = 0; metric < SCount; metric++) {
832
+ rb_ary_push(py_final_metrics, DBL2NUM(payoffmet[metric]));
833
+ }
779
834
  // rb_p(rb_str_new2("Generating output hash"));
780
835
  VALUE final_pvs = rb_hash_new();
781
836
  rb_hash_aset(final_pvs, rb_str_new2("positive_pv"), DBL2NUM( pvs_pos_sum / SCount ));
782
837
  rb_hash_aset(final_pvs, rb_str_new2("negative_pv"), DBL2NUM( pvs_neg_sum / SCount ));
783
838
  rb_hash_aset(final_pvs, rb_str_new2("total_pv"), DBL2NUM( (pvs_neg_sum + pvs_pos_sum) / SCount ));
784
839
  rb_hash_aset(final_pvs, rb_str_new2("metrics"), final_metrics);
840
+ rb_hash_aset(final_pvs, rb_str_new2("payoffmetrics"), py_final_metrics);
785
841
 
786
842
  //
787
843
  // free your arrays from memory once you're done using them
@@ -3,5 +3,5 @@
3
3
  # gem yank tarf_monte_carlo -v 2.3
4
4
 
5
5
  module TarfMonteCarlo
6
- VERSION = "3.56"
6
+ VERSION = "3.61"
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.56'
4
+ version: '3.61'
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-12 00:00:00.000000000 Z
11
+ date: 2020-10-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler