tarf_monte_carlo 3.27 → 3.32
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/ext/tarf_monte_carlo/tarf_monte_carlo.c +56 -34
- 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: 2fd5c07e07e1a0fa016c6f8137c1e2b964f031b7210dca898e4d1006c0781ff4
|
4
|
+
data.tar.gz: 95210edd7247efc5785fec37c5c13cbe64f86a7509570382f19234174a021e4c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b9da6d59b8810e6ff75ca95a02c66f59081dfc368bca41de0b809a6c14468b5c1935e07bcb3ba8108766b423177b43d454788fd62c44566747c2f2122a412626
|
7
|
+
data.tar.gz: a954cdf5255f86459bae5c6c171b9232dfce4ec4fa13e1f1ef8d5ebfe18beac0defbcbb3ba6d33fbe05af28c889b28031139b60d5e2cac1fd4a468099c387d77
|
@@ -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]
|
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
|
|
@@ -215,26 +237,18 @@ VALUE method_run_monte_carlo( VALUE self, VALUE args ) {
|
|
215
237
|
Spot_dash = Spot_dash * exp( drift + vSqrdt * eps_dash );
|
216
238
|
|
217
239
|
if(KType == FX_AMERICAN_BARRIER_KNOCKIN_DISCRETE || KType == FX_AMERICAN_BARRIER_KNOCKOUT_DISCRETE){
|
218
|
-
profit_loss =
|
219
|
-
profit_loss_dash =
|
240
|
+
profit_loss = Spot;
|
241
|
+
profit_loss_dash = Spot_dash;
|
220
242
|
|
221
|
-
double knockin = (Spot - *(Barrier_array + leg)) *
|
222
|
-
double knockin_dash = (Spot_dash - *(Barrier_array + leg)) *
|
243
|
+
double knockin = (Spot - *(Barrier_array + leg)) * dir2_sign;
|
244
|
+
double knockin_dash = (Spot_dash - *(Barrier_array + leg)) * dir2_sign;
|
223
245
|
|
224
|
-
if(knockedLeg == -1 && knockin
|
246
|
+
if(knockedLeg == -1 && knockin >= 0){
|
225
247
|
knockedLeg = leg;
|
226
248
|
}
|
227
|
-
if(
|
228
|
-
|
249
|
+
if(knockedLeg_dash == -1 && knockin_dash >= 0){
|
250
|
+
knockedLeg_dash = leg;
|
229
251
|
}
|
230
|
-
|
231
|
-
// if(knockedLeg_dash == -1 && knockin_dash > 0){
|
232
|
-
// knockedLeg_dash = leg;
|
233
|
-
// }
|
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
252
|
} else if ( KType == DOUBLE_STRIKE_POINTS || KType == DOUBLE_STRIKE_ABSOLUTE || KType == DOUBLE_STRIKE_LEGS ) {
|
239
253
|
if ( Spot < *( LSts_array + leg ) ) {
|
240
254
|
profit_loss = Spot - (*( LSts_array + leg ));
|
@@ -376,25 +390,33 @@ VALUE method_run_monte_carlo( VALUE self, VALUE args ) {
|
|
376
390
|
double ko_so_far = K, ko_so_far_dash = K;
|
377
391
|
if(KType == FX_AMERICAN_BARRIER_KNOCKIN_DISCRETE){
|
378
392
|
if(knockedLeg >= 0){
|
379
|
-
|
393
|
+
double equivalent_notional = get_equivalent_notional(conversion_sign, ( *( Ns_array + knockedLeg ) ), sim[NL-1]);
|
394
|
+
sim_pos[NL-1] = european_payoff(( *( Xs_array + (knockedLeg) ) ), sim[NL-1], cp_sign, dir_sign, equivalent_notional);
|
395
|
+
}
|
396
|
+
else{
|
397
|
+
sim_pos[NL-1] = get_equivalent_rebate(rebate_conversion_sign, ( *( Rebate_array + 0 ) ), sim[NL-1]);
|
398
|
+
}
|
399
|
+
if(knockedLeg_dash >= 0 ){
|
400
|
+
double equivalent_notional = get_equivalent_notional(conversion_sign, ( *( Ns_array + knockedLeg_dash ) ), sim_dash[NL-1]);
|
401
|
+
sim_dash_pos[NL-1] = european_payoff(( *( Xs_array + (knockedLeg_dash) ) ), sim_dash[NL-1], cp_sign, dir_sign, equivalent_notional);
|
402
|
+
}
|
403
|
+
else{
|
404
|
+
sim_dash_pos[NL-1] = get_equivalent_rebate(rebate_conversion_sign, ( *( Rebate_array + 0 ) ), sim_dash[NL-1]);
|
380
405
|
}
|
381
|
-
// 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 ) );
|
383
|
-
// }
|
384
406
|
} else if(KType == FX_AMERICAN_BARRIER_KNOCKOUT_DISCRETE){
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
407
|
+
if(knockedLeg >= 0){
|
408
|
+
sim_pos[knockedLeg] = get_equivalent_rebate(rebate_conversion_sign, ( *( Rebate_array + knockedLeg ) ), sim[knockedLeg]);
|
409
|
+
}
|
410
|
+
else{
|
411
|
+
double equivalent_notional = get_equivalent_notional(conversion_sign, ( *( Ns_array + 0 ) ), sim[NL-1]);
|
412
|
+
sim_pos[NL-1] = european_payoff(( *( Xs_array + 0 ) ), sim[NL-1], cp_sign, dir_sign, equivalent_notional);
|
413
|
+
}
|
414
|
+
if(knockedLeg_dash >= 0 ){
|
415
|
+
sim_dash_pos[knockedLeg_dash] = get_equivalent_rebate(rebate_conversion_sign, ( *( Rebate_array + knockedLeg_dash ) ), sim[knockedLeg_dash]);
|
416
|
+
}
|
417
|
+
else{
|
418
|
+
double equivalent_notional = get_equivalent_notional(conversion_sign, ( *( Ns_array + 0 ) ), sim_dash[NL-1]);
|
419
|
+
sim_dash_pos[NL-1] = european_payoff(( *( Xs_array + 0 ) ), sim_dash[NL-1], cp_sign, dir_sign, equivalent_notional);
|
398
420
|
}
|
399
421
|
} else if( KType == ABSOLUTE || KType == PIVOT_ABSOLUTE || KType == COLLAR_ABSOLUTE || KType == DOUBLE_STRIKE_ABSOLUTE ) {
|
400
422
|
for( leg = 0; leg < NL; ++leg ) {
|
@@ -603,4 +625,4 @@ void Init_tarf_monte_carlo() {
|
|
603
625
|
// void rb_define_singleton_method(VALUE klass, const char *name, VALUE (*func)(), int argc)
|
604
626
|
rb_define_singleton_method(cTarfMonteCarlo, "box_muller", method_box_muller, 0);
|
605
627
|
rb_define_singleton_method(cTarfMonteCarlo, "run_monte_carlo", method_run_monte_carlo, -2);
|
606
|
-
}
|
628
|
+
}
|
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.32'
|
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-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|