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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 92ba4ec2f8c25a6704d3e7388a8a3e243ff51693b8ea1966d57b67b42d09514f
4
- data.tar.gz: f80d07fdca106e815b442561331e1cfce8a7772e5e8b9bfb830cf6b043432fcd
3
+ metadata.gz: e0d7cdafaf4865a66b7bbe6452a9ad3dd90c3ced070778cd288bf304cb3e2417
4
+ data.tar.gz: 79894b25d74fc53dfe3151009122e846323b18e31ba4ab71f4cced7edcad6eae
5
5
  SHA512:
6
- metadata.gz: 944741bc4e48a44ecd97d09e36a316bb2eba4b78a6d2bbd2e645699b5e595008e443f88e78e841844ef6765af80b45a9a47144978e8628048699787a8859ee9b
7
- data.tar.gz: a03e00f6749dcdc4358370b1d49056032b9d97ff4293208633045dddeb970fea0b9be734037383734a117f13dce003d5fa851e734a6b725cd72f4908a47b6e9f
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 (-1 * dir_sign * total);
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 == FX_AMERICAN_BARRIER_KNOCKIN_DISCRETE || KType == FX_AMERICAN_BARRIER_KNOCKOUT_DISCRETE) {
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 == FX_AMERICAN_BARRIER_KNOCKIN_DISCRETE || KType == FX_AMERICAN_BARRIER_KNOCKOUT_DISCRETE){
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 == FX_AMERICAN_BARRIER_KNOCKIN_DISCRETE || KType == FX_AMERICAN_BARRIER_KNOCKOUT_DISCRETE)){
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 == FX_AMERICAN_BARRIER_KNOCKOUT_DISCRETE){
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 == FX_AMERICAN_BARRIER_KNOCKIN_DISCRETE || KType == FX_AMERICAN_BARRIER_KNOCKOUT_DISCRETE)){
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 == FX_AMERICAN_BARRIER_KNOCKIN_DISCRETE || KType == FX_AMERICAN_BARRIER_KNOCKOUT_DISCRETE){
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 == FX_AMERICAN_BARRIER_KNOCKIN_DISCRETE || KType == FX_AMERICAN_BARRIER_KNOCKOUT_DISCRETE){
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 == FX_AMERICAN_BARRIER_KNOCKIN_DISCRETE || KType == FX_AMERICAN_BARRIER_KNOCKOUT_DISCRETE) ? BARRIER_DP : DATAPOINTS;
731
+ int dp = barrier_variations(KType) ? BARRIER_DP : DATAPOINTS;
683
732
  for(metric = 0; metric < dp; metric++) {
684
733
  free( metrics[metric] );
685
734
  }
@@ -3,5 +3,5 @@
3
3
  # gem yank tarf_monte_carlo -v 2.3
4
4
 
5
5
  module TarfMonteCarlo
6
- VERSION = "3.49"
6
+ VERSION = "3.54"
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.49'
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-07 00:00:00.000000000 Z
11
+ date: 2020-10-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler