Basics of Statistics - I
How to work with indicators
Basics of Statistics - II
Entropy Basics
Entropy Core Strategies
Entropy Advanced Strategies
Entropy Scanners
Backtest Entropy Alpha Strategy with Futures Data Part I
Backtest Entropy Alpha Strategy with Futures Data Part II
Backtest Entropy Alpha Strategy with Equities Data
Entropy FAQs
Entropy Trading Examples
Entropy Sessions

Analyzing Trading Metrics and Generating Graphs from Final Trade Logs

Calculate Trading Metrics

Now, here is a patch of code that analyze that details with various popular trading metrics to get an overview of strength of our strategy.

				
					net_pl = round(df["pl"].sum(), 2)
print("Net P&L:", net_pl)

num_target_hits = len(df[df['is_target']])
total_trades = len(df)
num_target_hits = total_trades-num_target_hits

print(f"Number of total trades: {total_trades}")
print(f"Number of times target is hit: {num_target_hits}")
print(f"Number of times stop loss is hit: {num_target_hits}")

win_ratio = round(num_target_hits / total_trades, 2)
print(f"Win Ratio: {win_ratio}")

avg_pl = round(df['pl'].mean(), 2)
max_pl = round(df['pl'].max(), 2)
min_pl = round(df['pl'].min(), 2)

print(f"Avg PL: {avg_pl}")
print(f"Max PL: {max_pl}")
print(f"Min PL: {min_pl}")

gross_pl = round(df['pl'].sum(), 2)
avg_gain = round(df[df['pl'] > 0]['pl'].mean(), 2)
avg_loss = round(df[df['pl'] < 0]['pl'].mean(), 2)
profit_factor = round(-df[df['pl'] < 0]['pl'].sum() / df[df['pl'] > 0]['pl'].sum(), 2)
expected_payoff = round(df['pl'].mean(), 2)
max_drawdown = round((df['pl'].cumsum().cummax() - df['pl'].cumsum()).max(), 2)

risk_free_rate = 0.02
sharpe_ratio = round((expected_payoff - risk_free_rate) / df['pl'].std(), 2)

print(f"Gross P&L: {gross_pl}")
print(f"Average Gain: {avg_gain}")
print(f"Average Loss: {avg_loss}")
print(f"Profit Factor: {profit_factor}")
print(f"Expected Payoff: {expected_payoff}")
print(f"Maximum Drawdown: {max_drawdown}")
print(f"Sharpe Ratio: {sharpe_ratio}")

# calculate gross profit and loss
gross_profit = round(df[df['pl'] > 0]['pl'].sum(), 2)
gross_loss = round(df[df['pl'] < 0]['pl'].sum(), 2)

print(f"Gross Profit: {gross_profit}")
print(f"Gross Loss: {gross_loss}")

# calculate recovery factor and maximal consecutive profit/loss
recovery_factor = round(abs(gross_profit / gross_loss), 2)
print(f"Recovery Factor: {recovery_factor}")

# calculate max consecutive wins and losses
wins = df['pl'] > 0
losses = df['pl'] < 0

max_wins = wins.groupby((wins != wins.shift()).cumsum()).cumsum().max()
max_losses = losses.groupby((losses != losses.shift()).cumsum()).cumsum().min()

print(f"Maximum consecutive wins: {max_wins}")
print(f"Maximum consecutive losses: {abs(max_losses)}")


max_consecutive_profit = df['pl'].rolling(window=2).sum().max()
max_consecutive_loss = abs(df['pl'].rolling(window=2).sum().min())

print(f"Maximal consecutive profit: {max_consecutive_profit:.2f}")
print(f"Maximal consecutive loss: {max_consecutive_loss:.2f}")

# convert the "Triggered at" and "square_off_time" columns to datetime format
df["Triggered at"] = pd.to_datetime(df["Triggered at"])
df["square_off_time"] = pd.to_datetime(df["square_off_time"])

# calculate the holding time for each trade
df["holding_time"] = df["square_off_time"] - df["Triggered at"]

# calculate the average holding time for all trades
avg_holding_time = df["holding_time"].mean()
print(f"Average holding time: {avg_holding_time}")

# calculate the average holding time for profit trades
profit_trades = df[df["pl"] > 0]
avg_profit_holding_time = profit_trades["holding_time"].mean()
print(f"Average holding time for profit trades: {avg_profit_holding_time}")

# calculate the average holding time for loss trades
loss_trades = df[df["pl"] < 0]
avg_loss_holding_time = loss_trades["holding_time"].mean()
print(f"Average holding time for loss trades: {avg_loss_holding_time}")

				
			

The Output shows all the available info you need to know to evaluate a strategy – 

				
					Net P&L: 166658.75
Number of total trades: 44
Number of times target is hit: 19
Number of times stop loss is hit: 25
Win Ratio: 0.57
Avg PL: 3787.7
Max PL: 25875.0
Min PL: -15847.5
Gross P&L: 166658.75
Average Gain: 9271.39
Average Loss: -4133.19
Profit Factor: 0.31
Expected Payoff: 3787.7
Maximum Drawdown: 25945.0
Sharpe Ratio: 0.42
Gross Profit: 241056.25
Gross Loss: -74397.5
Recovery Factor: 3.24
Maximum consecutive wins: 5
Maximum consecutive losses: 0
Maximal consecutive profit: 47250.00
Maximal consecutive loss: 19627.50
Average holding time: 0 days 04:44:50.454545454
Average holding time for profit trades: 0 days 05:29:34.615384615
Average holding time for loss trades: 0 days 03:40:13.333333333
				
			

Calculate the Profit/Loss over the Time

Let’s use the matplotlib library to plot the graph. Here goes the code –
				
					import matplotlib.pyplot as plt

# Set the color of the bars based on positive or negative values
colors = ['g' if pl >= 0 else 'r' for pl in df['pl']]

# Create the bar chart
plt.bar(df.index, df['pl'], color=colors)

# Set the labels and title
plt.xlabel("Trade Number")
plt.ylabel("P&L")
plt.title("P&L Over Time")

# Add a grid
plt.grid()

# Add copyright
plt.text(0.5, 0, "© Copyright 2000-2023, Unofficed Inc",
         horizontalalignment='center', verticalalignment='center',
         transform=plt.gca().transAxes, fontsize=8, color='gray')


# Show the plot
plt.show()

				
			

The graph looks like – 

Plot the Cumulative Profit/Loss Over Time

Here goes code snippet of another fancy graph. Despite the fancy tag, the graphs are good! It tells so much thing in so little space – 

				
					import matplotlib.pyplot as plt

cum_pl = df["pl"].cumsum()[::-1]
trade_num = range(1, len(df)+1)[::-1]

plt.plot(trade_num, cum_pl)
plt.title('Cumulative P&L Over Trades')
plt.xlabel('Trade Number')
plt.ylabel('Cumulative P&L')
# Add copyright
plt.text(0.5, 0, "© Copyright 2000-2023, Unofficed Inc",
         horizontalalignment='center', verticalalignment='center',
         transform=plt.gca().transAxes, fontsize=8, color='gray')

plt.show()

				
			

The graph looks like – 

That concludes this chapter. 

In the next chapter, We will simulate the trades in equity segment instead of derivatives.  

Post a comment

Leave a Comment

Your email address will not be published. Required fields are marked *

×Close