[Home] [Help]
PACKAGE BODY: APPS.QRM_FX_FORMULAS
Source
1 PACKAGE BODY QRM_FX_FORMULAS AS
2 /* $Header: qrmfxflb.pls 115.19 2003/11/22 00:36:22 prafiuly ship $ */
3
4 /*-------------------------------------------------------------
5 FX_GK_OPTION_SENS_CV
6 Cover procedure to calculate the sensitivity of a currency option
7 using Garman-Kohlhagen formula, which is the extension of
8 Black-Scholes formula.
9
10 IMPORTANT: it is better to supply a Simple 30/360 (from GET_MD_FROM_SET)
11 interest rates for this procedure in order to avoid redundant conversions.
12
13 IMPORTANT: this procedure is only accurate up to six decimal places due
14 to CUMULATIVE_NORM_DISTRIBUTION procedure it calls.
15
16 GK_OPTION_SENS_IN_REC_TYPE:
17 p_SPOT_DATE
18 p_MATURITY_DATE
19 p_CCY_FOR
20 p_CCY_DOM
21 p_RATE_DOM
22 p_RATE_TYPE_DOM
23 p_COMPOUND_FREQ_DOM
24 p_DAY_COUNT_BASIS_DOM
25 p_RATE_FOR
26 p_RATE_TYPE_FOR
27 p_COMPOUND_FREQ
28 p_DAY_COUNT_BASIS_FOR
29 p_SPOT_RATE
30 p_STRIKE_RATE
31 p_VOLATILITY
32
33 GK_OPTION_SENS_OUT_REC_TYPE:
34 p_DELTA_CALL
35 p_DELTA_PUT
36 p_THETA_CALL
37 p_THETA_PUT
38 p_RHO_CALL
39 p_RHO_PUT
40 p_RHO_F_CALL
41 p_RHO_F_PUT
42 p_GAMMA
43 p_VEGA
44
45
46 Formula:
47 Calls FX_GK_OPTION_SENS
48
49 p_SPOT_DATE = the spot date where the option value is evaluated
50 p_MATURITY_DATE = the maturity date where the option expires
51 p_CCY_DOM = domestic currency
52 p_CCY_FOR = foreign currency
53 p_RATE_DOM = domestic risk free interest rate.
54 p_RATE_TYPE_DOM/FOR = the p_RF_RATE_DOM/FOR rate's type. 'S' for Simple
55 Rate. 'C' for Continuous Rate, and 'P' for Compounding Rate.
56 Default value = 'S' (Simple IR)
57 p_DAY_COUNT_BASIS_DOM/FOR = day count basis for p_RF_RATE_DOM/FOR.
58 p_RATE_FOR = foreign risk free interest rate.
59 p_SPOT_RATE = the current market exchange rate = the value of one unit
60 of the foreign currency measured in the domestic currency.
61 p_STRIKE_RATE = the strike price agreed in the option.
62 p_VOLATILITY = volatility
63 p_COMPOUND_FREQ_DOM/FOR = frequencies of discretely compounded input/output
64 rate. This is only necessary if p_RATE_TYPE_DOM/FOR is 'P'.
65 ---------------------------------------------------------------*/
66 -- added fhu 3/26/02
67
68 PROCEDURE FX_GK_OPTION_SENS_CV(p_rec_in IN GK_OPTION_SENS_IN_REC_TYPE,
69 p_rec_out OUT NOCOPY GK_OPTION_SENS_OUT_REC_TYPE)
70 IS
71
72 p_gk_in XTR_FX_FORMULAS.gk_option_cv_in_rec_type;
73 p_gk_out XTR_FX_FORMULAS.gk_option_cv_out_rec_type;
74 p_conv_in XTR_RATE_CONVERSION.rate_conv_in_rec_type;
75 p_conv_out XTR_RATE_CONVERSION.rate_conv_out_rec_type;
76
77 p_day_count NUMBER;
78 p_annual_basis NUMBER;
79
80 p_base_int_rate NUMBER;
81 p_contra_int_rate NUMBER;
82 p_strike_rate NUMBER := p_rec_in.p_strike_rate;
83
84 p_delta_call NUMBER;
85 p_delta_put NUMBER;
86 p_theta_call NUMBER;
87 p_theta_put NUMBER;
88 p_rho_call NUMBER;
89 p_rho_put NUMBER;
90 p_rho_f_call NUMBER;
91 p_rho_f_put NUMBER;
92 p_gamma NUMBER;
93 p_vega NUMBER;
94
95 p_base_ccy VARCHAR2(15);
96 p_contra_ccy VARCHAR2(15);
97 p_reverse BOOLEAN;
98
99 BEGIN
100 IF (g_proc_level>=g_debug_level) THEN --bug 3236479
101 XTR_RISK_DEBUG_PKG.dpush(null,'QRM_FX_FORMULAS.FX_GK_OPTION_SENS_CV');
102 END IF;
103
104 IF (p_rec_in.p_volatility = 0) THEN
105 raise QRM_MM_FORMULAS.e_option_vol_zero;
106 END IF;
107
108
109 -- find days to maturity
110 XTR_CALC_P.calc_days_run_c(p_rec_in.p_spot_date, p_rec_in.p_maturity_date,
111 '30/', null, p_day_count, p_annual_basis);
112 IF (g_proc_level>=g_debug_level) THEN
113 XTR_RISK_DEBUG_PKG.dlog('FX_GK_OPTION_SENS_CV: ' || 'day count: '||p_day_count);
114 END IF;
115
116 -- convert base int rate to continous compounded 30/360 day count basis
117 IF NOT (p_rec_in.p_rate_type_for IN ('C','c') AND
118 p_rec_in.p_day_count_basis_for = '30/') THEN
119 p_conv_in.p_start_date := p_rec_in.p_spot_date;
120 p_conv_in.p_end_date := p_rec_in.p_maturity_date;
121 p_conv_in.p_day_count_basis_in := p_rec_in.p_day_count_basis_for;
122 p_conv_in.p_day_count_basis_out := '30/';
123 p_conv_in.p_rate_type_in := p_rec_in.p_rate_type_for;
124 p_conv_in.p_rate_type_out := 'C';
125 p_conv_in.p_compound_freq_in := p_rec_in.p_compound_freq_for;
126 p_conv_in.p_rate_in := p_rec_in.p_rate_for;
127 XTR_RATE_CONVERSION.rate_conversion(p_conv_in, p_conv_out);
128 p_base_int_rate := p_conv_out.p_rate_out;
129 IF (g_proc_level>=g_debug_level) THEN
130 XTR_RISK_DEBUG_PKG.dlog('FX_GK_OPTION_SENS_CV: ' || 'CONVERTED continuous base int rate:'||p_base_int_rate);
131 END IF;
132 END IF;
133
134 -- convert contra int rate to continuous compounded 30/360 day count basis
135 IF NOT (p_rec_in.p_rate_type_dom IN ('C','c') AND
136 p_rec_in.p_day_count_basis_dom = '30/') THEN
137 p_conv_in.p_start_date := p_rec_in.p_spot_date;
138 p_conv_in.p_end_date := p_rec_in.p_maturity_date;
139 p_conv_in.p_day_count_basis_in := p_rec_in.p_day_count_basis_dom;
140 p_conv_in.p_day_count_basis_out := '30/';
141 p_conv_in.p_rate_type_in := p_rec_in.p_rate_type_dom;
142 p_conv_in.p_rate_type_out := 'C';
143 p_conv_in.p_compound_freq_in := p_rec_in.p_compound_freq_dom;
144 p_conv_in.p_rate_in := p_rec_in.p_rate_dom;
145 XTR_RATE_CONVERSION.rate_conversion(p_conv_in, p_conv_out);
146 p_contra_int_rate := p_conv_out.p_rate_out;
147 IF (g_proc_level>=g_debug_level) THEN
148 XTR_RISK_DEBUG_PKG.dlog('FX_GK_OPTION_SENS_CV: ' || 'continuous contra int rate:'||p_contra_int_rate);
149 END IF;
150 END IF;
151
152 -- determine whether to invert strike price
153 -- invert when deal foreign ccy <> system base ccy
154 p_base_ccy := p_rec_in.p_ccy_for;
155 p_contra_ccy := p_rec_in.p_ccy_dom;
156 get_base_contra(p_base_ccy, p_contra_ccy, p_reverse);
157 IF (p_base_ccy <> p_rec_in.p_ccy_for) THEN
158 p_strike_rate := 1/p_rec_in.p_strike_rate;
159 END IF;
160 IF (g_proc_level>=g_debug_level) THEN
161 XTR_RISK_DEBUG_PKG.dlog('FX_GK_OPTION_SENS_CV: ' || 'strike rate is: '||p_strike_rate);
162 END IF;
163
164 fx_gk_option_sens(p_day_count, p_base_int_rate, p_contra_int_rate,
165 p_rec_in.p_spot_rate, p_strike_rate, p_rec_in.p_volatility,
166 p_delta_call, p_delta_put, p_theta_call, p_theta_put, p_rho_call,
167 p_rho_put, p_rho_f_call, p_rho_f_put, p_gamma, p_vega);
168
169 p_rec_out.p_delta_call := p_delta_call;
170 p_rec_out.p_delta_put := p_delta_put;
171 p_rec_out.p_theta_call := p_theta_call;
172 p_rec_out.p_theta_put := p_theta_put;
173 p_rec_out.p_rho_call := p_rho_call;
174 p_rec_out.p_rho_put := p_rho_put;
175 p_rec_out.p_rho_f_call := p_rho_f_call;
176 p_rec_out.p_rho_f_put := p_rho_f_put;
177 p_rec_out.p_gamma := p_gamma;
178 p_rec_out.p_vega := p_vega;
179
180 IF (g_proc_level>=g_debug_level) THEN --bug 3236479
181 XTR_RISK_DEBUG_PKG.dpop(null,'QRM_FX_FORMULAS.FX_GK_OPTION_SENS_CV');
182 END IF;
183 END FX_GK_OPTION_SENS_CV;
184
185
186 -- added fhu 6/19/01
187 -- modified fhu 3/27/02
188 PROCEDURE FX_GK_OPTION_SENS(
189 l_days IN NUMBER,
190 l_for_int_rate IN NUMBER,
191 l_dom_int_rate IN NUMBER,
192 l_spot_rate IN NUMBER,
193 l_strike_rate IN NUMBER,
194 vol IN NUMBER,
195 l_delta_call IN OUT NOCOPY NUMBER,
196 l_delta_put IN OUT NOCOPY NUMBER,
197 l_theta_call IN OUT NOCOPY NUMBER,
198 l_theta_put IN OUT NOCOPY NUMBER,
199 l_rho_call IN OUT NOCOPY NUMBER,
200 l_rho_put IN OUT NOCOPY NUMBER,
201 l_rho_f_call IN OUT NOCOPY NUMBER,
202 l_rho_f_put IN OUT NOCOPY NUMBER,
203 l_gamma IN OUT NOCOPY NUMBER,
204 l_vega IN OUT NOCOPY NUMBER) is
205
206 n_d1 number;
207 n_d2 number;
208 n_d1_a number;
209 n_d2_a number;
210 l_call number;
211 l_put number;
212 l_forward number;
213
214 r_f NUMBER := l_for_int_rate / 100;
215 r NUMBER := l_dom_int_rate / 100;
216 t NUMBER := l_days / 360;
217 v NUMBER := vol / 100;
218
219 BEGIN
220 IF (g_proc_level>=g_debug_level) THEN --bug 3236479
221 XTR_RISK_DEBUG_PKG.dpush(null,'QRM_FX_FORMULAS.FX_GK_OPTION_SENS');
222 END IF;
223 IF (vol = 0) THEN
224 raise QRM_MM_FORMULAS.e_option_vol_zero;
225 END IF;
226
227 -- call XTR_FX_FORMULAS.FX_GK_OPTION_PRICE
228 XTR_FX_FORMULAS.FX_GK_OPTION_PRICE(l_days, l_for_int_rate, l_dom_int_rate,
229 l_spot_rate, l_strike_rate, vol, l_call, l_put, l_forward, n_d1,
230 n_d2, n_d1_a, n_d2_a);
231
232 l_delta_call := EXP((-r_f)*t)*n_d1;
233 l_delta_put := EXP((-r_f)*t)*(n_d1 - 1);
234 l_gamma := (n_d1_a*EXP((-r_f)*t))/(l_spot_rate*v*SQRT(t));
235 l_vega := l_spot_rate*SQRT(t)*n_d1_a*EXP(-r_f*t);
236 l_theta_call := -((l_spot_rate*n_d1_a*v*EXP((-r_f)*t))/(2*SQRT(t)))+r_f*l_spot_rate*n_d1*EXP((-r_f)*t)-(r*l_strike_rate*EXP(-r*t)*n_d2);
237 l_theta_put := -((l_spot_rate*n_d1_a*v*EXP((-r_f)*t))/(2*SQRT(t)))-r_f*l_spot_rate*(1-n_d1)*EXP((-r_f)*t)+(r*l_strike_rate*EXP(-r*t)*(1-n_d2));
238 l_rho_call := l_strike_rate*t*EXP(-r*t)*n_d2;
239 l_rho_put := -l_strike_rate*t*EXP(-r*t)*(1-n_d2);
240 l_rho_f_call := -t*EXP((-r_f)*t)*l_spot_rate*n_d1;
241 l_rho_f_put := t*EXP((-r_f)*t)*l_spot_rate*(1-n_d1);
242
243 IF (g_proc_level>=g_debug_level) THEN --bug 3236479
244 XTR_RISK_DEBUG_PKG.dpop(null,'QRM_FX_FORMULAS.FX_GK_OPTION_SENS');
245 END IF;
246 END FX_GK_OPTION_SENS;
247
248 -- modified by sankim 9/14/01
249 /*
250 Calculates the DELTA SPOT of a FX forward. The Delta spot measures the
251 rate of change of the FX Forward Rate with respect to the Spot Rate.
252 See Deal Calculations HLD.
253
254 The arguments are defined as follows:
255 * p_CONTRA/BASE_CUR = Contra/Bid currency
256 * p_DF_CONTRA_BID/ASK = discount factor for the contra currency(Bid and Ask
257 side)
258 * p_DF_BASE_BID/ASK = discount factor for the base currency(Bid and Ask side)
259 * p_DF_USD_BID/ASK = discount factor for the USD(Bid and Ask side) required
260 only if USD is not Base or Contra
261 Returned:
262 * p_DELTA = delta spot(bid and ask returned as xtr_md_num_table[2]
263 (BID side = xtr_md_num_table[1],ASK side = xtr_md_num_table[2]))
264 All of USD discount factor parameters defaults to null because they are not
265 required if Base or Contra currency is USD. They are required if USD is not
266 Base or Contra However, if insufficient input is provided, error will be
267 raised. Because of the optional parameters, to use this function, the caller
268 can just pass in 6 parameters instead of 8, not passing in the last two USD
269 discount factors if they are not necessary.If it makes it easier, feel free to
270 pass values to all six discount factor parameters. This procedure will only
271 use the relevant parameters and ignore the rest.
272 */
273 FUNCTION FX_FORWARD_DELTA_SPOT(p_contra_cur IN VARCHAR2,
274 p_base_cur IN VARCHAR2,
275 p_df_contra_bid IN NUMBER,
276 p_df_contra_ask IN NUMBER,
277 p_df_base_bid IN NUMBER,
278 p_df_base_ask IN NUMBER,
279 p_df_usd_bid IN NUMBER,
280 p_df_usd_ask IN NUMBER)
281 RETURN XTR_MD_NUM_TABLE IS
282 v_results XTR_MD_NUM_TABLE:= XTR_MD_NUM_TABLE();
283
284 BEGIN
285 IF (g_proc_level>=g_debug_level) THEN --bug 3236479
286 XTR_RISK_DEBUG_PKG.dpush(null,'QRM_FX_FORMULAS.FX_FORWARD_DELTA_SPOT');
287 END IF;
288
289 v_results.extend;
290 v_results.extend;
291 -- calculate bid
292 IF p_contra_cur <> 'USD' and p_base_cur <> 'USD' THEN
293 IF (p_df_usd_bid is NULL) OR (p_df_usd_ask is NULL) THEN
294 RAISE_APPLICATION_ERROR
295 (-20001,'p_DF_USD_ASK or p_DF_USD_BID are missing.');
296 ELSE
297 v_results(1):= (p_df_usd_ask/p_df_base_bid)*
298 (p_df_contra_ask/p_df_usd_bid);
299 END IF;
300 ELSE
301 v_results(1):= (p_df_contra_ask/p_df_base_bid);
302 END IF;
303 -- calculate ask
304 IF p_contra_cur <> 'USD' and p_base_cur <> 'USD' THEN
305 v_results(2):= (p_df_usd_bid/p_df_base_ask)*(p_df_contra_bid/p_df_usd_ask);
306 ELSE
307 v_results(2):= (p_df_contra_bid/p_df_base_ask);
308 END IF;
309
310 IF (g_proc_level>=g_debug_level) THEN --bug 3236479
311 XTR_RISK_DEBUG_PKG.dpop(null,'QRM_FX_FORMULAS.FX_FORWARD_DELTA_SPOT');
312 END IF;
313
314 RETURN v_results;
315 END FX_FORWARD_DELTA_SPOT;
316
317
318
319
320
321 -- added fhu 6/12/01
322 --modified sankim 9/18/01
323 /*
324 Calculates the RHO, DELTA CONTRA/BASE INTEREST RATE of a FX forward.
325 See Deal Calculations HLD.
326 Example for FX: CHFGBP -> CHF = Base Currency
327 GBP = Contra Currency
328 parameters
329 * p_OUT = 'C' if want p_RHO to be rho contra, 'B' if want p_RHO to be rho base,
330 or 'D' if want both
331 * p_SPOT_RATE_BASE_BID/ASK = fair exchange rate of between the base currency
332 against USD. If the base currency is USD, then the default value of 1 should be
333 used.
334 * p_SPOT_RATE_CONTRA_BID/ASK = fair exchange rate of between the contra
335 currency against USD. If the contra currency is USD, then the default value of
336 1 should be used.
337 * p_BASE_CURR_INT_RATE_BID/ASK = bid/ask risk free interest rate for the base
338 currency. This parameter should be null if the base currency is USD.
339 * p_CONTRA_CURR_INT_RATE_BID/ASK = bid/ask risk free interest rate for the
340 contra currency. This parameter should be null if the contra currency is USD.
341 * p_USD _CURR_INT_RATE = risk free interest rate for the USD.
342 * p_DAY_COUNT_BASE/CONTRA = number of days between the spot date and the
343 forward date. If the contra currency is USD, then p_DAY_COUNT_CONTRA should be
344 null, and vice versa in the case of base is USD.
345 * p_ANNUAL_BASIS_BASE/CONTRA = number of days in a year of which the
346 p_DAY_COUNT_BASE/CONTRA and the p_BASE/CONTRA_CURR_INT_RATE are based on. If
347 the contra currency is USD, then p_ANNUAL_BASIS_CONTRA should be null, and vice
348 versa in the case of base is USD.
349 * p_DAY_COUNT_USD = number of days between the spot date and the forward date.
350 = number of days in a year of which the p_DAY_COUNT_USD and the
351 p_USD _CURR_INT_RATE are based on.
352 * p_ANNUAL_BASIS_USD = number of days in a year of which the p_DAY_COUNT_USD
353 and the p_USD _CURR_INT_RATE are based on.
354 * p_CURRENCY_CONTRA/BASE = the currency for contra/base.
355 * p_QUOTATION_BASIS_CONTRA/BASE indicates the quotation basis against USD for
356 the CONTRA /BASE side, 'C' for Commodity Unit Quote (=USDGBP) and 'B' for Base
357 Unit Quote (= GBPUSD) (Definitions are in FX Calculator HLD). This parameter is
358 required if base/contra is non-USD accordingly.
359 Returned:
360 * p_RHO (BID/ASK) indicates the bid/ask side of rho(bid and ask returned as
361 xtr_md_num_table[2](BID side = xtr_md_num_table[1],
362 ASK side = xtr_md_num_table[2]))
363 if p_OUT ='D' then the returned value is as following:
364 p_RHO xtr_md_num_table[4](Base BID side = xtr_md_num_table[1],
365 Base ASK side = xtr_md_num_table[2],
366 Contra BID side = xtr_md_num_table[3],
367 Contra ASK side = xtr_md_num_table[4])
368
369 Calls XTR_FX_FORMULAS.FX_FORWARD_RATE_CV (see def of fx_forward_rate above)
370 */
371 FUNCTION FX_FORWARD_RHO(p_out IN VARCHAR2,
372 p_spot_rate_base_bid IN NUMBER,
373 p_spot_rate_base_ask IN NUMBER,
377 p_base_curr_int_rate_ask IN NUMBER,
374 p_spot_rate_contra_bid IN NUMBER,
375 p_spot_rate_contra_ask IN NUMBER,
376 p_base_curr_int_rate_bid IN NUMBER,
378 p_contra_curr_int_rate_bid IN NUMBER,
379 p_contra_curr_int_rate_ask IN NUMBER,
380 p_usd_curr_int_rate_bid IN NUMBER,
381 p_usd_curr_int_rate_ask IN NUMBER,
382 p_day_count_base IN NUMBER,
383 p_day_count_contra IN NUMBER,
384 p_day_count_usd IN NUMBER,
385 p_annual_basis_base IN NUMBER,
386 p_annual_basis_contra IN NUMBER,
387 p_annual_basis_usd IN NUMBER,
388 p_currency_base IN VARCHAR2,
389 p_currency_contra IN VARCHAR2,
390 p_quotation_basis_base IN VARCHAR2,
391 p_quotation_basis_contra IN VARCHAR2)
392 RETURN XTR_MD_NUM_TABLE IS
393
394
395 v_forward_rate_base XTR_MD_NUM_TABLE:=XTR_MD_NUM_TABLE();
396 v_forward_rate_shifted XTR_MD_NUM_TABLE:=XTR_MD_NUM_TABLE();
397 v_rho XTR_MD_NUM_TABLE:=XTR_MD_NUM_TABLE();
398
399
400 BEGIN
401 IF (g_proc_level>=g_debug_level) THEN
402 xtr_risk_debug_pkg.dpush(null,'QRM_FX_FROMULAS.FX_FORWARD_RHO');
403 END IF;
404 v_forward_rate_base.extend;
405 v_forward_rate_base.extend;
406 v_forward_rate_shifted.extend;
407 v_forward_rate_shifted.extend;
408 v_rho.extend;
409 v_rho.extend;
410 IF p_out not in ('D','C','B') THEN
411 RAISE_APPLICATION_ERROR(-20001,'p_OUT must be ''C'',''B'',or ''D''.');
412 END IF;
413 IF p_out = 'B' or p_out = 'D' THEN
414 -- calculate base base forward rate
415 v_forward_rate_base:=XTR_FX_FORMULAS.fx_forward_rate_cv(
416 p_spot_rate_base_bid,p_spot_rate_base_ask, p_spot_rate_contra_bid,
417 p_spot_rate_contra_ask,p_base_curr_int_rate_bid, p_base_curr_int_rate_ask,
418 p_contra_curr_int_rate_bid, p_contra_curr_int_rate_ask,
419 p_usd_curr_int_rate_bid, p_usd_curr_int_rate_ask, p_day_count_base,
420 p_day_count_contra, p_day_count_usd, p_annual_basis_base,
421 p_annual_basis_contra, p_annual_basis_usd, p_currency_base,
422 p_currency_contra, p_quotation_basis_base, p_quotation_basis_contra);
423
424 -- calculate shifted base forward rate
425 IF p_currency_base = 'USD' THEN
426 v_forward_rate_shifted:=XTR_FX_FORMULAS.fx_forward_rate_cv(
427 p_spot_rate_base_bid,p_spot_rate_base_ask, p_spot_rate_contra_bid,
428 p_spot_rate_contra_ask,p_base_curr_int_rate_bid,
429 p_base_curr_int_rate_ask, p_contra_curr_int_rate_bid,
430 p_contra_curr_int_rate_ask, p_usd_curr_int_rate_bid+0.01,
431 p_usd_curr_int_rate_ask+0.01, p_day_count_base, p_day_count_contra,
432 p_day_count_usd, p_annual_basis_base, p_annual_basis_contra,
433 p_annual_basis_usd, p_currency_base, p_currency_contra,
434 p_quotation_basis_base, p_quotation_basis_contra);
435 ELSE
436 v_forward_rate_shifted:=XTR_FX_FORMULAS.fx_forward_rate_cv(
437 p_spot_rate_base_bid,p_spot_rate_base_ask, p_spot_rate_contra_bid,
438 p_spot_rate_contra_ask,p_base_curr_int_rate_bid+0.01,
439 p_base_curr_int_rate_ask+0.01, p_contra_curr_int_rate_bid,
440 p_contra_curr_int_rate_ask, p_usd_curr_int_rate_bid,
441 p_usd_curr_int_rate_ask, p_day_count_base, p_day_count_contra,
442 p_day_count_usd, p_annual_basis_base, p_annual_basis_contra,
443 p_annual_basis_usd, p_currency_base, p_currency_contra,
444 p_quotation_basis_base, p_quotation_basis_contra);
445 END IF;
446
447 --bidfirst
448 v_rho(1):=(v_forward_rate_shifted(1) - v_forward_rate_base(1))/.0001;
449 IF (g_proc_level>=g_debug_level) THEN
450 XTR_RISK_DEBUG_PKG.dlog('FX_FORWARD_RHO: ' || 'base bid forward rate: '||v_forward_rate_base(1));
451 XTR_RISK_DEBUG_PKG.dlog('FX_FORWARD_RHO: ' || 'base bid forward rate shifted: '||v_forward_rate_shifted(1));
452 END IF;
453 --ask
454 v_rho(2):=(v_forward_rate_shifted(2) - v_forward_rate_base(2))/.0001;
455 IF (g_proc_level>=g_debug_level) THEN
456 XTR_RISK_DEBUG_PKG.dlog('FX_FORWARD_RHO: ' || 'base ask forward rate: '||v_forward_rate_base(2));
457 XTR_RISK_DEBUG_PKG.dlog('FX_FORWARD_RHO: ' || 'base ask forward rate shifted: '||v_forward_rate_shifted(2));
458 END IF;
459 IF p_out = 'B' THEN
460 IF (g_proc_level>=g_debug_level) THEN
461 xtr_risk_debug_pkg.dpop('FX_FORWARD_RHO: ' || 'Rho');
462 END IF;
463 return v_rho;
464 END IF;
465 END IF;
466 IF p_out = 'C'OR p_out = 'D' THEN
467 -- calculate base contra forward rate
468 v_forward_rate_base:=XTR_FX_FORMULAS.fx_forward_rate_cv(
469 p_spot_rate_base_bid,p_spot_rate_base_ask, p_spot_rate_contra_bid,
470 p_spot_rate_contra_ask,p_base_curr_int_rate_bid, p_base_curr_int_rate_ask,
471 p_contra_curr_int_rate_bid, p_contra_curr_int_rate_ask,
472 p_usd_curr_int_rate_bid, p_usd_curr_int_rate_ask, p_day_count_base,
473 p_day_count_contra, p_day_count_usd, p_annual_basis_base,
474 p_annual_basis_contra, p_annual_basis_usd, p_currency_base,
475 p_currency_contra, p_quotation_basis_base, p_quotation_basis_contra);
476
477 -- calculate shifted contra forward rate
478 IF p_currency_contra = 'USD' THEN
479 v_forward_rate_shifted:=XTR_FX_FORMULAS.fx_forward_rate_cv(
480 p_spot_rate_base_bid,p_spot_rate_base_ask, p_spot_rate_contra_bid,
481 p_spot_rate_contra_ask,p_base_curr_int_rate_bid, p_base_curr_int_rate_ask
482 , p_contra_curr_int_rate_bid, p_contra_curr_int_rate_ask,
483 p_usd_curr_int_rate_bid+0.01, p_usd_curr_int_rate_ask+0.01,
484 p_day_count_base, p_day_count_contra, p_day_count_usd,
488 ELSE
485 p_annual_basis_base, p_annual_basis_contra, p_annual_basis_usd,
486 p_currency_base, p_currency_contra, p_quotation_basis_base,
487 p_quotation_basis_contra);
489 v_forward_rate_shifted:=XTR_FX_FORMULAS.fx_forward_rate_cv(
490 p_spot_rate_base_bid,p_spot_rate_base_ask, p_spot_rate_contra_bid,
491 p_spot_rate_contra_ask,p_base_curr_int_rate_bid, p_base_curr_int_rate_ask
492 , p_contra_curr_int_rate_bid+0.01, p_contra_curr_int_rate_ask+0.01,
493 p_usd_curr_int_rate_bid, p_usd_curr_int_rate_ask, p_day_count_base,
494 p_day_count_contra, p_day_count_usd, p_annual_basis_base,
495 p_annual_basis_contra, p_annual_basis_usd, p_currency_base,
496 p_currency_contra, p_quotation_basis_base, p_quotation_basis_contra);
497 END IF;
498
499 --bid first
500 IF (g_proc_level>=g_debug_level) THEN
501 xtr_risk_debug_pkg.dlog('FX_FORWARD_RHO: ' || 'v_forward_rate_base bid',v_forward_rate_base(1));
502 xtr_risk_debug_pkg.dlog('FX_FORWARD_RHO: ' || 'v_forward_rate_base ask',v_forward_rate_base(2));
503 xtr_risk_debug_pkg.dlog('FX_FORWARD_RHO: ' || 'v_forward_rate_shifted bid',v_forward_rate_shifted(1));
504 xtr_risk_debug_pkg.dlog('FX_FORWARD_RHO: ' || 'v_forward_rate_shifted ask',v_forward_rate_shifted(2));
505 END IF;
506 IF p_out = 'C' THEN
507 --just calculating contra
508 v_rho(1):=(v_forward_rate_shifted(1) - v_forward_rate_base(1))/.0001;
509 --ask
510 v_rho(2):=(v_forward_rate_shifted(2) - v_forward_rate_base(2))/.0001;
511 ELSE
512 -- calculating both base and contra
513 v_rho.extend;
514 v_rho.extend;
515 --bid
516 v_rho(3):=(v_forward_rate_shifted(1) - v_forward_rate_base(1))/.0001;
517 --ask
518 v_rho(4):=(v_forward_rate_shifted(2) - v_forward_rate_base(2))/.0001;
519 IF (g_proc_level>=g_debug_level) THEN
520 XTR_RISK_DEBUG_PKG.dlog('FX_FORWARD_RHO: ' || 'contra bid forward rate: '||v_forward_rate_base(1));
521 XTR_RISK_DEBUG_PKG.dlog('FX_FORWARD_RHO: ' || 'contra bid forward rate shifted: '||v_forward_rate_shifted(1));
522 XTR_RISK_DEBUG_PKG.dlog('FX_FORWARD_RHO: ' || 'contra ask forward rate: '||v_forward_rate_base(2));
523 XTR_RISK_DEBUG_PKG.dlog('FX_FORWARD_RHO: ' || 'contra ask forward rate shifted: '||v_forward_rate_shifted(2));
524 END IF;
525 END IF;
526 IF (g_proc_level>=g_debug_level) THEN
527 xtr_risk_debug_pkg.dpop(null,'QRM_FX_FROMULAS.FX_FORWARD_RHO');
528 END IF;
529 return v_rho;
530 END IF;
531 END FX_FORWARD_RHO;
532
533 /* SENSITIVITIES of FX OPTION -- See FX_GK_OPTION_PRICE procedure */
534
535
536 /*************** Fair Value Calculations *******/
537
538 /*********************************************************/
539 /* This procedure returns base and contra currency info */
540 /* from system rate setup.Also return TRUE */
541 /* if we need to invert base and contra */
542 /*********************************************************/
543 PROCEDURE get_base_contra(
544 p_base IN OUT NOCOPY VARCHAR2,
545 p_contra IN OUT NOCOPY VARCHAR2,
546 p_reverse OUT NOCOPY BOOLEAN) IS
547
548 l_cur VARCHAR2(15) := NULL;
549 cursor c_cur is
550 select CURRENCY_FIRST
551 from XTR_BUY_SELL_COMBINATIONS
552 where (CURRENCY_BUY = p_base and CURRENCY_SELL = p_contra)
553 or (CURRENCY_BUY = p_contra and CURRENCY_SELL = p_base);
554
555 begin
556 for l_tmp in c_cur loop
557 l_cur := l_tmp.CURRENCY_FIRST;
558 end loop;
559
560 if l_cur = p_base then
561 p_reverse := false;
562 else
563 -- swap it
564 p_reverse := true;
565 p_contra := p_base;
566 p_base := l_cur;
567 end if;
568
569 end get_base_contra;
570
571
572 PROCEDURE fv_fxo(p_price_model IN VARCHAR2,
573 p_deal_subtype IN VARCHAR2,
574 p_option_type IN VARCHAR2,
575 p_set_code IN VARCHAR2,
576 p_for_ccy IN VARCHAR2,
577 p_premium_ccy IN VARCHAR2,
578 p_buy_ccy IN VARCHAR2,
579 p_sell_ccy IN VARCHAR2,
580 p_interpolation_method IN VARCHAR2,
581 p_spot_date IN DATE,
582 p_future_date IN DATE,
583 p_strike_price IN NUMBER,
584 p_for_amount IN NUMBER,
585 p_side IN OUT NOCOPY VARCHAR2,
586 p_forward_rate IN OUT NOCOPY NUMBER,
587 p_fair_value IN OUT NOCOPY NUMBER) IS
588
589 p_base_ccy VARCHAR2(15);
590 p_contra_ccy VARCHAR2(15);
591 p_dom_ccy VARCHAR2(15);
592 p_ref_ccy VARCHAR2(15);
593 p_counter_ccy VARCHAR2(15);
594 p_dummy BOOLEAN;
595 p_cap_or_floor VARCHAR2(5);
596 p_day_count_basis VARCHAR2(15) := '30/';
597
598 p_volatility NUMBER;
599 p_buy_int_rate NUMBER;
600 p_sell_int_rate NUMBER;
601 p_base_rate NUMBER;
602 p_contra_rate NUMBER;
603 p_base_amount NUMBER;
604 p_contra_amount NUMBER;
605 p_spot_rate NUMBER;
606 p_strike NUMBER;
607 p_call_price NUMBER;
608 p_put_price NUMBER;
609
610 p_md_in xtr_market_data_p.md_from_set_in_rec_type;
611 p_md_out xtr_market_data_p.md_from_set_out_rec_type;
612 p_conv_in XTR_RATE_CONVERSION.RATE_CONV_IN_REC_TYPE;
613 p_conv_out XTR_RATE_CONVERSION.RATE_CONV_OUT_REC_TYPE;
614 p_fx_in XTR_FX_FORMULAS.GK_OPTION_CV_IN_REC_TYPE;
615 p_fx_out XTR_FX_FORMULAS.GK_OPTION_CV_OUT_REC_TYPE;
616
620 END IF;
617 BEGIN
618 IF (g_proc_level>=g_debug_level) THEN
619 XTR_RISK_DEBUG_PKG.dpush(null,'QRM_FX_FROMULAS.FV_FXO');
621 IF (p_price_model = 'GARMAN_KOHL') THEN
622 -- get base/contra currencies straight
623 p_base_ccy := p_buy_ccy;
624 p_contra_ccy := p_sell_ccy;
625 get_base_contra(p_base_ccy, p_contra_ccy, p_dummy);
626 IF (g_proc_level>=g_debug_level) THEN
627 XTR_RISK_DEBUG_PKG.dlog('fv_fxo: ' || 'base ccy: '||p_base_ccy);
628 XTR_RISK_DEBUG_PKG.dlog('fv_fxo: ' || 'contra ccy: '||p_contra_ccy);
629 END IF;
630
631 IF (p_deal_subtype = 'BUY') THEN
632 p_side := 'A';
633 ELSIF (p_deal_subtype = 'SELL') THEN
634 p_side := 'B';
635 ELSE
636 RAISE_APPLICATION_ERROR(-20001,'p_deal_subtype must be BUY or SELL');
637 END IF;
638
639 -- get volatility
640 p_md_in.p_md_set_code := p_set_code;
641 p_md_in.p_source := 'C';
642 p_md_in.p_indicator := 'V';
643 p_md_in.p_spot_date := p_spot_date;
644 p_md_in.p_future_date := p_future_date;
645 p_md_in.p_ccy := p_base_ccy;
646 p_md_in.p_contra_ccy := p_contra_ccy;
647 p_md_in.p_day_count_basis_out := p_day_count_basis;
648 p_md_in.p_interpolation_method := p_interpolation_method;
649 p_md_in.p_side := p_side;
650 p_md_in.p_batch_id := null;
651 p_md_in.p_bond_code := null;
652 XTR_MARKET_DATA_P.get_md_from_set(p_md_in, p_md_out);
653 p_volatility := p_md_out.p_md_out;
654 IF (p_volatility = 0) THEN
655 raise QRM_MM_FORMULAS.e_option_vol_zero;
656 END IF;
657 IF (g_proc_level>=g_debug_level) THEN
658 XTR_RISK_DEBUG_PKG.dlog('fv_fxo: ' || 'volatility: '||p_volatility);
659 END IF;
660
661 -- get interest rate buy buy currency (ask side)
662 p_md_in.p_side := 'A';
663 p_md_in.p_indicator := 'Y';
664 p_md_in.p_ccy := p_buy_ccy;
665 XTR_MARKET_DATA_P.get_md_from_set(p_md_in, p_md_out);
666 p_buy_int_rate := p_md_out.p_md_out;
667 IF (g_proc_level>=g_debug_level) THEN
668 XTR_RISK_DEBUG_PKG.dlog('fv_fxo: ' || 'buy ccy interp int rate: '||p_buy_int_rate);
669 END IF;
670
671 -- get interest rate for sell currency (bid side);
672 p_md_in.p_side := 'B';
673 p_md_in.p_ccy := p_sell_ccy;
674 XTR_MARKET_DATA_P.get_md_from_set(p_md_in, p_md_out);
675 p_sell_int_rate := p_md_out.p_md_out;
676 IF (g_proc_level>=g_debug_level) THEN
677 XTR_RISK_DEBUG_PKG.dlog('fv_fxo: ' || 'sell ccy interp int rate: '||p_sell_int_rate);
678 END IF;
679
680 -- convert buy/sell interest rate into base/contra
681 IF (p_buy_ccy = p_base_ccy) THEN
682 p_base_rate := p_buy_int_rate;
683 p_contra_rate := p_sell_int_rate;
684 ELSE
685 p_base_rate := p_sell_int_rate;
686 p_contra_rate := p_buy_int_rate;
687 END IF;
688
689 IF (g_proc_level>=g_debug_level) THEN
690 XTR_RISK_DEBUG_PKG.dlog('fv_fxo: ' || 'base ccy int rate: '||p_base_rate);
691 XTR_RISK_DEBUG_PKG.dlog('fv_fxo: ' || 'contra ccy int rate: '||p_contra_rate);
692 END IF;
693
694 -- convert to continuously compounded rates
695 p_conv_in.p_start_date := p_spot_date;
696 p_conv_in.p_end_date := p_future_date;
697 p_conv_in.p_day_count_basis_out := p_day_count_basis;
698 p_conv_in.p_rate_type_in := 'S';
699 p_conv_in.p_rate_type_out := 'C';
700 p_conv_in.p_rate_in := p_base_rate;
701 XTR_RATE_CONVERSION.rate_conversion(p_conv_in, p_conv_out);
702 p_base_rate := p_conv_out.p_rate_out;
703 p_conv_in.p_rate_in := p_contra_rate;
704 XTR_RATE_CONVERSION.rate_conversion(p_conv_in, p_conv_out);
705 p_contra_rate := p_conv_out.p_rate_out;
706
707 IF (g_proc_level>=g_debug_level) THEN
708 XTR_RISK_DEBUG_PKG.dlog('fv_fxo: ' || 'base ccy compounded int rate: '||p_base_rate);
709 XTR_RISK_DEBUG_PKG.dlog('fv_fxo: ' || 'contra ccy compounded int rate: '||p_contra_rate);
710 END IF;
711
712 -- get fx spot rate
713 IF (p_sell_ccy = p_base_ccy) THEN
714 p_side := 'B';
715 ELSE
716 p_side := 'A';
717 END IF;
718 p_md_in.p_indicator := 'S';
719 -- want spot rate in for_ccy/dom_ccy form
720 IF (p_for_ccy = p_base_ccy) THEN
721 p_md_in.p_ccy := p_base_ccy;
722 p_md_in.p_contra_ccy := p_contra_ccy;
723 p_dom_ccy := p_contra_ccy;
724 p_strike := p_strike_price;
725 ELSE
726 p_md_in.p_ccy := p_contra_ccy;
727 p_md_in.p_contra_ccy := p_base_ccy;
728 p_dom_ccy := p_base_ccy;
729 p_strike := 1/p_strike_price;
730 END IF;
731 p_md_in.p_side := p_side;
732 XTR_MARKET_DATA_P.get_md_from_set(p_md_in, p_md_out);
733 p_spot_rate := p_md_out.p_md_out;
734 IF (g_proc_level>=g_debug_level) THEN
735 XTR_RISK_DEBUG_PKG.dlog('fv_fxo: ' || 'strike price: '||p_strike);
736 XTR_RISK_DEBUG_PKG.dlog('fv_fxo: ' || 'fx spot rate: '||p_spot_rate);
737 END IF;
738
739 -- Garman Kohlhagen
740 p_fx_in.p_spot_date := p_spot_date;
741 p_fx_in.p_maturity_date := p_future_date;
742 IF (p_for_ccy = p_base_ccy) THEN
743 p_fx_in.p_rate_for := p_base_rate;
744 p_fx_in.p_rate_dom := p_contra_rate;
745 ELSE
746 p_fx_in.p_rate_for := p_contra_rate;
747 p_fx_in.p_rate_dom := p_base_rate;
748 END IF;
749
750 p_fx_in.p_day_count_basis_dom := p_day_count_basis;
751 p_fx_in.p_rate_type_dom := 'C';
752 p_fx_in.p_rate_type_for := 'C';
756 p_fx_in.p_strike_rate := p_strike;
753 --p_fx_in.p_rate_for := p_base_rate;
754 p_fx_in.p_day_count_basis_for := p_day_count_basis;
755 p_fx_in.p_spot_rate := p_spot_rate;
757 p_fx_in.p_volatility := p_volatility;
758
759 IF (g_proc_level>=g_debug_level) THEN
760 XTR_RISK_DEBUG_PKG.dlog('fv_fxo: ' || 'GK rate foreign: '||p_fx_in.p_rate_for);
761 XTR_RISK_DEBUG_PKG.dlog('fv_fxo: ' || 'GK rate domestic: '||p_fx_in.p_rate_dom);
762 XTR_RISK_DEBUG_PKG.dlog('fv_fxo: ' || 'GK spot rate: '||p_fx_in.p_spot_rate);
763 XTR_RISK_DEBUG_PKG.dlog('fv_fxo: ' || 'GK strike rate: '||p_fx_in.p_strike_rate);
764 XTR_RISK_DEBUG_PKG.dlog('fv_fxo: ' || 'GK volatility: '||p_fx_in.p_volatility);
765 END IF;
766
767 XTR_FX_FORMULAS.fx_gk_option_price_cv(p_fx_in, p_fx_out);
768 p_call_price := p_fx_out.p_CALL_PRICE;
769 p_put_price := p_fx_out.p_PUT_PRICE;
770 p_forward_rate := p_fx_out.p_fx_fwd_rate;
771 IF (p_for_ccy <> p_base_ccy) THEN
772 p_forward_rate := 1/p_forward_rate;
773 END IF;
774 IF (g_proc_level>=g_debug_level) THEN
775 XTR_RISK_DEBUG_PKG.dlog('fv_fxo: ' || 'garman kohlhagen fwd rate: '||p_forward_rate);
776 XTR_RISK_DEBUG_PKG.dlog('fv_fxo: ' || 'call price: '||p_call_price);
777 XTR_RISK_DEBUG_PKG.dlog('fv_fxo: ' || 'put price: '||p_put_price);
778 END IF;
779
780 -- calculate fair value, which is call/put_price * base amount
781 -- in deal contra ccy (domestic ccy);
782 IF (p_option_type = 'C') THEN
783 p_fair_value := p_call_price * ABS(p_for_amount);
784 ELSIF (p_option_type = 'P') THEN
785 p_fair_value := p_put_price * ABS(p_for_amount);
786 ELSE
787 RAISE_APPLICATION_ERROR(-20001,'p_option_type must be CALL or PUT');
788 END IF;
789
790 -- convert to premium ccy
791 IF (p_dom_ccy <> p_premium_ccy) THEN
792 -- then base currency is premium ccy
793 p_fair_value := p_fair_value / p_spot_rate;
794 END IF;
795
796 IF (p_deal_subtype = 'SELL') THEN
797 p_fair_value := p_fair_value * (-1);
798 END IF;
799 IF (g_proc_level>=g_debug_level) THEN
800 XTR_RISK_DEBUG_PKG.dlog('fv_fxo: ' || 'FAIR VALUE: '||p_fair_value);
801 END IF;
802 END IF;
803 IF (g_proc_level>=g_debug_level) THEN
804 XTR_RISK_DEBUG_PKG.dpop(null,'QRM_FX_FROMULAS.fv_fxo');
805 END IF;
806 END fv_fxo;
807
808
809 -- returns fair value in contra currency
810 PROCEDURE fv_fx (p_price_model IN VARCHAR2,
811 p_set_code IN VARCHAR2,
812 p_buy_ccy IN VARCHAR2,
813 p_sell_ccy IN VARCHAR2,
814 p_sob_ccy IN VARCHAR2,
815 p_interpolation_method IN VARCHAR2,
816 p_spot_date IN DATE,
817 p_future_date IN DATE,
818 p_buy_amount IN NUMBER,
819 p_sell_amount IN NUMBER,
820 p_side IN OUT NOCOPY VARCHAR2,
821 p_forward_rate IN OUT NOCOPY NUMBER,
822 p_fair_value IN OUT NOCOPY NUMBER) IS
823
824 p_base_ccy VARCHAR2(15);
825 p_contra_ccy VARCHAR2(15);
826 p_base_side VARCHAR2(5);
827 p_contra_side VARCHAR2(5);
828 p_spot_side VARCHAR2(5);
829 p_dummy_varchar VARCHAR2(15);
830 p_day_count_basis VARCHAR2(15) := '30/';
831
832 p_buf NUMBER;
833 p_base_amt NUMBER;
834 p_contra_amt NUMBER;
835 p_spot_rate NUMBER;
836 p_base_yield_rate NUMBER;
837 p_contra_yield_rate NUMBER;
838 p_num_days NUMBER;
839 p_year_basis NUMBER;
840 p_sob_spot_rate NUMBER;
841 p_sob_yield_rate NUMBER;
842 p_sob_forward_rate NUMBER;
843
844 p_reverse BOOLEAN;
845
846 p_md_in XTR_MARKET_DATA_P.md_from_set_in_rec_type;
847 p_md_out XTR_MARKET_DATA_P.md_from_set_out_rec_type;
848 p_mm_in XTR_MM_COVERS.presentValue_in_rec_type;
849 p_mm_out XTR_MM_COVERS.presentValue_out_rec_type;
850
851 BEGIN
852 IF (g_proc_level>=g_debug_level) THEN
853 XTR_RISK_DEBUG_PKG.dpush(null,'QRM_FX_FROMULAS.FV_FX');
854 END IF;
855 IF (p_price_model = 'FX_FORWARD') THEN
856 p_base_amt := ABS(p_buy_amount);
857 p_contra_amt := ABS(p_sell_amount);
858 p_base_ccy := p_buy_ccy;
859 p_contra_ccy := p_sell_ccy;
860 get_base_contra(p_base_ccy, p_contra_ccy, p_reverse);
861 IF (g_proc_level>=g_debug_level) THEN
862 XTR_RISK_DEBUG_PKG.dlog('fv_fx: ' || 'base ccy: ' || p_base_ccy);
863 XTR_RISK_DEBUG_PKG.dlog('fv_fx: ' || 'contra ccy: ' || p_contra_ccy);
864 END IF;
865 -- set p_side depend on ask or bid
866 -- also set amount to negative if appropriate
867 IF (p_reverse = TRUE) THEN
868 p_buf := p_base_amt;
869 p_base_amt := -p_contra_amt;
870 p_contra_amt := p_buf;
871 p_side := 'B';
872 ELSE
873 p_side := 'A';
874 p_contra_amt := -p_contra_amt;
875 END IF;
876
877 /* determine FX rates using 'FX Forward' price model */
878 XTR_CALC_P.calc_days_run_c(p_spot_date, p_future_date,
879 p_day_count_basis, null, p_num_days, p_year_basis);
880 IF (p_side = 'B') THEN
881 p_spot_side := 'B';
882 p_contra_side := 'B';
883 p_base_side := 'A';
884 ELSIF (p_side = 'A') then
885 p_spot_side := 'A';
886 p_contra_side := 'A';
887 p_base_side := 'B';
888 ELSE
889 p_spot_side := 'M';
890 p_contra_side := 'M';
891 p_base_side := 'M';
892 END IF;
893
894 -- get spot rate
895 p_md_in.p_md_set_code := p_set_code;
896 p_md_in.p_source := 'C';
897 p_md_in.p_indicator := 'S';
898 p_md_in.p_spot_date := p_spot_date;
899 p_md_in.p_future_date := p_future_date;
900 p_md_in.p_ccy := p_base_ccy;
901 p_md_in.p_contra_ccy := p_contra_ccy;
902 p_md_in.p_day_count_basis_out := p_day_count_basis;
903 p_md_in.p_interpolation_method := p_interpolation_method;
904 p_md_in.p_side := p_spot_side;
905 p_md_in.p_batch_id := null;
906 p_md_in.p_bond_code := null;
907 XTR_MARKET_DATA_P.get_md_from_set(p_md_in, p_md_out);
908 p_spot_rate := p_md_out.p_md_out;
909 IF (g_proc_level>=g_debug_level) THEN
910 XTR_RISK_DEBUG_PKG.dlog('fv_fx: ' || 'spot rate: ' || p_spot_rate);
911 END IF;
912
913 -- get base ccy interest rate
914 p_md_in.p_indicator := 'Y';
915 p_md_in.p_side := p_base_side;
916 XTR_MARKET_DATA_P.get_md_from_set(p_md_in, p_md_out);
917 p_base_yield_rate := p_md_out.p_md_out;
918 IF (g_proc_level>=g_debug_level) THEN
919 XTR_RISK_DEBUG_PKG.dlog('fv_fx: ' || 'base int rate: ' || p_base_yield_rate);
920 END IF;
921
925 XTR_MARKET_DATA_P.get_md_from_set(p_md_in, p_md_out);
922 -- get contra ccy interest rate
923 p_md_in.p_ccy := p_contra_ccy;
924 p_md_in.p_side := p_contra_side;
926 p_contra_yield_rate := p_md_out.p_md_out;
927 IF (g_proc_level>=g_debug_level) THEN
928 XTR_RISK_DEBUG_PKG.dlog('fv_fx: ' || 'contra int rate: ' || p_contra_yield_rate);
929 END IF;
930
931 -- get fx forward rate (immature deal)
932 XTR_FX_FORMULAS.fx_forward_rate(p_spot_rate, p_base_yield_rate,
933 p_contra_yield_rate, p_num_days, p_num_days, p_year_basis,
934 p_year_basis,p_forward_rate);
935 IF (g_proc_level>=g_debug_level) THEN
936 XTR_RISK_DEBUG_PKG.dlog('fv_fx: ' || 'forward rate: ' || p_forward_rate);
937 XTR_RISK_DEBUG_PKG.dlog('fv_fx: ' || 'contra amt: '||p_contra_amt);
938 XTR_RISK_DEBUG_PKG.dlog('fv_fx: ' || 'base amt: '||p_base_amt);
939 END IF;
940
941 -- calculate undiscounted fair value in contra currency
942 p_fair_value := p_base_amt * p_forward_rate + p_contra_amt;
943 IF (g_proc_level>=g_debug_level) THEN
944 XTR_RISK_DEBUG_PKG.dlog('fv_fx: ' || 'undiscounted fair value in contra ccy: '||p_fair_value);
945 END IF;
946
947
948 IF (p_contra_ccy <> p_sob_ccy) THEN
949 -- calculate sob yield rate
950 p_md_in.p_indicator := 'Y';
951 p_md_in.p_ccy := p_sob_ccy;
952 p_side := 'M';
953 XTR_MARKET_DATA_P.get_md_from_set(p_md_in, p_md_out);
954 p_sob_yield_rate := p_md_out.p_md_out;
955 IF (g_proc_level>=g_debug_level) THEN
956 XTR_RISK_DEBUG_PKG.dlog('fv_fx: ' || 'sob yield rate: '||p_sob_yield_rate);
957 END IF;
958
959 -- calculate fx spot rate from contra to sob ccy
960 p_md_in.p_indicator := 'S';
961 p_md_in.p_side := 'M';
962 p_md_in.p_ccy := p_contra_ccy;
963 p_md_in.p_contra_ccy := p_sob_ccy;
964 XTR_MARKET_DATA_P.get_md_from_set(p_md_in, p_md_out);
965 p_sob_spot_rate := p_md_out.p_md_out;
966 IF (g_proc_level>=g_debug_level) THEN
967 XTR_RISK_DEBUG_PKG.dlog('fv_fx: ' || 'sob spot rate: '||p_sob_spot_rate);
968 END IF;
969
970 -- calculate fx forward rate from contra to sob ccy
971 XTR_FX_FORMULAS.fx_forward_rate(p_sob_spot_rate,
972 p_contra_yield_rate, p_sob_yield_rate, p_num_days,
973 p_num_days, p_year_basis, p_year_basis, p_sob_forward_rate);
974 IF (g_proc_level>=g_debug_level) THEN
975 XTR_RISK_DEBUG_PKG.dlog('fv_fx: ' || 'sob forward rate: '||p_sob_forward_rate);
976 END IF;
977 ELSE
978 p_sob_forward_rate := 1;
979 p_sob_yield_rate := p_contra_yield_rate;
980 END IF;
981
982 -- calculate fair value in sob ccy (undiscounted)
983 p_fair_value := p_fair_value * p_sob_forward_rate;
984 IF (g_proc_level>=g_debug_level) THEN
985 XTR_RISK_DEBUG_PKG.dlog('fv_fx: ' || 'undiscounted fair value in sob ccy:' ||p_fair_value);
986 XTR_RISK_DEBUG_PKG.dlog('fv_fx: ' || 'sob discount rate: '||p_sob_yield_rate);
987 END IF;
988 -- discount fair value to spot date
989 p_mm_in.p_indicator := 'Y';
990 p_mm_in.p_future_val := p_fair_value;
991 p_mm_in.p_rate := p_sob_yield_rate;
992 p_mm_in.p_pv_date := p_spot_date;
993 p_mm_in.p_fv_date := p_future_date;
994 p_mm_in.p_day_count_basis := p_day_count_basis;
995 IF (QRM_MM_FORMULAS.within_one_year(p_spot_date, p_future_date)) THEN
996 p_mm_in.p_rate_type := 'S';
997 ELSE
998 p_mm_in.p_rate_type := 'P';
999 p_mm_in.p_compound_freq := 1;
1000 END IF;
1001 XTR_MM_COVERS.present_value(p_mm_in, p_mm_out);
1002 p_fair_value := p_mm_out.P_PRESENT_VAL;
1003 END IF;
1004 IF (g_proc_level>=g_debug_level) THEN
1005 XTR_RISK_DEBUG_PKG.dpop(null,'QRM_FX_FROMULAS.FV_FX');
1006 END IF;
1007 END fv_fx;
1008
1009
1010 END QRM_FX_FORMULAS;