Esempio n. 1
0
def list_longest_drawdowns(prices_tms: QFSeries, count: int) -> List[Tuple[datetime, datetime]]:
    """
    Analyses the specified series and finds the top ``count`` longest drawdowns.

    Returns
    -------
    A list of 2-item tuples. The first tuple item contains the start date and the second the end date of the drawdown
    period.
    """
    result = []

    drawdown_timeseries = drawdown_tms(prices_tms)

    start_date = None

    for date, value in drawdown_timeseries.iteritems():
        if value == 0:
            if start_date is not None:
                result.append((start_date, date))
                start_date = None
        else:
            if start_date is None:
                start_date = date

    if start_date is not None:
        result.append((start_date, drawdown_timeseries.index[-1]))

    # Sort according to drawdown length.
    result.sort(key=lambda val: val[0] - val[1])
    return result[:count]
Esempio n. 2
0
    def test_drawdown_tms(self):
        test_prices = [100, 90, 80, 85, 70, 100, 90, 95, 65]
        prices_tms = PricesSeries(data=test_prices, index=date_range('2015-01-01', periods=9))

        expected_drawdown_values = [0, 0.1, 0.2, 0.15, 0.3, 0, 0.1, 0.05, 0.35]
        expected_drawdowns_tms = QFSeries(expected_drawdown_values, date_range('2015-01-01', periods=9))
        actual_drawdowns_tms = drawdown_tms(prices_tms)

        assert_series_equal(expected_drawdowns_tms, actual_drawdowns_tms)
Esempio n. 3
0
 def decorate(self, chart: "Chart") -> None:
     drawdown_series = drawdown_tms(self.series)
     drawdown_series *= -1
     ax = chart.axes
     ax.yaxis.set_major_formatter(PercentageFormatter())
     ax.fill_between(drawdown_series.index,
                     0,
                     drawdown_series.values,
                     alpha=self._colors_alpha)
     ax.set_ylim(top=0)
Esempio n. 4
0
def avg_drawdown(prices_tms: QFSeries) -> float:
    """
    Finds the average drawdown for the given timeseries of prices.

    Parameters
    ----------
    prices_tms: QFSeries
        timeseries of prices

    Returns
    -------
    float
        average drawdown for the given timeseries of prices expressed as the percentage value (e.g. 0.5 corresponds
        to the 50% drawdown)
    """

    return drawdown_tms(prices_tms).mean()
Esempio n. 5
0
    def apply_data_element_decorators(
            self, data_element_decorators: List["DataElementDecorator"]):
        colors = cycle(Chart.get_axes_colors())

        for data_element in data_element_decorators:
            plot_settings = data_element.plot_settings.copy()
            plot_settings.setdefault("color", next(colors))

            series = data_element.data
            trimmed_series = self._trim_data(series)
            drawdown_series = drawdown_tms(trimmed_series)
            drawdown_series *= -1

            axes = self._ax
            axes.yaxis.set_major_formatter(PercentageFormatter())
            axes.fill_between(drawdown_series.index, 0, drawdown_series.values)
            axes.set_ylim(top=0)
Esempio n. 6
0
def list_of_max_drawdowns(prices_tms: QFSeries) -> (List[float], List[float]):
    """
    Finds the values of individual maximum drawdowns and the duration of each drawdown.

    Parameters
    ----------
    prices_tms
        timeseries of prices

    Returns
    -------
    max_drawdowns
        list of all maximum values in individual drawdowns
    duration_of_drawdowns
        list of all durations of drawdowns expressed in days
    """

    drawdown_timeseries = drawdown_tms(prices_tms)

    max_drawdowns = []
    duration_of_drawdowns = []

    series_sample = QFSeries()
    for date, value in drawdown_timeseries.iteritems():
        if value == 0:
            if not series_sample.empty:  # empty sequence returns false
                max_drawdowns.append(series_sample.max())
                time_span = series_sample.index[-1] - series_sample.index[
                    0] + Timedelta('1 days')
                duration_of_drawdowns.append(time_span)

                series_sample = QFSeries()  # reset the sample series
        else:
            series_sample[date] = value

    if not series_sample.empty:  # the last element was not added if the drawdown did not recovered
        max_drawdowns.append(series_sample.max())
        time_span = series_sample.index[-1] - series_sample.index[
            0] + Timedelta('1 days')
        duration_of_drawdowns.append(time_span)

    # convert the duration of drawdown to float value expressed in days
    duration_of_drawdowns = list(map(to_days, duration_of_drawdowns))

    return max_drawdowns, duration_of_drawdowns
Esempio n. 7
0
def max_drawdown(input_data: Union[QFSeries, QFDataFrame],
                 frequency: Frequency = None) -> Union[float, QFSeries]:
    """
    Finds maximal drawdown for the given timeseries of prices.

    Parameters
    ----------
    input_data: QFSeries, QFDataFrame
        timeseries of prices/returns
    frequency: Frequency
        optional parameter that improves teh performance of the function it is not need to infer the frequency

    Returns
    -------
        maximal drawdown for the given timeseries of prices expressed as the percentage value (e.g. 0.5 corresponds
        to the 50% drawdown)
    """
    return drawdown_tms(input_data, frequency=frequency).max()
Esempio n. 8
0
    def _get_underwater_chart(self,
                              series: QFSeries,
                              title="Drawdown",
                              benchmark_series: QFSeries = None,
                              rotate_x_axis: bool = False):
        underwater_chart = LineChart(start_x=series.index[0],
                                     end_x=series.index[-1],
                                     log_scale=False,
                                     rotate_x_axis=rotate_x_axis)
        underwater_chart.add_decorator(UnderwaterDecorator(series))
        underwater_chart.add_decorator(TitleDecorator(title))

        if benchmark_series is not None:
            legend = LegendDecorator()
            benchmark_dd = PricesSeries(drawdown_tms(benchmark_series))
            benchmark_dd *= -1
            benchmark_dd_elem = DataElementDecorator(benchmark_dd,
                                                     color="black",
                                                     linewidth=0.5)
            legend.add_entry(benchmark_dd_elem, "Benchmark DD")
            underwater_chart.add_decorator(benchmark_dd_elem)
            underwater_chart.add_decorator(legend)
        return underwater_chart
Esempio n. 9
0
 def test_avg_drawdown(self):
     avg_drawdown_value = avg_drawdown(self.test_dd_prices_tms)
     dd_tms = drawdown_tms(self.test_dd_prices_tms)
     self.assertEqual(avg_drawdown_value, dd_tms.mean())