tarf_monte_carlo 3.26 → 3.31

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: 1b551fb41bf0f6bada89b8b9b56a1cc16d1b6bdba6c4bece434a5ca8bbb103bc
4
- data.tar.gz: 6c76e80342cc906a4ad39665a8cc6ffe460b473e3fd2985bf3df571a6252f1d4
3
+ metadata.gz: 1ffba748a882648f94602365c6fe89ba13ad4012e4daa54ce87e836c757c2df7
4
+ data.tar.gz: 56cf966863ed9d42802d78634b411aef7039eab87a74420d33a3dc429e5c1fa5
5
5
  SHA512:
6
- metadata.gz: 5fe7a19bb8dd61ca522a23e5a216c726f7af22b385c9d16b111c9c903f5b7414ef64569168ee301e3a5fe62cb5b2f534e3445c65290f355c0d38c10af30ac5b0
7
- data.tar.gz: 6115a3972cb63edc48c8ee6c93d6206931608ef780a6322d9c6ff1add58cb3f43562288a0399abac710b4b27c5de5ede3a10d1166834da1044134d444a247c3b
6
+ metadata.gz: e15a1be8f1f8fcc330201ccbfd814866da27b0010428de8e8f4b449ca74b4879d62947309aedabecb86432657f5a1729f52b737518b2de147e967932beedbd96
7
+ data.tar.gz: 6d3a80d0819af9cacb1f4a15beb51a3e6edf3a65f38fdb50a0b6c03d0992d73f7046b126c7cf9e6a7febb1e1430fc4fbafba04590b629c02d21e51debcd0d7d7
@@ -56,6 +56,9 @@ VALUE cTarfMonteCarlo = Qnil;
56
56
 
57
57
  // Prototype for the initialization method - Ruby calls this, not you
58
58
  void Init_tarf_monte_carlo();
59
+ double european_payoff(double, double, int, int, double);
60
+ double get_equivalent_notional(int, double, float);
61
+ double get_equivalent_rebate(int, double, float);
59
62
 
60
63
  // Prototype for our methods - methods are prefixed by 'method_' here
61
64
  VALUE method_box_muller( VALUE );
@@ -80,6 +83,20 @@ VALUE method_box_muller( VALUE self ) {
80
83
  return DBL2NUM(eps);
81
84
  }
82
85
 
86
+ double european_payoff(double strike, double spot, int cp_sign, int dir_sign, double notional){
87
+ double diff = (spot - strike) * cp_sign;
88
+ diff = diff > 0 ? diff : 0;
89
+ return (diff * notional * dir_sign);
90
+ }
91
+
92
+ double get_equivalent_notional(int conversion_sign, double notional, float rate){
93
+ return (conversion_sign == 1) ? (notional / rate) : notional;
94
+ }
95
+
96
+ double get_equivalent_rebate(int conversion_sign, double rebate, float rate){
97
+ return (conversion_sign == 1) ? (rebate * rate) : rebate;
98
+ }
99
+
83
100
  // main method for running monte carlo simulation from sidekiq worker/outside method
84
101
  VALUE method_run_monte_carlo( VALUE self, VALUE args ) {
85
102
  VALUE MCInputs = rb_ary_shift(args);
@@ -105,6 +122,8 @@ VALUE method_run_monte_carlo( VALUE self, VALUE args ) {
105
122
  int dir_sign = NUM2INT( rb_hash_aref(MCInputs, rb_str_new2("direction_sign")) );
106
123
  int dir2_sign = NUM2INT( rb_hash_aref(MCInputs, rb_str_new2("direction2_sign")) );
107
124
  int cp_sign = NUM2INT( rb_hash_aref(MCInputs, rb_str_new2("callput_sign")) );
125
+ int conversion_sign = NUM2INT( rb_hash_aref(MCInputs, rb_str_new2("conversion_sign")) );
126
+ int rebate_conversion_sign = NUM2INT( rb_hash_aref(MCInputs, rb_str_new2("rebate_conversion_sign")) );
108
127
 
109
128
  // assign leg specific attributes
110
129
  double *pvs_pos = ( double* ) malloc( SCount * sizeof(double) );
@@ -122,6 +141,7 @@ VALUE method_run_monte_carlo( VALUE self, VALUE args ) {
122
141
  double *USts_array = ( double* ) malloc( NL * sizeof(double) );
123
142
  double *TempNs_array = ( double* ) malloc( NL * sizeof(double) );
124
143
  double *Barrier_array = ( double* ) malloc( NL * sizeof(double) );
144
+ double *Rebate_array = ( double* ) malloc( NL * sizeof(double) );
125
145
 
126
146
  VALUE Ls = rb_hash_aref(MCInputs, rb_str_new2("leverage_ratios") );
127
147
  VALUE Ts = rb_hash_aref(MCInputs, rb_str_new2("expiration_times") );
@@ -135,6 +155,7 @@ VALUE method_run_monte_carlo( VALUE self, VALUE args ) {
135
155
  VALUE LSts = rb_hash_aref(MCInputs, rb_str_new2("lower_strikes") );
136
156
  VALUE USts = rb_hash_aref(MCInputs, rb_str_new2("upper_strikes") );
137
157
  VALUE Brs = rb_hash_aref(MCInputs, rb_str_new2("barriers") );
158
+ VALUE Rbts = rb_hash_aref(MCInputs, rb_str_new2("rebates") );
138
159
 
139
160
  for (leg = 0; leg < NL; ++leg) {
140
161
  Ls_array[leg] = NUM2DBL( rb_ary_entry(Ls, leg) );
@@ -163,7 +184,8 @@ VALUE method_run_monte_carlo( VALUE self, VALUE args ) {
163
184
  }
164
185
  } else if (KType == FX_AMERICAN_BARRIER_KNOCKIN_DISCRETE || KType == FX_AMERICAN_BARRIER_KNOCKOUT_DISCRETE) {
165
186
  for (leg = 0; leg < NL; ++leg) {
166
- Barrier_array[leg] = NUM2DBL( rb_ary_entry(Brs, leg) );
187
+ Barrier_array[leg] = NUM2DBL( rb_ary_entry(Brs, leg) );
188
+ Rebate_array[leg] = NUM2DBL( rb_ary_entry(Rbts, leg) );
167
189
  }
168
190
  }
169
191
 
@@ -171,6 +193,7 @@ VALUE method_run_monte_carlo( VALUE self, VALUE args ) {
171
193
  // first create a 1-D array of pointers, and then, for each array entry, create another 1-D array.
172
194
  //
173
195
  double **metrics;
196
+ double data[4][NL];
174
197
  metrics = ( double** ) malloc( DATAPOINTS * sizeof(double*) );
175
198
  for( metric = 0; metric < DATAPOINTS; metric++ ) {
176
199
  metrics[metric] = ( double* ) malloc( NL * sizeof(double) );
@@ -194,6 +217,10 @@ VALUE method_run_monte_carlo( VALUE self, VALUE args ) {
194
217
  sim_dash[leg] = 0.0;
195
218
  sim_dash_pos[leg] = 0.0;
196
219
  sim_dash_neg[leg] = 0.0;
220
+ data[0][leg] = 0.0;
221
+ data[1][leg] = 0.0;
222
+ data[2][leg] = 0.0;
223
+ data[3][leg] = 0.0;
197
224
  }
198
225
 
199
226
  int knockedLeg = -1;
@@ -215,26 +242,18 @@ VALUE method_run_monte_carlo( VALUE self, VALUE args ) {
215
242
  Spot_dash = Spot_dash * exp( drift + vSqrdt * eps_dash );
216
243
 
217
244
  if(KType == FX_AMERICAN_BARRIER_KNOCKIN_DISCRETE || KType == FX_AMERICAN_BARRIER_KNOCKOUT_DISCRETE){
218
- profit_loss = 0;
219
- profit_loss_dash = 0;
245
+ profit_loss = Spot;
246
+ profit_loss_dash = Spot_dash;
220
247
 
221
- double knockin = (Spot - *(Barrier_array + leg)) * dir_sign * cp_sign * dir2_sign;
222
- double knockin_dash = (Spot_dash - *(Barrier_array + leg)) * dir_sign * cp_sign * dir2_sign;
248
+ double knockin = (Spot - *(Barrier_array + leg)) * dir2_sign;
249
+ double knockin_dash = (Spot_dash - *(Barrier_array + leg)) * dir2_sign;
223
250
 
224
- if(knockedLeg == -1 && knockin > 0){
251
+ if(knockedLeg == -1 && knockin >= 0){
225
252
  knockedLeg = leg;
226
253
  }
227
- if(knockedLeg == -1 && knockin < 0 && KType == FX_AMERICAN_BARRIER_KNOCKOUT_DISCRETE){
228
- profit_loss = dir_sign * dir2_sign * cp_sign * ( Spot - ( *( Xs_array + leg ) ) );
229
- }
230
-
231
- if(knockedLeg_dash == -1 && knockin_dash > 0){
254
+ if(knockedLeg_dash == -1 && knockin_dash >= 0){
232
255
  knockedLeg_dash = leg;
233
256
  }
234
- if(knockedLeg_dash == -1 && knockin_dash < 0 && KType == FX_AMERICAN_BARRIER_KNOCKOUT_DISCRETE){
235
- profit_loss = dir_sign * dir2_sign * cp_sign * ( Spot_dash - ( *( Xs_array + leg ) ) );
236
- }
237
-
238
257
  } else if ( KType == DOUBLE_STRIKE_POINTS || KType == DOUBLE_STRIKE_ABSOLUTE || KType == DOUBLE_STRIKE_LEGS ) {
239
258
  if ( Spot < *( LSts_array + leg ) ) {
240
259
  profit_loss = Spot - (*( LSts_array + leg ));
@@ -355,6 +374,8 @@ VALUE method_run_monte_carlo( VALUE self, VALUE args ) {
355
374
  sim[leg] = profit_loss;
356
375
  sim_dash[leg] = profit_loss_dash;
357
376
 
377
+ data[0][leg] = sim[leg];
378
+ data[1][leg] = sim_dash[leg];
358
379
  //
359
380
  // Store spot and spot dash
360
381
  //
@@ -371,30 +392,42 @@ VALUE method_run_monte_carlo( VALUE self, VALUE args ) {
371
392
  Spot_dash = S;
372
393
  }
373
394
  }
395
+
374
396
  // legs loop end
375
397
  // start from the Knock value
376
398
  double ko_so_far = K, ko_so_far_dash = K;
377
399
  if(KType == FX_AMERICAN_BARRIER_KNOCKIN_DISCRETE){
378
400
  if(knockedLeg >= 0){
379
- sim_pos[knockedLeg] = dir_sign * dir2_sign * cp_sign * ( Spot - ( *( Xs_array + (knockedLeg) ) ) ) * ( *( Ns_array + knockedLeg ) );
401
+ double equivalent_notional = get_equivalent_notional(conversion_sign, ( *( Ns_array + knockedLeg ) ), sim[NL-1]);
402
+ sim_pos[NL-1] = european_payoff(( *( Xs_array + (knockedLeg) ) ), sim[NL-1], cp_sign, dir_sign, equivalent_notional);
403
+ }
404
+ else{
405
+ sim_pos[NL-1] = get_equivalent_rebate(rebate_conversion_sign, ( *( Rebate_array + 0 ) ), sim[NL-1]);
380
406
  }
381
407
  if(knockedLeg_dash >= 0 ){
382
- sim_dash_pos[knockedLeg_dash] = dir_sign * dir2_sign * cp_sign * ( Spot_dash - ( *( Xs_array + (knockedLeg_dash) ) ) ) * ( *( Ns_array + knockedLeg_dash ) );
408
+ double equivalent_notional = get_equivalent_notional(conversion_sign, ( *( Ns_array + knockedLeg_dash ) ), sim_dash[NL-1]);
409
+ sim_dash_pos[NL-1] = european_payoff(( *( Xs_array + (knockedLeg_dash) ) ), sim_dash[NL-1], cp_sign, dir_sign, equivalent_notional);
383
410
  }
411
+ else{
412
+ sim_dash_pos[NL-1] = get_equivalent_rebate(rebate_conversion_sign, ( *( Rebate_array + 0 ) ), sim_dash[NL-1]);
413
+ }
414
+
415
+ data[2][NL-1] = sim_pos[NL-1];
416
+ data[3][NL-1] = sim_dash_pos[NL-1];
384
417
  } else if(KType == FX_AMERICAN_BARRIER_KNOCKOUT_DISCRETE){
385
- int brk_flg = 1;
386
- int brk_flg_dash = 1;
387
- for( leg = 0; leg < NL; ++leg ) {
388
- if((leg != knockedLeg) && brk_flg){
389
- sim_pos[leg] = sim[leg] * ( *( Ns_array + leg ) );
390
- }else{
391
- brk_flg = 0;
392
- }
393
- if((leg != knockedLeg_dash) && brk_flg_dash){
394
- sim_dash_pos[leg] = sim[leg] * ( *( Ns_array + leg ) );
395
- }else{
396
- brk_flg_dash = 0;
397
- }
418
+ if(knockedLeg >= 0){
419
+ sim_pos[knockedLeg] = get_equivalent_rebate(rebate_conversion_sign, ( *( Rebate_array + knockedLeg ) ), sim[knockedLeg]);
420
+ }
421
+ else{
422
+ double equivalent_notional = get_equivalent_notional(conversion_sign, ( *( Ns_array + 0 ) ), sim[NL-1]);
423
+ sim_pos[NL-1] = european_payoff(( *( Xs_array + 0 ) ), sim[NL-1], cp_sign, dir_sign, equivalent_notional);
424
+ }
425
+ if(knockedLeg_dash >= 0 ){
426
+ sim_dash_pos[knockedLeg_dash] = get_equivalent_rebate(rebate_conversion_sign, ( *( Rebate_array + knockedLeg_dash ) ), sim[knockedLeg_dash]);
427
+ }
428
+ else{
429
+ double equivalent_notional = get_equivalent_notional(conversion_sign, ( *( Ns_array + 0 ) ), sim_dash[NL-1]);
430
+ sim_dash_pos[NL-1] = european_payoff(( *( Xs_array + 0 ) ), sim_dash[NL-1], cp_sign, dir_sign, equivalent_notional);
398
431
  }
399
432
  } else if( KType == ABSOLUTE || KType == PIVOT_ABSOLUTE || KType == COLLAR_ABSOLUTE || KType == DOUBLE_STRIKE_ABSOLUTE ) {
400
433
  for( leg = 0; leg < NL; ++leg ) {
@@ -562,11 +595,11 @@ VALUE method_run_monte_carlo( VALUE self, VALUE args ) {
562
595
  //
563
596
  // rb_p(rb_str_new2("Converting metrics"));
564
597
  VALUE final_metrics = rb_ary_new();
565
- for(metric = 0; metric < DATAPOINTS; metric++) {
598
+ for(metric = 0; metric < 5; metric++) {
566
599
  VALUE leg_metrics = rb_ary_new();
567
600
 
568
601
  for(leg = 0; leg < NL; leg++) {
569
- rb_ary_push( leg_metrics, DBL2NUM( metrics[metric][leg] ) );
602
+ rb_ary_push( leg_metrics, DBL2NUM( data[metric][leg] ) );
570
603
  }
571
604
 
572
605
  rb_ary_push(final_metrics, leg_metrics);
@@ -603,4 +636,4 @@ void Init_tarf_monte_carlo() {
603
636
  // void rb_define_singleton_method(VALUE klass, const char *name, VALUE (*func)(), int argc)
604
637
  rb_define_singleton_method(cTarfMonteCarlo, "box_muller", method_box_muller, 0);
605
638
  rb_define_singleton_method(cTarfMonteCarlo, "run_monte_carlo", method_run_monte_carlo, -2);
606
- }
639
+ }
@@ -3,5 +3,5 @@
3
3
  # gem yank tarf_monte_carlo -v 2.3
4
4
 
5
5
  module TarfMonteCarlo
6
- VERSION = "3.26"
6
+ VERSION = "3.31"
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.26'
4
+ version: '3.31'
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-02 00:00:00.000000000 Z
11
+ date: 2020-10-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler