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 +4 -4
- data/ext/tarf_monte_carlo/tarf_monte_carlo.c +79 -23
- data/lib/tarf_monte_carlo/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 157664b6dfd86644998da3438b564db2580b1f4503bb602ab321bf2b4863d63c
|
|
4
|
+
data.tar.gz: aec6753b1e912651e2c04357d833dbacc920442a32956993d25f37c1b07de19d
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
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 =
|
|
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 =
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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
|
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.
|
|
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-
|
|
11
|
+
date: 2020-10-13 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: bundler
|