trader_agents_performance / tabs /trader_plots.py
cyberosa
updated graphs after missing non_Olas group
c571577
import gradio as gr
import pandas as pd
import plotly.express as px
from tabs.market_plots import color_mapping
from datetime import datetime
trader_metric_choices = [
"mech calls",
"bet amount",
"earnings",
"net earnings",
"ROI",
"nr_trades",
]
default_trader_metric = "ROI"
def get_metrics_text(trader_type: str = None, daily: bool = False) -> gr.Markdown:
if daily:
metric_text = """
## Metrics at the graph
These metrics are computed daily. The statistical measures are:
* min, max, 25th(q1), 50th(median) and 75th(q2) percentiles
* the upper and lower fences to delimit possible outliers
* the average values as the dotted lines
"""
elif trader_type is None:
metric_text = """
## Description of the graph
These metrics are computed weekly. The statistical measures are:
* min, max, 25th(q1), 50th(median) and 75th(q2) percentiles
* the upper and lower fences to delimit possible outliers
* the average values as the dotted lines
"""
elif trader_type == "Olas":
metric_text = """
## Definition of Olas trader
Agents using Mech, with a service ID and the corresponding safe in the registry
## Description of the graph
These metrics are computed weekly. The statistical measures are:
* min, max, 25th(q1), 50th(median) and 75th(q2) percentiles
* the upper and lower fences to delimit possible outliers
* the average values as the dotted lines
"""
elif trader_type == "non_Olas":
metric_text = """
## Definition of non-Olas trader
Agents using Mech, with no service ID
## Description of the graph
These metrics are computed weekly. The statistical measures are:
* min, max, 25th(q1), 50th(median) and 75th(q2) percentiles
* the upper and lower fences to delimit possible outliers
* the average values as the dotted lines
"""
else: # Unclassified
metric_text = """
## Definition of unclassified trader
Agents (safe/EOAs) not using Mechs
## Description of the graph
These metrics are computed weekly. The statistical measures are:
* min, max, 25th(q1), 50th(median) and 75th(q2) percentiles
* the upper and lower fences to delimit possible outliers
* the average values as the dotted lines
"""
return gr.Markdown(metric_text)
def get_interpretation_text() -> gr.Markdown:
interpretation_text = """
## Meaning of KL-divergence values
* Y = 0.05129
* Market accuracy off by 5%
* Y = 0.1053
* Market accuracy off by 10%
* Y = 0.2876
* Market accuracy off by 25%
* Y = 0.5108
* Market accuracy off by 40%
* Y = 1.2040
* Market accuracy off by 70%
* Y = 2.3026
* Market accuracy off by 90%
"""
return gr.Markdown(interpretation_text)
def plot_trader_metrics_by_market_creator(
metric_name: str, traders_df: pd.DataFrame
) -> gr.Plot:
"""Plots the weekly trader metrics."""
if metric_name == "mech calls":
metric_name = "mech_calls"
column_name = "nr_mech_calls"
yaxis_title = "Total nr of mech calls per trader"
elif metric_name == "ROI":
column_name = "roi"
yaxis_title = "Total ROI (net profit/cost)"
elif metric_name == "bet amount":
metric_name = "bet_amount"
column_name = metric_name
yaxis_title = "Total bet amount per trader (xDAI)"
elif metric_name == "net earnings":
metric_name = "net_earnings"
column_name = metric_name
yaxis_title = "Total net profit per trader (xDAI)"
elif metric_name == "nr_trades":
column_name = metric_name
yaxis_title = "Total nr of trades per trader"
else: # earnings
column_name = metric_name
yaxis_title = "Total gross profit per trader (xDAI)"
traders_filtered = traders_df[["month_year_week", "market_creator", column_name]]
# Convert string dates to datetime and sort them
all_dates_dt = sorted(
[
datetime.strptime(date, "%b-%d-%Y")
for date in traders_filtered["month_year_week"].unique()
]
)
# Convert back to string format
all_dates = [date.strftime("%b-%d-%Y") for date in all_dates_dt]
fig = px.box(
traders_filtered,
x="month_year_week",
y=column_name,
color="market_creator",
color_discrete_sequence=["purple", "goldenrod", "darkgreen"],
category_orders={"market_creator": ["pearl", "quickstart", "all"]},
)
fig.update_traces(boxmean=True)
fig.update_layout(
xaxis_title="Week",
yaxis_title=yaxis_title,
legend=dict(yanchor="top", y=0.5),
)
fig.update_xaxes(tickformat="%b %d\n%Y")
# Update layout to force x-axis category order (hotfix for a sorting issue)
fig.update_layout(xaxis={"categoryorder": "array", "categoryarray": all_dates})
return gr.Plot(
value=fig,
)
def plot_trader_daily_metrics_by_market_creator(
metric_name: str, traders_df: pd.DataFrame
) -> gr.Plot:
"""Plots the daily trader metrics."""
if metric_name == "mech calls":
metric_name = "mech_calls"
column_name = "nr_mech_calls"
yaxis_title = "Total nr of mech calls per trader"
elif metric_name == "ROI":
column_name = "roi"
yaxis_title = "Total ROI (net profit/cost)"
elif metric_name == "bet amount":
metric_name = "bet_amount"
column_name = metric_name
yaxis_title = "Total bet amount per trader (xDAI)"
elif metric_name == "net earnings":
metric_name = "net_earnings"
column_name = metric_name
yaxis_title = "Total net profit per trader (xDAI)"
elif metric_name == "nr_trades":
column_name = metric_name
yaxis_title = "Total nr of trades per trader"
else: # earnings
column_name = metric_name
yaxis_title = "Total gross profit per trader (xDAI)"
traders_filtered = traders_df[["creation_date", "market_creator", column_name]]
fig = px.box(
traders_filtered,
x="creation_date",
y=column_name,
color="market_creator",
color_discrete_sequence=["purple", "goldenrod", "darkgreen"],
category_orders={"market_creator": ["pearl", "quickstart", "all"]},
)
fig.update_traces(boxmean=True)
fig.update_layout(
xaxis_title="Day",
yaxis_title=yaxis_title,
legend=dict(yanchor="top", y=0.5),
)
fig.update_xaxes(tickformat="%b %d\n%Y")
return gr.Plot(
value=fig,
)
def plot_winning_metric_per_trader(traders_winning_df: pd.DataFrame) -> gr.Plot:
fig = px.box(
traders_winning_df,
x="month_year_week",
y="winning_perc",
color="market_creator",
color_discrete_sequence=["purple", "goldenrod", "darkgreen"],
category_orders={"market_creator": ["pearl", "quickstart", "all"]},
)
fig.update_traces(boxmean=True)
fig.update_layout(
xaxis_title="Week",
yaxis_title="Weekly winning percentage %",
legend=dict(yanchor="top", y=0.5),
width=1000, # Adjusted for better fit on laptop screens
height=600, # Adjusted for better fit on laptop screens
)
fig.update_xaxes(tickformat="%b %d\n%Y")
return gr.Plot(
value=fig,
)
def plot_total_bet_amount(
trades_df: pd.DataFrame, market_filter: str = "all"
) -> gr.Plot:
"""Plots the trade metrics."""
traders_all = trades_df.copy(deep=True)
traders_all["market_creator"] = "all"
# merging both dataframes
final_traders = pd.concat([traders_all, trades_df], ignore_index=True)
final_traders = final_traders.sort_values(by="creation_date", ascending=True)
# Create binary staking category
final_traders["trader_type"] = final_traders["staking"].apply(
lambda x: "non_Olas" if x == "non_Olas" else "Olas"
)
total_bet_amount = (
final_traders.groupby(
["month_year_week", "market_creator", "trader_type"], sort=False
)["collateral_amount"]
.sum()
.reset_index(name="total_bet_amount")
)
# Convert string dates to datetime and sort them
all_dates_dt = sorted(
[
datetime.strptime(date, "%b-%d-%Y")
for date in total_bet_amount["month_year_week"].unique()
]
)
# Convert back to string format
all_dates = [date.strftime("%b-%d-%Y") for date in all_dates_dt]
total_bet_amount["trader_market"] = total_bet_amount.apply(
lambda x: (x["trader_type"], x["market_creator"]), axis=1
)
color_discrete_sequence = ["purple", "goldenrod", "darkgreen"]
if market_filter == "pearl":
color_discrete_sequence = ["darkviolet", "goldenrod", "green"]
total_bet_amount = total_bet_amount.loc[
total_bet_amount["market_creator"] == "pearl"
]
elif market_filter == "quickstart":
total_bet_amount = total_bet_amount.loc[
total_bet_amount["market_creator"] == "quickstart"
]
else:
total_bet_amount = total_bet_amount.loc[
total_bet_amount["market_creator"] == "all"
]
fig = px.bar(
total_bet_amount,
x="month_year_week",
y="total_bet_amount",
color="trader_market",
color_discrete_sequence=color_mapping,
category_orders={
"market_creator": ["pearl", "quickstart", "all"],
"trader_market": [
("Olas", "pearl"),
("non_Olas", "pearl"),
("Olas", "quickstart"),
("non_Olas", "quickstart"),
("Olas", "all"),
("non_Olas", "all"),
],
},
barmode="group",
)
fig.update_layout(
xaxis_title="Week",
yaxis_title="Weekly total bet amount per trader type",
legend=dict(yanchor="top", y=0.5),
)
fig.update_xaxes(tickformat="%b %d")
# Update layout to force x-axis category order (hotfix for a sorting issue)
fig.update_layout(xaxis={"categoryorder": "array", "categoryarray": all_dates})
return gr.Plot(
value=fig,
)
def plot_active_traders(
active_traders_data: pd.DataFrame,
market_creator: str = None,
):
"""Function to plot the volume of active traders for the different categories and markets"""
filtered_traders_data = active_traders_data.copy()
if market_creator is not None:
filtered_traders_data = filtered_traders_data.loc[
filtered_traders_data["market_creator"] == market_creator
]
active_traders = (
filtered_traders_data.groupby(by=["month_year_week", "trader_type"])[
"trader_address"
]
.nunique()
.reset_index(name="nr_traders")
)
# Convert string dates to datetime and sort them
all_dates_dt = sorted(
[
datetime.strptime(date, "%b-%d-%Y")
for date in active_traders["month_year_week"].unique()
]
)
# Convert back to string format
all_dates = [date.strftime("%b-%d-%Y") for date in all_dates_dt]
color_mapping = [
"royalblue",
"goldenrod",
"gray",
]
fig = px.bar(
active_traders,
x="month_year_week",
y="nr_traders",
color="trader_type",
color_discrete_sequence=color_mapping,
category_orders={
"trader_type": ["Olas", "non_Olas", "unknown"],
},
barmode="group",
)
fig.update_layout(
xaxis_title="Week",
yaxis_title="Weekly active traders per trader type",
legend=dict(yanchor="top", y=0.5),
)
fig.update_xaxes(tickformat="%b %d")
# Update layout to force x-axis category order (hotfix for a sorting issue)
fig.update_layout(xaxis={"categoryorder": "array", "categoryarray": all_dates})
return gr.Plot(
value=fig,
)