def show_perf_attrib_stats(returns, positions, factor_returns, factor_loadings, transactions=None, pos_in_dollars=True): """ Calls `perf_attrib` using inputs, and displays outputs using `utils.print_table`. """ risk_exposures, perf_attrib_data = perf_attrib( returns, positions, factor_returns, factor_loadings, transactions, pos_in_dollars=pos_in_dollars, ) perf_attrib_stats, risk_exposure_stats =\ create_perf_attrib_stats(perf_attrib_data, risk_exposures) print_table(perf_attrib_stats.loc[[ 'Annualized Specific Return', 'Annualized Common Return', 'Annualized Total Return', 'Specific Sharpe Ratio' ]], name='Summary Statistics') print_table(risk_exposure_stats, name='Exposures Summary')
def strat_evaluation(return_dict, re_balance_freq=FreqType.EOM, margin_prop=0.0, need_plot=True): """ :param return_dict: dict, returnName: [returnData, ReturnType] :param margin_prop: :param re_balance_freq: str, optional, rebalance frequncy = daily/monthly/yearly :param need_plot: bool, optional, whether to plot the strategy/benchmark/hedged ptf npv :return: print out the perf stat table by years """ ptf_return = ptf_re_balance(return_dict=return_dict, margin_prop=margin_prop, re_balance_freq=re_balance_freq) perf_stats = print_perf_stat_by_year(ptf_return, ReturnType.Cumul) utils.print_table(perf_stats, name='Performance statistics for hedged portfolio', fmt='{0:.4f}') perf_stats_strat = print_perf_stat_by_year(return_dict['stratReturn'][0], return_dict['stratReturn'][1]) utils.print_table(perf_stats_strat, name='Performance statistics for unhedged portfolio', fmt='{0:.4f}') ptf_return_dict = {'ptfReturn': [ptf_return, ReturnType.Cumul]} return_dict = dict(return_dict, **ptf_return_dict) if need_plot: plot_alpha_curve(return_dict=return_dict) return
def show_perf_attrib_stats(perf_attrib_data, risk_exposures): """ Takes perf attribution data over a period of time, computes stats on it, and displays them using `utils.print_table`. """ perf_attrib_stats = create_perf_attrib_stats(perf_attrib_data) print_table(perf_attrib_stats) print_table(risk_exposures)
def print_table_from_perf_array(perf, factor_returns=None, show_baseline=False, show_header=True): APPROX_BDAYS_PER_MONTH = 21 # APPROX_BDAYS_PER_YEAR = 252 STAT_FUNCS_PCT = [ 'Annual return', 'Cumulative returns', 'Annual volatility', 'Max drawdown', 'Daily value at risk', 'Daily turnover' ] arr = list(zip(*[(pData[0], pf.utils.extract_rets_pos_txn_from_zipline(pData[1])[0]) for pData in perf])) names_arr = arr[0] returns_arr = arr[1] # get headers if show_header: returns = returns_arr[0] # take first row as representative of all other backtests date_rows = OrderedDict() if len(returns.index) > 0: date_rows['Start date'] = returns.index[0].strftime('%Y-%m-%d') date_rows['End date'] = returns.index[-1].strftime('%Y-%m-%d') date_rows['Total months'] = int(len(returns) / APPROX_BDAYS_PER_MONTH) else: date_rows = None # get peformance stats perf_stats_arr = [] # show baseline as one of the columns if show_baseline: perf_stats_arr.append( perf_stats(factor_returns, factor_returns=factor_returns) ) names_arr = ['Baseline'] + list(names_arr) for i in range(len(returns_arr)): perf_stats_arr.append( perf_stats(returns_arr[i], factor_returns=factor_returns) ) perf_stats_all = pd.concat(perf_stats_arr, axis=1) for column in perf_stats_all.columns: for stat, value in perf_stats_all[column].iteritems(): if stat in STAT_FUNCS_PCT: perf_stats_all.loc[stat, column] = str(np.round(value * 100, 3)) + '%' df = pd.DataFrame(perf_stats_all) df.columns = names_arr # print table print_table(df, float_format='{0:.2f}'.format, header_rows=date_rows) # return performance stats return df
def show_perf_attrib_stats(returns, positions, factor_returns, factor_loadings, transactions=None, pos_in_dollars=True): """ Calls `perf_attrib` using inputs, and displays outputs using `utils.print_table`. """ risk_exposures, perf_attrib_data = perf_attrib( returns, positions, factor_returns, factor_loadings, transactions, pos_in_dollars=pos_in_dollars, ) perf_attrib_stats, risk_exposure_stats =\ create_perf_attrib_stats(perf_attrib_data, risk_exposures) percentage_formatter = '{:.2%}'.format float_formatter = '{:.2f}'.format summary_stats = perf_attrib_stats.loc[['Annualized Specific Return', 'Annualized Common Return', 'Annualized Total Return', 'Specific Sharpe Ratio']] # Format return rows in summary stats table as percentages. for col_name in ( 'Annualized Specific Return', 'Annualized Common Return', 'Annualized Total Return', ): summary_stats[col_name] = percentage_formatter(summary_stats[col_name]) # Display sharpe to two decimal places. summary_stats['Specific Sharpe Ratio'] = float_formatter( summary_stats['Specific Sharpe Ratio'] ) print_table(summary_stats, name='Summary Statistics') print_table( risk_exposure_stats, name='Exposures Summary', # In exposures table, format exposure column to 2 decimal places, and # return columns as percentages. formatters={ 'Average Risk Factor Exposure': float_formatter, 'Annualized Return': percentage_formatter, 'Cumulative Return': percentage_formatter, }, )
def show_perf_attrib_stats(returns, positions, factor_returns, factor_loadings): """ Calls `perf_attrib` using inputs, and displays outputs using `utils.print_table`. """ risk_exposures, perf_attrib_data = perf_attrib(returns, positions, factor_returns, factor_loadings) perf_attrib_stats = create_perf_attrib_stats(perf_attrib_data) print_table(perf_attrib_stats) print_table(risk_exposures)
def strat_evaluation(return_dict, re_balance_freq=FreqType.EOM, margin_prop=0.0, need_plot=True, save_file=False, risk_free=0.0): """ :param return_dict: dict, returnName: [returnData, ReturnType] :param margin_prop: :param re_balance_freq: str, optional, rebalance frequncy = daily/monthly/yearly :param need_plot: bool, optional, whether to plot the strategy/benchmark/hedged ptf npv :param save_file: bool, optional, whether to save perf stat :param risk_free: float, optional, risk free rate used in evaluation :return: print out the perf stat table by years """ ptf_return = ptf_re_balance(return_dict=return_dict, margin_prop=margin_prop, re_balance_freq=re_balance_freq) perf_stats = print_perf_stat_by_year(ptf_return, ReturnType.Cumul, risk_free) utils.print_table(perf_stats, name='Performance statistics for hedged portfolio', fmt='{0:.4f}') perf_stats_strat = print_perf_stat_by_year(return_dict['stratReturn'][0], return_dict['stratReturn'][1], risk_free) utils.print_table(perf_stats_strat, name='Performance statistics for unhedged portfolio', fmt='{0:.4f}') ptf_return_dict = {'ptfReturn': [ptf_return, ReturnType.Cumul]} return_dict = dict(return_dict, **ptf_return_dict) if need_plot: plot_alpha_curve(return_dict=return_dict, save_file=save_file) if save_file: perf_stats.to_csv('perf_hedged_ptf.csv', date_format='%Y-%m-%d', encoding='gbk') perf_stats_strat.to_csv('perf_unhedged_ptf.csv', date_format='%Y-%m-%d', encoding='gbk') return
def strategy_performance(returns=None, factor_returns=None, positions=None, transactions=None, details=None): if details is not None: returns, factor_returns = details['return'], details['factor_return'] positions, transactions = details[[details['symbol'].iloc[0], 'cash']], details[[ 'symbol', 'price', 'amount' ]] new_perf_stats = OrderedDict() new_perf_stats['Backtest days'] = round(len(returns) / (360 * 24), 4) if transactions is not None: new_perf_stats['Trades/hour'] = round( len(transactions.iloc[transactions['amount'].nonzero()[0]]) / 360, 4) perf_stats_all = timeseries.perf_stats(returns, factor_returns=factor_returns, positions=positions, transactions=transactions) for k in perf_stats_all.keys(): j = ('Hourly' + k.replace('Annual', '')) if 'Annual' in k \ else ('Tick' + k.replace('Daily', '')) if 'Daily' in k else k new_perf_stats[j] = perf_stats_all[k] perf_stats = pd.DataFrame(pd.Series(new_perf_stats), columns=['Results']) for column in perf_stats.columns: for stat, value in perf_stats[column].iteritems(): if stat in STAT_FUNCS_PCT: perf_stats.loc[stat, column] = str(round(value * 100, 1)) + '%' utils.print_table(perf_stats, fmt='{0:.2f}') plot_returns(returns, factor_returns, transactions=transactions if new_perf_stats['Backtest days'] <= 0.05 else None)