def test_duration_of_drawdowns(self): series_of_max_drawdowns, duration_of_drawdowns = list_of_max_drawdowns( self.test_dd_prices_tms) drawdowns = [0.3, 0.75, 0.25] durations = [93, 62, 1] assert_lists_equal(durations, duration_of_drawdowns) assert_lists_equal(drawdowns, series_of_max_drawdowns)
def create_dd_probability_chart_3d(prices_tms: QFSeries) -> SurfaceChart3D: """Create a 3d drawdowns probability chart""" def count_dd_above_threshold(drawdown_series: Sequence, threshold: float): return sum(1 for dd in drawdown_series if dd > threshold) drawdowns, duration_of_drawdowns = list_of_max_drawdowns(prices_tms) bear_marker_definitions = np.arange(0.15, 0.55, 0.05) # rows -> will be the Y axis all_examined_dds = np.arange(0.01, 0.20, 0.01) # columns -> will be the X axis percentage_ending_in_bear_market = np.ones( (len(bear_marker_definitions), len(all_examined_dds))) * 100 for i, bear_marker_definition in enumerate(bear_marker_definitions): nr_of_bear_markets = count_dd_above_threshold(drawdowns, bear_marker_definition) for j, examined_dd in enumerate(all_examined_dds): if examined_dd <= bear_marker_definition: number_of_dds_above = count_dd_above_threshold( drawdowns, examined_dd) percentage = nr_of_bear_markets / number_of_dds_above * 100 percentage_ending_in_bear_market[i, j] = percentage chart = SurfaceChart3D(all_examined_dds, bear_marker_definitions, percentage_ending_in_bear_market) chart.set_axes_names('examined drawdown', 'bear market definition') chart.set_title('Percentage of drawdowns ending in bear market') return chart
def avg_drawdown_duration(prices_tms: QFSeries) -> float: """ Finds the average duration of a drawdown for the given timeseries of prices. Parameters ---------- prices_tms timeseries of prices Returns ------- avg_duration average duration of a drawdown for the given timeseries of prices expressed in days """ from qf_lib.common.utils.returns.list_of_max_drawdowns import list_of_max_drawdowns series_of_max_drawdowns, duration_of_drawdowns = list_of_max_drawdowns(prices_tms) if len(duration_of_drawdowns) > 0: return mean(duration_of_drawdowns) else: return 0.0
def create_dd_probability_chart( prices_tms: QFSeries, bear_market_definition: float = 0.2) -> Tuple[Chart, Chart]: """Creates drawdowns probability chart. Parameters ---------- prices_tms: QFSeries timeseries of prices bear_market_definition: float definition of bear market threshold Returns ------- Tuple[Chart, Chart] Returns two charts - one showing the probability of drawdowns going beyond a certain level and one showing the marginal increase of probability of drawdowns going beyond the given level. """ def count_dd_above_threshold(drawdown_series: Sequence, threshold: float): return sum(1 for dd in drawdown_series if dd > threshold) drawdowns, duration_of_drawdowns = list_of_max_drawdowns(prices_tms) examined_dds = np.arange(0.01, bear_market_definition, 0.005) percentage_ending_in_bear_market = [] nr_of_bear_markets = count_dd_above_threshold(drawdowns, bear_market_definition) for examined_dd in examined_dds: number_of_dds_above = count_dd_above_threshold(drawdowns, examined_dd) percentage = nr_of_bear_markets / number_of_dds_above * 100 percentage_ending_in_bear_market.append(percentage) chart = LineChart() chart.add_decorator( ScatterDecorator(examined_dds * 100, percentage_ending_in_bear_market, edgecolors='black')) chart.add_decorator( TitleDecorator("Percentage of drawdowns going beyond {:2.0f}%".format( bear_market_definition * 100))) axis_dec = AxesLabelDecorator( "examined drawdown [%]", "chance that drawdown will go beyond {:2.0f}% in [%]".format( bear_market_definition * 100)) chart.add_decorator(axis_dec) x_axis_values = examined_dds * 100 prob_of_dd_chart = LineChart() prob_of_dd_chart.add_decorator( ScatterDecorator(x_axis_values, percentage_ending_in_bear_market, edgecolors='black')) prob_of_dd_chart.add_decorator( TitleDecorator("Percentage of drawdowns going beyond {:2.0f}%".format( bear_market_definition * 100))) axis_dec = AxesLabelDecorator( "examined drawdown [%]", "chance that drawdown will go beyond {:2.0f}% in [%]".format( bear_market_definition * 100)) prob_of_dd_chart.add_decorator(axis_dec) marginal_increase_in_prob_chart = LineChart() diff = np.diff([0] + percentage_ending_in_bear_market) marginal_increase_in_prob_chart.add_decorator( ScatterDecorator(x_axis_values, diff, edgecolors='black')) marginal_increase_in_prob_chart.add_decorator( TitleDecorator( "Marginal increase of probability of drawdowns going beyond {:2.0f}%" .format(bear_market_definition * 100))) axis_dec = AxesLabelDecorator( "examined drawdown [%]", "Marginal increase of chance that drawdown will go beyond {:2.0f}% in [%]" .format(bear_market_definition * 100)) marginal_increase_in_prob_chart.add_decorator(axis_dec) return prob_of_dd_chart, marginal_increase_in_prob_chart