tarf_monte_carlo 3.49 → 3.54
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 +66 -17
- 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: e0d7cdafaf4865a66b7bbe6452a9ad3dd90c3ced070778cd288bf304cb3e2417
|
4
|
+
data.tar.gz: 79894b25d74fc53dfe3151009122e846323b18e31ba4ab71f4cced7edcad6eae
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c513bd0d5cbc5b2d8e3a66334131cf0d95b094510a6fb42f1862b478448b605c1e04a2714f552e9a7234bf1eeb1bd3297e034dbec69445e13ad2bf3ff2c65b58
|
7
|
+
data.tar.gz: c0ce2f67ed9a9c32f1ddaef031350535c2522bd6bfde0c80bb493189b684f68aab392fbbf773b85d1d92a11fc3d488501e5d5e8ca87e3d8f9458694c8297f9e3
|
@@ -45,6 +45,8 @@
|
|
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
|
48
50
|
|
49
51
|
#define DATAPOINTS 200 // data for plotting
|
50
52
|
#define BARRIER_DP 4 // data for plotting
|
@@ -62,7 +64,8 @@ void Init_tarf_monte_carlo();
|
|
62
64
|
double european_payoff(double, double, int, int, double);
|
63
65
|
double get_equivalent_notional(int, double, float);
|
64
66
|
double get_equivalent_rebate(int, double, float, int);
|
65
|
-
|
67
|
+
bool barrier_variations(int);
|
68
|
+
bool double_barrier_variations(int);
|
66
69
|
// Prototype for our methods - methods are prefixed by 'method_' here
|
67
70
|
VALUE method_box_muller( VALUE );
|
68
71
|
VALUE method_run_monte_carlo( VALUE, VALUE );
|
@@ -98,9 +101,16 @@ double get_equivalent_notional(int conversion_sign, double notional, float rate)
|
|
98
101
|
|
99
102
|
double get_equivalent_rebate(int conversion_sign, double rebate, float rate, int dir_sign){
|
100
103
|
double total = (conversion_sign == 1) ? (rebate * rate) : rebate;
|
101
|
-
return (
|
104
|
+
return (dir_sign * total);
|
105
|
+
}
|
106
|
+
|
107
|
+
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);
|
102
109
|
}
|
103
110
|
|
111
|
+
bool double_barrier_variations(int KType){
|
112
|
+
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);
|
113
|
+
}
|
104
114
|
// main method for running monte carlo simulation from sidekiq worker/outside method
|
105
115
|
VALUE method_run_monte_carlo( VALUE self, VALUE args ) {
|
106
116
|
VALUE MCInputs = rb_ary_shift(args);
|
@@ -188,20 +198,21 @@ VALUE method_run_monte_carlo( VALUE self, VALUE args ) {
|
|
188
198
|
LSts_array[leg] = NUM2DBL( rb_ary_entry(LSts, leg) );
|
189
199
|
USts_array[leg] = NUM2DBL( rb_ary_entry(USts, leg) );
|
190
200
|
}
|
191
|
-
} else if (KType
|
201
|
+
} else if (barrier_variations(KType)) {
|
192
202
|
for (leg = 0; leg < NL; ++leg) {
|
193
203
|
Barrier_array[leg] = NUM2DBL( rb_ary_entry(Brs, leg) );
|
194
204
|
Rebate_array[leg] = NUM2DBL( rb_ary_entry(Rbts, leg) );
|
205
|
+
if(double_barrier_variations(KType)){
|
206
|
+
Barrier2_array[leg] = NUM2DBL( rb_ary_entry(Brs2, leg) );
|
207
|
+
}
|
195
208
|
}
|
196
|
-
} else if(KType == FX_AMERICAN_BARRIER_WINDOW_KNOCKIN || KType == FX_AMERICAN_BARRIER_WINDOW_KNOCKOUT){
|
197
|
-
Barrier2_array[leg] = NUM2DBL( rb_ary_entry(Brs2, leg) );
|
198
209
|
}
|
199
210
|
|
200
211
|
//
|
201
212
|
// first create a 1-D array of pointers, and then, for each array entry, create another 1-D array.
|
202
213
|
//
|
203
214
|
double **metrics;
|
204
|
-
if (KType
|
215
|
+
if (barrier_variations(KType)){
|
205
216
|
metrics = ( double** ) malloc( BARRIER_DP * sizeof(double*) );
|
206
217
|
for( metric = 0; metric < BARRIER_DP; metric++ ) {
|
207
218
|
metrics[metric] = ( double* ) malloc( DATAPOINTS * sizeof(double) );
|
@@ -237,8 +248,7 @@ VALUE method_run_monte_carlo( VALUE self, VALUE args ) {
|
|
237
248
|
sim_dash_neg[leg] = 0.0;
|
238
249
|
}
|
239
250
|
|
240
|
-
int knockedLeg = -1;
|
241
|
-
int knockedLeg_dash = -1;
|
251
|
+
int knockedLeg = -1, knockedLeg_dash = -1, knockedLeg2 = -1, knockedLeg2_dash = -1;
|
242
252
|
// legs loop start
|
243
253
|
for( leg = 0; leg < NL; ++leg ) {
|
244
254
|
double eps, eps_dash, drift, vSqrdt, profit_loss, profit_loss_dash;
|
@@ -268,6 +278,23 @@ VALUE method_run_monte_carlo( VALUE self, VALUE args ) {
|
|
268
278
|
if(knockedLeg_dash == -1 && knockin_dash >= 0){
|
269
279
|
knockedLeg_dash = leg;
|
270
280
|
}
|
281
|
+
} else if(KType == FX_AMERICAN_BARRIER_KIKO_UNTIL_KI || KType == FX_AMERICAN_BARRIER_KIKO_UNTIL_EXP){
|
282
|
+
profit_loss = Spot;
|
283
|
+
profit_loss_dash = Spot_dash;
|
284
|
+
|
285
|
+
if(knockedLeg == -1 && (Spot >= *(Barrier_array + leg))){
|
286
|
+
knockedLeg = leg;
|
287
|
+
}
|
288
|
+
if(knockedLeg_dash == -1 && (Spot_dash >= *(Barrier_array + leg))){
|
289
|
+
knockedLeg_dash = leg;
|
290
|
+
}
|
291
|
+
|
292
|
+
if(knockedLeg2 == -1 && (Spot >= *(Barrier2_array + leg))){
|
293
|
+
knockedLeg2 = leg;
|
294
|
+
}
|
295
|
+
if(knockedLeg2_dash == -1 && (Spot_dash >= *(Barrier2_array + leg))){
|
296
|
+
knockedLeg2_dash = leg;
|
297
|
+
}
|
271
298
|
} else if(KType == FX_AMERICAN_BARRIER_WINDOW_KNOCKIN || KType == FX_AMERICAN_BARRIER_WINDOW_KNOCKOUT){
|
272
299
|
profit_loss = Spot;
|
273
300
|
profit_loss_dash = Spot_dash;
|
@@ -401,7 +428,7 @@ VALUE method_run_monte_carlo( VALUE self, VALUE args ) {
|
|
401
428
|
//
|
402
429
|
// Store spot and spot dash
|
403
430
|
//
|
404
|
-
if (!(KType
|
431
|
+
if (!(barrier_variations(KType))){
|
405
432
|
if( point_pos <= SIM_LIMIT && (sim_count + 2) % INTERVAL == 0 ) {
|
406
433
|
// rb_p(rb_str_new2("Leg:Spots"));
|
407
434
|
metrics[ point_pos ][ leg ] = Spot;
|
@@ -419,7 +446,7 @@ VALUE method_run_monte_carlo( VALUE self, VALUE args ) {
|
|
419
446
|
// legs loop end
|
420
447
|
// start from the Knock value
|
421
448
|
double ko_so_far = K, ko_so_far_dash = K;
|
422
|
-
if(KType == FX_AMERICAN_BARRIER_KNOCKIN_DISCRETE){
|
449
|
+
if(KType == FX_AMERICAN_BARRIER_KNOCKIN_DISCRETE || KType == FX_AMERICAN_BARRIER_WINDOW_KNOCKIN){
|
423
450
|
if(knockedLeg >= 0){
|
424
451
|
double equivalent_notional = get_equivalent_notional(conversion_sign, ( *( Ns_array + knockedLeg ) ), sim[NL-1]);
|
425
452
|
sim_pos[NL-1] = european_payoff(( *( Xs_array + (knockedLeg) ) ), sim[NL-1], cp_sign, dir_sign, equivalent_notional);
|
@@ -442,7 +469,29 @@ VALUE method_run_monte_carlo( VALUE self, VALUE args ) {
|
|
442
469
|
metrics[1][point_pos+1] = (knockedLeg_dash >= 0) ? ( *( Xs_array + (knockedLeg_dash) ) ) : 0;
|
443
470
|
metrics[3][point_pos+1] = knockedLeg_dash;
|
444
471
|
}
|
445
|
-
} else if(KType ==
|
472
|
+
} else if(KType == FX_AMERICAN_BARRIER_KIKO_UNTIL_EXP || KType == FX_AMERICAN_BARRIER_KIKO_UNTIL_KI){
|
473
|
+
if(knockedLeg2 >= 0){
|
474
|
+
sim_pos[NL-1] = get_equivalent_rebate(rebate_conversion_sign, ( *( Rebate_array + 0 ) ), sim[NL-1], dir_sign);
|
475
|
+
} else if(knockedLeg >= 0) {
|
476
|
+
double equivalent_notional = get_equivalent_notional(conversion_sign, ( *( Ns_array + knockedLeg ) ), sim[NL-1]);
|
477
|
+
sim_pos[NL-1] = european_payoff(( *( Xs_array + (knockedLeg) ) ), sim[NL-1], cp_sign, dir_sign, equivalent_notional);
|
478
|
+
}
|
479
|
+
if(knockedLeg2_dash >= 0){
|
480
|
+
sim_dash_pos[NL-1] = get_equivalent_rebate(rebate_conversion_sign, ( *( Rebate_array + 0 ) ), sim_dash[NL-1], dir_sign);
|
481
|
+
} else if(knockedLeg_dash >= 0) {
|
482
|
+
double equivalent_notional = get_equivalent_notional(conversion_sign, ( *( Ns_array + knockedLeg_dash ) ), sim_dash[NL-1]);
|
483
|
+
sim_dash_pos[NL-1] = european_payoff(( *( Xs_array + (knockedLeg_dash) ) ), sim_dash[NL-1], cp_sign, dir_sign, equivalent_notional);
|
484
|
+
}
|
485
|
+
|
486
|
+
if ((point_pos < DATAPOINTS) && (sim_count % INTERVAL) == 0){
|
487
|
+
metrics[0][point_pos] = sim[NL-1];
|
488
|
+
metrics[1][point_pos] = (knockedLeg >= 0) ? ( *( Xs_array + (knockedLeg) ) ) : 0;
|
489
|
+
metrics[3][point_pos] = knockedLeg;
|
490
|
+
metrics[0][point_pos+1] = sim_dash[NL-1];
|
491
|
+
metrics[1][point_pos+1] = (knockedLeg_dash >= 0) ? ( *( Xs_array + (knockedLeg_dash) ) ) : 0;
|
492
|
+
metrics[3][point_pos+1] = knockedLeg_dash;
|
493
|
+
}
|
494
|
+
} else if(KType == FX_AMERICAN_BARRIER_KNOCKOUT_DISCRETE || KType == FX_AMERICAN_BARRIER_WINDOW_KNOCKOUT){
|
446
495
|
if(knockedLeg >= 0){
|
447
496
|
sim_pos[knockedLeg] = get_equivalent_rebate(rebate_conversion_sign, ( *( Rebate_array + knockedLeg ) ), sim[knockedLeg], dir_sign);
|
448
497
|
}
|
@@ -574,7 +623,7 @@ VALUE method_run_monte_carlo( VALUE self, VALUE args ) {
|
|
574
623
|
//
|
575
624
|
// store and send whichever payoff you want
|
576
625
|
//
|
577
|
-
if (!(KType
|
626
|
+
if (!(barrier_variations(KType))){
|
578
627
|
if( point_pos <= SIM_LIMIT && (sim_count + 2) % INTERVAL == 0 ) {
|
579
628
|
// rb_p(rb_str_new2("Leg:Payoffs"));
|
580
629
|
metrics[ point_pos + 1 ][ leg ] = (sim_pos[leg] + sim_neg[leg]);
|
@@ -594,8 +643,8 @@ VALUE method_run_monte_carlo( VALUE self, VALUE args ) {
|
|
594
643
|
pvs_neg[sim_count] = sim_neg_sum;
|
595
644
|
pvs_neg[sim_count + 1] = sim_dash_neg_sum;
|
596
645
|
|
597
|
-
|
598
|
-
if (KType
|
646
|
+
|
647
|
+
if (barrier_variations(KType)){
|
599
648
|
if ((point_pos < DATAPOINTS) && (sim_count % INTERVAL) == 0){
|
600
649
|
metrics[2][point_pos] = sim_pos_sum;
|
601
650
|
metrics[2][point_pos+1] = sim_dash_pos_sum;
|
@@ -645,8 +694,8 @@ VALUE method_run_monte_carlo( VALUE self, VALUE args ) {
|
|
645
694
|
//
|
646
695
|
// rb_p(rb_str_new2("Converting metrics"));
|
647
696
|
VALUE final_metrics = rb_ary_new();
|
648
|
-
|
649
|
-
if (KType
|
697
|
+
|
698
|
+
if (barrier_variations(KType)){
|
650
699
|
for(metric = 0; metric < BARRIER_DP; metric++) {
|
651
700
|
VALUE leg_metrics = rb_ary_new();
|
652
701
|
|
@@ -679,7 +728,7 @@ VALUE method_run_monte_carlo( VALUE self, VALUE args ) {
|
|
679
728
|
//
|
680
729
|
// free your arrays from memory once you're done using them
|
681
730
|
//
|
682
|
-
int dp = (KType
|
731
|
+
int dp = barrier_variations(KType) ? BARRIER_DP : DATAPOINTS;
|
683
732
|
for(metric = 0; metric < dp; metric++) {
|
684
733
|
free( metrics[metric] );
|
685
734
|
}
|
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.54'
|
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-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|