DBA Data[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;