cyberosa commited on
Commit
d8cf478
·
1 Parent(s): 0e17b05

First graph with market creator types

Browse files
.gitignore ADDED
@@ -0,0 +1,162 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Byte-compiled / optimized / DLL files
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+
6
+ .DS_Store
7
+
8
+ # C extensions
9
+ *.so
10
+
11
+ # Distribution / packaging
12
+ .Python
13
+ build/
14
+ develop-eggs/
15
+ dist/
16
+ downloads/
17
+ eggs/
18
+ .eggs/
19
+ lib/
20
+ lib64/
21
+ parts/
22
+ sdist/
23
+ var/
24
+ wheels/
25
+ share/python-wheels/
26
+ *.egg-info/
27
+ .installed.cfg
28
+ *.egg
29
+ MANIFEST
30
+
31
+ # PyInstaller
32
+ # Usually these files are written by a python script from a template
33
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
34
+ *.manifest
35
+ *.spec
36
+
37
+ # Installer logs
38
+ pip-log.txt
39
+ pip-delete-this-directory.txt
40
+
41
+ # Unit test / coverage reports
42
+ htmlcov/
43
+ .tox/
44
+ .nox/
45
+ .coverage
46
+ .coverage.*
47
+ .cache
48
+ nosetests.xml
49
+ coverage.xml
50
+ *.cover
51
+ *.py,cover
52
+ .hypothesis/
53
+ .pytest_cache/
54
+ cover/
55
+
56
+ # Translations
57
+ *.mo
58
+ *.pot
59
+
60
+ # Django stuff:
61
+ *.log
62
+ local_settings.py
63
+ db.sqlite3
64
+ db.sqlite3-journal
65
+
66
+ # Flask stuff:
67
+ instance/
68
+ .webassets-cache
69
+
70
+ # Scrapy stuff:
71
+ .scrapy
72
+
73
+ # Sphinx documentation
74
+ docs/_build/
75
+
76
+ # PyBuilder
77
+ .pybuilder/
78
+ target/
79
+
80
+ # Jupyter Notebook
81
+ .ipynb_checkpoints
82
+
83
+ # IPython
84
+ profile_default/
85
+ ipython_config.py
86
+
87
+ # pyenv
88
+ # For a library or package, you might want to ignore these files since the code is
89
+ # intended to run in multiple environments; otherwise, check them in:
90
+ # .python-version
91
+
92
+ # pipenv
93
+ # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
94
+ # However, in case of collaboration, if having platform-specific dependencies or dependencies
95
+ # having no cross-platform support, pipenv may install dependencies that don't work, or not
96
+ # install all needed dependencies.
97
+ #Pipfile.lock
98
+
99
+ # poetry
100
+ # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
101
+ # This is especially recommended for binary packages to ensure reproducibility, and is more
102
+ # commonly ignored for libraries.
103
+ # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
104
+ #poetry.lock
105
+
106
+ # pdm
107
+ # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
108
+ #pdm.lock
109
+ # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
110
+ # in version control.
111
+ # https://pdm.fming.dev/#use-with-ide
112
+ .pdm.toml
113
+
114
+ # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
115
+ __pypackages__/
116
+
117
+ # Celery stuff
118
+ celerybeat-schedule
119
+ celerybeat.pid
120
+
121
+ # SageMath parsed files
122
+ *.sage.py
123
+
124
+ # Environments
125
+ .env
126
+ .venv
127
+ env/
128
+ venv/
129
+ ENV/
130
+ env.bak/
131
+ venv.bak/
132
+
133
+ # Spyder project settings
134
+ .spyderproject
135
+ .spyproject
136
+
137
+ # Rope project settings
138
+ .ropeproject
139
+
140
+ # mkdocs documentation
141
+ /site
142
+
143
+ # mypy
144
+ .mypy_cache/
145
+ .dmypy.json
146
+ dmypy.json
147
+
148
+ # Pyre type checker
149
+ .pyre/
150
+
151
+ # pytype static type analyzer
152
+ .pytype/
153
+
154
+ # Cython debug symbols
155
+ cython_debug/
156
+
157
+ # PyCharm
158
+ # JetBrains specific template is maintained in a separate JetBrains.gitignore that can
159
+ # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
160
+ # and can be added to the global gitignore or merged into this file. For a more nuclear
161
+ # option (not recommended) you can uncomment the following to ignore the entire idea folder.
162
+ #.idea/
README.md CHANGED
@@ -1,8 +1,8 @@
1
  ---
2
  title: Trader Agents Performance
3
- emoji: 👁
4
- colorFrom: pink
5
- colorTo: red
6
  sdk: gradio
7
  sdk_version: 4.44.0
8
  app_file: app.py
 
1
  ---
2
  title: Trader Agents Performance
3
+ emoji: 🏃
4
+ colorFrom: gray
5
+ colorTo: yellow
6
  sdk: gradio
7
  sdk_version: 4.44.0
8
  app_file: app.py
app.py ADDED
@@ -0,0 +1,172 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from datetime import datetime, timedelta
2
+ import gradio as gr
3
+ import pandas as pd
4
+ import duckdb
5
+ import logging
6
+
7
+
8
+ from scripts.metrics import (
9
+ compute_weekly_metrics_by_market_creator,
10
+ compute_weekly_metrics_by_trader_type,
11
+ )
12
+ from tabs.trader_plots import (
13
+ plot_trader_metrics_by_market_creator,
14
+ plot_trader_metrics_by_trader_type,
15
+ default_trader_metric,
16
+ trader_metric_choices,
17
+ get_trader_metrics_text,
18
+ )
19
+
20
+
21
+ def get_logger():
22
+ logger = logging.getLogger(__name__)
23
+ logger.setLevel(logging.DEBUG)
24
+ # stream handler and formatter
25
+ stream_handler = logging.StreamHandler()
26
+ stream_handler.setLevel(logging.DEBUG)
27
+ formatter = logging.Formatter(
28
+ "%(asctime)s - %(name)s - %(levelname)s - %(message)s"
29
+ )
30
+ stream_handler.setFormatter(formatter)
31
+ logger.addHandler(stream_handler)
32
+ return logger
33
+
34
+
35
+ logger = get_logger()
36
+
37
+
38
+ def get_all_data():
39
+ """
40
+ Get parquet file from weekly stats
41
+ """
42
+ logger.info("Getting traders data")
43
+ con = duckdb.connect(":memory:")
44
+ # Query to fetch data from all_trades_profitability.parquet
45
+ query1 = f"""
46
+ SELECT *
47
+ FROM read_parquet('./data/all_trades_profitability.parquet')
48
+ """
49
+ df1 = con.execute(query1).fetchdf()
50
+ logger.info("Got all data from all_trades_profitability.parquet")
51
+
52
+ con.close()
53
+
54
+ return df1
55
+
56
+
57
+ def prepare_data():
58
+
59
+ all_trades = get_all_data()
60
+
61
+ all_trades["creation_date"] = all_trades["creation_timestamp"].dt.date
62
+
63
+ # adding multi-bet variables
64
+ volume_trades_per_trader_and_market = (
65
+ all_trades.groupby(["trader_address", "title"])["roi"].count().reset_index()
66
+ )
67
+ volume_trades_per_trader_and_market.rename(
68
+ columns={"roi": "nr_trades_per_market"}, inplace=True
69
+ )
70
+
71
+ trader_agents_data = pd.merge(
72
+ all_trades, volume_trades_per_trader_and_market, on=["trader_address", "title"]
73
+ )
74
+ # right now all traders are of the same type: singlebet
75
+ trader_agents_data["trader_type"] = "singlebet"
76
+
77
+ trader_agents_data = trader_agents_data.sort_values(
78
+ by="creation_timestamp", ascending=True
79
+ )
80
+
81
+ trader_agents_data["month_year_week"] = (
82
+ trader_agents_data["creation_timestamp"].dt.to_period("W").dt.strftime("%b-%d")
83
+ )
84
+ return trader_agents_data
85
+
86
+
87
+ trader_agents_data = prepare_data()
88
+ print("trader agents data before computing metrics")
89
+ print(trader_agents_data.head())
90
+ demo = gr.Blocks()
91
+ # get weekly metrics by market creator: qs, pearl or all.
92
+ weekly_metrics_by_market_creator = compute_weekly_metrics_by_market_creator(
93
+ trader_agents_data
94
+ )
95
+ print("weekly metrics by market creator")
96
+ print(weekly_metrics_by_market_creator.head())
97
+ # get weekly metrics by trader type: multibet, singlebet or all.
98
+ # weekly_metrics_by_market_strategy = compute_weekly_metrics_by_trader_type(
99
+ # trader_agents_data
100
+ # )
101
+ with demo:
102
+ gr.HTML("<h1>Trader agents monitoring dashboard </h1>")
103
+ gr.Markdown(
104
+ "This app shows the weekly performance of the trader agents in Olas Predict."
105
+ )
106
+
107
+ with gr.Tabs():
108
+ with gr.TabItem("🔥Trader Agents Dashboard"):
109
+ # TODO Implement metrics showing market creator
110
+ with gr.Row():
111
+ gr.Markdown("# Weekly metrics of trader agents by market creator")
112
+ with gr.Row():
113
+ trader_details_selector = gr.Dropdown(
114
+ label="Select a trader metric",
115
+ choices=trader_metric_choices,
116
+ value=default_trader_metric,
117
+ )
118
+
119
+ with gr.Row():
120
+ with gr.Column(scale=3):
121
+ trader_markets_plot = plot_trader_metrics_by_market_creator(
122
+ metric_name=default_trader_metric,
123
+ traders_df=weekly_metrics_by_market_creator,
124
+ )
125
+ with gr.Column(scale=1):
126
+ trade_details_text = get_trader_metrics_text()
127
+
128
+ def update_trader_details(trader_detail):
129
+ return plot_trader_metrics_by_market_creator(
130
+ metric_name=trader_detail,
131
+ traders_df=weekly_metrics_by_market_creator,
132
+ )
133
+
134
+ trader_details_selector.change(
135
+ update_trader_details,
136
+ inputs=trader_details_selector,
137
+ outputs=trader_markets_plot,
138
+ )
139
+
140
+ # with gr.Row():
141
+ # gr.Markdown(
142
+ # "# Weekly metrics for trader agents by trader type (multibet or singlebet)"
143
+ # )
144
+ # with gr.Row():
145
+ # trade_details_selector = gr.Dropdown(
146
+ # label="Select a trader metric",
147
+ # choices=trader_metric_choices,
148
+ # value=default_trader_metric,
149
+ # )
150
+
151
+ # with gr.Row():
152
+ # with gr.Column(scale=3):
153
+ # trader_type_plot = plot_trader_metrics_by_trader_type(
154
+ # metric_name=default_trader_metric,
155
+ # trades_df=trades_df,
156
+ # )
157
+ # with gr.Column(scale=1):
158
+ # trade_details_text = get_trader_metrics_text()
159
+
160
+ # def update_trader_details(trader_detail):
161
+ # return plot_trader_metrics_by_trader_type(
162
+ # metric_name=trader_detail,
163
+ # trades_df=trades_df,
164
+ # )
165
+
166
+ # trader_details_selector.change(
167
+ # update_trader_details,
168
+ # inputs=trade_details_selector,
169
+ # outputs=trader_details_plot,
170
+ # )
171
+
172
+ demo.queue(default_concurrency_limit=40).launch()
data/all_trades_profitability.parquet ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:a12ff001752f6ca93c5ebbbf1ba39aa2c9a194d798cd4136c10bb096b8eb5490
3
+ size 698837
data/markets_live_data.parquet ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:69a3fffac1b1e11e818cdf3c709fd3006d6f93107df947693548a05bc66f337d
3
+ size 145777
notebooks/trader_agent_metrics.ipynb ADDED
The diff for this file is too large to render. See raw diff
 
scripts/metrics.py ADDED
@@ -0,0 +1,171 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import pandas as pd
2
+ from tqdm import tqdm
3
+
4
+ DEFAULT_MECH_FEE = 0.01 # xDAI
5
+
6
+
7
+ def compute_metrics(trader_address: str, trader_data: pd.DataFrame) -> dict:
8
+
9
+ if len(trader_data) == 0:
10
+ print("No data to compute metrics")
11
+ return {}
12
+
13
+ weekly_metrics = {}
14
+ weekly_metrics["trader_address"] = trader_address
15
+ total_net_earnings = trader_data.net_earnings.sum()
16
+ total_bet_amounts = trader_data.collateral_amount.sum()
17
+ total_num_mech_calls = trader_data.num_mech_calls.sum()
18
+ weekly_metrics["net_earnings"] = total_net_earnings
19
+ weekly_metrics["earnings"] = trader_data.earnings.sum()
20
+ weekly_metrics["bet_amount"] = total_bet_amounts
21
+ weekly_metrics["nr_mech_calls"] = total_num_mech_calls
22
+ total_fee_amounts = trader_data.mech_fee_amount.sum()
23
+ total_costs = (
24
+ total_bet_amounts
25
+ + total_fee_amounts
26
+ + (total_num_mech_calls * DEFAULT_MECH_FEE)
27
+ )
28
+ weekly_metrics["roi"] = total_net_earnings / total_costs
29
+ return weekly_metrics
30
+
31
+
32
+ def compute_trader_metrics_by_trader_type(
33
+ trader_address: str, week_traders_data: pd.DataFrame, trader_type: str = "all"
34
+ ) -> pd.DataFrame:
35
+ """This function computes for a specific week the different metrics: roi, net_earnings, earnings, bet_amount, nr_mech_calls.
36
+ The global roi of the trader agent by computing the individual net profit and the indivicual costs values
37
+ achieved per market and dividing both.
38
+ It is possible to filter by trader type: multibet, singlebet, all"""
39
+ assert "trader_type" in week_traders_data.columns
40
+ filtered_traders_data = week_traders_data.loc[
41
+ week_traders_data["trader_address"] == trader_address
42
+ ]
43
+
44
+ if trader_type != "all": # compute only for the specific type
45
+ filtered_traders_data = filtered_traders_data.loc[
46
+ filtered_traders_data["trader_type"] == trader_type
47
+ ]
48
+ if len(filtered_traders_data) == 0:
49
+ return pd.DataFrame() # No Data
50
+
51
+ return compute_metrics(trader_address, filtered_traders_data)
52
+
53
+
54
+ def compute_trader_metrics_by_market_creator(
55
+ trader_address: str, week_traders_data: pd.DataFrame, market_creator: str = "all"
56
+ ) -> dict:
57
+ """This function computes for a specific week the different metrics: roi, net_earnings, earnings, bet_amount, nr_mech_calls.
58
+ The global roi of the trader agent by computing the individual net profit and the indivicual costs values
59
+ achieved per market and dividing both.
60
+ It is possible to filter by market creator: quickstart, pearl, all"""
61
+ assert "market_creator" in week_traders_data.columns
62
+ filtered_traders_data = week_traders_data.loc[
63
+ week_traders_data["trader_address"] == trader_address
64
+ ]
65
+ if market_creator != "all": # compute only for the specific market creator
66
+ filtered_traders_data = filtered_traders_data.loc[
67
+ filtered_traders_data["market_creator"] == market_creator
68
+ ]
69
+ if len(filtered_traders_data) == 0:
70
+ tqdm.write(f"No data. Skipping market creator {market_creator}")
71
+ return {} # No Data
72
+ tqdm.write(
73
+ f"Volume of data for trader {trader_address} and market creator {market_creator} = {len(filtered_traders_data)}"
74
+ )
75
+ metrics = compute_metrics(trader_address, filtered_traders_data)
76
+ return metrics
77
+
78
+
79
+ def merge_trader_metrics(
80
+ trader: str, weekly_data: pd.DataFrame, week: str
81
+ ) -> pd.DataFrame:
82
+ trader_metrics = []
83
+ # computation as specification 1 for all types of markets
84
+ weekly_metrics_all = compute_trader_metrics_by_market_creator(
85
+ trader, weekly_data, market_creator="all"
86
+ )
87
+ weekly_metrics_all["month_year_week"] = week
88
+ weekly_metrics_all["market_creator"] = "all"
89
+ trader_metrics.append(weekly_metrics_all)
90
+
91
+ # computation as specification 1 for quickstart markets
92
+ weekly_metrics_qs = compute_trader_metrics_by_market_creator(
93
+ trader, weekly_data, market_creator="quickstart"
94
+ )
95
+ if len(weekly_metrics_qs) > 0:
96
+ weekly_metrics_qs["month_year_week"] = week
97
+ weekly_metrics_qs["market_creator"] = "quickstart"
98
+ trader_metrics.append(weekly_metrics_qs)
99
+ # computation as specification 1 for pearl markets
100
+ weekly_metrics_pearl = compute_trader_metrics_by_market_creator(
101
+ trader, weekly_data, market_creator="pearl"
102
+ )
103
+ if len(weekly_metrics_pearl) > 0:
104
+ weekly_metrics_pearl["month_year_week"] = week
105
+ weekly_metrics_pearl["market_creator"] = "pearl"
106
+ trader_metrics.append(weekly_metrics_pearl)
107
+ result = pd.DataFrame.from_dict(trader_metrics, orient="columns")
108
+ tqdm.write(f"Total length of all trader metrics for this week = {len(result)}")
109
+ return result
110
+
111
+
112
+ def compute_weekly_metrics_by_market_creator(
113
+ trader_agents_data: pd.DataFrame,
114
+ ) -> pd.DataFrame:
115
+ """Function to compute the metrics at the trader level per week and with different categories by market creator"""
116
+ contents = []
117
+ all_weeks = list(trader_agents_data.month_year_week.unique())
118
+ for week in all_weeks:
119
+ weekly_data = trader_agents_data.loc[
120
+ trader_agents_data["month_year_week"] == week
121
+ ]
122
+ print(f"Computing weekly metrics for week ={week} by market creator")
123
+ # traverse each trader agent
124
+ traders = list(weekly_data.trader_address.unique())
125
+ for trader in tqdm(traders, desc=f"Trader' metrics", unit="metrics"):
126
+ contents.append(merge_trader_metrics(trader, weekly_data, week))
127
+ print("End computing all weekly metrics by market creator")
128
+ return pd.concat(contents, ignore_index=True)
129
+
130
+
131
+ def compute_weekly_metrics_by_trader_type(
132
+ trader_agents_data: pd.DataFrame,
133
+ ) -> pd.DataFrame:
134
+ """Function to compute the metrics at the trader level per week and with different types of traders"""
135
+ contents = []
136
+ all_weeks = list(trader_agents_data.month_year_week.unique())
137
+ for week in all_weeks:
138
+ weekly_data = trader_agents_data.loc[
139
+ trader_agents_data["month_year_week"] == week
140
+ ]
141
+ print(f"Computing weekly metrics for week ={week} by trader type")
142
+ # traverse each trader agent
143
+ traders = list(weekly_data.trader_address.unique())
144
+ for trader in tqdm(traders, desc=f"Trader' metrics", unit="metrics"):
145
+ # computation as specification 1 for all types of traders
146
+ weekly_metrics = compute_trader_metrics_by_trader_type(
147
+ trader, weekly_data, trader_type="all"
148
+ )
149
+ weekly_metrics["month_year_week"] = week
150
+ weekly_metrics["trader_type"] = "all"
151
+ contents.append(weekly_metrics)
152
+
153
+ # computation as specification 1 for multibet traders
154
+ weekly_metrics = compute_trader_metrics_by_trader_type(
155
+ trader, weekly_data, trader_type="multibet"
156
+ )
157
+ if len(weekly_metrics) > 0:
158
+ weekly_metrics["month_year_week"] = week
159
+ weekly_metrics["trader_type"] = "multibet"
160
+ contents.append(weekly_metrics)
161
+
162
+ # computation as specification 1 for singlebet traders
163
+ weekly_metrics = compute_trader_metrics_by_trader_type(
164
+ trader, weekly_data, trader_type="singlebet"
165
+ )
166
+ if len(weekly_metrics) > 0:
167
+ weekly_metrics["month_year_week"] = week
168
+ weekly_metrics["trader_type"] = "singlebet"
169
+ contents.append(weekly_metrics)
170
+ print("End computing all weekly metrics by trader types")
171
+ return pd.concat(contents, ignore_index=True)
tabs/trader_plots.py ADDED
@@ -0,0 +1,75 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import pandas as pd
3
+ import plotly.express as px
4
+
5
+ trader_metric_choices = [
6
+ "mech calls",
7
+ "bet amount",
8
+ "earnings",
9
+ "net earnings",
10
+ "ROI",
11
+ ]
12
+ default_trader_metric = "ROI"
13
+
14
+
15
+ def get_trader_metrics_text() -> gr.Markdown:
16
+ metric_text = """
17
+ ## Description of the graph
18
+ These metrics are computed weekly. The statistical measures are:
19
+ * min, max, 25th(q1), 50th(median) and 75th(q2) percentiles
20
+ * the upper and lower fences to delimit possible outliers
21
+ * the average values as the dotted lines
22
+ """
23
+
24
+ return gr.Markdown(metric_text)
25
+
26
+
27
+ def plot_trader_metrics_by_market_creator(
28
+ metric_name: str, traders_df: pd.DataFrame
29
+ ) -> gr.Plot:
30
+ """Plots the weekly trader metrics."""
31
+
32
+ if metric_name == "mech calls":
33
+ metric_name = "mech_calls"
34
+ column_name = "nr_mech_calls"
35
+ yaxis_title = "Total nr of mech calls per trader"
36
+ elif metric_name == "ROI":
37
+ column_name = "roi"
38
+ yaxis_title = "Total ROI (net profit/cost)"
39
+ elif metric_name == "bet amount":
40
+ metric_name = "bet_amount"
41
+ column_name = metric_name
42
+ yaxis_title = "Total bet amount per trader (xDAI)"
43
+ elif metric_name == "net earnings":
44
+ metric_name = "net_earnings"
45
+ column_name = metric_name
46
+ yaxis_title = "Total net profit per trader (xDAI)"
47
+ else: # earnings
48
+ column_name = metric_name
49
+ yaxis_title = "Total gross profit per trader (xDAI)"
50
+
51
+ traders_filtered = traders_df[["month_year_week", "market_creator", column_name]]
52
+
53
+ fig = px.box(
54
+ traders_filtered,
55
+ x="month_year_week",
56
+ y=column_name,
57
+ color="market_creator",
58
+ color_discrete_sequence=["purple", "goldenrod", "darkgreen"],
59
+ category_orders={"market_creator": ["pearl", "quickstart", "all"]},
60
+ )
61
+ fig.update_traces(boxmean=True)
62
+ fig.update_layout(
63
+ xaxis_title="Week",
64
+ yaxis_title=yaxis_title,
65
+ legend=dict(yanchor="top", y=0.5),
66
+ )
67
+ fig.update_xaxes(tickformat="%b %d\n%Y")
68
+
69
+ return gr.Plot(
70
+ value=fig,
71
+ )
72
+
73
+
74
+ def plot_trader_metrics_by_trader_type():
75
+ print("WIP")