tarf_monte_carlo 3.51 → 3.56

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: a032374020fceff1a3ab39e9c45e4073a93e2919a3c129a78e8e29c888864e43
4
- data.tar.gz: d79b3c339ce40660d27b38e88abdf3ec50c0cb57062c28354bb1cc393f0269a8
3
+ metadata.gz: e049edbb4b08e73240bcefcb197f9f29d9d7491c6dba1d4c97130af405cfbfcf
4
+ data.tar.gz: 92ff0b4ad25f0e871ccbaa6e14f62e5eaabbe1500b9a7724bda47bd09839ee23
5
5
  SHA512:
6
- metadata.gz: 926cf7788193cf069f41290b4c973bb11a0698210305a039fca191077e5d8a5d3c850e9245eed4c1cbf392a1ad9b95335b3ba7a3eeb96401ebbf18205b2a9b33
7
- data.tar.gz: 423b8457497ba25e45539180f7a03a9ebc0224598455e0c250e880635489b6c447d8a459eb755aaadc34c5cf98676f8262832f18699c4d93608a62488d3ee1ef
6
+ metadata.gz: 4d2514c2a003eb7d117519e3c17e4d68bc00dec97ffc4bb2ac3498076b80612c15df901d94faee6087552876ba050899fe0d7beeee7b62bbd192777f4f9888e8
7
+ data.tar.gz: 71fa095eb08d47d02335e63d4800b20c9714215aaa17d3993567ff7d2ae861acbae22499490ae852727018908a36da319eaec08e1a1413ad00a4e8a4774bf20d
@@ -45,6 +45,10 @@
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
50
+ #define FX_AMERICAN_BARRIER_BINARY_IN_DISCRETE 19
51
+ #define FX_AMERICAN_BARRIER_BINARY_OUT_DISCRETE 20
48
52
 
49
53
  #define DATAPOINTS 200 // data for plotting
50
54
  #define BARRIER_DP 4 // data for plotting
@@ -63,6 +67,7 @@ double european_payoff(double, double, int, int, double);
63
67
  double get_equivalent_notional(int, double, float);
64
68
  double get_equivalent_rebate(int, double, float, int);
65
69
  bool barrier_variations(int);
70
+ bool double_barrier_variations(int);
66
71
  // Prototype for our methods - methods are prefixed by 'method_' here
67
72
  VALUE method_box_muller( VALUE );
68
73
  VALUE method_run_monte_carlo( VALUE, VALUE );
@@ -98,11 +103,15 @@ double get_equivalent_notional(int conversion_sign, double notional, float rate)
98
103
 
99
104
  double get_equivalent_rebate(int conversion_sign, double rebate, float rate, int dir_sign){
100
105
  double total = (conversion_sign == 1) ? (rebate * rate) : rebate;
101
- return (-1 * dir_sign * total);
106
+ return (dir_sign * total);
102
107
  }
103
108
 
104
109
  bool barrier_variations(int KType){
105
- 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);
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);
111
+ }
112
+
113
+ bool double_barrier_variations(int KType){
114
+ 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);
106
115
  }
107
116
  // main method for running monte carlo simulation from sidekiq worker/outside method
108
117
  VALUE method_run_monte_carlo( VALUE self, VALUE args ) {
@@ -122,6 +131,7 @@ VALUE method_run_monte_carlo( VALUE self, VALUE args ) {
122
131
  int NL = NUM2INT( rb_hash_aref(MCInputs, rb_str_new2("legs_count")) );
123
132
  int BS = NUM2INT( rb_hash_aref(MCInputs, rb_str_new2("buy_sell")) );
124
133
  double K = NUM2DBL( rb_hash_aref(MCInputs, rb_str_new2("knockout")) );
134
+ int CP = NUM2DBL( rb_hash_aref(MCInputs, rb_str_new2("callput")) );
125
135
  int KType = NUM2INT( rb_hash_aref(MCInputs, rb_str_new2("knockout_type")) );
126
136
  double S = NUM2DBL( rb_hash_aref(MCInputs, rb_str_new2("spot_rate")) );
127
137
  int Ko_compare_mult = NUM2INT( rb_hash_aref(MCInputs, rb_str_new2("multiplier")) );
@@ -191,11 +201,11 @@ VALUE method_run_monte_carlo( VALUE self, VALUE args ) {
191
201
  LSts_array[leg] = NUM2DBL( rb_ary_entry(LSts, leg) );
192
202
  USts_array[leg] = NUM2DBL( rb_ary_entry(USts, leg) );
193
203
  }
194
- } else if (KType == FX_AMERICAN_BARRIER_KNOCKIN_DISCRETE || KType == FX_AMERICAN_BARRIER_KNOCKOUT_DISCRETE) {
204
+ } else if (barrier_variations(KType)) {
195
205
  for (leg = 0; leg < NL; ++leg) {
196
206
  Barrier_array[leg] = NUM2DBL( rb_ary_entry(Brs, leg) );
197
207
  Rebate_array[leg] = NUM2DBL( rb_ary_entry(Rbts, leg) );
198
- if(KType == FX_AMERICAN_BARRIER_WINDOW_KNOCKIN || KType == FX_AMERICAN_BARRIER_WINDOW_KNOCKOUT){
208
+ if(double_barrier_variations(KType)){
199
209
  Barrier2_array[leg] = NUM2DBL( rb_ary_entry(Brs2, leg) );
200
210
  }
201
211
  }
@@ -241,8 +251,7 @@ VALUE method_run_monte_carlo( VALUE self, VALUE args ) {
241
251
  sim_dash_neg[leg] = 0.0;
242
252
  }
243
253
 
244
- int knockedLeg = -1;
245
- int knockedLeg_dash = -1;
254
+ int knockedLeg = -1, knockedLeg_dash = -1, knockedLeg2 = -1, knockedLeg2_dash = -1;
246
255
  // legs loop start
247
256
  for( leg = 0; leg < NL; ++leg ) {
248
257
  double eps, eps_dash, drift, vSqrdt, profit_loss, profit_loss_dash;
@@ -259,7 +268,7 @@ VALUE method_run_monte_carlo( VALUE self, VALUE args ) {
259
268
  Spot = Spot * exp( drift + vSqrdt * eps );
260
269
  Spot_dash = Spot_dash * exp( drift + vSqrdt * eps_dash );
261
270
 
262
- 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){
263
272
  profit_loss = Spot;
264
273
  profit_loss_dash = Spot_dash;
265
274
 
@@ -272,6 +281,23 @@ VALUE method_run_monte_carlo( VALUE self, VALUE args ) {
272
281
  if(knockedLeg_dash == -1 && knockin_dash >= 0){
273
282
  knockedLeg_dash = leg;
274
283
  }
284
+ } else if(KType == FX_AMERICAN_BARRIER_KIKO_UNTIL_KI || KType == FX_AMERICAN_BARRIER_KIKO_UNTIL_EXP){
285
+ profit_loss = Spot;
286
+ profit_loss_dash = Spot_dash;
287
+
288
+ if(knockedLeg == -1 && (Spot >= *(Barrier_array + leg))){
289
+ knockedLeg = leg;
290
+ }
291
+ if(knockedLeg_dash == -1 && (Spot_dash >= *(Barrier_array + leg))){
292
+ knockedLeg_dash = leg;
293
+ }
294
+
295
+ if(knockedLeg2 == -1 && (Spot >= *(Barrier2_array + leg))){
296
+ knockedLeg2 = leg;
297
+ }
298
+ if(knockedLeg2_dash == -1 && (Spot_dash >= *(Barrier2_array + leg))){
299
+ knockedLeg2_dash = leg;
300
+ }
275
301
  } else if(KType == FX_AMERICAN_BARRIER_WINDOW_KNOCKIN || KType == FX_AMERICAN_BARRIER_WINDOW_KNOCKOUT){
276
302
  profit_loss = Spot;
277
303
  profit_loss_dash = Spot_dash;
@@ -438,6 +464,83 @@ VALUE method_run_monte_carlo( VALUE self, VALUE args ) {
438
464
  else{
439
465
  sim_dash_pos[NL-1] = get_equivalent_rebate(rebate_conversion_sign, ( *( Rebate_array + 0 ) ), sim_dash[NL-1], dir_sign);
440
466
  }
467
+ if ((point_pos < DATAPOINTS) && (sim_count % INTERVAL) == 0){
468
+ metrics[0][point_pos] = sim[NL-1];
469
+ metrics[1][point_pos] = (knockedLeg >= 0) ? ( *( Xs_array + (knockedLeg) ) ) : 0;
470
+ metrics[3][point_pos] = knockedLeg;
471
+ metrics[0][point_pos+1] = sim_dash[NL-1];
472
+ metrics[1][point_pos+1] = (knockedLeg_dash >= 0) ? ( *( Xs_array + (knockedLeg_dash) ) ) : 0;
473
+ metrics[3][point_pos+1] = knockedLeg_dash;
474
+ }
475
+ } else if(KType == FX_AMERICAN_BARRIER_BINARY_IN_DISCRETE){
476
+ if(knockedLeg >= 0){
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);
479
+ }
480
+
481
+ if(knockedLeg_dash >= 0){
482
+ 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);
484
+ }
485
+ } else if(KType == FX_AMERICAN_BARRIER_BINARY_OUT_DISCRETE){
486
+ if(knockedLeg == -1){
487
+ sim_pos[NL - 1] = get_equivalent_rebate(rebate_conversion_sign, ( *( Rebate_array + 0 ) ), sim[NL - 1], dir_sign);
488
+ }
489
+
490
+ 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);
492
+ }
493
+ } else if(KType == FX_AMERICAN_BARRIER_KIKO_UNTIL_EXP){
494
+ if(knockedLeg2 >= 0){
495
+ sim_pos[NL-1] = get_equivalent_rebate(rebate_conversion_sign, ( *( Rebate_array + 0 ) ), sim[NL-1], dir_sign);
496
+ } else if(knockedLeg >= 0) {
497
+ double equivalent_notional = get_equivalent_notional(conversion_sign, ( *( Ns_array + knockedLeg ) ), sim[NL-1]);
498
+ sim_pos[NL-1] = european_payoff(( *( Xs_array + (knockedLeg) ) ), sim[NL-1], cp_sign, dir_sign, equivalent_notional);
499
+ }
500
+ if(knockedLeg2_dash >= 0){
501
+ sim_dash_pos[NL-1] = get_equivalent_rebate(rebate_conversion_sign, ( *( Rebate_array + 0 ) ), sim_dash[NL-1], dir_sign);
502
+ } else if(knockedLeg_dash >= 0) {
503
+ double equivalent_notional = get_equivalent_notional(conversion_sign, ( *( Ns_array + knockedLeg_dash ) ), sim_dash[NL-1]);
504
+ sim_dash_pos[NL-1] = european_payoff(( *( Xs_array + (knockedLeg_dash) ) ), sim_dash[NL-1], cp_sign, dir_sign, equivalent_notional);
505
+ }
506
+
507
+ if ((point_pos < DATAPOINTS) && (sim_count % INTERVAL) == 0){
508
+ metrics[0][point_pos] = sim[NL-1];
509
+ metrics[1][point_pos] = (knockedLeg >= 0) ? ( *( Xs_array + (knockedLeg) ) ) : 0;
510
+ metrics[3][point_pos] = knockedLeg;
511
+ metrics[0][point_pos+1] = sim_dash[NL-1];
512
+ metrics[1][point_pos+1] = (knockedLeg_dash >= 0) ? ( *( Xs_array + (knockedLeg_dash) ) ) : 0;
513
+ metrics[3][point_pos+1] = knockedLeg_dash;
514
+ }
515
+ } else if(KType == FX_AMERICAN_BARRIER_KIKO_UNTIL_KI){
516
+ if(knockedLeg >= 0 && knockedLeg2 >= 0){
517
+ if(knockedLeg < knockedLeg2){
518
+ double equivalent_notional = get_equivalent_notional(conversion_sign, ( *( Ns_array + knockedLeg ) ), sim[NL-1]);
519
+ sim_pos[NL-1] = european_payoff(( *( Xs_array + (knockedLeg) ) ), sim[NL-1], cp_sign, dir_sign, equivalent_notional);
520
+ } else {
521
+ sim_pos[knockedLeg2] = get_equivalent_rebate(rebate_conversion_sign, ( *( Rebate_array + 0 ) ), sim[knockedLeg2], dir_sign);
522
+ }
523
+ } else if(knockedLeg2 >= 0){
524
+ sim_pos[knockedLeg2] = get_equivalent_rebate(rebate_conversion_sign, ( *( Rebate_array + 0 ) ), sim[knockedLeg2], dir_sign);
525
+ } else if(knockedLeg >= 0) {
526
+ double equivalent_notional = get_equivalent_notional(conversion_sign, ( *( Ns_array + knockedLeg ) ), sim[NL-1]);
527
+ sim_pos[NL-1] = european_payoff(( *( Xs_array + (knockedLeg) ) ), sim[NL-1], cp_sign, dir_sign, equivalent_notional);
528
+ }
529
+
530
+ if(knockedLeg_dash >= 0 && knockedLeg2_dash >= 0){
531
+ if(knockedLeg_dash < knockedLeg2_dash){
532
+ double equivalent_notional = get_equivalent_notional(conversion_sign, ( *( Ns_array + knockedLeg_dash ) ), sim_dash[NL-1]);
533
+ sim_dash_pos[NL-1] = european_payoff(( *( Xs_array + (knockedLeg_dash) ) ), sim_dash[NL-1], cp_sign, dir_sign, equivalent_notional);
534
+ } else {
535
+ sim_dash_pos[knockedLeg2_dash] = get_equivalent_rebate(rebate_conversion_sign, ( *( Rebate_array + 0 ) ), sim_dash[knockedLeg2_dash], dir_sign);
536
+ }
537
+ } else if(knockedLeg2_dash >= 0){
538
+ sim_dash_pos[knockedLeg2_dash] = get_equivalent_rebate(rebate_conversion_sign, ( *( Rebate_array + 0 ) ), sim_dash[knockedLeg2_dash], dir_sign);
539
+ } else if(knockedLeg_dash >= 0) {
540
+ double equivalent_notional = get_equivalent_notional(conversion_sign, ( *( Ns_array + knockedLeg_dash ) ), sim_dash[NL-1]);
541
+ sim_dash_pos[NL-1] = european_payoff(( *( Xs_array + (knockedLeg_dash) ) ), sim_dash[NL-1], cp_sign, dir_sign, equivalent_notional);
542
+ }
543
+
441
544
  if ((point_pos < DATAPOINTS) && (sim_count % INTERVAL) == 0){
442
545
  metrics[0][point_pos] = sim[NL-1];
443
546
  metrics[1][point_pos] = (knockedLeg >= 0) ? ( *( Xs_array + (knockedLeg) ) ) : 0;
@@ -3,5 +3,5 @@
3
3
  # gem yank tarf_monte_carlo -v 2.3
4
4
 
5
5
  module TarfMonteCarlo
6
- VERSION = "3.51"
6
+ VERSION = "3.56"
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.51'
4
+ version: '3.56'
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-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler