def creditprof(): '''Credit profile derived from mortgage and corporate credit spreads.''' # Derivation in fecon235/nb/fred-credit-spreads.ipynb # See https://git.io/creditprof # First, note the oldest start date common among all series herein: start = '1991-08-30' # ----- MORTGAGE CREDIT SPREAD # Freddie Mac 15-Year Fixed Rate Mortgage v. Treasury 10-year bond. # Freddie Mac series is updated weekly on Thursdays, # so we apply daily interpolation to be # frequency compatible with the other series in this function: fmac = daily(get('MORTGAGE15US')) # Retrieve daily rates for 10-year Treasuries... ty = get(d4bond10) # ... then compute the mortgage spread: mort = todf(fmac - ty) # Profile the mortgage credit spread: mortmad = madmen(mort) # ----- CORPORATE BOND SPREAD # Examine daily BAA10Y spread between Moody's Seasoned Baa-rated # Corporate Bonds and 10-year Treasury Constant Maturity: baa = get('BAA10Y') # Profile the corporate credit spread: baamad = madmen(baa[start:]) # ----- UNIFIED PROFILE for generality, # take the mean of all profiles: return todf((mortmad + baamad) / 2)
def foreinfl(n=120, alpha=1.0, beta=0.3673): '''Forecast Unified Inflation 1-year ahead per https://git.io/infl which a rendering of fecon235/nb/fred-inflation.ipynb. SUMMARY output: [Average, "infl-date", GMR, HW, BEI] e.g. [2.2528, '2018-01-01', 1.5793, 3.0791, 2.1000] where Average is the mean of three orthogonal methods: GMR for geometric mean rate, HW for Holt-Winters time-series, and BEI for Break-even Inflation from the Treasury bond market. Default n denotes 120-month history, i.e. last 10 years. ''' # Holt-Winters parameters alpha and beta are optimized # from the 1960-2018 dataset, consisting of 697 monthly points. # Each "way" is an orthogonal method, to be averaged into way[0]. way = [-9, -9, -9, -9, -9] # dummy placeholders. inflall = get(m4infl) # synthetic Unified Inflation, monthly. infl = tail(inflall, n) way[1] = str(infl.index[-1]).replace(" 00:00:00", "") # ^Most recent month for CPI, CPIc, PCE, PCEc data. gm = gemrat(infl, yearly=12) way[2] = gm[0] # Geometric Mean Rate over n months. hw = foreholt(infl, 12, alpha, beta) # Holt-Winters model. way[3] = (tailvalue(hw) - 1) * 100 # Convert forecasted level to rate. bond10 = get(m4bond10) tips10 = get(m4tips10) bei = todf(bond10 - tips10) # 10-year BEI Break-even Inflation. # ^Treasury bond market data will be much more recent than m4infl. way[4] = tailvalue(bei) # Final forecast is the AVERAGE of three orthogonal methods: way[0] = sum(way[2:]) / len(way[2:]) return way
def forefunds(nearby='16m', distant='17m'): '''Forecast distant Fed Funds rate using Eurodollar futures.''' # Derivation in fecon235/nb/qdl-libor-fed-funds.ipynb # See https://git.io/fedfunds ffer = get('DFF') # ^Retrieve Fed Funds effective rate, daily since 1954. ffer_ema = ema(ffer['1981':], 0.0645) # ^Eurodollar futures debut. # ^Exponentially Weighted Moving Average, 30-period. libor_nearby = get('f4libor' + nearby) libor_distant = get('f4libor' + distant) libor_spread = todf(libor_nearby - libor_distant) # spread in forward style quote since futures uses 100-rate. return todf(ffer_ema + libor_spread)
def test_group_fecon236_GET_w4cotr_metals_from_QUANDL_vSlow_oLocal(): '''Test get() which uses getqdl() in qdl module. Here we get the CFTC Commitment of Traders Reports for gold and silver expressed as our position indicator. >>> print(qdl.w4cotr_metals) w4cotr_metals ''' metals = get(qdl.w4cotr_metals) assert round(tool.tailvalue(metals[:'2015-07-28']), 3) == 0.461
def foreholt(data, h=12, alpha=hw_alpha, beta=hw_beta, maxi=0): '''Data slang aware Holt-Winters holtforecast(), h-periods ahead. Thus "data" can be a fredcode, quandlcode, stock slang, OR a DataFrame should be detected. ''' if not isinstance(data, pd.DataFrame): try: data = get(data, maxi) except Exception: raise ValueError("INVALID data argument.") holtdf = holt(data, alpha, beta) return holtforecast(holtdf, h)
def groupget(ggdic=group4d, maxi=0): '''Retrieve and create group dataframe, given group dictionary.''' # Since dictionaries are unordered, create SORTED list of keys: keys = [key for key in sorted(ggdic)] # Download individual dataframes as values into a dictionary: dfdic = {key: get(ggdic[key], maxi) for key in keys} # ^Illustrates dictionary comprehension. # Paste together dataframes into one large sorted dataframe: groupdf = tool.paste([dfdic[key] for key in keys]) # Name the columns: groupdf.columns = keys return groupdf
def forecast(data, h=12, grids=0, maxi=0): '''h-period ahead forecasts by holtforecast or optimize_holtforecast, where "data" may be fredcode, quandlcode, stock slang, or DataFrame. Given default grids argument, forecast is very QUICK since we use FIXED parameters implicitly: alpha=hw_alpha and beta=hw_beta. Recommend grids=50 for reasonable results, but it is TIME-CONSUMING for search grids > 49 to find OPTIMAL alpha and beta. ''' if not isinstance(data, pd.DataFrame): try: data = get(data, maxi) # ^Expecting fredcode, quandlcode, or stock slang. except Exception: raise ValueError("INVALID data argument.") if grids > 0: opt = optimize_holtforecast(data, h, grids=grids) system.warn(str(opt[1]), stub="OPTIMAL alpha, beta, losspc, loss:") return opt[0] else: holtdf = holt(data) system.warn("Holt-Winters parameters have NOT been optimized.") return holtforecast(holtdf, h)
def test_group_fecon236_GET_d7xbtusd_from_QUANDL_vSlow_oLocal(): '''Test get() which uses getqdl() in qdl module. Here we get a Bitcoin price from Quandl. ''' xbt = get(qdl.d7xbtusd) assert tool.tailvalue(xbt[:'2018-06-14']) == 6315.7