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_calmar(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) params = {Ct.interval_key(): interval} calmar = Calmar() result = calmar.calculate(df, params) self.assertEqual(1.1700790532917946, result[Ct.calmar_key()]['TSLA'])
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'])
def get_reference_days(params): if Ct.interval_key() in params.keys(): period = params[Ct.interval_key()] else: raise ValueError( "Please set the corresponding Interval parameter" "{Ct.interval_key(): interval:Ct.INTERVAL.MONTH|Ct.INTERVAL.DAY}" ) if period == Ct.INTERVAL.DAY: # 252 trading days reference_days = 252 else: # 12 months reference_days = 12 return reference_days
def test_portfolio_rebalance(self): # DJI constituent stocks tickers = ["MMM", "AXP", "T", "BA", "CAT", "CSCO", "KO", "XOM", "GE", "GS", "HD", "IBM", "INTC", "JNJ", "JPM", "MCD", "MRK", "MSFT", "NKE", "PFE", "PG", "TRV", "UNH", "VZ", "V", "WMT", "DIS"] ref_tickers = ["^DJI"] end_date = dt.datetime.now() # dt.datetime(2021, 3, 7) interval = Ct.INTERVAL.MONTH 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(): end_date-dt.timedelta(3650), Ct.end_date_key(): end_date, Ct.interval_key(): interval, Ct.period_key(): None, Ct.bulk_key(): True } stocks = \ StocksFactory.create_stocks( conf=conf ) conf[Ct.tickers_key()] = ref_tickers stocks_ref = \ StocksFactory.create_stocks( conf=conf ) prices_df = stocks[0].get_prices_data(keys={Ct.adj_close_key(): True}) ref_prices_df = stocks_ref[0].get_prices_data(keys={Ct.adj_close_key(): True}) pr = PortfolioRebalance() params = {"m": 6, "x": 3, Ct.interval_key(): conf[Ct.interval_key()]} pr.backtest(prices_df, ref_prices_df, params)
def create_stocks(conf): tickers = conf[Ct.tickers_key()] data_source_historical = None data_source_fundamentals = None data_sources = \ DataCollector.get_data_sources( conf[Ct.historical_type_key()], conf[Ct.fundamentals_type_key()] ) if DataCollector.HISTORICAL_KEY in data_sources.keys(): data_source_historical = data_sources[DataCollector.HISTORICAL_KEY] if data_source_historical is not None: data_source_historical.extract_historical_data( tickers=tickers, start_date=conf[Ct.start_date_key()], end_date=conf[Ct.end_date_key()], period=conf[Ct.period_key()], interval=conf[Ct.interval_key()]) if DataCollector.FUNDAMENTALS_KEY in data_sources.keys(): data_source_fundamentals = data_sources[ DataCollector.FUNDAMENTALS_KEY] if data_source_fundamentals is not None: data_source_fundamentals.extract_fundamentals( tickers=tickers, date=conf[Ct.start_date_key], required_elements=conf[Ct.fundamentals_options_key()], force_server_data=conf[Ct.force_fundamentals_key()]) stocks = StocksFactory.load_stocks( tickers=tickers, data_source_historical=data_source_historical, data_source_fundamentals=data_source_fundamentals, bulk=conf[Ct.bulk_key()], indicators=conf[Ct.indicators_key()]) return stocks