2323
2424market_constants = MarketConstants ()
2525
26- @guvectorize (['void(f8[:], f8[:], f8[:], f8[:], intp, intp , f8[:])' ],
26+ @guvectorize (['void(f8[:], f8[:], f8[:], f8[:], f8, f8 , f8[:])' ],
2727 '(n),(n),(n),(n),(),()->(n)' , cache = True , target = "cpu" , nopython = True )
2828def _spot_index_numba (spot , time_diff , base_deposit , terms_deposit , base_daycount , terms_daycount , out ):
2929
@@ -39,7 +39,7 @@ def _spot_index_numba(spot, time_diff, base_deposit, terms_deposit, base_daycoun
3939def _spot_index (spot , time_diff , base_deposit , terms_deposit , base_daycount , terms_daycount ):
4040 import numpy as np
4141
42- out = np .zero ((len (spot )))
42+ out = np .zeros ((len (spot )))
4343 out [0 ] = 100
4444
4545 for i in range (1 , len (out )):
@@ -51,10 +51,6 @@ def _spot_index(spot, time_diff, base_deposit, terms_deposit, base_daycount, ter
5151
5252 return out
5353
54-
55- def _spot_index ():
56- pass
57-
5854class FXSpotCurve (object ):
5955 """Construct total return (spot) indices for FX. In future will also convert assets from local currency to foreign currency
6056 denomination and construct indices from forwards series.
@@ -110,7 +106,7 @@ def fetch_continuous_time_series(self, md_request, market_data_generator, depo_t
110106 spot_df = market .fetch_market (md_request_download )
111107
112108 return self .construct_total_return_index (md_request .tickers ,
113- self ._calculations .pandas_outer_join ([spot_df , depo_df ]), tenor = depo_tenor ,
109+ self ._calculations .pandas_outer_join ([spot_df , depo_df ]), depo_tenor = depo_tenor ,
114110 output_calculation_fields = output_calculation_fields )
115111 else :
116112 # eg. we calculate via your domestic currency such as USD, so returns will be in your domestic currency
@@ -217,26 +213,30 @@ def construct_total_return_index(self, cross_fx, market_df, depo_tenor=None, out
217213 carry = carry .fillna (method = 'bfill' )
218214
219215 spot = spot [cross + ".close" ].to_frame ()
220- base_deposit = carry [base_deposit .columns ]
221- terms_deposit = carry [terms_deposit .columns ]
222216
223- # Calculate the time difference between each data point
224- spot ['index_col' ] = spot .index
217+ spot_vals = spot [cross + ".close" ].values
218+ base_deposit_vals = carry [cross [0 :3 ] + depo_tenor + ".close" ].values
219+ terms_deposit_vals = carry [cross [3 :6 ] + depo_tenor + ".close" ].values
220+
221+ # Calculate the time difference between each data point (flooring it to whole days, because carry
222+ # is accured when there's a new day)
223+ spot ['index_col' ] = spot .index .floor ('D' )
225224 time = spot ['index_col' ].diff ()
226225 spot = spot .drop ('index_col' , 1 )
227226
228227 time_diff = time .values .astype (float ) / 86400000000000.0 # get time difference in days
228+ time_diff [0 ] = 0.0
229229
230+ # Use Numba to do total return index calculation given has many loops
230231 total_return_index_df = pd .DataFrame (index = spot .index , columns = [cross + "-tot.close" ],
231- data = _spot_index_numba (spot . values , time_diff , base_deposit . values , terms_deposit . values ,
232+ data = _spot_index_numba (spot_vals , time_diff , base_deposit_vals , terms_deposit_vals ,
232233 base_daycount , terms_daycount ))
233234
234235 if output_calculation_fields :
235236 total_return_index_df [cross + '-carry.close' ] = carry
236237 total_return_index_df [cross + '-tot-return.close' ] = total_return_index_df / total_return_index_df .shift (1 ) - 1.0
237- total_return_index_df [cross + '-spot-return.close' ] = spot / spot .shift (1 ) - 1.0
238+ total_return_index_df [cross + '-spot-return.close' ] = spot / spot .shift (1 ) - 1.0
238239
239- # Use Numba to do total return index calculation given has many loops
240240 total_return_index_df_agg .append (total_return_index_df )
241241
242242 return self ._calculations .pandas_outer_join (total_return_index_df_agg )
0 commit comments