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, )