tarf_monte_carlo 3.55 → 3.60

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: '06542868a0a9e3446d59880a36f2cc1f2d46c09ecf446c71fcad3ec235b08938'
4
- data.tar.gz: a6922adce8b10804cf0b7c09e837d91736863c7f97de606d1d7bd0ec2c80fe11
3
+ metadata.gz: 3e84d65efa37c58059ce27ed5c949cf99d734804ae813840e7da6b46694394af
4
+ data.tar.gz: 54943b6268ddf6ee4f4f7ac72d4dc3fe9f8abbee1176b159fee6c35428ac106e
5
5
  SHA512:
6
- metadata.gz: 6508270dcdc5a5958d2de0aec826a3141d0a315a72561798903315b9d0b37a49f960a9376e7b302f79a408996098cb13e715096fd123a0f536a15414d06c029a
7
- data.tar.gz: 8a6fb8e1a8554fbda71200c360db164ec4bf07953f672b7bd6982f4c2b7d394c7930dac88931f801a93438568e5976be490d31d25c334beb82d8748ca18d49d9
6
+ metadata.gz: c49d6bed204c1e80f618c828dabc12febd6576c5b2e663bc3b36de24eda39c5f4d1783006ddf7996865809cb7174acaa4ed28fd353ebcef78505e1f305e75380
7
+ data.tar.gz: 5d520f207257d87a69bb9675fc3e6e36853378a0aef16c5f146a94ec2387f1de7bac75081266325a97728c80f5df8045328a2cd32599b076510d215f826c0e8a
@@ -47,6 +47,10 @@
47
47
  #define FX_AMERICAN_BARRIER_WINDOW_KNOCKOUT 16
48
48
  #define FX_AMERICAN_BARRIER_KIKO_UNTIL_EXP 17
49
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
50
54
 
51
55
  #define DATAPOINTS 200 // data for plotting
52
56
  #define BARRIER_DP 4 // data for plotting
@@ -62,7 +66,6 @@ VALUE cTarfMonteCarlo = Qnil;
62
66
  // Prototype for the initialization method - Ruby calls this, not you
63
67
  void Init_tarf_monte_carlo();
64
68
  double european_payoff(double, double, int, int, double);
65
- double get_equivalent_notional(int, double, float);
66
69
  double get_equivalent_rebate(int, double, float, int);
67
70
  bool barrier_variations(int);
68
71
  bool double_barrier_variations(int);
@@ -95,17 +98,13 @@ double european_payoff(double strike, double spot, int cp_sign, int dir_sign, do
95
98
  return (diff * notional * dir_sign);
96
99
  }
97
100
 
98
- double get_equivalent_notional(int conversion_sign, double notional, float rate){
99
- return (conversion_sign == 1) ? (notional / rate) : notional;
100
- }
101
-
102
101
  double get_equivalent_rebate(int conversion_sign, double rebate, float rate, int dir_sign){
103
102
  double total = (conversion_sign == 1) ? (rebate * rate) : rebate;
104
103
  return (dir_sign * total);
105
104
  }
106
105
 
107
106
  bool barrier_variations(int KType){
108
- 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);
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);
109
108
  }
110
109
 
111
110
  bool double_barrier_variations(int KType){
@@ -129,6 +128,7 @@ VALUE method_run_monte_carlo( VALUE self, VALUE args ) {
129
128
  int NL = NUM2INT( rb_hash_aref(MCInputs, rb_str_new2("legs_count")) );
130
129
  int BS = NUM2INT( rb_hash_aref(MCInputs, rb_str_new2("buy_sell")) );
131
130
  double K = NUM2DBL( rb_hash_aref(MCInputs, rb_str_new2("knockout")) );
131
+ int CP = NUM2DBL( rb_hash_aref(MCInputs, rb_str_new2("callput")) );
132
132
  int KType = NUM2INT( rb_hash_aref(MCInputs, rb_str_new2("knockout_type")) );
133
133
  double S = NUM2DBL( rb_hash_aref(MCInputs, rb_str_new2("spot_rate")) );
134
134
  int Ko_compare_mult = NUM2INT( rb_hash_aref(MCInputs, rb_str_new2("multiplier")) );
@@ -211,6 +211,7 @@ VALUE method_run_monte_carlo( VALUE self, VALUE args ) {
211
211
  //
212
212
  // first create a 1-D array of pointers, and then, for each array entry, create another 1-D array.
213
213
  //
214
+ double payoffmet[SCount];
214
215
  double **metrics;
215
216
  if (barrier_variations(KType)){
216
217
  metrics = ( double** ) malloc( BARRIER_DP * sizeof(double*) );
@@ -235,6 +236,8 @@ VALUE method_run_monte_carlo( VALUE self, VALUE args ) {
235
236
  // run simulations loop
236
237
  for( sim_count = 0; sim_count < SCount; sim_count += 2 ) {
237
238
  // initial spot rate for each iteration would be current spot rate
239
+ payoffmet[sim_count] = 0;
240
+ payoffmet[sim_count + 1] = 0;
238
241
  double Spot = S, Spot_dash = S;
239
242
  double sim[NL], sim_pos[NL], sim_neg[NL], sim_dash[NL], sim_dash_pos[NL], sim_dash_neg[NL];
240
243
 
@@ -265,7 +268,7 @@ VALUE method_run_monte_carlo( VALUE self, VALUE args ) {
265
268
  Spot = Spot * exp( drift + vSqrdt * eps );
266
269
  Spot_dash = Spot_dash * exp( drift + vSqrdt * eps_dash );
267
270
 
268
- if(KType == FX_AMERICAN_BARRIER_KNOCKIN_DISCRETE || KType == FX_AMERICAN_BARRIER_KNOCKOUT_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){
269
272
  profit_loss = Spot;
270
273
  profit_loss_dash = Spot_dash;
271
274
 
@@ -448,14 +451,14 @@ VALUE method_run_monte_carlo( VALUE self, VALUE args ) {
448
451
  double ko_so_far = K, ko_so_far_dash = K;
449
452
  if(KType == FX_AMERICAN_BARRIER_KNOCKIN_DISCRETE || KType == FX_AMERICAN_BARRIER_WINDOW_KNOCKIN){
450
453
  if(knockedLeg >= 0){
451
- double equivalent_notional = get_equivalent_notional(conversion_sign, ( *( Ns_array + knockedLeg ) ), sim[NL-1]);
454
+ double equivalent_notional = *( Ns_array + knockedLeg );
452
455
  sim_pos[NL-1] = european_payoff(( *( Xs_array + (knockedLeg) ) ), sim[NL-1], cp_sign, dir_sign, equivalent_notional);
453
456
  }
454
457
  else{
455
458
  sim_pos[NL-1] = get_equivalent_rebate(rebate_conversion_sign, ( *( Rebate_array + 0 ) ), sim[NL-1], dir_sign);
456
459
  }
457
460
  if(knockedLeg_dash >= 0 ){
458
- double equivalent_notional = get_equivalent_notional(conversion_sign, ( *( Ns_array + knockedLeg_dash ) ), sim_dash[NL-1]);
461
+ double equivalent_notional = *( Ns_array + knockedLeg_dash );
459
462
  sim_dash_pos[NL-1] = european_payoff(( *( Xs_array + (knockedLeg_dash) ) ), sim_dash[NL-1], cp_sign, dir_sign, equivalent_notional);
460
463
  }
461
464
  else{
@@ -469,17 +472,83 @@ VALUE method_run_monte_carlo( VALUE self, VALUE args ) {
469
472
  metrics[1][point_pos+1] = (knockedLeg_dash >= 0) ? ( *( Xs_array + (knockedLeg_dash) ) ) : 0;
470
473
  metrics[3][point_pos+1] = knockedLeg_dash;
471
474
  }
475
+ } else if(KType == FX_AMERICAN_BARRIER_BINARY_IN_DISCRETE || KType == FX_AMERICAN_BARRIER_BINARY_CALLPUT_IN_DISCRETE){
476
+ if(knockedLeg >= 0){
477
+ int legIndex = (CP == 2) ? knockedLeg : (NL - 1);
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
+ }
488
+ }
489
+
490
+ if(knockedLeg_dash >= 0){
491
+ int legIndex_dash = (CP == 2) ? knockedLeg_dash : (NL - 1);
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 );
508
+ }
509
+ } else if(KType == FX_AMERICAN_BARRIER_BINARY_OUT_DISCRETE || KType == FX_AMERICAN_BARRIER_BINARY_CALLPUT_OUT_DISCRETE){
510
+ if(knockedLeg == -1){
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
+ }
521
+ }
522
+
523
+ if(knockedLeg_dash == -1){
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 );
540
+ }
472
541
  } else if(KType == FX_AMERICAN_BARRIER_KIKO_UNTIL_EXP){
473
542
  if(knockedLeg2 >= 0){
474
543
  sim_pos[NL-1] = get_equivalent_rebate(rebate_conversion_sign, ( *( Rebate_array + 0 ) ), sim[NL-1], dir_sign);
475
544
  } else if(knockedLeg >= 0) {
476
- double equivalent_notional = get_equivalent_notional(conversion_sign, ( *( Ns_array + knockedLeg ) ), sim[NL-1]);
545
+ double equivalent_notional = *( Ns_array + knockedLeg );
477
546
  sim_pos[NL-1] = european_payoff(( *( Xs_array + (knockedLeg) ) ), sim[NL-1], cp_sign, dir_sign, equivalent_notional);
478
547
  }
479
548
  if(knockedLeg2_dash >= 0){
480
549
  sim_dash_pos[NL-1] = get_equivalent_rebate(rebate_conversion_sign, ( *( Rebate_array + 0 ) ), sim_dash[NL-1], dir_sign);
481
550
  } else if(knockedLeg_dash >= 0) {
482
- double equivalent_notional = get_equivalent_notional(conversion_sign, ( *( Ns_array + knockedLeg_dash ) ), sim_dash[NL-1]);
551
+ double equivalent_notional = *( Ns_array + knockedLeg_dash );
483
552
  sim_dash_pos[NL-1] = european_payoff(( *( Xs_array + (knockedLeg_dash) ) ), sim_dash[NL-1], cp_sign, dir_sign, equivalent_notional);
484
553
  }
485
554
 
@@ -494,7 +563,7 @@ VALUE method_run_monte_carlo( VALUE self, VALUE args ) {
494
563
  } else if(KType == FX_AMERICAN_BARRIER_KIKO_UNTIL_KI){
495
564
  if(knockedLeg >= 0 && knockedLeg2 >= 0){
496
565
  if(knockedLeg < knockedLeg2){
497
- double equivalent_notional = get_equivalent_notional(conversion_sign, ( *( Ns_array + knockedLeg ) ), sim[NL-1]);
566
+ double equivalent_notional = *( Ns_array + knockedLeg );
498
567
  sim_pos[NL-1] = european_payoff(( *( Xs_array + (knockedLeg) ) ), sim[NL-1], cp_sign, dir_sign, equivalent_notional);
499
568
  } else {
500
569
  sim_pos[knockedLeg2] = get_equivalent_rebate(rebate_conversion_sign, ( *( Rebate_array + 0 ) ), sim[knockedLeg2], dir_sign);
@@ -502,13 +571,13 @@ VALUE method_run_monte_carlo( VALUE self, VALUE args ) {
502
571
  } else if(knockedLeg2 >= 0){
503
572
  sim_pos[knockedLeg2] = get_equivalent_rebate(rebate_conversion_sign, ( *( Rebate_array + 0 ) ), sim[knockedLeg2], dir_sign);
504
573
  } else if(knockedLeg >= 0) {
505
- double equivalent_notional = get_equivalent_notional(conversion_sign, ( *( Ns_array + knockedLeg ) ), sim[NL-1]);
574
+ double equivalent_notional = *( Ns_array + knockedLeg );
506
575
  sim_pos[NL-1] = european_payoff(( *( Xs_array + (knockedLeg) ) ), sim[NL-1], cp_sign, dir_sign, equivalent_notional);
507
576
  }
508
577
 
509
578
  if(knockedLeg_dash >= 0 && knockedLeg2_dash >= 0){
510
579
  if(knockedLeg_dash < knockedLeg2_dash){
511
- double equivalent_notional = get_equivalent_notional(conversion_sign, ( *( Ns_array + knockedLeg_dash ) ), sim_dash[NL-1]);
580
+ double equivalent_notional = *( Ns_array + knockedLeg_dash );
512
581
  sim_dash_pos[NL-1] = european_payoff(( *( Xs_array + (knockedLeg_dash) ) ), sim_dash[NL-1], cp_sign, dir_sign, equivalent_notional);
513
582
  } else {
514
583
  sim_dash_pos[knockedLeg2_dash] = get_equivalent_rebate(rebate_conversion_sign, ( *( Rebate_array + 0 ) ), sim_dash[knockedLeg2_dash], dir_sign);
@@ -516,7 +585,7 @@ VALUE method_run_monte_carlo( VALUE self, VALUE args ) {
516
585
  } else if(knockedLeg2_dash >= 0){
517
586
  sim_dash_pos[knockedLeg2_dash] = get_equivalent_rebate(rebate_conversion_sign, ( *( Rebate_array + 0 ) ), sim_dash[knockedLeg2_dash], dir_sign);
518
587
  } else if(knockedLeg_dash >= 0) {
519
- double equivalent_notional = get_equivalent_notional(conversion_sign, ( *( Ns_array + knockedLeg_dash ) ), sim_dash[NL-1]);
588
+ double equivalent_notional = *( Ns_array + knockedLeg_dash );
520
589
  sim_dash_pos[NL-1] = european_payoff(( *( Xs_array + (knockedLeg_dash) ) ), sim_dash[NL-1], cp_sign, dir_sign, equivalent_notional);
521
590
  }
522
591
 
@@ -533,14 +602,14 @@ VALUE method_run_monte_carlo( VALUE self, VALUE args ) {
533
602
  sim_pos[knockedLeg] = get_equivalent_rebate(rebate_conversion_sign, ( *( Rebate_array + knockedLeg ) ), sim[knockedLeg], dir_sign);
534
603
  }
535
604
  else{
536
- double equivalent_notional = get_equivalent_notional(conversion_sign, ( *( Ns_array + 0 ) ), sim[NL-1]);
605
+ double equivalent_notional = *( Ns_array + 0 );
537
606
  sim_pos[NL-1] = european_payoff(( *( Xs_array + 0 ) ), sim[NL-1], cp_sign, dir_sign, equivalent_notional);
538
607
  }
539
608
  if(knockedLeg_dash >= 0 ){
540
609
  sim_dash_pos[knockedLeg_dash] = get_equivalent_rebate(rebate_conversion_sign, ( *( Rebate_array + knockedLeg_dash ) ), sim[knockedLeg_dash], dir_sign);
541
610
  }
542
611
  else{
543
- double equivalent_notional = get_equivalent_notional(conversion_sign, ( *( Ns_array + 0 ) ), sim_dash[NL-1]);
612
+ double equivalent_notional = *( Ns_array + 0 );
544
613
  sim_dash_pos[NL-1] = european_payoff(( *( Xs_array + 0 ) ), sim_dash[NL-1], cp_sign, dir_sign, equivalent_notional);
545
614
  }
546
615
 
@@ -680,6 +749,8 @@ VALUE method_run_monte_carlo( VALUE self, VALUE args ) {
680
749
  pvs_neg[sim_count] = sim_neg_sum;
681
750
  pvs_neg[sim_count + 1] = sim_dash_neg_sum;
682
751
 
752
+ payoffmet[sim_count] = sim_pos_sum;
753
+ payoffmet[sim_count + 1] = sim_dash_pos_sum;
683
754
 
684
755
  if (barrier_variations(KType)){
685
756
  if ((point_pos < DATAPOINTS) && (sim_count % INTERVAL) == 0){
@@ -755,12 +826,20 @@ VALUE method_run_monte_carlo( VALUE self, VALUE args ) {
755
826
  }
756
827
  }
757
828
 
829
+
830
+ VALUE py_final_metrics = rb_ary_new();
831
+ for(metric = 0; metric < SCount; metric++) {
832
+ VALUE leg_metrics = rb_ary_new();
833
+
834
+ rb_ary_push(py_final_metrics, payoffmet[metric]);
835
+ }
758
836
  // rb_p(rb_str_new2("Generating output hash"));
759
837
  VALUE final_pvs = rb_hash_new();
760
838
  rb_hash_aset(final_pvs, rb_str_new2("positive_pv"), DBL2NUM( pvs_pos_sum / SCount ));
761
839
  rb_hash_aset(final_pvs, rb_str_new2("negative_pv"), DBL2NUM( pvs_neg_sum / SCount ));
762
840
  rb_hash_aset(final_pvs, rb_str_new2("total_pv"), DBL2NUM( (pvs_neg_sum + pvs_pos_sum) / SCount ));
763
841
  rb_hash_aset(final_pvs, rb_str_new2("metrics"), final_metrics);
842
+ rb_hash_aset(final_pvs, rb_str_new2("payoffmetrics"), py_final_metrics);
764
843
 
765
844
  //
766
845
  // 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.55"
6
+ VERSION = "3.60"
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.55'
4
+ version: '3.60'
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-10 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