Ejemplo n.º 1
0
 def get_results(self):
     for ticker in self.portfolio.positions:
         daily_return = pd.DataFrame(self.portfolio.positions[ticker].log)["price"].astype(float).pct_change().fillna(0.0)
         cum_return = np.exp(np.log(1+daily_return).cumsum())         
         drawdown,max_drawdown,drawdown_duration = perf.create_drawdowns(cum_return)
         
         statistics = {}
         statistics["sharpe"] = perf.create_sharpe_ratio(daily_return,self.periods)
         statistics["drawdowns"] = drawdown
         statistics["max_drawdown"] = max_drawdown
         statistics["max_drawdown_pct"] = max_drawdown
         statistics["max_drawdown_duration"] = drawdown_duration
         statistics["daily_returns"] = daily_return
         statistics["cum_returns"] = cum_return
         statistics["date"] = pd.DataFrame(self.portfolio.positions[ticker].log)["date"]
         
         self.constituents[ticker] = statistics
         
     if self.benchmark is not None:
         "Need to change the benchamrk here"
         daily_return_b = pd.DataFrame(self.portfolio.positions[ticker].log)["price"].astype(float).pct_change().fillna(0.0)
         cum_returns_b = np.exp(np.log(1 + daily_return_b).cumsum())
         dd_b, max_dd_b, dd_dur_b = perf.create_drawdowns(cum_returns_b)
         statistics["sharpe_b"] = perf.create_sharpe_ratio(returns_b)
         
         statistics["drawdowns_b"] = dd_b
         statistics["max_drawdown_pct_b"] = max_dd_b
         statistics["max_drawdown_duration_b"] = dd_dur_b
         statistics["security_b"] = security_b
         statistics["returns_b"] = returns_b
         statistics["rolling_sharpe_b"] = rolling_sharpe_b
         statistics["cum_returns_b"] = cum_returns_b
         self.constituents[ticker] = statistics
    def output_summary_stats(self):
        """
        Creates a list of summary statistics for the portfolio

        Outputs:
            equity.csv

        Can be loaded into a Matplotlib script, or spreadsheet software for
        analysis
        """

        total_return = self.equity_curve['equity_curve'][-1]
        returns = self.equity_curve['returns']
        pnl = self.equity_curve['equity_curve']

        sharpe_ratio = create_sharpe_ratio(returns, period=252*60*6.5)
        drawdown, max_dd, dd_duration = create_drawdowns(pnl)
        self.equity_curve['drawdown'] = drawdown

        stats = [("Total Return", "%0.2f%%" % \
                ((total_return - 1.0) * 100.0)),
                ("Sharpe Ratio", "%0.2f" % sharpe_ratio),
                ("Max Drawdown", "%0.2f%%" % (max_dd * 100.0)),
                ("Drawdown Duration", "%d" % dd_duration)]

        self.equity_curve.to_csv('equity.csv')

        return stats
Ejemplo n.º 3
0
    def output_summary_stats(self):
        """
        Creates a list of summary statistics for the portfolio.
        """
        total_return = self.equity_curve['equity_curve'][-1]
        returns = self.equity_curve['returns']
        pnl = self.equity_curve['equity_curve']

        # Days, hours, minutes or seconds
        if self.periods == "D":
            periods = 252
        elif self.periods == "H":
            periods = 252 * 6.5
        elif self.periods == "M":
            periods = 252 * 6.5 * 60
        elif self.periods == "S":
            periods = 252 * 6.5 * 60 * 60

        cagr = create_cagr(pnl, periods=periods)
        sharpe_ratio = create_sharpe_ratio(returns, periods=periods)
        drawdown, max_dd, dd_duration = create_drawdowns(pnl)

        stats = [("Total Return", "%0.2f%%" % ((total_return - 1.0) * 100.0)),
                 ("CAGR", "%0.2f%%" % (cagr * 100.0)),
                 ("Sharpe Ratio", "%0.2f" % sharpe_ratio),
                 ("Max Drawdown", "%0.2f%%" % (max_dd * 100.0)),
                 ("Drawdown Duration", "%d" % dd_duration)]

        self.equity_curve["drawdown"] = drawdown

        # Output equity curve statistics
        self.equity_curve.to_csv("equity.csv")

        return stats
    def output_summary_stats(self):
        """
        Calulate states(total_return, sharpe_ratio, max_drawdown, max_duration).

        :return: list; summary data.
        """
        total_return=self.equity_curve['equity_curve'][-1]
        returns=self.equity_curve['returns']
        pnl=self.equity_curve['equity_curve']
        
        sharpe_ratio=create_sharpe_ratio(returns,periods=252*60*6.5)
        drawdown,max_dd,max_duration=create_drawdowns(pnl)
        self.equity_curve['drawdown']=drawdown
        
        stats=[("Total Return","%0.2f%%"%((total_return-1.0)*100.0)),
               ("Sharpe Ratio","%0.2f%%"%sharpe_ratio),
               ("Max Drawdown","%0.2f%%"%(max_dd*100.0)),
               ("Drawdown Duration","%d"%max_duration)]
        self.equity_curve.to_csv('equity.csv')
        return stats
    
    
        
        
        
Ejemplo n.º 5
0
    def output_summary_stats(self):
        """
        Creates a list of summary statistics for the portfolio

        Outputs:
            equity.csv

        Can be loaded into a Matplotlib script, or spreadsheet software for
        analysis
        """

        total_return = self.equity_curve['equity_curve'][-1]
        returns = self.equity_curve['returns']
        pnl = self.equity_curve['equity_curve']

        sharpe_ratio = create_sharpe_ratio(returns, period=252*60*6.5)
        drawdown, max_dd, dd_duration = create_drawdowns(pnl)
        self.equity_curve['drawdown'] = drawdown

        stats = [("Total Return", "%0.2f%%" % \
                ((total_return - 1.0) * 100.0)),
                ("Sharpe Ratio", "%0.2f" % sharpe_ratio),
                ("Max Drawdown", "%0.2f%%" % (max_dd * 100.0)),
                ("Drawdown Duration", "%d" % dd_duration)]

        self.equity_curve.to_csv('equity.csv')

        return stats
    def output_summary_stats(self):
        """
        Creates a list of summary statistics for the portfolio.
        """
        total_return = self.equity_curve['equity_curve'][-1]
        returns = self.equity_curve['return']
        pnl = self.equity_curve['equity_curve']
        # periods = 252 * 60 * 6.5

        earn_rate_year = (1 + np.mean(returns))**252 - 1
        print("平均年化收益率:", earn_rate_year)

        sharpe_ratio = create_sharpe_ratio(returns, periods=252)
        max_dd, dd_duration = create_drawdowns(pnl)
        # drawdown, max_dd, dd_duration = create_drawdowns(pnl)
        #         # self.equity_curve['drawdown'] = drawdown

        stats = [("Total Return", "%0.2f%%" % ((total_return - 1.0) * 100.0)),
                 ("Avg Year Return", "%0.2f%%" % (earn_rate_year * 100.0)),
                 ("Sharpe Ratio", "%0.2f" % sharpe_ratio),
                 ("Max Drawdown", "%0.2f" % (max_dd)),
                 ("Drawdown Duration", "%d" % dd_duration)]

        filesavepath = os.path.join(self.savepath, 'equity.csv')
        self.equity_curve.to_csv(filesavepath, index=False)

        # 绘制累计日收益率曲线
        self.plot_equity_curve()
        return stats
Ejemplo n.º 7
0
    def output_summary_stats(self):
        """
        Creates a list of summary statistics for the portfolio.
        """
        total_return = self.equity_curve['equity_curve'][-1]
        returns = self.equity_curve['returns']
        pnl = self.equity_curve['equity_curve']

        # Days, hours, minutes or seconds
        if self.periods == "D":
            periods = 252
        elif self.periods == "H":
            periods = 252*6.5
        elif self.periods == "M":
            periods = 252*6.5*60
        elif self.periods == "S":
            periods = 252*6.5*60*60

        cagr = create_cagr(pnl, periods=periods)
        sharpe_ratio = create_sharpe_ratio(returns, periods=periods)
        drawdown, max_dd, dd_duration = create_drawdowns(pnl)

        stats = [("Total Return", "%0.2f%%" % ((total_return - 1.0) * 100.0)),
                 ("CAGR", "%0.2f%%" % (cagr * 100.0)),
                 ("Sharpe Ratio", "%0.2f" % sharpe_ratio),
                 ("Max Drawdown", "%0.2f%%" % (max_dd * 100.0)),
                 ("Drawdown Duration", "%d" % dd_duration)]

        self.equity_curve["drawdown"] = drawdown

        # Output equity curve statistics
        self.equity_curve.to_csv("equity.csv")

        return stats
Ejemplo n.º 8
0
    def output_summary_stats(self):
        total_return = self.equity_curve['equity_curve'][-1]
        drawdown, duration = create_drawdowns(
            self.equity_curve['equity_curve'])

        return [('Total return', (total_return - 1) * 100),
                ('Sharpe ratio',
                 create_sharpe_ratio(self.equity_curve['returns'])),
                ('Max drawdown', drawdown * 100),
                ('Drawdown duration', duration)]
Ejemplo n.º 9
0
	def output_summary_stats(self):
		total_return=self.equity_curve['equity_curve'][-1]
		returns=self.equity_curve['returns']
		pnl=self.equity_curve['equity_curve']
		sharpe_ratio=create_sharpe_ratio(returns)
		max_dd,dd_duration=create_drawdowns(pnl)
		stats=[("Total Return","%0.2f%%" % ((total_return-1.0)*1000.0)),("Sharpe Ratio", "%0.2f" % sharpe_ratio),("Max Drawdown", "%0.2f%%" % (max_dd*100.0)),("Drawdown Duration", "%d" % dd_duration)]
		plt.clf()
		plt.plot(self.equity_curve.index,pnl)
		plt.savefig('cumulative_return')
		return stats
Ejemplo n.º 10
0
 def output_summary_stats(self):
     """
     Creates a list of summary statistics for the portfolio
     """
     total_return = self.equity_curve['equity_curve'][-1]
     returns = self.equity_curve['returns']
     pnl = self.equity_curve['equity_curve']
     
     sharpe_ratio = create_sharpe_ratio(returns)
     max_dd, dd_duration = create_drawdowns(pnl)
     
     stats = [("Total Return", "%0.2f%%" % ((total_return - 1)*100)),
             ("Sharpe Ratio", "%0.2f" % sharpe_ratio),
             ("Max Drawdown", "%0.2f%%" % (max_dd*100.0)),
             ("Drawdown Duration", "%d" %dd_duration)]
             
     self.equity_curve.to_csv('equity.csv')
     return stats
     
     
     
     
     
     
     
     
     
     
     
         
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
Ejemplo n.º 11
0
 def output_summary_stats(self):
     total_return=self.equity_curve['equity_curve'][-1]
     returns=self.equity_curve['returns']
     pnl=self.equity_curve['equity_curve']
     
     sharpe_ratio=create_sharpe_ratio(returns)
     max_dd,dd_duration=create_drawdowns(pnl)
     
     stats=[("total return","%0.2f%%"%((total_return-1.0)*100.0)),
            ("sharpe ratio","%0.2f"%sharpe_ratio),
            ("Max Drawdown","%0.2f%%"%(max_dd*100)),
            ("Drawdown duration","%d"%dd_duration)]
     return stats
Ejemplo n.º 12
0
 def output_summary_stats(self):
     total_return = self.equity_curve['equity_curve'][-1]
     returns = self.equity_curve['returns']
     pnl = self.equity_curve['equity_curve']
     sharpe_ratio = create_sharpe_ratio(returns)
     max_dd, dd_duration = create_drawdowns(pnl)
     stats = [("Total Return", "%0.2f%%" % ((total_return - 1.0) * 1000.0)),
              ("Sharpe Ratio", "%0.2f" % sharpe_ratio),
              ("Max Drawdown", "%0.2f%%" % (max_dd * 100.0)),
              ("Drawdown Duration", "%d" % dd_duration)]
     plt.clf()
     plt.plot(self.equity_curve.index, pnl)
     plt.savefig('cumulative_return')
     return stats
Ejemplo n.º 13
0
    def output_summary_stats(self):
        # creates a list of summary statistics for the portfolio (ie. sharpie and markdown info)
        total_return = self.equity_curve['equity_curve'][-1]
        returns = self.equity_curve['returns']
        pnl = self.equity_curve['equity_curve']

        sharpe_ratio = create_sharpe_ratio(returns)
        max_dd, dd_duration = create_drawdowns(pnl)

        stats = [("Total Return", "%0.2f%%" % ((total_return - 1.0) * 100.0)),
                 ("Sharpe Ratio", "%0.2f" % sharpe_ratio),
                 ("Max Drawdown", "%0.2f%%" % (max_dd * 100.0)),
                 ("Drawdown Duration", "%d" % dd_duration)]

        return stats
Ejemplo n.º 14
0
    def output_summary_stats(self):
        equity_curve = self.create_equity_curve_df()

        total_return = equity_curve['equity_curve'][-1]
        returns = equity_curve['returns']
        pnl = equity_curve['equity_curve']

        sharpe_ratio = create_sharpe_ratio(returns)
        max_dd, dd_duration = create_drawdowns(pnl)

        stats = [('Total Return', '%0.2f%%' % ((total_return - 1.0) * 100.0)),
                 ('sharpe Ratio', '%0.2f' % sharpe_ratio),
                 ('Max Drawdown', '%0.2f%%' % (max_dd * 100.0)),
                 ('Drawdown Duration', '%s' % dd_duration)]
        return stats
Ejemplo n.º 15
0
    def output_summary_stats(self):
        """
        Создает список статистических показателей для портфолио — коэффициент Шарпа и данные по просадке.
        """
        total_return = self.equity_curve['equity_curve'][-1]
        returns = self.equity_curve['returns']
        pnl = self.equity_curve['equity_curve']

        sharpe_ratio = create_sharpe_ratio(returns)
        max_dd, dd_duration = create_drawdowns(pnl)

        stats = [("Total Return", "%0.2f%%" % ((total_return - 1.0) * 100.0)),
                 ("Sharpe Ratio", "%0.2f" % sharpe_ratio),
                 ("Max Drawdown", "%0.2f%%" % (max_dd * 100.0)),
                 ("Drawdown Duration", "%d" % dd_duration)]
        return stats
Ejemplo n.º 16
0
    def output_summary_stats(self):
        """
        统计夏普率, 回测等信息。
        """
        total_return = self.equity_curve['equity_curve'][-1]
        returns = self.equity_curve['returns']
        pnl = self.equity_curve['equity_curve']

        sharpe_ratio = create_sharpe_ratio(returns)
        max_dd, dd_duration = create_drawdowns(pnl)

        stats = [("Total Return", "%0.2f%%" % ((total_return - 1.0) * 100.0)),
                 ("Sharpe Ratio", "%0.2f" % sharpe_ratio),
                 ("Max Drawdown", "%0.2f%%" % (max_dd * 100.0)),
                 ("Drawdown Duration", "%d" % dd_duration)]
        return stats
Ejemplo n.º 17
0
    def output_summary_stats(self):

        total_return = self.equity_curve['equity_curve'][-1]
        returns = self.equity_curve['returns']
        pnl = self.equity_curve['equity_curve']

        sharpe_ratio = create_sharpe_ratio(returns)
        drawdown, max_dd, dd_duration = create_drawdowns(pnl)
        self.equity_curve['drawdown'] = drawdown

        stats = [("Total Return", "%0.2f%%" % ((total_return - 1.0) * 100.0)),
                 ("Sharpe Ratio", "%0.2f" % sharpe_ratio),
                 ("Max Drawdown", "%0.2f%%" % (max_dd * 100)),
                 ("Drawdown Duration", "%d" % dd_duration)]
        self.equity_curve.to_csv('equity.csv')
        return stats
Ejemplo n.º 18
0
    def output_summary_stats(self, frequency = 252):
        """
        Creates a list of summary statistics for the portfolio.
        """
        total_return = self.equity_curve['equity_curve'][-1]
        returns = self.equity_curve['returns']
        pnl = self.equity_curve['equity_curve']

        sharpe_ratio = create_sharpe_ratio(returns, periods=frequency)
        drawdown, max_dd, dd_duration = create_drawdowns(pnl)
        self.equity_curve['drawdown'] = drawdown
        self.equity_curve['drawdown'][0] = 0.0

        stats = [("Total Return", "%0.2f%%" %  ((total_return - 1.0) * 100.0)), 
        ("Sharpe Ratio", "%0.2f" % sharpe_ratio), ("Max Drawdown", "%0.2f%%" % (max_dd * 100.0)), ("Drawdown Duration", "%d" % dd_duration)]

        self.equity_curve.to_csv('EquityCurve.csv')
        return stats
Ejemplo n.º 19
0
    def output_summary_stats(self):
        """
        Creates a list of summary statistics for the portfolio such
        as Sharpe Ratio and drawdown information.
        """

        total_return = self.equity_curve['equity_curve'][-1]
        returns = self.equity_curve['returns']
        pnl = self.equity_cure['equity_curve']

        sharpe_ratio = create_sharpe_ratio(returns)
        max_dd, dd_duration = create_drawdowns(pnl)

        stats = [("Total Return: %0.2f%%" % ((total_return - 1.0) * 100.0)),
                 ("Sharpe Ratio: %0.2f" % sharpe_ratio),
                 ("Max Drawdown: %0.2f%%" % (max_dd * 100.0)),
                 ("Drawdown Duration: %d" % dd_duration)]
        return stats
Ejemplo n.º 20
0
    def output_summary_stats(self):
        """
        Creates a list of summary statistics for the portfolio.
        """
        total_return = self.equity_curve['equity_curve'][-1]
        returns = self.equity_curve['returns']
        pnl = self.equity_curve['equity_curve']

        sharpe_ratio = create_sharpe_ratio(returns, periods=252)
        drawdown, max_dd, dd_duration = create_drawdowns(pnl)
        self.equity_curve['drawdown'] = drawdown

        stats = [("Total Return: {:.2f}%".format((total_return - 1) * 100)),
                 ("Sharpe Ratio: {:.2f} ".format(sharpe_ratio)),
                 ("Max Drawdown: {:.2f}%".format(max_dd * 100)),
                 ("Drawdown Duration: {:.2f}".format(dd_duration))]
        # self.equity_curve.to_csv("equity.csv")
        return stats
Ejemplo n.º 21
0
    def output_summary_stats(self):
        """
        Creates a list of summary statistics for the portfolio.
        """
        total_return = self.equity_curve['equity_curve'][-1]
        returns = self.equity_curve['returns']
        pnl = self.equity_curve['equity_curve']

        sharpe_ratio = create_sharpe_ratio(returns, periods=252)
        drawdown, max_dd, dd_duration = create_drawdowns(pnl)
        self.equity_curve['drawdown'] = drawdown

        stats = [("Total Return: {:.2f}%".format((total_return - 1) * 100)),
                 ("Sharpe Ratio: {:.2f} ".format(sharpe_ratio)),
                 ("Max Drawdown: {:.2f}%".format(max_dd * 100)),
                 ("Drawdown Duration: {:.2f}".format(dd_duration))]
        # self.equity_curve.to_csv("equity.csv")
        return stats
Ejemplo n.º 22
0
    def output_summary_stats(self):

        #Returns a list of tuples

        self.equity_curve = self.create_equity_curve()
        total_return = self.equity_curve['equity_curve'][-1]
        returns = self.equity_curve['returns']
        equity_curve = self.equity_curve['equity_curve']

        sharpe_ratio = create_sharpe_ratio(returns)
        max_drawdown, duration = create_drawdowns(self.equity_curve)

        stats = [('Total Return', '{}'.format((total_return - 1) * 100)),
                 ('Sharpe Ratio', '{}'.format(sharpe_ratio)),
                 ('Max Drawdown', '{}'.format(max_drawdown)),
                 ('Drawdown Duration', '{}'.format(duration))]

        return stats
Ejemplo n.º 23
0
 def output_summary_stats(self):
     """
     Creates a list of summary statistics for the portfolio such
     as Sharpe Ratio and drawdown information.
     """
     
     total_return = self.equity_curve['equity_curve'][-1]
     returns = self.equity_curve['returns']
     pnl = self.equity_cure['equity_curve']
     
     sharpe_ratio = create_sharpe_ratio(returns)
     max_dd, dd_duration = create_drawdowns(pnl)
     
     stats = [("Total Return: %0.2f%%" % ((total_return - 1.0) * 100.0)),
              ("Sharpe Ratio: %0.2f" % sharpe_ratio),
              ("Max Drawdown: %0.2f%%" % (max_dd * 100.0)),
              ("Drawdown Duration: %d" % dd_duration)]
     return stats
Ejemplo n.º 24
0
    def output_summary_stats(self):
        total_return = self.equity_curve['equity_curve'][-1]
        returns = self.equity_curve['returns']
        pnl = self.equity_curve['equity_curve']

        print(total_return, returns, pnl)

        sharpe_ratio = create_sharpe_ratio(returns, periods=252 * 60 * 6.5)
        drawdown, max_dd, dd_duration = create_drawdowns(pnl)
        self.equity_curve['drawdown'] = drawdown

        stats = [('Total Return', '%0.2f%%' % ((total_return - 1.0) * 100.0)),
                 ('Sharpe Ratio', '%0.2f' % sharpe_ratio),
                 ('Max Drawdown', '%0.2f%%' % (max_dd * 100.0)),
                 ('Drawdown Duration', '%d' % dd_duration)]

        self.equity_curve.to_csv('equity.csv')

        return stats
Ejemplo n.º 25
0
    def output_summary_stats(self, filename):
        """
            Statistiche create per il portfolio
            """

        total_return = self.equity_curve['equity_curve'][-1]
        returns = self.equity_curve['returns']
        pnl = self.equity_curve['equity_curve']

        sharpe_ratio = create_sharpe_ratio(returns, periods=252)
        drawdown, max_dd, dd_duration = create_drawdowns(pnl)
        self.equity_curve['drawdown'] = drawdown

        stats = [("Total Return", "%0.2f%%" % \
                   ((total_return - 1.0) * 100.0)),
                ("Sharpe Ratio", "%0.2f%%" % sharpe_ratio),
                ("Max Drawdown", "%0.2f%%" % (max_dd * 100.0)),
                ("Drawdown Duration", "%f" % dd_duration)]
        self.equity_curve.to_csv(filename)
        return stats
Ejemplo n.º 26
0
    def output_summary_stats(self):
        """
        Creates a list of summary statistics for the portfolio.
        """
        total_return = self.equity_curve["equity_curve"][-1]
        returns = self.equity_curve["returns"]
        pnl = self.equity_curve["equity_curve"]
        sharpe_ratio = create_sharpe_ratio(returns, periods=252)  #*60*6.5)
        # здесь похоже не верно считал, так как все же мы статистику ведём пока по дням, а не по часам
        drawdown, max_dd, dd_duration = create_drawdowns(pnl)
        self.equity_curve["drawdown"] = drawdown
        stats = [("Total Return", "%0.2f%%" % \
            ((total_return - 1.0) * 100.0)),
            ("Sharpe Ratio", "%0.2f" % sharpe_ratio),
            ("Max Drawdown", "%0.2f%%" % (max_dd * 100.0)),
            ("Drawdown Duration", "%d" % dd_duration)]

        self.equity_curve.to_csv("equity.csv")
        draw(self.equity_curve['equity_curve'])
        # TODO Здесь рисует график. В идеале перенести его нужно по результатам выполнения бэктестинга
        return stats
    def output_summary_stats(self):

        #用performance的两个方程算sharp ratio/drawdown
        """
        Creates a list of summary statistics for the portfolio.
        """
        total_return = self.equity_curve['equity_curve'][-1]
        returns = self.equity_curve['returns']
        pnl = self.equity_curve['equity_curve']

        sharpe_ratio = create_sharpe_ratio(returns)
        drawdown, max_dd, dd_duration = create_drawdowns(pnl)
        self.equity_curve['drawdown'] = drawdown

        stats = [("Total Return", "%0.2f%%" % ((total_return - 1.0) * 100.0)),
                 ("Sharpe Ratio", "%0.2f" % sharpe_ratio),
                 ("Max Drawdown", "%0.2f%%" % (max_dd * 100.0)),
                 ("Drawdown Duration", "%d" % dd_duration)]

        self.equity_curve.to_csv('equity.csv')
        return stats
Ejemplo n.º 28
0
    def output_summary_stats(self):
        """
        Creates a list of summary statistics for the portfolio.
        """
        total_return = self.equity_curve['equity_curve'][-1]
        returns = self.equity_curve['returns']
        pnl = self.equity_curve['equity_curve']

        sharpe_ratio = create_sharpe_ratio(returns, periods=252 * 60 * 6.5)
        drawdown, max_dd, dd_duration = create_drawdowns(pnl)
        self.equity_curve['drawdown'] = drawdown

        trades_avg_duration = floor(
            self.trades['duration'].mean().total_seconds() / 60)
        trades_avg_return = self.trades['returns'].mean() * 100

        trades_total_win = self.trades['win_trades'].sum()
        trades_total_loss = self.trades['loss_trades'].sum()
        trades_win_loss_ratio = trades_total_win / trades_total_loss
        total_trades = len(self.trades)
        trades_win_pct = trades_total_win / total_trades * 100
        trades_loss_pct = trades_total_loss / total_trades * 100

        stats = [("Total Return", "%0.2f%%" % ((total_return - 1.0) * 100.0)),
                 ("Avg Return (%)", trades_avg_return),
                 ("Avg Trade Duration (min)", trades_avg_duration),
                 ("Total win trades", trades_total_win),
                 ("Total loss trades", trades_total_loss),
                 ("Win/Loss Ratio", trades_win_loss_ratio),
                 ("% Wins", trades_win_pct), ("% Losses", trades_loss_pct),
                 ("Sharpe Ratio", "%0.2f" % sharpe_ratio),
                 ("Max Drawdown", "%0.2f%%" % (max_dd * 100.0)),
                 ("Drawdown Duration", "%d" % dd_duration)]

        dir_path = f'{Path().absolute()}/backtest_results'

        self.equity_curve.to_csv(f'{dir_path}/equity.csv')
        self.trades.to_csv(f'{dir_path}/trades.csv')

        return stats
Ejemplo n.º 29
0
    def output_summary_stats(self):
        """
        Creates a list of summary statistics for the portfolio
        
        This method outputs the equity curve and varioys performance 
        statistics related to the strategy. 
        
        The final line ouputs a file, equity.csv, to the same directory
        as the code, whcih can be loaded into a Matplotlib Python script
        for subsequent analysis.
        
        Note:
            The drawdown duration is given in terms of the absolute 
            number of "bars" that teh drawdown carried on for, as 
            opposed to a particular timeframe.

        Returns
        -------
        'list'
            Returns a list of stats relating to portfolio performance

        """

        total_return = self.equity_curve['equity_curve'][-1]
        returns = self.equity_curve['returns']
        pnl = self.equity_curve['equity_curve']

        sharpe_ratio = create_sharpe_ratio(
            returns, periods=252)  # For Minute level bars: periods=252*6.5*60
        drawdown, max_dd, dd_duration = create_drawdowns(pnl)
        self.equity_curve['drawdown'] = drawdown

        stats = [("Total Return", "%0.2f%%" % ((total_return - 1) * 100.0)),
                 ("Sharpe Ratio", "%0.2f" % sharpe_ratio),
                 ("Max Drawdown", "%0.2f%%" % (max_dd * 100.0)),
                 ("Drawdown Duration", "%d" % dd_duration)]

        self.equity_curve.to_csv('equity.csv')
        return stats
Ejemplo n.º 30
0
    def output_results(self):
        # Chiusura del file csv del backtest.csv cosiì da poter
        # essere caricato con Pandas senza errori
        self.backtest_file.close()

        in_filename = "backtest.csv"
        out_filename = "equity.csv"
        in_file = os.path.join(OUTPUT_RESULTS_DIR, in_filename)
        out_file = os.path.join(OUTPUT_RESULTS_DIR, out_filename)

        # Crea il dataframe della curva di equity
        df = pd.read_csv(in_file, index_col=0)
        df.dropna(inplace=True)
        df["Total"] = df.sum(axis=1)
        df["Returns"] = df["Total"].pct_change()
        df["Equity"] = (1.0 + df["Returns"]).cumprod()

        # Crea le statistiche di drawdown
        drawdown, max_dd, dd_duration = create_drawdowns(df["Equity"])
        df["Drawdown"] = drawdown
        df.to_csv(out_file, index=True)

        print("Simulation complete and results exported to %s" % out_filename)
Ejemplo n.º 31
0
    def output_results(self):
        # Closes off the Backtest.csv file so it can be 
        # read via Pandas without problems
        self.backtest_file.close()
        
        in_filename = "backtest.csv"
        out_filename = "equity.csv" 
        in_file = os.path.join(OUTPUT_RESULTS_DIR, in_filename)
        out_file = os.path.join(OUTPUT_RESULTS_DIR, out_filename)

        # Create equity curve dataframe
        df = pd.read_csv(in_file, index_col=0)
        df.dropna(inplace=True)
        df["Total"] = df.sum(axis=1)
        df["Returns"] = df["Total"].pct_change()
        df["Equity"] = (1.0+df["Returns"]).cumprod()
        
        # Create drawdown statistics
        drawdown, max_dd, dd_duration = create_drawdowns(df["Equity"])
        df["Drawdown"] = drawdown
        df.to_csv(out_file, index=True)
        
        print("Simulation complete and results exported to %s" % out_filename)
Ejemplo n.º 32
0
    def output_summary_stats(self):
        """
        Creates a list of summary statistics for the portfolio.
        """
        total_return = self.equity_curve['equity_curve'][-1]
        returns = self.equity_curve['returns']
        pnl = self.equity_curve['equity_curve']

        sharpe_ratio = create_sharpe_ratio(returns)
        drawdown, max_dd, dd_duration = create_drawdowns(pnl)
        self.equity_curve['drawdown'] = drawdown
        if len(dd_duration) == 1:
            dd_duration = dd_duration[0]

        stats = [("Total Return", "%0.2f%%" % ((total_return - 1.0) * 100.0)),
                 ("Sharpe Ratio", "%0.2f" % sharpe_ratio),
                 ("Max Drawdown", "%0.2f%%" % (max_dd * 100.0)),
                 ("Drawdown Duration", "%s" % dd_duration)]

        self.equity_curve.to_csv('equity.csv')
        self.positions.to_csv('positions.csv')
        self.prices.to_csv('prices.csv')

        return stats
    def output_summary_stats(self, strategy_title):
        '''
        Creates a list of summary statistics for the portfolio.
        '''
        total_return = self.equity_curve['equity_curve'][-1]
        returns = self.equity_curve['returns']
        pnl = self.equity_curve['equity_curve']

        sharpe_ratio = create_sharpe_ratio(
            returns, periods=252)  # i guess this is for minute resolution
        drawdown, max_dd, dd_duration = create_drawdowns(pnl)
        self.equity_curve['drawdown'] = drawdown

        stats = [
            'Total Return',
            '%0.2f%%' % ((total_return - 1.0) * 100.0),
            ('Sharpe Ratio', '%0.2f' % sharpe_ratio),
            ('Max Drawdown', '%0.2f%%' % (max_dd * 100.0)),
            ('Drawdown Duration', '%d' % dd_duration)
        ]
        self.equity_curve.to_csv('equity.csv')
        self.print_chart(max_dd, dd_duration, total_return, sharpe_ratio,
                         strategy_title)
        return stats
Ejemplo n.º 34
0
    def output_summary_stats(self):
        """
        Creates a list of summary statistics for the portfolio.
        :return:
        """
        total_return = self.equity_curve['equity_curve'][-1]
        returns = self.equity_curve['returns']
        pnl = self.equity_curve['equity_curve']
        # self.equity_curve.to_csv("prac_equity_curve.csv")
        # pd.DataFrame(self.all_positions).to_csv("prac_position.csv")

        sharpe_ratio = create_sharpe_ratio(returns, periods='minutely')
        drawdown, max_dd, max_dd_duration = create_drawdowns(pnl)
        self.equity_curve['drawdown'] = drawdown

        stats = [('Total_Return', "%0.2f%%" % ((total_return - 1.0) * 100.0)),
                 ('Sharpe_Ratio', "%0.2f" % sharpe_ratio),
                 ("Max Drawdown", "%0.2f%%" % (max_dd * 100.0)),
                 ("Max Drawdown Dur.", "%d" % max_dd_duration)]

        self.equity_curve.to_csv('equity_curve.csv')
        # pnl.plot()
        # plt.show()
        return stats
Ejemplo n.º 35
0
    def output_summary_stats(self):
        """
        Creates a list of summary statistics for the portfolio.
        """
        total_return = self.equity_curve['equity_curve'][-1]
        returns = self.equity_curve['returns']
        pnl = self.equity_curve['equity_curve']

        sharpe_ratio = create_sharpe_ratio(returns, periods=252*60*6.5)
        drawdown, max_dd, dd_duration = create_drawdowns(pnl)
        self.equity_curve['drawdown'] = drawdown

        stats = [("Total Return", "%0.2f%%" % ((total_return - 1.0) * 100.0)),
                 ("Sharpe Ratio", "%0.2f" % sharpe_ratio),
                 ("Max Drawdown", "%0.2f%%" % (max_dd * 100.0)),
                 ("Drawdown Duration", "%d" % dd_duration)]

        output = {'Total Return': "%0.2f%%" % ((total_return - 1.0) * 100.0), 'Sharpe Ratio': "%0.2f" % sharpe_ratio, 'Max Drawdown': "%0.2f%%" % (max_dd * 100.0), 'Drawdown Duration': dd_duration}
        df = pd.Series(output).to_frame()
        df.columns = ['value']
        df.to_csv('output.csv', index_label='parameter')

        self.equity_curve.to_csv('../equity.csv')
        return stats
Ejemplo n.º 36
0
 def output_summary_stats(self):
     """
     Creates a list of summary statistics for the portfolio.
     """
     total_return = self.equity_curve[’equity_curve’][-1]
     returns = self.equity_curve[’returns’]
     pnl = self.equity_curve[’equity_curve’]
     sharpe_ratio = create_sharpe_ratio(returns, periods=252*60*6.5) drawdown, max_dd, dd_duration = create_drawdowns(pnl)
     self.equity_curve[’drawdown’] = drawdown
     stats = [("Total Return", "%0.2f%%" % \
        ((total_return - 1.0) * 100.0)),
     ("Sharpe Ratio", "%0.2f" % sharpe_ratio),
     ("Max Drawdown", "%0.2f%%" % (max_dd * 100.0)),
     ("Drawdown Duration", "%d" % dd_duration)]
     self.equity_curve.to_csv('eqiuity.csv')
     return stats
Ejemplo n.º 37
0
    periods = 252

    # Adjust lookback period from 50 to 200 in increments
    # of 10 in order to produce sensitivities
    for lb in lookbacks:
        print "Calculating lookback=%s..." % lb
        pairs = create_pairs_dataframe(datadir, symbols)
        pairs = calculate_spread_zscore(pairs, symbols, lookback=lb)
        pairs = create_long_short_market_signals(pairs, symbols,
                                                 z_entry_threshold=2.0,
                                                 z_exit_threshold=1.0)

        portfolio = create_portfolio_returns(pairs, symbols)
        returns.append(portfolio.ix[-1]['cum_returns'])
        sharps.append(create_sharpe_ratio(portfolio['returns']))
        drawdown, max_dd, dd_duration = create_drawdowns(portfolio['cum_returns'])
        draw_downs.append(max_dd)

    df = pd.DataFrame(lookbacks)
    df.columns = ['LookBack']
    df['Returns'] = returns
    df['Sharps'] = sharps
    df['Max Draw Down'] = draw_downs

    print df

    print "Plot the lookback-performance scatterchart..."
    plt.plot(lookbacks, returns, '-o')
    plt.show()
Ejemplo n.º 38
0
    def output_summary_stats(self):
        """
        Creates a list of summary statistics for the portfolio.
        """
        total_return = self.equity_curve["equity_curve"][-1]
        returns = self.equity_curve["returns"]
        pnl = self.equity_curve["equity_curve"]
        periods = self.equity_curve.shape[0]

        start_date = self.equity_curve.index[
            1]  #注意,一般來說應該要是[0],選擇[1]是因為資料不足一年以上
        end_date = self.equity_curve.index[-1]
        time_delta_days = (end_date - start_date).days

        cmd_list = ["TXFC2", "TXFD1", "TXFE1", "TXFL1"]  #先寫死,之後再改成讀入
        win = 0  #賺錢次數
        lose = 0  #賠錢次數
        entry_amount = 0  #進場金額
        out_amount = 0  #出場金額
        record_amount = {}
        record_amount["entry_amount"] = []
        record_amount["out_amount"] = []
        record_amount["profit"] = []
        record_amount["loss"] = []

        for commodity in cmd_list:
            for j in range(0, len(self.equity_curve[commodity]) - 1):
                if ((self.equity_curve[commodity][j + 1] >
                     self.equity_curve[commodity][j])
                        and self.equity_curve[commodity][j] == 0):
                    entry_amount = self.equity_curve[commodity][j + 1]
                    record_amount["entry_amount"].append(entry_amount)
                if (self.equity_curve[commodity][j] != 0
                        and self.equity_curve[commodity][j + 1] == 0):
                    out_amount = self.equity_curve[commodity][j]
                    record_amount["out_amount"].append(out_amount)

        for i in range(0, len(record_amount["out_amount"])):
            profit = record_amount["out_amount"][i] - record_amount[
                "entry_amount"][i]
            if profit > 0:
                win = win + 1
                record_amount["profit"].append(profit)
            elif profit <= 0:
                lose = lose + 1
                record_amount["loss"].append(profit)

        win_rate = win / (win + lose)  #勝率
        #賺賠比 = gross profit / gross loss
        profit_factor = (-1) * sum(record_amount["profit"]) / sum(
            record_amount["loss"])
        #CAGR = (初始價值/結束價值)**(1/年化期數)-1
        CAGR = (self.equity_curve["total"][-1] /
                self.equity_curve["total"][0])**(1 /
                                                 (time_delta_days / 252)) - 1

        yearly_sharpe_ratio, minutely_sharpe_ratio = create_sharpe_ratio(
            returns, periods)
        yearly_sortino_ratio, minutely_sortino_ratio = create_sortino_ratio(
            returns, periods)
        minutely_skewness = create_skewness(returns, periods)
        minutely_kurtosis = create_kurtosis(returns, periods)
        drawdown, max_dd, dd_duration = create_drawdowns(pnl)
        minutely_calmar_ratio = create_calmar_ratio(returns, periods, max_dd)
        self.equity_curve["drawdown"] = drawdown
        stats = [
            "Start Date:" + str(start_date), "End Date:" + str(end_date),
            ("Total Return", "%0.2f%%" % ((total_return - 1.0) * 100.0)),
            ("Minutely Sharpe Ratio", "%0.4f" % minutely_sharpe_ratio),
            ("Minutely Sortino Ratio", "%0.4f" % minutely_sortino_ratio),
            ("Minutely Skewness", "%0.3f" % minutely_skewness),
            ("Minutely Kurtosis", "%0.3f" % minutely_kurtosis),
            ("Minutely Calmar Ratio", "%0.6f" % minutely_calmar_ratio),
            ("CAGR", "%0.5f%%" % (CAGR * 100.0)),
            ("Yearly Sharpe Ratio", "%0.2f" % yearly_sharpe_ratio),
            ("Yearly Sortino Ratio", "%0.2f" % yearly_sortino_ratio),
            ("Max Drawdown", "%0.2f%%" % (max_dd * 100.0)),
            ("Drawdown Duration", "%d" % dd_duration),
            ("Win Rate", "%0.2f" % win_rate),
            ("Profit Factor", "%0.2f" % profit_factor)
        ]

        self.equity_curve.to_csv('equity.csv')
        return stats
Ejemplo n.º 39
0
    def get_results(self):
        """
        Return a dict with all important results & stats.
        """
        # Equity
        # equity_s = pd.Series(self.equity).sort_index()

        # Returns
        # returns_s = equity_s.pct_change().fillna(0.0)
        bench = pd.read_pickle(self.benchmark)
        rets = pd.concat([bench.loc[self.equity.index[0]:self.equity.index[-1]],
                          self.equity.rename("equity")], axis=1).fillna(0.0)
#         returns_s=self.equity.sort_index().fillna(0.0)
        returns_s = rets['equity']

        # Rolling Annualised Sharpe
        rolling = returns_s.rolling(window=self.periods)
        rolling_sharpe_s = np.sqrt(self.periods) * (
            rolling.mean() / rolling.std()
        )

        # Cummulative Returns
        cum_returns_s = np.exp(np.log(1 + returns_s).cumsum())

        # Drawdown, max drawdown, max drawdown duration
        dd_s, max_dd, dd_dur = perf.create_drawdowns(cum_returns_s)

        statistics = {}

        # Equity statistics
        statistics["sharpe"] = perf.create_sharpe_ratio(
            returns_s, self.periods
        )
        statistics["drawdowns"] = dd_s
        # TODO: need to have max_drawdown so it can be printed at end of test
        statistics["max_drawdown"] = max_dd
        statistics["max_drawdown_pct"] = max_dd
        statistics["max_drawdown_duration"] = dd_dur
        # statistics["equity"] = equity_s
        statistics["returns"] = returns_s
        statistics["rolling_sharpe"] = rolling_sharpe_s
        statistics["cum_returns"] = cum_returns_s

        # positions = self._get_positions()
        # if positions is not None:
        #     statistics["positions"] = positions

        # Benchmark statistics if benchmark ticker specified
#         if self.benchmark is not None:
        # equity_b = pd.Series(self.equity_benchmark).sort_index()
        # returns_b = equity_b.pct_change().fillna(0.0)
#         returns_b=self.equity_benchmark.sort_index().fillna(0.0)
        returns_b = rets['rets']
        rolling_b = returns_b.rolling(window=self.periods)
        rolling_sharpe_b = np.sqrt(self.periods) * (
            rolling_b.mean() / rolling_b.std()
        )
        cum_returns_b = np.exp(np.log(1 + returns_b).cumsum())
        dd_b, max_dd_b, dd_dur_b = perf.create_drawdowns(cum_returns_b)
        statistics["sharpe_b"] = perf.create_sharpe_ratio(returns_b)
        statistics["drawdowns_b"] = dd_b
        statistics["max_drawdown_pct_b"] = max_dd_b
        statistics["max_drawdown_duration_b"] = dd_dur_b
        # statistics["equity_b"] = equity_b
        statistics["returns_b"] = returns_b
        statistics["rolling_sharpe_b"] = rolling_sharpe_b
        statistics["cum_returns_b"] = cum_returns_b
        alphas = rets['equity'] - rets['rets']
        statistics["IR"] = np.mean(alphas) / np.std(alphas)

        return statistics
Ejemplo n.º 40
0
    def _plot_txt_curve(self, stats, ax=None, **kwargs):
        """
        Outputs the statistics for the equity curve.
        """
        def format_perc(x, pos):
            return '%.0f%%' % x

        returns = stats["returns"]
        cum_returns = stats['cum_returns']

        IR=stats['IR']

        # if 'positions' not in stats:
        #     trd_yr = 0
        # else:
        #     positions = stats['positions']
        #     trd_yr = positions.shape[0] / (
        #         (returns.index[-1] - returns.index[0]).days / 365.0
        #     )

        if ax is None:
            ax = plt.gca()

        y_axis_formatter = FuncFormatter(format_perc)
        ax.yaxis.set_major_formatter(FuncFormatter(y_axis_formatter))

        tot_ret = cum_returns[-1] - 1.0
        cagr = perf.create_cagr(cum_returns, self.periods)
        sharpe = perf.create_sharpe_ratio(returns, self.periods)
        sortino = perf.create_sortino_ratio(returns, self.periods)
        rsq = perf.rsquared(range(cum_returns.shape[0]), cum_returns)
        dd, dd_max, dd_dur = perf.create_drawdowns(cum_returns)

        ax.text(0.25, 8.9, '总收益率', fontsize=30)
        ax.text(7.50, 8.9, '{:.0%}'.format(
            tot_ret), fontweight='bold', horizontalalignment='right', fontsize=30)

        ax.text(0.25, 7.9, '复合年均增长率', fontsize=30)
        ax.text(7.50, 7.9, '{:.2%}'.format(
            cagr), fontweight='bold', horizontalalignment='right', fontsize=30)

        ax.text(0.25, 6.9, '夏普比率', fontsize=30)
        ax.text(7.50, 6.9, '{:.2f}'.format(
            sharpe), fontweight='bold', horizontalalignment='right', fontsize=30)

        ax.text(0.25, 5.9, '索提诺比率', fontsize=30)
        ax.text(7.50, 5.9, '{:.2f}'.format(
            sortino), fontweight='bold', horizontalalignment='right', fontsize=30)

        ax.text(0.25, 4.9, '年化波动率', fontsize=30)
        ax.text(7.50, 4.9, '{:.2%}'.format(returns.std() * np.sqrt(252)),
                fontweight='bold', horizontalalignment='right', fontsize=30)

        ax.text(0.25, 3.9, 'R-Squared', fontsize=30)
        ax.text(7.50, 3.9, '{:.2f}'.format(
            rsq), fontweight='bold', horizontalalignment='right', fontsize=30)

        ax.text(0.25, 2.9, '最大日回撤', fontsize=30)
        ax.text(7.50, 2.9, '{:.2%}'.format(dd_max), color='red',
                fontweight='bold', horizontalalignment='right', fontsize=30)

        ax.text(0.25, 1.9, '最大回撤持续期', fontsize=30)
        ax.text(7.50, 1.9, '{:.0f}'.format(
            dd_dur), fontweight='bold', horizontalalignment='right', fontsize=30)

        ax.text(0.25, 0.9, '信息比率', fontsize=30)
        ax.text(7.50, 0.9, '{:.2%}'.format(
            IR), fontweight='bold', horizontalalignment='right', fontsize=30)
        ax.set_title('Curve', fontweight='bold')

        if self.benchmark is not None:
            returns_b = stats['returns_b']
            equity_b = stats['cum_returns_b']
            tot_ret_b = equity_b[-1] - 1.0
            cagr_b = perf.create_cagr(equity_b)
            sharpe_b = perf.create_sharpe_ratio(returns_b)
            sortino_b = perf.create_sortino_ratio(returns_b)
            rsq_b = perf.rsquared(range(equity_b.shape[0]), equity_b)
            dd_b, dd_max_b, dd_dur_b = perf.create_drawdowns(equity_b)

            ax.text(9.75, 8.9, '{:.0%}'.format(
                tot_ret_b), fontweight='bold', horizontalalignment='right', fontsize=30)
            ax.text(9.75, 7.9, '{:.2%}'.format(
                cagr_b), fontweight='bold', horizontalalignment='right', fontsize=30)
            ax.text(9.75, 6.9, '{:.2f}'.format(
                sharpe_b), fontweight='bold', horizontalalignment='right', fontsize=30)
            ax.text(9.75, 5.9, '{:.2f}'.format(
                sortino_b), fontweight='bold', horizontalalignment='right', fontsize=30)
            ax.text(9.75, 4.9, '{:.2%}'.format(returns_b.std(
            ) * np.sqrt(252)), fontweight='bold', horizontalalignment='right', fontsize=30)
            ax.text(9.75, 3.9, '{:.2f}'.format(
                rsq_b), fontweight='bold', horizontalalignment='right', fontsize=30)
            ax.text(9.75, 2.9, '{:.2%}'.format(dd_max_b), color='red',
                    fontweight='bold', horizontalalignment='right', fontsize=30)
            ax.text(9.75, 1.9, '{:.0f}'.format(
                dd_dur_b), fontweight='bold', horizontalalignment='right', fontsize=30)

            ax.set_title('策略 vs. 基准', fontweight='bold',size='xx-large')

        ax.grid(False)
        ax.spines['top'].set_linewidth(2.0)
        ax.spines['bottom'].set_linewidth(2.0)
        ax.spines['right'].set_visible(False)
        ax.spines['left'].set_visible(False)
        ax.get_yaxis().set_visible(False)
        ax.get_xaxis().set_visible(False)
        ax.set_ylabel('')
        ax.set_xlabel('')

        ax.axis([0, 10, 0, 10])
        return ax
Ejemplo n.º 41
0
 def _plot_txt_curve(self, stats, ax=None, **kwargs):
        """
        Outputs the statistics for the security curve.
        """
        def format_perc(x, pos):
                return '%.0f%%' % x

        stats = pd.DataFrame(stats)
        stats['date']=pd.to_datetime(stats['date'])
        stats.set_index('date',inplace=True)
        returns = stats["daily_returns"]
        cum_returns = stats['cum_returns']

        y_axis_formatter = FuncFormatter(format_perc)
        ax.yaxis.set_major_formatter(FuncFormatter(y_axis_formatter))
            
        tot_ret = cum_returns[-1] - 1.0
        cagr = perf.create_cagr(cum_returns, self.periods)
        sharpe = perf.create_sharpe_ratio(returns, self.periods)
        rsq = perf.rsuqare(range(cum_returns.shape[0]), cum_returns)
        dd, dd_max, dd_dur = perf.create_drawdowns(cum_returns)

        ax.text(0.25, 7.9, 'Total Return', fontsize=8)
        ax.text(7.50, 7.9, '{:.0%}'.format(tot_ret), fontweight='bold', horizontalalignment='right', fontsize=8)
            
        ax.text(0.25, 6.9, 'CAGR', fontsize=8)
        ax.text(7.50, 6.9, '{:.2%}'.format(cagr), fontweight='bold', horizontalalignment='right', fontsize=8)

        ax.text(0.25, 5.9, 'Sharpe Ratio', fontsize=8)
        ax.text(7.50, 5.9, '{:.2f}'.format(sharpe), fontweight='bold', horizontalalignment='right', fontsize=8)
            
        ax.text(0.25, 4.9, 'Annual Volatility', fontsize=8)
        ax.text(7.50, 4.9, '{:.2%}'.format(returns.std() * np.sqrt(252)), fontweight='bold', horizontalalignment='right', fontsize=8)
            
        ax.text(0.25, 3.9, 'R-Squared', fontsize=8)
        ax.text(7.50, 3.9, '{:.2f}'.format(rsq), fontweight='bold', horizontalalignment='right', fontsize=8)

        ax.text(0.25, 2.9, 'Max Daily Drawdown', fontsize=8)
        ax.text(7.50, 2.9, '{:.2%}'.format(dd_max), color='red', fontweight='bold', horizontalalignment='right', fontsize=8)

        ax.text(0.25, 1.9, 'Max Drawdown Duration', fontsize=8)
        ax.text(7.50, 1.9, '{:.0f}'.format(dd_dur), fontweight='bold', horizontalalignment='right', fontsize=8)

        ax.set_title('Curve', fontweight='bold')

        if self.benchmark is not None:
            returns_b = stats['returns_b']
            security_b = stats['cum_returns_b']
            tot_ret_b = security_b[-1] - 1.0
            cagr_b = perf.create_cagr(security_b)
            sharpe_b = perf.create_sharpe_ratio(returns_b)
            rsq_b = perf.rsquared(range(security_b.shape[0]), security_b)
            dd_b, dd_max_b, dd_dur_b = perf.create_drawdowns(security_b)

            ax.text(9.75, 8.9, '{:.0%}'.format(tot_ret_b), fontweight='bold', horizontalalignment='right', fontsize=8)
            ax.text(9.75, 7.9, '{:.2%}'.format(cagr_b), fontweight='bold', horizontalalignment='right', fontsize=8)
            ax.text(9.75, 6.9, '{:.2f}'.format(sharpe_b), fontweight='bold', horizontalalignment='right', fontsize=8)
            ax.text(9.75, 5.9, '{:.2%}'.format(returns_b.std() * np.sqrt(252)), fontweight='bold', horizontalalignment='right', fontsize=8)
            ax.text(9.75, 4.9, '{:.2f}'.format(rsq_b), fontweight='bold', horizontalalignment='right', fontsize=8)
            ax.text(9.75, 3.9, '{:.2%}'.format(dd_max_b), color='red', fontweight='bold', horizontalalignment='right', fontsize=8)
            ax.text(9.75, 2.9, '{:.0f}'.format(dd_dur_b), fontweight='bold', horizontalalignment='right', fontsize=8)

            ax.set_title('Curve vs. Benchmark', fontweight='bold')

        ax.grid(False)
        ax.spines['top'].set_linewidth(2.0)
        ax.spines['bottom'].set_linewidth(2.0)
        ax.spines['right'].set_visible(False)
        ax.spines['left'].set_visible(False)
        ax.get_yaxis().set_visible(False)
        ax.get_xaxis().set_visible(False)
        ax.set_ylabel('')
        ax.set_xlabel('')
            
        ax.axis([0, 10, 0, 10]) 
        return ax