Esempio n. 1
0
def create_returns_bar_chart(returns: QFSeries,
                             frequency: Frequency = Frequency.YEARLY,
                             title: str = None) -> BarChart:
    """
    Constructs a new returns bar chart based on the returns specified. By default a new annual returns bar chart will
    be created.

    Parameters
    ----------
    returns: QFSeries
        The returns series to use in the chart.
    frequency: Frequency
        frequency of the returns after aggregation
    title:
        optional title for the chart

    Returns
    --------
    BarChart
    """
    colors = Chart.get_axes_colors()
    # Calculate data.
    aggregate_returns = get_aggregate_returns(returns,
                                              frequency,
                                              multi_index=True)
    data_series = QFSeries(aggregate_returns.sort_index(ascending=True))

    chart = BarChart(Orientation.Horizontal, align="center")
    chart.add_decorator(DataElementDecorator(data_series, key="data_element"))
    chart.add_decorator(BarValuesDecorator(data_series))

    # Format the x-axis so that its labels are shown as a percentage.
    chart.add_decorator(AxesFormatterDecorator(x_major=PercentageFormatter()))

    # Format Y axis to make sure we have a tick for each year or 2 years
    if len(data_series) > 10:
        y_labels = data_series[data_series.index % 2 == 1].index
    else:
        y_labels = data_series.index
    chart.add_decorator(
        AxisTickLabelsDecorator(labels=y_labels,
                                axis=Axis.Y,
                                tick_values=y_labels))

    # Add an average line.
    avg_line = VerticalLineDecorator(aggregate_returns.values.mean(),
                                     color=colors[1],
                                     key="avg_line",
                                     linestyle="--",
                                     alpha=0.8)
    chart.add_decorator(avg_line)

    # Add a legend.
    legend = LegendDecorator(key="legend_decorator")
    legend.add_entry(avg_line, "Mean")
    chart.add_decorator(legend)

    # Add a title.
    if title is None:
        title = str(frequency).capitalize() + " Returns"
    title = TitleDecorator(title, key="title_decorator")
    chart.add_decorator(title)
    chart.add_decorator(AxesLabelDecorator("Returns", "Year"))

    return chart
Esempio n. 2
0
def create_dot_plot(series1: QFSeries,
                    series2: QFSeries,
                    x_label: str,
                    y_label: str,
                    start_x: float = None,
                    end_x: float = None) -> LineChart:
    """Create a dot linechart.

    Parameters
    -----------
    series1: QFSeries
    series2: QFSeries
    x_label: str
    y_label: str
    start_x: float
    end_x: float

    Returns
    --------
    LineChart
    """

    # Combine the series.
    combined = pd.concat([series1, series2], axis=1)
    combined_series = QFSeries(data=combined.iloc[:, 0].values,
                               index=combined.iloc[:, 1].values)

    # Create a new line chart.
    line_chart = LineChart(start_x=start_x, end_x=end_x)
    line_chart.tick_fontweight = "bold"
    line_chart.tick_color = "black"

    # Add the data.
    data_element = DataElementDecorator(combined_series, marker="o")
    line_chart.add_decorator(data_element)

    # Add a title.
    title_decorator = TitleDecorator("US Beveridge Curve", key="title")
    line_chart.add_decorator(title_decorator)

    # Add axes labels.
    axes_label_decorator = AxesLabelDecorator(x_label=x_label, y_label=y_label)
    line_chart.add_decorator(axes_label_decorator)

    # Emphasise the last point.
    # This series has many NaNs, we want to retrieve the last non-NaN point.
    no_nans = combined_series.dropna()
    point_to_emphasise = (no_nans.index[len(no_nans) - 1],
                          no_nans.values[len(no_nans) - 1])
    point_emphasis_decorator = PointEmphasisDecorator(data_element,
                                                      point_to_emphasise,
                                                      color="#CC1414",
                                                      decimal_points=1,
                                                      label_format="")
    line_chart.add_decorator(point_emphasis_decorator)

    # Create a legend.
    legend_decorator = LegendDecorator()
    last_date = series1.dropna().index.max()
    legend_decorator.add_entry(
        point_emphasis_decorator,
        "Latest ({:g}, {:g}) [{}]".format(point_to_emphasise[0],
                                          point_to_emphasise[1],
                                          last_date.strftime("%b %y")))
    line_chart.add_decorator(legend_decorator)

    return line_chart
Esempio n. 3
0
def create_rolling_chart_using_benchmark(series: Union[QFSeries,
                                                       List[QFSeries]],
                                         benchmark_series: QFSeries,
                                         func: RollingWindowFunction,
                                         func_name: str,
                                         window_size: int = 126,
                                         step: int = 20,
                                         oos_date: str = None) -> LineChart:
    """
    Creates a new line chart and adds the rolling window for each of the specified series to it. The `func`
    function is fed data for each window and whatever it returns is added to the resulting rolled series.

    For example:

    .. code-block::python
        create_rolling_chart_using_benchmark([strategy1_tms, strategy2_tms], benchmark_tms
                             lambda a, b: beta_and_alpha(PricesSeries(a), PricesSeries(b))[0],
                             "Sharpe Ratio", oos_date=oos_date)

    The example above will return beta of every rolling window

    Parameters
    ----------
    series: QFSeries, List[QFSeries]
        One or more series to apply the rolling window transformation on add to the resulting chart.
    benchmark_series: QFSeries
        benchmark for every series passed as a first argument
    func: RollingWindowFunction
        Called for each window. Takes two arguments (series_window, benchmark_window). Returns a float.
    func_name: str
        Used in the title to specify the function that was called.
    window_size: int
    step: int
        determines by how many steps we shift the rolling window
    oos_date: str
        only the OOS date of the first series in the list will be taken into account

    Returns
    -------
    LineChart
    """

    chart = LineChart()

    # Add a legend.
    legend = LegendDecorator()
    chart.add_decorator(legend)

    series_list = series
    if isinstance(series_list, QFSeries):
        series_list = [series_list]
    assert isinstance(series_list, list)

    for tms in series_list:
        rolling = tms.rolling_window_with_benchmark(benchmark_series,
                                                    window_size,
                                                    func,
                                                    step=step)
        rolling_element = DataElementDecorator(rolling)
        chart.add_decorator(rolling_element)
        legend.add_entry(rolling_element, tms.name)

    # Add title
    chart.add_decorator(
        TitleDecorator("Rolling {} (window: {}, step: {}, BM: {}) ".format(
            func_name, window_size, step, benchmark_series.name)))

    # Add OOS line.
    new_oos_date = series_list[0].index.asof(pandas.to_datetime(oos_date))
    line = VerticalLineDecorator(new_oos_date,
                                 color='orange',
                                 linestyle="dashed")
    chart.add_decorator(line)

    return chart
Esempio n. 4
0
def create_skewness_chart(series: QFSeries, title: str = None) -> LineChart:
    """
    Creates a new line chart showing the skewness of the distribution.
    It plots original series together with another series which contains sorted absolute value of the returns

    Parameters
    ----------
    series
        ``QFSeries`` to plot on the chart.
    title
        title of the graph, specify ``None`` if you don't want the chart to show a title.

    Returns
    -------
    The constructed ``LineChart``.
    """

    original_price_series = series.to_prices(1)

    # Construct a series with returns sorted by their amplitude
    returns_series = series.to_simple_returns()
    abs_returns_series = returns_series.abs()

    returns_df = pd.concat([returns_series, abs_returns_series],
                           axis=1,
                           keys=['simple', 'abs'])
    sorted_returns_df = returns_df.sort_values(by='abs')
    skewness_series = SimpleReturnsSeries(
        index=returns_series.index, data=sorted_returns_df['simple'].values)
    skewed_price_series = skewness_series.to_prices(1)

    # Create a new Line Chart.
    line_chart = LineChart(start_x=series.index[0], rotate_x_axis=True)

    # Add original series to the chart
    original_series_element = DataElementDecorator(original_price_series)
    line_chart.add_decorator(original_series_element)

    skewed_series_element = DataElementDecorator(skewed_price_series)
    line_chart.add_decorator(skewed_series_element)

    # Add a point at the end
    point = (skewed_price_series.index[-1], skewed_price_series[-1])
    point_emphasis = PointEmphasisDecorator(skewed_series_element,
                                            point,
                                            font_size=9)
    line_chart.add_decorator(point_emphasis)

    # Create a title.
    if title is not None:
        title_decorator = TitleDecorator(title, "title")
        line_chart.add_decorator(title_decorator)

    # Add a legend.
    legend_decorator = LegendDecorator(key='legend')
    legend_decorator.add_entry(original_series_element,
                               'Chronological returns')
    legend_decorator.add_entry(skewed_series_element,
                               'Returns sorted by magnitude')
    line_chart.add_decorator(legend_decorator)
    line_chart.add_decorator(AxesLabelDecorator(y_label="Profit/Loss"))

    return line_chart
Esempio n. 5
0
def create_returns_similarity(strategy: QFSeries,
                              benchmark: QFSeries,
                              mean_normalization: bool = True,
                              std_normalization: bool = True,
                              frequency: Frequency = None) -> KDEChart:
    """
    Creates a new returns similarity chart. The frequency is determined by the specified returns series.

    Parameters
    ----------
    strategy
        The strategy series to plot.
    benchmark
        The benchmark series to plot.
    mean_normalization
        Whether to perform mean normalization on the series data.
    std_normalization
        Whether to perform variance normalization on the series data.
    frequency:
        Returns can be aggregated in to specific frequency before plotting the chart
    Returns
    -------
    A newly created KDEChart instance.
    """
    chart = KDEChart()
    colors = Chart.get_axes_colors()

    if frequency is not None:
        aggregate_strategy = get_aggregate_returns(
            strategy.to_simple_returns(), frequency)
        aggregate_benchmark = get_aggregate_returns(
            benchmark.to_simple_returns(), frequency)
    else:
        aggregate_strategy = strategy.to_simple_returns()
        aggregate_benchmark = benchmark.to_simple_returns()

    scaled_strategy = preprocessing.scale(aggregate_strategy,
                                          with_mean=mean_normalization,
                                          with_std=std_normalization)
    strategy_data_element = DataElementDecorator(scaled_strategy,
                                                 bw="scott",
                                                 shade=True,
                                                 label=strategy.name,
                                                 color=colors[0])
    chart.add_decorator(strategy_data_element)

    scaled_benchmark = preprocessing.scale(aggregate_benchmark,
                                           with_mean=mean_normalization,
                                           with_std=std_normalization)
    benchmark_data_element = DataElementDecorator(scaled_benchmark,
                                                  bw="scott",
                                                  shade=True,
                                                  label=benchmark.name,
                                                  color=colors[1])
    chart.add_decorator(benchmark_data_element)

    # Add a title.
    title = _get_title(mean_normalization, std_normalization, frequency)
    title_decorator = TitleDecorator(title, key="title")
    chart.add_decorator(title_decorator)
    chart.add_decorator(AxesLabelDecorator("Returns", "Similarity"))
    return chart
Esempio n. 6
0
 def __init__(self, strategy_tms, rotate_x_axis=False):
     super().__init__(rotate_x_axis=rotate_x_axis)
     self.add_decorator(DataElementDecorator(strategy_tms))
Esempio n. 7
0
    def historical_out_of_sample_performance_chart(self) -> LineChart:
        analysed_tms = self.model.input_data.analysed_tms
        frequency = self.model.input_data.frequency
        fund_cumulative_rets = analysed_tms.to_prices(
            initial_price=1.0, frequency=frequency) - 1  # type: PricesSeries
        fit_cumulative_rets = self.model.fitted_tms.to_prices(
            initial_price=1.0, frequency=frequency) - 1  # type: PricesSeries

        live_start_date = self.model.oos_start_date

        in_sample_fund_tms = fund_cumulative_rets.loc[:live_start_date]
        in_sample_fit_tms = fit_cumulative_rets.loc[:live_start_date]

        out_of_sample_fund_tms = fund_cumulative_rets.loc[live_start_date:]
        out_of_sample_fit_tms = fit_cumulative_rets.loc[live_start_date:]

        colors = Chart.get_axes_colors()

        in_sample_fund_data_elem = DataElementDecorator(in_sample_fund_tms,
                                                        color=colors[0])
        out_of_sample_fund_data_elem = DataElementDecorator(
            out_of_sample_fund_tms, color=colors[0])

        in_sample_fit_data_elem = DataElementDecorator(in_sample_fit_tms,
                                                       color=colors[1])
        out_of_sample_fit_data_elem = DataElementDecorator(
            out_of_sample_fit_tms, color=colors[1])

        legend_decorator = LegendDecorator(
            legend_placement=Location.LOWER_RIGHT)
        legend_decorator.add_entry(in_sample_fund_data_elem,
                                   self._get_security_name(analysed_tms.name))
        legend_decorator.add_entry(in_sample_fit_data_elem, 'Fit')

        is_vs_oos_performance_chart = LineChart()
        is_vs_oos_performance_chart.add_decorator(in_sample_fund_data_elem)
        is_vs_oos_performance_chart.add_decorator(out_of_sample_fund_data_elem)
        is_vs_oos_performance_chart.add_decorator(in_sample_fit_data_elem)
        is_vs_oos_performance_chart.add_decorator(out_of_sample_fit_data_elem)

        is_vs_oos_performance_chart.add_decorator(
            AxesFormatterDecorator(y_major=PercentageFormatter()))
        is_vs_oos_performance_chart.add_decorator(
            AxesLabelDecorator(y_label="Cumulative return [%]"))
        is_vs_oos_performance_chart.add_decorator(legend_decorator)

        is_vs_oos_performance_chart.add_decorator(
            TextDecorator("In Sample  ",
                          x=DataCoordinate(live_start_date),
                          y=AxesCoordinate(0.99),
                          verticalalignment='top',
                          horizontalalignment='right'))

        is_vs_oos_performance_chart.add_decorator(
            TextDecorator("  Out Of Sample",
                          x=DataCoordinate(live_start_date),
                          y=AxesCoordinate(0.99),
                          verticalalignment='top',
                          horizontalalignment='left'))
        last_date = fund_cumulative_rets.index[-1]
        is_vs_oos_performance_chart.add_decorator(
            VerticalSpanDecorator(x_min=live_start_date, x_max=last_date))

        return is_vs_oos_performance_chart