Great question. In the notebook, we are using get_strategy_returns()
function from the utils. You can see the function definition by running get_strategy_returns??
in the last line of the notebook. There is a parameter called bars_to_plot and it is set to 1500. We are passing this while plotting trading signals for the strategy. There are more than 1500 values for trading signals and that is why you are not able to see the full data like you see with returns and cumulative plot.
The trading signals chart is limited to show only the most recent 1500 bars for better visibility of the signals, while the returns and cumulative returns charts show the complete dataset.
Here is the get_strategy_returns()
def get_strategy_returns(data, col_names=['close', 'signal', 'strategy_returns'], bars_to_plot=1500):
"""
Plots the close prices, trading signals, returns, cumulative returns, and drawdowns of a trading strategy.
Also calculates and prints performance metrics like Sharpe Ratio and Maximum Drawdown.
Args:
data (pd.DataFrame): DataFrame containing close prices, trading signals, and strategy returns.
col_names (list, optional): List of column names corresponding to close prices, signals, and strategy returns. Defaults to ['close', 'signal', 'strategy_returns'].
bars_to_plot (int, optional): Number of bars to plot. Defaults to 1500.
"""
close = col_names[0]
signal = col_names[1]
strategy_returns = col_names[2]
# Plot the close prices of the stock
close_plot = data[close][-bars_to_plot:].plot(figsize=(15, 7), color='blue')
# Plot the signal
signal_plot = data[signal][-bars_to_plot:].plot(
figsize=(15, 7), secondary_y=True, ax=close_plot, style='green')
# Highlight the holding periods of the long positions
plt.fill_between(data[close][-bars_to_plot:].index, 0, 1, where=(data[signal][-bars_to_plot:] > 0),
color='green', alpha=0.1, lw=0)
# Highlight the holding periods of the short positions
plt.fill_between(data[close][-bars_to_plot:].index, 0, -1, where=(data[signal][-bars_to_plot:] < 0),
color='red', alpha=0.1, lw=0)
# Set title
plt.title('Signals for Strategy', fontsize=14)
# Plot xlabel
close_plot.set_xlabel('Date', fontsize=12)
# Plot ylabels
close_plot.set_ylabel('Price ($)', fontsize=12)
signal_plot.set_ylabel('Signal', fontsize=12)
# Set title
plt.title('Trading Signals for the Strategy', fontsize=14)
# Display the graph
plt.show()
# Plot returns
data[strategy_returns].plot(figsize=(15, 7), color='green')
plt.title('Returns of One Data Point', fontsize=14)
plt.ylabel('Returns', fontsize=12)
plt.xlabel('Year', fontsize=12)
plt.show()
# Plot cumulative returns
(data[strategy_returns]+1).cumprod().plot(figsize=(15, 7), color='black')
plt.title('Cumulative Returns', fontsize=14)
plt.ylabel('Returns (in times)', fontsize=12)
plt.xlabel('Year', fontsize=12)
plt.show()
# Create a data to store performance metrics
performance_metrics = pd.DataFrame(index=['Strategy'])
candle_difference = data.index.to_series().diff().mean().days
# Number of trading candles per day
if candle_difference >= 1:
n = np.floor(candle_difference)
else:
n = data.loc[datetime.datetime.strftime(
data.index[-1].date(), '%Y-%m-%d')].shape[0]
# Set a risk-free rate
risk_free_rate = 0.02/(252*n)
# Calculate Sharpe ratio
performance_metrics['Sharpe Ratio'] = round(np.sqrt(252*n)*(np.mean(data[strategy_returns]) -
(risk_free_rate))/np.std(data[strategy_returns]), 2)
# Compute the cumulative maximum
data['Peak'] = (data[strategy_returns]+1).cumprod().cummax()
# Compute the Drawdown
data['Drawdown'] = (
((data[strategy_returns]+1).cumprod()-data['Peak'])/data['Peak'])*100
# Compute the maximum drawdown
performance_metrics['Maximum Drawdown'] = "{0:.2f}%".format(
(data['Drawdown'].min()))
# Plot maximum drawdown
data['Drawdown'].plot(figsize=(15, 7), color='red')
# Set the title and axis labels
plt.title('Drawdowns', fontsize=14)
plt.ylabel('Drawdown(%)', fontsize=12)
plt.xlabel('Year', fontsize=12)
plt.fill_between(data['Drawdown'].index,
data['Drawdown'].values, color='red')
plt.show()
# Display performance metrics
print(performance_metrics.T)
Let me know if something is not clear.