def backtest(self, prices, ref_prices, params): m = params["m"] x = params["x"] interval = params[Ct.interval_key()] mon_ret_df = Financials.pct_change(prices) p_return = IntradayResistanceBreakout.calculate(mon_ret_df, m, x) cagr_params = {Ct.interval_key(): interval} cagr = CAGR.get_cagr(p_return, cagr_params) sharpe_params = {"rf": 0.025, Ct.interval_key(): interval} sharpe = Sharpe.get_sharpe(p_return, sharpe_params) max_dd = MaxDrawdown.get_max_drawdown(p_return) # calculating overall strategy's KPIs mon_ret_df = Financials.pct_change(ref_prices) cagr_ref = CAGR.get_cagr(mon_ret_df, cagr_params) sharpe_params = {"rf": 0.025, Ct.interval_key(): interval} sharpe_ref = Sharpe.get_sharpe(mon_ret_df, sharpe_params) max_dd_ref = MaxDrawdown.get_max_drawdown(mon_ret_df) print("CAGR - Portfolio: {}".format(cagr[Ct.cagr_key()]["mon_ret"])) print("Sharpe - Portfolio: {}".format( sharpe[Ct.sharpe_key()]["mon_ret"])) print("MAX-Drawdown - Portfolio: {}".format( max_dd[Ct.max_drawdown_key()]["mon_ret"])) print("CAGR - Ref: {}".format(cagr_ref[Ct.cagr_key()]["^DJI"])) print("Sharpe - Ref: {}".format(sharpe_ref[Ct.sharpe_key()]["^DJI"])) print("MAX-Drawdown - Ref: {}".format( max_dd_ref[Ct.max_drawdown_key()]["^DJI"])) IntradayResistanceBreakout.plot(p_return, mon_ret_df)
def test_KPI_max_drawdown(self): tickers = ["TSLA", "SPY"] interval = Ct.INTERVAL.DAY conf = { Ct.tickers_key(): tickers, Ct.historical_type_key(): DATASOURCETYPE.YFINANCE, Ct.fundamentals_type_key(): None, Ct.fundamentals_options_key(): [], Ct.force_fundamentals_key(): False, Ct.indicators_key(): [], Ct.start_date_key(): dt.datetime(2021, 3, 7) - dt.timedelta(1825), Ct.end_date_key(): dt.datetime(2021, 3, 7), Ct.interval_key(): interval, Ct.period_key(): None, Ct.bulk_key(): True } stocks = \ StocksFactory.create_stocks( conf=conf ) prices_df = stocks[0].get_prices_data(keys={Ct.adj_close_key(): True}) df = Financials.pct_change(prices_df) md = MaxDrawdown() result = md.calculate(df) self.assertEqual(0.6062653645917145, result[Ct.max_drawdown_key()]['TSLA']) self.assertEqual(0.3371725544013077, result[Ct.max_drawdown_key()]['SPY'])
class MaxDrawdown(KPI): kpi_name = Constants.max_drawdown_key() def __init__(self, params=None): super().__init__(params) if not params: self.params = {} def calculate(self, df, params=None): super().calculate(df) self.result = MaxDrawdown.get_max_drawdown(df) return self.result @staticmethod def get_max_drawdown(input_df): """ function to calculate max drawdown" """ df = input_df.copy() df.columns = df.columns.droplevel(1) cumprod_df = (1 + df).cumprod() cum_roll_max_df = cumprod_df.cummax() drawdown_df = cum_roll_max_df - cumprod_df drawdown_pct_df = drawdown_df / cum_roll_max_df result_df = pd.DataFrame() result_df[MaxDrawdown.kpi_name] = drawdown_pct_df.max() return result_df
def get_calmar(input_df, params=None): """function to calculate Calmar""" if params is None: params = {} cagr = CAGR.get_cagr(input_df, params) max_dd = MaxDrawdown.get_max_drawdown(input_df) result_df = pd.DataFrame() result_df[Calmar.kpi_name] = (cagr[Ct.cagr_key()] / max_dd[Ct.max_drawdown_key()]) return result_df